├── gql-codegen-cover.png
├── .prettierrc
├── .vscodeignore
├── .vscode
├── extensions.json
├── settings.json
├── tasks.json
└── launch.json
├── .eslintrc
├── .github
└── workflows
│ └── main.yml
├── tsconfig.json
├── LICENSE
├── .gitignore
├── vsc-extension-quickstart.md
├── README.md
├── package.json
└── src
└── extension.ts
/gql-codegen-cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capaj/graphql-codegen-vscode/HEAD/gql-codegen-cover.png
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "arrowParens": "always",
3 | "singleQuote": true,
4 | "semi": false,
5 | "trailingComma": "none"
6 | }
7 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/**
4 | src/**
5 | .gitignore
6 | .yarnrc
7 | vsc-extension-quickstart.md
8 | **/tsconfig.json
9 | **/.eslintrc.json
10 | **/*.map
11 | **/*.ts
12 | node_modules/**
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": ["dbaeumer.vscode-eslint", "eamodio.tsl-problem-matcher"]
5 | }
6 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "@typescript-eslint/parser",
4 | "plugins": ["@typescript-eslint"],
5 | "extends": [
6 | "eslint:recommended",
7 | "plugin:@typescript-eslint/eslint-recommended",
8 | "plugin:@typescript-eslint/recommended"
9 | ],
10 | "rules": {
11 | "@typescript-eslint/ban-ts-comment": "off"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: [master]
6 | pull_request:
7 | branches: [master]
8 |
9 | workflow_dispatch:
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - uses: actions/checkout@v2
17 | - uses: actions/setup-node@v2
18 | with:
19 | node-version: '18'
20 | cache: 'npm'
21 | - run: npm ci
22 | - run: npm run tsc
23 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false // set this to true to hide the "out" folder with the compiled JS files
5 | },
6 | "search.exclude": {
7 | "out": true // set this to false to include "out" folder in search results
8 | },
9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
10 | "typescript.tsc.autoDetect": "off",
11 | "cSpell.words": ["Codegen", "clonedeep", "codegens", "multimatch"],
12 | "typescript.tsdk": "node_modules/typescript/lib"
13 | }
14 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es6",
5 | "outDir": "dist",
6 | "lib": ["es6"],
7 | "sourceMap": true,
8 | "rootDir": "src",
9 | "esModuleInterop": true,
10 | "strict": true /* enable all strict type-checking options */,
11 | "useUnknownInCatchVariables": false
12 | /* Additional Checks */
13 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
14 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
15 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
16 | },
17 | "exclude": ["node_modules", ".vscode-test"]
18 | }
19 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "problemMatcher": ["$ts-webpack-watch", "$tslint-webpack-watch"],
10 | "isBackground": true,
11 | "presentation": {
12 | "reveal": "never"
13 | },
14 | "group": {
15 | "kind": "build",
16 | "isDefault": true
17 | }
18 | },
19 | {
20 | "type": "npm",
21 | "script": "test-watch",
22 | "problemMatcher": "$tsc-watch",
23 | "isBackground": true,
24 | "presentation": {
25 | "reveal": "never"
26 | },
27 | "group": "build"
28 | }
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | {
6 | "version": "0.2.0",
7 | "configurations": [
8 | {
9 | "name": "Run Extension",
10 | "type": "extensionHost",
11 | "request": "launch",
12 | "args": ["--extensionDevelopmentPath=${workspaceFolder}"],
13 | "outFiles": ["${workspaceFolder}/dist/**/*.js"],
14 | "preLaunchTask": "npm: build"
15 | },
16 | {
17 | "name": "Extension Tests",
18 | "type": "extensionHost",
19 | "request": "launch",
20 | "args": [
21 | "--verbose",
22 | "--extensionDevelopmentPath=${workspaceFolder}",
23 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
24 | ],
25 | "outFiles": ["${workspaceFolder}/out/test/**/*.js"],
26 | "preLaunchTask": "npm: test-watch"
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Jiri Spac
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 | out
106 | dist
107 | node_modules
108 | .vscode-test/
109 | *.vsix
110 |
--------------------------------------------------------------------------------
/vsc-extension-quickstart.md:
--------------------------------------------------------------------------------
1 | # Welcome to your VS Code Extension
2 |
3 | ## What's in the folder
4 |
5 | - This folder contains all of the files necessary for your extension.
6 | - `package.json` - this is the manifest file in which you declare your extension and command.
7 | - The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin.
8 | - `src/extension.ts` - this is the main file where you will provide the implementation of your command.
9 | - The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
10 | - We pass the function containing the implementation of the command as the second parameter to `registerCommand`.
11 |
12 | ## Get up and running straight away
13 |
14 | - Press `F5` to open a new window with your extension loaded.
15 | - Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`.
16 | - Set breakpoints in your code inside `src/extension.ts` to debug your extension.
17 | - Find output from your extension in the debug console.
18 |
19 | ## Make changes
20 |
21 | - You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`.
22 | - You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
23 |
24 | ## Explore the API
25 |
26 | - You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`.
27 |
28 | ## Run tests
29 |
30 | - Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Extension Tests`.
31 | - Press `F5` to run the tests in a new window with your extension loaded.
32 | - See the output of the test result in the debug console.
33 | - Make changes to `src/test/suite/extension.test.ts` or create new test files inside the `test/suite` folder.
34 | - The provided test runner will only consider files matching the name pattern `**.test.ts`.
35 | - You can create folders inside the `test` folder to structure your tests any way you want.
36 |
37 | ## Go further
38 |
39 | - Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension).
40 | - [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VSCode extension marketplace.
41 | - Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration).
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | # graphql-codegen-vscode
8 |
9 | Runs [@graphql-codegen](https://github.com/dotansimha/graphql-code-generator) generation as soon as you hit save on any `gql` or `graphql` file.
10 | Keep in mind it will only run when your node_modules contains `@graphql-codegen/cli` package.
11 |
12 | ## Extension config
13 |
14 | - `"graphql-codegen.fileExtensionsDeclaringGraphQLDocuments"`: change which file extensions are watched for saves. Defaults to `graphql` and `gql`. If you just use these files to define your mutations you don't need to configure anything.
15 | - `"graphql-codegen.filePathToWatch"`: allow users to specify a multimatch patters that file paths should match before running codegen. This is important as users could specify a more broad file (eg `ts`) that could exist in both paths relevant to graphql generation and paths that are not. Defaults to `null`, so watches everything.
16 | - `"graphql-codegen.configFilePath"`: allow users to specify a path to the codegen configuration file. Defaults to `codegen.yml`.
17 |
18 | ### How is it different than VilvaAthibanPB.graphql-codegen
19 |
20 | This extension uses codegen from your node_modules inside the folder you are working on, so you will never get a mismatching output to what your CLI would give you. Also it is faster-especially on large projects. VilvaAthibanPB's always executes all of the codegens.
21 | This extensions only executes codegens that match the last saved file.
22 |
23 | ### OS support
24 |
25 | Should support all major OSes.
26 |
27 | ### Contributing
28 |
29 | Testing is done manually until some basic specs are added.
30 |
31 | ## CLI Version support
32 |
33 | Extension was initially tested with @graphql-codegen/cli version 1.21.x. Last version is tested with version 5.0.0
34 | Other versions might not work as expected. If you hit any problems with other versions, please report them. The aim is to support as broad range of CLI versions as possible.
35 |
36 | ## FAQ
37 |
38 | ### Command output
39 |
40 | Since this runs the codegen behind the scenes you cannot see the output. You get notified of success/error with a vscode information message like this:
41 |
42 | 
43 |
44 | ### Multiple workspaces support
45 |
46 | You can have multiple workspaces in your editor, but keep in mind that we always iterate from the first to last and we run codegen inside the first workspace which has `/node_modules/@graphql-codegen/cli` module available.
47 | If you have multiple VSCode workspaces with this module, it might not work correctly.
48 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "graphql-codegen-vscode",
3 | "displayName": "graphql-codegen",
4 | "publisher": "capaj",
5 | "repository": {
6 | "type": "git",
7 | "url": "git+https://github.com/capaj/graphql-codegen-vscode.git"
8 | },
9 | "description": "integrates graphql-codegen into vscode, running it every time your query/mutation is saved",
10 | "icon": "gql-codegen-cover.png",
11 | "version": "1.1.4",
12 | "engines": {
13 | "vscode": "^1.94.0"
14 | },
15 | "categories": [
16 | "Other"
17 | ],
18 | "main": "./dist/graphql-codegen-vscode.js",
19 | "activationEvents": [
20 | "onLanguage:graphql",
21 | "onLanguage:GraphQL",
22 | "workspaceContains:package.json"
23 | ],
24 | "contributes": {
25 | "commands": [
26 | {
27 | "command": "graphql-codegen.generateGqlCodegen",
28 | "title": "Generate GQL codegen"
29 | }
30 | ],
31 | "configuration": {
32 | "title": "GraphQL Codegen",
33 | "properties": {
34 | "graphql-codegen.fileExtensionsDeclaringGraphQLDocuments": {
35 | "type": "array",
36 | "items": {
37 | "type": "string"
38 | },
39 | "default": [
40 | "graphql",
41 | "gql"
42 | ],
43 | "description": "GraphQL Codegen will automatically re-run codegen when files matching these file extensions are saved."
44 | },
45 | "graphql-codegen.filePathToWatch": {
46 | "type": [
47 | "string",
48 | "null"
49 | ],
50 | "default": null,
51 | "markdownDescription": "If specified, GraphQL Codegen will only re-run codegen if the files match the specified glob path. Uses [minimatch](https://github.com/isaacs/minimatch) glob syntax."
52 | },
53 | "graphql-codegen.configFilePath": {
54 | "type": [
55 | "string",
56 | "null"
57 | ],
58 | "default": null,
59 | "markdownDescription": "Path to the codegen configuration file"
60 | }
61 | }
62 | }
63 | },
64 | "scripts": {
65 | "vscode:prepublish": "npm run build",
66 | "pub": "vsce publish",
67 | "build": "esbuild src/extension.ts --bundle --outfile=dist/graphql-codegen-vscode.js --sourcemap --external:vscode --platform=node",
68 | "compile": "tsc -p ./",
69 | "tsc": "tsc --noEmit",
70 | "watch": "tsc -watch -p ./",
71 | "test-compile": "tsc -p ./",
72 | "test-watch": "tsc -watch -p ./",
73 | "pretest": "npm run test-compile && npm run lint",
74 | "lint": "eslint src --ext ts",
75 | "test": "npm run pretest"
76 | },
77 | "devDependencies": {
78 | "@types/glob": "^8.1.0",
79 | "@types/lodash.clonedeep": "^4.5.9",
80 | "@types/mocha": "^10.0.9",
81 | "@types/node": "^22.7.5",
82 | "@types/vscode": "^1.94.0",
83 | "@typescript-eslint/eslint-plugin": "^8.8.1",
84 | "@typescript-eslint/parser": "^8.8.1",
85 | "esbuild": "^0.24.0",
86 | "eslint": "^9",
87 | "glob": "^11.0.0",
88 | "husky": "^9.1.6",
89 | "mocha": "^10.7.3",
90 | "prettier": "^3.3.3",
91 | "pretty-quick": "^4.0.0",
92 | "ts-loader": "^9.5.1",
93 | "typescript": "^5.6.3",
94 | "vscode-test": "^1.6.1"
95 | },
96 | "husky": {
97 | "hooks": {
98 | "pre-commit": "pretty-quick --staged"
99 | }
100 | },
101 | "dependencies": {
102 | "@graphql-codegen/cli": "^5.0.3",
103 | "globby": "^14.0.2",
104 | "graphql": "^16.9.0",
105 | "graphql-config": "^5.1.3",
106 | "lodash.clonedeep": "^4.5.0",
107 | "multimatch": "^7.0.0"
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/extension.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-explicit-any */
2 | import * as vscode from 'vscode'
3 | import * as graphqlCodegenCli from '@graphql-codegen/cli'
4 |
5 | import * as path from 'path'
6 | import multimatch from 'multimatch'
7 | import cloneDeep from 'lodash.clonedeep'
8 | import { YamlCliFlags } from '@graphql-codegen/cli'
9 |
10 | import { globby } from 'globby'
11 |
12 | let workspaceWithGraphqlCodegenCli: string | null = null
13 |
14 | const makePathAbsolute = (fsPath: string): string => {
15 | if (path.isAbsolute(fsPath) || fsPath.startsWith('http')) {
16 | return fsPath
17 | }
18 | if (!workspaceWithGraphqlCodegenCli) {
19 | throw new Error(
20 | 'workspaceWithGraphqlCodegenCli is not set. This should not happen, please report this as a bug.'
21 | )
22 | }
23 | return path.join(workspaceWithGraphqlCodegenCli, fsPath)
24 | }
25 |
26 | const makePathOrPathArrayAbsolute = (
27 | fsPath: string | string[]
28 | ): string | string[] => {
29 | if (Array.isArray(fsPath)) {
30 | return fsPath.map(makePathOrPathArrayAbsolute) as string[]
31 | }
32 | return makePathAbsolute(fsPath)
33 | }
34 |
35 | const makePathAbsoluteInSchema = (
36 | schema: string | Record | (string | Record)[]
37 | ): string | Record | (string | Record)[] => {
38 | if (Array.isArray(schema)) {
39 | return schema.map(makePathAbsoluteInSchema)
40 | }
41 |
42 | if (typeof schema === 'string') {
43 | return makePathAbsolute(schema)
44 | }
45 |
46 | const [path, configuration] = Object.entries(schema)[0]
47 | return { [makePathAbsolute(path)]: configuration }
48 | }
49 |
50 | const PLUGIN_SETTINGS_ID = 'graphql-codegen'
51 | const FILE_EXTENSIONS_WITH_DOCUMENTS_KEY =
52 | 'fileExtensionsDeclaringGraphQLDocuments'
53 | const FILE_PATH_TO_WATCH_KEY = 'filePathToWatch'
54 | const CONFIG_FILE_PATH = 'configFilePath'
55 |
56 | function shouldRunGQLCodegenOnFile(filePath: string): boolean {
57 | const configuration = vscode.workspace.getConfiguration(PLUGIN_SETTINGS_ID)
58 |
59 | const fileExtensionsContainingGraphQLDocuments = configuration.get(
60 | FILE_EXTENSIONS_WITH_DOCUMENTS_KEY,
61 | ['graphql', 'gql']
62 | )
63 | const filePathToWatch = configuration.get(
64 | FILE_PATH_TO_WATCH_KEY,
65 | null
66 | )
67 |
68 | const fileMatchesExtensions = fileExtensionsContainingGraphQLDocuments.some(
69 | (ext) => filePath.endsWith(ext)
70 | )
71 | const fileInPathToWatch =
72 | filePathToWatch == null || multimatch(filePath, filePathToWatch).length > 0
73 |
74 | return fileMatchesExtensions && fileInPathToWatch
75 | }
76 |
77 | let cli: typeof graphqlCodegenCli | null = null
78 |
79 | function requireGQLCodegenCli() {
80 | if (cli) {
81 | return cli
82 | }
83 | if (vscode.workspace.workspaceFolders === undefined) {
84 | return
85 | }
86 | for (const dir of vscode.workspace.workspaceFolders) {
87 | try {
88 | cli = require(
89 | path.join(dir.uri.fsPath, '/node_modules/@graphql-codegen/cli')
90 | )
91 | workspaceWithGraphqlCodegenCli = dir.uri.fsPath
92 | return cli
93 | } catch (err) {
94 | // ignore-we only want to run if @graphql-codegen/cli is installed in node modules
95 | }
96 | }
97 | }
98 |
99 | const getConfigPath = async () => {
100 | const configuration = vscode.workspace.getConfiguration(PLUGIN_SETTINGS_ID)
101 | const userConfigPath = configuration.get(
102 | CONFIG_FILE_PATH,
103 | undefined
104 | )
105 |
106 | if (userConfigPath) {
107 | return makePathAbsolute(userConfigPath)
108 | }
109 |
110 | if (cli == null || !workspaceWithGraphqlCodegenCli) {
111 | throw new Error(
112 | 'cli is not set. This should not happen, please report this as a bug.'
113 | )
114 | }
115 |
116 | const foundConfigs = await globby(cli.generateSearchPlaces('codegen'), {
117 | cwd: workspaceWithGraphqlCodegenCli
118 | })
119 |
120 | return path.join(workspaceWithGraphqlCodegenCli, foundConfigs[0])
121 | }
122 |
123 | // TODO figure out why we're getting Activating extension 'GraphQL.vscode-graphql-execution' failed: Cannot find module 'graphql-config'
124 | // Require stack:
125 | // - /home/capaj/.vscode/extensions/graphql.vscode-graphql-execution-0.1.7/dist/providers/exec-content.js
126 | // - /home/capaj/.vscode/extensions/graphql.vscode-graphql-execution-0.1.7/dist/extension.js
127 | // it does not seem to affect anything, just annoying spam in the console, generation works fine
128 | export function activate(context: vscode.ExtensionContext) {
129 | let cachedCtx: graphqlCodegenCli.CodegenContext | null = null
130 | let originalGenerates: Record | null = null
131 |
132 | const getCodegenContextForVSCode = async () => {
133 | if (cachedCtx) {
134 | return cachedCtx
135 | }
136 |
137 | if (!cli) {
138 | vscode.window.showWarningMessage(
139 | `could not find '/node_modules/@graphql-codegen/cli'`
140 | )
141 | return
142 | }
143 |
144 | if (!workspaceWithGraphqlCodegenCli) {
145 | vscode.window.showWarningMessage(
146 | `could not find workspace with graphql-codegen-cli`
147 | )
148 | return
149 | }
150 |
151 | try {
152 | const configFilePath = await getConfigPath()
153 |
154 | const flags: Partial = {
155 | config: configFilePath
156 | }
157 | cachedCtx = await cli.createContext(flags as YamlCliFlags)
158 |
159 | cachedCtx.cwd = workspaceWithGraphqlCodegenCli
160 |
161 | const config = cachedCtx.getConfig()
162 | if (!config) {
163 | return
164 | }
165 |
166 | if (config.schema) {
167 | // typically on a config for a single codegen artefact0
168 | config.schema = makePathAbsoluteInSchema(config.schema)
169 | }
170 |
171 | const generates = config.generates
172 | if (generates) {
173 | originalGenerates = cloneDeep(generates)
174 | const generatesWithAllAbsolutePaths: Record = {}
175 | // typically on a config for a codegen with multiple artifacts
176 | for (const codegenGenerateOutput of Object.keys(generates)) {
177 | const codegenGenerate = generates[codegenGenerateOutput] as any // as Types.ConfiguredOutput
178 |
179 | if (codegenGenerate.schema) {
180 | codegenGenerate.schema = makePathAbsoluteInSchema(
181 | codegenGenerate.schema
182 | )
183 | }
184 | if (
185 | codegenGenerate.preset &&
186 | typeof codegenGenerate.preset === 'string' &&
187 | codegenGenerate.preset.includes('near-operation-file') &&
188 | !codegenGenerate.presetConfig?.cwd
189 | ) {
190 | if (!codegenGenerate.presetConfig) {
191 | codegenGenerate.presetConfig = {}
192 | }
193 | codegenGenerate.presetConfig.cwd = workspaceWithGraphqlCodegenCli
194 | }
195 |
196 | codegenGenerate.originalOutputPath = codegenGenerateOutput
197 | generatesWithAllAbsolutePaths[
198 | makePathAbsolute(codegenGenerateOutput) // this is only needed for windows. Not sure why, but it works fine on linux even when these paths are relative
199 | ] = codegenGenerate
200 | }
201 | config.generates = generatesWithAllAbsolutePaths
202 | }
203 |
204 | cachedCtx.updateConfig(config)
205 |
206 | // console.log('cached ctx', cachedCtx)
207 |
208 | return cachedCtx
209 | } catch (err) {
210 | console.error(err)
211 | throw err
212 | }
213 | }
214 |
215 | vscode.workspace.onDidSaveTextDocument(
216 | async (document: vscode.TextDocument) => {
217 | if (shouldRunGQLCodegenOnFile(document.fileName)) {
218 | requireGQLCodegenCli() // require the package lazily as late as possible-makes it possible to install the deps and get the generation working right away
219 |
220 | const ctx = await getCodegenContextForVSCode()
221 | if (!ctx) {
222 | return
223 | }
224 |
225 | const config = ctx.getConfig()
226 | if (!config) {
227 | return
228 | }
229 | if (config.schema) {
230 | config.documents = document.fileName
231 | } else {
232 | const { generates } = config
233 |
234 | for (const codegenGenerateOutput of Object.keys(generates)) {
235 | const codegenGenerate = generates[codegenGenerateOutput] as any // as Types.ConfiguredOutput
236 |
237 | const matches = multimatch(
238 | document.fileName.replace(
239 | `${workspaceWithGraphqlCodegenCli}/`,
240 | ''
241 | ),
242 | // @ts-expect-error
243 | originalGenerates[codegenGenerate.originalOutputPath].documents
244 | )
245 |
246 | if (matches.length === 0) {
247 | // this file does not match the glob. This will not generate so we can omit this
248 | codegenGenerate.documents = []
249 | } else {
250 | codegenGenerate.documents = document.fileName
251 | }
252 | }
253 | }
254 |
255 | ctx.updateConfig(config)
256 |
257 | await runCliGenerateWithUINotifications(ctx, document.fileName)
258 | }
259 | // const customConfig = customExtensionConfig()
260 | }
261 | )
262 |
263 | const disposable = vscode.commands.registerCommand(
264 | 'graphql-codegen.generateGqlCodegen',
265 | async () => {
266 | requireGQLCodegenCli()
267 |
268 | const ctx = await getCodegenContextForVSCode()
269 | if (!ctx) {
270 | return
271 | }
272 |
273 | const config = ctx.getConfig()
274 | if (!config) {
275 | vscode.window.showWarningMessage(
276 | `could not find @graphql-codegen/cli config`
277 | )
278 | return
279 | }
280 |
281 | config.documents = makePathOrPathArrayAbsolute(
282 | config.documents as string[]
283 | )
284 |
285 | ctx.updateConfig(config)
286 |
287 | await runCliGenerateWithUINotifications(ctx)
288 | }
289 | )
290 | context.subscriptions.push(disposable)
291 | }
292 |
293 | async function runCliGenerateWithUINotifications(
294 | ctx: graphqlCodegenCli.CodegenContext,
295 | file?: string
296 | ) {
297 | if (!cli) {
298 | vscode.window.showWarningMessage(
299 | `could not find '/node_modules/@graphql-codegen/cli'`
300 | )
301 | return
302 | }
303 |
304 | try {
305 | await cli.generate(ctx)
306 |
307 | vscode.window.showInformationMessage(
308 | `graphql codegen ${file ?? ''} successful!`
309 | )
310 | } catch (err) {
311 | if (err.errors?.length) {
312 | vscode.window.showErrorMessage(
313 | `Codegen threw ${err.errors.length} ${
314 | err.errors.length === 1 ? 'error' : 'errors'
315 | }, first one: ${err.errors[0].message}`
316 | )
317 | } else {
318 | vscode.window.showErrorMessage(`Codegen threw error: ${err.message}`)
319 | }
320 | }
321 | }
322 |
323 | export function deactivate() {
324 | cli = null
325 | }
326 |
--------------------------------------------------------------------------------