@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.
@@ -1,12 +1,25 @@
1
1
  import type { CodegenPlugin } from "@graphql-codegen/plugin-helpers";
2
2
  import { normalizeConfig, type RawPluginConfig } from "./config";
3
3
  import { convertName } from "./convertName";
4
+ import {
5
+ generateCalledMutation,
6
+ generateCalledQuery,
7
+ generateRegisterMutation,
8
+ generateRegisterMutationError,
9
+ generateRegisterQuery,
10
+ generateRegisterQueryError,
11
+ } from "./templates/method-generators";
12
+ import { getRuntimeCode } from "./templates/runtime";
4
13
 
5
14
  const plugin: CodegenPlugin<RawPluginConfig> = {
6
15
  plugin(_schema, documents, rawConfig, _info) {
7
16
  const config = normalizeConfig(rawConfig);
8
- const _fakeEndpoint = config.fakeServerEndpoint;
9
- const registerOperationResponseType = "{ ok: true } | { ok: false; errors: string[] }"; // Conditional fake types with generic Variables
17
+ const registerOperationResponseType = "{ ok: true }";
18
+
19
+ // Get runtime code from template function
20
+ const runtimeCode = getRuntimeCode();
21
+
22
+ // Conditional fake types with generic Variables
10
23
  const conditionRuleTypes = `
11
24
  export type FakeClientAlwaysConditionRule = { type: "always" };
12
25
  export type FakeClientVariablesConditionRule<TVariables = Record<string, any>> = { type: "variables"; value: TVariables };
@@ -24,318 +37,221 @@ export type FakeClientRegisterSequenceOptions<TVariables = Record<string, any>>
24
37
  const indentEachLine = (indent: string, text: string) => {
25
38
  return text
26
39
  .split("\n")
27
- .map((line) => `${indent}${line}`)
40
+ .map((line) => indent + line)
28
41
  .join("\n");
29
42
  };
30
43
  const generateFakeClient = (exportsFunctions: GenerateFakeFunction[]) => {
31
44
  const indent = " ";
32
- return `\
33
- export type CreateFakeClientOptions = {
34
- /**
35
- * The URL of the fake server
36
- * @example 'http://localhost:4000/fake'
37
- */
38
- fakeServerEndpoint: string;
39
- };
40
- export function createFakeClient(options: CreateFakeClientOptions) {
41
- if(!options.fakeServerEndpoint.endsWith('/fake')) {
42
- throw new Error('fakeServerEndpoint must end with "/fake"');
43
- }
44
- return {
45
- ${exportsFunctions
46
- .flatMap((fn) => {
47
- if (fn.type === "query") {
48
- return [
49
- indentEachLine(
50
- `${indent}${indent}`,
51
- generateRegisterOperationMethod(fn.name, "options.fakeServerEndpoint"),
52
- ),
53
- indentEachLine(
54
- `${indent}${indent}`,
55
- generateRegisterOperationErrorMethod(fn.name, "options.fakeServerEndpoint"),
56
- ),
57
- indentEachLine(
58
- `${indent}${indent}`,
59
- generateCalledQuery(fn.name, `options.fakeServerEndpoint + "/called"`),
60
- ),
61
- ];
62
- }
63
- if (fn.type === "mutation") {
64
- return [
65
- indentEachLine(
66
- `${indent}${indent}`,
67
- generateRegisterMutationMethod(fn.name, "options.fakeServerEndpoint"),
68
- ),
69
- indentEachLine(
70
- `${indent}${indent}`,
71
- generateRegisterMutationErrorMethod(fn.name, "options.fakeServerEndpoint"),
72
- ),
73
- indentEachLine(
74
- `${indent}${indent}`,
75
- generateCalledMutation(fn.name, `options.fakeServerEndpoint + "/called"`),
76
- ),
77
- ];
78
- }
79
- throw new Error(`Unknown type${fn}`);
80
- })
81
- .join(",\n")}
82
- };
83
- }`;
45
+
46
+ // Use runtime code from template
47
+ return (
48
+ runtimeCode +
49
+ "\n\n" +
50
+ "export function createFakeClient(options: CreateFakeClientOptions) {\n" +
51
+ " if(!options.fakeServerEndpoint.endsWith('/fake')) {\n" +
52
+ " throw new Error('fakeServerEndpoint must end with \"/fake\"');\n" +
53
+ " }\n" +
54
+ " \n" +
55
+ " // Create request queue for rate limiting\n" +
56
+ " const requestQueue = new RequestQueue();\n" +
57
+ " \n" +
58
+ " return {\n" +
59
+ exportsFunctions
60
+ .flatMap((fn) => {
61
+ if (fn.type === "query") {
62
+ return [
63
+ indentEachLine(
64
+ indent + indent,
65
+ generateRegisterOperationMethod(
66
+ fn.name,
67
+ "options.fakeServerEndpoint",
68
+ ),
69
+ ),
70
+ indentEachLine(
71
+ indent + indent,
72
+ generateRegisterOperationErrorMethod(
73
+ fn.name,
74
+ "options.fakeServerEndpoint",
75
+ ),
76
+ ),
77
+ indentEachLine(
78
+ indent + indent,
79
+ generateCalledQueryMethod(
80
+ fn.name,
81
+ 'options.fakeServerEndpoint + "/called"',
82
+ ),
83
+ ),
84
+ ];
85
+ }
86
+ if (fn.type === "mutation") {
87
+ return [
88
+ indentEachLine(
89
+ indent + indent,
90
+ generateRegisterMutationMethod(
91
+ fn.name,
92
+ "options.fakeServerEndpoint",
93
+ ),
94
+ ),
95
+ indentEachLine(
96
+ indent + indent,
97
+ generateRegisterMutationErrorMethod(
98
+ fn.name,
99
+ "options.fakeServerEndpoint",
100
+ ),
101
+ ),
102
+ indentEachLine(
103
+ indent + indent,
104
+ generateCalledMutationMethod(
105
+ fn.name,
106
+ 'options.fakeServerEndpoint + "/called"',
107
+ ),
108
+ ),
109
+ ];
110
+ }
111
+ throw new Error(`Unknown type${fn}`);
112
+ })
113
+ .join(",\n") +
114
+ "\n };\n}"
115
+ );
84
116
  };
85
117
  const generateRegisterOperationMethod = (
86
118
  name: string,
87
119
  fakeEndpointVariableName: string,
88
120
  ) => {
89
121
  const variablesType = `${convertName(name, config)}QueryVariables`;
90
- return `async register${name}QueryResponse(sequenceId:string, queryResponse: ${name}Query, sequenceOptions?: FakeClientRegisterSequenceOptions<${variablesType}>): Promise<${registerOperationResponseType}> {
91
- const requestCondition = sequenceOptions?.requestCondition ?? { type: "always" };
92
- return await fetch(${fakeEndpointVariableName}, {
93
- method: 'POST',
94
- headers: {
95
- 'Content-Type': 'application/json',
96
- 'sequence-id': sequenceId
97
- },
98
- body: JSON.stringify({
99
- type: "operation",
100
- operationName: "${name}",
101
- data: queryResponse,
102
- requestCondition: requestCondition
103
- }),
104
- }).then((res) => res.json()) as ${registerOperationResponseType};
105
- }`;
122
+ return generateRegisterQuery({
123
+ name,
124
+ variablesType,
125
+ responseType: registerOperationResponseType,
126
+ endpoint: fakeEndpointVariableName,
127
+ });
106
128
  };
107
129
  const generateRegisterOperationErrorMethod = (
108
130
  name: string,
109
131
  fakeEndpointVariableName: string,
110
132
  ) => {
111
- return `async register${name}QueryErrorResponse(sequenceId:string, { errors, responseStatusCode }: { errors: Record<string, unknown>[]; responseStatusCode: number }): Promise<${registerOperationResponseType}> {
112
- return await fetch(${fakeEndpointVariableName}, {
113
- method: 'POST',
114
- headers: {
115
- 'Content-Type': 'application/json',
116
- 'sequence-id': sequenceId
117
- },
118
- body: JSON.stringify({
119
- type: "network-error",
120
- operationName: "${name}",
121
- responseStatusCode,
122
- errors
123
- }),
124
- }).then((res) => res.json()) as ${registerOperationResponseType};
125
- }`;
133
+ return generateRegisterQueryError({
134
+ name,
135
+ responseType: registerOperationResponseType,
136
+ endpoint: fakeEndpointVariableName,
137
+ });
126
138
  };
127
139
  const generateRegisterMutationMethod = (name: string, fakeEndpointVariableName: string) => {
128
140
  const variablesType = `${convertName(name, config)}MutationVariables`;
129
- return `async register${name}MutationResponse(sequenceId:string, mutationResponse: ${name}Mutation, sequenceOptions?: FakeClientRegisterSequenceOptions<${variablesType}>): Promise<${registerOperationResponseType}> {
130
- const requestCondition = sequenceOptions?.requestCondition ?? { type: "always" };
131
- return await fetch(${fakeEndpointVariableName}, {
132
- method: 'POST',
133
- headers: {
134
- 'Content-Type': 'application/json',
135
- 'sequence-id': sequenceId
136
- },
137
- body: JSON.stringify({
138
- type: "operation",
139
- operationName: "${name}",
140
- data: mutationResponse,
141
- requestCondition: requestCondition
142
- }),
143
- }).then((res) => res.json()) as ${registerOperationResponseType};
144
- }`;
141
+ return generateRegisterMutation({
142
+ name,
143
+ variablesType,
144
+ responseType: registerOperationResponseType,
145
+ endpoint: fakeEndpointVariableName,
146
+ });
145
147
  };
146
148
  const generateRegisterMutationErrorMethod = (
147
149
  name: string,
148
150
  fakeEndpointVariableName: string,
149
151
  ) => {
150
- return `async register${name}MutationErrorResponse(sequenceId:string, { errors, responseStatusCode }: { errors: Record<string, unknown>[]; responseStatusCode: number }): Promise<${registerOperationResponseType}> {
151
- return await fetch(${fakeEndpointVariableName}, {
152
- method: 'POST',
153
- headers: {
154
- 'Content-Type': 'application/json',
155
- 'sequence-id': sequenceId
156
- },
157
- body: JSON.stringify({
158
- type: "network-error",
159
- operationName: "${name}",
160
- responseStatusCode,
161
- errors
162
- }),
163
- }).then((res) => res.json()) as ${registerOperationResponseType};
164
- }`;
152
+ return generateRegisterMutationError({
153
+ name,
154
+ responseType: registerOperationResponseType,
155
+ endpoint: fakeEndpointVariableName,
156
+ });
165
157
  };
166
- const generateCalledQuery = (name: string, calledEndpoint: string) => {
167
- return `async called${name}Query(sequenceId:string): Promise<{
168
- ok: true;
169
- data: {
170
- requestTimestamp: number;
171
- request: {
172
- headers: Record<string, unknown>;
173
- body: {
174
- operationName: string;
175
- query: string;
176
- variables: ${convertName(name, config)}QueryVariables;
177
- };
178
- };
179
- response: {
180
- statusCode: number;
181
- headers: Record<string, unknown>;
182
- body: ${convertName(name, config)}Query;
183
- };
184
- }[]
185
- }> {
186
- return await fetch(${calledEndpoint}, {
187
- method: 'POST',
188
- headers: {
189
- 'Content-Type': 'application/json',
190
- 'sequence-id': sequenceId
191
- },
192
- body: JSON.stringify({
193
- operationName: "${name}"
194
- }),
195
- }).then((res) => res.json()) as {
196
- ok: true;
197
- data: {
198
- requestTimestamp: number;
199
- request: {
200
- headers: Record<string, unknown>;
201
- body: {
202
- operationName: string;
203
- query: string;
204
- variables: ${convertName(name, config)}QueryVariables;
205
- };
206
- };
207
- response: {
208
- statusCode: number;
209
- headers: Record<string, unknown>;
210
- body: ${convertName(name, config)}Query;
211
- };
212
- }[];
213
- };
214
- }`;
158
+ const generateCalledQueryMethod = (name: string, calledEndpoint: string) => {
159
+ const variablesType = `${convertName(name, config)}QueryVariables`;
160
+ return generateCalledQuery({
161
+ name: convertName(name, config),
162
+ variablesType,
163
+ endpoint: calledEndpoint,
164
+ });
215
165
  };
216
166
 
217
- const generateCalledMutation = (name: string, calledEndpoint: string) => {
218
- return `async called${name}Mutation(sequenceId:string): Promise<{
219
- ok: true;
220
- data: {
221
- requestTimestamp: number;
222
- request: {
223
- headers: Record<string, unknown>;
224
- body: {
225
- operationName: string;
226
- query: string;
227
- variables: ${convertName(name, config)}MutationVariables;
228
- };
229
- };
230
- response: {
231
- statusCode: number;
232
- headers: Record<string, unknown>;
233
- body: ${convertName(name, config)}Mutation;
234
- };
235
- }[];
236
- }> {
237
- return await fetch(${calledEndpoint}, {
238
- method: 'POST',
239
- headers: {
240
- 'Content-Type': 'application/json',
241
- 'sequence-id': sequenceId
242
- },
243
- body: JSON.stringify({
244
- operationName: "${name}"
245
- }),
246
- }).then((res) => res.json()) as {
247
- ok: true;
248
- data: {
249
- requestTimestamp: number;
250
- request: {
251
- headers: Record<string, unknown>;
252
- body: {
253
- operationName: string;
254
- query: string;
255
- variables: ${convertName(name, config)}MutationVariables;
256
- };
257
- };
258
- response: {
259
- statusCode: number;
260
- headers: Record<string, unknown>;
261
- body: ${convertName(name, config)}Mutation;
262
- };
263
- }[];
264
- }
265
- }`;
167
+ const generateCalledMutationMethod = (name: string, calledEndpoint: string) => {
168
+ const variablesType = `${convertName(name, config)}MutationVariables`;
169
+ return generateCalledMutation({
170
+ name: convertName(name, config),
171
+ variablesType,
172
+ endpoint: calledEndpoint,
173
+ });
266
174
  };
267
175
 
268
176
  const importQueryIdentifierName = (documentName: string) => {
269
177
  return `import type { ${convertName(
270
178
  documentName,
271
179
  config,
272
- )}Query, ${convertName(documentName, config)}QueryVariables } from '${config.typesFile}';`;
180
+ )}Query, ${convertName(documentName, config)}QueryVariables } from \'${config.typesFile}\';`;
273
181
  };
274
182
  const importMutationIdentifierName = (documentName: string) => {
275
183
  return `import type { ${convertName(documentName, config)}Mutation, ${convertName(
276
184
  documentName,
277
185
  config,
278
- )}MutationVariables } from '${config.typesFile}';`;
186
+ )}MutationVariables } from \'${config.typesFile}\';`;
279
187
  };
