@constructive-io/graphql-codegen 2.19.0 → 2.20.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 (301) hide show
  1. package/README.md +1818 -113
  2. package/__tests__/codegen/input-types-generator.test.d.ts +1 -0
  3. package/__tests__/codegen/input-types-generator.test.js +635 -0
  4. package/cli/codegen/barrel.d.ts +27 -0
  5. package/cli/codegen/barrel.js +163 -0
  6. package/cli/codegen/client.d.ts +4 -0
  7. package/cli/codegen/client.js +170 -0
  8. package/cli/codegen/custom-mutations.d.ts +38 -0
  9. package/cli/codegen/custom-mutations.js +149 -0
  10. package/cli/codegen/custom-queries.d.ts +38 -0
  11. package/cli/codegen/custom-queries.js +358 -0
  12. package/cli/codegen/filters.d.ts +27 -0
  13. package/cli/codegen/filters.js +357 -0
  14. package/cli/codegen/gql-ast.d.ts +41 -0
  15. package/cli/codegen/gql-ast.js +329 -0
  16. package/cli/codegen/index.d.ts +71 -0
  17. package/cli/codegen/index.js +147 -0
  18. package/cli/codegen/mutations.d.ts +30 -0
  19. package/cli/codegen/mutations.js +410 -0
  20. package/cli/codegen/orm/barrel.d.ts +18 -0
  21. package/cli/codegen/orm/barrel.js +48 -0
  22. package/cli/codegen/orm/client-generator.d.ts +45 -0
  23. package/cli/codegen/orm/client-generator.js +646 -0
  24. package/cli/codegen/orm/custom-ops-generator.d.ts +30 -0
  25. package/cli/codegen/orm/custom-ops-generator.js +350 -0
  26. package/cli/codegen/orm/index.d.ts +38 -0
  27. package/cli/codegen/orm/index.js +88 -0
  28. package/cli/codegen/orm/input-types-generator.d.ts +21 -0
  29. package/cli/codegen/orm/input-types-generator.js +705 -0
  30. package/cli/codegen/orm/input-types-generator.test.d.ts +1 -0
  31. package/cli/codegen/orm/input-types-generator.test.js +75 -0
  32. package/cli/codegen/orm/model-generator.d.ts +32 -0
  33. package/cli/codegen/orm/model-generator.js +264 -0
  34. package/cli/codegen/orm/query-builder.d.ts +161 -0
  35. package/cli/codegen/orm/query-builder.js +366 -0
  36. package/cli/codegen/orm/select-types.d.ts +169 -0
  37. package/cli/codegen/orm/select-types.js +16 -0
  38. package/cli/codegen/orm/select-types.test.d.ts +11 -0
  39. package/cli/codegen/orm/select-types.test.js +22 -0
  40. package/cli/codegen/queries.d.ts +25 -0
  41. package/cli/codegen/queries.js +438 -0
  42. package/cli/codegen/scalars.d.ts +12 -0
  43. package/cli/codegen/scalars.js +71 -0
  44. package/cli/codegen/schema-gql-ast.d.ts +51 -0
  45. package/cli/codegen/schema-gql-ast.js +385 -0
  46. package/cli/codegen/ts-ast.d.ts +122 -0
  47. package/cli/codegen/ts-ast.js +280 -0
  48. package/cli/codegen/type-resolver.d.ts +96 -0
  49. package/cli/codegen/type-resolver.js +246 -0
  50. package/cli/codegen/types.d.ts +12 -0
  51. package/cli/codegen/types.js +69 -0
  52. package/cli/codegen/utils.d.ts +163 -0
  53. package/cli/codegen/utils.js +326 -0
  54. package/cli/commands/generate-orm.d.ts +37 -0
  55. package/cli/commands/generate-orm.js +195 -0
  56. package/cli/commands/generate.d.ts +39 -0
  57. package/cli/commands/generate.js +299 -0
  58. package/cli/commands/index.d.ts +7 -0
  59. package/cli/commands/index.js +12 -0
  60. package/cli/commands/init.d.ts +35 -0
  61. package/cli/commands/init.js +176 -0
  62. package/cli/index.d.ts +4 -0
  63. package/cli/index.js +291 -0
  64. package/cli/introspect/fetch-meta.d.ts +31 -0
  65. package/cli/introspect/fetch-meta.js +108 -0
  66. package/cli/introspect/fetch-schema.d.ts +21 -0
  67. package/cli/introspect/fetch-schema.js +86 -0
  68. package/cli/introspect/index.d.ts +8 -0
  69. package/cli/introspect/index.js +16 -0
  70. package/cli/introspect/meta-query.d.ts +111 -0
  71. package/cli/introspect/meta-query.js +191 -0
  72. package/cli/introspect/schema-query.d.ts +20 -0
  73. package/cli/introspect/schema-query.js +123 -0
  74. package/cli/introspect/transform-schema.d.ts +74 -0
  75. package/cli/introspect/transform-schema.js +269 -0
  76. package/cli/introspect/transform-schema.test.d.ts +1 -0
  77. package/cli/introspect/transform-schema.test.js +67 -0
  78. package/cli/introspect/transform.d.ts +21 -0
  79. package/cli/introspect/transform.js +216 -0
  80. package/cli/watch/cache.d.ts +45 -0
  81. package/cli/watch/cache.js +111 -0
  82. package/cli/watch/debounce.d.ts +19 -0
  83. package/cli/watch/debounce.js +89 -0
  84. package/cli/watch/hash.d.ts +17 -0
  85. package/cli/watch/hash.js +48 -0
  86. package/cli/watch/index.d.ts +10 -0
  87. package/cli/watch/index.js +22 -0
  88. package/cli/watch/orchestrator.d.ts +63 -0
  89. package/cli/watch/orchestrator.js +228 -0
  90. package/cli/watch/poller.d.ts +65 -0
  91. package/cli/watch/poller.js +203 -0
  92. package/cli/watch/types.d.ts +67 -0
  93. package/cli/watch/types.js +5 -0
  94. package/client/error.d.ts +95 -0
  95. package/client/error.js +255 -0
  96. package/client/execute.d.ts +57 -0
  97. package/client/execute.js +124 -0
  98. package/client/index.d.ts +6 -0
  99. package/client/index.js +18 -0
  100. package/client/typed-document.d.ts +31 -0
  101. package/client/typed-document.js +44 -0
  102. package/core/ast.d.ts +10 -0
  103. package/core/ast.js +593 -0
  104. package/core/custom-ast.d.ts +35 -0
  105. package/core/custom-ast.js +204 -0
  106. package/core/index.d.ts +8 -0
  107. package/core/index.js +33 -0
  108. package/core/meta-object/convert.d.ts +65 -0
  109. package/core/meta-object/convert.js +63 -0
  110. package/core/meta-object/format.json +93 -0
  111. package/core/meta-object/index.d.ts +2 -0
  112. package/core/meta-object/index.js +18 -0
  113. package/core/meta-object/validate.d.ts +9 -0
  114. package/core/meta-object/validate.js +34 -0
  115. package/core/query-builder.d.ts +46 -0
  116. package/core/query-builder.js +412 -0
  117. package/core/types.d.ts +139 -0
  118. package/core/types.js +28 -0
  119. package/esm/__tests__/codegen/input-types-generator.test.d.ts +1 -0
  120. package/esm/__tests__/codegen/input-types-generator.test.js +633 -0
  121. package/esm/cli/codegen/barrel.d.ts +27 -0
  122. package/esm/cli/codegen/barrel.js +156 -0
  123. package/esm/cli/codegen/client.d.ts +4 -0
  124. package/esm/cli/codegen/client.js +167 -0
  125. package/esm/cli/codegen/custom-mutations.d.ts +38 -0
  126. package/esm/cli/codegen/custom-mutations.js +145 -0
  127. package/esm/cli/codegen/custom-queries.d.ts +38 -0
  128. package/esm/cli/codegen/custom-queries.js +354 -0
  129. package/esm/cli/codegen/filters.d.ts +27 -0
  130. package/esm/cli/codegen/filters.js +351 -0
  131. package/esm/cli/codegen/gql-ast.d.ts +41 -0
  132. package/esm/cli/codegen/gql-ast.js +288 -0
  133. package/esm/cli/codegen/index.d.ts +71 -0
  134. package/esm/cli/codegen/index.js +124 -0
  135. package/esm/cli/codegen/mutations.d.ts +30 -0
  136. package/esm/cli/codegen/mutations.js +404 -0
  137. package/esm/cli/codegen/orm/barrel.d.ts +18 -0
  138. package/esm/cli/codegen/orm/barrel.js +44 -0
  139. package/esm/cli/codegen/orm/client-generator.d.ts +45 -0
  140. package/esm/cli/codegen/orm/client-generator.js +640 -0
  141. package/esm/cli/codegen/orm/custom-ops-generator.d.ts +30 -0
  142. package/esm/cli/codegen/orm/custom-ops-generator.js +346 -0
  143. package/esm/cli/codegen/orm/index.d.ts +38 -0
  144. package/esm/cli/codegen/orm/index.js +75 -0
  145. package/esm/cli/codegen/orm/input-types-generator.d.ts +21 -0
  146. package/esm/cli/codegen/orm/input-types-generator.js +700 -0
  147. package/esm/cli/codegen/orm/input-types-generator.test.d.ts +1 -0
  148. package/esm/cli/codegen/orm/input-types-generator.test.js +73 -0
  149. package/esm/cli/codegen/orm/model-generator.d.ts +32 -0
  150. package/esm/cli/codegen/orm/model-generator.js +260 -0
  151. package/esm/cli/codegen/orm/query-builder.d.ts +161 -0
  152. package/esm/cli/codegen/orm/query-builder.js +353 -0
  153. package/esm/cli/codegen/orm/select-types.d.ts +169 -0
  154. package/esm/cli/codegen/orm/select-types.js +15 -0
  155. package/esm/cli/codegen/orm/select-types.test.d.ts +11 -0
  156. package/esm/cli/codegen/orm/select-types.test.js +21 -0
  157. package/esm/cli/codegen/queries.d.ts +25 -0
  158. package/esm/cli/codegen/queries.js +433 -0
  159. package/esm/cli/codegen/scalars.d.ts +12 -0
  160. package/esm/cli/codegen/scalars.js +66 -0
  161. package/esm/cli/codegen/schema-gql-ast.d.ts +51 -0
  162. package/esm/cli/codegen/schema-gql-ast.js +343 -0
  163. package/esm/cli/codegen/ts-ast.d.ts +122 -0
  164. package/esm/cli/codegen/ts-ast.js +260 -0
  165. package/esm/cli/codegen/type-resolver.d.ts +96 -0
  166. package/esm/cli/codegen/type-resolver.js +224 -0
  167. package/esm/cli/codegen/types.d.ts +12 -0
  168. package/esm/cli/codegen/types.js +65 -0
  169. package/esm/cli/codegen/utils.d.ts +163 -0
  170. package/esm/cli/codegen/utils.js +288 -0
  171. package/esm/cli/commands/generate-orm.d.ts +37 -0
  172. package/esm/cli/commands/generate-orm.js +192 -0
  173. package/esm/cli/commands/generate.d.ts +39 -0
  174. package/esm/cli/commands/generate.js +262 -0
  175. package/esm/cli/commands/index.d.ts +7 -0
  176. package/esm/cli/commands/index.js +5 -0
  177. package/esm/cli/commands/init.d.ts +35 -0
  178. package/esm/cli/commands/init.js +138 -0
  179. package/esm/cli/index.d.ts +4 -0
  180. package/esm/cli/index.js +256 -0
  181. package/esm/cli/introspect/fetch-meta.d.ts +31 -0
  182. package/esm/cli/introspect/fetch-meta.js +104 -0
  183. package/esm/cli/introspect/fetch-schema.d.ts +21 -0
  184. package/esm/cli/introspect/fetch-schema.js +83 -0
  185. package/esm/cli/introspect/index.d.ts +8 -0
  186. package/esm/cli/introspect/index.js +6 -0
  187. package/esm/cli/introspect/meta-query.d.ts +111 -0
  188. package/esm/cli/introspect/meta-query.js +188 -0
  189. package/esm/cli/introspect/schema-query.d.ts +20 -0
  190. package/esm/cli/introspect/schema-query.js +120 -0
  191. package/esm/cli/introspect/transform-schema.d.ts +74 -0
  192. package/esm/cli/introspect/transform-schema.js +259 -0
  193. package/esm/cli/introspect/transform-schema.test.d.ts +1 -0
  194. package/esm/cli/introspect/transform-schema.test.js +65 -0
  195. package/esm/cli/introspect/transform.d.ts +21 -0
  196. package/esm/cli/introspect/transform.js +210 -0
  197. package/esm/cli/watch/cache.d.ts +45 -0
  198. package/esm/cli/watch/cache.js +73 -0
  199. package/esm/cli/watch/debounce.d.ts +19 -0
  200. package/esm/cli/watch/debounce.js +85 -0
  201. package/esm/cli/watch/hash.d.ts +17 -0
  202. package/esm/cli/watch/hash.js +43 -0
  203. package/esm/cli/watch/index.d.ts +10 -0
  204. package/esm/cli/watch/index.js +8 -0
  205. package/esm/cli/watch/orchestrator.d.ts +63 -0
  206. package/esm/cli/watch/orchestrator.js +223 -0
  207. package/esm/cli/watch/poller.d.ts +65 -0
  208. package/esm/cli/watch/poller.js +198 -0
  209. package/esm/cli/watch/types.d.ts +67 -0
  210. package/esm/cli/watch/types.js +4 -0
  211. package/esm/client/error.d.ts +95 -0
  212. package/esm/client/error.js +249 -0
  213. package/esm/client/execute.d.ts +57 -0
  214. package/esm/client/execute.js +120 -0
  215. package/esm/client/index.d.ts +6 -0
  216. package/esm/client/index.js +6 -0
  217. package/esm/client/typed-document.d.ts +31 -0
  218. package/esm/client/typed-document.js +40 -0
  219. package/esm/core/ast.d.ts +10 -0
  220. package/esm/core/ast.js +549 -0
  221. package/esm/core/custom-ast.d.ts +35 -0
  222. package/esm/core/custom-ast.js +161 -0
  223. package/esm/core/index.d.ts +8 -0
  224. package/esm/core/index.js +12 -0
  225. package/esm/core/meta-object/convert.d.ts +65 -0
  226. package/esm/core/meta-object/convert.js +60 -0
  227. package/esm/core/meta-object/format.json +93 -0
  228. package/esm/core/meta-object/index.d.ts +2 -0
  229. package/esm/core/meta-object/index.js +2 -0
  230. package/esm/core/meta-object/validate.d.ts +9 -0
  231. package/esm/core/meta-object/validate.js +28 -0
  232. package/esm/core/query-builder.d.ts +46 -0
  233. package/esm/core/query-builder.js +375 -0
  234. package/esm/core/types.d.ts +139 -0
  235. package/esm/core/types.js +24 -0
  236. package/esm/generators/field-selector.d.ts +30 -0
  237. package/esm/generators/field-selector.js +355 -0
  238. package/esm/generators/index.d.ts +6 -0
  239. package/esm/generators/index.js +9 -0
  240. package/esm/generators/mutations.d.ts +31 -0
  241. package/esm/generators/mutations.js +197 -0
  242. package/esm/generators/select.d.ts +50 -0
  243. package/esm/generators/select.js +636 -0
  244. package/esm/index.d.ts +12 -0
  245. package/esm/index.js +17 -3
  246. package/esm/react/index.d.ts +5 -0
  247. package/esm/react/index.js +6 -0
  248. package/esm/types/config.d.ts +199 -0
  249. package/esm/types/config.js +106 -0
  250. package/esm/types/index.d.ts +9 -0
  251. package/esm/types/index.js +4 -0
  252. package/esm/types/introspection.d.ts +121 -0
  253. package/esm/types/introspection.js +54 -0
  254. package/esm/types/mutation.d.ts +45 -0
  255. package/esm/types/mutation.js +4 -0
  256. package/esm/types/query.d.ts +82 -0
  257. package/esm/types/query.js +4 -0
  258. package/esm/types/schema.d.ts +253 -0
  259. package/esm/types/schema.js +5 -0
  260. package/esm/types/selection.d.ts +43 -0
  261. package/esm/types/selection.js +4 -0
  262. package/esm/utils/index.d.ts +4 -0
  263. package/esm/utils/index.js +4 -0
  264. package/generators/field-selector.d.ts +30 -0
  265. package/generators/field-selector.js +361 -0
  266. package/generators/index.d.ts +6 -0
  267. package/generators/index.js +27 -0
  268. package/generators/mutations.d.ts +31 -0
  269. package/generators/mutations.js +235 -0
  270. package/generators/select.d.ts +50 -0
  271. package/generators/select.js +679 -0
  272. package/index.d.ts +12 -3
  273. package/index.js +19 -3
  274. package/package.json +59 -38
  275. package/react/index.d.ts +5 -0
  276. package/react/index.js +9 -0
  277. package/types/config.d.ts +199 -0
  278. package/types/config.js +111 -0
  279. package/types/index.d.ts +9 -0
  280. package/types/index.js +10 -0
  281. package/types/introspection.d.ts +121 -0
  282. package/types/introspection.js +62 -0
  283. package/types/mutation.d.ts +45 -0
  284. package/types/mutation.js +5 -0
  285. package/types/query.d.ts +82 -0
  286. package/types/query.js +5 -0
  287. package/types/schema.d.ts +253 -0
  288. package/types/schema.js +6 -0
  289. package/types/selection.d.ts +43 -0
  290. package/types/selection.js +5 -0
  291. package/utils/index.d.ts +4 -0
  292. package/utils/index.js +7 -0
  293. package/codegen.d.ts +0 -13
  294. package/codegen.js +0 -293
  295. package/esm/codegen.js +0 -253
  296. package/esm/gql.js +0 -939
  297. package/esm/options.js +0 -27
  298. package/gql.d.ts +0 -188
  299. package/gql.js +0 -992
  300. package/options.d.ts +0 -45
  301. package/options.js +0 -31
