@newmo/graphql-codegen-fake-server-client 0.23.3 → 0.25.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.
@@ -178,9 +178,9 @@ function generateCalledQuery(params) {
178
178
  };
179
179
  };
180
180
  response: {
181
- statusCode: number;
181
+ status: number;
182
182
  headers: Record<string, unknown>;
183
- body: ${params.name}Query;
183
+ body: { data: ${params.name}Query };
184
184
  };
185
185
  }[]
186
186
  }`,
@@ -217,9 +217,9 @@ return result as {
217
217
  };
218
218
  };
219
219
  response: {
220
- statusCode: number;
220
+ status: number;
221
221
  headers: Record<string, unknown>;
222
- body: ${params.name}Query;
222
+ body: { data: ${params.name}Query };
223
223
  };
224
224
  }[];
225
225
  };`,
@@ -245,9 +245,9 @@ function generateCalledMutation(params) {
245
245
  };
246
246
  };
247
247
  response: {
248
- statusCode: number;
248
+ status: number;
249
249
  headers: Record<string, unknown>;
250
- body: ${params.name}Mutation;
250
+ body: { data: ${params.name}Mutation };
251
251
  };
252
252
  }[];
253
253
  }`,
@@ -284,9 +284,9 @@ return result as {
284
284
  };
285
285
  };
286
286
  response: {
287
- statusCode: number;
287
+ status: number;
288
288
  headers: Record<string, unknown>;
289
- body: ${params.name}Mutation;
289
+ body: { data: ${params.name}Mutation };
290
290
  };
291
291
  }[];
292
292
  };`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newmo/graphql-codegen-fake-server-client",
3
- "version": "0.23.3",
3
+ "version": "0.25.0",
4
4
  "private": false,
5
5
  "description": "GraphQL Codegen plugin for generating a fake server client",
6
6
  "keywords": [
@@ -62,5 +62,5 @@
62
62
  "access": "public",
63
63
  "registry": "https://registry.npmjs.org/"
64
64
  },
65
- "gitHead": "fdb857dc72e010f59daa8b274d027d495ddba6f1"
65
+ "gitHead": "d86dc669a3978f3c46f86c0d2e84b4d2c8f9311a"
66
66
  }
@@ -203,9 +203,9 @@ export function generateCalledQuery(params: {
203
203
  };
204
204
  };
205
205
  response: {
206
- statusCode: number;
206
+ status: number;
207
207
  headers: Record<string, unknown>;
208
- body: ${params.name}Query;
208
+ body: { data: ${params.name}Query };
209
209
  };
210
210
  }[]
211
211
  }`,
@@ -242,9 +242,9 @@ return result as {
242
242
  };
243
243
  };
244
244
  response: {
245
- statusCode: number;
245
+ status: number;
246
246
  headers: Record<string, unknown>;
247
- body: ${params.name}Query;
247
+ body: { data: ${params.name}Query };
248
248
  };
249
249
  }[];
250
250
  };`,
@@ -275,9 +275,9 @@ export function generateCalledMutation(params: {
275
275
  };
276
276
  };
277
277
  response: {
278
- statusCode: number;
278
+ status: number;
279
279
  headers: Record<string, unknown>;
280
- body: ${params.name}Mutation;
280
+ body: { data: ${params.name}Mutation };
281
281
  };
282
282
  }[];
283
283
  }`,
@@ -314,9 +314,9 @@ return result as {
314
314
  };
315
315
  };
316
316
  response: {
317
- statusCode: number;
317
+ status: number;
318
318
  headers: Record<string, unknown>;
319
- body: ${params.name}Mutation;
319
+ body: { data: ${params.name}Mutation };
320
320
  };
321
321
  }[];
322
322
  };`,
