@constructive-io/graphql-codegen 3.0.4 → 3.1.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.
@@ -1,4 +1,14 @@
1
+ export interface GenerateClientFileOptions {
2
+ /**
3
+ * Generate browser-compatible code using native fetch
4
+ * When true (default), uses native W3C fetch API
5
+ * When false, uses undici fetch with dispatcher support for localhost DNS resolution
6
+ * @default true
7
+ */
8
+ browserCompatible?: boolean;
9
+ }
1
10
  /**
2
11
  * Generate client.ts content
12
+ * @param options - Generation options
3
13
  */
4
- export declare function generateClientFile(): string;
14
+ export declare function generateClientFile(options?: GenerateClientFileOptions): string;
@@ -1,264 +1,79 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.generateClientFile = generateClientFile;
4
37
  /**
5
38
  * Client generator - generates client.ts with configure() and execute()
6
- */
7
- const utils_1 = require("./utils");
8
- /**
9
- * Generate client.ts content
10
- */
11
- function generateClientFile() {
12
- return `${(0, utils_1.getGeneratedFileHeader)('GraphQL client configuration and execution')}
13
-
14
- // ============================================================================
15
- // Configuration
16
- // ============================================================================
17
-
18
- export interface GraphQLClientConfig {
19
- /** GraphQL endpoint URL */
20
- endpoint: string;
21
- /** Default headers to include in all requests */
22
- headers?: Record<string, string>;
23
- }
24
-
25
- let globalConfig: GraphQLClientConfig | null = null;
26
-
27
- /**
28
- * Configure the GraphQL client
29
- *
30
- * @example
31
- * \`\`\`ts
32
- * import { configure } from './generated';
33
- *
34
- * configure({
35
- * endpoint: 'https://api.example.com/graphql',
36
- * headers: {
37
- * Authorization: 'Bearer <token>',
38
- * },
39
- * });
40
- * \`\`\`
41
- */
42
- export function configure(config: GraphQLClientConfig): void {
43
- globalConfig = config;
44
- }
45
-
46
- /**
47
- * Get the current configuration
48
- * @throws Error if not configured
49
- */
50
- export function getConfig(): GraphQLClientConfig {
51
- if (!globalConfig) {
52
- throw new Error(
53
- 'GraphQL client not configured. Call configure() before making requests.'
54
- );
55
- }
56
- return globalConfig;
57
- }
58
-
59
- /**
60
- * Set a single header value
61
- * Useful for updating Authorization after login
62
39
  *
63
- * @example
64
- * \`\`\`ts
65
- * setHeader('Authorization', 'Bearer <new-token>');
66
- * \`\`\`
40
+ * Reads from template files in the templates/ directory for proper type checking.
67
41
  */
68
- export function setHeader(key: string, value: string): void {
69
- const config = getConfig();
70
- globalConfig = {
71
- ...config,
72
- headers: { ...config.headers, [key]: value },
73
- };
74
- }
75
-
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
44
+ const utils_1 = require("./utils");
76
45
  /**
77
- * Merge multiple headers into the current configuration
78
- *
79
- * @example
80
- * \`\`\`ts
81
- * setHeaders({ Authorization: 'Bearer <token>', 'X-Custom': 'value' });
82
- * \`\`\`
46
+ * Find a template file path.
47
+ * Templates are at ./templates/ relative to this file in both src/ and dist/.
83
48
  */
84
- export function setHeaders(headers: Record<string, string>): void {
85
- const config = getConfig();
86
- globalConfig = {
87
- ...config,
88
- headers: { ...config.headers, ...headers },
89
- };
90
- }
91
-
92
- // ============================================================================
93
- // Error handling
94
- // ============================================================================
95
-
96
- export interface GraphQLError {
97
- message: string;
98
- locations?: Array<{ line: number; column: number }>;
99
- path?: Array<string | number>;
100
- extensions?: Record<string, unknown>;
101
- }
102
-
103
- export class GraphQLClientError extends Error {
104
- constructor(
105
- message: string,
106
- public errors: GraphQLError[],
107
- public response?: Response
108
- ) {
109
- super(message);
110
- this.name = 'GraphQLClientError';
111
- }
49
+ function findTemplateFile(templateName) {
50
+ const templatePath = path.join(__dirname, 'templates', templateName);
51
+ if (fs.existsSync(templatePath)) {
52
+ return templatePath;
53
+ }
54
+ throw new Error(`Could not find template file: ${templateName}. ` +
55
+ `Searched in: ${templatePath}`);
112
56
  }
113
-
114
- // ============================================================================
115
- // Execution
116
- // ============================================================================
117
-
118
- export interface ExecuteOptions {
119
- /** Override headers for this request */
120
- headers?: Record<string, string>;
121
- /** AbortSignal for request cancellation */
122
- signal?: AbortSignal;
123
- }
124
-
125
57
  /**
126
- * Execute a GraphQL operation
127
- *
128
- * @example
129
- * \`\`\`ts
130
- * const result = await execute<CarsQueryResult, CarsQueryVariables>(
131
- * carsQueryDocument,
132
- * { first: 10 }
133
- * );
134
- * \`\`\`
58
+ * Read a template file and replace the header with generated file header
135
59
  */
136
- export async function execute<TData = unknown, TVariables = Record<string, unknown>>(
137
- document: string,
138
- variables?: TVariables,
139
- options?: ExecuteOptions
140
- ): Promise<TData> {
141
- const config = getConfig();
142
-
143
- const response = await fetch(config.endpoint, {
144
- method: 'POST',
145
- headers: {
146
- 'Content-Type': 'application/json',
147
- ...config.headers,
148
- ...options?.headers,
149
- },
150
- body: JSON.stringify({
151
- query: document,
152
- variables,
153
- }),
154
- signal: options?.signal,
155
- });
156
-
157
- const json = await response.json();
158
-
159
- if (json.errors && json.errors.length > 0) {
160
- throw new GraphQLClientError(
161
- json.errors[0].message || 'GraphQL request failed',
162
- json.errors,
163
- response
164
- );
165
- }
166
-
167
- return json.data as TData;
60
+ function readTemplateFile(templateName, description) {
61
+ const templatePath = findTemplateFile(templateName);
62
+ let content = fs.readFileSync(templatePath, 'utf-8');
63
+ // Replace the source file header comment with the generated file header
64
+ // Match the header pattern used in template files
65
+ const headerPattern = /\/\*\*[\s\S]*?\* NOTE: This file is read at codegen time and written to output\.[\s\S]*?\*\/\n*/;
66
+ content = content.replace(headerPattern, (0, utils_1.getGeneratedFileHeader)(description) + '\n');
67
+ return content;
168
68
  }
169
-
170
69
  /**
171
- * Execute a GraphQL operation with full response (data + errors)
172
- * Useful when you want to handle partial data with errors
173
- */
174
- export async function executeWithErrors<TData = unknown, TVariables = Record<string, unknown>>(
175
- document: string,
176
- variables?: TVariables,
177
- options?: ExecuteOptions
178
- ): Promise<{ data: TData | null; errors: GraphQLError[] | null }> {
179
- const config = getConfig();
180
-
181
- const response = await fetch(config.endpoint, {
182
- method: 'POST',
183
- headers: {
184
- 'Content-Type': 'application/json',
185
- ...config.headers,
186
- ...options?.headers,
187
- },
188
- body: JSON.stringify({
189
- query: document,
190
- variables,
191
- }),
192
- signal: options?.signal,
193
- });
194
-
195
- const json = await response.json();
196
-
197
- return {
198
- data: json.data ?? null,
199
- errors: json.errors ?? null,
200
- };
201
- }
202
-
203
- // ============================================================================
204
- // QueryClient Factory
205
- // ============================================================================
206
-
207
- /**
208
- * Default QueryClient configuration optimized for GraphQL
209
- *
210
- * These defaults provide a good balance between freshness and performance:
211
- * - staleTime: 1 minute - data considered fresh, won't refetch
212
- * - gcTime: 5 minutes - unused data kept in cache
213
- * - refetchOnWindowFocus: false - don't refetch when tab becomes active
214
- * - retry: 1 - retry failed requests once
215
- */
216
- export const defaultQueryClientOptions = {
217
- defaultOptions: {
218
- queries: {
219
- staleTime: 1000 * 60, // 1 minute
220
- gcTime: 1000 * 60 * 5, // 5 minutes
221
- refetchOnWindowFocus: false,
222
- retry: 1,
223
- },
224
- },
225
- };
226
-
227
- /**
228
- * QueryClient options type for createQueryClient
70
+ * Generate client.ts content
71
+ * @param options - Generation options
229
72
  */
230
- export interface CreateQueryClientOptions {
231
- defaultOptions?: {
232
- queries?: {
233
- staleTime?: number;
234
- gcTime?: number;
235
- refetchOnWindowFocus?: boolean;
236
- retry?: number | boolean;
237
- retryDelay?: number | ((attemptIndex: number) => number);
238
- };
239
- mutations?: {
240
- retry?: number | boolean;
241
- retryDelay?: number | ((attemptIndex: number) => number);
242
- };
243
- };
244
- }
245
-
246
- // Note: createQueryClient is available when using with @tanstack/react-query
247
- // Import QueryClient from '@tanstack/react-query' and use these options:
248
- //
249
- // import { QueryClient } from '@tanstack/react-query';
250
- // const queryClient = new QueryClient(defaultQueryClientOptions);
251
- //
252
- // Or merge with your own options:
253
- // const queryClient = new QueryClient({
254
- // ...defaultQueryClientOptions,
255
- // defaultOptions: {
256
- // ...defaultQueryClientOptions.defaultOptions,
257
- // queries: {
258
- // ...defaultQueryClientOptions.defaultOptions.queries,
259
- // staleTime: 30000, // Override specific options
260
- // },
261
- // },
262
- // });
263
- `;
73
+ function generateClientFile(options = {}) {
74
+ const { browserCompatible = true } = options;
75
+ const templateName = browserCompatible
76
+ ? 'client.browser.ts'
77
+ : 'client.node.ts';
78
+ return readTemplateFile(templateName, 'GraphQL client configuration and execution');
264
79
  }
@@ -45,7 +45,9 @@ function generate(options) {
45
45
  // 1. Generate client.ts
46
46
  files.push({
47
47
  path: 'client.ts',
48
- content: (0, client_1.generateClientFile)(),
48
+ content: (0, client_1.generateClientFile)({
49
+ browserCompatible: config.browserCompatible ?? true,
50
+ }),
49
51
  });
50
52
  // Collect table type names for import path resolution
51
53
  const tableTypeNames = new Set(tables.map((t) => (0, utils_1.getTableNames)(t).typeName));
@@ -11,17 +11,20 @@ export interface GeneratedClientFile {
11
11
  /**
12
12
  * Generate the main client.ts file (OrmClient class)
13
13
  * This is the runtime client that handles GraphQL execution
14
+ *
15
+ * Reads from the templates directory for proper type checking.
14
16
  */
15
17
  export declare function generateOrmClientFile(): GeneratedClientFile;
16
18
  /**
17
19
  * Generate the query-builder.ts file (runtime query builder)
18
20
  *
19
- * Reads from the actual TypeScript file in the source directory,
20
- * which enables proper type checking and testability.
21
+ * Reads from the templates directory for proper type checking and testability.
21
22
  */
22
23
  export declare function generateQueryBuilderFile(): GeneratedClientFile;
23
24
  /**
24
25
  * Generate the select-types.ts file
26
+ *
27
+ * Reads from the templates directory for proper type checking.
25
28
  */
26
29
  export declare function generateSelectTypesFile(): GeneratedClientFile;
27
30
  /**