Setup GraphQL in a bonFHIR project
This guide will walk you through adding support for typesafe GraphQL in a bonFHIR project.
Although it is possible to use GraphQL in a bonFHIR project without any particular setup, we recommend that you go through the steps described here as it will provide type safety and even type completion which will greatly enhance the developer experience.
It is based on the GraphQL Code Generator installation guide.
It assumes that you already have a functionning bonFHIR application, and a FHIR Server that supports GraphQL.
If you don't have one, you can start with one of our project templates by running:
npm create -y bonfhir@latest
Install the GraphQL Code Generator
At the root of the project, start by installing the right packages:
- npm
- Yarn
- pnpm
npm install graphql
npm install -D @graphql-codegen/cli @parcel/watcher
yarn add graphql
yarn add --dev @graphql-codegen/cli @parcel/watcher
pnpm add graphql
pnpm add -D @graphql-codegen/cli @parcel/watcher
Then, run the initialization wizard
npx graphql-code-generator init
Select the following options:
- What type of application are you building? Application built with React
- Where is your schema?: (path or url) [location of your FHIR Server schema] - use "http://localhost:8103/fhir/R4/$graphql" if you are using the provided FHIR local development server
- Where are your operations and fragments?: **
src/**/\*.tsx
** - Where to write the output:
src/gql/
- Do you want to generate an introspection file? Yes
- How to name the config file?
codegen.ts
- What script in package.json should run the codegen?
codegen
Then install the configured plugins:
- npm
- Yarn
- pnpm
npm install
yarn install
pnpm install
Configure the GraphQL Code Generator
Open the codegen.ts
file - it should look like this:
import type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
overwrite: true,
schema: "http://localhost:8103/fhir/R4/$graphql",
documents: "src/**/*.tsx",
generates: {
"src/gql/": {
preset: "client",
plugins: [],
},
"./graphql.schema.json": {
plugins: ["introspection"],
},
},
};
export default config;
There are a few things that you may need to fix:
-
Ensure that your FHIR Server is running nad the introspection endpoint is available
(run thenpm fhir:start-server
command in a project created from a bonFHIR template) -
Your FHIR Server introspection endpoint may need authentication information; this is the case for our provided FHIR local development server
If this is the case you can add the authentication info like so:codegen.tsimport type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
overwrite: true,
schema: {
"http://localhost:8103/fhir/R4/$graphql": {
headers: {
Authorization:
"Basic ZjU0MzcwZGUtZWFmMy00ZDgxLWExN2UtMjQ4NjBmNjY3OTEyOjc1ZDhlN2QwNmJmOTI4MzkyNmM1MWQ1ZjQ2MTI5NWNjZjBiNjkxMjhlOTgzYjZlY2RkNWE5YzA3NTA2ODk1ZGU=",
},
},
},
documents: "src/*_/_.tsx",
generates: {
"src/gql/": {
preset: "client",
plugins: [],
},
"./graphql.schema.json": {
plugins: ["introspection"],
},
},
};
export default config; -
Ignore errors when there is no documents (
ignoreNoDocuments: true
):codegen.tsimport type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
overwrite: true,
schema: {
"http://localhost:8103/fhir/R4/$graphql": {
headers: {
Authorization:
"Basic ZjU0MzcwZGUtZWFmMy00ZDgxLWExN2UtMjQ4NjBmNjY3OTEyOjc1ZDhlN2QwNmJmOTI4MzkyNmM1MWQ1ZjQ2MTI5NWNjZjBiNjkxMjhlOTgzYjZlY2RkNWE5YzA3NTA2ODk1ZGU=",
},
},
},
documents: "src/*_/_.tsx",
generates: {
"src/gql/": {
preset: "client",
plugins: [],
},
"./graphql.schema.json": {
plugins: ["introspection"],
},
},
ignoreNoDocuments: true,
};
export default config; -
Run the codegen script
- npm
- Yarn
- pnpm
npm run codegen
yarn codegen
pnpm run codegen
This should create a file named
graphql.schema.json
at the root of the project; it is a dump of the GraphQL introspection endpoint.
It also create a directory named./src/gql
that we will use later. -
Use the local introspection file instead of the online one
You can keep using the server introspection point, but we do recommend that you switch to the one you just generated as it make life easier for everyone (including other developers and CI servers); this way they don't need a locally running FHIR Server to run GraphQL codegen tasks:codegen.tsimport type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
overwrite: true,
// schema: {
// "http://localhost:8103/fhir/R4/$graphql": {
// headers: {
// Authorization:
// "Basic ZjU0MzcwZGUtZWFmMy00ZDgxLWExN2UtMjQ4NjBmNjY3OTEyOjc1ZDhlN2QwNmJmOTI4MzkyNmM1MWQ1ZjQ2MTI5NWNjZjBiNjkxMjhlOTgzYjZlY2RkNWE5YzA3NTA2ODk1ZGU=",
// },
// },
// },
schema: "./graphql.schema.json",
documents: "src/**/*.tsx",
generates: {
"src/gql/": {
preset: "client",
plugins: [],
},
// "./graphql.schema.json": {
// plugins: ["introspection"],
// },
},
ignoreNoDocuments: true,
};
export default config;
Configure typescript language server to auto-complete the GraphQL schema
This step is optional but greatly recommended - it will provide type suggestions / completions inside your GraphQL queries, making them much easier to write!
There are others plugins or extensions available for this - you may prefer using your own technique for this part.
-
Install the LSP
- npm
- Yarn
- pnpm
npm install -D @0no-co/graphqlsp
yarn add --dev @0no-co/graphqlsp
pnpm add -D @0no-co/graphqlsp
-
Update the
tsconfig.json
file with the right options:tsconfig.json{
"compilerOptions": {
//...
"plugins": [
{
"name": "@0no-co/graphqlsp",
"schema": "./graphql.schema.json",
"template": "graphql",
"templateIsCallExpression": true
}
]
}
} -
If using Visual Studio Code, make sure to use the project typescript
Add (or edit) a file named.vscode/settings.json
with the following options:.vscode/settings.json{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}Immediately after saving this file, you should get prompt asking you to use the workspace typescript - answer Allow
Write your first GraphQL query
Let's write our first GraphQL query!
-
In a component file in your project (or a new file), type the following code:
import { useFhirGraphQL } from "@bonfhir/query/r4b";
import { graphql } from "./gql"; // The `./src/gql` directory created earlier
function MyComponent() {
const patientsQuery = useFhirGraphQL(
graphql(`
query PatientsQuery {
PatientList {
id
name {
given
family
}
}
}
`),
);
}You should notice 2 things:
- you have type completion support for your GraphQL query
- typescript reports a type error on the
graphql
call saying it can't find the appropriate type
-
Run the codegen script again
- npm
- Yarn
- pnpm
npm run codegen
yarn codegen
pnpm run codegen
You'll notice that the typescript error has disappeared - your GraphQL query is now fully typed!
-
Continue developping and enjoy a typed GraphQL experience!
import { useFhirGraphQL } from "@bonfhir/query/r4b";
import { graphql } from "./gql"; // The `./src/gql` directory created earlier
function MyComponent() {
const patientsQuery = useFhirGraphQL(
graphql(`
query PatientsQuery {
PatientList {
id
name {
given
family
}
}
}
`),
);
return (
<List>
{patientsQuery.data?.PatientList?.map((patient) => (
<List.Item key={patient?.id}>
<FhirValue type="HumanName" value={patient?.name} />
</List.Item>
))}
</List>
);
}You will need to run the
codegen
script everytime you change a GraphQL query.
It can be run in watch mode by running this:- npm
- Yarn
- pnpm
npm run codegen -- --watch
yarn codegen --watch
pnpm run codegen --watch