@depup/graphql-codegen__cli 6.2.1-depup.3 → 7.2.0-depup.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +27 -25
  3. package/changes.json +44 -36
  4. package/cjs/cli.js +17 -7
  5. package/cjs/codegen.js +84 -34
  6. package/cjs/config.js +55 -20
  7. package/cjs/documentTransforms.js +5 -1
  8. package/cjs/generate-and-save.js +1 -1
  9. package/cjs/graphql-config.js +5 -5
  10. package/cjs/init/helpers.js +8 -4
  11. package/cjs/init/index.js +1 -1
  12. package/cjs/init/plugins.js +3 -1
  13. package/cjs/init/questions.js +10 -3
  14. package/cjs/init/targets.js +1 -1
  15. package/cjs/isESMModule.js +9 -0
  16. package/cjs/load.js +6 -3
  17. package/cjs/utils/patterns.js +17 -6
  18. package/cjs/utils/watcher.js +12 -7
  19. package/cjs/version.js +4 -0
  20. package/esm/codegen.js +83 -33
  21. package/esm/config.js +55 -20
  22. package/esm/documentTransforms.js +5 -1
  23. package/esm/generate-and-save.js +1 -1
  24. package/esm/graphql-config.js +5 -5
  25. package/esm/init/helpers.js +8 -4
  26. package/esm/init/index.js +1 -1
  27. package/esm/init/plugins.js +3 -1
  28. package/esm/init/questions.js +11 -4
  29. package/esm/init/targets.js +1 -1
  30. package/esm/isESMModule.js +6 -0
  31. package/esm/load.js +6 -3
  32. package/esm/utils/file-system.js +1 -1
  33. package/esm/utils/patterns.js +17 -6
  34. package/esm/utils/watcher.js +12 -7
  35. package/esm/version.js +1 -0
  36. package/package.json +78 -69
  37. package/typings/config.d.cts +3 -2
  38. package/typings/config.d.ts +3 -2
  39. package/typings/init/questions.d.cts +1 -1
  40. package/typings/init/questions.d.ts +1 -1
  41. package/typings/init/targets.d.cts +1 -1
  42. package/typings/init/targets.d.ts +1 -1
  43. package/typings/isESMModule.d.cts +6 -0
  44. package/typings/isESMModule.d.ts +6 -0
  45. package/typings/load.d.cts +3 -2
  46. package/typings/load.d.ts +3 -2
  47. package/typings/version.d.cts +1 -0
  48. package/typings/version.d.ts +1 -0
  49. package/cjs/utils/abort-controller-polyfill.js +0 -99
  50. package/esm/utils/abort-controller-polyfill.js +0 -96
  51. package/typings/utils/abort-controller-polyfill.d.cts +0 -5
  52. package/typings/utils/abort-controller-polyfill.d.ts +0 -5
@@ -2,11 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CodegenExtension = void 0;
4
4
  exports.findAndLoadGraphQLConfig = findAndLoadGraphQLConfig;
5
+ const graphql_config_1 = require("graphql-config");
5
6
  const apollo_engine_loader_1 = require("@graphql-tools/apollo-engine-loader");
6
7
  const code_file_loader_1 = require("@graphql-tools/code-file-loader");
7
8
  const git_loader_1 = require("@graphql-tools/git-loader");
8
9
  const github_loader_1 = require("@graphql-tools/github-loader");
