@constructive-io/graphql-codegen 2.19.0 → 2.20.1

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,256 @@
1
+ /**
2
+ * CLI entry point for graphql-codegen
3
+ */
4
+ import { Command } from 'commander';
5
+ import { initCommand, findConfigFile, loadConfigFile } from './commands/init';
6
+ import { generateCommand } from './commands/generate';
7
+ import { generateOrmCommand } from './commands/generate-orm';
8
+ import { startWatch } from './watch';
9
+ import { resolveConfig } from '../types/config';
10
+ const program = new Command();
11
+ /**
12
+ * Load configuration for watch mode, merging CLI options with config file
13
+ */
14
+ async function loadWatchConfig(options) {
15
+ // Find config file
16
+ let configPath = options.config;
17
+ if (!configPath) {
18
+ configPath = findConfigFile() ?? undefined;
19
+ }
20
+ let baseConfig = {};
21
+ if (configPath) {
22
+ const loadResult = await loadConfigFile(configPath);
23
+ if (!loadResult.success) {
24
+ console.error('✗', loadResult.error);
25
+ return null;
26
+ }
27
+ baseConfig = loadResult.config;
28
+ }
29
+ // Merge CLI options with config
30
+ const mergedConfig = {
31
+ endpoint: options.endpoint || baseConfig.endpoint || '',
32
+ output: baseConfig.output,
33
+ headers: baseConfig.headers,
34
+ tables: baseConfig.tables,
35
+ queries: baseConfig.queries,
36
+ mutations: baseConfig.mutations,
37
+ excludeFields: baseConfig.excludeFields,
38
+ hooks: baseConfig.hooks,
39
+ postgraphile: baseConfig.postgraphile,
40
+ codegen: baseConfig.codegen,
41
+ orm: baseConfig.orm,
42
+ watch: {
43
+ ...baseConfig.watch,
44
+ // CLI options override config
45
+ ...(options.pollInterval !== undefined && { pollInterval: options.pollInterval }),
46
+ ...(options.debounce !== undefined && { debounce: options.debounce }),
47
+ ...(options.touch !== undefined && { touchFile: options.touch }),
48
+ ...(options.clear !== undefined && { clearScreen: options.clear }),
49
+ },
50
+ };
51
+ if (!mergedConfig.endpoint) {
52
+ console.error('✗ No endpoint specified. Use --endpoint or create a config file with "graphql-codegen init".');
53
+ return null;
54
+ }
55
+ return resolveConfig(mergedConfig);
56
+ }
57
+ program
58
+ .name('graphql-codegen')
59
+ .description('CLI for generating GraphQL SDK from PostGraphile endpoints')
60
+ .version('2.17.48');
61
+ // Init command
62
+ program
63
+ .command('init')
64
+ .description('Initialize a new graphql-codegen configuration file')
65
+ .option('-d, --directory <dir>', 'Target directory for the config file', '.')
66
+ .option('-f, --force', 'Force overwrite existing config', false)
67
+ .option('-e, --endpoint <url>', 'GraphQL endpoint URL to pre-populate')
68
+ .option('-o, --output <dir>', 'Output directory to pre-populate', './generated')
69
+ .action(async (options) => {
70
+ const result = await initCommand({
71
+ directory: options.directory,
72
+ force: options.force,
73
+ endpoint: options.endpoint,
74
+ output: options.output,
75
+ });
76
+ if (result.success) {
77
+ console.log('✓', result.message);
78
+ }
79
+ else {
80
+ console.error('✗', result.message);
81
+ process.exit(1);
82
+ }
83
+ });
84
+ // Generate command
85
+ program
86
+ .command('generate')
87
+ .description('Generate SDK from GraphQL endpoint')
88
+ .option('-c, --config <path>', 'Path to config file')
89
+ .option('-e, --endpoint <url>', 'GraphQL endpoint URL (overrides config)')
90
+ .option('-o, --output <dir>', 'Output directory (overrides config)')
91
+ .option('-a, --authorization <header>', 'Authorization header value')
92
+ .option('-v, --verbose', 'Verbose output', false)
93
+ .option('--dry-run', 'Dry run - show what would be generated without writing files', false)
94
+ .option('-w, --watch', 'Watch mode - poll endpoint for schema changes (in-memory)', false)
95
+ .option('--poll-interval <ms>', 'Polling interval in milliseconds (default: 3000)', parseInt)
96
+ .option('--debounce <ms>', 'Debounce delay before regenerating (default: 800)', parseInt)
97
+ .option('--touch <file>', 'File to touch on schema change')
98
+ .option('--no-clear', 'Do not clear terminal on regeneration')
99
+ .action(async (options) => {
100
+ // Watch mode
101
+ if (options.watch) {
102
+ const config = await loadWatchConfig(options);
103
+ if (!config) {
104
+ process.exit(1);
105
+ }
106
+ await startWatch({
107
+ config,
108
+ generatorType: 'generate',
109
+ verbose: options.verbose,
110
+ authorization: options.authorization,
111
+ outputDir: options.output,
112
+ });
113
+ return;
114
+ }
115
+ // Normal one-shot generation
116
+ const result = await generateCommand({
117
+ config: options.config,
118
+ endpoint: options.endpoint,
119
+ output: options.output,
120
+ authorization: options.authorization,
121
+ verbose: options.verbose,
122
+ dryRun: options.dryRun,
123
+ });
124
+ if (result.success) {
125
+ console.log('✓', result.message);
126
+ if (result.tables && result.tables.length > 0) {
127
+ console.log('\nTables:');
128
+ result.tables.forEach((t) => console.log(` - ${t}`));
129
+ }
130
+ if (result.filesWritten && result.filesWritten.length > 0) {
131
+ console.log('\nFiles written:');
132
+ result.filesWritten.forEach((f) => console.log(` - ${f}`));
133
+ }
134
+ }
135
+ else {
136
+ console.error('✗', result.message);
137
+ if (result.errors) {
138
+ result.errors.forEach((e) => console.error(' -', e));
139
+ }
140
+ process.exit(1);
141
+ }
142
+ });
143
+ // Generate ORM command
144
+ program
145
+ .command('generate-orm')
146
+ .description('Generate Prisma-like ORM client from GraphQL endpoint')
147
+ .option('-c, --config <path>', 'Path to config file')
148
+ .option('-e, --endpoint <url>', 'GraphQL endpoint URL (overrides config)')
149
+ .option('-o, --output <dir>', 'Output directory (overrides config)', './generated/orm')
150
+ .option('-a, --authorization <header>', 'Authorization header value')
151
+ .option('-v, --verbose', 'Verbose output', false)
152
+ .option('--dry-run', 'Dry run - show what would be generated without writing files', false)
153
+ .option('--skip-custom-operations', 'Skip custom operations (only generate table CRUD)', false)
154
+ .option('-w, --watch', 'Watch mode - poll endpoint for schema changes (in-memory)', false)
155
+ .option('--poll-interval <ms>', 'Polling interval in milliseconds (default: 3000)', parseInt)
156
+ .option('--debounce <ms>', 'Debounce delay before regenerating (default: 800)', parseInt)
157
+ .option('--touch <file>', 'File to touch on schema change')
158
+ .option('--no-clear', 'Do not clear terminal on regeneration')
159
+ .action(async (options) => {
160
+ // Watch mode
161
+ if (options.watch) {
162
+ const config = await loadWatchConfig(options);
163
+ if (!config) {
164
+ process.exit(1);
165
+ }
166
+ await startWatch({
167
+ config,
168
+ generatorType: 'generate-orm',
169
+ verbose: options.verbose,
170
+ authorization: options.authorization,
171
+ outputDir: options.output,
172
+ skipCustomOperations: options.skipCustomOperations,
173
+ });
174
+ return;
175
+ }
176
+ // Normal one-shot generation
177
+ const result = await generateOrmCommand({
178
+ config: options.config,
179
+ endpoint: options.endpoint,
180
+ output: options.output,
181
+ authorization: options.authorization,
182
+ verbose: options.verbose,
183
+ dryRun: options.dryRun,
184
+ skipCustomOperations: options.skipCustomOperations,
185
+ });
186
+ if (result.success) {
187
+ console.log('✓', result.message);
188
+ if (result.tables && result.tables.length > 0) {
189
+ console.log('\nTables:');
190
+ result.tables.forEach((t) => console.log(` - ${t}`));
191
+ }
192
+ if (result.customQueries && result.customQueries.length > 0) {
193
+ console.log('\nCustom Queries:');
194
+ result.customQueries.forEach((q) => console.log(` - ${q}`));
195
+ }
196
+ if (result.customMutations && result.customMutations.length > 0) {
197
+ console.log('\nCustom Mutations:');
198
+ result.customMutations.forEach((m) => console.log(` - ${m}`));
199
+ }
200
+ if (result.filesWritten && result.filesWritten.length > 0) {
201
+ console.log('\nFiles written:');
202
+ result.filesWritten.forEach((f) => console.log(` - ${f}`));
203
+ }
204
+ }
205
+ else {
206
+ console.error('✗', result.message);
207
+ if (result.errors) {
208
+ result.errors.forEach((e) => console.error(' -', e));
209
+ }
210
+ process.exit(1);
211
+ }
212
+ });
213
+ // Introspect command (for debugging)
214
+ program
215
+ .command('introspect')
216
+ .description('Introspect a GraphQL endpoint and print table info')
217
+ .requiredOption('-e, --endpoint <url>', 'GraphQL endpoint URL')
218
+ .option('-a, --authorization <header>', 'Authorization header value')
219
+ .option('--json', 'Output as JSON', false)
220
+ .action(async (options) => {
221
+ const { fetchMeta, validateEndpoint } = await import('./introspect/fetch-meta');
222
+ const { transformMetaToCleanTables, getTableNames } = await import('./introspect/transform');
223
+ // Validate endpoint
224
+ const validation = validateEndpoint(options.endpoint);
225
+ if (!validation.valid) {
226
+ console.error('✗ Invalid endpoint:', validation.error);
227
+ process.exit(1);
228
+ }
229
+ console.log('Fetching schema from', options.endpoint, '...');
230
+ const result = await fetchMeta({
231
+ endpoint: options.endpoint,
232
+ authorization: options.authorization,
233
+ });
234
+ if (!result.success) {
235
+ console.error('✗ Failed to fetch schema:', result.error);
236
+ process.exit(1);
237
+ }
238
+ const tables = transformMetaToCleanTables(result.data);
239
+ const tableNames = getTableNames(tables);
240
+ if (options.json) {
241
+ console.log(JSON.stringify(tables, null, 2));
242
+ }
243
+ else {
244
+ console.log(`\n✓ Found ${tables.length} tables:\n`);
245
+ tableNames.forEach((name) => {
246
+ const table = tables.find((t) => t.name === name);
247
+ const fieldCount = table.fields.length;
248
+ const relationCount = table.relations.belongsTo.length +
249
+ table.relations.hasOne.length +
250
+ table.relations.hasMany.length +
251
+ table.relations.manyToMany.length;
252
+ console.log(` ${name} (${fieldCount} fields, ${relationCount} relations)`);
253
+ });
254
+ }
255
+ });
256
+ program.parse();
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Fetch _meta query from a PostGraphile endpoint
3
+ */
4
+ import { type MetaQueryResponse } from './meta-query';
5
+ export interface FetchMetaOptions {
6
+ /** GraphQL endpoint URL */
7
+ endpoint: string;
8
+ /** Optional authorization header value (e.g., "Bearer token") */
9
+ authorization?: string;
10
+ /** Optional additional headers */
11
+ headers?: Record<string, string>;
12
+ /** Request timeout in milliseconds (default: 30000) */
13
+ timeout?: number;
14
+ }
15
+ export interface FetchMetaResult {
16
+ success: boolean;
17
+ data?: MetaQueryResponse;
18
+ error?: string;
19
+ statusCode?: number;
20
+ }
21
+ /**
22
+ * Fetch the _meta query from a PostGraphile endpoint
23
+ */
24
+ export declare function fetchMeta(options: FetchMetaOptions): Promise<FetchMetaResult>;
25
+ /**
26
+ * Validate that an endpoint URL is valid
27
+ */
28
+ export declare function validateEndpoint(endpoint: string): {
29
+ valid: boolean;
30
+ error?: string;
31
+ };
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Fetch _meta query from a PostGraphile endpoint
3
+ */
4
+ import { META_QUERY } from './meta-query';
5
+ /**
6
+ * Fetch the _meta query from a PostGraphile endpoint
7
+ */
8
+ export async function fetchMeta(options) {
9
+ const { endpoint, authorization, headers = {}, timeout = 30000 } = options;
10
+ // Build headers
11
+ const requestHeaders = {
12
+ 'Content-Type': 'application/json',
13
+ Accept: 'application/json',
14
+ ...headers,
15
+ };
16
+ if (authorization) {
17
+ requestHeaders['Authorization'] = authorization;
18
+ }
19
+ // Create abort controller for timeout
20
+ const controller = new AbortController();
21
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
22
+ try {
23
+ const response = await fetch(endpoint, {
24
+ method: 'POST',
25
+ headers: requestHeaders,
26
+ body: JSON.stringify({
27
+ query: META_QUERY,
28
+ variables: {},
29
+ }),
30
+ signal: controller.signal,
31
+ });
32
+ clearTimeout(timeoutId);
33
+ if (!response.ok) {
34
+ return {
35
+ success: false,
36
+ error: `HTTP ${response.status}: ${response.statusText}`,
37
+ statusCode: response.status,
38
+ };
39
+ }
40
+ const json = (await response.json());
41
+ // Check for GraphQL errors
42
+ if (json.errors && json.errors.length > 0) {
43
+ const errorMessages = json.errors.map((e) => e.message).join('; ');
44
+ return {
45
+ success: false,
46
+ error: `GraphQL errors: ${errorMessages}`,
47
+ statusCode: response.status,
48
+ };
49
+ }
50
+ // Check if _meta is present
51
+ if (!json.data?._meta) {
52
+ return {
53
+ success: false,
54
+ error: 'No _meta field in response. Make sure the endpoint has the PostGraphile meta plugin installed.',
55
+ statusCode: response.status,
56
+ };
57
+ }
58
+ return {
59
+ success: true,
60
+ data: json.data,
61
+ statusCode: response.status,
62
+ };
63
+ }
64
+ catch (err) {
65
+ clearTimeout(timeoutId);
66
+ if (err instanceof Error) {
67
+ if (err.name === 'AbortError') {
68
+ return {
69
+ success: false,
70
+ error: `Request timeout after ${timeout}ms`,
71
+ };
72
+ }
73
+ return {
74
+ success: false,
75
+ error: err.message,
76
+ };
77
+ }
78
+ return {
79
+ success: false,
80
+ error: 'Unknown error occurred',
81
+ };
82
+ }
83
+ }
84
+ /**
85
+ * Validate that an endpoint URL is valid
86
+ */
87
+ export function validateEndpoint(endpoint) {
88
+ try {
89
+ const url = new URL(endpoint);
90
+ if (!['http:', 'https:'].includes(url.protocol)) {
91
+ return {
92
+ valid: false,
93
+ error: 'Endpoint must use http or https protocol',
94
+ };
95
+ }
96
+ return { valid: true };
97
+ }
98
+ catch {
99
+ return {
100
+ valid: false,
101
+ error: 'Invalid URL format',
102
+ };
103
+ }
104
+ }
@@ -0,0 +1,21 @@
1
+ import type { IntrospectionQueryResponse } from '../../types/introspection';
2
+ export interface FetchSchemaOptions {
3
+ /** GraphQL endpoint URL */
4
+ endpoint: string;
5
+ /** Optional authorization header value (e.g., "Bearer token") */
6
+ authorization?: string;
7
+ /** Optional additional headers */
8
+ headers?: Record<string, string>;
9
+ /** Request timeout in milliseconds (default: 30000) */
10
+ timeout?: number;
11
+ }
12
+ export interface FetchSchemaResult {
13
+ success: boolean;
14
+ data?: IntrospectionQueryResponse;
15
+ error?: string;
16
+ statusCode?: number;
17
+ }
18
+ /**
19
+ * Fetch the full schema introspection from a GraphQL endpoint
20
+ */
21
+ export declare function fetchSchema(options: FetchSchemaOptions): Promise<FetchSchemaResult>;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Fetch GraphQL schema introspection from an endpoint
3
+ */
4
+ import { SCHEMA_INTROSPECTION_QUERY } from './schema-query';
5
+ /**
6
+ * Fetch the full schema introspection from a GraphQL endpoint
7
+ */
8
+ export async function fetchSchema(options) {
9
+ const { endpoint, authorization, headers = {}, timeout = 30000 } = options;
10
+ // Build headers
11
+ const requestHeaders = {
12
+ 'Content-Type': 'application/json',
13
+ Accept: 'application/json',
14
+ ...headers,
15
+ };
16
+ if (authorization) {
17
+ requestHeaders['Authorization'] = authorization;
18
+ }
19
+ // Create abort controller for timeout
20
+ const controller = new AbortController();
21
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
22
+ try {
23
+ const response = await fetch(endpoint, {
24
+ method: 'POST',
25
+ headers: requestHeaders,
26
+ body: JSON.stringify({
27
+ query: SCHEMA_INTROSPECTION_QUERY,
28
+ variables: {},
29
+ }),
30
+ signal: controller.signal,
31
+ });
32
+ clearTimeout(timeoutId);
33
+ if (!response.ok) {
34
+ return {
35
+ success: false,
36
+ error: `HTTP ${response.status}: ${response.statusText}`,
37
+ statusCode: response.status,
38
+ };
39
+ }
40
+ const json = (await response.json());
41
+ // Check for GraphQL errors
42
+ if (json.errors && json.errors.length > 0) {
43
+ const errorMessages = json.errors.map((e) => e.message).join('; ');
44
+ return {
45
+ success: false,
46
+ error: `GraphQL errors: ${errorMessages}`,
47
+ statusCode: response.status,
48
+ };
49
+ }
50
+ // Check if __schema is present
51
+ if (!json.data?.__schema) {
52
+ return {
53
+ success: false,
54
+ error: 'No __schema field in response. Introspection may be disabled on this endpoint.',
55
+ statusCode: response.status,
56
+ };
57
+ }
58
+ return {
59
+ success: true,
60
+ data: json.data,
61
+ statusCode: response.status,
62
+ };
63
+ }
64
+ catch (err) {
65
+ clearTimeout(timeoutId);
66
+ if (err instanceof Error) {
67
+ if (err.name === 'AbortError') {
68
+ return {
69
+ success: false,
70
+ error: `Request timeout after ${timeout}ms`,
71
+ };
72
+ }
73
+ return {
74
+ success: false,
75
+ error: err.message,
76
+ };
77
+ }
78
+ return {
79
+ success: false,
80
+ error: 'Unknown error occurred',
81
+ };
82
+ }
83
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Introspection module exports
3
+ */
4
+ export { META_QUERY } from './meta-query';
5
+ export type { MetaQueryResponse, MetaTable, MetaField, MetaFieldType, MetaConstraint, MetaForeignKeyConstraint, MetaTableQuery, MetaTableInflection, MetaBelongsToRelation, MetaHasRelation, MetaManyToManyRelation, MetaTableRelations, } from './meta-query';
6
+ export { fetchMeta, validateEndpoint } from './fetch-meta';
7
+ export type { FetchMetaOptions, FetchMetaResult } from './fetch-meta';
8
+ export { transformMetaToCleanTables, getTableNames, findTable, filterTables, } from './transform';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Introspection module exports
3
+ */
4
+ export { META_QUERY } from './meta-query';
5
+ export { fetchMeta, validateEndpoint } from './fetch-meta';
6
+ export { transformMetaToCleanTables, getTableNames, findTable, filterTables, } from './transform';
@@ -0,0 +1,111 @@
1
+ /**
2
+ * The _meta GraphQL query for introspecting PostGraphile schema
3
+ * This query fetches all table metadata including fields, constraints, and relations
4
+ */
5
+ export declare const META_QUERY = "\nquery Meta {\n _meta {\n tables {\n name\n query {\n all\n create\n delete\n one\n update\n }\n fields {\n name\n type {\n gqlType\n isArray\n modifier\n pgAlias\n pgType\n subtype\n typmod\n }\n }\n inflection {\n allRows\n allRowsSimple\n conditionType\n connection\n createField\n createInputType\n createPayloadType\n deleteByPrimaryKey\n deletePayloadType\n edge\n edgeField\n enumType\n filterType\n inputType\n orderByType\n patchField\n patchType\n tableFieldName\n tableType\n typeName\n updateByPrimaryKey\n updatePayloadType\n }\n primaryKeyConstraints {\n name\n fields {\n name\n type {\n gqlType\n isArray\n modifier\n pgAlias\n pgType\n subtype\n typmod\n }\n }\n }\n uniqueConstraints {\n name\n fields {\n name\n type {\n gqlType\n isArray\n modifier\n pgAlias\n pgType\n subtype\n typmod\n }\n }\n }\n foreignKeyConstraints {\n name\n fields {\n name\n type {\n gqlType\n isArray\n modifier\n pgAlias\n pgType\n subtype\n typmod\n }\n }\n refFields {\n name\n type {\n gqlType\n isArray\n modifier\n pgAlias\n pgType\n subtype\n typmod\n }\n }\n refTable {\n name\n }\n }\n relations {\n belongsTo {\n fieldName\n isUnique\n keys {\n name\n type {\n gqlType\n isArray\n modifier\n pgAlias\n pgType\n subtype\n typmod\n }\n }\n references {\n name\n }\n type\n }\n hasOne {\n fieldName\n isUnique\n keys {\n name\n type {\n gqlType\n isArray\n modifier\n pgAlias\n pgType\n subtype\n typmod\n }\n }\n referencedBy {\n name\n }\n type\n }\n hasMany {\n fieldName\n isUnique\n keys {\n name\n type {\n gqlType\n isArray\n modifier\n pgAlias\n pgType\n subtype\n typmod\n }\n }\n referencedBy {\n name\n }\n type\n }\n manyToMany {\n fieldName\n junctionTable {\n name\n }\n rightTable {\n name\n }\n type\n }\n }\n }\n }\n}\n";
6
+ /**
7
+ * Types for the _meta query response
8
+ */
9
+ export interface MetaFieldType {
10
+ gqlType: string;
11
+ isArray: boolean;
12
+ modifier: string | number | null;
13
+ pgAlias: string | null;
14
+ pgType: string | null;
15
+ subtype: string | null;
16
+ typmod: number | null;
17
+ }
18
+ export interface MetaField {
19
+ name: string;
20
+ type: MetaFieldType;
21
+ }
22
+ export interface MetaConstraint {
23
+ name: string;
24
+ fields: MetaField[];
25
+ }
26
+ export interface MetaForeignKeyConstraint extends MetaConstraint {
27
+ refFields: MetaField[];
28
+ refTable: {
29
+ name: string;
30
+ };
31
+ }
32
+ export interface MetaTableQuery {
33
+ all: string;
34
+ create: string;
35
+ delete: string | null;
36
+ one: string;
37
+ update: string | null;
38
+ }
39
+ export interface MetaTableInflection {
40
+ allRows: string;
41
+ allRowsSimple: string;
42
+ conditionType: string;
43
+ connection: string;
44
+ createField: string;
45
+ createInputType: string;
46
+ createPayloadType: string;
47
+ deleteByPrimaryKey: string | null;
48
+ deletePayloadType: string;
49
+ edge: string;
50
+ edgeField: string;
51
+ enumType: string;
52
+ filterType: string | null;
53
+ inputType: string;
54
+ orderByType: string;
55
+ patchField: string;
56
+ patchType: string | null;
57
+ tableFieldName: string;
58
+ tableType: string;
59
+ typeName: string;
60
+ updateByPrimaryKey: string | null;
61
+ updatePayloadType: string | null;
62
+ }
63
+ export interface MetaBelongsToRelation {
64
+ fieldName: string | null;
65
+ isUnique: boolean;
66
+ keys: MetaField[];
67
+ references: {
68
+ name: string;
69
+ };
70
+ type: string | null;
71
+ }
72
+ export interface MetaHasRelation {
73
+ fieldName: string | null;
74
+ isUnique: boolean;
75
+ keys: MetaField[];
76
+ referencedBy: {
77
+ name: string;
78
+ };
79
+ type: string | null;
80
+ }
81
+ export interface MetaManyToManyRelation {
82
+ fieldName: string | null;
83
+ junctionTable: {
84
+ name: string;
85
+ };
86
+ rightTable: {
87
+ name: string;
88
+ };
89
+ type: string | null;
90
+ }
91
+ export interface MetaTableRelations {
92
+ belongsTo: MetaBelongsToRelation[];
93
+ hasOne: MetaHasRelation[];
94
+ hasMany: MetaHasRelation[];
95
+ manyToMany: MetaManyToManyRelation[];
96
+ }
97
+ export interface MetaTable {
98
+ name: string;
99
+ query: MetaTableQuery;
100
+ fields: MetaField[];
101
+ inflection: MetaTableInflection;
102
+ primaryKeyConstraints: MetaConstraint[];
103
+ uniqueConstraints: MetaConstraint[];
104
+ foreignKeyConstraints: MetaForeignKeyConstraint[];
105
+ relations: MetaTableRelations;
106
+ }
107
+ export interface MetaQueryResponse {
108
+ _meta: {
109
+ tables: MetaTable[];
110
+ };
111
+ }