@@ -0,0 +1,39 @@
1
+ export interface GenerateOptions {
2
+ /** Path to config file */
3
+ config?: string;
4
+ /** GraphQL endpoint URL (overrides config) */
5
+ endpoint?: string;
6
+ /** Output directory (overrides config) */
7
+ output?: string;
8
+ /** Authorization header */
9
+ authorization?: string;
10
+ /** Verbose output */
11
+ verbose?: boolean;
12
+ /** Dry run - don't write files */
13
+ dryRun?: boolean;
14
+ /** Skip custom operations (only generate table CRUD) */
15
+ skipCustomOperations?: boolean;
16
+ }
17
+ export interface GenerateResult {
18
+ success: boolean;
19
+ message: string;
20
+ tables?: string[];
21
+ customQueries?: string[];
22
+ customMutations?: string[];
23
+ filesWritten?: string[];
24
+ errors?: string[];
25
+ }
26
+ /**
27
+ * Execute the generate command
28
+ */
29
+ export declare function generateCommand(options?: GenerateOptions): Promise<GenerateResult>;
30
+ export interface GeneratedFile {
31
+ path: string;
32
+ content: string;
33
+ }
34
+ export interface WriteResult {
35
+ success: boolean;
36
+ filesWritten?: string[];
37
+ errors?: string[];
38
+ }
39
+ export declare function writeGeneratedFiles(files: GeneratedFile[], outputDir: string, subdirs: string[]): Promise<WriteResult>;
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Generate command - introspects endpoint and generates SDK
3
+ *
4
+ * This command:
5
+ * 1. Fetches _meta query for table-based CRUD operations
6
+ * 2. Fetches __schema introspection for ALL operations
7
+ * 3. Filters out table operations from custom operations to avoid duplicates
8
+ * 4. Generates hooks for both table CRUD and custom operations
9
+ */
10
+ import * as fs from 'node:fs';
11
+ import * as path from 'node:path';
12
+ import * as prettier from 'prettier';
13
+ import { resolveConfig } from '../../types/config';
14
+ import { fetchMeta, validateEndpoint } from '../introspect/fetch-meta';
15
+ import { fetchSchema } from '../introspect/fetch-schema';
16
+ import { transformMetaToCleanTables, filterTables, } from '../introspect/transform';
17
+ import { transformSchemaToOperations, filterOperations, getTableOperationNames, getCustomOperations, } from '../introspect/transform-schema';
18
+ import { findConfigFile, loadConfigFile } from './init';
19
+ import { generate } from '../codegen';
20
+ /**
21
+ * Execute the generate command
22
+ */
23
+ export async function generateCommand(options = {}) {
24
+ const log = options.verbose ? console.log : () => { };
25
+ // 1. Load config
26
+ log('Loading configuration...');
27
+ const configResult = await loadConfig(options);
28
+ if (!configResult.success) {
29
+ return {
30
+ success: false,
31
+ message: configResult.error,
32
+ };
33
+ }
34
+ const config = configResult.config;
35
+ log(` Endpoint: ${config.endpoint}`);
36
+ log(` Output: ${config.output}`);
37
+ // 2. Validate endpoint
38
+ const endpointValidation = validateEndpoint(config.endpoint);
39
+ if (!endpointValidation.valid) {
40
+ return {
41
+ success: false,
42
+ message: `Invalid endpoint: ${endpointValidation.error}`,
43
+ };
44
+ }
45
+ // Build authorization header if provided
46
+ const authHeader = options.authorization || config.headers['Authorization'];
47
+ // 3. Fetch _meta for table-based operations
48
+ log('Fetching schema metadata (_meta)...');
49
+ const metaResult = await fetchMeta({
50
+ endpoint: config.endpoint,
51
+ authorization: authHeader,
52
+ headers: config.headers,
53
+ timeout: 30000,
54
+ });
55
+ if (!metaResult.success) {
56
+ return {
57
+ success: false,
58
+ message: `Failed to fetch _meta: ${metaResult.error}`,
59
+ };
60
+ }
61
+ // 4. Transform to CleanTable[]
62
+ log('Transforming table schema...');
63
+ let tables = transformMetaToCleanTables(metaResult.data);
64
+ log(` Found ${tables.length} tables`);
65
+ // 5. Filter tables
66
+ tables = filterTables(tables, config.tables.include, config.tables.exclude);
67
+ log(` After filtering: ${tables.length} tables`);
68
+ if (tables.length === 0) {
69
+ return {
70
+ success: false,
71
+ message: 'No tables found after filtering. Check your include/exclude patterns.',
72
+ };
73
+ }
74
+ // Get table operation names for filtering custom operations
75
+ const tableOperationNames = getTableOperationNames(tables);
76
+ // 6. Fetch __schema for custom operations (unless skipped)
77
+ let customQueries = [];
78
+ let customMutations = [];
79
+ let customOperationsData;
80
+ if (!options.skipCustomOperations) {
81
+ log('Fetching schema introspection (__schema)...');
82
+ const schemaResult = await fetchSchema({
83
+ endpoint: config.endpoint,
84
+ authorization: authHeader,
85
+ headers: config.headers,
86
+ timeout: 30000,
87
+ });
88
+ if (schemaResult.success && schemaResult.data) {
89
+ log('Transforming custom operations...');
90
+ // Transform to CleanOperation[]
91
+ const { queries: allQueries, mutations: allMutations, typeRegistry } = transformSchemaToOperations(schemaResult.data);
92
+ log(` Found ${allQueries.length} queries and ${allMutations.length} mutations total`);
93
+ // Filter by config include/exclude
94
+ const filteredQueries = filterOperations(allQueries, config.queries.include, config.queries.exclude);
95
+ const filteredMutations = filterOperations(allMutations, config.mutations.include, config.mutations.exclude);
96
+ log(` After config filtering: ${filteredQueries.length} queries, ${filteredMutations.length} mutations`);
97
+ // Remove table operations (already handled by table generators)
98
+ const customQueriesOps = getCustomOperations(filteredQueries, tableOperationNames);
99
+ const customMutationsOps = getCustomOperations(filteredMutations, tableOperationNames);
100
+ log(` Custom operations: ${customQueriesOps.length} queries, ${customMutationsOps.length} mutations`);
101
+ customQueries = customQueriesOps.map((q) => q.name);
102
+ customMutations = customMutationsOps.map((m) => m.name);
103
+ customOperationsData = {
104
+ queries: customQueriesOps,
105
+ mutations: customMutationsOps,
106
+ typeRegistry,
107
+ };
108
+ }
109
+ else {
110
+ log(` Warning: Could not fetch __schema: ${schemaResult.error}`);
111
+ log(' Continuing with table-only generation...');
112
+ }
113
+ }
114
+ // 7. Generate code
115
+ log('Generating code...');
116
+ const { files: generatedFiles, stats } = generate({
117
+ tables,
118
+ customOperations: customOperationsData,
119
+ config,
120
+ });
121
+ log(` Generated ${stats.queryHooks} table query hooks`);
122
+ log(` Generated ${stats.mutationHooks} table mutation hooks`);
123
+ log(` Generated ${stats.customQueryHooks} custom query hooks`);
124
+ log(` Generated ${stats.customMutationHooks} custom mutation hooks`);
125
+ log(` Total files: ${stats.totalFiles}`);
126
+ if (options.dryRun) {
127
+ return {
128
+ success: true,
129
+ message: `Dry run complete. Would generate ${generatedFiles.length} files for ${tables.length} tables and ${customQueries.length + customMutations.length} custom operations.`,
130
+ tables: tables.map((t) => t.name),
131
+ customQueries,
132
+ customMutations,
133
+ filesWritten: generatedFiles.map((f) => f.path),
134
+ };
135
+ }
136
+ // 8. Write files
137
+ log('Writing files...');
138
+ const writeResult = await writeGeneratedFiles(generatedFiles, config.output, ['queries', 'mutations']);
139
+ if (!writeResult.success) {
140
+ return {
141
+ success: false,
142
+ message: `Failed to write files: ${writeResult.errors?.join(', ')}`,
143
+ errors: writeResult.errors,
144
+ };
145
+ }
146
+ const totalOps = customQueries.length + customMutations.length;
147
+ const customOpsMsg = totalOps > 0 ? ` and ${totalOps} custom operations` : '';
148
+ return {
149
+ success: true,
150
+ message: `Generated SDK for ${tables.length} tables${customOpsMsg}. Files written to ${config.output}`,
151
+ tables: tables.map((t) => t.name),
152
+ customQueries,
153
+ customMutations,
154
+ filesWritten: writeResult.filesWritten,
155
+ };
156
+ }
157
+ async function loadConfig(options) {
158
+ // Find config file
159
+ let configPath = options.config;
160
+ if (!configPath) {
161
+ configPath = findConfigFile() ?? undefined;
162
+ }
163
+ let baseConfig = {};
164
+ if (configPath) {
165
+ const loadResult = await loadConfigFile(configPath);
166
+ if (!loadResult.success) {
167
+ return { success: false, error: loadResult.error };
168
+ }
169
+ baseConfig = loadResult.config;
170
+ }
171
+ // Override with CLI options
172
+ const mergedConfig = {
173
+ endpoint: options.endpoint || baseConfig.endpoint || '',
174
+ output: options.output || baseConfig.output,
175
+ headers: baseConfig.headers,
176
+ tables: baseConfig.tables,
177
+ queries: baseConfig.queries,
178
+ mutations: baseConfig.mutations,
179
+ excludeFields: baseConfig.excludeFields,
180
+ hooks: baseConfig.hooks,
181
+ postgraphile: baseConfig.postgraphile,
182
+ codegen: baseConfig.codegen,
183
+ };
184
+ if (!mergedConfig.endpoint) {
185
+ return {
186
+ success: false,
187
+ error: 'No endpoint specified. Use --endpoint or create a config file with "graphql-codegen init".',
188
+ };
189
+ }
190
+ // Resolve with defaults
191
+ const config = resolveConfig(mergedConfig);
192
+ return { success: true, config };
193
+ }
194
+ export async function writeGeneratedFiles(files, outputDir, subdirs) {
195
+ const errors = [];
196
+ const written = [];
197
+ // Ensure output directory exists
198
+ try {
199
+ fs.mkdirSync(outputDir, { recursive: true });
200
+ }
201
+ catch (err) {
202
+ const message = err instanceof Error ? err.message : 'Unknown error';
203
+ return {
204
+ success: false,
205
+ errors: [`Failed to create output directory: ${message}`],
206
+ };
207
+ }
208
+ // Create subdirectories
209
+ for (const subdir of subdirs) {
210
+ const subdirPath = path.join(outputDir, subdir);
211
+ try {
212
+ fs.mkdirSync(subdirPath, { recursive: true });
213
+ }
214
+ catch (err) {
215
+ const message = err instanceof Error ? err.message : 'Unknown error';
216
+ errors.push(`Failed to create directory ${subdirPath}: ${message}`);
217
+ }
218
+ }
219
+ if (errors.length > 0) {
220
+ return { success: false, errors };
221
+ }
222
+ for (const file of files) {
223
+ const filePath = path.join(outputDir, file.path);
224
+ // Ensure parent directory exists
225
+ const parentDir = path.dirname(filePath);
226
+ try {
227
+ fs.mkdirSync(parentDir, { recursive: true });
228
+ }
229
+ catch {
230
+ // Ignore if already exists
231
+ }
232
+ try {
233
+ // Format with prettier
234
+ const formattedContent = await formatCode(file.content);
235
+ fs.writeFileSync(filePath, formattedContent, 'utf-8');
236
+ written.push(filePath);
237
+ }
238
+ catch (err) {
239
+ const message = err instanceof Error ? err.message : 'Unknown error';
240
+ errors.push(`Failed to write ${filePath}: ${message}`);
241
+ }
242
+ }
243
+ return {
244
+ success: errors.length === 0,
245
+ filesWritten: written,
246
+ errors: errors.length > 0 ? errors : undefined,
247
+ };
248
+ }
249
+ async function formatCode(code) {
250
+ try {
251
+ return await prettier.format(code, {
252
+ parser: 'typescript',
253
+ singleQuote: true,
254
+ trailingComma: 'es5',
255
+ tabWidth: 2,
256
+ });
257
+ }
258
+ catch {
259
+ // If prettier fails, return unformatted code
260
+ return code;
261
+ }
262
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * CLI commands exports
3
+ */
4
+ export { initCommand, findConfigFile, loadConfigFile } from './init';
5
+ export type { InitOptions, InitResult } from './init';
6
+ export { generateCommand } from './generate';
7
+ export type { GenerateOptions, GenerateResult } from './generate';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * CLI commands exports
3
+ */
4
+ export { initCommand, findConfigFile, loadConfigFile } from './init';
5
+ export { generateCommand } from './generate';
@@ -0,0 +1,35 @@
1
+ export interface InitOptions {
2
+ /** Target directory for the config file */
3
+ directory?: string;
4
+ /** Force overwrite existing config */
5
+ force?: boolean;
6
+ /** GraphQL endpoint URL to pre-populate */
7
+ endpoint?: string;
8
+ /** Output directory to pre-populate */
9
+ output?: string;
10
+ }
11
+ export interface InitResult {
12
+ success: boolean;
13
+ message: string;
14
+ configPath?: string;
15
+ }
16
+ /**
17
+ * Execute the init command
18
+ */
19
+ export declare function initCommand(options?: InitOptions): Promise<InitResult>;
20
+ /**
21
+ * Find the nearest config file by walking up directories
22
+ */
23
+ export declare function findConfigFile(startDir?: string): string | null;
24
+ /**
25
+ * Load and validate a config file
26
+ *
27
+ * Uses jiti to support TypeScript config files (.ts) in addition to
28
+ * JavaScript (.js, .mjs, .cjs) without requiring the user to have
29
+ * tsx or ts-node installed.
30
+ */
31
+ export declare function loadConfigFile(configPath: string): Promise<{
32
+ success: boolean;
33
+ config?: any;
34
+ error?: string;
35
+ }>;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Init command - creates a new graphql-codegen configuration file
3
+ */
4
+ import * as fs from 'node:fs';
5
+ import * as path from 'node:path';
6
+ import { createJiti } from 'jiti';
7
+ const CONFIG_FILENAME = 'graphql-codegen.config.ts';
8
+ const CONFIG_TEMPLATE = `import { defineConfig } from '@constructive-io/graphql-codegen';
9
+
10
+ export default defineConfig({
11
+ // GraphQL endpoint URL (PostGraphile with _meta plugin)
12
+ endpoint: '{{ENDPOINT}}',
13
+
14
+ // Output directory for generated files
15
+ output: '{{OUTPUT}}',
16
+
17
+ // Optional: Tables to include/exclude (supports glob patterns)
18
+ // tables: {
19
+ // include: ['*'],
20
+ // exclude: ['_*', 'pg_*'],
21
+ // },
22
+
23
+ // Optional: Authorization header for authenticated endpoints
24
+ // headers: {
25
+ // Authorization: 'Bearer YOUR_TOKEN',
26
+ // },
27
+
28
+ // Optional: Watch mode settings (in-memory caching, no file I/O)
29
+ // watch: {
30
+ // pollInterval: 3000, // ms
31
+ // debounce: 800, // ms
32
+ // clearScreen: true,
33
+ // touchFile: '.trigger', // Optional: file to touch on change
34
+ // },
35
+ });
36
+ `;
37
+ /**
38
+ * Execute the init command
39
+ */
40
+ export async function initCommand(options = {}) {
41
+ const { directory = process.cwd(), force = false, endpoint = '', output = './generated' } = options;
42
+ const configPath = path.join(directory, CONFIG_FILENAME);
43
+ // Check if config already exists
44
+ if (fs.existsSync(configPath) && !force) {
45
+ return {
46
+ success: false,
47
+ message: `Configuration file already exists: ${configPath}\nUse --force to overwrite.`,
48
+ };
49
+ }
50
+ // Generate config content
51
+ const content = CONFIG_TEMPLATE
52
+ .replace('{{ENDPOINT}}', endpoint || 'http://localhost:5000/graphql')
53
+ .replace('{{OUTPUT}}', output);
54
+ try {
55
+ // Ensure directory exists
56
+ fs.mkdirSync(directory, { recursive: true });
57
+ // Write config file
58
+ fs.writeFileSync(configPath, content, 'utf-8');
59
+ return {
60
+ success: true,
61
+ message: `Created configuration file: ${configPath}`,
62
+ configPath,
63
+ };
64
+ }
65
+ catch (err) {
66
+ const message = err instanceof Error ? err.message : 'Unknown error';
67
+ return {
68
+ success: false,
69
+ message: `Failed to create configuration file: ${message}`,
70
+ };
71
+ }
72
+ }
73
+ /**
74
+ * Find the nearest config file by walking up directories
75
+ */
76
+ export function findConfigFile(startDir = process.cwd()) {
77
+ let currentDir = startDir;
78
+ while (true) {
79
+ const configPath = path.join(currentDir, CONFIG_FILENAME);
80
+ if (fs.existsSync(configPath)) {
81
+ return configPath;
82
+ }
83
+ const parentDir = path.dirname(currentDir);
84
+ if (parentDir === currentDir) {
85
+ // Reached root
86
+ return null;
87
+ }
88
+ currentDir = parentDir;
89
+ }
90
+ }
91
+ /**
92
+ * Load and validate a config file
93
+ *
94
+ * Uses jiti to support TypeScript config files (.ts) in addition to
95
+ * JavaScript (.js, .mjs, .cjs) without requiring the user to have
96
+ * tsx or ts-node installed.
97
+ */
98
+ export async function loadConfigFile(configPath) {
99
+ if (!fs.existsSync(configPath)) {
100
+ return {
101
+ success: false,
102
+ error: `Config file not found: ${configPath}`,
103
+ };
104
+ }
105
+ try {
106
+ // Use jiti to load TypeScript/ESM config files seamlessly
107
+ // jiti handles .ts, .js, .mjs, .cjs and ESM/CJS interop
108
+ const jiti = createJiti(__filename, {
109
+ interopDefault: true,
110
+ debug: process.env.JITI_DEBUG === '1',
111
+ });
112
+ // jiti.import() with { default: true } returns mod?.default ?? mod
113
+ const config = await jiti.import(configPath, { default: true });
114
+ if (!config || typeof config !== 'object') {
115
+ return {
116
+ success: false,
117
+ error: 'Config file must export a configuration object',
118
+ };
119
+ }
120
+ if (!('endpoint' in config)) {
121
+ return {
122
+ success: false,
123
+ error: 'Config file missing required "endpoint" property',
124
+ };
125
+ }
126
+ return {
127
+ success: true,
128
+ config,
129
+ };
130
+ }
131
+ catch (err) {
132
+ const message = err instanceof Error ? err.message : 'Unknown error';
133
+ return {
134
+ success: false,
135
+ error: `Failed to load config file: ${message}`,
136
+ };
137
+ }
138
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * CLI entry point for graphql-codegen
3
+ */
4
+ export {};