@unshared/client 0.3.2 → 0.4.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/chunks/{mHfUAX_g.d.ts → 5p4H9ZaI.d.ts} +11 -5
- package/dist/chunks/{0ZzUT3m_.js → B6pUErTM.js} +2 -2
- package/dist/chunks/B6pUErTM.js.map +1 -0
- package/dist/chunks/{CYmaYL5B.cjs → BDxlAULu.cjs} +2 -2
- package/dist/chunks/BDxlAULu.cjs.map +1 -0
- package/dist/chunks/{Biic1J5b.js → B_Gz6Yz8.js} +23 -1
- package/dist/chunks/B_Gz6Yz8.js.map +1 -0
- package/dist/chunks/{BMbsYNBd.cjs → BdFNzMcu.cjs} +2 -2
- package/dist/chunks/{BMbsYNBd.cjs.map → BdFNzMcu.cjs.map} +1 -1
- package/dist/chunks/{6IxvRpmY.js → Bys4-xE2.js} +2 -2
- package/dist/chunks/{6IxvRpmY.js.map → Bys4-xE2.js.map} +1 -1
- package/dist/chunks/CS5r-m4U.js +191 -0
- package/dist/chunks/CS5r-m4U.js.map +1 -0
- package/dist/chunks/CVzmr2NA.cjs +189 -0
- package/dist/chunks/CVzmr2NA.cjs.map +1 -0
- package/dist/chunks/D1QsGr3A.js +15 -0
- package/dist/chunks/D1QsGr3A.js.map +1 -0
- package/dist/chunks/{CtW2aMuA.cjs → DEyigyGy.cjs} +23 -1
- package/dist/chunks/DEyigyGy.cjs.map +1 -0
- package/dist/chunks/DXrQkl1A.cjs +14 -0
- package/dist/chunks/DXrQkl1A.cjs.map +1 -0
- package/dist/chunks/{CO11DuYE.d.ts → Nc32BOzg.d.ts} +23 -3
- package/dist/createClient.cjs +4 -58
- package/dist/createClient.cjs.map +1 -1
- package/dist/createClient.d.ts +13 -7
- package/dist/createClient.js +4 -59
- package/dist/createClient.js.map +1 -1
- package/dist/createService.cjs +3 -3
- package/dist/createService.cjs.map +1 -1
- package/dist/createService.d.ts +2 -2
- package/dist/createService.js +4 -4
- package/dist/createService.js.map +1 -1
- package/dist/index.cjs +5 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -5
- package/dist/openapi.cjs +13 -3
- package/dist/openapi.cjs.map +1 -1
- package/dist/openapi.d.ts +45 -4
- package/dist/openapi.js +11 -1
- package/dist/openapi.js.map +1 -1
- package/dist/utils.cjs +15 -3
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.ts +114 -8
- package/dist/utils.js +21 -8
- package/dist/utils.js.map +1 -1
- package/dist/websocket.cjs +2 -2
- package/dist/websocket.js +2 -2
- package/package.json +4 -4
- package/dist/chunks/0ZzUT3m_.js.map +0 -1
- package/dist/chunks/BUeqbyph.js +0 -114
- package/dist/chunks/BUeqbyph.js.map +0 -1
- package/dist/chunks/Biic1J5b.js.map +0 -1
- package/dist/chunks/CYmaYL5B.cjs.map +0 -1
- package/dist/chunks/Cayg8606.cjs +0 -112
- package/dist/chunks/Cayg8606.cjs.map +0 -1
- package/dist/chunks/CtW2aMuA.cjs.map +0 -1
- package/dist/chunks/DJJsADWD.js +0 -9
- package/dist/chunks/DJJsADWD.js.map +0 -1
- package/dist/chunks/Du_W5H6e.cjs +0 -8
- package/dist/chunks/Du_W5H6e.cjs.map +0 -1
package/dist/utils.cjs
CHANGED
@@ -1,18 +1,30 @@
|
|
1
1
|
"use strict";
|
2
|
-
var
|
2
|
+
var request = require("./chunks/DXrQkl1A.cjs"), handleResponse = require("./chunks/CVzmr2NA.cjs"), parseRequestQuery = require("./chunks/BDxlAULu.cjs");
|
3
3
|
require("@unshared/functions/awaitable");
|
4
|
-
|
4
|
+
function getCookie(headers, key) {
|
5
|
+
const cookie = handleResponse.getCookies(headers);
|
6
|
+
if (cookie)
|
7
|
+
return cookie[key];
|
8
|
+
}
|
9
|
+
exports.fetch = request.fetch;
|
10
|
+
exports.request = request.request;
|
11
|
+
exports.getCookies = handleResponse.getCookies;
|
12
|
+
exports.getHeader = handleResponse.getHeader;
|
5
13
|
exports.handleResponse = handleResponse.handleResponse;
|
6
14
|
exports.handleResponseStreamJson = handleResponse.handleResponseStreamJson;
|
7
15
|
exports.isFormDataLike = handleResponse.isFormDataLike;
|
8
16
|
exports.isObjectLike = handleResponse.isObjectLike;
|
9
17
|
exports.parseRequest = handleResponse.parseRequest;
|
18
|
+
exports.parseRequestBasicAuth = handleResponse.parseRequestBasicAuth;
|
10
19
|
exports.parseRequestBody = handleResponse.parseRequestBody;
|
11
20
|
exports.parseRequestHeaders = handleResponse.parseRequestHeaders;
|
21
|
+
exports.parseRequestToken = handleResponse.parseRequestToken;
|
12
22
|
exports.parseRequestUrl = handleResponse.parseRequestUrl;
|
23
|
+
exports.setCookie = handleResponse.setCookie;
|
24
|
+
exports.setHeader = handleResponse.setHeader;
|
13
25
|
exports.toFormData = handleResponse.toFormData;
|
14
26
|
exports.parseRequestParameters = parseRequestQuery.parseRequestParameters;
|
15
27
|
exports.parseRequestQuery = parseRequestQuery.parseRequestQuery;
|
16
28
|
exports.toSearchParams = parseRequestQuery.toSearchParams;
|
17
|
-
exports.
|
29
|
+
exports.getCookie = getCookie;
|
18
30
|
//# sourceMappingURL=utils.cjs.map
|
package/dist/utils.cjs.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"utils.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"utils.cjs","sources":["../utils/getCookie.ts"],"sourcesContent":["import { getCookies } from './getCookies'\n\n/**\n * Get a cookie value from the `HeadersInit` object.\n *\n * @param headers The headers to get the cookie value from.\n * @param key The key of the cookie to get.\n * @returns The value of the cookie.\n * @example\n * const headers = new Headers({ Cookie: 'key1=value1; key2=value2' })\n * const value = getCookie(headers, 'key1')\n */\nexport function getCookie(headers: HeadersInit, key: string): string | undefined {\n const cookie = getCookies(headers)\n if (!cookie) return\n return cookie[key]\n}\n"],"names":["getCookies"],"mappings":";;;AAYgB,SAAA,UAAU,SAAsB,KAAiC;AACzE,QAAA,SAASA,0BAAW,OAAO;AAC5B,MAAA;AACL,WAAO,OAAO,GAAG;AACnB;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/utils.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import {
|
2
|
-
export { c as FetchHeaders,
|
1
|
+
import { F as FetchOptions, R as RequestOptions, b as RequestContext } from './chunks/Nc32BOzg.js';
|
2
|
+
export { c as FetchHeaders, a as FetchMethod, d as SearchArrayFormat, S as SearchParamsObject, T as ToSearchParamsOptions, p as parseRequest, r as request, t as toSearchParams } from './chunks/Nc32BOzg.js';
|
3
3
|
import { Awaitable } from '@unshared/functions/awaitable';
|
4
4
|
import { ObjectLike } from '@unshared/types';
|
5
5
|
import './HttpHeaders.js';
|
@@ -16,6 +16,42 @@ import './HttpMethods.js';
|
|
16
16
|
*/
|
17
17
|
declare function fetch(route: string, options?: FetchOptions): Promise<Response>;
|
18
18
|
|
19
|
+
/**
|
20
|
+
* Get a cookie value from the `HeadersInit` object.
|
21
|
+
*
|
22
|
+
* @param headers The headers to get the cookie value from.
|
23
|
+
* @param key The key of the cookie to get.
|
24
|
+
* @returns The value of the cookie.
|
25
|
+
* @example
|
26
|
+
* const headers = new Headers({ Cookie: 'key1=value1; key2=value2' })
|
27
|
+
* const value = getCookie(headers, 'key1')
|
28
|
+
*/
|
29
|
+
declare function getCookie(headers: HeadersInit, key: string): string | undefined;
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Extract the cookies from the `HeadersInit` object.
|
33
|
+
*
|
34
|
+
* @param headers The headers to extract the cookies from.
|
35
|
+
* @returns An array of cookies.
|
36
|
+
* @example
|
37
|
+
* const headers = new Headers({ Cookie: 'key1=value1; key2=value2' })
|
38
|
+
* const cookies = getCookies(headers) // { key1: 'value1', key2: 'value2' }
|
39
|
+
*/
|
40
|
+
declare function getCookies(headers: HeadersInit): Record<string, string>;
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Get a header value from the `HeadersInit` object.
|
44
|
+
*
|
45
|
+
* @param headers The headers to get the key-value pair from.
|
46
|
+
* @param key The key of the header to get.
|
47
|
+
* @returns The value of the header.
|
48
|
+
* @example
|
49
|
+
* const headers = new Headers({ 'Content-Type': 'application/json' })
|
50
|
+
* const contentType = getHeader(headers, 'Content-Type')
|
51
|
+
* console.log(contentType) // 'application/json'
|
52
|
+
*/
|
53
|
+
declare function getHeader(headers: HeadersInit, key: string): string | undefined;
|
54
|
+
|
19
55
|
/**
|
20
56
|
* Handle a request response. This function will parse the response based on the content type and
|
21
57
|
* return the data. If an error occurs, the `onError` callback will be called and the function will
|
@@ -62,13 +98,29 @@ declare function isFormDataLike(value: unknown): value is FormDataLike;
|
|
62
98
|
*/
|
63
99
|
declare function isObjectLike(value: unknown): value is ObjectLike;
|
64
100
|
|
101
|
+
/**
|
102
|
+
* Parse the basic authentication headers based on the provided username and password.
|
103
|
+
*
|
104
|
+
* @param context The request context.
|
105
|
+
* @param options The request options.
|
106
|
+
* @example
|
107
|
+
*
|
108
|
+
* // Append the `Authorization` header to the request.
|
109
|
+
* const context = {}
|
110
|
+
* parseRequestBasicAuth(context, { username: 'user', password: 'pass' })
|
111
|
+
*
|
112
|
+
* // Will mutate the `init` object to include the headers.
|
113
|
+
* console.log(context) // => { init: { headers: { 'Authorization': 'Basic dXNlcjpwYXNz' } } }
|
114
|
+
*/
|
115
|
+
declare function parseRequestBasicAuth(context: Partial<RequestContext>, options: FetchOptions): void;
|
116
|
+
|
65
117
|
/**
|
66
118
|
* Parse the request body based on the provided data and options.
|
67
119
|
*
|
68
120
|
* @param context The request context.
|
69
121
|
* @param options The request options.
|
70
122
|
*/
|
71
|
-
declare function parseRequestBody(context: RequestContext
|
123
|
+
declare function parseRequestBody(context: Partial<RequestContext>, options: FetchOptions): void;
|
72
124
|
|
73
125
|
/**
|
74
126
|
* Parse the request headers based on the provided data and options.
|
@@ -84,7 +136,7 @@ declare function parseRequestBody(context: RequestContext, options: FetchOptions
|
|
84
136
|
* // Will mutate the `init` object to include the headers.
|
85
137
|
* console.log(context) // => { init: { headers: { 'Content-Type': 'application/json' } } }
|
86
138
|
*/
|
87
|
-
declare function parseRequestHeaders(context: RequestContext
|
139
|
+
declare function parseRequestHeaders(context: Partial<RequestContext>, options: FetchOptions): void;
|
88
140
|
|
89
141
|
/**
|
90
142
|
* Parse the request parameters from the request data. This function will mutate the
|
@@ -104,7 +156,7 @@ declare function parseRequestHeaders(context: RequestContext, options: FetchOpti
|
|
104
156
|
* parseRequestParameters(context, { parameters: { id: 1 } })
|
105
157
|
* console.log(context.url.pathname) // 'https://api.example.com/users/1'
|
106
158
|
*/
|
107
|
-
declare function parseRequestParameters(context: RequestContext
|
159
|
+
declare function parseRequestParameters(context: Partial<RequestContext>, options: FetchOptions): void;
|
108
160
|
|
109
161
|
/**
|
110
162
|
* Parse the query parameters from the request data. This function will append
|
@@ -113,7 +165,32 @@ declare function parseRequestParameters(context: RequestContext, options: FetchO
|
|
113
165
|
* @param context The request context to modify.
|
114
166
|
* @param options The options to pass to the request.
|
115
167
|
*/
|
116
|
-
declare function parseRequestQuery(context: RequestContext
|
168
|
+
declare function parseRequestQuery(context: Partial<RequestContext>, options: FetchOptions): void;
|
169
|
+
|
170
|
+
/**
|
171
|
+
* Parse the token and dynamically extend either the query, headers, or cookies.
|
172
|
+
*
|
173
|
+
* @param context The request context.
|
174
|
+
* @param options The request options.
|
175
|
+
* @example
|
176
|
+
* // Append the `token` to the query parameters.
|
177
|
+
* const context = { url: new URL('https://example.com') }
|
178
|
+
* parseRequestToken(context, { token: 'my-token', tokenLocation: 'query', tokenProperty: 'token' })
|
179
|
+
* console.log(context.url.searchParams.get('token')) // 'my-token'
|
180
|
+
*
|
181
|
+
* @example
|
182
|
+
* // Append the `token` to the headers.
|
183
|
+
* const context = { init: { headers: new Headers() } }
|
184
|
+
* parseRequestToken(context, { token: 'my-token', tokenLocation: 'header', tokenProperty: 'Authorization' })
|
185
|
+
* console.log(context.init.headers.get('Authorization')) // 'Bearer my-token'
|
186
|
+
*
|
187
|
+
* @example
|
188
|
+
* // Append the `token` to the cookies.
|
189
|
+
* const context = { init: { headers: new Headers() } }
|
190
|
+
* parseRequestToken(context, { token: 'my-token', tokenLocation: 'cookie', tokenProperty: 'token' })
|
191
|
+
* console.log(context.init.headers.get('Cookie')) // 'token=my-token'
|
192
|
+
*/
|
193
|
+
declare function parseRequestToken(context: Partial<RequestContext>, options: FetchOptions): void;
|
117
194
|
|
118
195
|
/**
|
119
196
|
* Parses the route name to extract the URL and method. It allows the url and method to be
|
@@ -124,7 +201,36 @@ declare function parseRequestQuery(context: RequestContext, options: FetchOption
|
|
124
201
|
* @param options The options to pass to the request.
|
125
202
|
* @example parseRequestUrl('GET /users', { baseUrl: 'https://api.example.com' }, context)
|
126
203
|
*/
|
127
|
-
declare function parseRequestUrl(context: RequestContext
|
204
|
+
declare function parseRequestUrl(context: Partial<RequestContext>, route: string, options: FetchOptions): void;
|
205
|
+
|
206
|
+
/**
|
207
|
+
* Set a cookie in the `HeadersInit` object.
|
208
|
+
*
|
209
|
+
* @param headers The headers to set the cookie in.
|
210
|
+
* @param key The key of the cookie to set.
|
211
|
+
* @param value The value of the cookie to set.
|
212
|
+
* @example
|
213
|
+
* const headers = new Headers()
|
214
|
+
* const cookie = { key: 'key1', value: 'value1', path: '/', secure: true }
|
215
|
+
* setCookie(headers, cookie)
|
216
|
+
* console.log(headers.get('Cookie')) // 'key1=value1; Path=/; Secure'
|
217
|
+
*/
|
218
|
+
declare function setCookie(headers: HeadersInit, key: string, value: string): void;
|
219
|
+
|
220
|
+
/**
|
221
|
+
* Set a header in the `HeadersInit` object whether it is a `Headers` instance, an
|
222
|
+
* array of key-value pairs, or an object. It is also case-insensitive, meaning that
|
223
|
+
* if a header with the same key but different case is found, it will be replaced.
|
224
|
+
*
|
225
|
+
* @param headers The headers to set the key-value pair in.
|
226
|
+
* @param key The key of the header to set.
|
227
|
+
* @param value The value of the header to set.
|
228
|
+
* @example
|
229
|
+
* const headers = new Headers()
|
230
|
+
* setHeader(headers, 'Content-Type', 'application/json')
|
231
|
+
* console.log(headers.get('Content-Type')) // 'application/json'
|
232
|
+
*/
|
233
|
+
declare function setHeader(headers: HeadersInit, key: string, value: number | string): void;
|
128
234
|
|
129
235
|
/**
|
130
236
|
* Casts an object that may contain `Blob`, `File`, or `FileList` values to a `FormData` object.
|
@@ -134,4 +240,4 @@ declare function parseRequestUrl(context: RequestContext, route: string, options
|
|
134
240
|
*/
|
135
241
|
declare function toFormData(object: FormDataLike): FormData;
|
136
242
|
|
137
|
-
export { FetchOptions, type FormDataLike, RequestContext, RequestOptions, fetch, handleResponse, handleResponseStreamJson, isFormDataLike, isObjectLike, parseRequestBody, parseRequestHeaders, parseRequestParameters, parseRequestQuery, parseRequestUrl, toFormData };
|
243
|
+
export { FetchOptions, type FormDataLike, RequestContext, RequestOptions, fetch, getCookie, getCookies, getHeader, handleResponse, handleResponseStreamJson, isFormDataLike, isObjectLike, parseRequestBasicAuth, parseRequestBody, parseRequestHeaders, parseRequestParameters, parseRequestQuery, parseRequestToken, parseRequestUrl, setCookie, setHeader, toFormData };
|
package/dist/utils.js
CHANGED
@@ -1,20 +1,33 @@
|
|
1
|
-
import { f,
|
2
|
-
import {
|
3
|
-
import {
|
1
|
+
import { f, r } from "./chunks/D1QsGr3A.js";
|
2
|
+
import { g as getCookies } from "./chunks/CS5r-m4U.js";
|
3
|
+
import { a, h, b, i, c, p, d, e, f as f2, j, k, s, l, t } from "./chunks/CS5r-m4U.js";
|
4
|
+
import { p as p2, a as a2, t as t2 } from "./chunks/B6pUErTM.js";
|
4
5
|
import "@unshared/functions/awaitable";
|
6
|
+
function getCookie(headers, key) {
|
7
|
+
const cookie = getCookies(headers);
|
8
|
+
if (cookie)
|
9
|
+
return cookie[key];
|
10
|
+
}
|
5
11
|
export {
|
6
12
|
f as fetch,
|
13
|
+
getCookie,
|
14
|
+
getCookies,
|
15
|
+
a as getHeader,
|
7
16
|
h as handleResponse,
|
8
|
-
|
17
|
+
b as handleResponseStreamJson,
|
9
18
|
i as isFormDataLike,
|
10
|
-
|
19
|
+
c as isObjectLike,
|
11
20
|
p as parseRequest,
|
12
|
-
|
13
|
-
|
21
|
+
d as parseRequestBasicAuth,
|
22
|
+
e as parseRequestBody,
|
23
|
+
f2 as parseRequestHeaders,
|
14
24
|
p2 as parseRequestParameters,
|
15
25
|
a2 as parseRequestQuery,
|
16
|
-
|
26
|
+
j as parseRequestToken,
|
27
|
+
k as parseRequestUrl,
|
17
28
|
r as request,
|
29
|
+
s as setCookie,
|
30
|
+
l as setHeader,
|
18
31
|
t as toFormData,
|
19
32
|
t2 as toSearchParams
|
20
33
|
};
|
package/dist/utils.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"utils.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"utils.js","sources":["../utils/getCookie.ts"],"sourcesContent":["import { getCookies } from './getCookies'\n\n/**\n * Get a cookie value from the `HeadersInit` object.\n *\n * @param headers The headers to get the cookie value from.\n * @param key The key of the cookie to get.\n * @returns The value of the cookie.\n * @example\n * const headers = new Headers({ Cookie: 'key1=value1; key2=value2' })\n * const value = getCookie(headers, 'key1')\n */\nexport function getCookie(headers: HeadersInit, key: string): string | undefined {\n const cookie = getCookies(headers)\n if (!cookie) return\n return cookie[key]\n}\n"],"names":[],"mappings":";;;;;AAYgB,SAAA,UAAU,SAAsB,KAAiC;AACzE,QAAA,SAAS,WAAW,OAAO;AAC5B,MAAA;AACL,WAAO,OAAO,GAAG;AACnB;"}
|
package/dist/websocket.cjs
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
"use strict";
|
2
|
-
var connect = require("./chunks/
|
2
|
+
var connect = require("./chunks/BdFNzMcu.cjs");
|
3
3
|
require("@unshared/functions");
|
4
|
-
require("./chunks/
|
4
|
+
require("./chunks/BDxlAULu.cjs");
|
5
5
|
exports.WebSocketChannel = connect.WebSocketChannel;
|
6
6
|
exports.connect = connect.connect;
|
7
7
|
exports.parseConnectOptions = connect.parseConnectOptions;
|
package/dist/websocket.js
CHANGED
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@unshared/client",
|
3
3
|
"type": "module",
|
4
|
-
"version": "0.
|
4
|
+
"version": "0.4.0",
|
5
5
|
"license": "MIT",
|
6
6
|
"sideEffects": false,
|
7
7
|
"author": "Stanley Horwood <stanley@hsjm.io>",
|
@@ -68,12 +68,12 @@
|
|
68
68
|
"LICENSE.md"
|
69
69
|
],
|
70
70
|
"dependencies": {
|
71
|
-
"@unshared/functions": "0.
|
72
|
-
"@unshared/types": "0.
|
71
|
+
"@unshared/functions": "0.4.0",
|
72
|
+
"@unshared/types": "0.4.0",
|
73
73
|
"openapi-types": "12.1.3"
|
74
74
|
},
|
75
75
|
"devDependencies": {
|
76
|
-
"@unshared/scripts": "0.
|
76
|
+
"@unshared/scripts": "0.4.0"
|
77
77
|
},
|
78
78
|
"scripts": {
|
79
79
|
"build:httpMethods": "tsx ./scripts/buildHttpMethods.ts",
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"0ZzUT3m_.js","sources":["../../utils/parseRequestParameters.ts","../../utils/toSearchParams.ts","../../utils/parseRequestQuery.ts"],"sourcesContent":["import type { FetchOptions, RequestContext } from './parseRequest'\n\n/** Regular expression to match path parameters in the URL. */\nconst EXP_PATH_PARAMETER = /:([\\w-]+)|%7B([\\w-]+)%7D/g\n\n/**\n * Parse the request parameters from the request data. This function will mutate the\n * `url` object of the context to include the path parameters based on the provided data.\n *\n * @param context The request context to mutate.\n * @param options The options to pass to the request.\n * @example\n *\n * // Using `express` style path parameters.\n * const context = { url: new URL('https://api.example.com/users/:id') }\n * parseRequestParameters(context, { parameters: { id: 1 } })\n * console.log(context.url.pathname) // 'https://api.example.com/users/1'\n *\n * // Using `OpenAPI` style path parameters.\n * const context = { url: new URL('https://api.example.com/users/{id}') }\n * parseRequestParameters(context, { parameters: { id: 1 } })\n * console.log(context.url.pathname) // 'https://api.example.com/users/1'\n */\nexport function parseRequestParameters(context: RequestContext, options: FetchOptions): void {\n const { url } = context\n const { parameters } = options\n\n // --- Return early if the parameters is not an object.\n if (typeof parameters !== 'object' || parameters === null) return\n if (url === undefined) return\n if (url instanceof URL === false) throw new Error('The `url` must be an instance of `URL`.')\n\n // --- If the method has a parameter, fill the path with the data.\n const pathParameters = url.pathname.match(EXP_PATH_PARAMETER)\n if (!pathParameters) return\n\n // --- Apply the path parameters to the URL.\n for (const parameter of pathParameters.values()) {\n const key = parameter.replaceAll(EXP_PATH_PARAMETER, '$1$2')\n const value = parameters[key]\n\n // --- If the parameter is provided, replace the path with the value.\n if (\n (typeof value === 'string' && value.length > 0)\n || (typeof value === 'number' && Number.isFinite(value))\n || (typeof value === 'boolean')\n ) {\n url.pathname = url.pathname.replace(parameter, value.toString())\n delete parameters[key]\n }\n }\n}\n","/* eslint-disable unicorn/prevent-abbreviations */\nimport type { MaybeArray } from '@unshared/types'\n\n/** An object that can be converted to a query string. */\nexport type SearchParamsObject = Record<string, MaybeArray<boolean | number | string> | undefined>\n\n/** The search array format options. */\nexport type SearchArrayFormat = 'brackets' | 'comma' | 'flat' | 'indices' | 'path'\n\n/** Options for the query string conversion. */\nexport interface ToSearchParamsOptions {\n\n /**\n * Defines how to handle arrays in the object. There is no standard way to\n * represent arrays in query strings, so this option allows you to choose\n * how to handle them. Additionally, you can provide a custom function to\n * handle it yourself.\n *\n * - `brackets` (default): Convert arrays to `key[]=value&key[]=value` format.\n * - `indices`: Convert arrays to `key[0]=value&key[1]=value` format.\n * - `comma`: Convert arrays to `key=value1,value2` format.\n * - `path`: Convert arrays to `key.0=value&key.1=value` format.\n * - `flat`: Convert arrays to `key=value1&key=value2` format.\n *\n * @default 'flat'\n */\n format?: SearchArrayFormat\n}\n\n/**\n * Convert object to query string parameters. Converting all values to strings\n * and arrays to `key[0]=value&key[1]=value` format.\n *\n * @param object The object to convert to a query string.\n * @param options The query string options.\n * @returns The `URLSearchParams` object.\n */\nexport function toSearchParams(object: SearchParamsObject, options: ToSearchParamsOptions = {}): URLSearchParams {\n const { format = 'flat' } = options\n const search = new URLSearchParams()\n for (const key in object) {\n const value = object[key]\n if (value === undefined) continue\n\n // --- Convert arrays based on the format.\n if (Array.isArray(value)) {\n if (format === 'brackets') for (const v of value) search.append(`${key}[]`, String(v))\n else if (format === 'indices') for (const [i, v] of value.entries()) search.append(`${key}[${i}]`, String(v))\n else if (format === 'comma') search.append(key, value.join(','))\n else if (format === 'path') for (const [i, v] of value.entries()) search.append(`${key}.${i}`, String(v))\n else if (format === 'flat') for (const v of value) search.append(key, String(v))\n }\n\n // --- Convert all values to strings.\n else { search.append(key, value.toString()) }\n }\n\n // --- Return the query string.\n return search\n}\n","/* eslint-disable unicorn/prevent-abbreviations */\nimport type { FetchOptions, RequestContext } from './parseRequest'\nimport type { SearchParamsObject as SearchParametersObject } from './toSearchParams'\nimport { toSearchParams } from './toSearchParams'\n\n/**\n * Parse the query parameters from the request data. This function will append\n * the query parameters to the URL based on the method and the data provided.\n *\n * @param context The request context to modify.\n * @param options The options to pass to the request.\n */\nexport function parseRequestQuery(context: RequestContext, options: FetchOptions): void {\n const { url } = context\n const { query, queryArrayFormat } = options\n\n // --- Return early if the query is not an object or the URL is not provided.\n if (url === undefined) return\n if (url instanceof URL === false) throw new Error('The `url` must be an instance of `URL.')\n if (typeof query !== 'object' || query === null) return\n\n // --- Append the `data` to the query parameters if the method does not expect a body.\n const queryObject: SearchParametersObject = {}\n for (const key in query) {\n const value = query[key]\n if (\n (typeof value === 'string' && value.length > 0)\n || (typeof value === 'number' && Number.isFinite(value))\n || (typeof value === 'boolean')\n || Array.isArray(value) && value.length > 0 && value.every(v => typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean')\n ) {\n queryObject[key] = value\n delete query[key]\n }\n }\n\n // --- Apply the query parameters to the URL.\n url.search = toSearchParams(queryObject, { format: queryArrayFormat }).toString()\n}\n"],"names":[],"mappings":"AAGA,MAAM,qBAAqB;AAoBX,SAAA,uBAAuB,SAAyB,SAA6B;AAC3F,QAAM,EAAE,IAAI,IAAI,SACV,EAAE,WAAe,IAAA;AAIvB,MADI,OAAO,cAAe,YAAY,eAAe,QACjD,QAAQ,OAAW;AACvB,MAAI,EAAe,eAAA,KAAqB,OAAA,IAAI,MAAM,yCAAyC;AAG3F,QAAM,iBAAiB,IAAI,SAAS,MAAM,kBAAkB;AACvD,MAAA;AAGM,eAAA,aAAa,eAAe,UAAU;AACzC,YAAA,MAAM,UAAU,WAAW,oBAAoB,MAAM,GACrD,QAAQ,WAAW,GAAG;AAG5B,OACG,OAAO,SAAU,YAAY,MAAM,SAAS,KACzC,OAAO,SAAU,YAAY,OAAO,SAAS,KAAK,KAClD,OAAO,SAAU,eAErB,IAAI,WAAW,IAAI,SAAS,QAAQ,WAAW,MAAM,SAAA,CAAU,GAC/D,OAAO,WAAW,GAAG;AAAA,IAAA;AAG3B;ACdO,SAAS,eAAe,QAA4B,UAAiC,IAAqB;AAC/G,QAAM,EAAE,SAAS,OAAA,IAAW,SACtB,SAAS,IAAI,gBAAgB;AACnC,aAAW,OAAO,QAAQ;AAClB,UAAA,QAAQ,OAAO,GAAG;AACxB,QAAI,UAAU;AAGV,UAAA,MAAM,QAAQ,KAAK;AACrB,YAAI,WAAW,WAAuB,YAAA,KAAK,MAAO,QAAO,OAAO,GAAG,GAAG,MAAM,OAAO,CAAC,CAAC;AAAA,iBAC5E,WAAW,UAAW,YAAW,CAAC,GAAG,CAAC,KAAK,MAAM,UAAkB,QAAA,OAAO,GAAG,GAAG,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC;AAAA,iBACnG,WAAW,QAAgB,QAAA,OAAO,KAAK,MAAM,KAAK,GAAG,CAAC;AAAA,iBACtD,WAAW,OAAQ,YAAW,CAAC,GAAG,CAAC,KAAK,MAAM,UAAkB,QAAA,OAAO,GAAG,GAAG,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC;AAAA,iBAC/F,WAAW,OAAQ,YAAW,KAAK,cAAc,OAAO,KAAK,OAAO,CAAC,CAAC;AAAA;AAI1E,eAAO,OAAO,KAAK,MAAM,SAAA,CAAU;AAAA,EAAA;AAIrC,SAAA;AACT;AC/CgB,SAAA,kBAAkB,SAAyB,SAA6B;AACtF,QAAM,EAAE,IAAI,IAAI,SACV,EAAE,OAAO,qBAAqB;AAGpC,MAAI,QAAQ,OAAW;AACvB,MAAI,EAAe,eAAA,KAAqB,OAAA,IAAI,MAAM,wCAAwC;AAC1F,MAAI,OAAO,SAAU,YAAY,UAAU,KAAM;AAGjD,QAAM,cAAsC,CAAC;AAC7C,aAAW,OAAO,OAAO;AACjB,UAAA,QAAQ,MAAM,GAAG;AACvB,KACG,OAAO,SAAU,YAAY,MAAM,SAAS,KACzC,OAAO,SAAU,YAAY,OAAO,SAAS,KAAK,KAClD,OAAO,SAAU,aAClB,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,KAAK,MAAM,MAAM,CAAA,MAAK,OAAO,KAAM,YAAY,OAAO,KAAM,YAAY,OAAO,KAAM,SAAS,OAExI,YAAY,GAAG,IAAI,OACnB,OAAO,MAAM,GAAG;AAAA,EAAA;AAKhB,MAAA,SAAS,eAAe,aAAa,EAAE,QAAQ,iBAAiB,CAAC,EAAE,SAAS;AAClF;"}
|
package/dist/chunks/BUeqbyph.js
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
import { p as parseRequestParameters, a as parseRequestQuery } from "./0ZzUT3m_.js";
|
2
|
-
import { awaitable } from "@unshared/functions/awaitable";
|
3
|
-
function isObjectLike(value) {
|
4
|
-
return typeof value == "object" && value !== null && value.constructor === Object;
|
5
|
-
}
|
6
|
-
function isFormDataLike(value) {
|
7
|
-
if (typeof value != "object" || value === null) return !1;
|
8
|
-
if (value instanceof FormData) return !0;
|
9
|
-
const values = Object.values(value);
|
10
|
-
return values.length === 0 ? !1 : values.every((x) => x instanceof File ? !0 : Array.isArray(x) ? x.every((item) => item instanceof File) : x instanceof Blob);
|
11
|
-
}
|
12
|
-
function toFormData(object) {
|
13
|
-
if (object instanceof FormData) return object;
|
14
|
-
const formData = new FormData();
|
15
|
-
for (const key in object) {
|
16
|
-
const value = object[key];
|
17
|
-
if (value !== void 0)
|
18
|
-
if (Array.isArray(value))
|
19
|
-
for (const item of value)
|
20
|
-
formData.append(key, item);
|
21
|
-
else
|
22
|
-
formData.append(key, value);
|
23
|
-
}
|
24
|
-
return formData;
|
25
|
-
}
|
26
|
-
function parseRequestBody(context, options) {
|
27
|
-
const { body } = options;
|
28
|
-
context.init?.method && (["get", "head", "delete"].includes(context.init.method ?? "get") || body != null && (isFormDataLike(body) ? (context.init.body = toFormData(body), context.init.headers = context.init.headers ?? {}, context.init.headers = { ...context.init.headers, "Content-Type": "multipart/form-data" }) : body instanceof ReadableStream ? (context.init.body = body, context.init.headers = context.init.headers ?? {}, context.init.headers = { ...context.init.headers, "Content-Type": "application/octet-stream" }) : body instanceof File ? (context.init.body = body.stream(), context.init.headers = context.init.headers ?? {}, context.init.headers = { ...context.init.headers, "Content-Type": "application/octet-stream" }) : isObjectLike(body) ? (context.init.body = JSON.stringify(body), context.init.headers = context.init.headers ?? {}, context.init.headers = { ...context.init.headers, "Content-Type": "application/json" }) : context.init.body = body));
|
29
|
-
}
|
30
|
-
function parseRequestHeaders(context, options) {
|
31
|
-
const { headers } = options;
|
32
|
-
for (const key in headers) {
|
33
|
-
const value = headers[key];
|
34
|
-
(typeof value != "string" || value.length === 0) && typeof value != "number" || (context.init = context.init ?? {}, context.init.headers = context.init.headers ?? {}, context.init.headers = { ...context.init.headers, [key]: String(value) });
|
35
|
-
}
|
36
|
-
}
|
37
|
-
const EXP_REQUEST = /^((?<method>[a-z]+) )?(?<url>[^:]+?:\/{2}[^/]+)?(?<path>\/[^\s?]*)/i, METHODS = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete", "head", "options"]);
|
38
|
-
function parseRequestUrl(context, route, options) {
|
39
|
-
const { method, baseUrl } = options, match = EXP_REQUEST.exec(route);
|
40
|
-
if (!match?.groups) throw new Error("Could not resolve the `RequestInit` object: Invalid route name.");
|
41
|
-
const routeMethod = method ?? match.groups.method ?? "get", routeBaseUrl = baseUrl ?? match.groups.url;
|
42
|
-
if (!routeBaseUrl) throw new Error("Could not resolve the `RequestInit` object: the `baseUrl` is missing.");
|
43
|
-
const methodLower = routeMethod.toLowerCase();
|
44
|
-
if (!METHODS.has(methodLower)) throw new Error(`Could not resolve the \`RequestInit\` object:, the method \`${routeMethod}\` is invalid.`);
|
45
|
-
context.init = context.init ?? {}, context.init.method = methodLower, context.url = new URL(routeBaseUrl), context.url.pathname += context.url.pathname.endsWith("/") ? match.groups.path.slice(1) : match.groups.path;
|
46
|
-
}
|
47
|
-
function parseRequest(route, options = {}) {
|
48
|
-
const { data, body, query, parameters, headers, method, baseUrl, queryArrayFormat, ...init } = options, context = { init }, dataObject = isObjectLike(data) ? data : void 0;
|
49
|
-
parseRequestUrl(context, route, { baseUrl, method }), parseRequestParameters(context, { parameters: parameters ?? dataObject });
|
50
|
-
const requestMethod = context.init?.method?.toLowerCase() ?? "get", requestExpectsBody = ["post", "put", "patch"].includes(requestMethod);
|
51
|
-
return parseRequestQuery(context, { queryArrayFormat, query: requestExpectsBody ? query : query ?? dataObject }), parseRequestBody(context, { body: requestExpectsBody ? body ?? dataObject : void 0 }), parseRequestHeaders(context, { headers }), context;
|
52
|
-
}
|
53
|
-
async function fetch(route, options = {}) {
|
54
|
-
const { url, init } = parseRequest(route, options);
|
55
|
-
if (!url) throw new Error("Could not parse request URL");
|
56
|
-
return await globalThis.fetch(url, init);
|
57
|
-
}
|
58
|
-
async function* createResponseStreamJsonIterator(response, options) {
|
59
|
-
const { onError, onSuccess, onData, onEnd } = options;
|
60
|
-
try {
|
61
|
-
const body = response.body;
|
62
|
-
if (body === null) throw new Error("Could not read the response body, it is empty.");
|
63
|
-
const reader = body.getReader();
|
64
|
-
for (; ; ) {
|
65
|
-
const { done, value } = await reader.read();
|
66
|
-
if (done) break;
|
67
|
-
const parts = new TextDecoder().decode(value).trim().split("\0").filter(Boolean);
|
68
|
-
for (const part of parts) {
|
69
|
-
const payload = JSON.parse(part);
|
70
|
-
onData && onData(payload), yield payload;
|
71
|
-
}
|
72
|
-
}
|
73
|
-
onSuccess && onSuccess(response);
|
74
|
-
} catch (error) {
|
75
|
-
onError && onError(error);
|
76
|
-
} finally {
|
77
|
-
onEnd && onEnd(response);
|
78
|
-
}
|
79
|
-
}
|
80
|
-
function handleResponseStreamJson(response, options) {
|
81
|
-
const responseIterator = createResponseStreamJsonIterator(response, options);
|
82
|
-
return awaitable(responseIterator);
|
83
|
-
}
|
84
|
-
async function handleResponse(response, options = {}) {
|
85
|
-
const { onError, onSuccess, onData, onEnd, onFailure } = options, contentType = response.headers.get("Content-Type");
|
86
|
-
if (!response.ok)
|
87
|
-
throw onFailure && onFailure(response), onEnd && onEnd(response), new Error(response.statusText);
|
88
|
-
if (response.status === 204) {
|
89
|
-
onSuccess && onSuccess(response), onEnd && onEnd(response);
|
90
|
-
return;
|
91
|
-
}
|
92
|
-
return contentType?.startsWith("text/") ? await response.text().then((data) => (onData && onData(data), onSuccess && onSuccess(response), data)).catch((error) => {
|
93
|
-
throw onError && onError(error), error;
|
94
|
-
}).finally(() => {
|
95
|
-
onEnd && onEnd(response);
|
96
|
-
}) : contentType === "application/json" ? await response.json().then((data) => (onData && onData(data), onSuccess && onSuccess(response), data)).catch((error) => {
|
97
|
-
throw onError && onError(error), error;
|
98
|
-
}).finally(() => {
|
99
|
-
onEnd && onEnd(response);
|
100
|
-
}) : contentType === "application/stream+json" ? handleResponseStreamJson(response, options) : (onSuccess && onSuccess(response), onEnd && onEnd(response), response.body);
|
101
|
-
}
|
102
|
-
export {
|
103
|
-
handleResponseStreamJson as a,
|
104
|
-
isObjectLike as b,
|
105
|
-
parseRequestBody as c,
|
106
|
-
parseRequestHeaders as d,
|
107
|
-
parseRequestUrl as e,
|
108
|
-
fetch as f,
|
109
|
-
handleResponse as h,
|
110
|
-
isFormDataLike as i,
|
111
|
-
parseRequest as p,
|
112
|
-
toFormData as t
|
113
|
-
};
|
114
|
-
//# sourceMappingURL=BUeqbyph.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"BUeqbyph.js","sources":["../../utils/isObjectLike.ts","../../utils/isFormDataLike.ts","../../utils/toFormData.ts","../../utils/parseRequestBody.ts","../../utils/parseRequestHeaders.ts","../../utils/parseRequestUrl.ts","../../utils/parseRequest.ts","../../utils/fetch.ts","../../utils/handleResponseStreamJson.ts","../../utils/handleResponse.ts"],"sourcesContent":["import type { ObjectLike } from '@unshared/types'\n\n/**\n * Predicate to check if a value is an object-like value.\n *\n * @param value The value to check.\n * @returns `true` if the value is an object-like value, `false` otherwise.\n * @example isObjectLike({}) // true\n */\nexport function isObjectLike(value: unknown): value is ObjectLike {\n return typeof value === 'object' && value !== null && value.constructor === Object\n}\n","/**\n * A type that represents a FormData-like object, which is a plain object with\n * nested Blob, File, or FileList values. Or a FormData instance.\n */\nexport type FormDataLike = FormData | Record<string, Blob | File | FileList>\n\n/**\n * Predicate to check if a value is FormData-like, meaning it is a plain object\n * with nested Blob, File, or FileList values.\n *\n * @param value The value to check.\n * @returns `true` if the value is FormData-like, `false` otherwise.\n * @example isFormDataLike({ file: new File(['test'], 'test.txt') }) // true\n */\nexport function isFormDataLike(value: unknown): value is FormDataLike {\n if (typeof value !== 'object' || value === null) return false\n if (value instanceof FormData) return true\n const values = Object.values(value)\n if (values.length === 0) return false\n return values.every((x) => {\n if (x instanceof File) return true\n if (Array.isArray(x)) return x.every(item => item instanceof File)\n return x instanceof Blob\n })\n}\n","import type { FormDataLike } from './isFormDataLike'\n\n/**\n * Casts an object that may contain `Blob`, `File`, or `FileList` values to a `FormData` object.\n *\n * @param object The object to cast to a `FormData` object.\n * @returns The `FormData` object.\n */\nexport function toFormData(object: FormDataLike): FormData {\n if (object instanceof FormData) return object\n const formData = new FormData()\n for (const key in object) {\n const value = object[key]\n if (value === undefined) continue\n if (Array.isArray(value)) {\n for (const item of value)\n formData.append(key, item as Blob | string)\n }\n else {\n formData.append(key, value as Blob | string)\n }\n }\n return formData\n}\n","import type { FetchOptions, RequestContext } from './parseRequest'\nimport { isFormDataLike } from './isFormDataLike'\nimport { isObjectLike } from './isObjectLike'\nimport { toFormData } from './toFormData'\n\n/**\n * Parse the request body based on the provided data and options.\n *\n * @param context The request context.\n * @param options The request options.\n */\nexport function parseRequestBody(context: RequestContext, options: FetchOptions): void {\n const { body } = options\n\n // --- If the method is `GET`, `HEAD`, or `DELETE`, return early.\n if (!context.init?.method) return\n if (['get', 'head', 'delete'].includes(context.init.method ?? 'get')) return\n\n // --- If no data is provided, return early.\n if (body === null || body === undefined) return\n\n // --- If data contains a `File` object, create a FormData object.\n if (isFormDataLike(body)) {\n context.init.body = toFormData(body)\n context.init.headers = context.init.headers ?? {}\n context.init.headers = { ...context.init.headers, 'Content-Type': 'multipart/form-data' }\n }\n\n // --- If the data is a `ReadableStream`, pass it directly to the body.\n else if (body instanceof ReadableStream) {\n context.init.body = body\n context.init.headers = context.init.headers ?? {}\n context.init.headers = { ...context.init.headers, 'Content-Type': 'application/octet-stream' }\n }\n\n // --- If the data is a Blob, pass it directly to the body.\n else if (body instanceof File) {\n context.init.body = body.stream()\n context.init.headers = context.init.headers ?? {}\n context.init.headers = { ...context.init.headers, 'Content-Type': 'application/octet-stream' }\n }\n\n // --- Otherwise, stringify the data and set the content type to JSON.\n else if (isObjectLike(body)) {\n context.init.body = JSON.stringify(body)\n context.init.headers = context.init.headers ?? {}\n context.init.headers = { ...context.init.headers, 'Content-Type': 'application/json' }\n }\n\n // --- For all other data types, set the body directly.\n else {\n context.init.body = body as BodyInit\n }\n}\n","import type { FetchOptions, RequestContext } from './parseRequest'\n\n/**\n * Parse the request headers based on the provided data and options.\n *\n * @param context The request context.\n * @param options The request options.\n * @example\n *\n * // Append the `Content-Type` header to the request.\n * const context = {}\n * parseRequestHeaders(context, { headers: { 'Content-Type': 'application/json' } })\n *\n * // Will mutate the `init` object to include the headers.\n * console.log(context) // => { init: { headers: { 'Content-Type': 'application/json' } } }\n */\nexport function parseRequestHeaders(context: RequestContext, options: FetchOptions): void {\n const { headers } = options\n\n // --- Merge the headers with the existing headers.\n for (const key in headers) {\n const value = headers[key]\n if (((typeof value !== 'string' || value.length === 0) && typeof value !== 'number')) continue\n context.init = context.init ?? {}\n context.init.headers = context.init.headers ?? {}\n context.init.headers = { ...context.init.headers, [key]: String(value) }\n }\n}\n","import type { FetchOptions, RequestContext } from './parseRequest'\n\n/** Regular expression to match the request method and URL. */\nconst EXP_REQUEST = /^((?<method>[a-z]+) )?(?<url>[^:]+?:\\/{2}[^/]+)?(?<path>\\/[^\\s?]*)/i\n\n/** Valid HTTP methods. */\nconst METHODS = new Set(['get', 'post', 'put', 'patch', 'delete', 'head', 'options'])\n\n/**\n * Parses the route name to extract the URL and method. It allows the url and method to be\n * provided in the route name, or in the options object. The method will default to 'get'.\n *\n * @param context The request context to mutate.\n * @param route The name of the route to fetch.\n * @param options The options to pass to the request.\n * @example parseRequestUrl('GET /users', { baseUrl: 'https://api.example.com' }, context)\n */\nexport function parseRequestUrl(context: RequestContext, route: string, options: FetchOptions): void {\n const { method, baseUrl } = options\n\n // --- Extract the path, method, and base URL from the route name.\n const match = EXP_REQUEST.exec(route)\n if (!match?.groups) throw new Error('Could not resolve the `RequestInit` object: Invalid route name.')\n const routeMethod = method ?? match.groups.method ?? 'get'\n const routeBaseUrl = baseUrl ?? match.groups.url\n\n // --- Assert the base URL is provided, either in the options or the route name.\n if (!routeBaseUrl) throw new Error('Could not resolve the `RequestInit` object: the `baseUrl` is missing.')\n\n // --- Assert the method is valid.\n const methodLower = routeMethod.toLowerCase()\n const methodIsValid = METHODS.has(methodLower)\n if (!methodIsValid) throw new Error(`Could not resolve the \\`RequestInit\\` object:, the method \\`${routeMethod}\\` is invalid.`)\n\n // --- Create the url and apply the method.\n context.init = context.init ?? {}\n context.init.method = methodLower\n context.url = new URL(routeBaseUrl)\n\n // --- Append the path to the URL while making sure there are no double slashes.\n context.url.pathname += context.url.pathname.endsWith('/') ? match.groups.path.slice(1) : match.groups.path\n}\n","import type { Loose, MaybeLiteral, ObjectLike } from '@unshared/types'\nimport type { UnionMerge } from '@unshared/types'\nimport type { HttpHeader } from '../HttpHeaders'\nimport type { HttpMethod } from '../HttpMethods'\nimport type { SearchArrayFormat } from './toSearchParams'\nimport { isObjectLike } from './isObjectLike'\nimport { parseRequestBody } from './parseRequestBody'\nimport { parseRequestHeaders } from './parseRequestHeaders'\nimport { parseRequestParameters } from './parseRequestParameters'\nimport { parseRequestQuery } from './parseRequestQuery'\nimport { parseRequestUrl } from './parseRequestUrl'\n\n/** The methods to use for the request. */\nexport type FetchMethod = Lowercase<keyof typeof HttpMethod> | Uppercase<keyof typeof HttpMethod>\n\n/** Headers to include in the request. */\nexport type FetchHeaders = Partial<Record<MaybeLiteral<HttpHeader>, number | string>>\n\n/** Options to pass to the request. */\nexport interface FetchOptions<\n Method extends FetchMethod = FetchMethod,\n BaseUrl extends string = string,\n Parameters extends ObjectLike = ObjectLike,\n Query extends ObjectLike = ObjectLike,\n Body = unknown,\n Headers extends ObjectLike = ObjectLike,\n> extends Omit<RequestInit, 'body' | 'headers' | 'method'> {\n\n /**\n * The method to use for the request.\n *\n * @example 'GET'\n */\n method?: Method\n\n /**\n * The base URL to use for the request. This URL will be used to resolve the\n * path and query parameters of the request.\n *\n * @example 'https://api.example.com'\n */\n baseUrl?: BaseUrl\n\n /**\n * The data to include in the request. This data will be used to populate the\n * query parameters, body, and headers of the request based on the method type.\n *\n * @example { id: 1 }\n */\n data?: Loose<UnionMerge<Body | Headers | Query>>\n\n /**\n * The path parameters to include in the request.\n */\n parameters?: Parameters\n\n /**\n * The query parameters to include in the request.\n */\n query?: Loose<Query>\n\n /**\n * The format to use when serializing the query parameters.\n */\n queryArrayFormat?: SearchArrayFormat\n\n /**\n * The body to include in the request.\n */\n body?: Body extends ObjectLike ? Loose<Body> : Body\n\n /**\n * The headers to include in the request.\n */\n headers?: FetchHeaders & Headers\n}\n\nexport interface RequestContext {\n url?: URL\n init?: RequestInit\n}\n\n/**\n * Resolves the request body and/or query parameters based on the method type. This function\n * will mutate the `init` object to include the request body and headers based on the data type.\n *\n * @param route The name of the route to fetch.\n * @param options The options to pass to the request.\n * @returns The URL and the `RequestInit` object.\n */\nexport function parseRequest(route: string, options: FetchOptions = {}): RequestContext {\n const { data, body, query, parameters, headers, method, baseUrl, queryArrayFormat, ...init } = options\n const context: RequestContext = { init }\n const dataObject = isObjectLike(data) ? data : undefined\n\n // --- Parse the URL and insert the path parameters.\n parseRequestUrl(context, route, { baseUrl, method })\n parseRequestParameters(context, { parameters: parameters ?? dataObject })\n\n // --- Depending on the method, parse the query, body, and headers.\n const requestMethod = context.init?.method?.toLowerCase() ?? 'get'\n const requestExpectsBody = ['post', 'put', 'patch'].includes(requestMethod)\n parseRequestQuery(context, { queryArrayFormat, query: requestExpectsBody ? query : query ?? dataObject })\n parseRequestBody(context, { body: requestExpectsBody ? body ?? dataObject : undefined })\n parseRequestHeaders(context, { headers })\n\n // --- Return the context with the URL and the `RequestInit` object.\n return context\n}\n","import type { FetchOptions } from './parseRequest'\nimport { parseRequest } from './parseRequest'\n\n/**\n * Fetch a route with the provided options. This function will parse the route and\n * options to create a `Request` object and return the response from the server.\n *\n * @param route The name of the route to fetch.\n * @param options The options to pass to the request.\n * @returns The response from the server.\n * @example fetch('GET /users', { query: { limit: 10 } })\n */\nexport async function fetch(route: string, options?: FetchOptions): Promise<Response>\nexport async function fetch(route: string, options: FetchOptions = {}): Promise<Response> {\n const { url, init } = parseRequest(route, options)\n if (!url) throw new Error('Could not parse request URL')\n return await globalThis.fetch(url, init)\n}\n","import type { Awaitable } from '@unshared/functions/awaitable'\nimport type { RequestOptions } from './request'\nimport { awaitable } from '@unshared/functions/awaitable'\n\nasync function * createResponseStreamJsonIterator(response: Response, options: RequestOptions): AsyncGenerator<unknown, void, unknown> {\n const { onError, onSuccess, onData, onEnd } = options\n try {\n const body = response.body\n if (body === null) throw new Error('Could not read the response body, it is empty.')\n const reader = body.getReader()\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n const parts = new TextDecoder().decode(value).trim().split('\\0').filter(Boolean)\n\n // --- For each part, parse as JSON and yield the data.\n for (const part of parts) {\n const payload = JSON.parse(part) as unknown\n if (onData) onData(payload)\n yield payload\n }\n }\n if (onSuccess) onSuccess(response)\n }\n catch (error) {\n if (onError) onError(error as Error)\n }\n finally {\n if (onEnd) onEnd(response)\n }\n}\n\n/**\n * Handle a request response where the content type is a stream of JSON objects. This function\n * will parse the JSON objects and yield the data to the caller. If an error occurs, the `onError`\n * callback will be called and the function will return.\n *\n * @param response The response to handle.\n * @param options The options to pass to the request.\n * @returns An awaitable iterator that yields the parsed JSON objects.\n */\nexport function handleResponseStreamJson(response: Response, options: RequestOptions): Awaitable<AsyncIterable<unknown>, unknown[]> {\n const responseIterator = createResponseStreamJsonIterator(response, options)\n return awaitable(responseIterator)\n}\n","import type { RequestOptions } from './request'\nimport { handleResponseStreamJson } from './handleResponseStreamJson'\n\n/**\n * Handle a request response. This function will parse the response based on the content type and\n * return the data. If an error occurs, the `onError` callback will be called and the function will\n * throw an error.\n *\n * @param response The response to handle.\n * @param options The options to pass to the request.\n * @returns The parsed data from the response.\n */\nexport async function handleResponse(response: Response, options: RequestOptions = {}): Promise<unknown> {\n const { onError, onSuccess, onData, onEnd, onFailure } = options\n const contentType = response.headers.get('Content-Type')\n\n // --- If the response is not OK, throw an error with the response message.\n if (!response.ok) {\n if (onFailure) onFailure(response)\n if (onEnd) onEnd(response)\n throw new Error(response.statusText)\n }\n\n // --- If the status code is 204, return an empty response early.\n if (response.status === 204) {\n if (onSuccess) onSuccess(response)\n if (onEnd) onEnd(response)\n return\n }\n\n // --- If the response is a text content type, return the text response.\n if (contentType?.startsWith('text/')) {\n return await response.text()\n .then((data) => {\n if (onData) onData(data)\n if (onSuccess) onSuccess(response)\n return data\n })\n .catch((error: Error) => {\n if (onError) onError(error)\n throw error\n })\n .finally(() => {\n if (onEnd) onEnd(response)\n })\n }\n\n // --- If the response is a application/json, parse the JSON and return it.\n if (contentType === 'application/json') {\n return await response.json()\n .then((data) => {\n if (onData) onData(data)\n if (onSuccess) onSuccess(response)\n return data as unknown\n })\n .catch((error: Error) => {\n if (onError) onError(error)\n throw error\n })\n .finally(() => {\n if (onEnd) onEnd(response)\n })\n }\n\n // --- If the response is a application/stream+json, return an iterator that parses the JSON.\n if (contentType === 'application/stream+json')\n return handleResponseStreamJson(response, options)\n\n // --- Otherwise, fallback to returning the response body as-is.\n if (onSuccess) onSuccess(response)\n if (onEnd) onEnd(response)\n return response.body\n}\n"],"names":[],"mappings":"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"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"Biic1J5b.js","sources":["../../openapi/getServerUrl.ts","../../openapi/resolveOperation.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/** Get the base URL of an OpenAPI specification. */\nexport type ServerUrl<T> =\n\n // --- Handle OpenAPI 2.0 specifications.\n T extends {\n host: infer Host extends string\n basePath?: infer BasePath extends string\n schemes?: Array<infer Scheme extends string>\n }\n ? `${Scheme}://${Host}${BasePath}`\n\n // --- Handle OpenAPI 3.0 specifications.\n : T extends { servers: Array<{ url: infer U extends string }> }\n ? U\n : string\n\n/**\n * Given an OpenAPI specification, get the first base URL.\n *\n * @param specification The OpenAPI specification.\n * @returns The first base URL.\n * @example getBaseUrl(specification) // 'https://api.example.com/v1'\n */\nexport function getServerUrl<T>(specification: T): ServerUrl<T> {\n\n // --- Ensure the specification is an object.\n if (\n !specification\n || typeof specification !== 'object'\n || specification === null)\n throw new Error('Invalid OpenAPI specification.')\n\n // --- Handle OpenAPI 3.0 specifications.\n if (\n 'servers' in specification\n && Array.isArray(specification.servers)\n && specification.servers.length > 0\n && 'url' in specification.servers[0]\n && typeof specification.servers[0].url === 'string'\n && specification.servers[0].url.length > 0)\n return specification.servers[0].url as ServerUrl<T>\n\n // --- Handle OpenAPI 2.0 specifications.\n if (\n 'host' in specification\n && typeof specification.host === 'string') {\n\n const scheme = (\n 'schemes' in specification\n && Array.isArray(specification.schemes)\n && specification.schemes.length > 0\n && typeof specification.schemes[0] === 'string')\n ? specification.schemes[0]\n : 'https'\n\n const basePath = (\n 'basePath' in specification\n && typeof specification.basePath === 'string'\n && specification.basePath.length > 0)\n ? specification.basePath\n : '/'\n\n return `${scheme}://${specification.host}${basePath}` as ServerUrl<T>\n }\n\n throw new Error('No base URL found in the OpenAPI specification.')\n}\n","import type { CollectKey, Pretty } from '@unshared/types'\nimport type { OpenAPI } from 'openapi-types'\nimport type { FetchMethod } from '../utils/parseRequest'\n\n/** The HTTP methods supported by OpenAPI. */\nconst methods = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch'] as const\n\n/** Union of all operation IDs in the specification. */\nexport type OperationId<T> =\nT extends { paths: infer P }\n ? P extends Record<string, infer R>\n ? R extends Record<string, infer O>\n ? O extends { operationId: infer N }\n ? N\n : string\n : string\n : string\n : string\n\n/** A union of possible Operations types in the specification. */\nexport type Operation = OpenAPI.Operation & { method: FetchMethod; path: string }\n\n/** Find an operation by its operationId in an OpenAPI specification. */\nexport type OperationById<T, U extends OperationId<T>> =\n T extends { paths: infer P }\n ? CollectKey<P> extends Record<string, infer R>\n ? CollectKey<R> extends Record<string, infer O>\n ? O extends { $key: [infer P extends string, infer M extends string]; operationId: U }\n ? Pretty<Omit<O, '$key'> & { method: M; path: P }>\n : never\n : never\n : never\n : never\n\n/**\n * Given an OpenAPI specification, find an operation by its operationId.\n *\n * @param document The OpenAPI specification document.\n * @param operationId The operationId of the operation to resolve.\n * @returns The resolved operation.\n * @example resolveOperation(document, 'getUser') // { method: 'get', path: '/users/{username}', ... }\n */\nexport function resolveOperation<T, U extends OperationId<T>>(document: T, operationId: U): OperationById<T, U> {\n\n // --- Validate the specification.\n if (!document\n || typeof document !== 'object'\n || document === null\n || 'paths' in document === false\n || typeof document.paths !== 'object'\n || document.paths === null)\n throw new Error('Missing paths object in the OpenAPI specification.')\n\n // --- Search for the operation in the specification's paths.\n const paths = document.paths as OpenAPI.Document['paths']\n for (const path in paths) {\n const route = paths[path]\n if (typeof route !== 'object' || route === null) continue\n\n // --- Search in each method for the operation.\n for (const method of methods) {\n const operation = route[method]\n if (method in route === false\n || typeof operation !== 'object'\n || operation === null\n || 'operationId' in operation === false\n || operation.operationId !== operationId) continue\n\n // --- Route was found, return the operation.\n return { ...route[method], method, path } as OperationById<T, U>\n }\n }\n\n // --- Throw an error if the operation was not found.\n throw new Error(`Operation \"${operationId}\" not found in specification.`)\n}\n"],"names":[],"mappings":"AAwBO,SAAS,aAAgB,eAAgC;AAG9D,MACE,CAAC,iBACE,OAAO,iBAAkB,YACzB,kBAAkB;AACf,UAAA,IAAI,MAAM,gCAAgC;AAGlD,MACE,aAAa,iBACV,MAAM,QAAQ,cAAc,OAAO,KACnC,cAAc,QAAQ,SAAS,KAC/B,SAAS,cAAc,QAAQ,CAAC,KAChC,OAAO,cAAc,QAAQ,CAAC,EAAE,OAAQ,YACxC,cAAc,QAAQ,CAAC,EAAE,IAAI,SAAS;AAClC,WAAA,cAAc,QAAQ,CAAC,EAAE;AAGlC,MACE,UAAU,iBACP,OAAO,cAAc,QAAS,UAAU;AAE3C,UAAM,SACJ,aAAa,iBACV,MAAM,QAAQ,cAAc,OAAO,KACnC,cAAc,QAAQ,SAAS,KAC/B,OAAO,cAAc,QAAQ,CAAC,KAAM,WACrC,cAAc,QAAQ,CAAC,IACvB,SAEE,WACJ,cAAc,iBACX,OAAO,cAAc,YAAa,YAClC,cAAc,SAAS,SAAS,IACjC,cAAc,WACd;AAEJ,WAAO,GAAG,MAAM,MAAM,cAAc,IAAI,GAAG,QAAQ;AAAA,EAAA;AAG/C,QAAA,IAAI,MAAM,iDAAiD;AACnE;AC9DA,MAAM,UAAU,CAAC,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,OAAO;AAqC3D,SAAA,iBAA8C,UAAa,aAAqC;AAG9G,MAAI,CAAC,YACA,OAAO,YAAa,YACpB,aAAa,QACb,EAAW,WAAA,aACX,OAAO,SAAS,SAAU,YAC1B,SAAS,UAAU;AAChB,UAAA,IAAI,MAAM,oDAAoD;AAGtE,QAAM,QAAQ,SAAS;AACvB,aAAW,QAAQ,OAAO;AAClB,UAAA,QAAQ,MAAM,IAAI;AACpB,QAAA,EAAA,OAAO,SAAU,YAAY,UAAU;AAG3C,iBAAW,UAAU,SAAS;AACtB,cAAA,YAAY,MAAM,MAAM;AAC1B,YAAA,EAAA,EAAA,UAAU,UACT,OAAO,aAAc,YACrB,cAAc,QACd,EAAA,iBAAiB,cACjB,UAAU,gBAAgB;AAG/B,iBAAO,EAAE,GAAG,MAAM,MAAM,GAAG,QAAQ,KAAK;AAAA,MAAA;AAAA,EAC1C;AAIF,QAAM,IAAI,MAAM,cAAc,WAAW,+BAA+B;AAC1E;"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"CYmaYL5B.cjs","sources":["../../utils/parseRequestParameters.ts","../../utils/toSearchParams.ts","../../utils/parseRequestQuery.ts"],"sourcesContent":["import type { FetchOptions, RequestContext } from './parseRequest'\n\n/** Regular expression to match path parameters in the URL. */\nconst EXP_PATH_PARAMETER = /:([\\w-]+)|%7B([\\w-]+)%7D/g\n\n/**\n * Parse the request parameters from the request data. This function will mutate the\n * `url` object of the context to include the path parameters based on the provided data.\n *\n * @param context The request context to mutate.\n * @param options The options to pass to the request.\n * @example\n *\n * // Using `express` style path parameters.\n * const context = { url: new URL('https://api.example.com/users/:id') }\n * parseRequestParameters(context, { parameters: { id: 1 } })\n * console.log(context.url.pathname) // 'https://api.example.com/users/1'\n *\n * // Using `OpenAPI` style path parameters.\n * const context = { url: new URL('https://api.example.com/users/{id}') }\n * parseRequestParameters(context, { parameters: { id: 1 } })\n * console.log(context.url.pathname) // 'https://api.example.com/users/1'\n */\nexport function parseRequestParameters(context: RequestContext, options: FetchOptions): void {\n const { url } = context\n const { parameters } = options\n\n // --- Return early if the parameters is not an object.\n if (typeof parameters !== 'object' || parameters === null) return\n if (url === undefined) return\n if (url instanceof URL === false) throw new Error('The `url` must be an instance of `URL`.')\n\n // --- If the method has a parameter, fill the path with the data.\n const pathParameters = url.pathname.match(EXP_PATH_PARAMETER)\n if (!pathParameters) return\n\n // --- Apply the path parameters to the URL.\n for (const parameter of pathParameters.values()) {\n const key = parameter.replaceAll(EXP_PATH_PARAMETER, '$1$2')\n const value = parameters[key]\n\n // --- If the parameter is provided, replace the path with the value.\n if (\n (typeof value === 'string' && value.length > 0)\n || (typeof value === 'number' && Number.isFinite(value))\n || (typeof value === 'boolean')\n ) {\n url.pathname = url.pathname.replace(parameter, value.toString())\n delete parameters[key]\n }\n }\n}\n","/* eslint-disable unicorn/prevent-abbreviations */\nimport type { MaybeArray } from '@unshared/types'\n\n/** An object that can be converted to a query string. */\nexport type SearchParamsObject = Record<string, MaybeArray<boolean | number | string> | undefined>\n\n/** The search array format options. */\nexport type SearchArrayFormat = 'brackets' | 'comma' | 'flat' | 'indices' | 'path'\n\n/** Options for the query string conversion. */\nexport interface ToSearchParamsOptions {\n\n /**\n * Defines how to handle arrays in the object. There is no standard way to\n * represent arrays in query strings, so this option allows you to choose\n * how to handle them. Additionally, you can provide a custom function to\n * handle it yourself.\n *\n * - `brackets` (default): Convert arrays to `key[]=value&key[]=value` format.\n * - `indices`: Convert arrays to `key[0]=value&key[1]=value` format.\n * - `comma`: Convert arrays to `key=value1,value2` format.\n * - `path`: Convert arrays to `key.0=value&key.1=value` format.\n * - `flat`: Convert arrays to `key=value1&key=value2` format.\n *\n * @default 'flat'\n */\n format?: SearchArrayFormat\n}\n\n/**\n * Convert object to query string parameters. Converting all values to strings\n * and arrays to `key[0]=value&key[1]=value` format.\n *\n * @param object The object to convert to a query string.\n * @param options The query string options.\n * @returns The `URLSearchParams` object.\n */\nexport function toSearchParams(object: SearchParamsObject, options: ToSearchParamsOptions = {}): URLSearchParams {\n const { format = 'flat' } = options\n const search = new URLSearchParams()\n for (const key in object) {\n const value = object[key]\n if (value === undefined) continue\n\n // --- Convert arrays based on the format.\n if (Array.isArray(value)) {\n if (format === 'brackets') for (const v of value) search.append(`${key}[]`, String(v))\n else if (format === 'indices') for (const [i, v] of value.entries()) search.append(`${key}[${i}]`, String(v))\n else if (format === 'comma') search.append(key, value.join(','))\n else if (format === 'path') for (const [i, v] of value.entries()) search.append(`${key}.${i}`, String(v))\n else if (format === 'flat') for (const v of value) search.append(key, String(v))\n }\n\n // --- Convert all values to strings.\n else { search.append(key, value.toString()) }\n }\n\n // --- Return the query string.\n return search\n}\n","/* eslint-disable unicorn/prevent-abbreviations */\nimport type { FetchOptions, RequestContext } from './parseRequest'\nimport type { SearchParamsObject as SearchParametersObject } from './toSearchParams'\nimport { toSearchParams } from './toSearchParams'\n\n/**\n * Parse the query parameters from the request data. This function will append\n * the query parameters to the URL based on the method and the data provided.\n *\n * @param context The request context to modify.\n * @param options The options to pass to the request.\n */\nexport function parseRequestQuery(context: RequestContext, options: FetchOptions): void {\n const { url } = context\n const { query, queryArrayFormat } = options\n\n // --- Return early if the query is not an object or the URL is not provided.\n if (url === undefined) return\n if (url instanceof URL === false) throw new Error('The `url` must be an instance of `URL.')\n if (typeof query !== 'object' || query === null) return\n\n // --- Append the `data` to the query parameters if the method does not expect a body.\n const queryObject: SearchParametersObject = {}\n for (const key in query) {\n const value = query[key]\n if (\n (typeof value === 'string' && value.length > 0)\n || (typeof value === 'number' && Number.isFinite(value))\n || (typeof value === 'boolean')\n || Array.isArray(value) && value.length > 0 && value.every(v => typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean')\n ) {\n queryObject[key] = value\n delete query[key]\n }\n }\n\n // --- Apply the query parameters to the URL.\n url.search = toSearchParams(queryObject, { format: queryArrayFormat }).toString()\n}\n"],"names":[],"mappings":";AAGA,MAAM,qBAAqB;AAoBX,SAAA,uBAAuB,SAAyB,SAA6B;AAC3F,QAAM,EAAE,IAAI,IAAI,SACV,EAAE,WAAe,IAAA;AAIvB,MADI,OAAO,cAAe,YAAY,eAAe,QACjD,QAAQ,OAAW;AACvB,MAAI,EAAe,eAAA,KAAqB,OAAA,IAAI,MAAM,yCAAyC;AAG3F,QAAM,iBAAiB,IAAI,SAAS,MAAM,kBAAkB;AACvD,MAAA;AAGM,eAAA,aAAa,eAAe,UAAU;AACzC,YAAA,MAAM,UAAU,WAAW,oBAAoB,MAAM,GACrD,QAAQ,WAAW,GAAG;AAG5B,OACG,OAAO,SAAU,YAAY,MAAM,SAAS,KACzC,OAAO,SAAU,YAAY,OAAO,SAAS,KAAK,KAClD,OAAO,SAAU,eAErB,IAAI,WAAW,IAAI,SAAS,QAAQ,WAAW,MAAM,SAAA,CAAU,GAC/D,OAAO,WAAW,GAAG;AAAA,IAAA;AAG3B;ACdO,SAAS,eAAe,QAA4B,UAAiC,IAAqB;AAC/G,QAAM,EAAE,SAAS,OAAA,IAAW,SACtB,SAAS,IAAI,gBAAgB;AACnC,aAAW,OAAO,QAAQ;AAClB,UAAA,QAAQ,OAAO,GAAG;AACxB,QAAI,UAAU;AAGV,UAAA,MAAM,QAAQ,KAAK;AACrB,YAAI,WAAW,WAAuB,YAAA,KAAK,MAAO,QAAO,OAAO,GAAG,GAAG,MAAM,OAAO,CAAC,CAAC;AAAA,iBAC5E,WAAW,UAAW,YAAW,CAAC,GAAG,CAAC,KAAK,MAAM,UAAkB,QAAA,OAAO,GAAG,GAAG,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC;AAAA,iBACnG,WAAW,QAAgB,QAAA,OAAO,KAAK,MAAM,KAAK,GAAG,CAAC;AAAA,iBACtD,WAAW,OAAQ,YAAW,CAAC,GAAG,CAAC,KAAK,MAAM,UAAkB,QAAA,OAAO,GAAG,GAAG,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC;AAAA,iBAC/F,WAAW,OAAQ,YAAW,KAAK,cAAc,OAAO,KAAK,OAAO,CAAC,CAAC;AAAA;AAI1E,eAAO,OAAO,KAAK,MAAM,SAAA,CAAU;AAAA,EAAA;AAIrC,SAAA;AACT;AC/CgB,SAAA,kBAAkB,SAAyB,SAA6B;AACtF,QAAM,EAAE,IAAI,IAAI,SACV,EAAE,OAAO,qBAAqB;AAGpC,MAAI,QAAQ,OAAW;AACvB,MAAI,EAAe,eAAA,KAAqB,OAAA,IAAI,MAAM,wCAAwC;AAC1F,MAAI,OAAO,SAAU,YAAY,UAAU,KAAM;AAGjD,QAAM,cAAsC,CAAC;AAC7C,aAAW,OAAO,OAAO;AACjB,UAAA,QAAQ,MAAM,GAAG;AACvB,KACG,OAAO,SAAU,YAAY,MAAM,SAAS,KACzC,OAAO,SAAU,YAAY,OAAO,SAAS,KAAK,KAClD,OAAO,SAAU,aAClB,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,KAAK,MAAM,MAAM,CAAA,MAAK,OAAO,KAAM,YAAY,OAAO,KAAM,YAAY,OAAO,KAAM,SAAS,OAExI,YAAY,GAAG,IAAI,OACnB,OAAO,MAAM,GAAG;AAAA,EAAA;AAKhB,MAAA,SAAS,eAAe,aAAa,EAAE,QAAQ,iBAAiB,CAAC,EAAE,SAAS;AAClF;;;;"}
|