@constructive-io/graphql-codegen 2.32.0 → 3.0.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 (270) hide show
  1. package/README.md +429 -1691
  2. package/cli/index.d.ts +5 -2
  3. package/cli/index.js +98 -581
  4. package/cli/shared.d.ts +35 -0
  5. package/cli/shared.js +106 -0
  6. package/{esm/cli → core}/codegen/barrel.d.ts +1 -1
  7. package/{cli → core}/codegen/barrel.js +1 -4
  8. package/{esm/cli → core}/codegen/index.d.ts +15 -5
  9. package/{cli → core}/codegen/index.js +44 -24
  10. package/{cli → core}/codegen/invalidation.d.ts +2 -2
  11. package/{esm/cli → core}/codegen/mutation-keys.d.ts +2 -2
  12. package/{cli → core}/codegen/orm/client-generator.js +2 -3
  13. package/{esm/cli → core}/codegen/orm/index.d.ts +9 -2
  14. package/{cli → core}/codegen/orm/index.js +3 -2
  15. package/{cli → core}/codegen/query-keys.d.ts +2 -2
  16. package/core/codegen/shared/index.d.ts +39 -0
  17. package/core/codegen/shared/index.js +118 -0
  18. package/core/config/index.d.ts +5 -0
  19. package/core/config/index.js +13 -0
  20. package/core/config/loader.d.ts +18 -0
  21. package/{cli/commands/init.js → core/config/loader.js} +7 -94
  22. package/core/config/resolver.d.ts +46 -0
  23. package/core/config/resolver.js +104 -0
  24. package/core/database/index.d.ts +43 -0
  25. package/core/database/index.js +85 -0
  26. package/core/generate.d.ts +22 -0
  27. package/core/generate.js +192 -0
  28. package/core/index.d.ts +13 -1
  29. package/core/index.js +22 -2
  30. package/{cli → core}/introspect/fetch-schema.js +58 -9
  31. package/core/introspect/source/api-schemas.d.ts +44 -0
  32. package/core/introspect/source/api-schemas.js +122 -0
  33. package/core/introspect/source/database.d.ts +32 -0
  34. package/core/introspect/source/database.js +91 -0
  35. package/core/introspect/source/index.d.ts +112 -0
  36. package/core/introspect/source/index.js +173 -0
  37. package/core/introspect/source/pgpm-module.d.ts +83 -0
  38. package/core/introspect/source/pgpm-module.js +200 -0
  39. package/core/output/index.d.ts +4 -0
  40. package/core/output/index.js +9 -0
  41. package/core/output/writer.d.ts +38 -0
  42. package/core/output/writer.js +156 -0
  43. package/{cli/commands/shared.d.ts → core/pipeline/index.d.ts} +5 -3
  44. package/{cli/commands/shared.js → core/pipeline/index.js} +4 -0
  45. package/{cli → core}/watch/orchestrator.d.ts +25 -3
  46. package/{cli → core}/watch/orchestrator.js +35 -27
  47. package/{cli → core}/watch/types.d.ts +1 -1
  48. package/esm/cli/index.d.ts +5 -2
  49. package/esm/cli/index.js +97 -547
  50. package/esm/cli/shared.d.ts +35 -0
  51. package/esm/cli/shared.js +101 -0
  52. package/{cli → esm/core}/codegen/barrel.d.ts +1 -1
  53. package/esm/{cli → core}/codegen/barrel.js +1 -4
  54. package/{cli → esm/core}/codegen/index.d.ts +15 -5
  55. package/esm/{cli → core}/codegen/index.js +44 -24
  56. package/esm/{cli → core}/codegen/invalidation.d.ts +2 -2
  57. package/{cli → esm/core}/codegen/mutation-keys.d.ts +2 -2
  58. package/esm/{cli → core}/codegen/orm/client-generator.js +2 -3
  59. package/{cli → esm/core}/codegen/orm/index.d.ts +9 -2
  60. package/esm/{cli → core}/codegen/orm/index.js +3 -2
  61. package/esm/{cli → core}/codegen/query-keys.d.ts +2 -2
  62. package/esm/core/codegen/shared/index.d.ts +39 -0
  63. package/esm/core/codegen/shared/index.js +79 -0
  64. package/esm/core/config/index.d.ts +5 -0
  65. package/esm/core/config/index.js +5 -0
  66. package/esm/core/config/loader.d.ts +18 -0
  67. package/esm/core/config/loader.js +71 -0
  68. package/esm/core/config/resolver.d.ts +46 -0
  69. package/esm/core/config/resolver.js +100 -0
  70. package/esm/core/database/index.d.ts +43 -0
  71. package/esm/core/database/index.js +48 -0
  72. package/esm/core/generate.d.ts +22 -0
  73. package/esm/core/generate.js +186 -0
  74. package/esm/core/index.d.ts +13 -1
  75. package/esm/core/index.js +20 -1
  76. package/esm/{cli → core}/introspect/fetch-schema.js +55 -9
  77. package/esm/core/introspect/source/api-schemas.d.ts +44 -0
  78. package/esm/core/introspect/source/api-schemas.js +117 -0
  79. package/esm/core/introspect/source/database.d.ts +32 -0
  80. package/esm/core/introspect/source/database.js +87 -0
  81. package/esm/core/introspect/source/index.d.ts +112 -0
  82. package/esm/core/introspect/source/index.js +154 -0
  83. package/esm/core/introspect/source/pgpm-module.d.ts +83 -0
  84. package/esm/core/introspect/source/pgpm-module.js +194 -0
  85. package/esm/core/output/index.d.ts +4 -0
  86. package/esm/core/output/index.js +4 -0
  87. package/esm/core/output/writer.d.ts +38 -0
  88. package/esm/core/output/writer.js +119 -0
  89. package/esm/{cli/commands/shared.d.ts → core/pipeline/index.d.ts} +5 -3
  90. package/esm/{cli/commands/shared.js → core/pipeline/index.js} +1 -0
  91. package/esm/{cli → core}/watch/orchestrator.d.ts +25 -3
  92. package/esm/{cli → core}/watch/orchestrator.js +35 -27
  93. package/esm/{cli → core}/watch/types.d.ts +1 -1
  94. package/esm/index.d.ts +8 -3
  95. package/esm/index.js +9 -3
  96. package/esm/types/config.d.ts +101 -138
  97. package/esm/types/config.js +8 -35
  98. package/esm/types/index.d.ts +2 -2
  99. package/esm/types/index.js +1 -1
  100. package/index.d.ts +8 -3
  101. package/index.js +18 -8
  102. package/package.json +18 -11
  103. package/types/config.d.ts +101 -138
  104. package/types/config.js +9 -38
  105. package/types/index.d.ts +2 -2
  106. package/types/index.js +3 -3
  107. package/cli/commands/generate-orm.d.ts +0 -53
  108. package/cli/commands/generate-orm.js +0 -292
  109. package/cli/commands/generate.d.ts +0 -66
  110. package/cli/commands/generate.js +0 -431
  111. package/cli/commands/index.d.ts +0 -9
  112. package/cli/commands/index.js +0 -14
  113. package/cli/commands/init.d.ts +0 -35
  114. package/cli/introspect/source/index.d.ts +0 -48
  115. package/cli/introspect/source/index.js +0 -72
  116. package/esm/cli/commands/generate-orm.d.ts +0 -53
  117. package/esm/cli/commands/generate-orm.js +0 -289
  118. package/esm/cli/commands/generate.d.ts +0 -66
  119. package/esm/cli/commands/generate.js +0 -393
  120. package/esm/cli/commands/index.d.ts +0 -9
  121. package/esm/cli/commands/index.js +0 -6
  122. package/esm/cli/commands/init.d.ts +0 -35
  123. package/esm/cli/commands/init.js +0 -158
  124. package/esm/cli/introspect/source/index.d.ts +0 -48
  125. package/esm/cli/introspect/source/index.js +0 -54
  126. /package/{cli → core}/codegen/babel-ast.d.ts +0 -0
  127. /package/{cli → core}/codegen/babel-ast.js +0 -0
  128. /package/{cli → core}/codegen/client.d.ts +0 -0
  129. /package/{cli → core}/codegen/client.js +0 -0
  130. /package/{cli → core}/codegen/custom-mutations.d.ts +0 -0
  131. /package/{cli → core}/codegen/custom-mutations.js +0 -0
  132. /package/{cli → core}/codegen/custom-queries.d.ts +0 -0
  133. /package/{cli → core}/codegen/custom-queries.js +0 -0
  134. /package/{cli → core}/codegen/gql-ast.d.ts +0 -0
  135. /package/{cli → core}/codegen/gql-ast.js +0 -0
  136. /package/{cli → core}/codegen/invalidation.js +0 -0
  137. /package/{cli → core}/codegen/mutation-keys.js +0 -0
  138. /package/{cli → core}/codegen/mutations.d.ts +0 -0
  139. /package/{cli → core}/codegen/mutations.js +0 -0
  140. /package/{cli → core}/codegen/orm/barrel.d.ts +0 -0
  141. /package/{cli → core}/codegen/orm/barrel.js +0 -0
  142. /package/{cli → core}/codegen/orm/client-generator.d.ts +0 -0
  143. /package/{cli → core}/codegen/orm/client.d.ts +0 -0
  144. /package/{cli → core}/codegen/orm/client.js +0 -0
  145. /package/{cli → core}/codegen/orm/custom-ops-generator.d.ts +0 -0
  146. /package/{cli → core}/codegen/orm/custom-ops-generator.js +0 -0
  147. /package/{cli → core}/codegen/orm/input-types-generator.d.ts +0 -0
  148. /package/{cli → core}/codegen/orm/input-types-generator.js +0 -0
  149. /package/{cli → core}/codegen/orm/model-generator.d.ts +0 -0
  150. /package/{cli → core}/codegen/orm/model-generator.js +0 -0
  151. /package/{cli → core}/codegen/orm/query-builder.d.ts +0 -0
  152. /package/{cli → core}/codegen/orm/query-builder.js +0 -0
  153. /package/{cli → core}/codegen/orm/query-builder.ts +0 -0
  154. /package/{cli → core}/codegen/orm/select-types.d.ts +0 -0
  155. /package/{cli → core}/codegen/orm/select-types.js +0 -0
  156. /package/{cli → core}/codegen/queries.d.ts +0 -0
  157. /package/{cli → core}/codegen/queries.js +0 -0
  158. /package/{cli → core}/codegen/query-keys.js +0 -0
  159. /package/{cli → core}/codegen/scalars.d.ts +0 -0
  160. /package/{cli → core}/codegen/scalars.js +0 -0
  161. /package/{cli → core}/codegen/schema-gql-ast.d.ts +0 -0
  162. /package/{cli → core}/codegen/schema-gql-ast.js +0 -0
  163. /package/{cli → core}/codegen/schema-types-generator.d.ts +0 -0
  164. /package/{cli → core}/codegen/schema-types-generator.js +0 -0
  165. /package/{cli → core}/codegen/type-resolver.d.ts +0 -0
  166. /package/{cli → core}/codegen/type-resolver.js +0 -0
  167. /package/{cli → core}/codegen/types.d.ts +0 -0
  168. /package/{cli → core}/codegen/types.js +0 -0
  169. /package/{cli → core}/codegen/utils.d.ts +0 -0
  170. /package/{cli → core}/codegen/utils.js +0 -0
  171. /package/{cli → core}/introspect/fetch-schema.d.ts +0 -0
  172. /package/{cli → core}/introspect/index.d.ts +0 -0
  173. /package/{cli → core}/introspect/index.js +0 -0
  174. /package/{cli → core}/introspect/infer-tables.d.ts +0 -0
  175. /package/{cli → core}/introspect/infer-tables.js +0 -0
  176. /package/{cli → core}/introspect/schema-query.d.ts +0 -0
  177. /package/{cli → core}/introspect/schema-query.js +0 -0
  178. /package/{cli → core}/introspect/source/endpoint.d.ts +0 -0
  179. /package/{cli → core}/introspect/source/endpoint.js +0 -0
  180. /package/{cli → core}/introspect/source/file.d.ts +0 -0
  181. /package/{cli → core}/introspect/source/file.js +0 -0
  182. /package/{cli → core}/introspect/source/types.d.ts +0 -0
  183. /package/{cli → core}/introspect/source/types.js +0 -0
  184. /package/{cli → core}/introspect/transform-schema.d.ts +0 -0
  185. /package/{cli → core}/introspect/transform-schema.js +0 -0
  186. /package/{cli → core}/introspect/transform.d.ts +0 -0
  187. /package/{cli → core}/introspect/transform.js +0 -0
  188. /package/{cli → core}/watch/cache.d.ts +0 -0
  189. /package/{cli → core}/watch/cache.js +0 -0
  190. /package/{cli → core}/watch/debounce.d.ts +0 -0
  191. /package/{cli → core}/watch/debounce.js +0 -0
  192. /package/{cli → core}/watch/hash.d.ts +0 -0
  193. /package/{cli → core}/watch/hash.js +0 -0
  194. /package/{cli → core}/watch/index.d.ts +0 -0
  195. /package/{cli → core}/watch/index.js +0 -0
  196. /package/{cli → core}/watch/poller.d.ts +0 -0
  197. /package/{cli → core}/watch/poller.js +0 -0
  198. /package/{cli → core}/watch/types.js +0 -0
  199. /package/esm/{cli → core}/codegen/babel-ast.d.ts +0 -0
  200. /package/esm/{cli → core}/codegen/babel-ast.js +0 -0
  201. /package/esm/{cli → core}/codegen/client.d.ts +0 -0
  202. /package/esm/{cli → core}/codegen/client.js +0 -0
  203. /package/esm/{cli → core}/codegen/custom-mutations.d.ts +0 -0
  204. /package/esm/{cli → core}/codegen/custom-mutations.js +0 -0
  205. /package/esm/{cli → core}/codegen/custom-queries.d.ts +0 -0
  206. /package/esm/{cli → core}/codegen/custom-queries.js +0 -0
  207. /package/esm/{cli → core}/codegen/gql-ast.d.ts +0 -0
  208. /package/esm/{cli → core}/codegen/gql-ast.js +0 -0
  209. /package/esm/{cli → core}/codegen/invalidation.js +0 -0
  210. /package/esm/{cli → core}/codegen/mutation-keys.js +0 -0
  211. /package/esm/{cli → core}/codegen/mutations.d.ts +0 -0
  212. /package/esm/{cli → core}/codegen/mutations.js +0 -0
  213. /package/esm/{cli → core}/codegen/orm/barrel.d.ts +0 -0
  214. /package/esm/{cli → core}/codegen/orm/barrel.js +0 -0
  215. /package/esm/{cli → core}/codegen/orm/client-generator.d.ts +0 -0
  216. /package/esm/{cli → core}/codegen/orm/client.d.ts +0 -0
  217. /package/esm/{cli → core}/codegen/orm/client.js +0 -0
  218. /package/esm/{cli → core}/codegen/orm/custom-ops-generator.d.ts +0 -0
  219. /package/esm/{cli → core}/codegen/orm/custom-ops-generator.js +0 -0
  220. /package/esm/{cli → core}/codegen/orm/input-types-generator.d.ts +0 -0
  221. /package/esm/{cli → core}/codegen/orm/input-types-generator.js +0 -0
  222. /package/esm/{cli → core}/codegen/orm/model-generator.d.ts +0 -0
  223. /package/esm/{cli → core}/codegen/orm/model-generator.js +0 -0
  224. /package/esm/{cli → core}/codegen/orm/query-builder.d.ts +0 -0
  225. /package/esm/{cli → core}/codegen/orm/query-builder.js +0 -0
  226. /package/esm/{cli → core}/codegen/orm/select-types.d.ts +0 -0
  227. /package/esm/{cli → core}/codegen/orm/select-types.js +0 -0
  228. /package/esm/{cli → core}/codegen/queries.d.ts +0 -0
  229. /package/esm/{cli → core}/codegen/queries.js +0 -0
  230. /package/esm/{cli → core}/codegen/query-keys.js +0 -0
  231. /package/esm/{cli → core}/codegen/scalars.d.ts +0 -0
  232. /package/esm/{cli → core}/codegen/scalars.js +0 -0
  233. /package/esm/{cli → core}/codegen/schema-gql-ast.d.ts +0 -0
  234. /package/esm/{cli → core}/codegen/schema-gql-ast.js +0 -0
  235. /package/esm/{cli → core}/codegen/schema-types-generator.d.ts +0 -0
  236. /package/esm/{cli → core}/codegen/schema-types-generator.js +0 -0
  237. /package/esm/{cli → core}/codegen/type-resolver.d.ts +0 -0
  238. /package/esm/{cli → core}/codegen/type-resolver.js +0 -0
  239. /package/esm/{cli → core}/codegen/types.d.ts +0 -0
  240. /package/esm/{cli → core}/codegen/types.js +0 -0
  241. /package/esm/{cli → core}/codegen/utils.d.ts +0 -0
  242. /package/esm/{cli → core}/codegen/utils.js +0 -0
  243. /package/esm/{cli → core}/introspect/fetch-schema.d.ts +0 -0
  244. /package/esm/{cli → core}/introspect/index.d.ts +0 -0
  245. /package/esm/{cli → core}/introspect/index.js +0 -0
  246. /package/esm/{cli → core}/introspect/infer-tables.d.ts +0 -0
  247. /package/esm/{cli → core}/introspect/infer-tables.js +0 -0
  248. /package/esm/{cli → core}/introspect/schema-query.d.ts +0 -0
  249. /package/esm/{cli → core}/introspect/schema-query.js +0 -0
  250. /package/esm/{cli → core}/introspect/source/endpoint.d.ts +0 -0
  251. /package/esm/{cli → core}/introspect/source/endpoint.js +0 -0
  252. /package/esm/{cli → core}/introspect/source/file.d.ts +0 -0
  253. /package/esm/{cli → core}/introspect/source/file.js +0 -0
  254. /package/esm/{cli → core}/introspect/source/types.d.ts +0 -0
  255. /package/esm/{cli → core}/introspect/source/types.js +0 -0
  256. /package/esm/{cli → core}/introspect/transform-schema.d.ts +0 -0
  257. /package/esm/{cli → core}/introspect/transform-schema.js +0 -0
  258. /package/esm/{cli → core}/introspect/transform.d.ts +0 -0
  259. /package/esm/{cli → core}/introspect/transform.js +0 -0
  260. /package/esm/{cli → core}/watch/cache.d.ts +0 -0
  261. /package/esm/{cli → core}/watch/cache.js +0 -0
  262. /package/esm/{cli → core}/watch/debounce.d.ts +0 -0
  263. /package/esm/{cli → core}/watch/debounce.js +0 -0
  264. /package/esm/{cli → core}/watch/hash.d.ts +0 -0
  265. /package/esm/{cli → core}/watch/hash.js +0 -0
  266. /package/esm/{cli → core}/watch/index.d.ts +0 -0
  267. /package/esm/{cli → core}/watch/index.js +0 -0
  268. /package/esm/{cli → core}/watch/poller.d.ts +0 -0
  269. /package/esm/{cli → core}/watch/poller.js +0 -0
  270. /package/esm/{cli → core}/watch/types.js +0 -0
