Skip to content

Commit 1772322

Browse files
Integrate graphql-codegen to generate GraphQL types (#2155)
* configure graphql-codegen * refactor query names to be unique * Update code (sort alphabetically) * ignore graphql-codegen generated files * Run graphql-codegen * remove fetchCsrfTokenServer and use a config constructor * Update code * use near-operation-file-preset * use typed-document-node plugin * Update code (sort alphabetically) * Update code * add graphql-codegen generated types to end-of-file-fixer * add hook for graphql-codegen for schema validation * Update code * skip graphql-codegen pre-commit hook * add graphql-codegen * add generate-graphql-types to make check * run make check * Update code --------- Co-authored-by: Arkadii Yakovets <[email protected]> Co-authored-by: Arkadii Yakovets <[email protected]>
1 parent 657ce95 commit 1772322

34 files changed

+4028
-295
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ repos:
6464
- id: check-yaml
6565
- id: detect-private-key
6666
- id: end-of-file-fixer
67+
exclude: frontend/src/types/__generated__
6768
exclude_types:
6869
- svg
6970
- id: file-contents-sorter

frontend/.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.pnpm-store/
22
pnpm-lock.yaml
3+
src/types/__generated__/**/*

frontend/Makefile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ SHELL := /bin/bash
22

33
check-frontend: \
44
format-frontend-code \
5-
lint-frontend-code
5+
lint-frontend-code \
6+
generate-graphql-types
67

78
clean-frontend-dependencies:
89
@rm -rf frontend/.next
@@ -27,6 +28,9 @@ format-frontend-code:
2728
|| (printf "pnpm run format"; for i in $$(seq 1 58); do printf "."; done; printf "\033[37;41mFailed\033[0m\n" \
2829
&& pnpm run format))
2930

31+
graphql-codegen:
32+
@cd frontend && pnpm run graphql-codegen
33+
3034
lighthouse-ci:
3135
@cd frontend && pnpm run lighthouse-ci
3236

@@ -39,6 +43,12 @@ lint-frontend-code:
3943
|| (printf "pnpm run lint"; for i in $$(seq 1 60); do printf "."; done; printf "\033[37;41mFailed\033[0m\n" \
4044
&& pnpm run lint))
4145

46+
generate-graphql-types:
47+
@(cd frontend && pnpm run graphql-codegen >/dev/null 2>&1 \
48+
&& (printf "pnpm run graphql-codegen"; for i in $$(seq 1 49); do printf "."; done; printf "\033[30;42mPassed\033[0m\n") \
49+
|| (printf "pnpm run graphql-codegen"; for i in $$(seq 1 49); do printf "."; done; printf "\033[37;41mFailed\033[0m\n" \
50+
&& pnpm run graphql-codegen))
51+
4252
shell-frontend:
4353
@CMD="/bin/sh" $(MAKE) exec-frontend-command-it
4454