280
- return `/* eslint-disable */
281
- // This file was generated by a @newmo/graphql-codegen-fake-server-operation
282
- ${documents
283
- .flatMap((document) => {
284
- return document.document?.definitions?.map((definition) => {
285
- // query
286
- if (
287
- definition.kind === "OperationDefinition" &&
288
- definition.operation === "query" &&
289
- definition.name
290
- ) {
291
- return importQueryIdentifierName(definition.name.value);
292
- }
293
- if (
294
- definition.kind === "OperationDefinition" &&
295
- definition.operation === "mutation" &&
296
- definition.name
297
- ) {
298
- return importMutationIdentifierName(definition.name.value);
299
- }
300
- return [];
301
- });
302
- })
303
- .join("\n")}
304
- ${conditionRuleTypes}
305
- ${generateFakeClient(
306
- documents.flatMap((document) => {
307
- const flatMap =
308
- document.document?.definitions?.flatMap((definition) => {
309
- if (
310
- definition.kind === "OperationDefinition" &&
311
- definition.operation === "query" &&
312
- definition.name
313
- ) {
314
- return [
315
- {
316
- name: convertName(definition.name.value, config),
317
- type: "query",
318
- },
319
- ] satisfies GenerateFakeFunction[] as GenerateFakeFunction[];
320
- }
321
- if (
322
- definition.kind === "OperationDefinition" &&
323
- definition.operation === "mutation" &&
324
- definition.name
325
- ) {
326
- return [
327
- {
328
- name: convertName(definition.name.value, config),
329
- type: "mutation",
330
- },
331
- ] satisfies GenerateFakeFunction[] as GenerateFakeFunction[];
332
- }
333
- return [];
334
- }) ?? [];
335
- return flatMap satisfies GenerateFakeFunction[] as GenerateFakeFunction[];
336
- }),
337
- )}
338
- `;
188
+ const importsSection = documents
189
+ .flatMap((document) => {
190
+ return document.document?.definitions?.map((definition) => {
191
+ // query
192
+ if (
193
+ definition.kind === "OperationDefinition" &&
194
+ definition.operation === "query" &&
195
+ definition.name
196
+ ) {
197
+ return importQueryIdentifierName(definition.name.value);
198
+ }
199
+ if (
200
+ definition.kind === "OperationDefinition" &&
201
+ definition.operation === "mutation" &&
202
+ definition.name
203
+ ) {
204
+ return importMutationIdentifierName(definition.name.value);
205
+ }
206
+ return [];
207
+ });
208
+ })
209
+ .join("\n");
210
+
211
+ const functionsSection = generateFakeClient(
212
+ documents.flatMap((document) => {
213
+ const flatMap =
214
+ document.document?.definitions?.flatMap((definition) => {
215
+ if (
216
+ definition.kind === "OperationDefinition" &&
217
+ definition.operation === "query" &&
218
+ definition.name
219
+ ) {
220
+ return [
221
+ {
222
+ name: convertName(definition.name.value, config),
223
+ type: "query",
224
+ },
225
+ ] satisfies GenerateFakeFunction[] as GenerateFakeFunction[];
226
+ }
227
+ if (
228
+ definition.kind === "OperationDefinition" &&
229
+ definition.operation === "mutation" &&
230
+ definition.name
231
+ ) {
232
+ return [
233
+ {
234
+ name: convertName(definition.name.value, config),
235
+ type: "mutation",
236
+ },
237
+ ] satisfies GenerateFakeFunction[] as GenerateFakeFunction[];
238
+ }
239
+ return [];
240
+ }) ?? [];
241
+ return flatMap satisfies GenerateFakeFunction[] as GenerateFakeFunction[];
242
+ }),
243
+ );
244
+
245
+ return (
246
+ "/* eslint-disable */\n" +
247
+ "// This file was generated by a @newmo/graphql-codegen-fake-server-operation\n" +
248
+ importsSection +
249
+ "\n" +
250
+ conditionRuleTypes +
251
+ "\n" +
252
+ functionsSection +
253
+ "\n"
254
+ );
339
255
  },
340
256
  };
341
257
  // GraphQL Codegen Plugin requires CommonJS export