@constructive-io/graphql-codegen 3.2.0 → 3.3.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 (216) hide show
  1. package/README.md +25 -30
  2. package/cli/index.js +36 -41
  3. package/cli/shared.d.ts +15 -17
  4. package/cli/shared.js +113 -21
  5. package/client/error.js +31 -9
  6. package/client/execute.js +2 -2
  7. package/client/index.d.ts +3 -3
  8. package/client/index.js +6 -6
  9. package/core/ast.d.ts +1 -1
  10. package/core/ast.js +1 -1
  11. package/core/codegen/babel-ast.d.ts +1 -1
  12. package/core/codegen/babel-ast.js +2 -2
  13. package/core/codegen/barrel.d.ts +0 -6
  14. package/core/codegen/barrel.js +22 -19
  15. package/core/codegen/client.d.ts +2 -12
  16. package/core/codegen/client.js +7 -21
  17. package/core/codegen/custom-mutations.d.ts +0 -14
  18. package/core/codegen/custom-mutations.js +139 -88
  19. package/core/codegen/custom-queries.d.ts +0 -14
  20. package/core/codegen/custom-queries.js +483 -193
  21. package/core/codegen/hooks-ast.d.ts +75 -0
  22. package/core/codegen/hooks-ast.js +522 -0
  23. package/core/codegen/index.d.ts +16 -18
  24. package/core/codegen/index.js +42 -88
  25. package/core/codegen/invalidation.d.ts +1 -7
  26. package/core/codegen/invalidation.js +50 -16
  27. package/core/codegen/mutation-keys.d.ts +1 -10
  28. package/core/codegen/mutation-keys.js +22 -8
  29. package/core/codegen/mutations.d.ts +0 -13
  30. package/core/codegen/mutations.js +301 -366
  31. package/core/codegen/orm/barrel.d.ts +0 -5
  32. package/core/codegen/orm/barrel.js +5 -0
  33. package/core/codegen/orm/client-generator.d.ts +0 -5
  34. package/core/codegen/orm/client-generator.js +7 -2
  35. package/core/codegen/orm/client.js +3 -1
  36. package/core/codegen/orm/custom-ops-generator.d.ts +0 -6
  37. package/core/codegen/orm/custom-ops-generator.js +104 -51
  38. package/core/codegen/orm/index.d.ts +4 -4
  39. package/core/codegen/orm/index.js +28 -15
  40. package/core/codegen/orm/input-types-generator.d.ts +1 -13
  41. package/core/codegen/orm/input-types-generator.js +85 -23
  42. package/core/codegen/orm/model-generator.d.ts +0 -5
  43. package/core/codegen/orm/model-generator.js +309 -131
  44. package/core/codegen/orm/select-types.d.ts +19 -14
  45. package/core/codegen/queries.d.ts +0 -8
  46. package/core/codegen/queries.js +360 -559
  47. package/core/codegen/query-keys.d.ts +1 -1
  48. package/core/codegen/query-keys.js +37 -23
  49. package/core/codegen/scalars.js +3 -1
  50. package/core/codegen/schema-types-generator.d.ts +1 -1
  51. package/core/codegen/schema-types-generator.js +17 -2
  52. package/core/codegen/select-helpers.d.ts +19 -0
  53. package/core/codegen/select-helpers.js +40 -0
  54. package/core/codegen/selection.d.ts +4 -0
  55. package/core/codegen/selection.js +65 -0
  56. package/core/codegen/shared/index.d.ts +2 -15
  57. package/core/codegen/shared/index.js +17 -4
  58. package/core/codegen/templates/hooks-client.ts +49 -0
  59. package/core/codegen/templates/hooks-selection.ts +58 -0
  60. package/core/codegen/templates/orm-client.ts +8 -6
  61. package/core/codegen/templates/query-builder.ts +250 -46
  62. package/core/codegen/templates/select-types.ts +31 -14
  63. package/core/codegen/type-resolver.d.ts +1 -5
  64. package/core/codegen/type-resolver.js +0 -22
  65. package/core/codegen/types.d.ts +0 -3
  66. package/core/codegen/types.js +71 -14
  67. package/core/codegen/utils.d.ts +1 -4
  68. package/core/codegen/utils.js +4 -1
  69. package/core/config/index.d.ts +1 -1
  70. package/core/config/resolver.js +1 -3
  71. package/core/generate.js +38 -50
  72. package/core/index.d.ts +3 -3
  73. package/core/index.js +3 -4
  74. package/core/introspect/index.d.ts +6 -6
  75. package/core/introspect/index.js +5 -8
  76. package/core/introspect/infer-tables.d.ts +0 -14
  77. package/core/introspect/infer-tables.js +15 -1
  78. package/core/introspect/source/database.js +1 -1
  79. package/core/introspect/source/endpoint.d.ts +0 -6
  80. package/core/introspect/source/endpoint.js +7 -1
  81. package/core/introspect/source/index.d.ts +4 -4
  82. package/core/introspect/source/index.js +5 -9
  83. package/core/introspect/source/pgpm-module.js +3 -3
  84. package/core/introspect/transform-schema.d.ts +2 -2
  85. package/core/introspect/transform-schema.js +2 -2
  86. package/core/output/index.d.ts +1 -1
  87. package/core/output/index.js +2 -2
  88. package/core/output/writer.d.ts +3 -0
  89. package/core/output/writer.js +20 -1
  90. package/core/pipeline/index.d.ts +2 -2
  91. package/core/query-builder.d.ts +2 -2
  92. package/core/query-builder.js +1 -1
  93. package/core/watch/index.d.ts +4 -4
  94. package/core/watch/index.js +9 -9
  95. package/core/watch/orchestrator.js +5 -3
  96. package/esm/cli/index.js +37 -42
  97. package/esm/cli/shared.d.ts +15 -17
  98. package/esm/cli/shared.js +103 -20
  99. package/esm/client/error.js +31 -9
  100. package/esm/client/execute.js +2 -2
  101. package/esm/client/index.d.ts +3 -3
  102. package/esm/client/index.js +3 -3
  103. package/esm/core/ast.d.ts +1 -1
  104. package/esm/core/ast.js +1 -1
  105. package/esm/core/codegen/babel-ast.d.ts +1 -1
  106. package/esm/core/codegen/babel-ast.js +2 -2
  107. package/esm/core/codegen/barrel.d.ts +0 -6
  108. package/esm/core/codegen/barrel.js +23 -20
  109. package/esm/core/codegen/client.d.ts +2 -12
  110. package/esm/core/codegen/client.js +7 -21
  111. package/esm/core/codegen/custom-mutations.d.ts +0 -14
  112. package/esm/core/codegen/custom-mutations.js +141 -90
  113. package/esm/core/codegen/custom-queries.d.ts +0 -14
  114. package/esm/core/codegen/custom-queries.js +486 -196
  115. package/esm/core/codegen/hooks-ast.d.ts +75 -0
  116. package/esm/core/codegen/hooks-ast.js +424 -0
  117. package/esm/core/codegen/index.d.ts +16 -18
  118. package/esm/core/codegen/index.js +26 -71
  119. package/esm/core/codegen/invalidation.d.ts +1 -7
  120. package/esm/core/codegen/invalidation.js +51 -17
  121. package/esm/core/codegen/mutation-keys.d.ts +1 -10
  122. package/esm/core/codegen/mutation-keys.js +23 -9
  123. package/esm/core/codegen/mutations.d.ts +0 -13
  124. package/esm/core/codegen/mutations.js +302 -367
  125. package/esm/core/codegen/orm/barrel.d.ts +0 -5
  126. package/esm/core/codegen/orm/barrel.js +6 -1
  127. package/esm/core/codegen/orm/client-generator.d.ts +0 -5
  128. package/esm/core/codegen/orm/client-generator.js +7 -2
  129. package/esm/core/codegen/orm/client.js +3 -1
  130. package/esm/core/codegen/orm/custom-ops-generator.d.ts +0 -6
  131. package/esm/core/codegen/orm/custom-ops-generator.js +103 -50
  132. package/esm/core/codegen/orm/index.d.ts +4 -4
  133. package/esm/core/codegen/orm/index.js +25 -12
  134. package/esm/core/codegen/orm/input-types-generator.d.ts +1 -13
  135. package/esm/core/codegen/orm/input-types-generator.js +85 -23
  136. package/esm/core/codegen/orm/model-generator.d.ts +0 -5
  137. package/esm/core/codegen/orm/model-generator.js +310 -132
  138. package/esm/core/codegen/orm/select-types.d.ts +19 -14
  139. package/esm/core/codegen/queries.d.ts +0 -8
  140. package/esm/core/codegen/queries.js +362 -561
  141. package/esm/core/codegen/query-keys.d.ts +1 -1
  142. package/esm/core/codegen/query-keys.js +38 -24
  143. package/esm/core/codegen/scalars.js +3 -1
  144. package/esm/core/codegen/schema-types-generator.d.ts +1 -1
  145. package/esm/core/codegen/schema-types-generator.js +17 -2
  146. package/esm/core/codegen/select-helpers.d.ts +19 -0
  147. package/esm/core/codegen/select-helpers.js +35 -0
  148. package/esm/core/codegen/selection.d.ts +4 -0
  149. package/esm/core/codegen/selection.js +29 -0
  150. package/esm/core/codegen/shared/index.d.ts +2 -15
  151. package/esm/core/codegen/shared/index.js +16 -3
  152. package/esm/core/codegen/type-resolver.d.ts +1 -5
  153. package/esm/core/codegen/type-resolver.js +1 -22
  154. package/esm/core/codegen/types.d.ts +0 -3
  155. package/esm/core/codegen/types.js +72 -15
  156. package/esm/core/codegen/utils.d.ts +1 -4
  157. package/esm/core/codegen/utils.js +4 -1
  158. package/esm/core/config/index.d.ts +1 -1
  159. package/esm/core/config/resolver.js +2 -4
  160. package/esm/core/generate.js +38 -50
  161. package/esm/core/index.d.ts +3 -3
  162. package/esm/core/index.js +2 -3
  163. package/esm/core/introspect/index.d.ts +6 -6
  164. package/esm/core/introspect/index.js +3 -6
  165. package/esm/core/introspect/infer-tables.d.ts +0 -14
  166. package/esm/core/introspect/infer-tables.js +16 -2
  167. package/esm/core/introspect/source/database.js +2 -2
  168. package/esm/core/introspect/source/endpoint.d.ts +0 -6
  169. package/esm/core/introspect/source/endpoint.js +7 -1
  170. package/esm/core/introspect/source/index.d.ts +4 -4
  171. package/esm/core/introspect/source/index.js +6 -10
  172. package/esm/core/introspect/source/pgpm-module.js +3 -3
  173. package/esm/core/introspect/transform-schema.d.ts +2 -2
  174. package/esm/core/introspect/transform-schema.js +2 -2
  175. package/esm/core/output/index.d.ts +1 -1
  176. package/esm/core/output/index.js +1 -1
  177. package/esm/core/output/writer.d.ts +3 -0
  178. package/esm/core/output/writer.js +20 -1
  179. package/esm/core/pipeline/index.d.ts +2 -2
  180. package/esm/core/pipeline/index.js +2 -2
  181. package/esm/core/query-builder.d.ts +2 -2
  182. package/esm/core/query-builder.js +2 -2
  183. package/esm/core/watch/index.d.ts +4 -4
  184. package/esm/core/watch/index.js +3 -3
  185. package/esm/core/watch/orchestrator.js +5 -3
  186. package/esm/generators/index.d.ts +3 -3
  187. package/esm/generators/index.js +3 -3
  188. package/esm/generators/mutations.d.ts +1 -1
  189. package/esm/generators/select.d.ts +1 -1
  190. package/esm/index.d.ts +3 -3
  191. package/esm/index.js +1 -4
  192. package/esm/types/config.d.ts +0 -10
  193. package/esm/types/config.js +0 -2
  194. package/esm/types/index.d.ts +6 -6
  195. package/esm/types/index.js +1 -1
  196. package/generators/index.d.ts +3 -3
  197. package/generators/index.js +8 -8
  198. package/generators/mutations.d.ts +1 -1
  199. package/generators/select.d.ts +1 -1
  200. package/index.d.ts +3 -3
  201. package/index.js +11 -5
  202. package/package.json +11 -11
  203. package/types/config.d.ts +0 -10
  204. package/types/config.js +0 -2
  205. package/types/index.d.ts +6 -6
  206. package/types/index.js +2 -2
  207. package/core/codegen/gql-ast.d.ts +0 -41
  208. package/core/codegen/gql-ast.js +0 -353
  209. package/core/codegen/schema-gql-ast.d.ts +0 -51
  210. package/core/codegen/schema-gql-ast.js +0 -385
  211. package/core/codegen/templates/client.browser.ts +0 -271
  212. package/core/codegen/templates/client.node.ts +0 -337
  213. package/esm/core/codegen/gql-ast.d.ts +0 -41
  214. package/esm/core/codegen/gql-ast.js +0 -312
  215. package/esm/core/codegen/schema-gql-ast.d.ts +0 -51
  216. package/esm/core/codegen/schema-gql-ast.js +0 -343
