@newmo/graphql-codegen-fake-server-client 0.22.0 → 0.23.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.
@@ -0,0 +1,175 @@
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 = 10; // 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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newmo/graphql-codegen-fake-server-client",
3
- "version": "0.22.0",
3
+ "version": "0.23.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": "345acb9af4854850a12c1418e057c7fadd7a00be"
65
+ "gitHead": "9f78beca5016a585f3de1ca2cc0a3ccb24fd743e"
66
66
  }