@depup/graphql-codegen__cli 6.2.1-depup.0

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 (112) hide show
  1. package/README.md +51 -0
  2. package/changes.json +90 -0
  3. package/cjs/bin.js +13 -0
  4. package/cjs/cli.js +64 -0
  5. package/cjs/codegen.js +388 -0
  6. package/cjs/config.js +370 -0
  7. package/cjs/documentTransforms.js +63 -0
  8. package/cjs/generate-and-save.js +153 -0
  9. package/cjs/graphql-config.js +67 -0
  10. package/cjs/hooks.js +93 -0
  11. package/cjs/index.js +13 -0
  12. package/cjs/init/helpers.js +90 -0
  13. package/cjs/init/index.js +62 -0
  14. package/cjs/init/plugins.js +136 -0
  15. package/cjs/init/questions.js +177 -0
  16. package/cjs/init/targets.js +45 -0
  17. package/cjs/init/types.js +15 -0
  18. package/cjs/load.js +102 -0
  19. package/cjs/package.json +1 -0
  20. package/cjs/plugins.js +43 -0
  21. package/cjs/presets.js +50 -0
  22. package/cjs/utils/abort-controller-polyfill.js +99 -0
  23. package/cjs/utils/cli-error.js +24 -0
  24. package/cjs/utils/debugging.js +22 -0
  25. package/cjs/utils/file-system.js +24 -0
  26. package/cjs/utils/get-latest-version.js +14 -0
  27. package/cjs/utils/helpers.js +12 -0
  28. package/cjs/utils/logger.js +24 -0
  29. package/cjs/utils/patterns.js +235 -0
  30. package/cjs/utils/watcher.js +244 -0
  31. package/esm/bin.js +11 -0
  32. package/esm/cli.js +37 -0
  33. package/esm/codegen.js +384 -0
  34. package/esm/config.js +357 -0
  35. package/esm/documentTransforms.js +59 -0
  36. package/esm/generate-and-save.js +149 -0
  37. package/esm/graphql-config.js +62 -0
  38. package/esm/hooks.js +89 -0
  39. package/esm/index.js +7 -0
  40. package/esm/init/helpers.js +82 -0
  41. package/esm/init/index.js +59 -0
  42. package/esm/init/plugins.js +133 -0
  43. package/esm/init/questions.js +172 -0
  44. package/esm/init/targets.js +42 -0
  45. package/esm/init/types.js +12 -0
  46. package/esm/load.js +97 -0
  47. package/esm/plugins.js +40 -0
  48. package/esm/presets.js +47 -0
  49. package/esm/utils/abort-controller-polyfill.js +96 -0
  50. package/esm/utils/cli-error.js +20 -0
  51. package/esm/utils/debugging.js +17 -0
  52. package/esm/utils/file-system.js +17 -0
  53. package/esm/utils/get-latest-version.js +11 -0
  54. package/esm/utils/helpers.js +9 -0
  55. package/esm/utils/logger.js +18 -0
  56. package/esm/utils/patterns.js +226 -0
  57. package/esm/utils/watcher.js +239 -0
  58. package/package.json +205 -0
  59. package/typings/bin.d.cts +2 -0
  60. package/typings/bin.d.ts +2 -0
  61. package/typings/cli.d.cts +2 -0
  62. package/typings/cli.d.ts +2 -0
  63. package/typings/codegen.d.cts +6 -0
  64. package/typings/codegen.d.ts +6 -0
  65. package/typings/config.d.cts +152 -0
  66. package/typings/config.d.ts +152 -0
  67. package/typings/documentTransforms.d.cts +3 -0
  68. package/typings/documentTransforms.d.ts +3 -0
  69. package/typings/generate-and-save.d.cts +10 -0
  70. package/typings/generate-and-save.d.ts +10 -0
  71. package/typings/graphql-config.d.cts +3 -0
  72. package/typings/graphql-config.d.ts +3 -0
  73. package/typings/hooks.d.cts +11 -0
  74. package/typings/hooks.d.ts +11 -0
  75. package/typings/index.d.cts +8 -0
  76. package/typings/index.d.ts +8 -0
  77. package/typings/init/helpers.d.cts +10 -0
  78. package/typings/init/helpers.d.ts +10 -0
  79. package/typings/init/index.d.cts +1 -0
  80. package/typings/init/index.d.ts +1 -0
  81. package/typings/init/plugins.d.cts +2 -0
  82. package/typings/init/plugins.d.ts +2 -0
  83. package/typings/init/questions.d.cts +13 -0
  84. package/typings/init/questions.d.ts +13 -0
  85. package/typings/init/targets.d.cts +2 -0
  86. package/typings/init/targets.d.ts +2 -0
  87. package/typings/init/types.d.cts +30 -0
  88. package/typings/init/types.d.ts +30 -0
  89. package/typings/load.d.cts +15 -0
  90. package/typings/load.d.ts +15 -0
  91. package/typings/plugins.d.cts +2 -0
  92. package/typings/plugins.d.ts +2 -0
  93. package/typings/presets.d.cts +5 -0
  94. package/typings/presets.d.ts +5 -0
  95. package/typings/utils/abort-controller-polyfill.d.cts +5 -0
  96. package/typings/utils/abort-controller-polyfill.d.ts +5 -0
  97. package/typings/utils/cli-error.d.cts +10 -0
  98. package/typings/utils/cli-error.d.ts +10 -0
  99. package/typings/utils/debugging.d.cts +3 -0
  100. package/typings/utils/debugging.d.ts +3 -0
  101. package/typings/utils/file-system.d.cts +8 -0
  102. package/typings/utils/file-system.d.ts +8 -0
  103. package/typings/utils/get-latest-version.d.cts +6 -0
  104. package/typings/utils/get-latest-version.d.ts +6 -0
  105. package/typings/utils/helpers.d.cts +1 -0
  106. package/typings/utils/helpers.d.ts +1 -0
  107. package/typings/utils/logger.d.cts +5 -0
  108. package/typings/utils/logger.d.ts +5 -0
  109. package/typings/utils/patterns.d.cts +91 -0
  110. package/typings/utils/patterns.d.ts +91 -0
  111. package/typings/utils/watcher.d.cts +16 -0
  112. package/typings/utils/watcher.d.ts +16 -0