@@ -83,9 +83,10 @@ async function formatFileContent(fileName, content, formatFn) {
83
83
  * @param options - Write options
84
84
  */
85
85
  async function writeGeneratedFiles(files, outputDir, subdirs, options = {}) {
86
- const { showProgress = true, formatFiles = true } = options;
86
+ const { showProgress = true, formatFiles = true, pruneStaleFiles = false, } = options;
87
87
  const errors = [];
88
88
  const written = [];
89
+ const removed = [];
89
90
  const total = files.length;
90
91
  const isTTY = process.stdout.isTTY;
91
92
  // Ensure output directory exists
@@ -113,6 +114,23 @@ async function writeGeneratedFiles(files, outputDir, subdirs, options = {}) {
113
114
  if (errors.length > 0) {
114
115
  return { success: false, errors };
115
116
  }
117
+ if (pruneStaleFiles) {
118
+ const expectedFiles = new Set(files.map((file) => path.resolve(outputDir, file.path)));
119
+ const existingTsFiles = findTsFiles(outputDir);
120
+ for (const existingFile of existingTsFiles) {
121
+ const absolutePath = path.resolve(existingFile);
122
+ if (expectedFiles.has(absolutePath))
123
+ continue;
124
+ try {
125
+ fs.rmSync(absolutePath, { force: true });
126
+ removed.push(absolutePath);
127
+ }
128
+ catch (err) {
129
+ const message = err instanceof Error ? err.message : 'Unknown error';
130
+ errors.push(`Failed to remove stale file ${absolutePath}: ${message}`);
131
+ }
132
+ }
133
+ }
116
134
  // Get oxfmt format function if formatting is enabled
117
135
  const formatFn = formatFiles ? await getOxfmtFormat() : null;
118
136
  if (formatFiles && !formatFn && showProgress) {
@@ -161,6 +179,7 @@ async function writeGeneratedFiles(files, outputDir, subdirs, options = {}) {
161
179
  return {
162
180
  success: errors.length === 0,
163
181
  filesWritten: written,
182
+ filesRemoved: removed,
164
183
  errors: errors.length > 0 ? errors : undefined,
165
184
  };
166
185
  }
@@ -9,10 +9,10 @@
9
9
  * - Filtering
10
10
  */
11
11
  import type { GraphQLSDKConfigTarget } from '../../types/config';
12
- import type { CleanTable, CleanOperation, TypeRegistry } from '../../types/schema';
12
+ import type { CleanOperation, CleanTable, TypeRegistry } from '../../types/schema';
13
13
  import type { SchemaSource } from '../introspect/source';
14
14
  export type { SchemaSource } from '../introspect/source';
15
- export { createSchemaSource, validateSourceOptions } from '../introspect/source';
15
+ export { createSchemaSource, validateSourceOptions, } from '../introspect/source';
16
16
  export interface CodegenPipelineOptions {
17
17
  /**
18
18
  * Schema source (endpoint or file)
@@ -1,4 +1,4 @@
1
- import type { QueryFieldSelection, IntrospectionSchema, MetaObject, QueryBuilderOptions, QueryBuilderResult, QueryDefinition, QuerySelectionOptions } from './types';
1
+ import type { IntrospectionSchema, MetaObject, QueryBuilderOptions, QueryBuilderResult, QueryDefinition, QueryFieldSelection, QuerySelectionOptions } from './types';
2
2
  export * as MetaObject from './meta-object';
3
3
  export declare class QueryBuilder {
4
4
  _introspection: IntrospectionSchema;
@@ -12,7 +12,7 @@ export declare class QueryBuilder {
12
12
  private _op;
13
13
  private _mutation;
14
14
  private _select;
15
- constructor({ meta, introspection, }: QueryBuilderOptions);
15
+ constructor({ meta, introspection }: QueryBuilderOptions);
16
16
  initModelMap(): void;
17
17
  clear(): void;
18
18
  query(model: string): QueryBuilder;
@@ -52,7 +52,7 @@ class QueryBuilder {
52
52
  _op;
53
53
  _mutation;
54
54
  _select;
55
- constructor({ meta = {}, introspection, }) {
55
+ constructor({ meta = {}, introspection }) {
56
56
  this._introspection = introspection;
57
57
  this._meta = meta;
58
58
  this.clear();
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Watch mode module exports
3
3
  */
4
- export { SchemaPoller, computeSchemaHash } from './poller';
5
4
  export { SchemaCache, touchFile } from './cache';
6
- export { sha256, hashObject, combineHashes } from './hash';
7
5
  export { debounce, debounceAsync } from './debounce';
8
- export { WatchOrchestrator, startWatch } from './orchestrator';
9
- export type { PollResult, WatchOptions, PollEventType, PollEventHandler, PollEvent, GeneratorType, } from './types';
6
+ export { combineHashes, hashObject, sha256 } from './hash';
10
7
  export type { WatchOrchestratorOptions, WatchStatus } from './orchestrator';
8
+ export { startWatch, WatchOrchestrator } from './orchestrator';
9
+ export { computeSchemaHash, SchemaPoller } from './poller';
10
+ export type { GeneratorType, PollEvent, PollEventHandler, PollEventType, PollResult, WatchOptions, } from './types';
@@ -3,20 +3,20 @@
3
3
  * Watch mode module exports
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.startWatch = exports.WatchOrchestrator = exports.debounceAsync = exports.debounce = exports.combineHashes = exports.hashObject = exports.sha256 = exports.touchFile = exports.SchemaCache = exports.computeSchemaHash = exports.SchemaPoller = void 0;
7
- var poller_1 = require("./poller");
8
- Object.defineProperty(exports, "SchemaPoller", { enumerable: true, get: function () { return poller_1.SchemaPoller; } });
9
- Object.defineProperty(exports, "computeSchemaHash", { enumerable: true, get: function () { return poller_1.computeSchemaHash; } });
6
+ exports.SchemaPoller = exports.computeSchemaHash = exports.WatchOrchestrator = exports.startWatch = exports.sha256 = exports.hashObject = exports.combineHashes = exports.debounceAsync = exports.debounce = exports.touchFile = exports.SchemaCache = void 0;
10
7
  var cache_1 = require("./cache");
11
8
  Object.defineProperty(exports, "SchemaCache", { enumerable: true, get: function () { return cache_1.SchemaCache; } });
12
9
  Object.defineProperty(exports, "touchFile", { enumerable: true, get: function () { return cache_1.touchFile; } });
13
- var hash_1 = require("./hash");
14
- Object.defineProperty(exports, "sha256", { enumerable: true, get: function () { return hash_1.sha256; } });
15
- Object.defineProperty(exports, "hashObject", { enumerable: true, get: function () { return hash_1.hashObject; } });
16
- Object.defineProperty(exports, "combineHashes", { enumerable: true, get: function () { return hash_1.combineHashes; } });
17
10
  var debounce_1 = require("./debounce");
18
11
  Object.defineProperty(exports, "debounce", { enumerable: true, get: function () { return debounce_1.debounce; } });
19
12
  Object.defineProperty(exports, "debounceAsync", { enumerable: true, get: function () { return debounce_1.debounceAsync; } });
13
+ var hash_1 = require("./hash");
14
+ Object.defineProperty(exports, "combineHashes", { enumerable: true, get: function () { return hash_1.combineHashes; } });
15
+ Object.defineProperty(exports, "hashObject", { enumerable: true, get: function () { return hash_1.hashObject; } });
16
+ Object.defineProperty(exports, "sha256", { enumerable: true, get: function () { return hash_1.sha256; } });
20
17
  var orchestrator_1 = require("./orchestrator");
21
- Object.defineProperty(exports, "WatchOrchestrator", { enumerable: true, get: function () { return orchestrator_1.WatchOrchestrator; } });
22
18
  Object.defineProperty(exports, "startWatch", { enumerable: true, get: function () { return orchestrator_1.startWatch; } });
19
+ Object.defineProperty(exports, "WatchOrchestrator", { enumerable: true, get: function () { return orchestrator_1.WatchOrchestrator; } });
20
+ var poller_1 = require("./poller");
21
+ Object.defineProperty(exports, "computeSchemaHash", { enumerable: true, get: function () { return poller_1.computeSchemaHash; } });
22
+ Object.defineProperty(exports, "SchemaPoller", { enumerable: true, get: function () { return poller_1.SchemaPoller; } });
@@ -7,8 +7,8 @@
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.WatchOrchestrator = void 0;
9
9
  exports.startWatch = startWatch;
10
- const poller_1 = require("./poller");
11
10
  const debounce_1 = require("./debounce");
11
+ const poller_1 = require("./poller");
12
12
  /**
13
13
  * Main watch orchestrator class
14
14
  */
@@ -139,12 +139,14 @@ class WatchOrchestrator {
139
139
  case 'react-query':
140
140
  generateFn = this.options.generateReactQuery;
141
141
  // React Query hooks go to {output}/hooks
142
- outputDir = this.options.outputDir ?? `${this.options.config.output}/hooks`;
142
+ outputDir =
143
+ this.options.outputDir ?? `${this.options.config.output}/hooks`;
143
144
  break;
144
145
  case 'orm':
145
146
  generateFn = this.options.generateOrm;
146
147
  // ORM client goes to {output}/orm
147
- outputDir = this.options.outputDir ?? `${this.options.config.output}/orm`;
148
+ outputDir =
149
+ this.options.outputDir ?? `${this.options.config.output}/orm`;
148
150
  break;
149
151
  default:
150
152
  throw new Error(`Unknown generator type: ${this.options.generatorType}`);
package/esm/cli/index.js CHANGED
@@ -6,9 +6,9 @@
6
6
  * All business logic is in the core modules.
7
7
  */
8
8
  import { CLI, getPackageJson } from 'inquirerer';
9
- import { generate } from '../core/generate';
10
9
  import { findConfigFile, loadConfigFile } from '../core/config';
11
- import { codegenQuestions, printResult } from './shared';
10
+ import { generate } from '../core/generate';
11
+ import { buildDbConfig, buildGenerateOptions, camelizeArgv, codegenQuestions, hasResolvedCodegenSource, normalizeCodegenListOptions, printResult, seedArgvFromConfig, } from './shared';
12
12
  const usage = `
13
13
  graphql-codegen - GraphQL SDK generator for Constructive databases
14
14
 
@@ -30,8 +30,6 @@ Generator Options:
30
30
  -o, --output <dir> Output directory
31
31
  -t, --target <name> Target name (for multi-target configs)
32
32
  -a, --authorization <token> Authorization header value
33
- --browser-compatible Generate browser-compatible code (default: true)
34
- Set to false for Node.js with localhost DNS fix
35
33
  --dry-run Preview without writing files
36
34
  -v, --verbose Show detailed output
37
35
 
@@ -48,9 +46,16 @@ export const commands = async (argv, prompter, _options) => {
48
46
  console.log(usage);
49
47
  process.exit(0);
50
48
  }
51
- const configPath = (argv.config || argv.c || findConfigFile());
49
+ const hasSourceFlags = Boolean(argv.endpoint ||
50
+ argv.e ||
51
+ argv['schema-file'] ||
52
+ argv.s ||
53
+ argv.schemas ||
54
+ argv['api-names']);
55
+ const explicitConfigPath = (argv.config || argv.c);
56
+ const configPath = explicitConfigPath || (!hasSourceFlags ? findConfigFile() : undefined);
52
57
  const targetName = (argv.target || argv.t);
53
- // If config file exists, load and run
58
+ let fileConfig = {};
54
59
  if (configPath) {
55
60
  const loaded = await loadConfigFile(configPath);
56
61
  if (!loaded.success) {
@@ -58,20 +63,24 @@ export const commands = async (argv, prompter, _options) => {
58
63
  process.exit(1);
59
64
  }
60
65
  const config = loaded.config;
61
- // Check if it's a multi-target config (no source fields at top level)
62
- const isMulti = !('endpoint' in config || 'schemaFile' in config || 'db' in config);
66
+ const isMulti = !('endpoint' in config ||
67
+ 'schemaFile' in config ||
68
+ 'db' in config);
63
69
  if (isMulti) {
64
- // Multi-target: simple for loop over targets
65
70
  const targets = config;
66
71
  const names = targetName ? [targetName] : Object.keys(targets);
67
72
  if (targetName && !targets[targetName]) {
68
73
  console.error('x', `Target "${targetName}" not found. Available: ${Object.keys(targets).join(', ')}`);
69
74
  process.exit(1);
70
75
  }
76
+ const cliOptions = buildDbConfig(normalizeCodegenListOptions(camelizeArgv(argv)));
71
77
  let hasError = false;
72
78
  for (const name of names) {
73
79
  console.log(`\n[${name}]`);
74
- const result = await generate(targets[name]);
80
+ const result = await generate({
81
+ ...targets[name],
82
+ ...cliOptions,
83
+ });
75
84
  printResult(result);
76
85
  if (!result.success)
77
86
  hasError = true;
@@ -81,33 +90,14 @@ export const commands = async (argv, prompter, _options) => {
81
90
  process.exit(1);
82
91
  return argv;
83
92
  }
84
- // Single config
85
- const result = await generate(config);
86
- printResult(result);
87
- if (!result.success)
88
- process.exit(1);
89
- prompter.close();
90
- return argv;
93
+ fileConfig = config;
91
94
  }
92
- // No config file - prompt for options using shared questions
93
- const answers = await prompter.prompt(argv, codegenQuestions);
94
- // Build db config if schemas or apiNames provided
95
- const db = (answers.schemas || answers.apiNames) ? {
96
- schemas: answers.schemas,
97
- apiNames: answers.apiNames,
98
- } : undefined;
99
- const result = await generate({
100
- endpoint: answers.endpoint,
101
- schemaFile: answers.schemaFile,
102
- db,
103
- output: answers.output,
104
- authorization: answers.authorization,
105
- reactQuery: answers.reactQuery,
106
- orm: answers.orm,
107
- browserCompatible: answers.browserCompatible,
108
- dryRun: answers.dryRun,
109
- verbose: answers.verbose,
110
- });
95
+ const seeded = seedArgvFromConfig(argv, fileConfig);
96
+ const answers = hasResolvedCodegenSource(seeded)
97
+ ? seeded
98
+ : await prompter.prompt(seeded, codegenQuestions);
99
+ const options = buildGenerateOptions(answers, fileConfig);
100
+ const result = await generate(options);
111
101
  printResult(result);
112
102
  prompter.close();
113
103
  return argv;
@@ -124,13 +114,18 @@ export const options = {
124
114
  a: 'authorization',
125
115
  v: 'verbose',
126
116
  },
127
- boolean: [
128
- 'help', 'version', 'verbose', 'dry-run', 'react-query', 'orm', 'keep-db', 'browser-compatible',
129
- ],
130
117
  string: [
131
- 'config', 'endpoint', 'schema-file', 'output', 'target', 'authorization',
132
- 'pgpm-module-path', 'pgpm-workspace-path', 'pgpm-module-name',
133
- 'schemas', 'api-names',
118
+ 'config',
119
+ 'endpoint',
120
+ 'schema-file',
121
+ 'output',
122
+ 'target',
123
+ 'authorization',
124
+ 'pgpm-module-path',
125
+ 'pgpm-workspace-path',
126
+ 'pgpm-module-name',
127
+ 'schemas',
128
+ 'api-names',
134
129
  ],
135
130
  },
136
131
  };
@@ -1,18 +1,7 @@
1
- /**
2
- * Shared CLI utilities for graphql-codegen
3
- *
4
- * These are exported so that packages/cli can use the same questions
5
- * and types, ensuring consistency between the two CLIs.
6
- */
7
1
  import type { Question } from 'inquirerer';
8
2
  import type { GenerateResult } from '../core/generate';
9
- /**
10
- * Sanitize function that splits comma-separated strings into arrays
11
- */
3
+ import type { GraphQLSDKConfigTarget } from '../types/config';
12
4
  export declare const splitCommas: (input: string | undefined) => string[] | undefined;
13
- /**
14
- * Interface for codegen CLI answers
15
- */
16
5
  export interface CodegenAnswers {
17
6
  endpoint?: string;
18
7
  schemaFile?: string;
@@ -21,16 +10,25 @@ export interface CodegenAnswers {
21
10
  apiNames?: string[];
22
11
  reactQuery?: boolean;
23
12
  orm?: boolean;
24
- browserCompatible?: boolean;
25
13
  authorization?: string;
26
14
  dryRun?: boolean;
27
15
  verbose?: boolean;
28
16
  }
17
+ export declare const codegenQuestions: Question[];
18
+ export declare function printResult(result: GenerateResult): void;
19
+ export declare const camelizeArgv: (argv: Record<string, any>) => Record<string, any>;
20
+ export declare const hyphenateKeys: (obj: Record<string, any>) => Record<string, any>;
21
+ export declare function filterDefined(obj: Record<string, unknown>): Record<string, unknown>;
22
+ export declare function flattenDbFields(config: Record<string, unknown>): Record<string, unknown>;
23
+ export declare function buildDbConfig(options: Record<string, unknown>): Record<string, unknown>;
29
24
  /**
30
- * Questions for the codegen CLI
25
+ * Normalizes top-level list-like CLI options to string arrays.
26
+ * This keeps non-interactive paths equivalent to prompt sanitize behavior.
31
27
  */
32
- export declare const codegenQuestions: Question[];
28
+ export declare function normalizeCodegenListOptions(options: Record<string, unknown>): Record<string, unknown>;
33
29
  /**
34
- * Print the result of a generate operation
30
+ * Returns true when source options are already available, so prompting can be skipped.
35
31
  */
36
- export declare function printResult(result: GenerateResult): void;
32
+ export declare function hasResolvedCodegenSource(options: Record<string, unknown>): boolean;
33
+ export declare function seedArgvFromConfig(argv: Record<string, unknown>, fileConfig: GraphQLSDKConfigTarget): Record<string, unknown>;
34
+ export declare function buildGenerateOptions(answers: Record<string, unknown>, fileConfig?: GraphQLSDKConfigTarget): GraphQLSDKConfigTarget;
package/esm/cli/shared.js CHANGED
@@ -1,14 +1,31 @@
1
1
  /**
2
- * Sanitize function that splits comma-separated strings into arrays
2
+ * Shared CLI utilities for graphql-codegen
3
+ *
4
+ * These are exported so that packages/cli can use the same questions,
5
+ * types, and transform utilities, ensuring consistency between the two CLIs.
3
6
  */
7
+ import { camelize } from 'inflekt';
8
+ import { inflektTree } from 'inflekt/transform-keys';
4
9
  export const splitCommas = (input) => {
5
10
  if (!input)
6
11
  return undefined;
7
- return input.split(',').map((s) => s.trim()).filter(Boolean);
12
+ return input
13
+ .split(',')
14
+ .map((s) => s.trim())
15
+ .filter(Boolean);
8
16
  };
9
- /**
10
- * Questions for the codegen CLI
11
- */
17
+ function normalizeListOption(input) {
18
+ if (Array.isArray(input)) {
19
+ return input
20
+ .flatMap((item) => typeof item === 'string' ? (splitCommas(item) ?? []) : [String(item)])
21
+ .map((s) => s.trim())
22
+ .filter(Boolean);
23
+ }
24
+ if (typeof input === 'string') {
25
+ return splitCommas(input);
26
+ }
27
+ return undefined;
28
+ }
12
29
  export const codegenQuestions = [
13
30
  {
14
31
  name: 'endpoint',
@@ -17,7 +34,7 @@ export const codegenQuestions = [
17
34
  required: false,
18
35
  },
19
36
  {
20
- name: 'schemaFile',
37
+ name: 'schema-file',
21
38
  message: 'Path to GraphQL schema file',
22
39
  type: 'text',
23
40
  required: false,
@@ -38,14 +55,14 @@ export const codegenQuestions = [
38
55
  sanitize: splitCommas,
39
56
  },
40
57
  {
41
- name: 'apiNames',
58
+ name: 'api-names',
42
59
  message: 'API names (comma-separated)',
43
60
  type: 'text',
44
61
  required: false,
45
62
  sanitize: splitCommas,
46
63
  },
47
64
  {
48
- name: 'reactQuery',
65
+ name: 'react-query',
49
66
  message: 'Generate React Query hooks?',
50
67
  type: 'confirm',
51
68
  required: false,
@@ -60,14 +77,6 @@ export const codegenQuestions = [
60
77
  default: false,
61
78
  useDefault: true,
62
79
  },
63
- {
64
- name: 'browserCompatible',
65
- message: 'Generate browser-compatible code?',
66
- type: 'confirm',
67
- required: false,
68
- default: true,
69
- useDefault: true,
70
- },
71
80
  {
72
81
  name: 'authorization',
73
82
  message: 'Authorization header value',
@@ -75,7 +84,7 @@ export const codegenQuestions = [
75
84
  required: false,
76
85
  },
77
86
  {
78
- name: 'dryRun',
87
+ name: 'dry-run',
79
88
  message: 'Preview without writing files?',
80
89
  type: 'confirm',
81
90
  required: false,
@@ -91,9 +100,6 @@ export const codegenQuestions = [
91
100
  useDefault: true,
92
101
  },
93
102
  ];
94
- /**
95
- * Print the result of a generate operation
96
- */
97
103
  export function printResult(result) {
98
104
  if (result.success) {
99
105
  console.log('[ok]', result.message);
@@ -107,3 +113,80 @@ export function printResult(result) {
107
113
  process.exit(1);
108
114
  }
109
115
  }
116
+ // ============================================================================
117
+ // Key transform utilities
118
+ // ============================================================================
119
+ const isTopLevel = (_key, path) => path.length === 0;
120
+ const skipNonTopLevel = (key, path) => !isTopLevel(key, path) || key === '_' || key.startsWith('_');
121
+ export const camelizeArgv = (argv) => inflektTree(argv, (key) => {
122
+ const underscored = key.replace(/-/g, '_');
123
+ return camelize(underscored, true);
124
+ }, { skip: skipNonTopLevel });
125
+ export const hyphenateKeys = (obj) => inflektTree(obj, (key) => key.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase()), {
126
+ skip: skipNonTopLevel,
127
+ });
128
+ // ============================================================================
129
+ // Config <-> CLI shape transforms
130
+ // ============================================================================
131
+ export function filterDefined(obj) {
132
+ return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined && v !== null));
133
+ }
134
+ export function flattenDbFields(config) {
135
+ const { db, ...rest } = config;
136
+ if (db && typeof db === 'object') {
137
+ const dbObj = db;
138
+ const schemas = Array.isArray(dbObj.schemas)
139
+ ? dbObj.schemas.join(',')
140
+ : dbObj.schemas;
141
+ const apiNames = Array.isArray(dbObj.apiNames)
142
+ ? dbObj.apiNames.join(',')
143
+ : dbObj.apiNames;
144
+ return { ...rest, schemas, apiNames };
145
+ }
146
+ return rest;
147
+ }
148
+ export function buildDbConfig(options) {
149
+ const { schemas, apiNames, ...rest } = options;
150
+ if (schemas || apiNames) {
151
+ return { ...rest, db: { schemas, apiNames } };
152
+ }
153
+ return rest;
154
+ }
155
+ /**
156
+ * Normalizes top-level list-like CLI options to string arrays.
157
+ * This keeps non-interactive paths equivalent to prompt sanitize behavior.
158
+ */
159
+ export function normalizeCodegenListOptions(options) {
160
+ return {
161
+ ...options,
162
+ schemas: normalizeListOption(options.schemas),
163
+ apiNames: normalizeListOption(options.apiNames),
164
+ };
165
+ }
166
+ /**
167
+ * Returns true when source options are already available, so prompting can be skipped.
168
+ */
169
+ export function hasResolvedCodegenSource(options) {
170
+ const normalized = normalizeCodegenListOptions(camelizeArgv(options));
171
+ const db = normalized.db;
172
+ const dbSchemas = normalizeListOption(db?.schemas);
173
+ const dbApiNames = normalizeListOption(db?.apiNames);
174
+ return Boolean(normalized.endpoint ||
175
+ normalized.schemaFile ||
176
+ normalized.schemas?.length ||
177
+ normalized.apiNames?.length ||
178
+ dbSchemas?.length ||
179
+ dbApiNames?.length);
180
+ }
181
+ export function seedArgvFromConfig(argv, fileConfig) {
182
+ const flat = flattenDbFields(fileConfig);
183
+ const hyphenated = hyphenateKeys(flat);
184
+ const defined = filterDefined(hyphenated);
185
+ return { ...defined, ...argv };
186
+ }
187
+ export function buildGenerateOptions(answers, fileConfig = {}) {
188
+ const camelized = camelizeArgv(answers);
189
+ const normalized = normalizeCodegenListOptions(camelized);
190
+ const withDb = buildDbConfig(normalized);
191
+ return { ...fileConfig, ...withDb };
192
+ }
@@ -120,17 +120,35 @@ export const PG_ERROR_CODES = {
120
120
  // Error Factory
121
121
  // ============================================================================
122
122
  export const createError = {
123
- network: (originalError) => new DataError(DataErrorType.NETWORK_ERROR, 'Network error occurred', { originalError }),
124
- timeout: (originalError) => new DataError(DataErrorType.TIMEOUT_ERROR, 'Request timed out', { originalError }),
123
+ network: (originalError) => new DataError(DataErrorType.NETWORK_ERROR, 'Network error occurred', {
124
+ originalError,
125
+ }),
126
+ timeout: (originalError) => new DataError(DataErrorType.TIMEOUT_ERROR, 'Request timed out', {
127
+ originalError,
128
+ }),
125
129
  unauthorized: (message = 'Authentication required') => new DataError(DataErrorType.UNAUTHORIZED, message),
126
130
  forbidden: (message = 'Access forbidden') => new DataError(DataErrorType.FORBIDDEN, message),
127
131
  badRequest: (message, code) => new DataError(DataErrorType.BAD_REQUEST, message, { code }),
128
132
  notFound: (message = 'Resource not found') => new DataError(DataErrorType.NOT_FOUND, message),
129
133
  graphql: (message, code) => new DataError(DataErrorType.GRAPHQL_ERROR, message, { code }),
130
- uniqueViolation: (message, fieldName, constraint) => new DataError(DataErrorType.UNIQUE_VIOLATION, message, { fieldName, constraint, code: '23505' }),
131
- foreignKeyViolation: (message, fieldName, constraint) => new DataError(DataErrorType.FOREIGN_KEY_VIOLATION, message, { fieldName, constraint, code: '23503' }),
132
- notNullViolation: (message, fieldName, constraint) => new DataError(DataErrorType.NOT_NULL_VIOLATION, message, { fieldName, constraint, code: '23502' }),
133
- unknown: (originalError) => new DataError(DataErrorType.UNKNOWN_ERROR, originalError.message, { originalError }),
134
+ uniqueViolation: (message, fieldName, constraint) => new DataError(DataErrorType.UNIQUE_VIOLATION, message, {
135
+ fieldName,
136
+ constraint,
137
+ code: '23505',
138
+ }),
139
+ foreignKeyViolation: (message, fieldName, constraint) => new DataError(DataErrorType.FOREIGN_KEY_VIOLATION, message, {
140
+ fieldName,
141
+ constraint,
142
+ code: '23503',
143
+ }),
144
+ notNullViolation: (message, fieldName, constraint) => new DataError(DataErrorType.NOT_NULL_VIOLATION, message, {
145
+ fieldName,
146
+ constraint,
147
+ code: '23502',
148
+ }),
149
+ unknown: (originalError) => new DataError(DataErrorType.UNKNOWN_ERROR, originalError.message, {
150
+ originalError,
151
+ }),
134
152
  };
135
153
  function parseGraphQLErrorCode(code) {
136
154
  if (!code)
@@ -161,10 +179,13 @@ function classifyByMessage(message) {
161
179
  if (lower.includes('timeout') || lower.includes('timed out')) {
162
180
  return DataErrorType.TIMEOUT_ERROR;
163
181
  }
164
- if (lower.includes('network') || lower.includes('fetch') || lower.includes('failed to fetch')) {
182
+ if (lower.includes('network') ||
183
+ lower.includes('fetch') ||
184
+ lower.includes('failed to fetch')) {
165
185
  return DataErrorType.NETWORK_ERROR;
166
186
  }
167
- if (lower.includes('unauthorized') || lower.includes('authentication required')) {
187
+ if (lower.includes('unauthorized') ||
188
+ lower.includes('authentication required')) {
168
189
  return DataErrorType.UNAUTHORIZED;
169
190
  }
170
191
  if (lower.includes('forbidden') || lower.includes('permission')) {
@@ -176,7 +197,8 @@ function classifyByMessage(message) {
176
197
  if (lower.includes('foreign key constraint')) {
177
198
  return DataErrorType.FOREIGN_KEY_VIOLATION;
178
199
  }
179
- if (lower.includes('not-null constraint') || lower.includes('null value in column')) {
200
+ if (lower.includes('not-null constraint') ||
201
+ lower.includes('null value in column')) {
180
202
  return DataErrorType.NOT_NULL_VIOLATION;
181
203
  }
182
204
  return DataErrorType.UNKNOWN_ERROR;
@@ -2,8 +2,8 @@
2
2
  * GraphQL execution utilities
3
3
  */
4
4
  import { print } from 'graphql';
5
- import { TypedDocumentString } from './typed-document';
6
5
  import { createError, parseGraphQLError } from './error';
6
+ import { TypedDocumentString } from './typed-document';
7
7
  // ============================================================================
8
8
  // Helpers
9
9
  // ============================================================================
@@ -98,7 +98,7 @@ async function handleHttpError(response) {
98
98
  * Create a GraphQL client instance
99
99
  */
100
100
  export function createGraphQLClient(options) {
101
- const { endpoint, headers: defaultHeaders = {}, timeout: defaultTimeout = 30000 } = options;
101
+ const { endpoint, headers: defaultHeaders = {}, timeout: defaultTimeout = 30000, } = options;
102
102
  return {
103
103
  /**
104
104
  * Execute a GraphQL operation
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Client exports
3
3
  */
4
- export { TypedDocumentString, type DocumentTypeDecoration } from './typed-document';
5
- export { DataError, DataErrorType, createError, parseGraphQLError, isDataError, PG_ERROR_CODES, type DataErrorOptions, type GraphQLError, } from './error';
6
- export { execute, createGraphQLClient, type ExecuteOptions, type GraphQLClientOptions, type GraphQLClient, type GraphQLResponse, } from './execute';
4
+ export { createError, DataError, type DataErrorOptions, DataErrorType, type GraphQLError, isDataError, parseGraphQLError, PG_ERROR_CODES, } from './error';
5
+ export { createGraphQLClient, execute, type ExecuteOptions, type GraphQLClient, type GraphQLClientOptions, type GraphQLResponse, } from './execute';
6
+ export { type DocumentTypeDecoration, TypedDocumentString, } from './typed-document';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Client exports
3
3
  */
4
- export { TypedDocumentString } from './typed-document';
5
- export { DataError, DataErrorType, createError, parseGraphQLError, isDataError, PG_ERROR_CODES, } from './error';
6
- export { execute, createGraphQLClient, } from './execute';
4
+ export { createError, DataError, DataErrorType, isDataError, parseGraphQLError, PG_ERROR_CODES, } from './error';
5
+ export { createGraphQLClient, execute, } from './execute';
6
+ export { TypedDocumentString, } from './typed-document';
package/esm/core/ast.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { DocumentNode, FieldNode } from 'graphql';
2
- import type { ASTFunctionParams, QueryFieldSelection, MutationASTParams } from './types';
2
+ import type { ASTFunctionParams, MutationASTParams, QueryFieldSelection } from './types';
3
3
  export declare const getAll: ({ queryName, operationName, selection, }: ASTFunctionParams) => DocumentNode;
4
4
  export declare const getCount: ({ queryName, operationName, query, }: Omit<ASTFunctionParams, "selection">) => DocumentNode;
5
5
  export declare const getMany: ({ builder, queryName, operationName, query, selection, }: ASTFunctionParams) => DocumentNode;
package/esm/core/ast.js CHANGED
@@ -527,7 +527,7 @@ function getUpdateVariablesAst(attrs, patchers) {
527
527
  const patchVariables = attrs
528
528
  .filter((field) => !patchers.includes(field.name))
529
529
  .map((field) => {
530
- const { name: fieldName, type: fieldType, isArray, isArrayNotNull } = field;
530
+ const { name: fieldName, type: fieldType, isArray, isArrayNotNull, } = field;
531
531
  let type = t.namedType({ type: fieldType });
532
532
  if (isArray) {
533
533
  type = t.listType({ type });