typed-openapi 2.0.2 → 2.1.1
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.
- package/dist/{chunk-Q6LQYDKL.js → chunk-CO4NONVX.js} +1 -1
- package/dist/{chunk-KF4JBLDM.js → chunk-KAZF7BK3.js} +111 -103
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/node.export.d.ts +1 -1
- package/dist/node.export.js +2 -2
- package/dist/{types-DsI2d-HE.d.ts → types-BOJSTQwz.d.ts} +1 -3
- package/package.json +3 -2
- package/src/generator.ts +64 -61
- package/src/map-openapi-endpoints.ts +56 -63
- package/src/tanstack-query.generator.ts +2 -2
|
@@ -449,16 +449,10 @@ var parameterObjectToString = (parameters, ctx) => {
|
|
|
449
449
|
}
|
|
450
450
|
return str + "}";
|
|
451
451
|
};
|
|
452
|
-
var responseHeadersObjectToString = (responseHeaders
|
|
452
|
+
var responseHeadersObjectToString = (responseHeaders) => {
|
|
453
453
|
let str = "{";
|
|
454
454
|
for (const [key, responseHeader] of Object.entries(responseHeaders)) {
|
|
455
|
-
|
|
456
|
-
if (Box.isReference(box) && !box.params.generics && box.value !== "null") {
|
|
457
|
-
box.value = `Schemas.${box.value}`;
|
|
458
|
-
}
|
|
459
|
-
return box;
|
|
460
|
-
}).value : responseHeader.value;
|
|
461
|
-
str += `${wrapWithQuotesIfNeeded(key.toLowerCase())}: ${value},
|
|
455
|
+
str += `${wrapWithQuotesIfNeeded(key.toLowerCase())}: ${responseHeader.value},
|
|
462
456
|
`;
|
|
463
457
|
}
|
|
464
458
|
return str + "}";
|
|
@@ -503,14 +497,8 @@ var generateEndpointSchemaList = (ctx) => {
|
|
|
503
497
|
ctx
|
|
504
498
|
)},` : ""}
|
|
505
499
|
}` : "parameters: never,"}
|
|
506
|
-
response: ${ctx.runtime === "none" ? endpoint.response.recompute((box) => {
|
|
507
|
-
if (Box.isReference(box) && !box.params.generics && box.value !== "null") {
|
|
508
|
-
box.value = `Schemas.${box.value}`;
|
|
509
|
-
}
|
|
510
|
-
return box;
|
|
511
|
-
}).value : endpoint.response.value},
|
|
512
500
|
${endpoint.responses ? `responses: ${generateResponsesObject(endpoint.responses, ctx)},` : ""}
|
|
513
|
-
${endpoint.responseHeaders ? `responseHeaders: ${responseHeadersObjectToString(endpoint.responseHeaders
|
|
501
|
+
${endpoint.responseHeaders ? `responseHeaders: ${responseHeadersObjectToString(endpoint.responseHeaders)},` : ""}
|
|
514
502
|
}
|
|
515
503
|
`;
|
|
516
504
|
});
|
|
@@ -567,7 +555,6 @@ type RequestFormat = "json" | "form-data" | "form-url" | "binary" | "text";
|
|
|
567
555
|
|
|
568
556
|
export type DefaultEndpoint = {
|
|
569
557
|
parameters?: EndpointParameters | undefined;
|
|
570
|
-
response: unknown;
|
|
571
558
|
responses?: Record<string, unknown>;
|
|
572
559
|
responseHeaders?: Record<string, unknown>;
|
|
573
560
|
};
|
|
@@ -583,7 +570,6 @@ export type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
|
|
|
583
570
|
hasParameters: boolean;
|
|
584
571
|
areParametersRequired: boolean;
|
|
585
572
|
};
|
|
586
|
-
response: TConfig["response"];
|
|
587
573
|
responses?: TConfig["responses"];
|
|
588
574
|
responseHeaders?: TConfig["responseHeaders"]
|
|
589
575
|
};
|
|
@@ -596,49 +582,63 @@ export type SuccessStatusCode = typeof successStatusCodes[number];
|
|
|
596
582
|
export const errorStatusCodes = [${ctx.errorStatusCodes.join(",")}] as const;
|
|
597
583
|
export type ErrorStatusCode = typeof errorStatusCodes[number];
|
|
598
584
|
|
|
599
|
-
//
|
|
585
|
+
// Taken from https://github.com/unjs/fetchdts/blob/ec4eaeab5d287116171fc1efd61f4a1ad34e4609/src/fetch.ts#L3
|
|
586
|
+
export interface TypedHeaders<TypedHeaderValues extends Record<string, string> | unknown> extends Omit<Headers, 'append' | 'delete' | 'get' | 'getSetCookie' | 'has' | 'set' | 'forEach'> {
|
|
587
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/append) */
|
|
588
|
+
append: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name, value: Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) => void
|
|
589
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/delete) */
|
|
590
|
+
delete: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => void
|
|
591
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/get) */
|
|
592
|
+
get: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => (Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) | null
|
|
593
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/getSetCookie) */
|
|
594
|
+
getSetCookie: () => string[]
|
|
595
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/has) */
|
|
596
|
+
has: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => boolean
|
|
597
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/set) */
|
|
598
|
+
set: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name, value: Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) => void
|
|
599
|
+
forEach: (callbackfn: (value: TypedHeaderValues[keyof TypedHeaderValues] | string & {}, key: Extract<keyof TypedHeaderValues, string> | string & {}, parent: TypedHeaders<TypedHeaderValues>) => void, thisArg?: any) => void
|
|
600
|
+
}
|
|
601
|
+
|
|
600
602
|
/** @see https://developer.mozilla.org/en-US/docs/Web/API/Response */
|
|
601
|
-
interface
|
|
603
|
+
export interface TypedSuccessResponse<TSuccess, TStatusCode, THeaders> extends Omit<Response, "ok" | "status" | "json" | "headers"> {
|
|
602
604
|
ok: true;
|
|
603
605
|
status: TStatusCode;
|
|
606
|
+
headers: never extends THeaders ? Headers : TypedHeaders<THeaders>;
|
|
604
607
|
data: TSuccess;
|
|
605
608
|
/** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Response/json) */
|
|
606
609
|
json: () => Promise<TSuccess>;
|
|
607
610
|
}
|
|
608
611
|
|
|
609
612
|
/** @see https://developer.mozilla.org/en-US/docs/Web/API/Response */
|
|
610
|
-
interface
|
|
613
|
+
export interface TypedErrorResponse<TData, TStatusCode, THeaders> extends Omit<Response, "ok" | "status" | "json" | "headers"> {
|
|
611
614
|
ok: false;
|
|
612
615
|
status: TStatusCode;
|
|
616
|
+
headers: never extends THeaders ? Headers : TypedHeaders<THeaders>;
|
|
613
617
|
data: TData;
|
|
614
618
|
/** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Response/json) */
|
|
615
619
|
json: () => Promise<TData>;
|
|
616
620
|
}
|
|
617
621
|
|
|
618
|
-
export type TypedApiResponse<
|
|
619
|
-
(
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
? K extends
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
: never;
|
|
633
|
-
}[keyof TAllResponses]);
|
|
622
|
+
export type TypedApiResponse<TAllResponses extends Record<string | number, unknown> = {}, THeaders = {}> =
|
|
623
|
+
({
|
|
624
|
+
[K in keyof TAllResponses]: K extends string
|
|
625
|
+
? K extends \`\${infer TStatusCode extends number}\`
|
|
626
|
+
? TStatusCode extends SuccessStatusCode
|
|
627
|
+
? TypedSuccessResponse<TAllResponses[K], TStatusCode, K extends keyof THeaders ? THeaders[K] : never>
|
|
628
|
+
: TypedErrorResponse<TAllResponses[K], TStatusCode, K extends keyof THeaders ? THeaders[K] : never>
|
|
629
|
+
: never
|
|
630
|
+
: K extends number
|
|
631
|
+
? K extends SuccessStatusCode
|
|
632
|
+
? TypedSuccessResponse<TAllResponses[K], K, K extends keyof THeaders ? THeaders[K] : never>
|
|
633
|
+
: TypedErrorResponse<TAllResponses[K], K, K extends keyof THeaders ? THeaders[K] : never>
|
|
634
|
+
: never;
|
|
635
|
+
}[keyof TAllResponses]);
|
|
634
636
|
|
|
635
|
-
export type SafeApiResponse<TEndpoint> = TEndpoint extends {
|
|
637
|
+
export type SafeApiResponse<TEndpoint> = TEndpoint extends { responses: infer TResponses }
|
|
636
638
|
? TResponses extends Record<string, unknown>
|
|
637
|
-
? TypedApiResponse<
|
|
638
|
-
:
|
|
639
|
-
:
|
|
640
|
-
? SuccessResponse<TSuccess, number>
|
|
641
|
-
: never;
|
|
639
|
+
? TypedApiResponse<TResponses, TEndpoint extends { responseHeaders: infer THeaders } ? THeaders : never>
|
|
640
|
+
: never
|
|
641
|
+
: never
|
|
642
642
|
|
|
643
643
|
export type InferResponseByStatus<TEndpoint, TStatusCode> = Extract<SafeApiResponse<TEndpoint>, { status: TStatusCode }>
|
|
644
644
|
|
|
@@ -653,9 +653,9 @@ type MaybeOptionalArg<T> = RequiredKeys<T> extends never ? [config?: T] : [confi
|
|
|
653
653
|
const apiClient = `
|
|
654
654
|
// <TypedResponseError>
|
|
655
655
|
export class TypedResponseError extends Error {
|
|
656
|
-
response:
|
|
656
|
+
response: TypedErrorResponse<unknown, ErrorStatusCode, unknown>;
|
|
657
657
|
status: number;
|
|
658
|
-
constructor(response:
|
|
658
|
+
constructor(response: TypedErrorResponse<unknown, ErrorStatusCode, unknown>) {
|
|
659
659
|
super(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
660
660
|
this.name = 'TypedResponseError';
|
|
661
661
|
this.response = response;
|
|
@@ -691,7 +691,13 @@ export class ApiClient {
|
|
|
691
691
|
${method}<Path extends keyof ${capitalizedMethod}Endpoints, TEndpoint extends ${capitalizedMethod}Endpoints[Path]>(
|
|
692
692
|
path: Path,
|
|
693
693
|
...params: MaybeOptionalArg<${match(ctx.runtime).with("zod", "yup", () => infer(`TEndpoint["parameters"]`)).with("arktype", "io-ts", "typebox", "valibot", () => infer(`TEndpoint`) + `["parameters"]`).otherwise(() => `TEndpoint["parameters"]`)} & { withResponse?: false; throwOnStatusError?: boolean }>
|
|
694
|
-
): Promise<${match(ctx.runtime).with("zod", "yup", () => infer(`TEndpoint
|
|
694
|
+
): Promise<${match(ctx.runtime).with("zod", "yup", () => infer(`InferResponseByStatus<TEndpoint, SuccessStatusCode>`)).with(
|
|
695
|
+
"arktype",
|
|
696
|
+
"io-ts",
|
|
697
|
+
"typebox",
|
|
698
|
+
"valibot",
|
|
699
|
+
() => `InferResponseByStatus<${infer(`TEndpoint`)}, SuccessStatusCode>["data"]`
|
|
700
|
+
).otherwise(() => `InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"]`)}>;
|
|
695
701
|
|
|
696
702
|
${method}<Path extends keyof ${capitalizedMethod}Endpoints, TEndpoint extends ${capitalizedMethod}Endpoints[Path]>(
|
|
697
703
|
path: Path,
|
|
@@ -721,7 +727,13 @@ export class ApiClient {
|
|
|
721
727
|
return withResponse ? typedResponse : data;
|
|
722
728
|
});
|
|
723
729
|
|
|
724
|
-
return promise ${match(ctx.runtime).with("zod", "yup", () => `as Promise<${infer(`TEndpoint
|
|
730
|
+
return promise ${match(ctx.runtime).with("zod", "yup", () => `as Promise<${infer(`InferResponseByStatus<TEndpoint, SuccessStatusCode>`)}>`).with(
|
|
731
|
+
"arktype",
|
|
732
|
+
"io-ts",
|
|
733
|
+
"typebox",
|
|
734
|
+
"valibot",
|
|
735
|
+
() => `as Promise<InferResponseByStatus<${infer(`TEndpoint`)}, SuccessStatusCode>["data"]>`
|
|
736
|
+
).otherwise(() => `as Promise<InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"]>`)}
|
|
725
737
|
}
|
|
726
738
|
// </ApiClient.${method}>
|
|
727
739
|
` : "";
|
|
@@ -1082,7 +1094,6 @@ var mapOpenApiEndpoints = (doc, options) => {
|
|
|
1082
1094
|
method,
|
|
1083
1095
|
path,
|
|
1084
1096
|
requestFormat: "json",
|
|
1085
|
-
response: openApiSchemaToTs({ schema: {}, ctx }),
|
|
1086
1097
|
meta: {
|
|
1087
1098
|
alias,
|
|
1088
1099
|
areParametersRequired: false,
|
|
@@ -1124,11 +1135,11 @@ var mapOpenApiEndpoints = (doc, options) => {
|
|
|
1124
1135
|
if (operation.requestBody) {
|
|
1125
1136
|
endpoint.meta.hasParameters = true;
|
|
1126
1137
|
const requestBody = refs.unwrap(operation.requestBody ?? {});
|
|
1127
|
-
const
|
|
1128
|
-
const matchingMediaType = Object.keys(
|
|
1129
|
-
if (matchingMediaType &&
|
|
1138
|
+
const content = requestBody.content;
|
|
1139
|
+
const matchingMediaType = Object.keys(content).find(isAllowedParamMediaTypes);
|
|
1140
|
+
if (matchingMediaType && content[matchingMediaType]) {
|
|
1130
1141
|
params.body = openApiSchemaToTs({
|
|
1131
|
-
schema:
|
|
1142
|
+
schema: content[matchingMediaType]?.schema ?? {},
|
|
1132
1143
|
ctx
|
|
1133
1144
|
});
|
|
1134
1145
|
}
|
|
@@ -1159,67 +1170,64 @@ var mapOpenApiEndpoints = (doc, options) => {
|
|
|
1159
1170
|
}
|
|
1160
1171
|
endpoint.parameters = Object.keys(params).length ? params : void 0;
|
|
1161
1172
|
}
|
|
1162
|
-
let responseObject;
|
|
1163
1173
|
const allResponses = {};
|
|
1174
|
+
const allHeaders = {};
|
|
1164
1175
|
Object.entries(operation.responses ?? {}).map(([status, responseOrRef]) => {
|
|
1165
|
-
const statusCode = Number(status);
|
|
1166
1176
|
const responseObj = refs.unwrap(responseOrRef);
|
|
1167
|
-
const
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1177
|
+
const content = responseObj?.content;
|
|
1178
|
+
const mediaTypes = Object.keys(content ?? {}).filter(isResponseMediaType);
|
|
1179
|
+
if (content && mediaTypes.length) {
|
|
1180
|
+
mediaTypes.forEach((mediaType) => {
|
|
1181
|
+
const schema = content[mediaType] ? content[mediaType].schema ?? {} : {};
|
|
1182
|
+
const t2 = createBoxFactory(schema, ctx);
|
|
1183
|
+
const mediaTypeResponse = openApiSchemaToTs({ schema, ctx });
|
|
1184
|
+
if (allResponses[status]) {
|
|
1185
|
+
allResponses[status] = t2.union([
|
|
1186
|
+
...Array.isArray(allResponses[status]) ? allResponses[status] : [allResponses[status]],
|
|
1187
|
+
mediaTypeResponse
|
|
1188
|
+
]);
|
|
1189
|
+
} else {
|
|
1190
|
+
allResponses[status] = mediaTypeResponse;
|
|
1191
|
+
}
|
|
1192
|
+
});
|
|
1193
|
+
} else {
|
|
1194
|
+
const schema = {};
|
|
1195
|
+
const unknown = openApiSchemaToTs({ schema: {}, ctx });
|
|
1196
|
+
const t2 = createBoxFactory(schema, ctx);
|
|
1197
|
+
if (allResponses[status]) {
|
|
1198
|
+
allResponses[status] = t2.union([
|
|
1199
|
+
...Array.isArray(allResponses[status]) ? allResponses[status] : [allResponses[status]],
|
|
1200
|
+
unknown
|
|
1201
|
+
]);
|
|
1175
1202
|
} else {
|
|
1176
|
-
allResponses[status] =
|
|
1203
|
+
allResponses[status] = unknown;
|
|
1177
1204
|
}
|
|
1178
|
-
} else {
|
|
1179
|
-
allResponses[status] = openApiSchemaToTs({ schema: {}, ctx });
|
|
1180
1205
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1206
|
+
const headers = responseObj?.headers;
|
|
1207
|
+
const t = createBoxFactory(
|
|
1208
|
+
{ type: "object", properties: headers ?? {}, required: Object.keys(headers ?? {}) },
|
|
1209
|
+
ctx
|
|
1210
|
+
);
|
|
1211
|
+
if (headers) {
|
|
1212
|
+
const mappedHeaders = Object.entries(headers).reduce(
|
|
1213
|
+
(acc, [name, headerOrRef]) => {
|
|
1214
|
+
const header = refs.unwrap(headerOrRef);
|
|
1215
|
+
const box = openApiSchemaToTs({ schema: header.schema ?? {}, ctx });
|
|
1216
|
+
acc[name] = box;
|
|
1217
|
+
return acc;
|
|
1218
|
+
},
|
|
1219
|
+
{}
|
|
1220
|
+
);
|
|
1221
|
+
if (Object.keys(mappedHeaders).length) {
|
|
1222
|
+
allHeaders[status] = t.object(mappedHeaders);
|
|
1197
1223
|
}
|
|
1198
1224
|
}
|
|
1199
|
-
}
|
|
1225
|
+
});
|
|
1200
1226
|
if (Object.keys(allResponses).length > 0) {
|
|
1201
1227
|
endpoint.responses = allResponses;
|
|
1202
1228
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
const matchingMediaType = Object.keys(content).find(isResponseMediaType);
|
|
1206
|
-
if (matchingMediaType && content[matchingMediaType]) {
|
|
1207
|
-
endpoint.response = openApiSchemaToTs({
|
|
1208
|
-
schema: content[matchingMediaType]?.schema ?? {},
|
|
1209
|
-
ctx
|
|
1210
|
-
});
|
|
1211
|
-
}
|
|
1212
|
-
}
|
|
1213
|
-
const headers = responseObject?.headers;
|
|
1214
|
-
if (headers) {
|
|
1215
|
-
endpoint.responseHeaders = Object.entries(headers).reduce(
|
|
1216
|
-
(acc, [name, headerOrRef]) => {
|
|
1217
|
-
const header = refs.unwrap(headerOrRef);
|
|
1218
|
-
acc[name] = openApiSchemaToTs({ schema: header.schema ?? {}, ctx });
|
|
1219
|
-
return acc;
|
|
1220
|
-
},
|
|
1221
|
-
{}
|
|
1222
|
-
);
|
|
1229
|
+
if (Object.keys(allHeaders).length) {
|
|
1230
|
+
endpoint.responseHeaders = allHeaders;
|
|
1223
1231
|
}
|
|
1224
1232
|
endpointList.push(endpoint);
|
|
1225
1233
|
});
|
|
@@ -1325,7 +1333,7 @@ var generateTanstackQueryFile = async (ctx) => {
|
|
|
1325
1333
|
withResponse: false as const
|
|
1326
1334
|
};
|
|
1327
1335
|
const res = await this.client.${method}(path, requestParams);
|
|
1328
|
-
return res as TEndpoint["
|
|
1336
|
+
return res as InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"];
|
|
1329
1337
|
},
|
|
1330
1338
|
queryKey: queryKey
|
|
1331
1339
|
}),
|
|
@@ -1340,7 +1348,7 @@ var generateTanstackQueryFile = async (ctx) => {
|
|
|
1340
1348
|
withResponse: false as const
|
|
1341
1349
|
};
|
|
1342
1350
|
const res = await this.client.${method}(path, requestParams);
|
|
1343
|
-
return res as TEndpoint["
|
|
1351
|
+
return res as InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"];
|
|
1344
1352
|
}
|
|
1345
1353
|
}
|
|
1346
1354
|
};
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReferenceObject } from 'openapi3-ts/oas31';
|
|
2
|
-
import { S as StringOrBox, O as OpenapiSchemaConvertContext, L as LibSchemaObject, B as BoxFactory, m as mapOpenApiEndpoints, N as NameTransformOptions, a as OpenapiSchemaConvertArgs, b as Box, A as AnyBoxDef } from './types-
|
|
3
|
-
export { q as AnyBox, j as BoxArray, f as BoxDefinition, i as BoxIntersection, o as BoxKeyword, n as BoxLiteral, p as BoxObject, k as BoxOptional, g as BoxParams, l as BoxRef, h as BoxUnion, c as Endpoint, E as EndpointParameters, F as FactoryCreator, G as GenericFactory, M as Method, R as RefInfo, e as RefResolver, W as WithSchema, d as createRefResolver } from './types-
|
|
2
|
+
import { S as StringOrBox, O as OpenapiSchemaConvertContext, L as LibSchemaObject, B as BoxFactory, m as mapOpenApiEndpoints, N as NameTransformOptions, a as OpenapiSchemaConvertArgs, b as Box, A as AnyBoxDef } from './types-BOJSTQwz.js';
|
|
3
|
+
export { q as AnyBox, j as BoxArray, f as BoxDefinition, i as BoxIntersection, o as BoxKeyword, n as BoxLiteral, p as BoxObject, k as BoxOptional, g as BoxParams, l as BoxRef, h as BoxUnion, c as Endpoint, E as EndpointParameters, F as FactoryCreator, G as GenericFactory, M as Method, R as RefInfo, e as RefResolver, W as WithSchema, d as createRefResolver } from './types-BOJSTQwz.js';
|
|
4
4
|
import * as arktype_internal_methods_string_ts from 'arktype/internal/methods/string.ts';
|
|
5
5
|
import * as Codegen from '@sinclair/typebox-codegen';
|
|
6
6
|
import 'openapi3-ts/oas30';
|
package/dist/index.js
CHANGED
package/dist/node.export.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as arktype_internal_methods_object_ts from 'arktype/internal/methods/object.ts';
|
|
2
|
-
import { N as NameTransformOptions } from './types-
|
|
2
|
+
import { N as NameTransformOptions } from './types-BOJSTQwz.js';
|
|
3
3
|
import 'openapi3-ts/oas31';
|
|
4
4
|
import 'openapi3-ts/oas30';
|
|
5
5
|
|
package/dist/node.export.js
CHANGED
|
@@ -99,9 +99,8 @@ type EndpointParameters = {
|
|
|
99
99
|
type RequestFormat = "json" | "form-data" | "form-url" | "binary" | "text";
|
|
100
100
|
type DefaultEndpoint = {
|
|
101
101
|
parameters?: EndpointParameters | undefined;
|
|
102
|
-
response: AnyBox;
|
|
103
102
|
responses?: Record<string, AnyBox>;
|
|
104
|
-
responseHeaders?: Record<string,
|
|
103
|
+
responseHeaders?: Record<string, Box<BoxObject>>;
|
|
105
104
|
};
|
|
106
105
|
type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
|
|
107
106
|
operation: OperationObject;
|
|
@@ -114,7 +113,6 @@ type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
|
|
|
114
113
|
hasParameters: boolean;
|
|
115
114
|
areParametersRequired: boolean;
|
|
116
115
|
};
|
|
117
|
-
response: TConfig["response"];
|
|
118
116
|
responses?: TConfig["responses"];
|
|
119
117
|
responseHeaders?: TConfig["responseHeaders"];
|
|
120
118
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typed-openapi",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.1.1",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
"msw": "2.10.5",
|
|
37
37
|
"tsup": "^8.4.0",
|
|
38
38
|
"typescript": "^5.8.3",
|
|
39
|
-
"vitest": "^3.1.3"
|
|
39
|
+
"vitest": "^3.1.3",
|
|
40
|
+
"zod": "3.21.4"
|
|
40
41
|
},
|
|
41
42
|
"files": [
|
|
42
43
|
"src",
|
package/src/generator.ts
CHANGED
|
@@ -6,7 +6,7 @@ import * as Codegen from "@sinclair/typebox-codegen";
|
|
|
6
6
|
import { match } from "ts-pattern";
|
|
7
7
|
import { type } from "arktype";
|
|
8
8
|
import { wrapWithQuotesIfNeeded } from "./string-utils.ts";
|
|
9
|
-
import type { NameTransformOptions } from "./types.ts";
|
|
9
|
+
import type { BoxObject, NameTransformOptions } from "./types.ts";
|
|
10
10
|
|
|
11
11
|
// Default success status codes (2xx and 3xx ranges)
|
|
12
12
|
export const DEFAULT_SUCCESS_STATUS_CODES = [
|
|
@@ -170,20 +170,10 @@ const parameterObjectToString = (parameters: Box<AnyBoxDef> | Record<string, Any
|
|
|
170
170
|
return str + "}";
|
|
171
171
|
};
|
|
172
172
|
|
|
173
|
-
const responseHeadersObjectToString = (responseHeaders: Record<string,
|
|
173
|
+
const responseHeadersObjectToString = (responseHeaders: Record<string, Box<BoxObject>>) => {
|
|
174
174
|
let str = "{";
|
|
175
175
|
for (const [key, responseHeader] of Object.entries(responseHeaders)) {
|
|
176
|
-
|
|
177
|
-
ctx.runtime === "none"
|
|
178
|
-
? responseHeader.recompute((box) => {
|
|
179
|
-
if (Box.isReference(box) && !box.params.generics && box.value !== "null") {
|
|
180
|
-
box.value = `Schemas.${box.value}`;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return box;
|
|
184
|
-
}).value
|
|
185
|
-
: responseHeader.value;
|
|
186
|
-
str += `${wrapWithQuotesIfNeeded(key.toLowerCase())}: ${value},\n`;
|
|
176
|
+
str += `${wrapWithQuotesIfNeeded(key.toLowerCase())}: ${responseHeader.value},\n`;
|
|
187
177
|
}
|
|
188
178
|
return str + "}";
|
|
189
179
|
};
|
|
@@ -242,21 +232,10 @@ const generateEndpointSchemaList = (ctx: GeneratorContext) => {
|
|
|
242
232
|
}`
|
|
243
233
|
: "parameters: never,"
|
|
244
234
|
}
|
|
245
|
-
response: ${
|
|
246
|
-
ctx.runtime === "none"
|
|
247
|
-
? endpoint.response.recompute((box) => {
|
|
248
|
-
if (Box.isReference(box) && !box.params.generics && box.value !== "null") {
|
|
249
|
-
box.value = `Schemas.${box.value}`;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return box;
|
|
253
|
-
}).value
|
|
254
|
-
: endpoint.response.value
|
|
255
|
-
},
|
|
256
235
|
${endpoint.responses ? `responses: ${generateResponsesObject(endpoint.responses, ctx)},` : ""}
|
|
257
236
|
${
|
|
258
237
|
endpoint.responseHeaders
|
|
259
|
-
? `responseHeaders: ${responseHeadersObjectToString(endpoint.responseHeaders
|
|
238
|
+
? `responseHeaders: ${responseHeadersObjectToString(endpoint.responseHeaders)},`
|
|
260
239
|
: ""
|
|
261
240
|
}
|
|
262
241
|
}\n`;
|
|
@@ -331,7 +310,6 @@ type RequestFormat = "json" | "form-data" | "form-url" | "binary" | "text";
|
|
|
331
310
|
|
|
332
311
|
export type DefaultEndpoint = {
|
|
333
312
|
parameters?: EndpointParameters | undefined;
|
|
334
|
-
response: unknown;
|
|
335
313
|
responses?: Record<string, unknown>;
|
|
336
314
|
responseHeaders?: Record<string, unknown>;
|
|
337
315
|
};
|
|
@@ -347,7 +325,6 @@ export type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
|
|
|
347
325
|
hasParameters: boolean;
|
|
348
326
|
areParametersRequired: boolean;
|
|
349
327
|
};
|
|
350
|
-
response: TConfig["response"];
|
|
351
328
|
responses?: TConfig["responses"];
|
|
352
329
|
responseHeaders?: TConfig["responseHeaders"]
|
|
353
330
|
};
|
|
@@ -360,49 +337,63 @@ export type SuccessStatusCode = typeof successStatusCodes[number];
|
|
|
360
337
|
export const errorStatusCodes = [${ctx.errorStatusCodes.join(",")}] as const;
|
|
361
338
|
export type ErrorStatusCode = typeof errorStatusCodes[number];
|
|
362
339
|
|
|
363
|
-
//
|
|
340
|
+
// Taken from https://github.com/unjs/fetchdts/blob/ec4eaeab5d287116171fc1efd61f4a1ad34e4609/src/fetch.ts#L3
|
|
341
|
+
export interface TypedHeaders<TypedHeaderValues extends Record<string, string> | unknown> extends Omit<Headers, 'append' | 'delete' | 'get' | 'getSetCookie' | 'has' | 'set' | 'forEach'> {
|
|
342
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/append) */
|
|
343
|
+
append: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name, value: Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) => void
|
|
344
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/delete) */
|
|
345
|
+
delete: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => void
|
|
346
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/get) */
|
|
347
|
+
get: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => (Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) | null
|
|
348
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/getSetCookie) */
|
|
349
|
+
getSetCookie: () => string[]
|
|
350
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/has) */
|
|
351
|
+
has: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => boolean
|
|
352
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/set) */
|
|
353
|
+
set: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name, value: Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) => void
|
|
354
|
+
forEach: (callbackfn: (value: TypedHeaderValues[keyof TypedHeaderValues] | string & {}, key: Extract<keyof TypedHeaderValues, string> | string & {}, parent: TypedHeaders<TypedHeaderValues>) => void, thisArg?: any) => void
|
|
355
|
+
}
|
|
356
|
+
|
|
364
357
|
/** @see https://developer.mozilla.org/en-US/docs/Web/API/Response */
|
|
365
|
-
interface
|
|
358
|
+
export interface TypedSuccessResponse<TSuccess, TStatusCode, THeaders> extends Omit<Response, "ok" | "status" | "json" | "headers"> {
|
|
366
359
|
ok: true;
|
|
367
360
|
status: TStatusCode;
|
|
361
|
+
headers: never extends THeaders ? Headers : TypedHeaders<THeaders>;
|
|
368
362
|
data: TSuccess;
|
|
369
363
|
/** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Response/json) */
|
|
370
364
|
json: () => Promise<TSuccess>;
|
|
371
365
|
}
|
|
372
366
|
|
|
373
367
|
/** @see https://developer.mozilla.org/en-US/docs/Web/API/Response */
|
|
374
|
-
interface
|
|
368
|
+
export interface TypedErrorResponse<TData, TStatusCode, THeaders> extends Omit<Response, "ok" | "status" | "json" | "headers"> {
|
|
375
369
|
ok: false;
|
|
376
370
|
status: TStatusCode;
|
|
371
|
+
headers: never extends THeaders ? Headers : TypedHeaders<THeaders>;
|
|
377
372
|
data: TData;
|
|
378
373
|
/** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Response/json) */
|
|
379
374
|
json: () => Promise<TData>;
|
|
380
375
|
}
|
|
381
376
|
|
|
382
|
-
export type TypedApiResponse<
|
|
383
|
-
(
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
? K extends
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
export type SafeApiResponse<TEndpoint> = TEndpoint extends { response: infer TSuccess; responses: infer TResponses }
|
|
377
|
+
export type TypedApiResponse<TAllResponses extends Record<string | number, unknown> = {}, THeaders = {}> =
|
|
378
|
+
({
|
|
379
|
+
[K in keyof TAllResponses]: K extends string
|
|
380
|
+
? K extends \`\${infer TStatusCode extends number}\`
|
|
381
|
+
? TStatusCode extends SuccessStatusCode
|
|
382
|
+
? TypedSuccessResponse<TAllResponses[K], TStatusCode, K extends keyof THeaders ? THeaders[K] : never>
|
|
383
|
+
: TypedErrorResponse<TAllResponses[K], TStatusCode, K extends keyof THeaders ? THeaders[K] : never>
|
|
384
|
+
: never
|
|
385
|
+
: K extends number
|
|
386
|
+
? K extends SuccessStatusCode
|
|
387
|
+
? TypedSuccessResponse<TAllResponses[K], K, K extends keyof THeaders ? THeaders[K] : never>
|
|
388
|
+
: TypedErrorResponse<TAllResponses[K], K, K extends keyof THeaders ? THeaders[K] : never>
|
|
389
|
+
: never;
|
|
390
|
+
}[keyof TAllResponses]);
|
|
391
|
+
|
|
392
|
+
export type SafeApiResponse<TEndpoint> = TEndpoint extends { responses: infer TResponses }
|
|
400
393
|
? TResponses extends Record<string, unknown>
|
|
401
|
-
? TypedApiResponse<
|
|
402
|
-
:
|
|
403
|
-
:
|
|
404
|
-
? SuccessResponse<TSuccess, number>
|
|
405
|
-
: never;
|
|
394
|
+
? TypedApiResponse<TResponses, TEndpoint extends { responseHeaders: infer THeaders } ? THeaders : never>
|
|
395
|
+
: never
|
|
396
|
+
: never
|
|
406
397
|
|
|
407
398
|
export type InferResponseByStatus<TEndpoint, TStatusCode> = Extract<SafeApiResponse<TEndpoint>, { status: TStatusCode }>
|
|
408
399
|
|
|
@@ -418,9 +409,9 @@ type MaybeOptionalArg<T> = RequiredKeys<T> extends never ? [config?: T] : [confi
|
|
|
418
409
|
const apiClient = `
|
|
419
410
|
// <TypedResponseError>
|
|
420
411
|
export class TypedResponseError extends Error {
|
|
421
|
-
response:
|
|
412
|
+
response: TypedErrorResponse<unknown, ErrorStatusCode, unknown>;
|
|
422
413
|
status: number;
|
|
423
|
-
constructor(response:
|
|
414
|
+
constructor(response: TypedErrorResponse<unknown, ErrorStatusCode, unknown>) {
|
|
424
415
|
super(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
425
416
|
this.name = 'TypedResponseError';
|
|
426
417
|
this.response = response;
|
|
@@ -463,9 +454,15 @@ export class ApiClient {
|
|
|
463
454
|
.with("arktype", "io-ts", "typebox", "valibot", () => infer(`TEndpoint`) + `["parameters"]`)
|
|
464
455
|
.otherwise(() => `TEndpoint["parameters"]`)} & { withResponse?: false; throwOnStatusError?: boolean }>
|
|
465
456
|
): Promise<${match(ctx.runtime)
|
|
466
|
-
.with("zod", "yup", () => infer(`TEndpoint
|
|
467
|
-
.with(
|
|
468
|
-
|
|
457
|
+
.with("zod", "yup", () => infer(`InferResponseByStatus<TEndpoint, SuccessStatusCode>`))
|
|
458
|
+
.with(
|
|
459
|
+
"arktype",
|
|
460
|
+
"io-ts",
|
|
461
|
+
"typebox",
|
|
462
|
+
"valibot",
|
|
463
|
+
() => `InferResponseByStatus<${infer(`TEndpoint`)}, SuccessStatusCode>["data"]`,
|
|
464
|
+
)
|
|
465
|
+
.otherwise(() => `InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"]`)}>;
|
|
469
466
|
|
|
470
467
|
${method}<Path extends keyof ${capitalizedMethod}Endpoints, TEndpoint extends ${capitalizedMethod}Endpoints[Path]>(
|
|
471
468
|
path: Path,
|
|
@@ -499,9 +496,15 @@ export class ApiClient {
|
|
|
499
496
|
});
|
|
500
497
|
|
|
501
498
|
return promise ${match(ctx.runtime)
|
|
502
|
-
.with("zod", "yup", () => `as Promise<${infer(`TEndpoint
|
|
503
|
-
.with(
|
|
504
|
-
|
|
499
|
+
.with("zod", "yup", () => `as Promise<${infer(`InferResponseByStatus<TEndpoint, SuccessStatusCode>`)}>`)
|
|
500
|
+
.with(
|
|
501
|
+
"arktype",
|
|
502
|
+
"io-ts",
|
|
503
|
+
"typebox",
|
|
504
|
+
"valibot",
|
|
505
|
+
() => `as Promise<InferResponseByStatus<${infer(`TEndpoint`)}, SuccessStatusCode>["data"]>`,
|
|
506
|
+
)
|
|
507
|
+
.otherwise(() => `as Promise<InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"]>`)}
|
|
505
508
|
}
|
|
506
509
|
// </ApiClient.${method}>
|
|
507
510
|
`
|
|
@@ -6,7 +6,7 @@ import { createBoxFactory } from "./box-factory.ts";
|
|
|
6
6
|
import { openApiSchemaToTs } from "./openapi-schema-to-ts.ts";
|
|
7
7
|
import { createRefResolver } from "./ref-resolver.ts";
|
|
8
8
|
import { tsFactory } from "./ts-factory.ts";
|
|
9
|
-
import { AnyBox, BoxRef, OpenapiSchemaConvertContext } from "./types.ts";
|
|
9
|
+
import { AnyBox, BoxRef, OpenapiSchemaConvertContext, type BoxObject, type LibSchemaObject } from "./types.ts";
|
|
10
10
|
import { pathToVariableName } from "./string-utils.ts";
|
|
11
11
|
import { NameTransformOptions } from "./types.ts";
|
|
12
12
|
import { match, P } from "ts-pattern";
|
|
@@ -33,7 +33,6 @@ export const mapOpenApiEndpoints = (doc: OpenAPIObject, options?: { nameTransfor
|
|
|
33
33
|
method: method as Method,
|
|
34
34
|
path,
|
|
35
35
|
requestFormat: "json",
|
|
36
|
-
response: openApiSchemaToTs({ schema: {}, ctx }),
|
|
37
36
|
meta: {
|
|
38
37
|
alias,
|
|
39
38
|
areParametersRequired: false,
|
|
@@ -131,86 +130,81 @@ export const mapOpenApiEndpoints = (doc: OpenAPIObject, options?: { nameTransfor
|
|
|
131
130
|
}
|
|
132
131
|
}
|
|
133
132
|
|
|
134
|
-
// No need to pass empty objects, it's confusing
|
|
135
133
|
endpoint.parameters = Object.keys(params).length ? (params as any as EndpointParameters) : undefined;
|
|
136
134
|
}
|
|
137
135
|
|
|
138
|
-
// Match the first 2xx-3xx response found, or fallback to default one otherwise
|
|
139
|
-
let responseObject: ResponseObject | undefined;
|
|
140
136
|
const allResponses: Record<string, AnyBox> = {};
|
|
137
|
+
const allHeaders: Record<string, Box<BoxObject>> = {};
|
|
141
138
|
|
|
142
139
|
Object.entries(operation.responses ?? {}).map(([status, responseOrRef]) => {
|
|
143
|
-
const statusCode = Number(status);
|
|
144
140
|
const responseObj = refs.unwrap<ResponseObject>(responseOrRef);
|
|
145
141
|
|
|
146
142
|
// Collect all responses for error handling
|
|
147
143
|
const content = responseObj?.content;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
allResponses[status] = openApiSchemaToTs({
|
|
152
|
-
schema: content[matchingMediaType]?.schema ?? {},
|
|
153
|
-
ctx,
|
|
154
|
-
});
|
|
155
|
-
} else {
|
|
144
|
+
const mediaTypes = Object.keys(content ?? {}).filter(isResponseMediaType);
|
|
145
|
+
if (content && mediaTypes.length) {
|
|
146
|
+
mediaTypes.forEach((mediaType) => {
|
|
156
147
|
// If no JSON content, use unknown type
|
|
157
|
-
|
|
158
|
-
|
|
148
|
+
const schema = content[mediaType] ? (content[mediaType].schema ?? {}) : {};
|
|
149
|
+
const t = createBoxFactory(schema as LibSchemaObject, ctx);
|
|
150
|
+
const mediaTypeResponse = openApiSchemaToTs({ schema, ctx });
|
|
151
|
+
|
|
152
|
+
if (allResponses[status]) {
|
|
153
|
+
allResponses[status] = t.union([
|
|
154
|
+
...(Array.isArray(allResponses[status]) ? allResponses[status] : [allResponses[status]]),
|
|
155
|
+
mediaTypeResponse,
|
|
156
|
+
]);
|
|
157
|
+
} else {
|
|
158
|
+
allResponses[status] = mediaTypeResponse;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
159
161
|
} else {
|
|
160
162
|
// If no content defined, use unknown type
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
const schema = {};
|
|
164
|
+
const unknown = openApiSchemaToTs({ schema: {}, ctx });
|
|
165
|
+
const t = createBoxFactory(schema as LibSchemaObject, ctx);
|
|
166
|
+
|
|
167
|
+
if (allResponses[status]) {
|
|
168
|
+
allResponses[status] = t.union([
|
|
169
|
+
...(Array.isArray(allResponses[status]) ? allResponses[status] : [allResponses[status]]),
|
|
170
|
+
unknown,
|
|
171
|
+
]);
|
|
172
|
+
} else {
|
|
173
|
+
allResponses[status] = unknown;
|
|
174
|
+
}
|
|
167
175
|
}
|
|
168
|
-
});
|
|
169
176
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
177
|
+
// Map response headers
|
|
178
|
+
const headers = responseObj?.headers;
|
|
179
|
+
const t = createBoxFactory(
|
|
180
|
+
{ type: "object", properties: (headers ?? {}) as never, required: Object.keys(headers ?? {}) },
|
|
181
|
+
ctx,
|
|
182
|
+
);
|
|
183
|
+
if (headers) {
|
|
184
|
+
const mappedHeaders = Object.entries(headers).reduce(
|
|
185
|
+
(acc, [name, headerOrRef]) => {
|
|
186
|
+
const header = refs.unwrap(headerOrRef);
|
|
187
|
+
const box = openApiSchemaToTs({ schema: header.schema ?? {}, ctx });
|
|
188
|
+
acc[name] = box;
|
|
189
|
+
|
|
190
|
+
return acc;
|
|
191
|
+
},
|
|
192
|
+
{} as Record<string, Box>,
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
if (Object.keys(mappedHeaders).length) {
|
|
196
|
+
allHeaders[status] = t.object(mappedHeaders);
|
|
183
197
|
}
|
|
184
198
|
}
|
|
185
|
-
}
|
|
199
|
+
});
|
|
186
200
|
|
|
187
201
|
// Set the responses collection
|
|
188
202
|
if (Object.keys(allResponses).length > 0) {
|
|
189
203
|
endpoint.responses = allResponses;
|
|
190
204
|
}
|
|
191
205
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const matchingMediaType = Object.keys(content).find(isResponseMediaType);
|
|
195
|
-
if (matchingMediaType && content[matchingMediaType]) {
|
|
196
|
-
endpoint.response = openApiSchemaToTs({
|
|
197
|
-
schema: content[matchingMediaType]?.schema ?? {},
|
|
198
|
-
ctx,
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Map response headers
|
|
204
|
-
const headers = responseObject?.headers;
|
|
205
|
-
if (headers) {
|
|
206
|
-
endpoint.responseHeaders = Object.entries(headers).reduce(
|
|
207
|
-
(acc, [name, headerOrRef]) => {
|
|
208
|
-
const header = refs.unwrap(headerOrRef);
|
|
209
|
-
acc[name] = openApiSchemaToTs({ schema: header.schema ?? {}, ctx });
|
|
210
|
-
return acc;
|
|
211
|
-
},
|
|
212
|
-
{} as Record<string, Box>,
|
|
213
|
-
);
|
|
206
|
+
if (Object.keys(allHeaders).length) {
|
|
207
|
+
endpoint.responseHeaders = allHeaders;
|
|
214
208
|
}
|
|
215
209
|
|
|
216
210
|
endpointList.push(endpoint);
|
|
@@ -233,7 +227,8 @@ const isAllowedParamMediaTypes = (
|
|
|
233
227
|
allowedParamMediaTypes.includes(mediaType as any) ||
|
|
234
228
|
mediaType.includes("text/");
|
|
235
229
|
|
|
236
|
-
const isResponseMediaType = (mediaType: string) =>
|
|
230
|
+
const isResponseMediaType = (mediaType: string) =>
|
|
231
|
+
mediaType === "*/*" || (mediaType.includes("application/") && mediaType.includes("json"));
|
|
237
232
|
const getAlias = ({ path, method, operation }: Endpoint) =>
|
|
238
233
|
sanitizeName(
|
|
239
234
|
(method + "_" + capitalize(operation.operationId ?? pathToVariableName(path))).replace(/-/g, "__"),
|
|
@@ -254,9 +249,8 @@ type RequestFormat = "json" | "form-data" | "form-url" | "binary" | "text";
|
|
|
254
249
|
|
|
255
250
|
type DefaultEndpoint = {
|
|
256
251
|
parameters?: EndpointParameters | undefined;
|
|
257
|
-
response: AnyBox;
|
|
258
252
|
responses?: Record<string, AnyBox>;
|
|
259
|
-
responseHeaders?: Record<string,
|
|
253
|
+
responseHeaders?: Record<string, Box<BoxObject>>;
|
|
260
254
|
};
|
|
261
255
|
|
|
262
256
|
export type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
|
|
@@ -270,7 +264,6 @@ export type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
|
|
|
270
264
|
hasParameters: boolean;
|
|
271
265
|
areParametersRequired: boolean;
|
|
272
266
|
};
|
|
273
|
-
response: TConfig["response"];
|
|
274
267
|
responses?: TConfig["responses"];
|
|
275
268
|
responseHeaders?: TConfig["responseHeaders"];
|
|
276
269
|
};
|
|
@@ -95,7 +95,7 @@ export const generateTanstackQueryFile = async (ctx: GeneratorContext & { relati
|
|
|
95
95
|
withResponse: false as const
|
|
96
96
|
};
|
|
97
97
|
const res = await this.client.${method}(path, requestParams);
|
|
98
|
-
return res as TEndpoint["
|
|
98
|
+
return res as InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"];
|
|
99
99
|
},
|
|
100
100
|
queryKey: queryKey
|
|
101
101
|
}),
|
|
@@ -110,7 +110,7 @@ export const generateTanstackQueryFile = async (ctx: GeneratorContext & { relati
|
|
|
110
110
|
withResponse: false as const
|
|
111
111
|
};
|
|
112
112
|
const res = await this.client.${method}(path, requestParams);
|
|
113
|
-
return res as TEndpoint["
|
|
113
|
+
return res as InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"];
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
};
|