@sohcah/openapi-generator 0.0.2 → 0.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,29 +1,144 @@
1
1
  import { __toESM } from "../chunk-51aI8Tpl.js";
2
- import { DocumentContext, NotImplementedError, ensureImport, ensureNamespaceImport, getKey, helpers_exports, require_lib } from "../helpers-CKmqJXD5.js";
3
- import { Effect } from "effect";
2
+ import { DocumentContext, NotImplementedError, ensureImport, ensureNamespaceImport, getKey, helpers_exports, notImplementedStatement, require_lib } from "../helpers-CUZHcCFJ.js";
3
+ import { Context, Effect } from "effect";
4
+ import escapeRegex from "regex-escape";
4
5
 
6
+ //#region src/generators/requestFormats/json.ts
7
+ var import_lib$8 = /* @__PURE__ */ __toESM(require_lib(), 1);
8
+ const generateJsonRequestCodec = Effect.fn(function* (options, schema, decoded) {
9
+ return options.transformer({
10
+ encoded: options.schema.string,
11
+ decoded,
12
+ decode: notImplementedStatement,
13
+ encode: import_lib$8.callExpression(import_lib$8.memberExpression(import_lib$8.identifier("JSON"), import_lib$8.identifier("stringify")), [import_lib$8.identifier("from")])
14
+ });
15
+ });
16
+
17
+ //#endregion
18
+ //#region src/generators/requestFormats/formData.ts
19
+ var import_lib$7 = /* @__PURE__ */ __toESM(require_lib(), 1);
20
+ const maybeStringify = Effect.fn(function* (expression, schema) {
21
+ const resolved = yield* resolveSchema(schema);
22
+ if (resolved.type === "object" || resolved.type === "array") return import_lib$7.callExpression(import_lib$7.memberExpression(import_lib$7.identifier("JSON"), import_lib$7.identifier("stringify")), [expression]);
23
+ if (resolved.type === "string") return expression;
24
+ return import_lib$7.callExpression(import_lib$7.identifier("String"), [expression]);
25
+ });
26
+ const generateFormDataRequestCodec = Effect.fn(function* (options, schema, decoded) {
27
+ const encode = import_lib$7.blockStatement([import_lib$7.variableDeclaration("const", [import_lib$7.variableDeclarator(import_lib$7.identifier("formData"), import_lib$7.newExpression(import_lib$7.identifier("FormData"), []))])]);
28
+ const properties = schema.properties ?? {};
29
+ for (const [propertyKey, rawProperty] of Object.entries(properties)) {
30
+ const property = yield* resolveSchema(rawProperty);
31
+ const propertyExpression = import_lib$7.memberExpression(import_lib$7.identifier("from"), import_lib$7.stringLiteral(propertyKey), true);
32
+ if (property.type === "array") {
33
+ encode.body.push(import_lib$7.forOfStatement(import_lib$7.variableDeclaration("const", [import_lib$7.variableDeclarator(import_lib$7.identifier("propertyValue"))]), propertyExpression, import_lib$7.blockStatement([import_lib$7.expressionStatement(import_lib$7.callExpression(import_lib$7.memberExpression(import_lib$7.identifier("formData"), import_lib$7.identifier("append")), [import_lib$7.stringLiteral(propertyKey), yield* maybeStringify(import_lib$7.identifier("propertyValue"), property.items)]))])));
34
+ continue;
35
+ }
36
+ encode.body.push(import_lib$7.expressionStatement(import_lib$7.callExpression(import_lib$7.memberExpression(import_lib$7.identifier("formData"), import_lib$7.identifier("append")), [import_lib$7.stringLiteral(propertyKey), yield* maybeStringify(propertyExpression, property)])));
37
+ }
38
+ encode.body.push(import_lib$7.returnStatement(import_lib$7.identifier("formData")));
39
+ return options.transformer({
40
+ encoded: import_lib$7.callExpression(options.schema.instanceOf, [import_lib$7.identifier("FormData")]),
41
+ decoded,
42
+ decode: notImplementedStatement,
43
+ encode
44
+ });
45
+ });
46
+
47
+ //#endregion
48
+ //#region src/generators/generatePathExpression.ts
49
+ var import_lib$6 = /* @__PURE__ */ __toESM(require_lib(), 1);
50
+ function generatePathExpression(path, pathParameters, queryParameter) {
51
+ let modifiedPath = path;
52
+ if (queryParameter) modifiedPath += "?";
53
+ const split = modifiedPath.split(new RegExp(`\\{(${Object.keys(pathParameters).map((i) => escapeRegex(i)).join("|")})\\}`, "g"));
54
+ const quasis = [];
55
+ const expressions = [];
56
+ for (const [i, part] of split.entries()) if (i % 2 === 0) quasis.push(import_lib$6.templateElement({
57
+ raw: part,
58
+ cooked: part
59
+ }, false));
60
+ else {
61
+ const paramExpression = pathParameters[part];
62
+ if (!paramExpression) throw new Error(`Path parameter ${part} not found`);
63
+ expressions.push(paramExpression);
64
+ }
65
+ if (queryParameter) {
66
+ expressions.push(queryParameter);
67
+ quasis.push(import_lib$6.templateElement({
68
+ raw: "",
69
+ cooked: ""
70
+ }, false));
71
+ }
72
+ return import_lib$6.templateLiteral(quasis, expressions);
73
+ }
74
+
75
+ //#endregion
76
+ //#region src/generators/responseFormats/json.ts
77
+ var import_lib$5 = /* @__PURE__ */ __toESM(require_lib(), 1);
78
+ const generateJsonResponseCodec = Effect.fn(function* (options, schema, decoded) {
79
+ return options.transformer({
80
+ encoded: import_lib$5.callExpression(options.schema.instanceOf, [import_lib$5.identifier("Response")]),
81
+ decoded,
82
+ decode: import_lib$5.blockStatement([import_lib$5.tryStatement(import_lib$5.blockStatement([import_lib$5.returnStatement(import_lib$5.tsAsExpression(import_lib$5.awaitExpression(import_lib$5.callExpression(import_lib$5.memberExpression(import_lib$5.identifier("from"), import_lib$5.identifier("json")), [])), import_lib$5.tsAnyKeyword()))]), import_lib$5.catchClause(Object.assign(import_lib$5.identifier("error"), { typeAnnotation: import_lib$5.tsTypeAnnotation(import_lib$5.tsUnknownKeyword()) }), options.transformerCatch(import_lib$5.identifier("error"))))]),
83
+ decodeAsync: true,
84
+ encode: notImplementedStatement
85
+ });
86
+ });
87
+
88
+ //#endregion
89
+ //#region src/generators/responseFormats/blob.ts
90
+ var import_lib$4 = /* @__PURE__ */ __toESM(require_lib(), 1);
91
+ const generateBlobResponseCodec = Effect.fn(function* (options) {
92
+ return options.transformer({
93
+ encoded: import_lib$4.callExpression(options.schema.instanceOf, [import_lib$4.identifier("Response")]),
94
+ decoded: import_lib$4.callExpression(options.schema.instanceOf, [import_lib$4.identifier("Blob")]),
95
+ decode: import_lib$4.blockStatement([import_lib$4.tryStatement(import_lib$4.blockStatement([import_lib$4.returnStatement(import_lib$4.tsAsExpression(import_lib$4.awaitExpression(import_lib$4.callExpression(import_lib$4.memberExpression(import_lib$4.identifier("from"), import_lib$4.identifier("blob")), [])), import_lib$4.tsAnyKeyword()))]), import_lib$4.catchClause(Object.assign(import_lib$4.identifier("error"), { typeAnnotation: import_lib$4.tsTypeAnnotation(import_lib$4.tsUnknownKeyword()) }), options.transformerCatch(import_lib$4.identifier("error"))))]),
96
+ decodeAsync: true,
97
+ encode: notImplementedStatement
98
+ });
99
+ });
100
+
101
+ //#endregion
5
102
  //#region src/generators/schema.ts
