typed-openapi 2.0.1 → 2.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.
- package/dist/{chunk-4EZJSCLI.js → chunk-I2PUFY2J.js} +109 -95
- package/dist/{chunk-GD55PFNE.js → chunk-J2KG2QH2.js} +1 -1
- 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 +62 -49
- package/src/map-openapi-endpoints.ts +56 -63
- package/src/tanstack-query.generator.ts +2 -2
|
@@ -503,12 +503,6 @@ var generateEndpointSchemaList = (ctx) => {
|
|
|
503
503
|
ctx
|
|
504
504
|
)},` : ""}
|
|
505
505
|
}` : "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
506
|
${endpoint.responses ? `responses: ${generateResponsesObject(endpoint.responses, ctx)},` : ""}
|
|
513
507
|
${endpoint.responseHeaders ? `responseHeaders: ${responseHeadersObjectToString(endpoint.responseHeaders, ctx)},` : ""}
|
|
514
508
|
}
|
|
@@ -567,7 +561,6 @@ type RequestFormat = "json" | "form-data" | "form-url" | "binary" | "text";
|
|
|
567
561
|
|
|
568
562
|
export type DefaultEndpoint = {
|
|
569
563
|
parameters?: EndpointParameters | undefined;
|
|
570
|
-
response: unknown;
|
|
571
564
|
responses?: Record<string, unknown>;
|
|
572
565
|
responseHeaders?: Record<string, unknown>;
|
|
573
566
|
};
|
|
@@ -583,7 +576,6 @@ export type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
|
|
|
583
576
|
hasParameters: boolean;
|
|
584
577
|
areParametersRequired: boolean;
|
|
585
578
|
};
|
|
586
|
-
response: TConfig["response"];
|
|
587
579
|
responses?: TConfig["responses"];
|
|
588
580
|
responseHeaders?: TConfig["responseHeaders"]
|
|
589
581
|
};
|
|
@@ -596,49 +588,63 @@ export type SuccessStatusCode = typeof successStatusCodes[number];
|
|
|
596
588
|
export const errorStatusCodes = [${ctx.errorStatusCodes.join(",")}] as const;
|
|
597
589
|
export type ErrorStatusCode = typeof errorStatusCodes[number];
|
|
598
590
|
|
|
599
|
-
//
|
|
591
|
+
// Taken from https://github.com/unjs/fetchdts/blob/ec4eaeab5d287116171fc1efd61f4a1ad34e4609/src/fetch.ts#L3
|
|
592
|
+
export interface TypedHeaders<TypedHeaderValues extends Record<string, string> | unknown> extends Omit<Headers, 'append' | 'delete' | 'get' | 'getSetCookie' | 'has' | 'set' | 'forEach'> {
|
|
593
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/append) */
|
|
594
|
+
append: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name, value: Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) => void
|
|
595
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/delete) */
|
|
596
|
+
delete: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => void
|
|
597
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/get) */
|
|
598
|
+
get: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => (Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) | null
|
|
599
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/getSetCookie) */
|
|
600
|
+
getSetCookie: () => string[]
|
|
601
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/has) */
|
|
602
|
+
has: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => boolean
|
|
603
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/set) */
|
|
604
|
+
set: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name, value: Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) => void
|
|
605
|
+
forEach: (callbackfn: (value: TypedHeaderValues[keyof TypedHeaderValues] | string & {}, key: Extract<keyof TypedHeaderValues, string> | string & {}, parent: TypedHeaders<TypedHeaderValues>) => void, thisArg?: any) => void
|
|
606
|
+
}
|
|
607
|
+
|
|
600
608
|
/** @see https://developer.mozilla.org/en-US/docs/Web/API/Response */
|
|
601
|
-
interface
|
|
609
|
+
export interface TypedSuccessResponse<TSuccess, TStatusCode, THeaders> extends Omit<Response, "ok" | "status" | "json" | "headers"> {
|
|
602
610
|
ok: true;
|
|
603
611
|
status: TStatusCode;
|
|
612
|
+
headers: never extends THeaders ? Headers : TypedHeaders<THeaders>;
|
|
604
613
|
data: TSuccess;
|
|
605
614
|
/** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Response/json) */
|
|
606
615
|
json: () => Promise<TSuccess>;
|
|
607
616
|
}
|
|
608
617
|
|
|
609
618
|
/** @see https://developer.mozilla.org/en-US/docs/Web/API/Response */
|
|
610
|
-
interface
|
|
619
|
+
export interface TypedErrorResponse<TData, TStatusCode, THeaders> extends Omit<Response, "ok" | "status" | "json" | "headers"> {
|
|
611
620
|
ok: false;
|
|
612
621
|
status: TStatusCode;
|
|
622
|
+
headers: never extends THeaders ? Headers : TypedHeaders<THeaders>;
|
|
613
623
|
data: TData;
|
|
614
624
|
/** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Response/json) */
|
|
615
625
|
json: () => Promise<TData>;
|
|
616
626
|
}
|
|
617
627
|
|
|
618
|
-
export type TypedApiResponse<
|
|
619
|
-
(
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
? K extends
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
: never;
|
|
633
|
-
}[keyof TAllResponses]);
|
|
628
|
+
export type TypedApiResponse<TAllResponses extends Record<string | number, unknown> = {}, THeaders = {}> =
|
|
629
|
+
({
|
|
630
|
+
[K in keyof TAllResponses]: K extends string
|
|
631
|
+
? K extends \`\${infer TStatusCode extends number}\`
|
|
632
|
+
? TStatusCode extends SuccessStatusCode
|
|
633
|
+
? TypedSuccessResponse<TAllResponses[K], TStatusCode, K extends keyof THeaders ? THeaders[K] : never>
|
|
634
|
+
: TypedErrorResponse<TAllResponses[K], TStatusCode, K extends keyof THeaders ? THeaders[K] : never>
|
|
635
|
+
: never
|
|
636
|
+
: K extends number
|
|
637
|
+
? K extends SuccessStatusCode
|
|
638
|
+
? TypedSuccessResponse<TAllResponses[K], K, K extends keyof THeaders ? THeaders[K] : never>
|
|
639
|
+
: TypedErrorResponse<TAllResponses[K], K, K extends keyof THeaders ? THeaders[K] : never>
|
|
640
|
+
: never;
|
|
641
|
+
}[keyof TAllResponses]);
|
|
634
642
|
|
|
635
|
-
export type SafeApiResponse<TEndpoint> = TEndpoint extends {
|
|
643
|
+
export type SafeApiResponse<TEndpoint> = TEndpoint extends { responses: infer TResponses }
|
|
636
644
|
? TResponses extends Record<string, unknown>
|
|
637
|
-
? TypedApiResponse<
|
|
638
|
-
:
|
|
639
|
-
:
|
|
640
|
-
? SuccessResponse<TSuccess, number>
|
|
641
|
-
: never;
|
|
645
|
+
? TypedApiResponse<TResponses, TEndpoint extends { responseHeaders: infer THeaders } ? THeaders : never>
|
|
646
|
+
: never
|
|
647
|
+
: never
|
|
642
648
|
|
|
643
649
|
export type InferResponseByStatus<TEndpoint, TStatusCode> = Extract<SafeApiResponse<TEndpoint>, { status: TStatusCode }>
|
|
644
650
|
|
|
@@ -653,9 +659,9 @@ type MaybeOptionalArg<T> = RequiredKeys<T> extends never ? [config?: T] : [confi
|
|
|
653
659
|
const apiClient = `
|
|
654
660
|
// <TypedResponseError>
|
|
655
661
|
export class TypedResponseError extends Error {
|
|
656
|
-
response:
|
|
662
|
+
response: TypedErrorResponse<unknown, ErrorStatusCode, unknown>;
|
|
657
663
|
status: number;
|
|
658
|
-
constructor(response:
|
|
664
|
+
constructor(response: TypedErrorResponse<unknown, ErrorStatusCode, unknown>) {
|
|
659
665
|
super(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
660
666
|
this.name = 'TypedResponseError';
|
|
661
667
|
this.response = response;
|
|
@@ -691,7 +697,13 @@ export class ApiClient {
|
|
|
691
697
|
${method}<Path extends keyof ${capitalizedMethod}Endpoints, TEndpoint extends ${capitalizedMethod}Endpoints[Path]>(
|
|
692
698
|
path: Path,
|
|
693
699
|
...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
|
|
700
|
+
): Promise<${match(ctx.runtime).with("zod", "yup", () => infer(`InferResponseByStatus<TEndpoint, SuccessStatusCode>`)).with(
|
|
701
|
+
"arktype",
|
|
702
|
+
"io-ts",
|
|
703
|
+
"typebox",
|
|
704
|
+
"valibot",
|
|
705
|
+
() => `InferResponseByStatus<${infer(`TEndpoint`)}, SuccessStatusCode>["data"]`
|
|
706
|
+
).otherwise(() => `InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"]`)}>;
|
|
695
707
|
|
|
696
708
|
${method}<Path extends keyof ${capitalizedMethod}Endpoints, TEndpoint extends ${capitalizedMethod}Endpoints[Path]>(
|
|
697
709
|
path: Path,
|
|
@@ -721,7 +733,13 @@ export class ApiClient {
|
|
|
721
733
|
return withResponse ? typedResponse : data;
|
|
722
734
|
});
|
|
723
735
|
|
|
724
|
-
return promise ${match(ctx.runtime).with("zod", "yup", () => `as Promise<${infer(`TEndpoint
|
|
736
|
+
return promise ${match(ctx.runtime).with("zod", "yup", () => `as Promise<${infer(`InferResponseByStatus<TEndpoint, SuccessStatusCode>`)}>`).with(
|
|
737
|
+
"arktype",
|
|
738
|
+
"io-ts",
|
|
739
|
+
"typebox",
|
|
740
|
+
"valibot",
|
|
741
|
+
() => `as Promise<InferResponseByStatus<${infer(`TEndpoint`)}, SuccessStatusCode>["data"]>`
|
|
742
|
+
).otherwise(() => `as Promise<InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"]>`)}
|
|
725
743
|
}
|
|
726
744
|
// </ApiClient.${method}>
|
|
727
745
|
` : "";
|
|
@@ -1082,7 +1100,6 @@ var mapOpenApiEndpoints = (doc, options) => {
|
|
|
1082
1100
|
method,
|
|
1083
1101
|
path,
|
|
1084
1102
|
requestFormat: "json",
|
|
1085
|
-
response: openApiSchemaToTs({ schema: {}, ctx }),
|
|
1086
1103
|
meta: {
|
|
1087
1104
|
alias,
|
|
1088
1105
|
areParametersRequired: false,
|
|
@@ -1124,11 +1141,11 @@ var mapOpenApiEndpoints = (doc, options) => {
|
|
|
1124
1141
|
if (operation.requestBody) {
|
|
1125
1142
|
endpoint.meta.hasParameters = true;
|
|
1126
1143
|
const requestBody = refs.unwrap(operation.requestBody ?? {});
|
|
1127
|
-
const
|
|
1128
|
-
const matchingMediaType = Object.keys(
|
|
1129
|
-
if (matchingMediaType &&
|
|
1144
|
+
const content = requestBody.content;
|
|
1145
|
+
const matchingMediaType = Object.keys(content).find(isAllowedParamMediaTypes);
|
|
1146
|
+
if (matchingMediaType && content[matchingMediaType]) {
|
|
1130
1147
|
params.body = openApiSchemaToTs({
|
|
1131
|
-
schema:
|
|
1148
|
+
schema: content[matchingMediaType]?.schema ?? {},
|
|
1132
1149
|
ctx
|
|
1133
1150
|
});
|
|
1134
1151
|
}
|
|
@@ -1159,67 +1176,64 @@ var mapOpenApiEndpoints = (doc, options) => {
|
|
|
1159
1176
|
}
|
|
1160
1177
|
endpoint.parameters = Object.keys(params).length ? params : void 0;
|
|
1161
1178
|
}
|
|
1162
|
-
let responseObject;
|
|
1163
1179
|
const allResponses = {};
|
|
1180
|
+
const allHeaders = {};
|
|
1164
1181
|
Object.entries(operation.responses ?? {}).map(([status, responseOrRef]) => {
|
|
1165
|
-
const statusCode = Number(status);
|
|
1166
1182
|
const responseObj = refs.unwrap(responseOrRef);
|
|
1167
|
-
const
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1183
|
+
const content = responseObj?.content;
|
|
1184
|
+
const mediaTypes = Object.keys(content ?? {}).filter(isResponseMediaType);
|
|
1185
|
+
if (content && mediaTypes.length) {
|
|
1186
|
+
mediaTypes.forEach((mediaType) => {
|
|
1187
|
+
const schema = content[mediaType] ? content[mediaType].schema ?? {} : {};
|
|
1188
|
+
const t2 = createBoxFactory(schema, ctx);
|
|
1189
|
+
const mediaTypeResponse = openApiSchemaToTs({ schema, ctx });
|
|
1190
|
+
if (allResponses[status]) {
|
|
1191
|
+
allResponses[status] = t2.union([
|
|
1192
|
+
...Array.isArray(allResponses[status]) ? allResponses[status] : [allResponses[status]],
|
|
1193
|
+
mediaTypeResponse
|
|
1194
|
+
]);
|
|
1195
|
+
} else {
|
|
1196
|
+
allResponses[status] = mediaTypeResponse;
|
|
1197
|
+
}
|
|
1198
|
+
});
|
|
1199
|
+
} else {
|
|
1200
|
+
const schema = {};
|
|
1201
|
+
const unknown = openApiSchemaToTs({ schema: {}, ctx });
|
|
1202
|
+
const t2 = createBoxFactory(schema, ctx);
|
|
1203
|
+
if (allResponses[status]) {
|
|
1204
|
+
allResponses[status] = t2.union([
|
|
1205
|
+
...Array.isArray(allResponses[status]) ? allResponses[status] : [allResponses[status]],
|
|
1206
|
+
unknown
|
|
1207
|
+
]);
|
|
1175
1208
|
} else {
|
|
1176
|
-
allResponses[status] =
|
|
1209
|
+
allResponses[status] = unknown;
|
|
1177
1210
|
}
|
|
1178
|
-
} else {
|
|
1179
|
-
allResponses[status] = openApiSchemaToTs({ schema: {}, ctx });
|
|
1180
1211
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1212
|
+
const headers = responseObj?.headers;
|
|
1213
|
+
const t = createBoxFactory(
|
|
1214
|
+
{ type: "object", properties: headers ?? {}, required: Object.keys(headers ?? {}) },
|
|
1215
|
+
ctx
|
|
1216
|
+
);
|
|
1217
|
+
if (headers) {
|
|
1218
|
+
const mappedHeaders = Object.entries(headers).reduce(
|
|
1219
|
+
(acc, [name, headerOrRef]) => {
|
|
1220
|
+
const header = refs.unwrap(headerOrRef);
|
|
1221
|
+
const box = openApiSchemaToTs({ schema: header.schema ?? {}, ctx });
|
|
1222
|
+
acc[name] = box;
|
|
1223
|
+
return acc;
|
|
1224
|
+
},
|
|
1225
|
+
{}
|
|
1226
|
+
);
|
|
1227
|
+
if (Object.keys(mappedHeaders).length) {
|
|
1228
|
+
allHeaders[status] = t.object(mappedHeaders);
|
|
1197
1229
|
}
|
|
1198
1230
|
}
|
|
1199
|
-
}
|
|
1231
|
+
});
|
|
1200
1232
|
if (Object.keys(allResponses).length > 0) {
|
|
1201
1233
|
endpoint.responses = allResponses;
|
|
1202
1234
|
}
|
|
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
|
-
);
|
|
1235
|
+
if (Object.keys(allHeaders).length) {
|
|
1236
|
+
endpoint.responseHeaders = allHeaders;
|
|
1223
1237
|
}
|
|
1224
1238
|
endpointList.push(endpoint);
|
|
1225
1239
|
});
|
|
@@ -1233,7 +1247,7 @@ var allowedParamMediaTypes = [
|
|
|
1233
1247
|
"*/*"
|
|
1234
1248
|
];
|
|
1235
1249
|
var isAllowedParamMediaTypes = (mediaType) => mediaType.includes("application/") && mediaType.includes("json") || allowedParamMediaTypes.includes(mediaType) || mediaType.includes("text/");
|
|
1236
|
-
var isResponseMediaType = (mediaType) => mediaType === "
|
|
1250
|
+
var isResponseMediaType = (mediaType) => mediaType === "*/*" || mediaType.includes("application/") && mediaType.includes("json");
|
|
1237
1251
|
var getAlias = ({ path, method, operation }) => sanitizeName(
|
|
1238
1252
|
(method + "_" + capitalize3(operation.operationId ?? pathToVariableName(path))).replace(/-/g, "__"),
|
|
1239
1253
|
"endpoint"
|
|
@@ -1325,7 +1339,7 @@ var generateTanstackQueryFile = async (ctx) => {
|
|
|
1325
1339
|
withResponse: false as const
|
|
1326
1340
|
};
|
|
1327
1341
|
const res = await this.client.${method}(path, requestParams);
|
|
1328
|
-
return res as TEndpoint["
|
|
1342
|
+
return res as InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"];
|
|
1329
1343
|
},
|
|
1330
1344
|
queryKey: queryKey
|
|
1331
1345
|
}),
|
|
@@ -1340,7 +1354,7 @@ var generateTanstackQueryFile = async (ctx) => {
|
|
|
1340
1354
|
withResponse: false as const
|
|
1341
1355
|
};
|
|
1342
1356
|
const res = await this.client.${method}(path, requestParams);
|
|
1343
|
-
return res as TEndpoint["
|
|
1357
|
+
return res as InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"];
|
|
1344
1358
|
}
|
|
1345
1359
|
}
|
|
1346
1360
|
};
|
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.0
|
|
4
|
+
"version": "2.1.0",
|
|
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,7 +170,7 @@ 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>>, ctx: GeneratorContext) => {
|
|
174
174
|
let str = "{";
|
|
175
175
|
for (const [key, responseHeader] of Object.entries(responseHeaders)) {
|
|
176
176
|
const value =
|
|
@@ -242,17 +242,6 @@ const generateEndpointSchemaList = (ctx: GeneratorContext) => {
|
|
|
242
242
|
}`
|
|
243
243
|
: "parameters: never,"
|
|
244
244
|
}
|
|
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
245
|
${endpoint.responses ? `responses: ${generateResponsesObject(endpoint.responses, ctx)},` : ""}
|
|
257
246
|
${
|
|
258
247
|
endpoint.responseHeaders
|
|
@@ -331,7 +320,6 @@ type RequestFormat = "json" | "form-data" | "form-url" | "binary" | "text";
|
|
|
331
320
|
|
|
332
321
|
export type DefaultEndpoint = {
|
|
333
322
|
parameters?: EndpointParameters | undefined;
|
|
334
|
-
response: unknown;
|
|
335
323
|
responses?: Record<string, unknown>;
|
|
336
324
|
responseHeaders?: Record<string, unknown>;
|
|
337
325
|
};
|
|
@@ -347,7 +335,6 @@ export type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
|
|
|
347
335
|
hasParameters: boolean;
|
|
348
336
|
areParametersRequired: boolean;
|
|
349
337
|
};
|
|
350
|
-
response: TConfig["response"];
|
|
351
338
|
responses?: TConfig["responses"];
|
|
352
339
|
responseHeaders?: TConfig["responseHeaders"]
|
|
353
340
|
};
|
|
@@ -360,49 +347,63 @@ export type SuccessStatusCode = typeof successStatusCodes[number];
|
|
|
360
347
|
export const errorStatusCodes = [${ctx.errorStatusCodes.join(",")}] as const;
|
|
361
348
|
export type ErrorStatusCode = typeof errorStatusCodes[number];
|
|
362
349
|
|
|
363
|
-
//
|
|
350
|
+
// Taken from https://github.com/unjs/fetchdts/blob/ec4eaeab5d287116171fc1efd61f4a1ad34e4609/src/fetch.ts#L3
|
|
351
|
+
export interface TypedHeaders<TypedHeaderValues extends Record<string, string> | unknown> extends Omit<Headers, 'append' | 'delete' | 'get' | 'getSetCookie' | 'has' | 'set' | 'forEach'> {
|
|
352
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/append) */
|
|
353
|
+
append: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name, value: Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) => void
|
|
354
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/delete) */
|
|
355
|
+
delete: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => void
|
|
356
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/get) */
|
|
357
|
+
get: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => (Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) | null
|
|
358
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/getSetCookie) */
|
|
359
|
+
getSetCookie: () => string[]
|
|
360
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/has) */
|
|
361
|
+
has: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name) => boolean
|
|
362
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/set) */
|
|
363
|
+
set: <Name extends Extract<keyof TypedHeaderValues, string> | string & {}> (name: Name, value: Lowercase<Name> extends keyof TypedHeaderValues ? TypedHeaderValues[Lowercase<Name>] : string) => void
|
|
364
|
+
forEach: (callbackfn: (value: TypedHeaderValues[keyof TypedHeaderValues] | string & {}, key: Extract<keyof TypedHeaderValues, string> | string & {}, parent: TypedHeaders<TypedHeaderValues>) => void, thisArg?: any) => void
|
|
365
|
+
}
|
|
366
|
+
|
|
364
367
|
/** @see https://developer.mozilla.org/en-US/docs/Web/API/Response */
|
|
365
|
-
interface
|
|
368
|
+
export interface TypedSuccessResponse<TSuccess, TStatusCode, THeaders> extends Omit<Response, "ok" | "status" | "json" | "headers"> {
|
|
366
369
|
ok: true;
|
|
367
370
|
status: TStatusCode;
|
|
371
|
+
headers: never extends THeaders ? Headers : TypedHeaders<THeaders>;
|
|
368
372
|
data: TSuccess;
|
|
369
373
|
/** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Response/json) */
|
|
370
374
|
json: () => Promise<TSuccess>;
|
|
371
375
|
}
|
|
372
376
|
|
|
373
377
|
/** @see https://developer.mozilla.org/en-US/docs/Web/API/Response */
|
|
374
|
-
interface
|
|
378
|
+
export interface TypedErrorResponse<TData, TStatusCode, THeaders> extends Omit<Response, "ok" | "status" | "json" | "headers"> {
|
|
375
379
|
ok: false;
|
|
376
380
|
status: TStatusCode;
|
|
381
|
+
headers: never extends THeaders ? Headers : TypedHeaders<THeaders>;
|
|
377
382
|
data: TData;
|
|
378
383
|
/** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Response/json) */
|
|
379
384
|
json: () => Promise<TData>;
|
|
380
385
|
}
|
|
381
386
|
|
|
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 }
|
|
387
|
+
export type TypedApiResponse<TAllResponses extends Record<string | number, unknown> = {}, THeaders = {}> =
|
|
388
|
+
({
|
|
389
|
+
[K in keyof TAllResponses]: K extends string
|
|
390
|
+
? K extends \`\${infer TStatusCode extends number}\`
|
|
391
|
+
? TStatusCode extends SuccessStatusCode
|
|
392
|
+
? TypedSuccessResponse<TAllResponses[K], TStatusCode, K extends keyof THeaders ? THeaders[K] : never>
|
|
393
|
+
: TypedErrorResponse<TAllResponses[K], TStatusCode, K extends keyof THeaders ? THeaders[K] : never>
|
|
394
|
+
: never
|
|
395
|
+
: K extends number
|
|
396
|
+
? K extends SuccessStatusCode
|
|
397
|
+
? TypedSuccessResponse<TAllResponses[K], K, K extends keyof THeaders ? THeaders[K] : never>
|
|
398
|
+
: TypedErrorResponse<TAllResponses[K], K, K extends keyof THeaders ? THeaders[K] : never>
|
|
399
|
+
: never;
|
|
400
|
+
}[keyof TAllResponses]);
|
|
401
|
+
|
|
402
|
+
export type SafeApiResponse<TEndpoint> = TEndpoint extends { responses: infer TResponses }
|
|
400
403
|
? TResponses extends Record<string, unknown>
|
|
401
|
-
? TypedApiResponse<
|
|
402
|
-
:
|
|
403
|
-
:
|
|
404
|
-
? SuccessResponse<TSuccess, number>
|
|
405
|
-
: never;
|
|
404
|
+
? TypedApiResponse<TResponses, TEndpoint extends { responseHeaders: infer THeaders } ? THeaders : never>
|
|
405
|
+
: never
|
|
406
|
+
: never
|
|
406
407
|
|
|
407
408
|
export type InferResponseByStatus<TEndpoint, TStatusCode> = Extract<SafeApiResponse<TEndpoint>, { status: TStatusCode }>
|
|
408
409
|
|
|
@@ -418,9 +419,9 @@ type MaybeOptionalArg<T> = RequiredKeys<T> extends never ? [config?: T] : [confi
|
|
|
418
419
|
const apiClient = `
|
|
419
420
|
// <TypedResponseError>
|
|
420
421
|
export class TypedResponseError extends Error {
|
|
421
|
-
response:
|
|
422
|
+
response: TypedErrorResponse<unknown, ErrorStatusCode, unknown>;
|
|
422
423
|
status: number;
|
|
423
|
-
constructor(response:
|
|
424
|
+
constructor(response: TypedErrorResponse<unknown, ErrorStatusCode, unknown>) {
|
|
424
425
|
super(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
425
426
|
this.name = 'TypedResponseError';
|
|
426
427
|
this.response = response;
|
|
@@ -463,9 +464,15 @@ export class ApiClient {
|
|
|
463
464
|
.with("arktype", "io-ts", "typebox", "valibot", () => infer(`TEndpoint`) + `["parameters"]`)
|
|
464
465
|
.otherwise(() => `TEndpoint["parameters"]`)} & { withResponse?: false; throwOnStatusError?: boolean }>
|
|
465
466
|
): Promise<${match(ctx.runtime)
|
|
466
|
-
.with("zod", "yup", () => infer(`TEndpoint
|
|
467
|
-
.with(
|
|
468
|
-
|
|
467
|
+
.with("zod", "yup", () => infer(`InferResponseByStatus<TEndpoint, SuccessStatusCode>`))
|
|
468
|
+
.with(
|
|
469
|
+
"arktype",
|
|
470
|
+
"io-ts",
|
|
471
|
+
"typebox",
|
|
472
|
+
"valibot",
|
|
473
|
+
() => `InferResponseByStatus<${infer(`TEndpoint`)}, SuccessStatusCode>["data"]`,
|
|
474
|
+
)
|
|
475
|
+
.otherwise(() => `InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"]`)}>;
|
|
469
476
|
|
|
470
477
|
${method}<Path extends keyof ${capitalizedMethod}Endpoints, TEndpoint extends ${capitalizedMethod}Endpoints[Path]>(
|
|
471
478
|
path: Path,
|
|
@@ -499,9 +506,15 @@ export class ApiClient {
|
|
|
499
506
|
});
|
|
500
507
|
|
|
501
508
|
return promise ${match(ctx.runtime)
|
|
502
|
-
.with("zod", "yup", () => `as Promise<${infer(`TEndpoint
|
|
503
|
-
.with(
|
|
504
|
-
|
|
509
|
+
.with("zod", "yup", () => `as Promise<${infer(`InferResponseByStatus<TEndpoint, SuccessStatusCode>`)}>`)
|
|
510
|
+
.with(
|
|
511
|
+
"arktype",
|
|
512
|
+
"io-ts",
|
|
513
|
+
"typebox",
|
|
514
|
+
"valibot",
|
|
515
|
+
() => `as Promise<InferResponseByStatus<${infer(`TEndpoint`)}, SuccessStatusCode>["data"]>`,
|
|
516
|
+
)
|
|
517
|
+
.otherwise(() => `as Promise<InferResponseByStatus<TEndpoint, SuccessStatusCode>["data"]>`)}
|
|
505
518
|
}
|
|
506
519
|
// </ApiClient.${method}>
|
|
507
520
|
`
|
|
@@ -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
|
};
|