frontend/eslint.config.mjs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,16 @@ const eslintConfig = [
2727
...compat.extends('next/typescript'),
2828
react.configs.flat['jsx-runtime'],
2929
{
30-
ignores: ['.cache', '.next', '.pnpm-store', 'node_modules', 'build', 'dist', 'next-env.d.ts'],
30+
ignores: [
31+
'.cache',
32+
'.next',
33+
'.pnpm-store',
34+
'node_modules',
35+
'build',
36+
'dist',
37+
'next-env.d.ts',
38+
'src/types/__generated__/**/*',
39+
],
3140
},
3241
js.configs.recommended,
3342
{

frontend/graphql-codegen.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { CodegenConfig } from '@graphql-codegen/cli'
2+
3+
const PUBLIC_API_URL = process.env.PUBLIC_API_URL || 'http://localhost:8000'
4+
5+
export default (async (): Promise<CodegenConfig> => {
6+
let response
7+
8+
try {
9+
response = await fetch(`${PUBLIC_API_URL}/csrf/`, {
10+
method: 'GET',
11+
})
12+
} catch {
13+
/* eslint-disable no-console */
14+
console.log('Failed to fetch CSRF token: make sure the backend is running.')
15+
return
16+
}
17+
18+
if (!response.ok) {
19+
throw new Error(`Failed to fetch CSRF token: ${response.status} ${response.statusText}`)
20+
}
21+
const csrfToken = (await response.json()).csrftoken
22+
23+
return {
24+
documents: ['src/**/*.{ts,tsx}', '!src/types/__generated__/**'],
25+
generates: {
26+
'./src/': {
27+
config: {
28+
avoidOptionals: {
29+
// Use `null` for nullable fields instead of optionals
30+
field: true,
31+
// Allow nullable input fields to remain unspecified
32+
inputValue: false,
33+
},
34+
// Use `unknown` instead of `any` for unconfigured scalars
35+
defaultScalarType: 'unknown',
36+
// Apollo Client always includes `__typename` fields
37+
nonOptionalTypename: true,
38+
// Apollo Client doesn't add the `__typename` field to root types so
39+
// don't generate a type for the `__typename` for root operation types.
40+
skipTypeNameForRoot: true,
41+
},
42+
// Order of plugins matter
43+
plugins: ['typescript-operations', 'typed-document-node'],
44+
preset: 'near-operation-file',
45+
presetConfig: {
46+
// This should be the file generated by the "typescript" plugin above,
47+
// relative to the directory specified for this configuration
48+
baseTypesPath: './types/__generated__/graphql.ts',
49+
// Relative to the source files
50+
folder: '../../types/__generated__',
51+
},
52+
},
53+
'./src/types/__generated__/graphql.ts': {
54+
plugins: ['typescript'],
55+
},
56+
},
57+
// Don't exit with non-zero status when there are no documents
58+
ignoreNoDocuments: true,
59+
overwrite: true,
60+
schema: {
61+
[`${PUBLIC_API_URL}/graphql/`]: {
62+
headers: {
63+
Cookie: `csrftoken=${csrfToken}`,
64+
'X-CSRFToken': csrfToken,
65+
},
66+
},
67+
},
68+
}
69+
})()

frontend/package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"dev": "next dev --port 3000",
99
"format": "prettier --log-level warn --write .",
1010
"format:check": "prettier --check .",
11+
"graphql-codegen": "graphql-codegen --config graphql-codegen.ts",
1112
"lighthouse-ci": "lhci autorun",
1213
"lighthouse-ci:desktop": "lhci autorun --collect.settings.preset=desktop",
1314
"lint": "eslint . --config eslint.config.mjs --fix --max-warnings=0",
@@ -23,6 +24,7 @@
2324
"@fortawesome/free-regular-svg-icons": "^6.7.2",
2425
"@fortawesome/free-solid-svg-icons": "^6.7.2",
2526
"@fortawesome/react-fontawesome": "^3.0.1",
27+
"@graphql-typed-document-node/core": "^3.2.0",
2628
"@heroui/button": "^2.2.24",
2729
"@heroui/modal": "^2.2.21",
2830
"@heroui/react": "^2.8.2",
@@ -68,6 +70,11 @@
6870
"@axe-core/react": "^4.10.2",
6971
"@eslint/eslintrc": "^3.3.1",
7072
"@eslint/js": "^9.34.0",
73+
"@graphql-codegen/cli": "^5.0.7",
74+
"@graphql-codegen/near-operation-file-preset": "^3.1.0",
75+
"@graphql-codegen/typed-document-node": "^5.1.2",
76+
"@graphql-codegen/typescript": "^4.1.6",
77+
"@graphql-codegen/typescript-operations": "^4.6.1",
7178
"@lhci/cli": "^0.15.1",
7279
"@playwright/test": "^1.55.0",
7380
"@swc/core": "^1.13.5",

0 commit comments

Comments
 (0)