6
103
  var import_lib$3 = /* @__PURE__ */ __toESM(require_lib(), 1);
7
104
  const equivalentType = (type) => ({
8
105
  typeDecoded: type,
9
106
  typeEncoded: type
10
107
  });
11
- function defaultParseJson(options) {
12
- return (expression) => options.transformer({
13
- encoded: options.schema.string,
14
- decoded: expression,
15
- decode: import_lib$3.blockStatement([import_lib$3.tryStatement(import_lib$3.blockStatement([import_lib$3.returnStatement(import_lib$3.callExpression(import_lib$3.memberExpression(import_lib$3.identifier("JSON"), import_lib$3.identifier("parse")), [import_lib$3.identifier("from")]))]), import_lib$3.catchClause(Object.assign(import_lib$3.identifier("error"), { typeAnnotation: import_lib$3.tsTypeAnnotation(import_lib$3.tsUnknownKeyword()) }), options.transformerCatch(import_lib$3.identifier("error"))))]),
16
- encode: import_lib$3.callExpression(import_lib$3.memberExpression(import_lib$3.identifier("JSON"), import_lib$3.identifier("stringify")), [import_lib$3.identifier("from")])
17
- });
18
- }
108
+ const resolveSchema = Effect.fn(function* (schema) {
109
+ const ctx = yield* DocumentContext;
110
+ let resolvedSchema = schema;
111
+ for (let i = 0; i < 10; i++) {
112
+ if (!("$ref" in resolvedSchema)) return resolvedSchema;
113
+ const ref = resolvedSchema.$ref;
114
+ if (!ref.startsWith("#/components/schemas/")) return yield* new NotImplementedError({ message: `$ref ${ref}` });
115
+ const schemaName = ref.slice(21);
116
+ const nextSchema = ctx.document.components?.schemas?.[schemaName];
117
+ if (!nextSchema) return yield* new NotImplementedError({ message: `Missing $ref ${ref}` });
118
+ resolvedSchema = nextSchema;
119
+ }
120
+ return yield* new NotImplementedError({ message: `Too many $ref in schema` });
121
+ });
122
+ const stringLiteralOrIdentifier = (value) => {
123
+ if (value.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/)) return import_lib$3.identifier(value);
124
+ return import_lib$3.stringLiteral(value);
125
+ };
126
+ const memberExpressionWithStringProperty = (object, property) => {
127
+ if (property.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/)) return import_lib$3.memberExpression(object, import_lib$3.identifier(property));
128
+ return import_lib$3.memberExpression(object, import_lib$3.stringLiteral(property), true);
129
+ };
19
130
  function createSchemaGenerator(options) {
20
131
  const ensureStandardParametersSchema = Effect.fn(function* () {
21
132
  const ctx = yield* DocumentContext;
22
133
  if (!ctx.schemas.has("ParametersSchema")) ctx.schemas.set("ParametersSchema", [import_lib$3.exportNamedDeclaration(import_lib$3.variableDeclaration("const", [import_lib$3.variableDeclarator(import_lib$3.identifier("ParametersSchema"), import_lib$3.callExpression(options.schema.object, [import_lib$3.objectExpression([
23
- import_lib$3.objectProperty(import_lib$3.identifier("query"), options.modifiers.optional(import_lib$3.callExpression(options.schema.instanceOf, [import_lib$3.identifier("URLSearchParams")]))),
134
+ import_lib$3.objectProperty(import_lib$3.identifier("path"), options.schema.string),
24
135
  import_lib$3.objectProperty(import_lib$3.identifier("headers"), options.modifiers.optional(import_lib$3.callExpression(options.schema.instanceOf, [import_lib$3.identifier("Headers")]))),
25
- import_lib$3.objectProperty(import_lib$3.identifier("path"), options.modifiers.optional(options.schema.record(options.schema.string, options.schema.string))),
26
- import_lib$3.objectProperty(import_lib$3.identifier("body"), options.modifiers.optional(options.schema.union([options.schema.string, import_lib$3.callExpression(options.schema.instanceOf, [import_lib$3.identifier("Blob")])])))
136
+ import_lib$3.objectProperty(import_lib$3.identifier("body"), options.modifiers.optional(options.schema.union([
137
+ options.schema.string,
138
+ import_lib$3.callExpression(options.schema.instanceOf, [import_lib$3.identifier("Blob")]),
139
+ import_lib$3.callExpression(options.schema.instanceOf, [import_lib$3.identifier("FormData")]),
140
+ import_lib$3.callExpression(options.schema.instanceOf, [import_lib$3.identifier("URLSearchParams")])
141
+ ])))
27
142
  ])]))]))]);
28
143
  return import_lib$3.identifier("ParametersSchema");
29
144
  });
@@ -89,11 +204,16 @@ function createSchemaGenerator(options) {
89
204
  };
90
205
  }