@@ -0,0 +1,100 @@
1
+ import { mergeConfig, getConfigOptions } from '../../types/config';
2
+ import { findConfigFile, loadConfigFile } from './loader';
3
+ /**
4
+ * Load and resolve configuration from file and/or options
5
+ *
6
+ * This is the main entry point for configuration loading. It:
7
+ * 1. Finds and loads the config file (if any)
8
+ * 2. Applies CLI option overrides
9
+ * 3. Returns fully resolved configuration ready for use
10
+ */
11
+ export async function loadAndResolveConfig(options) {
12
+ // Destructure CLI-only fields, rest is config overrides
13
+ const { config: configPath, ...overrides } = options;
14
+ // Validate that at most one source is specified
15
+ const sources = [
16
+ overrides.endpoint,
17
+ overrides.schemaFile,
18
+ overrides.db,
19
+ ].filter(Boolean);
20
+ if (sources.length > 1) {
21
+ return {
22
+ success: false,
23
+ error: 'Multiple sources specified. Use only one of: endpoint, schemaFile, or db.',
24
+ };
25
+ }
26
+ // Find config file
27
+ let resolvedConfigPath = configPath;
28
+ if (!resolvedConfigPath) {
29
+ resolvedConfigPath = findConfigFile() ?? undefined;
30
+ }
31
+ let baseConfig = {};
32
+ if (resolvedConfigPath) {
33
+ const loadResult = await loadConfigFile(resolvedConfigPath);
34
+ if (!loadResult.success) {
35
+ return { success: false, error: loadResult.error };
36
+ }
37
+ baseConfig = loadResult.config;
38
+ }
39
+ const mergedConfig = mergeConfig(baseConfig, overrides);
40
+ // Check if we have a source (endpoint, schemaFile, or db)
41
+ const hasSource = mergedConfig.endpoint ||
42
+ mergedConfig.schemaFile ||
43
+ mergedConfig.db;
44
+ if (!hasSource) {
45
+ return {
46
+ success: false,
47
+ error: 'No source specified. Use --endpoint, --schema-file, or --db, or create a config file with "graphql-codegen init".',
48
+ };
49
+ }
50
+ return {
51
+ success: true,
52
+ config: getConfigOptions(mergedConfig),
53
+ };
54
+ }
55
+ /**
56
+ * Build watch configuration from options
57
+ *
58
+ * Used by watch mode to resolve configuration with watch-specific overrides.
59
+ */
60
+ export async function loadWatchConfig(options) {
61
+ let configPath = options.config;
62
+ if (!configPath) {
63
+ configPath = findConfigFile() ?? undefined;
64
+ }
65
+ let baseConfig = {};
66
+ if (configPath) {
67
+ const loadResult = await loadConfigFile(configPath);
68
+ if (!loadResult.success) {
69
+ console.error('x', loadResult.error);
70
+ return null;
71
+ }
72
+ baseConfig = loadResult.config;
73
+ }
74
+ const sourceOverrides = {};
75
+ if (options.endpoint) {
76
+ sourceOverrides.endpoint = options.endpoint;
77
+ sourceOverrides.schemaFile = undefined;
78
+ }
79
+ const watchOverrides = {
80
+ watch: {
81
+ ...(options.pollInterval !== undefined && {
82
+ pollInterval: options.pollInterval,
83
+ }),
84
+ ...(options.debounce !== undefined && { debounce: options.debounce }),
85
+ ...(options.touch !== undefined && { touchFile: options.touch }),
86
+ ...(options.clear !== undefined && { clearScreen: options.clear }),
87
+ },
88
+ };
89
+ let mergedConfig = mergeConfig(baseConfig, sourceOverrides);
90
+ mergedConfig = mergeConfig(mergedConfig, watchOverrides);
91
+ if (!mergedConfig.endpoint) {
92
+ console.error('x No endpoint specified. Watch mode only supports live endpoints.');
93
+ return null;
94
+ }
95
+ if (mergedConfig.schemaFile) {
96
+ console.error('x Watch mode is only supported with an endpoint, not schemaFile.');
97
+ return null;
98
+ }
99
+ return getConfigOptions(mergedConfig);
100
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Database schema utilities
3
+ *
4
+ * Provides functions for building GraphQL schemas directly from PostgreSQL databases.
5
+ */
6
+ export interface BuildSchemaFromDatabaseOptions {
7
+ /** Database name */
8
+ database: string;
9
+ /** PostgreSQL schemas to include */
10
+ schemas: string[];
11
+ /** Output directory for the schema file */
12
+ outDir: string;
13
+ /** Optional filename (default: schema.graphql) */
14
+ filename?: string;
15
+ }
16
+ export interface BuildSchemaFromDatabaseResult {
17
+ /** Path to the generated schema file */
18
+ schemaPath: string;
19
+ /** The SDL content */
20
+ sdl: string;
21
+ }
22
+ /**
23
+ * Build a GraphQL schema from a PostgreSQL database and write it to a file.
24
+ *
25
+ * This function introspects the database using PostGraphile and generates
26
+ * a GraphQL SDL file that can be used for code generation.
27
+ *
28
+ * @param options - Configuration options
29
+ * @returns The path to the generated schema file and the SDL content
30
+ */
31
+ export declare function buildSchemaFromDatabase(options: BuildSchemaFromDatabaseOptions): Promise<BuildSchemaFromDatabaseResult>;
32
+ /**
33
+ * Build a GraphQL schema SDL string from a PostgreSQL database without writing to file.
34
+ *
35
+ * This is a convenience wrapper around buildSchemaSDL from graphql-server.
36
+ *
37
+ * @param options - Configuration options
38
+ * @returns The SDL content as a string
39
+ */
40
+ export declare function buildSchemaSDLFromDatabase(options: {
41
+ database: string;
42
+ schemas: string[];
43
+ }): Promise<string>;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Database schema utilities
3
+ *
4
+ * Provides functions for building GraphQL schemas directly from PostgreSQL databases.
5
+ */
6
+ import * as fs from 'node:fs';
7
+ import * as path from 'node:path';
8
+ import { buildSchemaSDL } from '@constructive-io/graphql-server';
9
+ /**
10
+ * Build a GraphQL schema from a PostgreSQL database and write it to a file.
11
+ *
12
+ * This function introspects the database using PostGraphile and generates
13
+ * a GraphQL SDL file that can be used for code generation.
14
+ *
15
+ * @param options - Configuration options
16
+ * @returns The path to the generated schema file and the SDL content
17
+ */
18
+ export async function buildSchemaFromDatabase(options) {
19
+ const { database, schemas, outDir, filename = 'schema.graphql' } = options;
20
+ // Ensure output directory exists
21
+ await fs.promises.mkdir(outDir, { recursive: true });
22
+ // Build schema SDL from database
23
+ const sdl = await buildSchemaSDL({
24
+ database,
25
+ schemas,
26
+ graphile: { pgSettings: async () => ({ role: 'administrator' }) },
27
+ });
28
+ // Write schema to file
29
+ const schemaPath = path.join(outDir, filename);
30
+ await fs.promises.writeFile(schemaPath, sdl, 'utf-8');
31
+ return { schemaPath, sdl };
32
+ }
33
+ /**
34
+ * Build a GraphQL schema SDL string from a PostgreSQL database without writing to file.
35
+ *
36
+ * This is a convenience wrapper around buildSchemaSDL from graphql-server.
37
+ *
38
+ * @param options - Configuration options
39
+ * @returns The SDL content as a string
40
+ */
41
+ export async function buildSchemaSDLFromDatabase(options) {
42
+ const { database, schemas } = options;
43
+ return buildSchemaSDL({
44
+ database,
45
+ schemas,
46
+ graphile: { pgSettings: async () => ({ role: 'administrator' }) },
47
+ });
48
+ }
@@ -0,0 +1,22 @@
1
+ import type { GraphQLSDKConfigTarget } from '../types/config';
2
+ export interface GenerateOptions extends GraphQLSDKConfigTarget {
3
+ authorization?: string;
4
+ verbose?: boolean;
5
+ dryRun?: boolean;
6
+ skipCustomOperations?: boolean;
7
+ }
8
+ export interface GenerateResult {
9
+ success: boolean;
10
+ message: string;
11
+ output?: string;
12
+ tables?: string[];
13
+ filesWritten?: string[];
14
+ errors?: string[];
15
+ }
16
+ /**
17
+ * Main generate function - takes a single config and generates code
18
+ *
19
+ * This is the primary entry point for programmatic usage.
20
+ * For multiple configs, call this function in a loop.
21
+ */
22
+ export declare function generate(options?: GenerateOptions): Promise<GenerateResult>;
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Main generate function - orchestrates the entire codegen pipeline
3
+ *
4
+ * This is the primary entry point for programmatic usage.
5
+ * The CLI is a thin wrapper around this function.
6
+ */
7
+ import path from 'path';
8
+ import { createSchemaSource, validateSourceOptions } from './introspect';
9
+ import { runCodegenPipeline, validateTablesFound } from './pipeline';
10
+ import { generate as generateReactQueryFiles } from './codegen';
11
+ import { generateOrm as generateOrmFiles } from './codegen/orm';
12
+ import { generateSharedTypes } from './codegen/shared';
13
+ import { writeGeneratedFiles } from './output';
14
+ import { getConfigOptions } from '../types/config';
15
+ /**
16
+ * Main generate function - takes a single config and generates code
17
+ *
18
+ * This is the primary entry point for programmatic usage.
19
+ * For multiple configs, call this function in a loop.
20
+ */
21
+ export async function generate(options = {}) {
22
+ // Apply defaults to get resolved config
23
+ const config = getConfigOptions(options);
24
+ const outputRoot = config.output;
25
+ // Determine which generators to run
26
+ const runReactQuery = config.reactQuery ?? false;
27
+ const runOrm = config.orm ?? false;
28
+ if (!runReactQuery && !runOrm) {
29
+ return {
30
+ success: false,
31
+ message: 'No generators enabled. Use reactQuery: true or orm: true in your config.',
32
+ output: outputRoot,
33
+ };
34
+ }
35
+ // Validate source
36
+ const sourceValidation = validateSourceOptions({
37
+ endpoint: config.endpoint || undefined,
38
+ schemaFile: config.schemaFile || undefined,
39
+ db: config.db,
40
+ });
41
+ if (!sourceValidation.valid) {
42
+ return {
43
+ success: false,
44
+ message: sourceValidation.error,
45
+ output: outputRoot,
46
+ };
47
+ }
48
+ const source = createSchemaSource({
49
+ endpoint: config.endpoint || undefined,
50
+ schemaFile: config.schemaFile || undefined,
51
+ db: config.db,
52
+ authorization: options.authorization || config.headers?.['Authorization'],
53
+ headers: config.headers,
54
+ });
55
+ // Run pipeline
56
+ let pipelineResult;
57
+ try {
58
+ console.log(`Fetching schema from ${source.describe()}...`);
59
+ pipelineResult = await runCodegenPipeline({
60
+ source,
61
+ config,
62
+ verbose: options.verbose,
63
+ skipCustomOperations: options.skipCustomOperations,
64
+ });
65
+ }
66
+ catch (err) {
67
+ return {
68
+ success: false,
69
+ message: `Failed to fetch schema: ${err instanceof Error ? err.message : 'Unknown error'}`,
70
+ output: outputRoot,
71
+ };
72
+ }
73
+ const { tables, customOperations } = pipelineResult;
74
+ // Validate tables
75
+ const tablesValidation = validateTablesFound(tables);
76
+ if (!tablesValidation.valid) {
77
+ return {
78
+ success: false,
79
+ message: tablesValidation.error,
80
+ output: outputRoot,
81
+ };
82
+ }
83
+ const allFilesWritten = [];
84
+ const bothEnabled = runReactQuery && runOrm;
85
+ // Generate shared types when both are enabled
86
+ if (bothEnabled) {
87
+ console.log('Generating shared types...');
88
+ const sharedResult = generateSharedTypes({
89
+ tables,
90
+ customOperations: {
91
+ queries: customOperations.queries,
92
+ mutations: customOperations.mutations,
93
+ typeRegistry: customOperations.typeRegistry,
94
+ },
95
+ config,
96
+ });
97
+ if (!options.dryRun) {
98
+ const writeResult = await writeGeneratedFiles(sharedResult.files, outputRoot, []);
99
+ if (!writeResult.success) {
100
+ return {
101
+ success: false,
102
+ message: `Failed to write shared types: ${writeResult.errors?.join(', ')}`,
103
+ output: outputRoot,
104
+ errors: writeResult.errors,
105
+ };
106
+ }
107
+ allFilesWritten.push(...(writeResult.filesWritten ?? []));
108
+ }
109
+ }
110
+ // Generate React Query hooks
111
+ if (runReactQuery) {
112
+ const hooksDir = path.join(outputRoot, 'hooks');
113
+ console.log('Generating React Query hooks...');
114
+ const { files } = generateReactQueryFiles({
115
+ tables,
116
+ customOperations: {
117
+ queries: customOperations.queries,
118
+ mutations: customOperations.mutations,
119
+ typeRegistry: customOperations.typeRegistry,
120
+ },
121
+ config,
122
+ sharedTypesPath: bothEnabled ? '..' : undefined,
123
+ });
124
+ if (!options.dryRun) {
125
+ const writeResult = await writeGeneratedFiles(files, hooksDir, ['queries', 'mutations']);
126
+ if (!writeResult.success) {
127
+ return {
128
+ success: false,
129
+ message: `Failed to write React Query hooks: ${writeResult.errors?.join(', ')}`,
130
+ output: outputRoot,
131
+ errors: writeResult.errors,
132
+ };
133
+ }
134
+ allFilesWritten.push(...(writeResult.filesWritten ?? []));
135
+ }
136
+ }
137
+ // Generate ORM client
138
+ if (runOrm) {
139
+ const ormDir = path.join(outputRoot, 'orm');
140
+ console.log('Generating ORM client...');
141
+ const { files } = generateOrmFiles({
142
+ tables,
143
+ customOperations: {
144
+ queries: customOperations.queries,
145
+ mutations: customOperations.mutations,
146
+ typeRegistry: customOperations.typeRegistry,
147
+ },
148
+ config,
149
+ sharedTypesPath: bothEnabled ? '..' : undefined,
150
+ });
151
+ if (!options.dryRun) {
152
+ const writeResult = await writeGeneratedFiles(files, ormDir, ['models', 'query', 'mutation']);
153
+ if (!writeResult.success) {
154
+ return {
155
+ success: false,
156
+ message: `Failed to write ORM client: ${writeResult.errors?.join(', ')}`,
157
+ output: outputRoot,
158
+ errors: writeResult.errors,
159
+ };
160
+ }
161
+ allFilesWritten.push(...(writeResult.filesWritten ?? []));
162
+ }
163
+ }
164
+ // Generate unified barrel when both are enabled
165
+ if (bothEnabled && !options.dryRun) {
166
+ const barrelContent = `/**
167
+ * Generated SDK - auto-generated, do not edit
168
+ * @generated by @constructive-io/graphql-codegen
169
+ */
170
+ export * from './types';
171
+ export * from './hooks';
172
+ export * from './orm';
173
+ `;
174
+ await writeGeneratedFiles([{ path: 'index.ts', content: barrelContent }], outputRoot, []);
175
+ }
176
+ const generators = [runReactQuery && 'React Query', runOrm && 'ORM'].filter(Boolean).join(' and ');
177
+ return {
178
+ success: true,
179
+ message: options.dryRun
180
+ ? `Dry run complete. Would generate ${generators} for ${tables.length} tables.`
181
+ : `Generated ${generators} for ${tables.length} tables. Files written to ${outputRoot}`,
182
+ output: outputRoot,
183
+ tables: tables.map((t) => t.name),
184
+ filesWritten: allFilesWritten,
185
+ };
186
+ }
@@ -1,8 +1,20 @@
1
1
  /**
2
- * Core query building exports
2
+ * Core module exports
3
+ *
4
+ * This module contains all the core business logic for graphql-codegen.
5
+ * The CLI is a thin wrapper around these core functions.
3
6
  */
7
+ export { generate } from './generate';
8
+ export type { GenerateOptions, GenerateResult } from './generate';
4
9
  export * from './types';
5
10
  export * from './ast';
6
11
  export * from './custom-ast';
7
12
  export { QueryBuilder, MetaObject } from './query-builder';
8
13
  export { validateMetaObject, convertFromMetaSchema } from './meta-object';
14
+ export * from './config';
15
+ export * from './codegen';
16
+ export * from './introspect';
17
+ export * from './pipeline';
18
+ export * from './output';
19
+ export * from './watch';
20
+ export * from './database';
package/esm/core/index.js CHANGED
@@ -1,6 +1,11 @@
1
1
  /**
2
- * Core query building exports
2
+ * Core module exports
3
+ *
4
+ * This module contains all the core business logic for graphql-codegen.
5
+ * The CLI is a thin wrapper around these core functions.
3
6
  */
7
+ // Main generate function (orchestrates the entire pipeline)
8
+ export { generate } from './generate';
4
9
  // Types
5
10
  export * from './types';
6
11
  // AST generation
@@ -10,3 +15,17 @@ export * from './custom-ast';
10
15
  export { QueryBuilder, MetaObject } from './query-builder';
11
16
  // Meta object utilities
12
17
  export { validateMetaObject, convertFromMetaSchema } from './meta-object';
18
+ // Configuration loading and resolution
19
+ export * from './config';
20
+ // Code generation
21
+ export * from './codegen';
22
+ // Schema introspection
23
+ export * from './introspect';
24
+ // Codegen pipeline
25
+ export * from './pipeline';
26
+ // File output
27
+ export * from './output';
28
+ // Watch mode
29
+ export * from './watch';
30
+ // Database schema utilities
31
+ export * from './database';
@@ -1,34 +1,80 @@
1
1
  /**
2
2
  * Fetch GraphQL schema introspection from an endpoint
3
3
  */
4
+ import dns from 'node:dns';
5
+ import { Agent } from 'undici';
4
6
  import { SCHEMA_INTROSPECTION_QUERY } from './schema-query';
7
+ /**
8
+ * Check if a hostname is localhost or a localhost subdomain
9
+ */
10
+ function isLocalhostHostname(hostname) {
11
+ return hostname === 'localhost' || hostname.endsWith('.localhost');
12
+ }
13
+ /**
14
+ * Create an undici Agent that resolves *.localhost to 127.0.0.1
15
+ * This fixes DNS resolution issues on macOS where subdomains like api.localhost
16
+ * don't resolve automatically (unlike browsers which handle *.localhost).
17
+ */
18
+ function createLocalhostAgent() {
19
+ return new Agent({
20
+ connect: {
21
+ lookup(hostname, opts, cb) {
22
+ if (isLocalhostHostname(hostname)) {
23
+ cb(null, '127.0.0.1', 4);
24
+ return;
25
+ }
26
+ dns.lookup(hostname, opts, cb);
27
+ },
28
+ },
29
+ });
30
+ }
31
+ let localhostAgent = null;
32
+ function getLocalhostAgent() {
33
+ if (!localhostAgent) {
34
+ localhostAgent = createLocalhostAgent();
35
+ }
36
+ return localhostAgent;
37
+ }
5
38
  /**
6
39
  * Fetch the full schema introspection from a GraphQL endpoint
7
40
  */
8
41
  export async function fetchSchema(options) {
9
42
  const { endpoint, authorization, headers = {}, timeout = 30000 } = options;
43
+ // Parse the endpoint URL to check for localhost
44
+ const url = new URL(endpoint);
45
+ const useLocalhostAgent = isLocalhostHostname(url.hostname);
10
46
  // Build headers
11
47
  const requestHeaders = {
12
48
  'Content-Type': 'application/json',
13
49
  Accept: 'application/json',
14
50
  ...headers,
15
51
  };
52
+ // Set Host header for localhost subdomains to preserve routing
53
+ if (useLocalhostAgent && url.hostname !== 'localhost') {
54
+ requestHeaders['Host'] = url.hostname;
55
+ }
16
56
  if (authorization) {
17
57
  requestHeaders['Authorization'] = authorization;
18
58
  }
19
59
  // Create abort controller for timeout
20
60
  const controller = new AbortController();
21
61
  const timeoutId = setTimeout(() => controller.abort(), timeout);
62
+ // Build fetch options
63
+ const fetchOptions = {
64
+ method: 'POST',
65
+ headers: requestHeaders,
66
+ body: JSON.stringify({
67
+ query: SCHEMA_INTROSPECTION_QUERY,
68
+ variables: {},
69
+ }),
70
+ signal: controller.signal,
71
+ };
72
+ // Use custom agent for localhost to fix DNS resolution on macOS
73
+ if (useLocalhostAgent) {
74
+ fetchOptions.dispatcher = getLocalhostAgent();
75
+ }
22
76
  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
- });
77
+ const response = await fetch(endpoint, fetchOptions);
32
78
  clearTimeout(timeoutId);