package/esm/hooks.js ADDED
@@ -0,0 +1,89 @@
1
+ import { exec } from 'child_process';
2
+ import { delimiter, sep } from 'path';
3
+ import { quote } from 'shell-quote';
4
+ import { debugLog } from './utils/debugging.js';
5
+ const DEFAULT_HOOKS = {
6
+ afterStart: [],
7
+ beforeDone: [],
8
+ onWatchTriggered: [],
9
+ onError: [],
10
+ afterOneFileWrite: [],
11
+ afterAllFileWrite: [],
12
+ beforeOneFileWrite: [],
13
+ beforeAllFileWrite: [],
14
+ };
15
+ function execShellCommand(cmd) {
16
+ return new Promise((resolve, reject) => {
17
+ exec(cmd, {
18
+ env: {
19
+ ...process.env,
20
+ PATH: `${process.env.PATH}${delimiter}${process.cwd()}${sep}node_modules${sep}.bin`,
21
+ },
22
+ }, (error, stdout, stderr) => {
23
+ if (error) {
24
+ reject(error);
25
+ // eslint-disable-next-line no-console
26
+ console.error(error);
27
+ }
28
+ else {
29
+ debugLog(stdout || stderr);
30
+ resolve(stdout || stderr);
31
+ }
32
+ });
33
+ });
34
+ }
35
+ async function executeHooks(hookName, _scripts = [], args = [], initialState) {
36
+ debugLog(`Running lifecycle hook "${hookName}" scripts...`);
37
+ let state = initialState;
38
+ const scripts = Array.isArray(_scripts) ? _scripts : [_scripts];
39
+ const quotedArgs = quote(args);
40
+ for (const script of scripts) {
41
+ if (typeof script === 'string') {
42
+ debugLog(`Running lifecycle hook "${hookName}" script: ${script} with args: ${quotedArgs}...`);
43
+ await execShellCommand(`${script} ${quotedArgs}`);
44
+ }
45
+ else {
46
+ debugLog(`Running lifecycle hook "${hookName}" script: ${script.name} with args: ${args.join(' ')}...`);
47
+ const hookArgs = state === undefined ? args : [...args, state];
48
+ const hookResult = await script(...hookArgs);
49
+ if (typeof hookResult === 'string' && typeof state === 'string') {
50
+ debugLog(`Received new content from lifecycle hook "${hookName}" script: ${script.name}`);
51
+ state = hookResult;
52
+ }
53
+ }
54
+ }
55
+ return state;
56
+ }
57
+ export const lifecycleHooks = (_hooks = {}) => {
58
+ const hooks = {
59
+ ...DEFAULT_HOOKS,
60
+ ..._hooks,
61
+ };
62
+ return {
63
+ afterStart: async () => {
64
+ await executeHooks('afterStart', hooks.afterStart);
65
+ },
66
+ onWatchTriggered: async (event, path) => {
67
+ await executeHooks('onWatchTriggered', hooks.onWatchTriggered, [event, path]);
68
+ },
69
+ onError: async (error) => {
70
+ await executeHooks('onError', hooks.onError, [error]);
71
+ },
72
+ afterOneFileWrite: async (path) => {
73
+ await executeHooks('afterOneFileWrite', hooks.afterOneFileWrite, [path]);
74
+ },
75
+ afterAllFileWrite: async (paths) => {
76
+ await executeHooks('afterAllFileWrite', hooks.afterAllFileWrite, paths);
77
+ },
78
+ beforeOneFileWrite: async (path, content) => {
79
+ const result = await executeHooks('beforeOneFileWrite', hooks.beforeOneFileWrite, [path], content);
80
+ return typeof result === 'string' ? result : content;
81
+ },
82
+ beforeAllFileWrite: async (paths) => {
83
+ await executeHooks('beforeAllFileWrite', hooks.beforeAllFileWrite, paths);
84
+ },
85
+ beforeDone: async () => {
86
+ await executeHooks('beforeDone', hooks.beforeDone);
87
+ },
88
+ };
89
+ };
package/esm/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export * from './cli.js';
2
+ export { executeCodegen } from './codegen.js';
3
+ export * from './config.js';
4
+ export { generate } from './generate-and-save.js';
5
+ export * from './graphql-config.js';
6
+ export * from './init/index.js';
7
+ export * from './utils/cli-error.js';
@@ -0,0 +1,82 @@
1
+ import { readFileSync, writeFileSync } from 'fs';
2
+ import { relative, resolve } from 'path';
3
+ import generate from '@babel/generator';
4
+ import template from '@babel/template';
5
+ import * as t from '@babel/types';
6
+ import chalk from 'chalk';
7
+ import detectIndent from 'detect-indent';
8
+ import { getLatestVersion } from '../utils/get-latest-version.js';
9
+ import { Tags } from './types.js';
10
+ function jsObjectToBabelObjectExpression(obj) {
11
+ const objExp = t.objectExpression([]);
12
+ for (const [key, val] of Object.entries(obj)) {
13
+ if (Array.isArray(val)) {
14
+ 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))))));
15
+ }
16
+ else {
17
+ 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)));
18
+ }
19
+ }
20
+ return objExp;
21
+ }
22
+ // Parses config and writes it to a file
23
+ export async function writeConfig(answers, config) {
24
+ const YAML = await import('json-to-pretty-yaml').then(m => ('default' in m ? m.default : m));
25
+ const ext = answers.config.toLocaleLowerCase().split('.')[1];
26
+ const fullPath = resolve(process.cwd(), answers.config);
27
+ const relativePath = relative(process.cwd(), answers.config);
28
+ let content;
29
+ if (ext === 'ts') {
30
+ const buildRequire = template.statement(`%%config%%`);
31
+ const ast = buildRequire({
32
+ config: jsObjectToBabelObjectExpression(config),
33
+ });
34
+ content = `
35
+ import type { CodegenConfig } from '@graphql-codegen/cli';
36
+
37
+ const config: CodegenConfig = ${generate(ast).code.replace(/\(|\)/g, '')}
38
+
39
+ export default config;
40
+ `;
41
+ }
42
+ else {
43
+ content = ext === 'json' ? JSON.stringify(config) : YAML.stringify(config);
44
+ }
45
+ writeFileSync(fullPath, content, 'utf8');
46
+ return {
47
+ relativePath,
48
+ fullPath,
49
+ };
50
+ }
51
+ // Updates package.json (script and plugins as dependencies)
52
+ export async function writePackage(answers, configLocation) {
53
+ // script
54
+ const pkgPath = resolve(process.cwd(), 'package.json');
55
+ const pkgContent = readFileSync(pkgPath, 'utf8');
56
+ const pkg = JSON.parse(pkgContent);
57
+ const { indent } = detectIndent(pkgContent);
58
+ pkg.scripts ||= {};
59
+ pkg.scripts[answers.script] = `graphql-codegen --config ${configLocation}`;
60
+ // plugin
61
+ pkg.devDependencies ||= {};
62
+ await Promise.all((answers.plugins || []).map(async (plugin) => {
63
+ pkg.devDependencies[plugin.package] = await getLatestVersion(plugin.package);
64
+ }));
65
+ if (answers.introspection) {
66
+ pkg.devDependencies['@graphql-codegen/introspection'] = await getLatestVersion('@graphql-codegen/introspection');
67
+ }
68
+ pkg.devDependencies['@graphql-codegen/cli'] = await getLatestVersion('@graphql-codegen/cli');
69
+ if (answers.targets.includes(Tags.client)) {
70
+ pkg.devDependencies['@graphql-codegen/client-preset'] = await getLatestVersion('@graphql-codegen/client-preset');
71
+ }
72
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, indent));
73
+ }
74
+ export function bold(str) {
75
+ return chalk.bold(str);
76
+ }
77
+ export function grey(str) {
78
+ return chalk.grey(str);
79
+ }
80
+ export function italic(str) {
81
+ return chalk.italic(str);
82
+ }
@@ -0,0 +1,59 @@
1
+ import { bold, writeConfig, writePackage } from './helpers.js';
2
+ import { getAnswers } from './questions.js';
3
+ import { guessTargets } from './targets.js';
4
+ import { Tags } from './types.js';
5
+ function log(...msgs) {
6
+ // eslint-disable-next-line no-console
7
+ console.log(...msgs);
8
+ }
9
+ export async function init() {
10
+ log(`
11
+ Welcome to ${bold('GraphQL Code Generator')}!
12
+ Answer few questions and we will setup everything for you.
13
+ `);
14
+ const possibleTargets = await guessTargets();
15
+ const answers = await getAnswers(possibleTargets);
16
+ // define config
17
+ const config = {
18
+ overwrite: true,
19
+ schema: answers.schema,
20
+ ...(answers.targets.includes(Tags.client) ||
21
+ answers.targets.includes(Tags.angular) ||
22
+ answers.targets.includes(Tags.stencil)
23
+ ? { documents: answers.documents }
24
+ : {}),
25
+ generates: {
26
+ [answers.output]: {
27
+ ...(answers.targets.includes(Tags.client) ? { preset: 'client' } : {}),
28
+ plugins: answers.plugins ? answers.plugins.map(p => p.value) : [],
29
+ },
30
+ },
31
+ };
32
+ // introspection
33
+ if (answers.introspection) {
34
+ addIntrospection(config);
35
+ }
36
+ // config file
37
+ const { relativePath } = await writeConfig(answers, config);
38
+ log(`Fetching latest versions of selected plugins...`);
39
+ // write package.json
40
+ await writePackage(answers, relativePath);
41
+ // Emit status to the terminal
42
+ log(`
43
+ Config file generated at ${bold(relativePath)}
44
+
45
+ ${bold('$ npm install')}
46
+
47
+ To install the plugins.
48
+
49
+ ${bold(`$ npm run ${answers.script}`)}
50
+
51
+ To run GraphQL Code Generator.
52
+ `);
53
+ }
54
+ // adds an introspection to `generates`
55
+ function addIntrospection(config) {
56
+ config.generates['./graphql.schema.json'] = {
57
+ plugins: ['introspection'],
58
+ };
59
+ }
@@ -0,0 +1,133 @@
1
+ import { italic } from './helpers.js';
2
+ import { Tags } from './types.js';
3
+ export const plugins = [
4
+ {
5
+ name: `TypeScript ${italic('(required by other typescript plugins)')}`,
6
+ package: '@graphql-codegen/typescript',
7
+ value: 'typescript',
8
+ pathInRepo: 'typescript/typescript',
9
+ available: hasTag(Tags.typescript),
10
+ shouldBeSelected: tags => oneOf(tags, Tags.angular, Tags.stencil) || allOf(tags, Tags.typescript, Tags.react) || noneOf(tags, Tags.flow),
11
+ defaultExtension: '.ts',
12
+ },
13
+ {
14
+ name: `TypeScript Operations ${italic('(operations and fragments)')}`,
15
+ package: '@graphql-codegen/typescript-operations',
16
+ value: 'typescript-operations',
17
+ pathInRepo: 'typescript/operations',
18
+ available: tags => allOf(tags, Tags.client, Tags.typescript) || hasTag(Tags.stencil)(tags),
19
+ shouldBeSelected: tags => oneOf(tags, Tags.angular, Tags.stencil) || allOf(tags, Tags.typescript, Tags.react),
20
+ defaultExtension: '.ts',
21
+ },
22
+ {
23
+ name: `TypeScript Resolvers ${italic('(strongly typed resolve functions)')}`,
24
+ package: '@graphql-codegen/typescript-resolvers',
25
+ value: 'typescript-resolvers',
26
+ pathInRepo: 'typescript/resolvers',
27
+ available: tags => allOf(tags, Tags.node, Tags.typescript),
28
+ shouldBeSelected: tags => noneOf(tags, Tags.flow),
29
+ defaultExtension: '.ts',
30
+ },
31
+ {
32
+ name: `Flow ${italic('(required by other flow plugins)')}`,
33
+ package: '@graphql-codegen/flow',
34
+ value: 'flow',
35
+ pathInRepo: 'flow/flow',
36
+ available: hasTag(Tags.flow),
37
+ shouldBeSelected: tags => noneOf(tags, Tags.typescript),
38
+ defaultExtension: '.js',
39
+ },
40
+ {
41
+ name: `Flow Operations ${italic('(operations and fragments)')}`,
42
+ package: '@graphql-codegen/flow-operations',
43
+ value: 'flow-operations',
44
+ pathInRepo: 'flow/operations',
45
+ available: tags => allOf(tags, Tags.client, Tags.flow),
46
+ shouldBeSelected: tags => noneOf(tags, Tags.typescript),
47
+ defaultExtension: '.js',
48
+ },
49
+ {
50
+ name: `Flow Resolvers ${italic('(strongly typed resolve functions)')}`,
51
+ package: '@graphql-codegen/flow-resolvers',
52
+ value: 'flow-resolvers',
53
+ pathInRepo: 'flow/resolvers',
54
+ available: tags => allOf(tags, Tags.node, Tags.flow),
55
+ shouldBeSelected: tags => noneOf(tags, Tags.typescript),
56
+ defaultExtension: '.js',
57
+ },
58
+ {
59
+ name: `TypeScript Stencil Apollo ${italic('(typed components)')}`,
60
+ package: '@graphql-codegen/typescript-stencil-apollo',
61
+ value: 'typescript-stencil-apollo',
62
+ pathInRepo: 'typescript/stencil-apollo',
63
+ available: hasTag(Tags.stencil),
64
+ shouldBeSelected: () => true,
65
+ defaultExtension: '.tsx',
66
+ },
67
+ {
68
+ name: `TypeScript MongoDB ${italic('(typed MongoDB objects)')}`,
69
+ package: '@graphql-codegen/typescript-mongodb',
70
+ value: 'typescript-mongodb',
71
+ pathInRepo: 'typescript/mongodb',
72
+ available: tags => allOf(tags, Tags.node, Tags.typescript),
73
+ shouldBeSelected: () => false,
74
+ defaultExtension: '.ts',
75
+ },
76
+ {
77
+ name: `TypeScript GraphQL files modules ${italic('(declarations for .graphql files)')}`,
78
+ package: '@graphql-codegen/typescript-graphql-files-modules',
79
+ value: 'typescript-graphql-files-modules',
80
+ pathInRepo: 'typescript/graphql-files-modules',
81
+ available: tags => allOf(tags, Tags.client, Tags.typescript) || hasTag(Tags.stencil)(tags),
82
+ shouldBeSelected: () => false,
83
+ defaultExtension: '.ts',
84
+ },
85
+ {
86
+ name: `TypeScript GraphQL document nodes ${italic('(embedded GraphQL document)')}`,
87
+ package: '@graphql-codegen/typescript-document-nodes',
88
+ value: 'typescript-document-nodes',
89
+ pathInRepo: 'typescript/document-nodes',
90
+ available: tags => allOf(tags, Tags.typescript) || hasTag(Tags.stencil)(tags),
91
+ shouldBeSelected: () => false,
92
+ defaultExtension: '.ts',
93
+ },
94
+ {
95
+ name: `Introspection Fragment Matcher ${italic('(for Apollo Client)')}`,
96
+ package: '@graphql-codegen/fragment-matcher',
97
+ value: 'fragment-matcher',
98
+ pathInRepo: 'other/fragment-matcher',
99
+ available: tags => hasTag(Tags.client)(tags) || hasTag(Tags.angular)(tags) || hasTag(Tags.stencil)(tags),
100
+ shouldBeSelected: () => false,
101
+ defaultExtension: '.ts',
102
+ },
103
+ {
104
+ name: `Urql Introspection ${italic('(for Urql Client)')}`,
105
+ package: '@graphql-codegen/urql-introspection',
106
+ value: 'urql-introspection',
107
+ pathInRepo: 'other/urql-introspection',
108
+ available: tags => hasTag(Tags.client)(tags) || hasTag(Tags.stencil)(tags),
109
+ shouldBeSelected: () => false,
110
+ defaultExtension: '.ts',
111
+ },
112
+ {
113
+ name: `TypeScript Apollo Angular ${italic('(typed GQL services)')}`,
114
+ package: '@graphql-codegen/typescript-apollo-angular',
115
+ value: 'typescript-apollo-angular',
116
+ pathInRepo: 'typescript/apollo-angular',
117
+ available: hasTag(Tags.angular),
118
+ shouldBeSelected: () => true,
119
+ defaultExtension: '.ts',
120
+ },
121
+ ];
122
+ function hasTag(tag) {
123
+ return (tags) => tags.includes(tag);
124
+ }
125
+ function oneOf(list, ...items) {
126
+ return list.some(i => items.includes(i));
127
+ }
128
+ function noneOf(list, ...items) {
129
+ return !list.some(i => items.includes(i));
130
+ }
131
+ function allOf(list, ...items) {
132
+ return items.every(i => list.includes(i));
133
+ }
@@ -0,0 +1,172 @@
1
+ import { checkbox, input, select, confirm } from '@inquirer/prompts';
2
+ import { grey } from './helpers.js';
3
+ import { plugins } from './plugins.js';
4
+ import { Tags } from './types.js';
5
+ export async function getAnswers(possibleTargets) {
6
+ try {
7
+ const targetChoices = getApplicationTypeChoices(possibleTargets);
8
+ const targets = await select({
9
+ message: `What type of application are you building?`,
10
+ choices: targetChoices,
11
+ default: targetChoices.find(c => c.checked)?.value,
12
+ });
13
+ const schema = await input({
14
+ message: `Where is your schema?: ${grey('(path or url)')}`,
15
+ default: 'http://localhost:4000', // matches Apollo Server's default
16
+ validate: str => str.length > 0,
17
+ });
18
+ let documents;
19
+ if (targets.includes(Tags.client) || targets.includes(Tags.angular) || targets.includes(Tags.stencil))
20
+ documents = await input({
21
+ message: 'Where are your operations and fragments?:',
22
+ default: getDocumentsDefaultValue(targets),
23
+ validate: str => str.length > 0,
24
+ });
25
+ let plugins;
26
+ if (!targets.includes(Tags.client)) {
27
+ plugins = await checkbox({
28
+ message: 'Pick plugins:',
29
+ choices: getPluginChoices(targets),
30
+ validate: plugins => plugins.length > 0,
31
+ });
32
+ }
33
+ const output = await input({
34
+ message: 'Where to write the output:',
35
+ default: getOutputDefaultValue({ targets, plugins }),
36
+ validate: str => str.length > 0,
37
+ });
38
+ const introspection = await confirm({
39
+ message: 'Do you want to generate an introspection file?',
40
+ default: false,
41
+ });
42
+ const config = await input({
43
+ message: 'How to name the config file?',
44
+ default: (() => targets.includes(Tags.client) || targets.includes(Tags.typescript) || targets.includes(Tags.angular)
45
+ ? 'codegen.ts'
46
+ : 'codegen.yml')(),
47
+ validate: str => {
48
+ const isNotEmpty = str.length > 0;
49
+ const hasCorrectExtension = ['json', 'yml', 'yaml', 'js', 'ts'].some(ext => str.toLocaleLowerCase().endsWith(`.${ext}`));
50
+ return isNotEmpty && hasCorrectExtension;
51
+ },
52
+ });
53
+ const script = await input({
54
+ default: 'codegen',
55
+ message: 'What script in package.json should run the codegen?',
56
+ validate: (str) => str.length > 0,
57
+ });
58
+ return {
59
+ targets,
60
+ schema,
61
+ documents,
62
+ plugins,
63
+ output,
64
+ introspection,
65
+ config,
66
+ script,
67
+ };
68
+ }
69
+ catch (error) {
70
+ if (error instanceof Error && error.name === 'ExitPromptError') {
71
+ // This error because user exited using CMD+C, just exit gracefully or else user would see an ugly error message
72
+ // https://github.com/SBoudrias/Inquirer.js/blob/ee16061a1e3f99a6cc714a3d473f7cd12b06a3f1/packages/prompts/README.md#handling-ctrlc-gracefully
73
+ process.exit();
74
+ }
75
+ else {
76
+ throw error;
77
+ }
78
+ }
79
+ }
80
+ export function getApplicationTypeChoices(possibleTargets) {
81
+ function withFlowOrTypescript(tags) {
82
+ if (possibleTargets.TypeScript) {
83
+ tags.push(Tags.typescript);
84
+ }
85
+ else if (possibleTargets.Flow) {
86
+ tags.push(Tags.flow);
87
+ }
88
+ else if (possibleTargets.Node) {
89
+ tags.push(Tags.typescript, Tags.flow);
90
+ }
91
+ return tags;
92
+ }
93
+ return [
94
+ {
95
+ name: 'Backend - API or server',
96
+ key: 'backend',
97
+ value: withFlowOrTypescript([Tags.node]),
98
+ checked: possibleTargets.Node,
99
+ },
100
+ {
101
+ name: 'Application built with Angular',
102
+ key: 'angular',
103
+ value: [Tags.angular],
104
+ checked: possibleTargets.Angular,
105
+ },
106
+ {
107
+ name: 'Application built with React',
108
+ key: 'react',
109
+ value: withFlowOrTypescript([Tags.react, Tags.client]),
110
+ checked: possibleTargets.React,
111
+ },
112
+ {
113
+ name: 'Application built with Stencil',
114
+ key: 'stencil',
115
+ value: [Tags.stencil, Tags.typescript],
116
+ checked: possibleTargets.Stencil,
117
+ },
118
+ {
119
+ name: 'Application built with Vue',
120
+ key: 'vue',
121
+ value: [Tags.vue, Tags.client],
122
+ checked: possibleTargets.Vue,
123
+ },
124
+ {
125
+ name: 'Application using graphql-request',
126
+ key: 'graphqlRequest',
127
+ value: [Tags.graphqlRequest, Tags.client],
128
+ checked: possibleTargets.graphqlRequest,
129
+ },
130
+ {
131
+ name: 'Application built with other framework or vanilla JS',
132
+ key: 'client',
133
+ value: [Tags.typescript, Tags.flow],
134
+ checked: possibleTargets.Browser && !possibleTargets.Angular && !possibleTargets.React && !possibleTargets.Stencil,
135
+ },
136
+ ];
137
+ }
138
+ export function getPluginChoices(targets) {
139
+ return plugins
140
+ .filter(p => p.available(targets))
141
+ .map(p => {
142
+ return {
143
+ name: p.name,
144
+ value: p,
145
+ checked: p.shouldBeSelected(targets),
146
+ };
147
+ });
148
+ }
149
+ function getOutputDefaultValue({ targets, plugins }) {
150
+ if (targets.includes(Tags.client)) {
151
+ return 'src/gql/';
152
+ }
153
+ if (plugins.some(plugin => plugin.defaultExtension === '.tsx')) {
154
+ return 'src/generated/graphql.tsx';
155
+ }
156
+ if (plugins.some(plugin => plugin.defaultExtension === '.ts')) {
157
+ return 'src/generated/graphql.ts';
158
+ }
159
+ return 'src/generated/graphql.js';
160
+ }
161
+ function getDocumentsDefaultValue(targets) {
162
+ if (targets.includes(Tags.vue)) {
163
+ return 'src/**/*.vue';
164
+ }
165
+ if (targets.includes(Tags.angular)) {
166
+ return 'src/**/*.ts';
167
+ }
168
+ if (targets.includes(Tags.client)) {
169
+ return 'src/**/*.tsx';
170
+ }
171
+ return 'src/**/*.graphql';
172
+ }
@@ -0,0 +1,42 @@
1
+ import { readFileSync } from 'fs';
2
+ import { resolve } from 'path';
3
+ import { Tags } from './types.js';
4
+ export async function guessTargets() {
5
+ const pkg = JSON.parse(readFileSync(resolve(process.cwd(), 'package.json'), 'utf8'));
6
+ const dependencies = Object.keys({
7
+ ...pkg.dependencies,
8
+ ...pkg.devDependencies,
9
+ });
10
+ return {
11
+ [Tags.angular]: isAngular(dependencies),
12
+ [Tags.react]: isReact(dependencies),
13
+ [Tags.stencil]: isStencil(dependencies),
14
+ [Tags.vue]: isVue(dependencies),
15
+ [Tags.client]: false,
16
+ [Tags.node]: false,
17
+ [Tags.typescript]: isTypescript(dependencies),
18
+ [Tags.flow]: isFlow(dependencies),
19
+ [Tags.graphqlRequest]: isGraphqlRequest(dependencies),
20
+ };
21
+ }
22
+ function isAngular(dependencies) {
23
+ return dependencies.includes('@angular/core');
24
+ }
25
+ function isReact(dependencies) {
26
+ return dependencies.includes('react');
27
+ }
28
+ function isStencil(dependencies) {
29
+ return dependencies.includes('@stencil/core');
30
+ }
31
+ function isVue(dependencies) {
32
+ return dependencies.includes('vue') || dependencies.includes('nuxt');
33
+ }
34
+ function isTypescript(dependencies) {
35
+ return dependencies.includes('typescript');
36
+ }
37
+ function isFlow(dependencies) {
38
+ return dependencies.includes('flow');
39
+ }
40
+ function isGraphqlRequest(dependencies) {
41
+ return dependencies.includes('graphql-request');
42
+ }
@@ -0,0 +1,12 @@
1
+ export var Tags;
2
+ (function (Tags) {
3
+ Tags["client"] = "Browser";
4
+ Tags["node"] = "Node";
5
+ Tags["typescript"] = "TypeScript";
6
+ Tags["flow"] = "Flow";
7
+ Tags["angular"] = "Angular";
8
+ Tags["stencil"] = "Stencil";
9
+ Tags["react"] = "React";
10
+ Tags["vue"] = "Vue";
11
+ Tags["graphqlRequest"] = "graphqlRequest";
12
+ })(Tags || (Tags = {}));