91
206
  if (schema.enum) {
92
- const unsupportedEnumValue = schema.enum.find((i) => typeof i !== "string");
207
+ const unsupportedEnumValue = schema.enum.find((i) => typeof i !== "string" && typeof i !== "number" && typeof i !== "boolean" && i !== null);
93
208
  if (unsupportedEnumValue !== void 0) return yield* new NotImplementedError({ message: `Unsupported 'enum' value: ${JSON.stringify(unsupportedEnumValue)}` });
209
+ const getLiteral = (value) => {
210
+ if (typeof value === "number") return import_lib$3.numericLiteral(value);
211
+ if (typeof value === "boolean") return import_lib$3.booleanLiteral(value);
212
+ return import_lib$3.stringLiteral(value);
213
+ };
94
214
  return {
95
- expression: options.schema.enum(schema.enum.map((e) => import_lib$3.stringLiteral(e))),
96
- ...equivalentType(import_lib$3.tsUnionType(schema.enum.map((e) => import_lib$3.tsLiteralType(import_lib$3.stringLiteral(e))))),
215
+ expression: options.schema.enum(schema.enum.map((e) => e === null ? import_lib$3.nullLiteral() : getLiteral(e))),
216
+ ...equivalentType(import_lib$3.tsUnionType(schema.enum.map((e) => e === null ? import_lib$3.tsNullKeyword() : import_lib$3.tsLiteralType(getLiteral(e))))),
97
217
  typeMeta
98
218
  };
99
219
  }
@@ -104,6 +224,11 @@ function createSchemaGenerator(options) {
104
224
  typeMeta
105
225
  };
106
226
  case "string": {
227
+ if (schema.format === "binary") return {
228
+ expression: import_lib$3.callExpression(options.schema.instanceOf, [import_lib$3.identifier("Blob")]),
229
+ ...equivalentType(import_lib$3.tsTypeReference(import_lib$3.identifier("Blob"))),
230
+ typeMeta
231
+ };
107
232
  let expression = {
108
233
  expression: options.schema.string,
109
234
  ...equivalentType(import_lib$3.tsStringKeyword()),
@@ -137,7 +262,7 @@ function createSchemaGenerator(options) {
137
262
  decodedMember.optional = true;
138
263
  encodedMember.optional = true;
139
264
  }
140
- const objectProperty = import_lib$3.objectProperty(import_lib$3.identifier(propertyKey), propertySchema.expression);
265
+ const objectProperty = import_lib$3.objectProperty(stringLiteralOrIdentifier(propertyKey), propertySchema.expression);
141
266
  if (property.description) import_lib$3.addComment(objectProperty, "leading", `* ${property.description}`);
142
267
  object.properties.push(objectProperty);
143
268
  objectTypeDecoded.members.push(decodedMember);
@@ -220,44 +345,40 @@ function createSchemaGenerator(options) {
220
345
  };
221
346
  return expressions[0];
222
347
  });
