@shipworthy/openapi-fetch 0.0.0-stage → 0.0.2
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/LICENSE +21 -0
- package/README.md +575 -2
- package/dist/index.cjs +538 -0
- package/dist/index.d.cts +450 -0
- package/dist/index.d.ts +450 -0
- package/dist/index.js +522 -0
- package/package.json +55 -4
package/dist/index.js
ADDED
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
//#region src/headers.ts
|
|
2
|
+
/** Iterate any `HeadersOptions` form (plain object, `Headers`, or `[name, value]` tuples) as entries */
|
|
3
|
+
function headerEntries(h) {
|
|
4
|
+
if (h instanceof Headers) return h.entries();
|
|
5
|
+
if (Array.isArray(h)) return new Headers(h).entries();
|
|
6
|
+
return Object.entries(h);
|
|
7
|
+
}
|
|
8
|
+
/** Merge headers a and b, with b taking priority */
|
|
9
|
+
function mergeHeaders(...allHeaders) {
|
|
10
|
+
const finalHeaders = new Headers();
|
|
11
|
+
for (const h of allHeaders) {
|
|
12
|
+
if (!h || typeof h !== "object") continue;
|
|
13
|
+
for (const [k, v] of headerEntries(h)) if (v === null) finalHeaders.delete(k);
|
|
14
|
+
else if (Array.isArray(v)) for (const v2 of v) finalHeaders.append(k, String(v2));
|
|
15
|
+
else if (v !== void 0) finalHeaders.set(k, String(v));
|
|
16
|
+
}
|
|
17
|
+
return finalHeaders;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/serializers/body.ts
|
|
21
|
+
/** Serialize body object to string */
|
|
22
|
+
function defaultBodySerializer(body, headers) {
|
|
23
|
+
if (body instanceof FormData) return body;
|
|
24
|
+
if (headers) {
|
|
25
|
+
if ((typeof headers.get === "function" ? headers.get("Content-Type") ?? headers.get("content-type") : headers["Content-Type"] ?? headers["content-type"]) === "application/x-www-form-urlencoded") return new URLSearchParams(body).toString();
|
|
26
|
+
}
|
|
27
|
+
return JSON.stringify(body);
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/serializers/param.ts
|
|
31
|
+
/** Serialize primitive params to string */
|
|
32
|
+
function serializePrimitiveParam(name, value, options) {
|
|
33
|
+
if (value === void 0 || value === null) return "";
|
|
34
|
+
if (typeof value === "object") throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");
|
|
35
|
+
return `${name}=${options?.allowReserved === true ? value : encodeURIComponent(value)}`;
|
|
36
|
+
}
|
|
37
|
+
/** Serialize object param to string */
|
|
38
|
+
function serializeObjectParam(name, value, options) {
|
|
39
|
+
if (!value || typeof value !== "object") return "";
|
|
40
|
+
const values = [];
|
|
41
|
+
const joiner = {
|
|
42
|
+
simple: ",",
|
|
43
|
+
label: ".",
|
|
44
|
+
matrix: ";"
|
|
45
|
+
}[options.style] || "&";
|
|
46
|
+
if (options.style !== "deepObject" && options.explode === false) {
|
|
47
|
+
for (const k in value) values.push(k, options.allowReserved === true ? value[k] : encodeURIComponent(String(value[k])));
|
|
48
|
+
const final = values.join(",");
|
|
49
|
+
switch (options.style) {
|
|
50
|
+
case "form": return `${name}=${final}`;
|
|
51
|
+
case "label": return `.${final}`;
|
|
52
|
+
case "matrix": return `;${name}=${final}`;
|
|
53
|
+
default: return final;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (const k in value) {
|
|
57
|
+
const finalName = options.style === "deepObject" ? `${name}[${k}]` : k;
|
|
58
|
+
values.push(serializePrimitiveParam(finalName, value[k], options));
|
|
59
|
+
}
|
|
60
|
+
const final = values.join(joiner);
|
|
61
|
+
return options.style === "label" || options.style === "matrix" ? `${joiner}${final}` : final;
|
|
62
|
+
}
|
|
63
|
+
/** Serialize array param (shallow only) */
|
|
64
|
+
function serializeArrayParam(name, value, options) {
|
|
65
|
+
if (!Array.isArray(value)) return "";
|
|
66
|
+
if (options.explode === false) {
|
|
67
|
+
const joiner = {
|
|
68
|
+
form: ",",
|
|
69
|
+
spaceDelimited: "%20",
|
|
70
|
+
pipeDelimited: "|"
|
|
71
|
+
}[options.style] || ",";
|
|
72
|
+
const final = (options.allowReserved === true ? value : value.map((v) => encodeURIComponent(String(v)))).join(joiner);
|
|
73
|
+
switch (options.style) {
|
|
74
|
+
case "simple": return final;
|
|
75
|
+
case "label": return `.${final}`;
|
|
76
|
+
case "matrix": return `;${name}=${final}`;
|
|
77
|
+
default: return `${name}=${final}`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const joiner = {
|
|
81
|
+
simple: ",",
|
|
82
|
+
label: ".",
|
|
83
|
+
matrix: ";"
|
|
84
|
+
}[options.style] || "&";
|
|
85
|
+
const values = [];
|
|
86
|
+
for (const v of value) if (options.style === "simple" || options.style === "label") values.push(options.allowReserved === true ? v : encodeURIComponent(String(v)));
|
|
87
|
+
else values.push(serializePrimitiveParam(name, v, options));
|
|
88
|
+
return options.style === "label" || options.style === "matrix" ? `${joiner}${values.join(joiner)}` : values.join(joiner);
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/serializers/cookie.ts
|
|
92
|
+
/**
|
|
93
|
+
* Serialize cookie params to a `Cookie` header value using the OpenAPI default
|
|
94
|
+
* (style: form, explode: true). Arrays repeat the name, objects emit one pair per key,
|
|
95
|
+
* and values are URI-encoded. `undefined` and `null` values are skipped.
|
|
96
|
+
* @see https://swagger.io/docs/specification/serialization/#cookie
|
|
97
|
+
*/
|
|
98
|
+
function serializeCookieParams(cookieParams) {
|
|
99
|
+
const pairs = [];
|
|
100
|
+
if (!cookieParams || typeof cookieParams !== "object") return "";
|
|
101
|
+
const push = (name, value) => {
|
|
102
|
+
if (value === void 0 || value === null) return;
|
|
103
|
+
pairs.push(serializePrimitiveParam(name, value));
|
|
104
|
+
};
|
|
105
|
+
for (const name in cookieParams) {
|
|
106
|
+
const value = cookieParams[name];
|
|
107
|
+
if (Array.isArray(value)) for (const v of value) push(name, v);
|
|
108
|
+
else if (value !== null && typeof value === "object") for (const [k, v] of Object.entries(value)) push(k, v);
|
|
109
|
+
else push(name, value);
|
|
110
|
+
}
|
|
111
|
+
return pairs.join("; ");
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/serializers/path.ts
|
|
115
|
+
const PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
116
|
+
/**
|
|
117
|
+
* Handle different OpenAPI 3.x serialization styles
|
|
118
|
+
* @see https://swagger.io/docs/specification/serialization/#path
|
|
119
|
+
*/
|
|
120
|
+
function defaultPathSerializer(pathname, pathParams) {
|
|
121
|
+
let nextURL = pathname;
|
|
122
|
+
for (const match of pathname.match(PATH_PARAM_RE) ?? []) {
|
|
123
|
+
let name = match.substring(1, match.length - 1);
|
|
124
|
+
let explode = false;
|
|
125
|
+
let style = "simple";
|
|
126
|
+
if (name.endsWith("*")) {
|
|
127
|
+
explode = true;
|
|
128
|
+
name = name.substring(0, name.length - 1);
|
|
129
|
+
}
|
|
130
|
+
if (name.startsWith(".")) {
|
|
131
|
+
style = "label";
|
|
132
|
+
name = name.substring(1);
|
|
133
|
+
} else if (name.startsWith(";")) {
|
|
134
|
+
style = "matrix";
|
|
135
|
+
name = name.substring(1);
|
|
136
|
+
}
|
|
137
|
+
if (!pathParams || pathParams[name] === void 0 || pathParams[name] === null) continue;
|
|
138
|
+
const value = pathParams[name];
|
|
139
|
+
if (Array.isArray(value)) {
|
|
140
|
+
nextURL = nextURL.replace(match, serializeArrayParam(name, value, {
|
|
141
|
+
style,
|
|
142
|
+
explode
|
|
143
|
+
}));
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (typeof value === "object") {
|
|
147
|
+
nextURL = nextURL.replace(match, serializeObjectParam(name, value, {
|
|
148
|
+
style,
|
|
149
|
+
explode
|
|
150
|
+
}));
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (style === "matrix") {
|
|
154
|
+
nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
nextURL = nextURL.replace(match, style === "label" ? `.${encodeURIComponent(value)}` : encodeURIComponent(value));
|
|
158
|
+
}
|
|
159
|
+
return nextURL;
|
|
160
|
+
}
|
|
161
|
+
//#endregion
|
|
162
|
+
//#region src/serializers/query.ts
|
|
163
|
+
/** Serialize query params to string */
|
|
164
|
+
function createQuerySerializer(options) {
|
|
165
|
+
return function querySerializer(queryParams) {
|
|
166
|
+
const search = [];
|
|
167
|
+
if (queryParams && typeof queryParams === "object") for (const name in queryParams) {
|
|
168
|
+
const value = queryParams[name];
|
|
169
|
+
if (value === void 0 || value === null) continue;
|
|
170
|
+
if (Array.isArray(value)) {
|
|
171
|
+
if (value.length === 0) continue;
|
|
172
|
+
search.push(serializeArrayParam(name, value, {
|
|
173
|
+
style: "form",
|
|
174
|
+
explode: true,
|
|
175
|
+
...options?.array,
|
|
176
|
+
allowReserved: options?.allowReserved || false
|
|
177
|
+
}));
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (typeof value === "object") {
|
|
181
|
+
search.push(serializeObjectParam(name, value, {
|
|
182
|
+
style: "deepObject",
|
|
183
|
+
explode: true,
|
|
184
|
+
...options?.object,
|
|
185
|
+
allowReserved: options?.allowReserved || false
|
|
186
|
+
}));
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
search.push(serializePrimitiveParam(name, value, options));
|
|
190
|
+
}
|
|
191
|
+
return search.join("&");
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
//#endregion
|
|
195
|
+
//#region src/serializers/url.ts
|
|
196
|
+
/** Construct URL string from baseUrl and handle path and query params */
|
|
197
|
+
function createFinalURL(pathname, options) {
|
|
198
|
+
let finalURL = `${options.baseUrl}${pathname}`;
|
|
199
|
+
if (options.params?.path) finalURL = options.pathSerializer(finalURL, options.params.path);
|
|
200
|
+
let search = options.querySerializer(options.params.query ?? {});
|
|
201
|
+
if (search.startsWith("?")) search = search.substring(1);
|
|
202
|
+
if (search) finalURL += `?${search}`;
|
|
203
|
+
return finalURL;
|
|
204
|
+
}
|
|
205
|
+
/** Remove trailing slash from url */
|
|
206
|
+
function removeTrailingSlash(url) {
|
|
207
|
+
if (url.endsWith("/")) return url.substring(0, url.length - 1);
|
|
208
|
+
return url;
|
|
209
|
+
}
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region src/client.ts
|
|
212
|
+
function supportsRequestInitExt() {
|
|
213
|
+
const nodeProcess = globalThis.process;
|
|
214
|
+
return typeof nodeProcess === "object" && Number.parseInt(nodeProcess?.versions?.node?.substring(0, 2) ?? "") >= 18 && nodeProcess?.versions?.undici;
|
|
215
|
+
}
|
|
216
|
+
/** Returns a cheap, non-cryptographically-secure random ID. */
|
|
217
|
+
function randomID() {
|
|
218
|
+
return Math.random().toString(36).slice(2, 11);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Create an openapi-fetch client.
|
|
222
|
+
*/
|
|
223
|
+
function createClient(clientOptions) {
|
|
224
|
+
let { baseUrl = "", Request: CustomRequest = globalThis.Request, fetch: baseFetch = globalThis.fetch, querySerializer: globalQuerySerializer, bodySerializer: globalBodySerializer, pathSerializer: globalPathSerializer, headers: baseHeaders, requestInitExt, ...baseOptions } = { ...clientOptions };
|
|
225
|
+
requestInitExt = supportsRequestInitExt() ? requestInitExt : void 0;
|
|
226
|
+
baseUrl = removeTrailingSlash(baseUrl);
|
|
227
|
+
const globalMiddlewares = [];
|
|
228
|
+
/**
|
|
229
|
+
* Per-request fetch (keeps settings created in createClient()
|
|
230
|
+
*/
|
|
231
|
+
async function coreFetch(schemaPath, fetchOptions) {
|
|
232
|
+
const { baseUrl: localBaseUrl, fetch = baseFetch, Request = CustomRequest, headers, params = {}, parseAs = "json", querySerializer: requestQuerySerializer, bodySerializer = globalBodySerializer ?? defaultBodySerializer, pathSerializer: requestPathSerializer, body, middleware: requestMiddlewares = [], ...init } = fetchOptions || {};
|
|
233
|
+
let finalBaseUrl = baseUrl;
|
|
234
|
+
if (localBaseUrl) finalBaseUrl = removeTrailingSlash(localBaseUrl) ?? baseUrl;
|
|
235
|
+
let querySerializer = typeof globalQuerySerializer === "function" ? globalQuerySerializer : createQuerySerializer(globalQuerySerializer);
|
|
236
|
+
if (requestQuerySerializer) querySerializer = typeof requestQuerySerializer === "function" ? requestQuerySerializer : createQuerySerializer({
|
|
237
|
+
...typeof globalQuerySerializer === "object" ? globalQuerySerializer : {},
|
|
238
|
+
...requestQuerySerializer
|
|
239
|
+
});
|
|
240
|
+
const pathSerializer = requestPathSerializer || globalPathSerializer || defaultPathSerializer;
|
|
241
|
+
const serializedBody = body === void 0 ? void 0 : bodySerializer(body, mergeHeaders(baseHeaders, headers, params.header));
|
|
242
|
+
const finalHeaders = mergeHeaders(serializedBody === void 0 || serializedBody instanceof FormData ? {} : { "Content-Type": "application/json" }, baseHeaders, headers, params.header);
|
|
243
|
+
const serializedCookies = serializeCookieParams(params.cookie);
|
|
244
|
+
if (serializedCookies) {
|
|
245
|
+
const existingCookie = finalHeaders.get("Cookie");
|
|
246
|
+
finalHeaders.set("Cookie", existingCookie ? `${existingCookie}; ${serializedCookies}` : serializedCookies);
|
|
247
|
+
}
|
|
248
|
+
const finalMiddlewares = [...globalMiddlewares, ...requestMiddlewares];
|
|
249
|
+
const requestInit = {
|
|
250
|
+
redirect: "follow",
|
|
251
|
+
...baseOptions,
|
|
252
|
+
...init,
|
|
253
|
+
body: serializedBody,
|
|
254
|
+
headers: finalHeaders
|
|
255
|
+
};
|
|
256
|
+
let id;
|
|
257
|
+
let options;
|
|
258
|
+
let request = new Request(createFinalURL(schemaPath, {
|
|
259
|
+
baseUrl: finalBaseUrl,
|
|
260
|
+
params,
|
|
261
|
+
querySerializer,
|
|
262
|
+
pathSerializer
|
|
263
|
+
}), requestInit);
|
|
264
|
+
let response;
|
|
265
|
+
/** Add custom parameters to Request object */
|
|
266
|
+
for (const key in init) if (!(key in request)) request[key] = init[key];
|
|
267
|
+
if (finalMiddlewares.length) {
|
|
268
|
+
id = randomID();
|
|
269
|
+
options = Object.freeze({
|
|
270
|
+
baseUrl: finalBaseUrl,
|
|
271
|
+
fetch,
|
|
272
|
+
parseAs,
|
|
273
|
+
querySerializer,
|
|
274
|
+
bodySerializer,
|
|
275
|
+
pathSerializer
|
|
276
|
+
});
|
|
277
|
+
for (const m of finalMiddlewares) if (m && typeof m === "object" && typeof m.onRequest === "function") {
|
|
278
|
+
const result = await m.onRequest({
|
|
279
|
+
request,
|
|
280
|
+
schemaPath,
|
|
281
|
+
params,
|
|
282
|
+
options,
|
|
283
|
+
id
|
|
284
|
+
});
|
|
285
|
+
if (result) {
|
|
286
|
+
if (result instanceof Request) request = result;
|
|
287
|
+
else if (result instanceof Response) {
|
|
288
|
+
response = result;
|
|
289
|
+
break;
|
|
290
|
+
} else throw new Error("onRequest: must return new Request() or Response() when modifying the request");
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (!response) {
|
|
295
|
+
try {
|
|
296
|
+
response = await fetch(request, requestInitExt);
|
|
297
|
+
} catch (error) {
|
|
298
|
+
let errorAfterMiddleware = error;
|
|
299
|
+
if (finalMiddlewares.length) for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
|
|
300
|
+
const m = finalMiddlewares[i];
|
|
301
|
+
if (m && typeof m === "object" && typeof m.onError === "function") {
|
|
302
|
+
const result = await m.onError({
|
|
303
|
+
request,
|
|
304
|
+
error: errorAfterMiddleware,
|
|
305
|
+
schemaPath,
|
|
306
|
+
params,
|
|
307
|
+
options,
|
|
308
|
+
id
|
|
309
|
+
});
|
|
310
|
+
if (result) {
|
|
311
|
+
if (result instanceof Response) {
|
|
312
|
+
response = result;
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
if (result instanceof Error) {
|
|
316
|
+
errorAfterMiddleware = result;
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
throw new Error("onError: must return new Response() or instance of Error");
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (!response) throw errorAfterMiddleware;
|
|
324
|
+
}
|
|
325
|
+
if (finalMiddlewares.length) for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
|
|
326
|
+
const m = finalMiddlewares[i];
|
|
327
|
+
if (m && typeof m === "object" && typeof m.onResponse === "function") {
|
|
328
|
+
const result = await m.onResponse({
|
|
329
|
+
request,
|
|
330
|
+
response,
|
|
331
|
+
schemaPath,
|
|
332
|
+
params,
|
|
333
|
+
options,
|
|
334
|
+
id
|
|
335
|
+
});
|
|
336
|
+
if (result) {
|
|
337
|
+
if (!(result instanceof Response)) throw new Error("onResponse: must return new Response() when modifying the response");
|
|
338
|
+
response = result;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
const finalResponse = response;
|
|
344
|
+
const contentLength = finalResponse.headers.get("Content-Length");
|
|
345
|
+
if (finalResponse.status === 204 || request.method === "HEAD" || contentLength === "0" && !finalResponse.headers.get("Transfer-Encoding")?.includes("chunked")) return finalResponse.ok ? {
|
|
346
|
+
data: void 0,
|
|
347
|
+
response: finalResponse
|
|
348
|
+
} : {
|
|
349
|
+
error: void 0,
|
|
350
|
+
response: finalResponse
|
|
351
|
+
};
|
|
352
|
+
if (finalResponse.ok) {
|
|
353
|
+
const getResponseData = async () => {
|
|
354
|
+
if (parseAs === "stream") return finalResponse.body;
|
|
355
|
+
if (parseAs === "json" && !contentLength) {
|
|
356
|
+
const raw = await finalResponse.text();
|
|
357
|
+
return raw ? JSON.parse(raw) : void 0;
|
|
358
|
+
}
|
|
359
|
+
return await finalResponse[parseAs]();
|
|
360
|
+
};
|
|
361
|
+
return {
|
|
362
|
+
data: await getResponseData(),
|
|
363
|
+
response: finalResponse
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
const raw = await finalResponse.text();
|
|
367
|
+
if (!raw) return {
|
|
368
|
+
error: void 0,
|
|
369
|
+
response: finalResponse
|
|
370
|
+
};
|
|
371
|
+
let error = raw;
|
|
372
|
+
try {
|
|
373
|
+
error = JSON.parse(raw);
|
|
374
|
+
} catch {}
|
|
375
|
+
return {
|
|
376
|
+
error,
|
|
377
|
+
response: finalResponse
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
request(method, url, init) {
|
|
382
|
+
return coreFetch(url, {
|
|
383
|
+
...init,
|
|
384
|
+
method: method.toUpperCase()
|
|
385
|
+
});
|
|
386
|
+
},
|
|
387
|
+
/** Call a GET endpoint */
|
|
388
|
+
GET(url, init) {
|
|
389
|
+
return coreFetch(url, {
|
|
390
|
+
...init,
|
|
391
|
+
method: "GET"
|
|
392
|
+
});
|
|
393
|
+
},
|
|
394
|
+
/** Call a PUT endpoint */
|
|
395
|
+
PUT(url, init) {
|
|
396
|
+
return coreFetch(url, {
|
|
397
|
+
...init,
|
|
398
|
+
method: "PUT"
|
|
399
|
+
});
|
|
400
|
+
},
|
|
401
|
+
/** Call a POST endpoint */
|
|
402
|
+
POST(url, init) {
|
|
403
|
+
return coreFetch(url, {
|
|
404
|
+
...init,
|
|
405
|
+
method: "POST"
|
|
406
|
+
});
|
|
407
|
+
},
|
|
408
|
+
/** Call a DELETE endpoint */
|
|
409
|
+
DELETE(url, init) {
|
|
410
|
+
return coreFetch(url, {
|
|
411
|
+
...init,
|
|
412
|
+
method: "DELETE"
|
|
413
|
+
});
|
|
414
|
+
},
|
|
415
|
+
/** Call a OPTIONS endpoint */
|
|
416
|
+
OPTIONS(url, init) {
|
|
417
|
+
return coreFetch(url, {
|
|
418
|
+
...init,
|
|
419
|
+
method: "OPTIONS"
|
|
420
|
+
});
|
|
421
|
+
},
|
|
422
|
+
/** Call a HEAD endpoint */
|
|
423
|
+
HEAD(url, init) {
|
|
424
|
+
return coreFetch(url, {
|
|
425
|
+
...init,
|
|
426
|
+
method: "HEAD"
|
|
427
|
+
});
|
|
428
|
+
},
|
|
429
|
+
/** Call a PATCH endpoint */
|
|
430
|
+
PATCH(url, init) {
|
|
431
|
+
return coreFetch(url, {
|
|
432
|
+
...init,
|
|
433
|
+
method: "PATCH"
|
|
434
|
+
});
|
|
435
|
+
},
|
|
436
|
+
/** Call a TRACE endpoint */
|
|
437
|
+
TRACE(url, init) {
|
|
438
|
+
return coreFetch(url, {
|
|
439
|
+
...init,
|
|
440
|
+
method: "TRACE"
|
|
441
|
+
});
|
|
442
|
+
},
|
|
443
|
+
/** Register middleware */
|
|
444
|
+
use(...middleware) {
|
|
445
|
+
for (const m of middleware) {
|
|
446
|
+
if (!m) continue;
|
|
447
|
+
if (typeof m !== "object" || !("onRequest" in m || "onResponse" in m || "onError" in m)) throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");
|
|
448
|
+
globalMiddlewares.push(m);
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
/** Unregister middleware */
|
|
452
|
+
eject(...middleware) {
|
|
453
|
+
for (const m of middleware) {
|
|
454
|
+
const i = globalMiddlewares.indexOf(m);
|
|
455
|
+
if (i !== -1) globalMiddlewares.splice(i, 1);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
//#endregion
|
|
461
|
+
//#region src/path-client.ts
|
|
462
|
+
var PathCallForwarder = class {
|
|
463
|
+
client;
|
|
464
|
+
url;
|
|
465
|
+
constructor(client, url) {
|
|
466
|
+
this.client = client;
|
|
467
|
+
this.url = url;
|
|
468
|
+
}
|
|
469
|
+
GET = (init) => {
|
|
470
|
+
return this.client.GET(this.url, init);
|
|
471
|
+
};
|
|
472
|
+
PUT = (init) => {
|
|
473
|
+
return this.client.PUT(this.url, init);
|
|
474
|
+
};
|
|
475
|
+
POST = (init) => {
|
|
476
|
+
return this.client.POST(this.url, init);
|
|
477
|
+
};
|
|
478
|
+
DELETE = (init) => {
|
|
479
|
+
return this.client.DELETE(this.url, init);
|
|
480
|
+
};
|
|
481
|
+
OPTIONS = (init) => {
|
|
482
|
+
return this.client.OPTIONS(this.url, init);
|
|
483
|
+
};
|
|
484
|
+
HEAD = (init) => {
|
|
485
|
+
return this.client.HEAD(this.url, init);
|
|
486
|
+
};
|
|
487
|
+
PATCH = (init) => {
|
|
488
|
+
return this.client.PATCH(this.url, init);
|
|
489
|
+
};
|
|
490
|
+
TRACE = (init) => {
|
|
491
|
+
return this.client.TRACE(this.url, init);
|
|
492
|
+
};
|
|
493
|
+
};
|
|
494
|
+
var PathClientProxyHandler = class {
|
|
495
|
+
client = null;
|
|
496
|
+
get(coreClient, url) {
|
|
497
|
+
const forwarder = new PathCallForwarder(coreClient, url);
|
|
498
|
+
this.client[url] = forwarder;
|
|
499
|
+
return forwarder;
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
/**
|
|
503
|
+
* Wrap openapi-fetch client to support a path based API.
|
|
504
|
+
*/
|
|
505
|
+
function wrapAsPathBasedClient(coreClient) {
|
|
506
|
+
const handler = new PathClientProxyHandler();
|
|
507
|
+
const proxy = new Proxy(coreClient, handler);
|
|
508
|
+
function ClientCtor() {}
|
|
509
|
+
ClientCtor.prototype = proxy;
|
|
510
|
+
const client = new ClientCtor();
|
|
511
|
+
handler.client = client;
|
|
512
|
+
return client;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Convenience method to an openapi-fetch path based client.
|
|
516
|
+
* Strictly equivalent to `wrapAsPathBasedClient(createClient(...))`.
|
|
517
|
+
*/
|
|
518
|
+
function createPathBasedClient(clientOptions) {
|
|
519
|
+
return wrapAsPathBasedClient(createClient(clientOptions));
|
|
520
|
+
}
|
|
521
|
+
//#endregion
|
|
522
|
+
export { createClient, createClient as default, createFinalURL, createPathBasedClient, createQuerySerializer, defaultBodySerializer, defaultPathSerializer, mergeHeaders, removeTrailingSlash, serializeArrayParam, serializeObjectParam, serializePrimitiveParam, wrapAsPathBasedClient };
|
package/package.json
CHANGED
|
@@ -1,6 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shipworthy/openapi-fetch",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"files": [
|
|
5
|
+
"dist"
|
|
6
|
+
],
|
|
7
|
+
"description": "Fast, type-safe fetch client for your OpenAPI schema. Only 6 kb (min). Works with React, Vue, Svelte, or vanilla JS.",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"api",
|
|
10
|
+
"fetch",
|
|
11
|
+
"oapi_3",
|
|
12
|
+
"oapi_3_1",
|
|
13
|
+
"openapi",
|
|
14
|
+
"react",
|
|
15
|
+
"rest",
|
|
16
|
+
"svelte",
|
|
17
|
+
"swagger",
|
|
18
|
+
"typescript",
|
|
19
|
+
"vue"
|
|
20
|
+
],
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/ShipWorthyAI/openapi.git",
|
|
25
|
+
"directory": "packages/openapi-fetch"
|
|
26
|
+
},
|
|
27
|
+
"type": "module",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"import": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
},
|
|
34
|
+
"require": {
|
|
35
|
+
"types": "./dist/index.d.cts",
|
|
36
|
+
"default": "./dist/index.cjs"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"./package.json": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "rm -rf dist && tsdown",
|
|
43
|
+
"test": "vitest run"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"tsdown": "0.23.0",
|
|
47
|
+
"typescript": "^7.0.2",
|
|
48
|
+
"vitest": "5.0.3"
|
|
49
|
+
},
|
|
50
|
+
"main": "./dist/index.cjs",
|
|
51
|
+
"module": "./dist/index.js",
|
|
52
|
+
"types": "./dist/index.d.cts",
|
|
53
|
+
"react-native": "./dist/index.js",
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
}
|
|
57
|
+
}
|