33
79
  if (!response.ok) {
34
80
  return {
@@ -0,0 +1,44 @@
1
+ /**
2
+ * API Schemas Resolution
3
+ *
4
+ * Utilities for resolving PostgreSQL schema names from API names
5
+ * by querying the services_public.api_schemas table.
6
+ */
7
+ import { Pool } from 'pg';
8
+ /**
9
+ * Result of validating services schema requirements
10
+ */
11
+ export interface ServicesSchemaValidation {
12
+ valid: boolean;
13
+ error?: string;
14
+ }
15
+ /**
16
+ * Validate that the required services schemas exist in the database
17
+ *
18
+ * Checks for:
19
+ * - services_public schema with apis and api_schemas tables
20
+ * - metaschema_public schema with schema table
21
+ *
22
+ * @param pool - Database connection pool
23
+ * @returns Validation result
24
+ */
25
+ export declare function validateServicesSchemas(pool: Pool): Promise<ServicesSchemaValidation>;
26
+ /**
27
+ * Resolve schema names from API names by querying services_public.api_schemas
28
+ *
29
+ * Joins services_public.apis, services_public.api_schemas, and metaschema_public.schema
30
+ * to get the actual PostgreSQL schema names for the given API names.
31
+ *
32
+ * @param pool - Database connection pool
33
+ * @param apiNames - Array of API names to resolve
34
+ * @returns Array of PostgreSQL schema names
35
+ * @throws Error if validation fails or no schemas found
36
+ */
37
+ export declare function resolveApiSchemas(pool: Pool, apiNames: string[]): Promise<string[]>;
38
+ /**
39
+ * Create a database pool for the given database name or connection string
40
+ *
41
+ * @param database - Database name or connection string
42
+ * @returns Database connection pool
43
+ */
44
+ export declare function createDatabasePool(database: string): Pool;