9
- const graphql_config_1 = require("graphql-config");
10
10
  const CodegenExtension = (api) => {
11
11
  // Schema
12
12
  api.loaders.schema.register(new code_file_loader_1.CodeFileLoader({
@@ -48,10 +48,6 @@ function isGraphQLConfig(config) {
48
48
  if (!config) {
49
49
  return false;
50
50
  }
51
- try {
52
- return config.getDefault().hasExtension('codegen');
53
- }
54
- catch { }
55
51
  try {
56
52
  for (const projectName in config.projects) {
57
53
  if (Object.prototype.hasOwnProperty.call(config.projects, projectName)) {
@@ -63,5 +59,9 @@ function isGraphQLConfig(config) {
63
59
  }
64
60
  }
65
61
  catch { }
62
+ try {
63
+ return config.getDefault().hasExtension('codegen');
64
+ }
65
+ catch { }
66
66
  return false;
67
67
  }
@@ -8,21 +8,25 @@ exports.italic = italic;
8
8
  const tslib_1 = require("tslib");
9
9
  const fs_1 = require("fs");
10
10
  const path_1 = require("path");
11
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
12
+ const detect_indent_1 = tslib_1.__importDefault(require("detect-indent"));
11
13
  const generator_1 = tslib_1.__importDefault(require("@babel/generator"));
12
14
  const template_1 = tslib_1.__importDefault(require("@babel/template"));
13
15
  const t = tslib_1.__importStar(require("@babel/types"));
14
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
15
- const detect_indent_1 = tslib_1.__importDefault(require("detect-indent"));
16
16
  const get_latest_version_js_1 = require("../utils/get-latest-version.js");
17
17
  const types_js_1 = require("./types.js");
18
18
  function jsObjectToBabelObjectExpression(obj) {
19
19
  const objExp = t.objectExpression([]);
20
20
  for (const [key, val] of Object.entries(obj)) {
21
21
  if (Array.isArray(val)) {
22
- objExp.properties.push(t.objectProperty(/^[a-zA-Z0-9]+$/.test(key) ? t.identifier(key) : t.stringLiteral(key), t.arrayExpression(val.map(v => (typeof v === 'object' ? jsObjectToBabelObjectExpression(v) : t.valueToNode(v))))));
22
+ objExp.properties.push(t.objectProperty(/^[a-zA-Z0-9]+$/.test(key) ? t.identifier(key) : t.stringLiteral(key), t.arrayExpression(val.map(v => typeof v === 'object'
23
+ ? jsObjectToBabelObjectExpression(v)
24
+ : t.valueToNode(v)))));
23
25
  }
24
26
  else {
25
- objExp.properties.push(t.objectProperty(/^[a-zA-Z0-9]+$/.test(key) ? t.identifier(key) : t.stringLiteral(key), typeof val === 'object' ? jsObjectToBabelObjectExpression(val) : t.valueToNode(val)));
27
+ objExp.properties.push(t.objectProperty(/^[a-zA-Z0-9]+$/.test(key) ? t.identifier(key) : t.stringLiteral(key), typeof val === 'object'
28
+ ? jsObjectToBabelObjectExpression(val)
29
+ : t.valueToNode(val)));
26
30
  }
27
31
  }
28
32
  return objExp;
package/cjs/init/index.js CHANGED
@@ -14,7 +14,7 @@ async function init() {
14
14
  Welcome to ${(0, helpers_js_1.bold)('GraphQL Code Generator')}!
15
15
  Answer few questions and we will setup everything for you.
16
16
  `);
17
- const possibleTargets = await (0, targets_js_1.guessTargets)();
17
+ const possibleTargets = (0, targets_js_1.guessTargets)();
18
18
  const answers = await (0, questions_js_1.getAnswers)(possibleTargets);
19
19
  // define config
20
20
  const config = {
@@ -10,7 +10,9 @@ exports.plugins = [
10
10
  value: 'typescript',
11
11
  pathInRepo: 'typescript/typescript',
12
12
  available: hasTag(types_js_1.Tags.typescript),
13
- shouldBeSelected: tags => oneOf(tags, types_js_1.Tags.angular, types_js_1.Tags.stencil) || allOf(tags, types_js_1.Tags.typescript, types_js_1.Tags.react) || noneOf(tags, types_js_1.Tags.flow),
13
+ shouldBeSelected: tags => oneOf(tags, types_js_1.Tags.angular, types_js_1.Tags.stencil) ||
14
+ allOf(tags, types_js_1.Tags.typescript, types_js_1.Tags.react) ||
15
+ noneOf(tags, types_js_1.Tags.flow),
14
16
  defaultExtension: '.ts',
15
17
  },
16
18
  {
@@ -21,7 +21,9 @@ async function getAnswers(possibleTargets) {
21
21
  validate: str => str.length > 0,
22
22
  });
23
23
  let documents;
24
- if (targets.includes(types_js_1.Tags.client) || targets.includes(types_js_1.Tags.angular) || targets.includes(types_js_1.Tags.stencil))
24
+ if (targets.includes(types_js_1.Tags.client) ||
25
+ targets.includes(types_js_1.Tags.angular) ||
26
+ targets.includes(types_js_1.Tags.stencil))
25
27
  documents = await (0, prompts_1.input)({
26
28
  message: 'Where are your operations and fragments?:',
27
29
  default: getDocumentsDefaultValue(targets),
@@ -46,7 +48,9 @@ async function getAnswers(possibleTargets) {
46
48
  });
47
49
  const config = await (0, prompts_1.input)({
48
50
  message: 'How to name the config file?',
49
- default: (() => targets.includes(types_js_1.Tags.client) || targets.includes(types_js_1.Tags.typescript) || targets.includes(types_js_1.Tags.angular)
51
+ default: (() => targets.includes(types_js_1.Tags.client) ||
52
+ targets.includes(types_js_1.Tags.typescript) ||
53
+ targets.includes(types_js_1.Tags.angular)
50
54
  ? 'codegen.ts'
51
55
  : 'codegen.yml')(),
52
56
  validate: str => {
@@ -136,7 +140,10 @@ function getApplicationTypeChoices(possibleTargets) {
136
140
  name: 'Application built with other framework or vanilla JS',
137
141
  key: 'client',
138
142
  value: [types_js_1.Tags.typescript, types_js_1.Tags.flow],
139
- checked: possibleTargets.Browser && !possibleTargets.Angular && !possibleTargets.React && !possibleTargets.Stencil,
143
+ checked: possibleTargets.Browser &&
144
+ !possibleTargets.Angular &&
145
+ !possibleTargets.React &&
146
+ !possibleTargets.Stencil,
140
147
  },
141
148
  ];
142
149
  }
@@ -4,7 +4,7 @@ exports.guessTargets = guessTargets;
4
4
  const fs_1 = require("fs");
5
5
  const path_1 = require("path");
6
6
  const types_js_1 = require("./types.js");
7
- async function guessTargets() {
7
+ function guessTargets() {
8
8
  const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.resolve)(process.cwd(), 'package.json'), 'utf8'));
9
9
  const dependencies = Object.keys({
10
10
  ...pkg.dependencies,
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isESMModule = void 0;
4
+ /**
5
+ * Poor mans ESM detection.
6
+ * Looking at this and you have a better method?
7
+ * Send a PR.
8
+ */
9
+ exports.isESMModule = (typeof __dirname === 'string') === false;
package/cjs/load.js CHANGED
@@ -4,6 +4,7 @@ exports.defaultDocumentsLoadOptions = exports.defaultSchemaLoadOptions = void 0;
4
4
  exports.loadSchema = loadSchema;
5
5
  exports.loadDocuments = loadDocuments;
6
6
  const path_1 = require("path");
7
+ const graphql_1 = require("graphql");
7
8
  const apollo_engine_loader_1 = require("@graphql-tools/apollo-engine-loader");
8
9
  const code_file_loader_1 = require("@graphql-tools/code-file-loader");
9
10
  const git_loader_1 = require("@graphql-tools/git-loader");
@@ -12,7 +13,6 @@ const graphql_file_loader_1 = require("@graphql-tools/graphql-file-loader");
12
13
  const json_file_loader_1 = require("@graphql-tools/json-file-loader");
13
14
  const load_1 = require("@graphql-tools/load");
14
15
  const url_loader_1 = require("@graphql-tools/url-loader");
15
- const graphql_1 = require("graphql");
16
16
  exports.defaultSchemaLoadOptions = {
17
17
  assumeValidSDL: true,
18
18
  sort: true,
@@ -73,7 +73,7 @@ async function loadDocuments(documentPointers, config) {
73
73
  // we omit paths that don't resolve to a specific file
74
74
  continue;
75
75
  }
76
- ignore.push((0, path_1.join)(process.cwd(), generatePath));
76
+ ignore.push((0, path_1.join)(config.cwd || process.cwd(), generatePath));
77
77
  }
78
78
  try {
79
79
  const loadedFromToolkit = await (0, load_1.loadDocuments)(documentPointers, {
@@ -91,7 +91,10 @@ async function loadDocuments(documentPointers, config) {
91
91
  throw error;
92
92
  }
93
93
  // For other errors, we need to add an error message with documentPointers, so it's better for DevX
94
- throw new Error([`Failed to load documents from ${Object.keys(documentPointers).join(',')}:`, printError(error)].join('\n'));
94
+ throw new Error([
95
+ `Failed to load documents from ${Object.keys(documentPointers).join(',')}:`,
96
+ printError(error),
97
+ ].join('\n'));
95
98
  }
96
99
  }
97
100
  const printError = (error) => {
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sortPatterns = exports.makeLocalPatternSet = exports.makeGlobalPatternSet = exports.makeShouldRebuild = exports.allAffirmativePatternsFromPatternSets = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const path_1 = require("path");
6
- const utils_1 = require("@graphql-tools/utils");
7
- const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
8
6
  const is_glob_1 = tslib_1.__importDefault(require("is-glob"));
9
7
  const micromatch_1 = tslib_1.__importDefault(require("micromatch"));
8
+ const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
9
+ const utils_1 = require("@graphql-tools/utils");
10
10
  const helpers_js_1 = require("./helpers.js");
11
11
  /**
12
12
  * Flatten a list of pattern sets to be a list of only the affirmative patterns
@@ -44,7 +44,10 @@ const makeShouldRebuild = ({ globalPatternSet, localPatternSets, }) => {
44
44
  const localMatchers = localPatternSets.map(localPatternSet => {
45
45
  return (path) => {
46
46
  // Is path negated by any negating watch pattern?
47
- if (matchesAnyNegatedPattern(path, [...globalPatternSet.watch.negated, ...localPatternSet.watch.negated])) {
47
+ if (matchesAnyNegatedPattern(path, [
48
+ ...globalPatternSet.watch.negated,
49
+ ...localPatternSet.watch.negated,
50
+ ])) {
48
51
  // Short circut: negations in watch patterns take priority
49
52
  return false;
50
53
  }
@@ -61,7 +64,10 @@ const makeShouldRebuild = ({ globalPatternSet, localPatternSets, }) => {
61
64
  ...globalPatternSet.documents.affirmative,
62
65
  ...localPatternSet.documents.affirmative,
63
66
  ]) &&
64
- !matchesAnyNegatedPattern(path, [...globalPatternSet.documents.negated, ...localPatternSet.documents.negated])) {
67
+ !matchesAnyNegatedPattern(path, [
68
+ ...globalPatternSet.documents.negated,
69
+ ...localPatternSet.documents.negated,
70
+ ])) {
65
71
  return true;
66
72
  }
67
73
  // Does path match schemas patterns (without being negated)?
@@ -69,7 +75,10 @@ const makeShouldRebuild = ({ globalPatternSet, localPatternSets, }) => {
69
75
  ...globalPatternSet.schemas.affirmative,
70
76
  ...localPatternSet.schemas.affirmative,
71
77
  ]) &&
72
- !matchesAnyNegatedPattern(path, [...globalPatternSet.schemas.negated, ...localPatternSet.schemas.negated])) {
78
+ !matchesAnyNegatedPattern(path, [
79
+ ...globalPatternSet.schemas.negated,
80
+ ...localPatternSet.schemas.negated,
81
+ ])) {
73
82
  return true;
74
83
  }
75
84
  // Otherwise, there is no match
@@ -100,7 +109,9 @@ const makeGlobalPatternSet = (initialContext) => {
100
109
  const config = initialContext.getConfig();
101
110
  return {
102
111
  watch: (0, exports.sortPatterns)([
103
- ...(typeof config.watch === 'boolean' ? [] : (0, plugin_helpers_1.normalizeInstanceOrArray)(config.watch ?? [])),
112
+ ...(typeof config.watch === 'boolean'
113
+ ? []
114
+ : (0, plugin_helpers_1.normalizeInstanceOrArray)(config.watch ?? [])),
104
115
  (0, path_1.relative)(process.cwd(), initialContext.filepath),
105
116
  ]),
106
117
  schemas: (0, exports.sortPatterns)(makePatternsFromSchemas((0, plugin_helpers_1.normalizeInstanceOrArray)(config.schema))),
@@ -3,18 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createWatcher = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const path_1 = require("path");
6
- const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
7
6
  const debounce_1 = tslib_1.__importDefault(require("debounce"));
8
- const micromatch_1 = tslib_1.__importDefault(require("micromatch"));
9
7
  const log_symbols_1 = tslib_1.__importDefault(require("log-symbols"));
8
+ const micromatch_1 = tslib_1.__importDefault(require("micromatch"));
9
+ const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
10
10
  const codegen_js_1 = require("../codegen.js");
11
11
  const config_js_1 = require("../config.js");
12
12
  const hooks_js_1 = require("../hooks.js");
13
- const file_system_js_1 = require("./file-system.js");
14
13
  const debugging_js_1 = require("./debugging.js");
14
+ const file_system_js_1 = require("./file-system.js");
15
15
  const logger_js_1 = require("./logger.js");
16
16
  const patterns_js_1 = require("./patterns.js");
17
- const abort_controller_polyfill_js_1 = require("./abort-controller-polyfill.js");
18
17
  function log(msg) {
19
18
  // double spaces to inline the message with Listr
20
19
  (0, logger_js_1.getLogger)().info(` ${msg}`);
@@ -29,8 +28,14 @@ const createWatcher = (initialContext, onNext) => {
29
28
  const localPatternSets = Object.keys(config.generates)
30
29
  .map(filename => (0, plugin_helpers_1.normalizeOutputParam)(config.generates[filename]))
31
30
  .map(conf => (0, patterns_js_1.makeLocalPatternSet)(conf));
32
- const allAffirmativePatterns = (0, patterns_js_1.allAffirmativePatternsFromPatternSets)([globalPatternSet, ...localPatternSets]);
33
- const shouldRebuild = (0, patterns_js_1.makeShouldRebuild)({ globalPatternSet, localPatternSets });
31
+ const allAffirmativePatterns = (0, patterns_js_1.allAffirmativePatternsFromPatternSets)([
32
+ globalPatternSet,
33
+ ...localPatternSets,
34
+ ]);
35
+ const shouldRebuild = (0, patterns_js_1.makeShouldRebuild)({
36
+ globalPatternSet,
37
+ localPatternSets,
38
+ });
34
39
  let watcherSubscription;
35
40
  const runWatcher = async (abortSignal) => {
36
41
  const watchDirectory = await findHighestCommonDirectory(allAffirmativePatterns);
@@ -133,7 +138,7 @@ const createWatcher = (initialContext, onNext) => {
133
138
  };
134
139
  // Use an AbortController for shutdown signals
135
140
  // NOTE: This will be polyfilled on Node 14 (or any environment without it defined)
136
- const abortController = new abort_controller_polyfill_js_1.AbortController();
141
+ const abortController = new AbortController();
137
142
  /**
138
143
  * Send shutdown signal and return a promise that only resolves after the
139
144
  * runningWatcher has resolved, which only resolved after the shutdown signal has been handled
package/cjs/version.js ADDED
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.version = void 0;
4
+ exports.version = '7.2.0';
package/esm/codegen.js CHANGED
@@ -2,23 +2,18 @@ import fs from 'fs';
2
2
  import { createRequire } from 'module';
3
3
  import { cpus } from 'os';
4
4
  import path from 'path';
5
+ import { buildASTSchema, GraphQLError, isSchema } from 'graphql';
6
+ import { Listr } from 'listr2';
5
7
  import { codegen } from '@graphql-codegen/core';
6
8
  import { getCachedDocumentNodeFromSchema, normalizeConfig, normalizeImportExtension, normalizeInstanceOrArray, normalizeOutputParam, } from '@graphql-codegen/plugin-helpers';
7
9
  import { NoTypeDefinitionsFound } from '@graphql-tools/load';
8
- import { buildASTSchema, GraphQLError, isSchema } from 'graphql';
9
10
  import { mergeTypeDefs } from '@graphql-tools/merge';
10
- import { Listr } from 'listr2';
11
11
  import { ensureContext } from './config.js';
12
+ import { getDocumentTransform } from './documentTransforms.js';
13
+ import { isESMModule } from './isESMModule.js';
12
14
  import { getPluginByName } from './plugins.js';
13
15
  import { getPresetByName } from './presets.js';
14
16
  import { debugLog, printLogs } from './utils/debugging.js';
15
- import { getDocumentTransform } from './documentTransforms.js';
16
- /**
17
- * Poor mans ESM detection.
18
- * Looking at this and you have a better method?
19
- * Send a PR.
20
- */
21
- const isESMModule = (typeof __dirname === 'string') === false;
22
17
  const makeDefaultLoader = (from) => {
23
18
  if (fs.statSync(from).isDirectory()) {
24
19
  from = path.join(from, '__fake.js');
@@ -31,6 +26,8 @@ const makeDefaultLoader = (from) => {
31
26
  * as import.meta is unavailable in a CommonJS context
32
27
  * and furthermore unavailable in stable Node.js.
33
28
  **/
29
+ // FIXME(pnpm-update): this causes dev-test devDeps to be brought into CLI's package.json, which is not ideal.
30
+ // Note that `relativeRequire.resolve(mod)` seems to work correctly for ESM as well.
34
31
  mod
35
32
  : relativeRequire.resolve(mod));
36
33
  };
@@ -56,6 +53,7 @@ export async function executeCodegen(input) {
56
53
  let rootConfig = {};
57
54
  let rootSchemas;
58
55
  let rootDocuments;
56
+ let rootExternalDocuments;
59
57
  const generates = {};
60
58
  const cache = createCache();
61
59
  // We need a simple string to uniqually identify the provided GraphQLSchema objects for the above cache.
@@ -97,6 +95,8 @@ export async function executeCodegen(input) {
97
95
  rootSchemas = normalizeInstanceOrArray(config.schema);
98
96
  /* Normalize root "documents" field */
99
97
  rootDocuments = normalizeInstanceOrArray(config.documents);
98
+ /* Normalize root "externalDocuments" field */
99
+ rootExternalDocuments = normalizeInstanceOrArray(config.externalDocuments);
100
100
  /* Normalize "generators" field */
101
101
  const generateKeys = Object.keys(config.generates || {});
102
102
  if (generateKeys.length === 0) {
@@ -169,9 +169,10 @@ export async function executeCodegen(input) {
169
169
  let outputSchemaAst;
170
170
  let outputSchema;
171
171
  const outputFileTemplateConfig = outputConfig.config || {};
172
- let outputDocuments = [];
172
+ const outputDocuments = [];
173
173
  const outputSpecificSchemas = normalizeInstanceOrArray(outputConfig.schema);
174
174
  let outputSpecificDocuments = normalizeInstanceOrArray(outputConfig.documents);
175
+ let outputSpecificExternalDocuments = normalizeInstanceOrArray(outputConfig.externalDocuments);
175
176
  const preset = hasPreset
176
177
  ? typeof outputConfig.preset === 'string'
177
178
  ? await getPresetByName(outputConfig.preset, makeDefaultLoader(context.cwd))
@@ -179,6 +180,7 @@ export async function executeCodegen(input) {
179
180
  : null;
180
181
  if (preset?.prepareDocuments) {
181
182
  outputSpecificDocuments = await preset.prepareDocuments(filename, outputSpecificDocuments);
183
+ outputSpecificExternalDocuments = await preset.prepareDocuments(filename, outputSpecificExternalDocuments);
182
184
  }
183
185
  return subTask.newListr([
184
186
  {
@@ -187,7 +189,10 @@ export async function executeCodegen(input) {
187
189
  debugLog(`[CLI] Loading Schemas`);
188
190
  const schemaPointerMap = {};
189
191
  const parsedSchemas = [];
190
- const allSchemaDenormalizedPointers = [...rootSchemas, ...outputSpecificSchemas];
192
+ const allSchemaDenormalizedPointers = [
193
+ ...rootSchemas,
194
+ ...outputSpecificSchemas,
195
+ ];
191
196
  for (const denormalizedPtr of allSchemaDenormalizedPointers) {
192
197
  if (isSchema(denormalizedPtr)) {
193
198
  parsedSchemas.push(denormalizedPtr);
@@ -199,7 +204,8 @@ export async function executeCodegen(input) {
199
204
  Object.assign(schemaPointerMap, denormalizedPtr);
200
205
  }
201
206
  }
202
- const hash = JSON.stringify(schemaPointerMap) + parsedSchemas.map(getJsObjectId).join(',');
207
+ const hash = JSON.stringify(schemaPointerMap) +
208
+ parsedSchemas.map(getJsObjectId).join(',');
203
209
  const result = await cache('schema', hash, async () => {
204
210
  // collect parsed schemas
205
211
  const schemasToMerge = [...parsedSchemas];
@@ -225,34 +231,74 @@ export async function executeCodegen(input) {
225
231
  title: 'Load GraphQL documents',
226
232
  task: wrapTask(async () => {
227
233
  debugLog(`[CLI] Loading Documents`);
228
- const documentPointerMap = {};
229
- const allDocumentsDenormalizedPointers = [...rootDocuments, ...outputSpecificDocuments];
230
- for (const denormalizedPtr of allDocumentsDenormalizedPointers) {
231
- if (typeof denormalizedPtr === 'string') {
232
- documentPointerMap[denormalizedPtr] = {};
233
- }
234
- else if (typeof denormalizedPtr === 'object') {
235
- Object.assign(documentPointerMap, denormalizedPtr);
234
+ const populateDocumentPointerMap = (allDocumentsDenormalizedPointers) => {
235
+ const pointer = {};
236
+ for (const denormalizedPtr of allDocumentsDenormalizedPointers) {
237
+ if (typeof denormalizedPtr === 'string') {
238
+ pointer[denormalizedPtr] = {};
239
+ }
240
+ else if (typeof denormalizedPtr === 'object') {
241
+ Object.assign(pointer, denormalizedPtr);
242
+ }
236
243
  }
237
- }
244
+ return pointer;
245
+ };
246
+ const allDocumentsDenormalizedPointers = [
247
+ ...rootDocuments,
248
+ ...outputSpecificDocuments,
249
+ ];
250
+ const documentPointerMap = populateDocumentPointerMap(allDocumentsDenormalizedPointers);
238
251
  const hash = JSON.stringify(documentPointerMap);
239
- const result = await cache('documents', hash, async () => {
252
+ const outputDocumentsStandard = await cache('documents', hash, async () => {
240
253
  try {
241
- const documents = await context.loadDocuments(documentPointerMap);
242
- return {
243
- documents,
244
- };
254
+ const documents = await context.loadDocuments(documentPointerMap, 'standard');
255
+ return documents;
245
256
  }
246
257
  catch (error) {
247
- if (error instanceof NoTypeDefinitionsFound && config.ignoreNoDocuments) {
248
- return {
249
- documents: [],
250
- };
258
+ if (error instanceof NoTypeDefinitionsFound &&
259
+ config.ignoreNoDocuments) {
260
+ return [];
251
261
  }
252
262
  throw error;
253
263
  }
254
264
  });
255
- outputDocuments = result.documents;
265
+ const allExternalDocumentsDenormalizedPointers = [
266
+ ...rootExternalDocuments,
267
+ ...outputSpecificExternalDocuments,
268
+ ];
269
+ const externalDocumentsPointerMap = populateDocumentPointerMap(allExternalDocumentsDenormalizedPointers);
270
+ const externalDocumentHash = JSON.stringify(externalDocumentsPointerMap);
271
+ const outputExternalDocuments = await cache('documents', externalDocumentHash, async () => {
272
+ try {
273
+ const documents = await context.loadDocuments(externalDocumentsPointerMap, 'external');
274
+ return documents;
275
+ }
276
+ catch (error) {
277
+ if (error instanceof NoTypeDefinitionsFound &&
278
+ config.ignoreNoDocuments) {
279
+ return [];
280
+ }
281
+ throw error;
282
+ }
283
+ });
284
+ /**
285
+ * Merging `standard` and `external` documents here,
286
+ * so they can be processed the same way,
287
+ * before passed into presets and plugins
288
+ */
289
+ const processedFile = {};
290
+ const mergedDocuments = [
291
+ ...outputDocumentsStandard,
292
+ ...outputExternalDocuments,
293
+ ];
294
+ for (const file of mergedDocuments) {
295
+ const fileIdentifier = (file.location || '') + (file.hash || '');
296
+ if (processedFile[fileIdentifier]) {
297
+ continue;
298
+ }
299
+ outputDocuments.push(file);
300
+ processedFile[fileIdentifier] = true;
301
+ }
256
302
  }, filename, `Load GraphQL documents: ${filename}`, ctx),
257
303
  },
258
304
  {
@@ -351,7 +397,9 @@ export async function executeCodegen(input) {
351
397
  exitOnError: false,
352
398
  };
353
399
  });
354
- return task.newListr(generateTasks, { concurrent: cpus().length || 1 });
400
+ return task.newListr(generateTasks, {
401
+ concurrent: cpus().length || 1,
402
+ });
355
403
  },
356
404
  },
357
405
  ], {
@@ -378,7 +426,9 @@ export async function executeCodegen(input) {
378
426
  const errors = executedContext.errors.map(subErr => subErr.message || subErr.toString());
379
427
  error = new AggregateError(executedContext.errors, String(errors.join('\n\n')));
380
428
  // Best-effort to all stack traces for debugging
381
- error.stack = `${error.stack}\n\n${executedContext.errors.map(subErr => subErr.stack).join('\n\n')}`;
429
+ error.stack = `${error.stack}\n\n${executedContext.errors
430
+ .map(subErr => subErr.stack)
431
+ .join('\n\n')}`;
382
432
  }
383
433
  return { result, error };
384
434
  }
package/esm/config.js CHANGED
@@ -1,16 +1,19 @@
1
1
  import { createHash } from 'crypto';
2
2
  import { promises } from 'fs';
3
3
  import { createRequire } from 'module';
4
+ import * as url from 'node:url';
4
5
  import { resolve } from 'path';
5
- import { createNoopProfiler, createProfiler, getCachedDocumentNodeFromSchema, } from '@graphql-codegen/plugin-helpers';
6
6
  import { cosmiconfig, defaultLoaders } from 'cosmiconfig';
7
- import { createJiti } from 'jiti';
8
7
  import { print } from 'graphql';
8
+ import { createJiti } from 'jiti';
9
9
  import { env } from 'string-env-interpolation';
10
10
  import yaml from 'yaml';
11
11
  import yargs from 'yargs';
12
+ import { createNoopProfiler, createProfiler, getCachedDocumentNodeFromSchema, } from '@graphql-codegen/plugin-helpers';
12
13
  import { findAndLoadGraphQLConfig } from './graphql-config.js';
13
- import { defaultDocumentsLoadOptions, defaultSchemaLoadOptions, loadDocuments, loadSchema } from './load.js';
14
+ import { isESMModule } from './isESMModule.js';
15
+ import { defaultDocumentsLoadOptions, defaultSchemaLoadOptions, loadDocuments, loadSchema, } from './load.js';
16
+ import { version } from './version.js';
14
17
  const { lstat } = promises;
15
18
  export function generateSearchPlaces(moduleName) {
16
19
  const extensions = ['json', 'yaml', 'yml', 'js', 'ts', 'config.js'];
@@ -180,12 +183,12 @@ export function buildOptions() {
180
183
  };
181
184
  }
182
185
  export function parseArgv(argv = process.argv) {
183
- return yargs(argv).options(buildOptions()).parse(argv);
186
+ return yargs(argv).version(version).options(buildOptions()).parse(argv);
184
187
  }
185
188
  export async function createContext(cliFlags = parseArgv(process.argv)) {
186
189
  if (cliFlags.require && cliFlags.require.length > 0) {
187
190
  const relativeRequire = createRequire(process.cwd());
188
- await Promise.all(cliFlags.require.map(mod => import(relativeRequire.resolve(mod, {
191
+ await Promise.all(cliFlags.require.map(mod => safeDynamicImport(relativeRequire.resolve(mod, {
189
192
  paths: [process.cwd()],
190
193
  }))));
191
194
  }
@@ -254,7 +257,7 @@ export class CodegenContext {
254
257
  this._config = config;
255
258
  this._graphqlConfig = graphqlConfig;
256
259
  this.filepath = this._graphqlConfig ? this._graphqlConfig.filepath : filepath;
257
- this.cwd = this._graphqlConfig ? this._graphqlConfig.dirpath : process.cwd();
260
+ this.cwd = this._graphqlConfig ? this._graphqlConfig.dirpath : config?.cwd || process.cwd();
258
261
  this.profiler = createNoopProfiler();
259
262
  }
260
263
  useProject(name) {
@@ -275,10 +278,18 @@ export class CodegenContext {
275
278
  this.config = { ...this._config, pluginContext: this._pluginContext };
276
279
  }
277
280
  }
278
- return {
281
+ const config = {
282
+ noSilentErrors: true, // When a `documents` pattern matches multiple files e.g. `*` exists in filename like `src/something.*.ts`, and some files fail but some pass syntax error check, the failed files will silently fail if `noSilentErrors: false`. So, `noSilentErrors: true` is turned on by default to help users detect errors faster.
279
283
  ...extraConfig,
280
284
  ...this.config,
281
285
  };
286
+ if (this._graphqlConfig) {
287
+ return config;
288
+ }
289
+ return {
290
+ ...config,
291
+ cwd: this.cwd,
292
+ };
282
293
  }
283
294
  updateConfig(config) {
284
295
  this.config = {
@@ -312,13 +323,15 @@ export class CodegenContext {
312
323
  }
313
324
  return addHashToSchema(loadSchema(pointer, config));
314
325
  }
315
- async loadDocuments(pointer) {
326
+ async loadDocuments(pointer, type) {
316
327
  const config = this.getConfig(defaultDocumentsLoadOptions);
317
328
  if (this._graphqlConfig) {
318
329
  // TODO: pointer won't work here
319
- return addHashToDocumentFiles(this._graphqlConfig.getProject(this._project).loadDocuments(pointer, { ...config, ...config.config }));
330
+ return addMetadataToSources(this._graphqlConfig
331
+ .getProject(this._project)
332
+ .loadDocuments(pointer, { ...config, ...config.config }), type);
320
333
  }
321
- return addHashToDocumentFiles(loadDocuments(pointer, config));
334
+ return addMetadataToSources(loadDocuments(pointer, config), type);
322
335
  }
323
336
  }
324
337
  export function ensureContext(input) {
@@ -340,18 +353,40 @@ function addHashToSchema(schemaPromise) {
340
353
  return schema;
341
354
  });
342
355
  }
343
- function hashDocument(doc) {
344
- if (doc.rawSDL) {
345
- return hashContent(doc.rawSDL);
346
- }
347
- if (doc.document) {
348
- return hashContent(print(doc.document));
356
+ async function addMetadataToSources(documentFilesPromise, type) {
357
+ function hashDocument(doc) {
358
+ if (doc.rawSDL) {
359
+ return hashContent(doc.rawSDL);
360
+ }
361
+ if (doc.document) {
362
+ return hashContent(print(doc.document));
363
+ }
364
+ return null;
349
365
  }
350
- return null;
351
- }
352
- function addHashToDocumentFiles(documentFilesPromise) {
353
- return documentFilesPromise.then(documentFiles => documentFiles.map(doc => {
366
+ return documentFilesPromise.then(documentFiles =>
367
+ // Note: `doc` here is technically `Source`, but by the end of the funciton it's `Types.DocumentFile`. This re-declaration makes TypeScript happy.
368
+ documentFiles.map((doc) => {
354
369
  doc.hash = hashDocument(doc);
370
+ doc.type = type;
355
371
  return doc;
356
372
  }));
357
373
  }
374
+ /**
375
+ * `safeDynamicImport` is a wrapper of dynamic `import()`
376
+ * to work across Linux and Windows
377
+ *
378
+ * CJS:
379
+ * `import()` seems to work well in CJS when given resolved filename
380
+ *
381
+ * ESM:
382
+ * On native Windows (i.e. no WSL or CI), filename may look like this: `C:\\Users\\path\\to\\file.ts`
383
+ * If used directly with `import()`, we'll see `ERR_UNSUPPORTED_ESM_URL_SCHEME` error because `c:` is not a valid protocol
384
+ * `url.pathToFileURL` turns the filename to `file:///C:/Users/path/to/file.ts`, which is import-able
385
+ */
386
+ const safeDynamicImport = (absoluteFilename) => {
387
+ if (isESMModule) {
388
+ const { href: fileUrl } = url.pathToFileURL(absoluteFilename);
389
+ return import(fileUrl);
390
+ }
391
+ return import(absoluteFilename);
392
+ };
@@ -10,7 +10,11 @@ export async function getDocumentTransform(documentTransform, loader, defaultNam
10
10
  if (isTransformFileConfig(documentTransform)) {
11
11
  const name = Object.keys(documentTransform)[0];
12
12
  const transformObject = await getDocumentTransformByName(name, loader);
13
- return { name, transformObject, config: Object.values(documentTransform)[0] };
13
+ return {
14
+ name,
15
+ transformObject,
16
+ config: Object.values(documentTransform)[0],
17
+ };
14
18
  }
15
19
  throw new Error(`
16
20
  An unknown format document transform: '${defaultName}'.