@@ -1,141 +0,0 @@
1
- "use strict";
2
- // Runtime utilities for generated fake client
3
- // This file is embedded into the generated code
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.RequestQueue = void 0;
6
- exports.fetchWithRetry = fetchWithRetry;
7
- // Request queue implementation for rate limiting
8
- class RequestQueue {
9
- queue = [];
10
- running = 0;
11
- maxConcurrent = 5; // Reduced default for better stability
12
- requestDelay = 10; // Small delay to prevent overwhelming the server
13
- lastRequestTime = 0;
14
- async add(fn) {
15
- return new Promise((resolve, reject) => {
16
- this.queue.push(async () => {
17
- try {
18
- // Apply request delay if configured
19
- if (this.requestDelay > 0) {
20
- const now = Date.now();
21
- const timeSinceLastRequest = now - this.lastRequestTime;
22
- if (timeSinceLastRequest < this.requestDelay) {
23
- await new Promise(r => setTimeout(r, this.requestDelay - timeSinceLastRequest));
24
- }
25
- this.lastRequestTime = Date.now();
26
- }
27
- const result = await fn();
28
- resolve(result);
29
- }
30
- catch (error) {
31
- reject(error);
32
- }
33
- });
34
- this.process();
35
- });
36
- }
37
- async process() {
38
- if (this.running >= this.maxConcurrent || this.queue.length === 0) {
39
- return;
40
- }
41
- this.running++;
42
- const fn = this.queue.shift();
43
- if (fn) {
44
- await fn();
45
- this.running--;
46
- this.process();
47
- }
48
- }
49
- }
50
- exports.RequestQueue = RequestQueue;
51
- // Retry helper function with exponential backoff
52
- async function fetchWithRetry(url, options) {
53
- const maxAttempts = 3;
54
- const initialDelay = 100;
55
- const maxDelay = 2000;
56
- const backoffFactor = 2;
57
- // Apply HTTP options with sensible defaults
58
- const fetchOptions = {
59
- ...options,
60
- // Enable keepalive for connection reuse
61
- keepalive: true,
62
- // Set a reasonable timeout (30 seconds)
63
- signal: AbortSignal.timeout(30000),
64
- };
65
- let lastError;
66
- let lastResponse;
67
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
68
- try {
69
- const response = await fetch(url, fetchOptions);
70
- lastResponse = response;
71
- // Success (2xx) or client error (4xx) - don't retry
72
- if (response.status < 500) {
73
- return response;
74
- }
75
- // Server error (5xx) - should retry
76
- if (attempt < maxAttempts - 1) {
77
- const requestInfo = {
78
- url,
79
- status: response.status,
80
- statusText: response.statusText,
81
- attempt: attempt + 1,
82
- maxAttempts,
83
- operationName: JSON.parse(options.body)?.operationName,
84
- sequenceId: options.headers?.['sequence-id'],
85
- };
86
- console.error(`[FakeClient] Server error, will retry:`, requestInfo);
87
- // Calculate delay with exponential backoff and jitter
88
- const baseDelay = Math.min(initialDelay * Math.pow(backoffFactor, attempt), maxDelay);
89
- const jitter = Math.random() * 0.1 * baseDelay; // 10% jitter
90
- const delay = baseDelay + jitter;
91
- console.log(`[FakeClient] Retrying in ${Math.round(delay)}ms...`);
92
- await new Promise(resolve => setTimeout(resolve, delay));
93
- continue;
94
- }
95
- // Last attempt and still server error
96
- return response;
97
- }
98
- catch (error) {
99
- lastError = error;
100
- // Determine if error is retryable
101
- let shouldRetry = false;
102
- let errorType = 'unknown';
103
- if (error instanceof TypeError) {
104
- // Network errors from fetch (connection failures)
105
- shouldRetry = true;
106
- errorType = 'network';
107
- }
108
- else if (error instanceof Error && error.name === 'AbortError') {
109
- // Timeout errors
110
- shouldRetry = true;
111
- errorType = 'timeout';
112
- }
113
- const requestInfo = {
114
- url,
115
- errorType,
116
- error: error instanceof Error ? error.message : String(error),
117
- attempt: attempt + 1,
118
- maxAttempts,
119
- operationName: JSON.parse(options.body)?.operationName,
120
- sequenceId: options.headers?.['sequence-id'],
121
- };
122
- console.error(`[FakeClient] Request failed:`, requestInfo);
123
- if (shouldRetry && attempt < maxAttempts - 1) {
124
- // Calculate delay with exponential backoff and jitter
125
- const baseDelay = Math.min(initialDelay * Math.pow(backoffFactor, attempt), maxDelay);
126
- const jitter = Math.random() * 0.1 * baseDelay; // 10% jitter
127
- const delay = baseDelay + jitter;
128
- console.log(`[FakeClient] Retrying in ${Math.round(delay)}ms...`);
129
- await new Promise(resolve => setTimeout(resolve, delay));
130
- continue;
131
- }
132
- // Not retryable or max attempts reached
133
- throw error;
134
- }
135
- }
136
- // Should not reach here, but just in case
137
- if (lastResponse) {
138
- return lastResponse;
139
- }
140
- throw new Error('Max retry attempts reached', { cause: lastError });
141
- }
@@ -1,175 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getRuntimeCode = getRuntimeCode;
4
- /**
5
- * Returns the runtime code as a string template
6
- * This is used to embed the runtime code in the generated client
7
- */
8
- function getRuntimeCode() {
9
- return `// Runtime utilities for generated fake client
10
- export type CreateFakeClientOptions = {
11
- /**
12
- * The URL of the fake server
13
- * @example 'http://localhost:4000/fake'
14
- */
15
- fakeServerEndpoint: string;
16
- };
17
-
18
- // Request queue implementation for rate limiting
19
- class RequestQueue {
20
- private queue: Array<() => Promise<any>> = [];
21
- private running = 0;
22
- private maxConcurrent: number = 5; // Reduced default for better stability
23
- private requestDelay: number = 10; // Small delay to prevent overwhelming the server
24
- private lastRequestTime = 0;
25
-
26
- async add<T>(fn: () => Promise<T>): Promise<T> {
27
- return new Promise((resolve, reject) => {
28
- this.queue.push(async () => {
29
- try {
30
- // Apply request delay if configured
31
- if (this.requestDelay > 0) {
32
- const now = Date.now();
33
- const timeSinceLastRequest = now - this.lastRequestTime;
34
- if (timeSinceLastRequest < this.requestDelay) {
35
- await new Promise(r => setTimeout(r, this.requestDelay - timeSinceLastRequest));
36
- }
37
- this.lastRequestTime = Date.now();
38
- }
39
-
40
- const result = await fn();
41
- resolve(result);
42
- } catch (error) {
43
- reject(error);
44
- }
45
- });
46
- this.process();
47
- });
48
- }
49
-
50
- private async process() {
51
- if (this.running >= this.maxConcurrent || this.queue.length === 0) {
52
- return;
53
- }
54
-
55
- this.running++;
56
- const fn = this.queue.shift();
57
- if (fn) {
58
- await fn();
59
- this.running--;
60
- this.process();
61
- }
62
- }
63
- }
64
-
65
- // Retry helper function with exponential backoff
66
- async function fetchWithRetry(
67
- url: string,
68
- options: RequestInit
69
- ): Promise<Response> {
70
- const maxAttempts = 3;
71
- const initialDelay = 100;
72
- const maxDelay = 2000;
73
- const backoffFactor = 2;
74
-
75
- // Apply HTTP options with sensible defaults
76
- const fetchOptions: RequestInit = {
77
- ...options,
78
- // Enable keepalive for connection reuse
79
- keepalive: true,
80
- // Set a reasonable timeout (30 seconds)
81
- signal: AbortSignal.timeout(30000),
82
- };
83
-
84
- let lastError: Error | undefined;
85
- let lastResponse: Response | undefined;
86
-
87
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
88
- try {
89
- const response = await fetch(url, fetchOptions);
90
- lastResponse = response;
91
-
92
- // Success (2xx) or client error (4xx) - don't retry
93
- if (response.status < 500) {
94
- return response;
95
- }
96
-
97
- // Server error (5xx) - should retry
98
- if (attempt < maxAttempts - 1) {
99
- const requestInfo = {
100
- url,
101
- status: response.status,
102
- statusText: response.statusText,
103
- attempt: attempt + 1,
104
- maxAttempts,
105
- operationName: JSON.parse(options.body as string)?.operationName,
106
- sequenceId: (options.headers as any)?.['sequence-id'],
107
- };
108
-
109
- console.error(\`[FakeClient] Server error, will retry:\`, requestInfo);
110
-
111
- // Calculate delay with exponential backoff and jitter
112
- const baseDelay = Math.min(initialDelay * Math.pow(backoffFactor, attempt), maxDelay);
113
- const jitter = Math.random() * 0.1 * baseDelay; // 10% jitter
114
- const delay = baseDelay + jitter;
115
-
116
- console.log(\`[FakeClient] Retrying in \${Math.round(delay)}ms...\`);
117
- await new Promise(resolve => setTimeout(resolve, delay));
118
- continue;
119
- }
120
-
121
- // Last attempt and still server error
122
- return response;
123
-
124
- } catch (error) {
125
- lastError = error as Error;
126
-
127
- // Determine if error is retryable
128
- let shouldRetry = false;
129
- let errorType = 'unknown';
130
-
131
- if (error instanceof TypeError) {
132
- // Network errors from fetch (connection failures)
133
- shouldRetry = true;
134
- errorType = 'network';
135
- } else if (error instanceof Error && error.name === 'AbortError') {
136
- // Timeout errors
137
- shouldRetry = true;
138
- errorType = 'timeout';
139
- }
140
-
141
- const requestInfo = {
142
- url,
143
- errorType,
144
- error: error instanceof Error ? error.message : String(error),
145
- attempt: attempt + 1,
146
- maxAttempts,
147
- operationName: JSON.parse(options.body as string)?.operationName,
148
- sequenceId: (options.headers as any)?.['sequence-id'],
149
- };
150
-
151
- console.error(\`[FakeClient] Request failed:\`, requestInfo);
152
-
153
- if (shouldRetry && attempt < maxAttempts - 1) {
154
- // Calculate delay with exponential backoff and jitter
155
- const baseDelay = Math.min(initialDelay * Math.pow(backoffFactor, attempt), maxDelay);
156
- const jitter = Math.random() * 0.1 * baseDelay; // 10% jitter
157
- const delay = baseDelay + jitter;
158
-
159
- console.log(\`[FakeClient] Retrying in \${Math.round(delay)}ms...\`);
160
- await new Promise(resolve => setTimeout(resolve, delay));
161
- continue;
162
- }
163
-
164
- // Not retryable or max attempts reached
165
- throw error;
166
- }
167
- }
168
-
169
- // Should not reach here, but just in case
170
- if (lastResponse) {
171
- return lastResponse;
172
- }
173
- throw new Error('Max retry attempts reached', { cause: lastError });
174
- }`;
175
- }
@@ -1,291 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateRegisterQuery = generateRegisterQuery;
4
- exports.generateRegisterQueryError = generateRegisterQueryError;
5
- exports.generateRegisterMutation = generateRegisterMutation;
6
- exports.generateRegisterMutationError = generateRegisterMutationError;
7
- exports.generateCalledQuery = generateCalledQuery;
8
- exports.generateCalledMutation = generateCalledMutation;
9
- /**
10
- * Helper to indent each line of a string
11
- */
12
- function indent(str, spaces = 4) {
13
- const indentStr = ' '.repeat(spaces);
14
- return str.split('\n').map(line => line ? indentStr + line : line).join('\n');
15
- }
16
- /**
17
- * Helper to create method templates with better readability
18
- */
19
- function createMethod(config) {
20
- return `async ${config.name}(${config.params}): Promise<${config.returnType}> {
21
- ${indent(config.body)}
22
- }`;
23
- }
24
- /**
25
- * Generate register query method template
26
- */
27
- function generateRegisterQuery(params) {
28
- return createMethod({
29
- name: `register${params.name}QueryResponse`,
30
- params: `sequenceId:string, queryResponse: ${params.name}Query, sequenceOptions?: FakeClientRegisterSequenceOptions<${params.variablesType}>`,
31
- returnType: params.responseType,
32
- body: `const requestCondition = sequenceOptions?.requestCondition ?? { type: "always" };
33
- const response = await requestQueue.add(() => fetchWithRetry(
34
- ${params.endpoint},
35
- {
36
- method: 'POST',
37
- headers: {
38
- 'Content-Type': 'application/json',
39
- 'sequence-id': sequenceId
40
- },
41
- body: JSON.stringify({
42
- type: "operation",
43
- operationName: "${params.name}",
44
- data: queryResponse,
45
- requestCondition: requestCondition
46
- }),
47
- }
48
- ));
49
-
50
- const result = await response.json();
51
- if (!response.ok) {
52
- const errorResult = result as { errors?: string[] };
53
- throw new Error(\`Failed to register fake response: \${response.status} \${response.statusText}\${errorResult.errors ? ' - ' + JSON.stringify(errorResult.errors) : ''}\`);
54
- }
55
- return result as ${params.responseType};`
56
- });
57
- }
58
- /**
59
- * Generate register query error method template
60
- */
61
- function generateRegisterQueryError(params) {
62
- return createMethod({
63
- name: `register${params.name}QueryErrorResponse`,
64
- params: `sequenceId:string, { errors, responseStatusCode }: { errors: Record<string, unknown>[]; responseStatusCode: number }`,
65
- returnType: params.responseType,
66
- body: `const response = await requestQueue.add(() => fetchWithRetry(
67
- ${params.endpoint},
68
- {
69
- method: 'POST',
70
- headers: {
71
- 'Content-Type': 'application/json',
72
- 'sequence-id': sequenceId
73
- },
74
- body: JSON.stringify({
75
- type: "network-error",
76
- operationName: "${params.name}",
77
- responseStatusCode,
78
- errors
79
- }),
80
- }
81
- ));
82
-
83
- const result = await response.json();
84
- if (!response.ok) {
85
- const errorResult = result as { errors?: string[] };
86
- throw new Error(\`Failed to register fake error response: \${response.status} \${response.statusText}\${errorResult.errors ? ' - ' + JSON.stringify(errorResult.errors) : ''}\`);
87
- }
88
- return result as ${params.responseType};`
89
- });
90
- }
91
- /**
92
- * Generate register mutation method template
93
- */
94
- function generateRegisterMutation(params) {
95
- return createMethod({
96
- name: `register${params.name}MutationResponse`,
97
- params: `sequenceId:string, mutationResponse: ${params.name}Mutation, sequenceOptions?: FakeClientRegisterSequenceOptions<${params.variablesType}>`,
98
- returnType: params.responseType,
99
- body: `const requestCondition = sequenceOptions?.requestCondition ?? { type: "always" };
100
- const response = await requestQueue.add(() => fetchWithRetry(
101
- ${params.endpoint},
102
- {
103
- method: 'POST',
104
- headers: {
105
- 'Content-Type': 'application/json',
106
- 'sequence-id': sequenceId
107
- },
108
- body: JSON.stringify({
109
- type: "operation",
110
- operationName: "${params.name}",
111
- data: mutationResponse,
112
- requestCondition: requestCondition
113
- }),
114
- }
115
- ));
116
-
117
- const result = await response.json();
118
- if (!response.ok) {
119
- const errorResult = result as { errors?: string[] };
120
- throw new Error(\`Failed to register fake response: \${response.status} \${response.statusText}\${errorResult.errors ? ' - ' + JSON.stringify(errorResult.errors) : ''}\`);
121
- }
122
- return result as ${params.responseType};`
123
- });
124
- }
125
- /**
126
- * Generate register mutation error method template
127
- */
128
- function generateRegisterMutationError(params) {
129
- return createMethod({
130
- name: `register${params.name}MutationErrorResponse`,
131
- params: `sequenceId:string, { errors, responseStatusCode }: { errors: Record<string, unknown>[]; responseStatusCode: number }`,
132
- returnType: params.responseType,
133
- body: `const response = await requestQueue.add(() => fetchWithRetry(
134
- ${params.endpoint},
135
- {
136
- method: 'POST',
137
- headers: {
138
- 'Content-Type': 'application/json',
139
- 'sequence-id': sequenceId
140
- },
141
- body: JSON.stringify({
142
- type: "network-error",
143
- operationName: "${params.name}",
144
- responseStatusCode,
145
- errors
146
- }),
147
- }
148
- ));
149
-
150
- const result = await response.json();
151
- if (!response.ok) {
152
- const errorResult = result as { errors?: string[] };
153
- throw new Error(\`Failed to register fake error response: \${response.status} \${response.statusText}\${errorResult.errors ? ' - ' + JSON.stringify(errorResult.errors) : ''}\`);
154
- }
155
- return result as ${params.responseType};`
156
- });
157
- }
158
- /**
159
- * Generate called query method template
160
- */
161
- function generateCalledQuery(params) {
162
- return createMethod({
163
- name: `called${params.name}Query`,
164
- params: `sequenceId:string`,
165
- returnType: `{
166
- ok: true;
167
- data: {
168
- requestTimestamp: number;
169
- request: {
170
- headers: Record<string, unknown>;
171
- body: {
172
- operationName: string;
173
- query: string;
174
- variables: ${params.variablesType};
175
- };
176
- };
177
- response: {
178
- statusCode: number;
179
- headers: Record<string, unknown>;
180
- body: ${params.name}Query;
181
- };
182
- }[]
183
- }`,
184
- body: `const response = await requestQueue.add(() => fetchWithRetry(
185
- ${params.endpoint},
186
- {
187
- method: 'POST',
188
- headers: {
189
- 'Content-Type': 'application/json',
190
- 'sequence-id': sequenceId
191
- },
192
- body: JSON.stringify({
193
- operationName: "${params.name}"
194
- }),
195
- }
196
- ));
197
-
198
- const result = await response.json();
199
- if (!response.ok) {
200
- const errorResult = result as { errors?: string[] };
201
- throw new Error(\`Failed to get called data: \${response.status} \${response.statusText}\${errorResult.errors ? ' - ' + JSON.stringify(errorResult.errors) : ''}\`);
202
- }
203
-
204
- return result as {
205
- ok: true;
206
- data: {
207
- requestTimestamp: number;
208
- request: {
209
- headers: Record<string, unknown>;
210
- body: {
211
- operationName: string;
212
- query: string;
213
- variables: ${params.variablesType};
214
- };
215
- };
216
- response: {
217
- statusCode: number;
218
- headers: Record<string, unknown>;
219
- body: ${params.name}Query;
220
- };
221
- }[];
222
- };`
223
- });
224
- }
225
- /**
226
- * Generate called mutation method template
227
- */
228
- function generateCalledMutation(params) {
229
- return createMethod({
230
- name: `called${params.name}Mutation`,
231
- params: `sequenceId:string`,
232
- returnType: `{
233
- ok: true;
234
- data: {
235
- requestTimestamp: number;
236
- request: {
237
- headers: Record<string, unknown>;
238
- body: {
239
- operationName: string;
240
- query: string;
241
- variables: ${params.variablesType};
242
- };
243
- };
244
- response: {
245
- statusCode: number;
246
- headers: Record<string, unknown>;
247
- body: ${params.name}Mutation;
248
- };
249
- }[];
250
- }`,
251
- body: `const response = await requestQueue.add(() => fetchWithRetry(
252
- ${params.endpoint},
253
- {
254
- method: 'POST',
255
- headers: {
256
- 'Content-Type': 'application/json',
257
- 'sequence-id': sequenceId
258
- },
259
- body: JSON.stringify({
260
- operationName: "${params.name}"
261
- }),
262
- }
263
- ));
264
-
265
- const result = await response.json();
266
- if (!response.ok) {
267
- const errorResult = result as { errors?: string[] };
268
- throw new Error(\`Failed to get called data: \${response.status} \${response.statusText}\${errorResult.errors ? ' - ' + JSON.stringify(errorResult.errors) : ''}\`);
269
- }
270
-
271
- return result as {
272
- ok: true;
273
- data: {
274
- requestTimestamp: number;
275
- request: {
276
- headers: Record<string, unknown>;
277
- body: {
278
- operationName: string;
279
- query: string;
280
- variables: ${params.variablesType};
281
- };
282
- };
283
- response: {
284
- statusCode: number;
285
- headers: Record<string, unknown>;
286
- body: ${params.name}Mutation;
287
- };
288
- }[];
289
- };`
290
- });
291
- }