223
- const ensureParametersSchema = Effect.fn(function* (operationKey, method) {
348
+ const ensureParametersSchema = Effect.fn(function* (operationKey, method, path) {
224
349
  const ctx = yield* DocumentContext;
225
350
  const identifier = import_lib$3.identifier(`${operationKey.upper}_Parameters`);
226
351
  const object = import_lib$3.objectExpression([]);
227
352
  const queryArray = import_lib$3.arrayExpression([]);
228
- const pathObject = import_lib$3.objectExpression([]);
353
+ const pathParameters = {};
229
354
  const headerArray = import_lib$3.arrayExpression([]);
230
355
  let hasBody = false;
231
- for (const parameter of method.parameters ?? []) {
232
- if ("$ref" in parameter) return yield* new NotImplementedError({ message: "$ref in parameter" });
356
+ for (let parameter of method.parameters ?? []) {
357
+ if ("$ref" in parameter) {
358
+ const newParameter = ctx.document.components?.parameters?.[parameter.$ref.slice(24)];
359
+ if (newParameter) parameter = newParameter;
360
+ else return yield* new NotImplementedError({ message: "Unresolved $ref in parameter" });
361
+ if ("$ref" in parameter) return yield* new NotImplementedError({ message: "$ref in parameter" });
362
+ }
233
363
  if (!parameter.schema) return yield* new NotImplementedError({ message: "parameter without schema" });
234
364
  let expression = (yield* ensureSchema(parameter.schema)).expression;
235
365
  if (!parameter.required) expression = options.modifiers.optional(expression);
236
- const objectProperty = import_lib$3.objectProperty(import_lib$3.identifier(parameter.name), expression);
366
+ const objectProperty = import_lib$3.objectProperty(stringLiteralOrIdentifier(parameter.name), expression);
237
367
  if (parameter.description) import_lib$3.addComment(objectProperty, "leading", `* ${parameter.description}`);
238
368
  object.properties.push(objectProperty);
239
369
  if (parameter.in === "query") {
240
- const param = import_lib$3.memberExpression(import_lib$3.identifier("from"), import_lib$3.identifier(parameter.name));
241
- if ("type" in parameter.schema && parameter.schema.type === "array") queryArray.elements.push(import_lib$3.spreadElement(import_lib$3.logicalExpression("??", Object.assign(import_lib$3.optionalCallExpression(import_lib$3.optionalMemberExpression(param, import_lib$3.identifier("map"), false, true), [import_lib$3.arrowFunctionExpression([import_lib$3.identifier("value")], import_lib$3.arrayExpression([import_lib$3.stringLiteral(parameter.name), import_lib$3.callExpression(import_lib$3.identifier("String"), [import_lib$3.identifier("value")])]))], false), { typeParameters: import_lib$3.tsTypeParameterInstantiation([import_lib$3.tsTypeReference(import_lib$3.identifier("[string, string]"))]) }), import_lib$3.arrayExpression([]))));
370
+ const param = memberExpressionWithStringProperty(import_lib$3.identifier("from"), parameter.name);
371
+ if ("type" in parameter.schema && parameter.schema.type === "array") queryArray.elements.push(import_lib$3.spreadElement(import_lib$3.logicalExpression("??", Object.assign(import_lib$3.optionalCallExpression(import_lib$3.optionalMemberExpression(param, import_lib$3.identifier("map"), false, true), [import_lib$3.arrowFunctionExpression([import_lib$3.identifier("value")], import_lib$3.arrayExpression([import_lib$3.stringLiteral(parameter.name), import_lib$3.callExpression(import_lib$3.identifier("String"), [import_lib$3.identifier("value")])]))], false), { typeParameters: import_lib$3.tsTypeParameterInstantiation([import_lib$3.tsTupleType([import_lib$3.tsStringKeyword(), import_lib$3.tsStringKeyword()])]) }), import_lib$3.arrayExpression([]))));
242
372
  else queryArray.elements.push(import_lib$3.arrayExpression([import_lib$3.stringLiteral(parameter.name), import_lib$3.callExpression(import_lib$3.identifier("String"), [param])]));
243
- } else if (parameter.in === "path") pathObject.properties.push(import_lib$3.objectProperty(import_lib$3.identifier(parameter.name), import_lib$3.callExpression(import_lib$3.identifier("String"), [import_lib$3.memberExpression(import_lib$3.identifier("from"), import_lib$3.identifier(parameter.name))])));
244
- else if (parameter.in === "header") headerArray.elements.push(import_lib$3.arrayExpression([import_lib$3.stringLiteral(parameter.name), import_lib$3.callExpression(import_lib$3.identifier("String"), [import_lib$3.memberExpression(import_lib$3.identifier("from"), import_lib$3.identifier(parameter.name))])]));
373
+ } else if (parameter.in === "path") pathParameters[parameter.name] = memberExpressionWithStringProperty(import_lib$3.identifier("from"), parameter.name);
374
+ else if (parameter.in === "header") headerArray.elements.push(import_lib$3.arrayExpression([import_lib$3.stringLiteral(parameter.name), import_lib$3.callExpression(import_lib$3.identifier("String"), [memberExpressionWithStringProperty(import_lib$3.identifier("from"), parameter.name)])]));
245
375
  else return yield* new NotImplementedError({ message: `parameter in ${parameter.in}` });
246
376
  }
247
- body: if (method.requestBody) {
248
- if ("$ref" in method.requestBody) return yield* new NotImplementedError({ message: "$ref in requestBody" });
249
- for (const contentKey in method.requestBody.content) {
250
- hasBody = true;
251
- const schema = method.requestBody.content[contentKey]?.schema;
252
- if (!!schema && contentKey === "application/json") {
253
- object.properties.push(import_lib$3.objectProperty(import_lib$3.identifier("data"), (options.builtins.parseJson ?? defaultParseJson(options))((yield* ensureSchema(schema)).expression)));
254
- break body;
255
- } else if (contentKey === "application/octet-stream") {
256
- object.properties.push(import_lib$3.objectProperty(import_lib$3.identifier("data"), import_lib$3.callExpression(options.schema.instanceOf, [import_lib$3.identifier("Blob")])));
257
- break body;
258
- }
259
- }
260
- return yield* new NotImplementedError({ message: `No supported requestBody type (${Object.keys(method.requestBody.content).join(", ")})` });
377
+ const body = yield* requestBodySchema(operationKey, method);
378
+ if (body) {
379
+ hasBody = true;
380
+ object.properties.push(import_lib$3.objectProperty(import_lib$3.identifier("data"), body.data));
381
+ headerArray.elements.push(...body.headers);
261
382
  }
262
383
  const decodedSchema = import_lib$3.callExpression(options.schema.object, [object]);
263
384
  const transform = options.transformer({
@@ -265,9 +386,8 @@ function createSchemaGenerator(options) {
265
386
  decoded: decodedSchema,
266
387
  decode: import_lib$3.blockStatement([import_lib$3.throwStatement(import_lib$3.newExpression(import_lib$3.identifier("Error"), [import_lib$3.stringLiteral("Not implemented")]))]),
267
388
  encode: import_lib$3.objectExpression([
268
- ...queryArray.elements.length ? [import_lib$3.objectProperty(import_lib$3.identifier("query"), import_lib$3.newExpression(import_lib$3.identifier("URLSearchParams"), [queryArray]))] : [],
269
- ...pathObject.properties.length ? [import_lib$3.objectProperty(import_lib$3.identifier("path"), pathObject)] : [],
270
- ...headerArray.elements.length ? [import_lib$3.objectProperty(import_lib$3.identifier("header"), import_lib$3.newExpression(import_lib$3.identifier("Headers"), [headerArray]))] : [],
389
+ import_lib$3.objectProperty(import_lib$3.identifier("path"), generatePathExpression(path, pathParameters, queryArray.elements.length ? import_lib$3.newExpression(import_lib$3.identifier("URLSearchParams"), [queryArray]) : null)),
390
+ ...headerArray.elements.length ? [import_lib$3.objectProperty(import_lib$3.identifier("headers"), import_lib$3.newExpression(import_lib$3.identifier("Headers"), [headerArray]))] : [],
271
391
  ...hasBody ? [import_lib$3.objectProperty(import_lib$3.identifier("body"), import_lib$3.memberExpression(import_lib$3.identifier("from"), import_lib$3.identifier("data")))] : []
272
392
  ])
273
393
  });
@@ -277,16 +397,65 @@ function createSchemaGenerator(options) {
277
397
  typeReference: import_lib$3.tsTypeReference(options.types.typeDecoded, import_lib$3.tsTypeParameterInstantiation([import_lib$3.tsTypeQuery(identifier)]))
278
398
  };
279
399
  });
400
+ const requestBodySchema = Effect.fn(function* (operationKey, method) {
401
+ if (!method.requestBody) return null;
402
+ if ("$ref" in method.requestBody) return yield* new NotImplementedError({ message: "$ref in requestBody" });
403
+ let hasBody = false;
404
+ for (const contentType in method.requestBody.content) {
405
+ hasBody = true;
406
+ const schema = method.requestBody.content[contentType]?.schema;
407
+ if (contentType === "application/json") {
408
+ if (!schema) continue;
409
+ return {
410
+ headers: [import_lib$3.arrayExpression([import_lib$3.stringLiteral("Content-Type"), import_lib$3.stringLiteral("application/json")])],
411
+ data: yield* generateJsonRequestCodec(options, yield* resolveSchema(schema), (yield* ensureSchema(schema)).expression)
412
+ };
413
+ } else if (contentType === "multipart/form-data") {
414
+ if (!schema) continue;
415
+ return {
416
+ headers: [],
417
+ data: yield* generateFormDataRequestCodec(options, yield* resolveSchema(schema), (yield* ensureSchema(schema)).expression)
418
+ };
419
+ } else {
420
+ if (schema && ("$ref" in schema || schema.type !== "string" && schema.format !== "binary")) continue;
421
+ return {
422
+ headers: [import_lib$3.arrayExpression([import_lib$3.stringLiteral("Content-Type"), import_lib$3.stringLiteral(contentType)])],
423
+ data: import_lib$3.callExpression(options.schema.instanceOf, [import_lib$3.identifier("Blob")])
424
+ };
425
+ }
426
+ }
427
+ if (!hasBody) return null;
428
+ return yield* new NotImplementedError({ message: `No supported requestBody type (${Object.keys(method.requestBody.content).join(", ")}) in ${operationKey.upper}` });
429
+ });
430
+ const responseSchema = Effect.fn(function* (content) {
431
+ if (content) {
432
+ for (const [format, formatContent] of Object.entries(content)) if (format === "application/json") {
433
+ if (!formatContent.schema) continue;
434
+ const schema = formatContent.schema;
435
+ const decodedSchema = (yield* ensureSchema(schema)).expression;
436
+ return yield* generateJsonResponseCodec(options, yield* resolveSchema(schema), decodedSchema);
437
+ }
438
+ }
439
+ return yield* generateBlobResponseCodec(options);
440
+ });
280
441
  const ensureResponseSchema = Effect.fn(function* (operationKey, method) {
281
442
  const ctx = yield* DocumentContext;
282
- if (!method.responses?.["200"]) return null;
283
- if ("$ref" in method.responses["200"]) return yield* new NotImplementedError({ message: "$ref in response" });
284
- if (!method.responses["200"].content) return null;
285
- if (!method.responses["200"].content["application/json"]?.schema) return yield* new NotImplementedError({ message: `response without 'application/json' content schema in ${operationKey.upper}` });
286
- const schema = method.responses["200"].content["application/json"].schema;
443
+ let transform;
444
+ if (!method.responses?.["200"]) transform = yield* responseSchema(void 0);
445
+ else {
446
+ let response;
447
+ if ("$ref" in method.responses["200"]) {
448
+ const ref = method.responses["200"].$ref;
449
+ if (!ref.startsWith("#/components/responses/")) return yield* new NotImplementedError({ message: `$ref ${ref} in response in ${operationKey.upper}` });
450
+ const responseName = ref.slice(23);
451
+ const newResponse = ctx.document.components?.responses?.[responseName];
452
+ if (!newResponse) return yield* new NotImplementedError({ message: `Missing $ref ${ref} in response in ${operationKey.upper}` });
453
+ if ("$ref" in newResponse) return yield* new NotImplementedError({ message: `$ref in $ref in response in ${operationKey.upper}` });
454
+ response = newResponse;
455
+ } else response = method.responses["200"];
456
+ transform = yield* responseSchema(response.content);
457
+ }
287
458
  const identifier = import_lib$3.identifier(`${operationKey.upper}_Response`);
288
- const decodedSchema = (yield* ensureSchema(schema)).expression;
289
- const transform = (options.builtins.parseJson ?? defaultParseJson(options))(decodedSchema);
290
459
  ctx.schemas.set(identifier.name, [import_lib$3.exportNamedDeclaration(import_lib$3.variableDeclaration("const", [import_lib$3.variableDeclarator(identifier, transform)]))]);
291
460
  return {
292
461
  expression: identifier,
@@ -296,17 +465,25 @@ function createSchemaGenerator(options) {
296
465
  const processSchema = Effect.fn(function* (schema) {
297
466
  if (options.includeSchemas ?? true) yield* ensureSchema(schema);
298
467
  });
299
- const processOperation = Effect.fn(function* (operationKey, _path, _method, operation) {
468
+ const processOperation = Effect.fn(function* (operationKey, path, _method, operation) {
300
469
  if (options.includeOperations) {
301
- yield* ensureParametersSchema(operationKey, operation);
470
+ yield* ensureParametersSchema(operationKey, operation, path);
302
471
  yield* ensureResponseSchema(operationKey, operation);
303
472
  }
304
473
  });
474
+ const decodeResponse = Effect.fn(function* (schema, response) {
475
+ return options.methods.decode(schema, response);
476
+ });
477
+ const encodeParameters = Effect.fn(function* (schema, response) {
478
+ return options.methods.encode(schema, response);
479
+ });
305
480
  return {
306
481
  processSchema,
307
482
  processOperation,
308
483
  ensureParametersSchema,
309
484
  ensureResponseSchema,
485
+ decodeResponse,
486
+ encodeParameters,
310
487
  get schemaType() {
311
488
  return options.types.schema;
312
489
  }
@@ -346,26 +523,37 @@ const createEffectSchemaGenerator = (options) => ({
346
523
  null: import_lib$2.memberExpression(import_lib$2.identifier("Schema"), import_lib$2.identifier("Null")),
347
524
  unknown: import_lib$2.memberExpression(import_lib$2.identifier("Schema"), import_lib$2.identifier("Unknown"))
348
525
  },
349
- transformer: ({ encoded, decoded, decode, encode }) => import_lib$2.callExpression(import_lib$2.memberExpression(import_lib$2.identifier("Schema"), import_lib$2.identifier("transform")), [
350
- encoded,
351
- decoded,
352
- import_lib$2.objectExpression([
353
- import_lib$2.objectProperty(import_lib$2.identifier("strict"), import_lib$2.booleanLiteral(true)),
354
- import_lib$2.objectProperty(import_lib$2.identifier("decode"), import_lib$2.arrowFunctionExpression([import_lib$2.identifier("from"), import_lib$2.identifier("ctx")], decode)),
355
- import_lib$2.objectProperty(import_lib$2.identifier("encode"), import_lib$2.arrowFunctionExpression([import_lib$2.identifier("from"), import_lib$2.identifier("ctx")], encode))
356
- ])
357
- ]),
526
+ transformer: ({ encoded, decoded, decode, decodeAsync, encode, encodeAsync }) => {
527
+ let decodeFn;
528
+ let encodeFn;
529
+ if (decodeAsync || encodeAsync) {
530
+ decodeFn = import_lib$2.arrowFunctionExpression([import_lib$2.identifier("from"), import_lib$2.identifier("ctx")], import_lib$2.callExpression(import_lib$2.memberExpression(import_lib$2.identifier("Effect"), import_lib$2.identifier("promise")), [import_lib$2.arrowFunctionExpression([], decode, true)]));
531
+ encodeFn = import_lib$2.arrowFunctionExpression([import_lib$2.identifier("from"), import_lib$2.identifier("ctx")], import_lib$2.callExpression(import_lib$2.memberExpression(import_lib$2.identifier("Effect"), import_lib$2.identifier("promise")), [import_lib$2.arrowFunctionExpression([], encode, true)]));
532
+ } else {
533
+ decodeFn = import_lib$2.arrowFunctionExpression([import_lib$2.identifier("from"), import_lib$2.identifier("ctx")], decode);
534
+ encodeFn = import_lib$2.arrowFunctionExpression([import_lib$2.identifier("from"), import_lib$2.identifier("ctx")], encode);
535
+ }
536
+ return import_lib$2.callExpression(import_lib$2.memberExpression(import_lib$2.identifier("Schema"), import_lib$2.identifier(decodeAsync || encodeAsync ? "transformOrFail" : "transform")), [
537
+ encoded,
538
+ decoded,
539
+ import_lib$2.objectExpression([
540
+ import_lib$2.objectProperty(import_lib$2.identifier("strict"), import_lib$2.booleanLiteral(true)),
541
+ import_lib$2.objectProperty(import_lib$2.identifier("decode"), decodeFn),
542
+ import_lib$2.objectProperty(import_lib$2.identifier("encode"), encodeFn)
543
+ ])
544
+ ]);
545
+ },
358
546
  transformerCatch: (expression) => import_lib$2.blockStatement([import_lib$2.throwStatement(expression)]),
359
- builtins: { parseJson: (expression) => import_lib$2.callExpression(import_lib$2.memberExpression(import_lib$2.identifier("Schema"), import_lib$2.identifier("parseJson")), [expression]) },
360
547
  methods: {
361
- encode: (schema, value) => import_lib$2.callExpression(import_lib$2.callExpression(import_lib$2.memberExpression(import_lib$2.identifier("Schema"), import_lib$2.identifier("encodeSync")), [schema]), [value]),
362
- decode: (schema, value) => import_lib$2.callExpression(import_lib$2.callExpression(import_lib$2.memberExpression(import_lib$2.identifier("Schema"), import_lib$2.identifier("decodeSync")), [schema]), [value]),
363
- parse: (schema, value) => import_lib$2.callExpression(import_lib$2.callExpression(import_lib$2.memberExpression(import_lib$2.identifier("Schema"), import_lib$2.identifier("decodeUnknownSync")), [schema]), [value])
548
+ encode: (schema, value) => import_lib$2.callExpression(import_lib$2.callExpression(import_lib$2.memberExpression(import_lib$2.identifier("Schema"), import_lib$2.identifier("encodePromise")), [schema]), [value]),
549
+ decode: (schema, value) => import_lib$2.callExpression(import_lib$2.callExpression(import_lib$2.memberExpression(import_lib$2.identifier("Schema"), import_lib$2.identifier("decodePromise")), [schema]), [value]),
550
+ parse: (schema, value) => import_lib$2.callExpression(import_lib$2.callExpression(import_lib$2.memberExpression(import_lib$2.identifier("Schema"), import_lib$2.identifier("decodeUnknownPromise")), [schema]), [value])
364
551
  },
365
552
  supportsImmutability: true
366
553
  }),
367
554
  initialize: Effect.fn(function* () {
368
555
  yield* ensureNamespaceImport("Schema", "effect/Schema");
556
+ yield* ensureImport("Effect", "effect");
369
557
  })
370
558
  });
371
559
 
@@ -405,21 +593,20 @@ const createZodSchemaGenerator = ({ mini = false,...options }) => {
405
593
  null: import_lib$1.callExpression(import_lib$1.memberExpression(z, import_lib$1.identifier("null")), []),
406
594
  unknown: import_lib$1.callExpression(import_lib$1.memberExpression(z, import_lib$1.identifier("unknown")), [])
407
595
  },
408
- transformer: ({ encoded, decoded, decode, encode }) => import_lib$1.callExpression(import_lib$1.memberExpression(z, import_lib$1.identifier("codec")), [
596
+ transformer: ({ encoded, decoded, decode, decodeAsync, encode, encodeAsync }) => import_lib$1.callExpression(import_lib$1.memberExpression(z, import_lib$1.identifier("codec")), [
409
597
  encoded,
410
598
  decoded,
411
- import_lib$1.objectExpression([import_lib$1.objectProperty(import_lib$1.identifier("decode"), import_lib$1.arrowFunctionExpression([import_lib$1.identifier("from"), import_lib$1.identifier("ctx")], decode)), import_lib$1.objectProperty(import_lib$1.identifier("encode"), import_lib$1.arrowFunctionExpression([import_lib$1.identifier("from"), import_lib$1.identifier("ctx")], encode))])
599
+ import_lib$1.objectExpression([import_lib$1.objectProperty(import_lib$1.identifier("decode"), import_lib$1.arrowFunctionExpression([import_lib$1.identifier("from"), import_lib$1.identifier("ctx")], decode, decodeAsync)), import_lib$1.objectProperty(import_lib$1.identifier("encode"), import_lib$1.arrowFunctionExpression([import_lib$1.identifier("from"), import_lib$1.identifier("ctx")], encode, encodeAsync))])
412
600
  ]),
413
601
  transformerCatch: (expression) => import_lib$1.blockStatement([import_lib$1.expressionStatement(import_lib$1.callExpression(import_lib$1.memberExpression(import_lib$1.memberExpression(import_lib$1.identifier("ctx"), import_lib$1.identifier("issues")), import_lib$1.identifier("push")), [import_lib$1.objectExpression([
414
602
  import_lib$1.objectProperty(import_lib$1.identifier("code"), import_lib$1.stringLiteral("custom")),
415
603
  import_lib$1.objectProperty(import_lib$1.identifier("input"), import_lib$1.identifier("from")),
416
604
  import_lib$1.objectProperty(import_lib$1.identifier("message"), import_lib$1.memberExpression(import_lib$1.tsAsExpression(expression, import_lib$1.tsTypeReference(import_lib$1.identifier("Error"))), import_lib$1.identifier("message")))
417
605
  ])])), import_lib$1.returnStatement(import_lib$1.memberExpression(import_lib$1.identifier("z"), import_lib$1.identifier("NEVER")))]),
418
- builtins: {},
419
606
  methods: {
420
- encode: (schema, value) => import_lib$1.callExpression(import_lib$1.memberExpression(import_lib$1.identifier("z"), import_lib$1.identifier("encode")), [schema, value]),
421
- decode: (schema, value) => import_lib$1.callExpression(import_lib$1.memberExpression(import_lib$1.identifier("z"), import_lib$1.identifier("decode")), [schema, value]),
422
- parse: (schema, value) => import_lib$1.callExpression(import_lib$1.memberExpression(import_lib$1.identifier("z"), import_lib$1.identifier("parse")), [schema, value])
607
+ encode: (schema, value) => import_lib$1.callExpression(import_lib$1.memberExpression(import_lib$1.identifier("z"), import_lib$1.identifier("encodeAsync")), [schema, value]),
608
+ decode: (schema, value) => import_lib$1.callExpression(import_lib$1.memberExpression(import_lib$1.identifier("z"), import_lib$1.identifier("decodeAsync")), [schema, value]),
609
+ parse: (schema, value) => import_lib$1.callExpression(import_lib$1.memberExpression(import_lib$1.identifier("z"), import_lib$1.identifier("parseAsync")), [schema, value])
423
610
  },
424
611
  supportsImmutability: false
425
612
  }),
@@ -436,22 +623,22 @@ function createReactQueryClientGenerator(options) {
436
623
  const ensureApi = Effect.fn(function* () {
437
624
  const ctx = yield* DocumentContext;
438
625
  if (!ctx.schemas.has("Api")) {
439
- const makeRequest = import_lib.identifier("makeRequest");
440
- const makeRequestOptions = import_lib.identifier("options");
441
- makeRequestOptions.typeAnnotation = import_lib.tsTypeAnnotation(import_lib.tsTypeLiteral([
626
+ const fetch = import_lib.identifier("fetch");
627
+ const fetchPath = import_lib.identifier("path");
628
+ fetchPath.typeAnnotation = import_lib.tsTypeAnnotation(import_lib.tsStringKeyword());
629
+ const fetchOptions = import_lib.identifier("options");
630
+ fetchOptions.typeAnnotation = import_lib.tsTypeAnnotation(import_lib.tsTypeLiteral([
442
631
  import_lib.tsPropertySignature(import_lib.identifier("method"), import_lib.tsTypeAnnotation(import_lib.tsStringKeyword())),
443
- import_lib.tsPropertySignature(import_lib.identifier("path"), import_lib.tsTypeAnnotation(import_lib.tsStringKeyword())),
444
- import_lib.tsPropertySignature(import_lib.identifier("parametersSchema"), import_lib.tsTypeAnnotation(import_lib.tsTypeReference(options.schema.schemaType, import_lib.tsTypeParameterInstantiation([import_lib.tsTypeReference(import_lib.identifier("TParams")), import_lib.tsTypeLiteral([
445
- Object.assign(import_lib.tsPropertySignature(import_lib.identifier("query"), import_lib.tsTypeAnnotation(import_lib.tsTypeReference(import_lib.identifier("URLSearchParams")))), { optional: true }),
446
- Object.assign(import_lib.tsPropertySignature(import_lib.identifier("body"), import_lib.tsTypeAnnotation(import_lib.tsUnionType([import_lib.tsStringKeyword(), import_lib.tsTypeReference(import_lib.identifier("Blob"))]))), { optional: true }),
447
- Object.assign(import_lib.tsPropertySignature(import_lib.identifier("headers"), import_lib.tsTypeAnnotation(import_lib.tsTypeReference(import_lib.identifier("Headers")))), { optional: true }),
448
- Object.assign(import_lib.tsPropertySignature(import_lib.identifier("path"), import_lib.tsTypeAnnotation(import_lib.tsTypeReference(import_lib.identifier("Record<string, string>")))), { optional: true })
449
- ])])))),
450
- import_lib.tsPropertySignature(import_lib.identifier("parameters"), import_lib.tsTypeAnnotation(import_lib.tsTypeReference(import_lib.identifier("TParams")))),
451
- Object.assign(import_lib.tsPropertySignature(import_lib.identifier("responseSchema"), import_lib.tsTypeAnnotation(import_lib.tsTypeReference(options.schema.schemaType, import_lib.tsTypeParameterInstantiation([import_lib.tsTypeReference(import_lib.identifier("TResponse")), import_lib.tsStringKeyword()])))), { optional: true })
632
+ Object.assign(import_lib.tsPropertySignature(import_lib.identifier("headers"), import_lib.tsTypeAnnotation(import_lib.tsTypeReference(import_lib.identifier("Headers")))), { optional: true }),
633
+ Object.assign(import_lib.tsPropertySignature(import_lib.identifier("body"), import_lib.tsTypeAnnotation(import_lib.tsUnionType([
634
+ import_lib.tsTypeReference(import_lib.identifier("string")),
635
+ import_lib.tsTypeReference(import_lib.identifier("Blob")),
636
+ import_lib.tsTypeReference(import_lib.identifier("FormData")),
637
+ import_lib.tsTypeReference(import_lib.identifier("URLSearchParams"))
638
+ ]))), { optional: true })
452
639
  ]));
453
- makeRequest.typeAnnotation = import_lib.tsTypeAnnotation(import_lib.tsFunctionType(import_lib.tsTypeParameterDeclaration([import_lib.tsTypeParameter(null, null, "TParams"), import_lib.tsTypeParameter(null, null, "TResponse")]), [makeRequestOptions], import_lib.tsTypeAnnotation(import_lib.tsTypeReference(import_lib.identifier(options.responseGeneric ? `Promise<${(yield* ensureImport(options.responseGeneric.name, options.responseGeneric.from)).name}<TResponse>>` : "Promise<TResponse>")))));
454
- ctx.schemas.set("Api", [import_lib.exportNamedDeclaration(import_lib.classDeclaration(import_lib.identifier("Api"), null, import_lib.classBody([import_lib.classPrivateProperty(import_lib.privateName(makeRequest)), import_lib.classMethod("constructor", import_lib.identifier("constructor"), [makeRequest], import_lib.blockStatement([import_lib.expressionStatement(import_lib.assignmentExpression("=", import_lib.memberExpression(import_lib.thisExpression(), import_lib.privateName(makeRequest)), makeRequest))]))])))]);
640
+ fetch.typeAnnotation = import_lib.tsTypeAnnotation(import_lib.tsFunctionType(null, [fetchPath, fetchOptions], import_lib.tsTypeAnnotation(import_lib.tsTypeReference(import_lib.identifier("Promise"), import_lib.tsTypeParameterInstantiation([import_lib.tsTypeReference(import_lib.identifier("Response"))])))));
641
+ ctx.schemas.set("Api", [import_lib.exportNamedDeclaration(import_lib.classDeclaration(import_lib.identifier("Api"), null, import_lib.classBody([import_lib.classPrivateProperty(import_lib.privateName(fetch)), import_lib.classMethod("constructor", import_lib.identifier("constructor"), [fetch], import_lib.blockStatement([import_lib.expressionStatement(import_lib.assignmentExpression("=", import_lib.memberExpression(import_lib.thisExpression(), import_lib.privateName(fetch)), fetch))]))])))]);
455
642
  }
456
643
  return ctx.schemas.get("Api")[0].declaration.body;
457
644
  });
@@ -461,20 +648,21 @@ function createReactQueryClientGenerator(options) {
461
648
  if (options.schema.initialize) yield* options.schema.initialize();
462
649
  }),
463
650
  processOperation: Effect.fn(function* (operationKey, path, method, operation) {
464
- yield* DocumentContext;
465
- const parametersSchema = yield* options.schema.ensureParametersSchema(operationKey, operation);
651
+ const parametersSchema = yield* options.schema.ensureParametersSchema(operationKey, operation, path);
466
652
  const responseSchema = yield* options.schema.ensureResponseSchema(operationKey, operation);
467
653
  const parameters = import_lib.identifier("parameters");
468
654
  parameters.typeAnnotation = import_lib.tsTypeAnnotation(parametersSchema.typeReference);
469
- const isMutation = method !== "get";
470
- const fnBody = import_lib.awaitExpression(import_lib.callExpression(import_lib.memberExpression(import_lib.thisExpression(), import_lib.privateName(import_lib.identifier("makeRequest"))), [import_lib.objectExpression([
655
+ const isMutation = method !== "get" && method !== "head" && method !== "options";
656
+ const fetchCall = import_lib.awaitExpression(import_lib.callExpression(import_lib.memberExpression(import_lib.thisExpression(), import_lib.privateName(import_lib.identifier("fetch"))), [import_lib.memberExpression(import_lib.identifier("params"), import_lib.identifier("path")), import_lib.objectExpression([
471
657
  import_lib.objectProperty(import_lib.identifier("method"), import_lib.stringLiteral(method)),
472
- import_lib.objectProperty(import_lib.identifier("path"), import_lib.stringLiteral(path)),
473
- import_lib.objectProperty(import_lib.identifier("parametersSchema"), parametersSchema.expression, false, true),
474
- import_lib.objectProperty(import_lib.identifier("parameters"), parameters),
475
- ...responseSchema ? [import_lib.objectProperty(import_lib.identifier("responseSchema"), responseSchema.expression)] : []
658
+ import_lib.objectProperty(import_lib.identifier("headers"), import_lib.memberExpression(import_lib.identifier("params"), import_lib.identifier("headers"))),
659
+ import_lib.objectProperty(import_lib.identifier("body"), import_lib.memberExpression(import_lib.identifier("params"), import_lib.identifier("body")))
476
660
  ])]));
477
- const doMethod = import_lib.classMethod("method", import_lib.identifier(operationKey.lower), [parameters], import_lib.blockStatement([import_lib.returnStatement(fnBody)]), false, false, false, true);
661
+ const doMethod = import_lib.classMethod("method", import_lib.identifier(operationKey.lower), [parameters], import_lib.blockStatement([
662
+ import_lib.variableDeclaration("const", [import_lib.variableDeclarator(import_lib.identifier("params"), import_lib.awaitExpression(yield* options.schema.encodeParameters(parametersSchema.expression, import_lib.identifier("parameters"))))]),
663
+ import_lib.variableDeclaration("const", [import_lib.variableDeclarator(import_lib.identifier("response"), fetchCall)]),
664
+ import_lib.returnStatement(import_lib.awaitExpression(yield* options.schema.decodeResponse(responseSchema.expression, import_lib.identifier("response"))))
665
+ ]), false, false, false, true);
478
666
  const queryMethod = import_lib.classMethod("method", import_lib.identifier(operationKey.lower + (isMutation ? "Mutation" : "Query")), isMutation ? [] : [parameters], import_lib.blockStatement([import_lib.returnStatement(import_lib.callExpression(yield* ensureImport(isMutation ? "mutationOptions" : "queryOptions", "@tanstack/react-query"), [import_lib.objectExpression([...isMutation ? [] : [import_lib.objectProperty(import_lib.identifier("queryKey"), import_lib.tsAsExpression(import_lib.arrayExpression([import_lib.stringLiteral(operationKey.upper), parameters]), import_lib.tsTypeReference(yield* ensureImport("QueryKey", "@tanstack/react-query", true))))], import_lib.objectProperty(import_lib.identifier(isMutation ? "mutationFn" : "queryFn"), import_lib.arrowFunctionExpression(isMutation ? [parameters] : [], import_lib.callExpression(import_lib.memberExpression(import_lib.thisExpression(), import_lib.identifier(operationKey.lower)), [parameters]), true))])]))]));
479
667
  const commentLines = [];
480
668
  if (operation.summary) commentLines.push(`### ${operation.summary}`);