@constructive-io/graphql-codegen 3.2.1 → 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 (215) hide show
  1. package/cli/index.js +36 -43
  2. package/cli/shared.d.ts +15 -19
  3. package/cli/shared.js +104 -25
  4. package/client/error.js +31 -9
  5. package/client/execute.js +2 -2
  6. package/client/index.d.ts +3 -3
  7. package/client/index.js +6 -6
  8. package/core/ast.d.ts +1 -1
  9. package/core/ast.js +1 -1
  10. package/core/codegen/babel-ast.d.ts +1 -1
  11. package/core/codegen/babel-ast.js +2 -2
  12. package/core/codegen/barrel.d.ts +0 -6
  13. package/core/codegen/barrel.js +22 -19
  14. package/core/codegen/client.d.ts +2 -12
  15. package/core/codegen/client.js +7 -21
  16. package/core/codegen/custom-mutations.d.ts +0 -14
  17. package/core/codegen/custom-mutations.js +139 -88
  18. package/core/codegen/custom-queries.d.ts +0 -14
  19. package/core/codegen/custom-queries.js +483 -193
  20. package/core/codegen/hooks-ast.d.ts +75 -0
  21. package/core/codegen/hooks-ast.js +522 -0
  22. package/core/codegen/index.d.ts +16 -18
  23. package/core/codegen/index.js +42 -88
  24. package/core/codegen/invalidation.d.ts +1 -7
  25. package/core/codegen/invalidation.js +50 -16
  26. package/core/codegen/mutation-keys.d.ts +1 -10
  27. package/core/codegen/mutation-keys.js +22 -8
  28. package/core/codegen/mutations.d.ts +0 -13
  29. package/core/codegen/mutations.js +301 -366
  30. package/core/codegen/orm/barrel.d.ts +0 -5
  31. package/core/codegen/orm/barrel.js +5 -0
  32. package/core/codegen/orm/client-generator.d.ts +0 -5
  33. package/core/codegen/orm/client-generator.js +7 -2
  34. package/core/codegen/orm/client.js +3 -1
  35. package/core/codegen/orm/custom-ops-generator.d.ts +0 -6
  36. package/core/codegen/orm/custom-ops-generator.js +104 -51
  37. package/core/codegen/orm/index.d.ts +4 -4
  38. package/core/codegen/orm/index.js +28 -15
  39. package/core/codegen/orm/input-types-generator.d.ts +1 -13
  40. package/core/codegen/orm/input-types-generator.js +85 -23
  41. package/core/codegen/orm/model-generator.d.ts +0 -5
  42. package/core/codegen/orm/model-generator.js +309 -131
  43. package/core/codegen/orm/select-types.d.ts +19 -14
  44. package/core/codegen/queries.d.ts +0 -8
  45. package/core/codegen/queries.js +360 -559
  46. package/core/codegen/query-keys.d.ts +1 -1
  47. package/core/codegen/query-keys.js +37 -23
  48. package/core/codegen/scalars.js +3 -1
  49. package/core/codegen/schema-types-generator.d.ts +1 -1
  50. package/core/codegen/schema-types-generator.js +17 -2
  51. package/core/codegen/select-helpers.d.ts +19 -0
  52. package/core/codegen/select-helpers.js +40 -0
  53. package/core/codegen/selection.d.ts +4 -0
  54. package/core/codegen/selection.js +65 -0
  55. package/core/codegen/shared/index.d.ts +2 -15
  56. package/core/codegen/shared/index.js +17 -4
  57. package/core/codegen/templates/hooks-client.ts +49 -0
  58. package/core/codegen/templates/hooks-selection.ts +58 -0
  59. package/core/codegen/templates/orm-client.ts +8 -6
  60. package/core/codegen/templates/query-builder.ts +250 -46
  61. package/core/codegen/templates/select-types.ts +31 -14
  62. package/core/codegen/type-resolver.d.ts +1 -5
  63. package/core/codegen/type-resolver.js +0 -22
  64. package/core/codegen/types.d.ts +0 -3
  65. package/core/codegen/types.js +71 -14
  66. package/core/codegen/utils.d.ts +1 -4
  67. package/core/codegen/utils.js +4 -1
  68. package/core/config/index.d.ts +1 -1
  69. package/core/config/resolver.js +1 -3
  70. package/core/generate.js +38 -50
  71. package/core/index.d.ts +3 -3
  72. package/core/index.js +3 -4
  73. package/core/introspect/index.d.ts +6 -6
  74. package/core/introspect/index.js +5 -8
  75. package/core/introspect/infer-tables.d.ts +0 -14
  76. package/core/introspect/infer-tables.js +15 -1
  77. package/core/introspect/source/database.js +1 -1
  78. package/core/introspect/source/endpoint.d.ts +0 -6
  79. package/core/introspect/source/endpoint.js +7 -1
  80. package/core/introspect/source/index.d.ts +4 -4
  81. package/core/introspect/source/index.js +5 -9
  82. package/core/introspect/source/pgpm-module.js +3 -3
  83. package/core/introspect/transform-schema.d.ts +2 -2
  84. package/core/introspect/transform-schema.js +2 -2
  85. package/core/output/index.d.ts +1 -1
  86. package/core/output/index.js +2 -2
  87. package/core/output/writer.d.ts +3 -0
  88. package/core/output/writer.js +20 -1
  89. package/core/pipeline/index.d.ts +2 -2
  90. package/core/query-builder.d.ts +2 -2
  91. package/core/query-builder.js +1 -1
  92. package/core/watch/index.d.ts +4 -4
  93. package/core/watch/index.js +9 -9
  94. package/core/watch/orchestrator.js +5 -3
  95. package/esm/cli/index.js +37 -44
  96. package/esm/cli/shared.d.ts +15 -19
  97. package/esm/cli/shared.js +94 -23
  98. package/esm/client/error.js +31 -9
  99. package/esm/client/execute.js +2 -2
  100. package/esm/client/index.d.ts +3 -3
  101. package/esm/client/index.js +3 -3
  102. package/esm/core/ast.d.ts +1 -1
  103. package/esm/core/ast.js +1 -1
  104. package/esm/core/codegen/babel-ast.d.ts +1 -1
  105. package/esm/core/codegen/babel-ast.js +2 -2
  106. package/esm/core/codegen/barrel.d.ts +0 -6
  107. package/esm/core/codegen/barrel.js +23 -20
  108. package/esm/core/codegen/client.d.ts +2 -12
  109. package/esm/core/codegen/client.js +7 -21
  110. package/esm/core/codegen/custom-mutations.d.ts +0 -14
  111. package/esm/core/codegen/custom-mutations.js +141 -90
  112. package/esm/core/codegen/custom-queries.d.ts +0 -14
  113. package/esm/core/codegen/custom-queries.js +486 -196
  114. package/esm/core/codegen/hooks-ast.d.ts +75 -0
  115. package/esm/core/codegen/hooks-ast.js +424 -0
  116. package/esm/core/codegen/index.d.ts +16 -18
  117. package/esm/core/codegen/index.js +26 -71
  118. package/esm/core/codegen/invalidation.d.ts +1 -7
  119. package/esm/core/codegen/invalidation.js +51 -17
  120. package/esm/core/codegen/mutation-keys.d.ts +1 -10
  121. package/esm/core/codegen/mutation-keys.js +23 -9
  122. package/esm/core/codegen/mutations.d.ts +0 -13
  123. package/esm/core/codegen/mutations.js +302 -367
  124. package/esm/core/codegen/orm/barrel.d.ts +0 -5
  125. package/esm/core/codegen/orm/barrel.js +6 -1
  126. package/esm/core/codegen/orm/client-generator.d.ts +0 -5
  127. package/esm/core/codegen/orm/client-generator.js +7 -2
  128. package/esm/core/codegen/orm/client.js +3 -1
  129. package/esm/core/codegen/orm/custom-ops-generator.d.ts +0 -6
  130. package/esm/core/codegen/orm/custom-ops-generator.js +103 -50
  131. package/esm/core/codegen/orm/index.d.ts +4 -4
  132. package/esm/core/codegen/orm/index.js +25 -12
  133. package/esm/core/codegen/orm/input-types-generator.d.ts +1 -13
  134. package/esm/core/codegen/orm/input-types-generator.js +85 -23
  135. package/esm/core/codegen/orm/model-generator.d.ts +0 -5
  136. package/esm/core/codegen/orm/model-generator.js +310 -132
  137. package/esm/core/codegen/orm/select-types.d.ts +19 -14
  138. package/esm/core/codegen/queries.d.ts +0 -8
  139. package/esm/core/codegen/queries.js +362 -561
  140. package/esm/core/codegen/query-keys.d.ts +1 -1
  141. package/esm/core/codegen/query-keys.js +38 -24
  142. package/esm/core/codegen/scalars.js +3 -1
  143. package/esm/core/codegen/schema-types-generator.d.ts +1 -1
  144. package/esm/core/codegen/schema-types-generator.js +17 -2
  145. package/esm/core/codegen/select-helpers.d.ts +19 -0
  146. package/esm/core/codegen/select-helpers.js +35 -0
  147. package/esm/core/codegen/selection.d.ts +4 -0
  148. package/esm/core/codegen/selection.js +29 -0
  149. package/esm/core/codegen/shared/index.d.ts +2 -15
  150. package/esm/core/codegen/shared/index.js +16 -3
  151. package/esm/core/codegen/type-resolver.d.ts +1 -5
  152. package/esm/core/codegen/type-resolver.js +1 -22
  153. package/esm/core/codegen/types.d.ts +0 -3
  154. package/esm/core/codegen/types.js +72 -15
  155. package/esm/core/codegen/utils.d.ts +1 -4
  156. package/esm/core/codegen/utils.js +4 -1
  157. package/esm/core/config/index.d.ts +1 -1
  158. package/esm/core/config/resolver.js +2 -4
  159. package/esm/core/generate.js +38 -50
  160. package/esm/core/index.d.ts +3 -3
  161. package/esm/core/index.js +2 -3
  162. package/esm/core/introspect/index.d.ts +6 -6
  163. package/esm/core/introspect/index.js +3 -6
  164. package/esm/core/introspect/infer-tables.d.ts +0 -14
  165. package/esm/core/introspect/infer-tables.js +16 -2
  166. package/esm/core/introspect/source/database.js +2 -2
  167. package/esm/core/introspect/source/endpoint.d.ts +0 -6
  168. package/esm/core/introspect/source/endpoint.js +7 -1
  169. package/esm/core/introspect/source/index.d.ts +4 -4
  170. package/esm/core/introspect/source/index.js +6 -10
  171. package/esm/core/introspect/source/pgpm-module.js +3 -3
  172. package/esm/core/introspect/transform-schema.d.ts +2 -2
  173. package/esm/core/introspect/transform-schema.js +2 -2
  174. package/esm/core/output/index.d.ts +1 -1
  175. package/esm/core/output/index.js +1 -1
  176. package/esm/core/output/writer.d.ts +3 -0
  177. package/esm/core/output/writer.js +20 -1
  178. package/esm/core/pipeline/index.d.ts +2 -2
  179. package/esm/core/pipeline/index.js +2 -2
  180. package/esm/core/query-builder.d.ts +2 -2
  181. package/esm/core/query-builder.js +2 -2
  182. package/esm/core/watch/index.d.ts +4 -4
  183. package/esm/core/watch/index.js +3 -3
  184. package/esm/core/watch/orchestrator.js +5 -3
  185. package/esm/generators/index.d.ts +3 -3
  186. package/esm/generators/index.js +3 -3
  187. package/esm/generators/mutations.d.ts +1 -1
  188. package/esm/generators/select.d.ts +1 -1
  189. package/esm/index.d.ts +3 -3
  190. package/esm/index.js +1 -4
  191. package/esm/types/config.d.ts +0 -10
  192. package/esm/types/config.js +0 -2
  193. package/esm/types/index.d.ts +6 -6
  194. package/esm/types/index.js +1 -1
  195. package/generators/index.d.ts +3 -3
  196. package/generators/index.js +8 -8
  197. package/generators/mutations.d.ts +1 -1
  198. package/generators/select.d.ts +1 -1
  199. package/index.d.ts +3 -3
  200. package/index.js +11 -6
  201. package/package.json +10 -10
  202. package/types/config.d.ts +0 -10
  203. package/types/config.js +0 -2
  204. package/types/index.d.ts +6 -6
  205. package/types/index.js +2 -2
  206. package/core/codegen/gql-ast.d.ts +0 -41
  207. package/core/codegen/gql-ast.js +0 -353
  208. package/core/codegen/schema-gql-ast.d.ts +0 -51
  209. package/core/codegen/schema-gql-ast.js +0 -385
  210. package/core/codegen/templates/client.browser.ts +0 -271
  211. package/core/codegen/templates/client.node.ts +0 -337
  212. package/esm/core/codegen/gql-ast.d.ts +0 -41
  213. package/esm/core/codegen/gql-ast.js +0 -312
  214. package/esm/core/codegen/schema-gql-ast.d.ts +0 -51
  215. 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 { camelizeArgv, 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,35 +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
- // Convert kebab-case CLI args to camelCase for internal use
95
- const camelized = camelizeArgv(answers);
96
- // Build db config if schemas or apiNames provided
97
- const db = (camelized.schemas || camelized.apiNames) ? {
98
- schemas: camelized.schemas,
99
- apiNames: camelized.apiNames,
100
- } : undefined;
101
- const result = await generate({
102
- endpoint: camelized.endpoint,
103
- schemaFile: camelized.schemaFile,
104
- db,
105
- output: camelized.output,
106
- authorization: camelized.authorization,
107
- reactQuery: camelized.reactQuery,
108
- orm: camelized.orm,
109
- browserCompatible: camelized.browserCompatible,
110
- dryRun: camelized.dryRun,
111
- verbose: camelized.verbose,
112
- });
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);
113
101
  printResult(result);
