Skip to content

Commit 7806860

Browse files
authored
Add requestFormat in endpoint schemas (#48)
1 parent 803aaae commit 7806860

24 files changed

+910
-1
lines changed

packages/typed-openapi/src/generator.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ const generateEndpointSchemaList = (ctx: GeneratorContext) => {
137137
file += `export type ${endpoint.meta.alias} = {
138138
method: "${endpoint.method.toUpperCase()}",
139139
path: "${endpoint.path}",
140+
requestFormat: "${endpoint.requestFormat}",
140141
${
141142
endpoint.meta.hasParameters
142143
? `parameters: {
@@ -235,6 +236,8 @@ export type EndpointParameters = {
235236
export type MutationMethod = "post" | "put" | "patch" | "delete";
236237
export type Method = "get" | "head" | MutationMethod;
237238
239+
type RequestFormat = "json" | "form-data" | "form-url" | "binary" | "text";
240+
238241
export type DefaultEndpoint = {
239242
parameters?: EndpointParameters | undefined;
240243
response: unknown;
@@ -244,6 +247,7 @@ export type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
244247
operationId: string;
245248
method: Method;
246249
path: string;
250+
requestFormat: RequestFormat;
247251
parameters?: TConfig["parameters"];
248252
meta: {
249253
alias: string;

packages/typed-openapi/src/map-openapi-endpoints.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { createRefResolver } from "./ref-resolver";
88
import { tsFactory } from "./ts-factory";
99
import { AnyBox, BoxRef, OpenapiSchemaConvertContext } from "./types";
1010
import { pathToVariableName } from "./string-utils";
11+
import { match, P } from "ts-pattern";
1112

1213
const factory = tsFactory;
1314

@@ -25,6 +26,7 @@ export const mapOpenApiEndpoints = (doc: OpenAPIObject) => {
2526
operation,
2627
method: method as Method,
2728
path,
29+
requestFormat: "json",
2830
response: openApiSchemaToTs({ schema: {}, ctx }),
2931
meta: {
3032
alias: getAlias({ path, method, operation } as Endpoint),
@@ -83,12 +85,21 @@ export const mapOpenApiEndpoints = (doc: OpenAPIObject) => {
8385
ctx,
8486
});
8587
}
88+
89+
endpoint.requestFormat = match(matchingMediaType)
90+
.with("application/octet-stream", () => "binary" as const)
91+
.with("multipart/form-data", () => "form-data" as const)
92+
.with("application/x-www-form-urlencoded", () => "form-url" as const)
93+
.with(P.string.includes("json"), () => "json" as const)
94+
.otherwise(() => "text" as const);
8695
}
8796

8897
// Make parameters optional if all or some of them are not required
8998
if (params) {
9099
const t = createBoxFactory({}, ctx);
91-
const filtered_params = ["query", "path", "header"] as Array<keyof Pick<typeof params, "query" | "path" | "header">>;
100+
const filtered_params = ["query", "path", "header"] as Array<
101+
keyof Pick<typeof params, "query" | "path" | "header">
102+
>;
92103

93104
for (const k of filtered_params) {
94105
if (params[k] && lists[k].length) {
@@ -165,6 +176,8 @@ export type EndpointParameters = {
165176
path?: Box<BoxRef> | Record<string, AnyBox>;
166177
};
167178

179+
type RequestFormat = "json" | "form-data" | "form-url" | "binary" | "text";
180+
168181
type DefaultEndpoint = {
169182
parameters?: EndpointParameters | undefined;
170183
response: AnyBox;
@@ -175,6 +188,7 @@ export type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
175188
method: Method;
176189
path: string;
177190
parameters?: TConfig["parameters"];
191+
requestFormat: RequestFormat;
178192
meta: {
179193
alias: string;
180194
hasParameters: boolean;

packages/typed-openapi/tests/generator.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ describe("generator", () => {
5151
export type put_UpdatePet = {
5252
method: "PUT";
5353
path: "/pet";
54+
requestFormat: "json";
5455
parameters: {
5556
body: Schemas.Pet;
5657
};
@@ -59,6 +60,7 @@ describe("generator", () => {
5960
export type post_AddPet = {
6061
method: "POST";
6162
path: "/pet";
63+
requestFormat: "json";
6264
parameters: {
6365
body: Schemas.Pet;
6466
};
@@ -67,6 +69,7 @@ describe("generator", () => {
6769
export type get_FindPetsByStatus = {
6870
method: "GET";
6971
path: "/pet/findByStatus";
72+
requestFormat: "json";
7073
parameters: {
7174
query: Partial<{ status: "available" | "pending" | "sold" }>;
7275
};
@@ -75,6 +78,7 @@ describe("generator", () => {
7578
export type get_FindPetsByTags = {
7679
method: "GET";
7780
path: "/pet/findByTags";
81+
requestFormat: "json";
7882
parameters: {
7983
query: Partial<{ tags: Array<string> }>;
8084
};
@@ -83,6 +87,7 @@ describe("generator", () => {
8387
export type get_GetPetById = {
8488
method: "GET";
8589
path: "/pet/{petId}";
90+
requestFormat: "json";
8691
parameters: {
8792
path: { petId: number };
8893
};
@@ -91,6 +96,7 @@ describe("generator", () => {
9196
export type post_UpdatePetWithForm = {
9297
method: "POST";
9398
path: "/pet/{petId}";
99+
requestFormat: "json";
94100
parameters: {
95101
query: Partial<{ name: string; status: string }>;
96102
path: { petId: number };
@@ -100,6 +106,7 @@ describe("generator", () => {
100106
export type delete_DeletePet = {
101107
method: "DELETE";
102108
path: "/pet/{petId}";
109+
requestFormat: "json";
103110
parameters: {
104111
path: { petId: number };
105112
header: Partial<{ api_key: string }>;
@@ -109,6 +116,7 @@ describe("generator", () => {
109116
export type post_UploadFile = {
110117
method: "POST";
111118
path: "/pet/{petId}/uploadImage";
119+
requestFormat: "binary";
112120
parameters: {
113121
query: Partial<{ additionalMetadata: string }>;
114122
path: { petId: number };
@@ -120,12 +128,14 @@ describe("generator", () => {
120128
export type get_GetInventory = {
121129
method: "GET";
122130
path: "/store/inventory";
131+
requestFormat: "json";
123132
parameters: never;
124133
response: unknown;
125134
};
126135
export type post_PlaceOrder = {
127136
method: "POST";
128137
path: "/store/order";
138+
requestFormat: "json";
129139
parameters: {
130140
body: Schemas.Order;
131141
};
@@ -134,6 +144,7 @@ describe("generator", () => {
134144
export type get_GetOrderById = {
135145
method: "GET";
136146
path: "/store/order/{orderId}";
147+
requestFormat: "json";
137148
parameters: {
138149
path: { orderId: number };
139150
};
@@ -142,6 +153,7 @@ describe("generator", () => {
142153
export type delete_DeleteOrder = {
143154
method: "DELETE";
144155
path: "/store/order/{orderId}";
156+
requestFormat: "json";
145157
parameters: {
146158
path: { orderId: number };
147159
};
@@ -150,6 +162,7 @@ describe("generator", () => {
150162
export type post_CreateUser = {
151163
method: "POST";
152164
path: "/user";
165+
requestFormat: "json";
153166
parameters: {
154167
body: Schemas.User;
155168
};
@@ -158,6 +171,7 @@ describe("generator", () => {
158171
export type post_CreateUsersWithListInput = {
159172
method: "POST";
160173
path: "/user/createWithList";
174+
requestFormat: "json";
161175
parameters: {
162176
body: Array<Schemas.User>;
163177
};
@@ -166,6 +180,7 @@ describe("generator", () => {
166180
export type get_LoginUser = {
167181
method: "GET";
168182
path: "/user/login";
183+
requestFormat: "json";
169184
parameters: {
170185
query: Partial<{ username: string; password: string }>;
171186
};
@@ -174,12 +189,14 @@ describe("generator", () => {
174189
export type get_LogoutUser = {
175190
method: "GET";
176191
path: "/user/logout";
192+
requestFormat: "json";
177193
parameters: never;
178194
response: unknown;
179195
};
180196
export type get_GetUserByName = {
181197
method: "GET";
182198
path: "/user/{username}";
199+
requestFormat: "json";
183200
parameters: {
184201
path: { username: string };
185202
};
@@ -188,6 +205,7 @@ describe("generator", () => {
188205
export type put_UpdateUser = {
189206
method: "PUT";
190207
path: "/user/{username}";
208+
requestFormat: "json";
191209
parameters: {
192210
path: { username: string };
193211
@@ -198,6 +216,7 @@ describe("generator", () => {
198216
export type delete_DeleteUser = {
199217
method: "DELETE";
200218
path: "/user/{username}";
219+
requestFormat: "json";
201220
parameters: {
202221
path: { username: string };
203222
};
@@ -259,6 +278,8 @@ describe("generator", () => {
259278
export type MutationMethod = "post" | "put" | "patch" | "delete";
260279
export type Method = "get" | "head" | MutationMethod;
261280
281+
type RequestFormat = "json" | "form-data" | "form-url" | "binary" | "text";
282+
262283
export type DefaultEndpoint = {
263284
parameters?: EndpointParameters | undefined;
264285
response: unknown;
@@ -268,6 +289,7 @@ describe("generator", () => {
268289
operationId: string;
269290
method: Method;
270291
path: string;
292+
requestFormat: RequestFormat;
271293
parameters?: TConfig["parameters"];
272294
meta: {
273295
alias: string;

0 commit comments

Comments
 (0)