114
102
  prompter.close();
115
103
  return argv;
@@ -126,13 +114,18 @@ export const options = {
126
114
  a: 'authorization',
127
115
  v: 'verbose',
128
116
  },
129
- boolean: [
130
- 'help', 'version', 'verbose', 'dry-run', 'react-query', 'orm', 'keep-db', 'browser-compatible',
131
- ],
132
117
  string: [
133
- 'config', 'endpoint', 'schema-file', 'output', 'target', 'authorization',
134
- 'pgpm-module-path', 'pgpm-workspace-path', 'pgpm-module-name',
135
- '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',
136
129
  ],
137
130
  },
138
131
  };
@@ -1,19 +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
- * CLI accepts kebab-case arguments, converted to camelCase for internal use
16
- */
17
5
  export interface CodegenAnswers {
18
6
  endpoint?: string;
19
7
  schemaFile?: string;
@@ -22,17 +10,25 @@ export interface CodegenAnswers {
22
10
  apiNames?: string[];
23
11
  reactQuery?: boolean;
24
12
  orm?: boolean;
25
- browserCompatible?: boolean;
26
13
  authorization?: string;
27
14
  dryRun?: boolean;
28
15
  verbose?: boolean;
29
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>;
30
24
  /**
31
- * 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.
32
27
  */
33
- export declare const codegenQuestions: Question[];
28
+ export declare function normalizeCodegenListOptions(options: Record<string, unknown>): Record<string, unknown>;
34
29
  /**
35
- * Print the result of a generate operation
30
+ * Returns true when source options are already available, so prompting can be skipped.
36
31
  */
37
- export declare function printResult(result: GenerateResult): void;
38
- export declare const camelizeArgv: (argv: Record<string, any>) => any;
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,16 +1,31 @@
1
- import { camelize } from 'inflekt';
2
- import { inflektTree } from 'inflekt/transform-keys';
3
1
  /**
4
- * 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.
5
6
  */
7
+ import { camelize } from 'inflekt';
8
+ import { inflektTree } from 'inflekt/transform-keys';
6
9
  export const splitCommas = (input) => {
7
10
  if (!input)
8
11
  return undefined;
9
- return input.split(',').map((s) => s.trim()).filter(Boolean);
12
+ return input
13
+ .split(',')
14
+ .map((s) => s.trim())
15
+ .filter(Boolean);
10
16
  };
11
- /**
12
- * Questions for the codegen CLI
13
- */
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
+ }
14
29
  export const codegenQuestions = [
15
30
  {
16
31
  name: 'endpoint',
@@ -62,14 +77,6 @@ export const codegenQuestions = [
62
77
  default: false,
63
78
  useDefault: true,
64
79
  },
65
- {
66
- name: 'browser-compatible',
67
- message: 'Generate browser-compatible code?',
68
- type: 'confirm',
69
- required: false,
70
- default: true,
71
- useDefault: true,
72
- },
73
80
  {
74
81
  name: 'authorization',
75
82
  message: 'Authorization header value',
@@ -93,9 +100,6 @@ export const codegenQuestions = [
93
100
  useDefault: true,
94
101
  },
95
102
  ];
96
- /**
97
- * Print the result of a generate operation
98
- */
99
103
  export function printResult(result) {
100
104
  if (result.success) {
101
105
  console.log('[ok]', result.message);
@@ -109,13 +113,80 @@ export function printResult(result) {
109
113
  process.exit(1);
110
114
  }
111
115
  }
116
+ // ============================================================================
117
+ // Key transform utilities
118
+ // ============================================================================
112
119
  const isTopLevel = (_key, path) => path.length === 0;
120
+ const skipNonTopLevel = (key, path) => !isTopLevel(key, path) || key === '_' || key.startsWith('_');
113
121
  export const camelizeArgv = (argv) => inflektTree(argv, (key) => {
114
- // inflection.camelize expects underscores, so replace hyphens first
115
122
  const underscored = key.replace(/-/g, '_');
116
123
  return camelize(underscored, true);
117
- }, {
118
- skip: (key, path) => !isTopLevel(key, path) ||
119
- key === '_' ||
120
- key.startsWith('_')
124
+ }, { skip: skipNonTopLevel });
125
+ export const hyphenateKeys = (obj) => inflektTree(obj, (key) => key.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase()), {
126
+ skip: skipNonTopLevel,
121
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 });
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import generate from '@babel/generator';
9
9
  import * as t from '@babel/types';
10
- export { t, generate };
10
+ export { generate, t };
11
11
  /**
12
12
  * Generate code from an array of statements
13
13
  */