@unshared/client 0.2.1 → 0.2.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.
Files changed (47) hide show
  1. package/dist/chunks/{DvNxpeLr.js → B5hc73Po.js} +6 -13
  2. package/dist/chunks/B5hc73Po.js.map +1 -0
  3. package/dist/chunks/{KZzRv9Rx.d.ts → BsMghIPi.d.ts} +1 -1
  4. package/dist/chunks/CKfJvIQ8.js +50 -0
  5. package/dist/chunks/CKfJvIQ8.js.map +1 -0
  6. package/dist/chunks/Cx8m1YzL.cjs +49 -0
  7. package/dist/chunks/Cx8m1YzL.cjs.map +1 -0
  8. package/dist/chunks/D-WqCFul.js +30 -0
  9. package/dist/chunks/D-WqCFul.js.map +1 -0
  10. package/dist/chunks/{Bul9W_0Q.cjs → D8Tsm7xC.cjs} +6 -13
  11. package/dist/chunks/D8Tsm7xC.cjs.map +1 -0
  12. package/dist/chunks/{D8ZTxxpG.d.ts → DZp6zyqV.d.ts} +5 -3
  13. package/dist/chunks/r8pYO6Hx.d.ts +38 -0
  14. package/dist/chunks/xRZPkxch.cjs +29 -0
  15. package/dist/chunks/xRZPkxch.cjs.map +1 -0
  16. package/dist/createClient.cjs +6 -10
  17. package/dist/createClient.cjs.map +1 -1
  18. package/dist/createClient.d.ts +6 -5
  19. package/dist/createClient.js +6 -9
  20. package/dist/createClient.js.map +1 -1
  21. package/dist/fetch.cjs +2 -2
  22. package/dist/fetch.cjs.map +1 -1
  23. package/dist/fetch.d.ts +5 -1
  24. package/dist/fetch.js +2 -2
  25. package/dist/fetch.js.map +1 -1
  26. package/dist/index.cjs +12 -9
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.ts +5 -3
  29. package/dist/index.js +15 -11
  30. package/dist/index.js.map +1 -1
  31. package/dist/openapi.cjs +45 -7
  32. package/dist/openapi.cjs.map +1 -1
  33. package/dist/openapi.d.ts +2 -2
  34. package/dist/openapi.js +43 -5
  35. package/dist/openapi.js.map +1 -1
  36. package/dist/utils.cjs +4 -1
  37. package/dist/utils.cjs.map +1 -1
  38. package/dist/utils.d.ts +17 -3
  39. package/dist/utils.js +6 -2
  40. package/dist/utils.js.map +1 -1
  41. package/package.json +4 -3
  42. package/dist/chunks/Bul9W_0Q.cjs.map +0 -1
  43. package/dist/chunks/BzqHK4CV.cjs +0 -71
  44. package/dist/chunks/BzqHK4CV.cjs.map +0 -1
  45. package/dist/chunks/CRISqhP7.js +0 -72
  46. package/dist/chunks/CRISqhP7.js.map +0 -1
  47. package/dist/chunks/DvNxpeLr.js.map +0 -1
@@ -23,14 +23,13 @@ function toFormData(object) {
23
23
  }
24
24
  function parseRequestBody(route, options, context) {
25
25
  const { data, body = data } = options, { init } = context;
26
- init.headers = init.headers ?? {}, !["get", "head", "delete"].includes(init.method ?? "get") && body != null && (isFormDataLike(body) ? (init.body = toFormData(body), init.headers = { ...init.headers, "Content-Type": "multipart/form-data" }) : body instanceof ReadableStream ? init.body = body : body instanceof File ? (init.body = body.stream(), init.headers = { ...init.headers, "Content-Type": "application/octet-stream" }) : isObjectLike(body) ? (init.body = JSON.stringify(body), init.headers = { ...init.headers, "Content-Type": "application/json" }) : init.body = body);
26
+ ["get", "head", "delete"].includes(init.method ?? "get") || body != null && (isFormDataLike(body) ? (init.body = toFormData(body), init.headers = init.headers ?? {}, init.headers = { ...init.headers, "Content-Type": "multipart/form-data" }) : body instanceof ReadableStream ? init.body = body : body instanceof File ? (init.body = body.stream(), init.headers = init.headers ?? {}, init.headers = { ...init.headers, "Content-Type": "application/octet-stream" }) : isObjectLike(body) ? (init.body = JSON.stringify(body), init.headers = init.headers ?? {}, init.headers = { ...init.headers, "Content-Type": "application/json" }) : init.body = body);
27
27
  }
28
28
  function parseRequestHeaders(route, options, context) {
29
29
  const { headers = {} } = options, { init } = context;
30
- init.headers = init.headers ?? {};
31
30
  for (const key in headers) {
32
31
  const value = headers[key];
33
- value !== void 0 && typeof value == "string" && (init.headers = { ...init.headers, [key]: value });
32
+ value !== void 0 && typeof value == "string" && (init.headers = init.headers ?? {}, init.headers = { ...init.headers, [key]: value });
34
33
  }
35
34
  }
36
35
  const EXP_PATH_PARAMETER = /:([\w-]+)|%7B([\w-]+)%7D/g;
@@ -38,17 +37,11 @@ function parseRequestParameters(route, options, context) {
38
37
  const { url } = context, { data, parameters = {} } = options;
39
38
  if (!url) throw new Error("Could not resolve the `RequestInit` object: the `url` is missing.");
40
39
  const pathParameters = url.pathname.match(EXP_PATH_PARAMETER);
41
- if (pathParameters) {
42
- if (isObjectLike(data))
43
- for (const key in data) {
44
- const value = data[key];
45
- value !== void 0 && typeof value == "string" && parameters[key] === void 0 && (parameters[key] = value, delete data[key]);
46
- }
40
+ if (pathParameters)
47
41
  for (const parameter of pathParameters.values()) {
48
42
  const key = parameter.replaceAll(EXP_PATH_PARAMETER, "$1$2"), value = parameters[key];
49
- value !== void 0 && typeof value == "string" && (url.pathname = url.pathname.replace(parameter, value));
43
+ value !== void 0 && typeof value == "string" ? url.pathname = url.pathname.replace(parameter, value) : isObjectLike(data) && data[key] !== void 0 && typeof data[key] == "string" && (url.pathname = url.pathname.replace(parameter, data[key]), delete data[key]);
50
44
  }
51
- }
52
45
  }
53
46
  function toSearchParams(object, options = {}) {
54
47
  const { searchArrayFormat = "flat" } = options, search = new URLSearchParams();
@@ -84,7 +77,7 @@ function parseRequestUrl(route, options, context) {
84
77
  if (!METHODS.has(methodLower)) throw new Error(`Could not resolve the \`RequestInit\` object:, the method \`${routeMethod}\` is invalid.`);
85
78
  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;
86
79
  }
87
- function parseRequest(route, options = {}) {
80
+ function parseRequest(route, options) {
88
81
  const { data, body, query, headers, parameters, baseUrl, method, searchArrayFormat, ...requestInit } = options, context = { init: requestInit };
89
82
  return parseRequestUrl(route, { baseUrl, method }, context), parseRequestParameters(route, { data, parameters }, context), parseRequestQuery(route, { data, query, searchArrayFormat }, context), parseRequestBody(route, { data, body }, context), parseRequestHeaders(route, { headers }, context), context;
90
83
  }
@@ -100,4 +93,4 @@ export {
100
93
  parseRequest as p,
101
94
  toFormData as t
102
95
  };
103
- //# sourceMappingURL=DvNxpeLr.js.map
96
+ //# sourceMappingURL=B5hc73Po.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"B5hc73Po.js","sources":["../../utils/isFormDataLike.ts","../../utils/isObjectLike.ts","../../utils/toFormData.ts","../../utils/parseRequestBody.ts","../../utils/parseRequestHeaders.ts","../../utils/parseRequestParameters.ts","../../utils/toSearchParams.ts","../../utils/parseRequestQuery.ts","../../utils/parseRequestUrl.ts","../../utils/parseRequest.ts"],"sourcesContent":["/**\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","/**\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 Record<string, unknown> {\n return typeof value === 'object' && value !== null && value.constructor === Object\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 { RequestContext, RequestOptions } 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 route The route path.\n * @param options The request options.\n * @param context The request context.\n */\nexport function parseRequestBody(route: string, options: Pick<RequestOptions, 'body' | 'data'>, context: RequestContext): void {\n const { data, body = data } = options\n const { init } = context\n\n // --- If the method is `GET`, `HEAD`, or `DELETE`, return early.\n if (['get', 'head', 'delete'].includes(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 init.body = toFormData(body)\n init.headers = init.headers ?? {}\n init.headers = { ...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 init.body = body\n }\n\n // --- If the data is a Blob, pass it directly to the body.\n else if (body instanceof File) {\n init.body = body.stream()\n init.headers = init.headers ?? {}\n init.headers = { ...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 init.body = JSON.stringify(body)\n init.headers = init.headers ?? {}\n init.headers = { ...init.headers, 'Content-Type': 'application/json' }\n }\n\n // --- For all other data types, set the body directly.\n else {\n init.body = body\n }\n}\n","import type { RequestContext, RequestOptions } from './parseRequest'\n\n/**\n * Parse the request headers based on the provided data and options.\n *\n * @param route The route path.\n * @param options The request options.\n * @param context The request context.\n */\nexport function parseRequestHeaders(route: string, options: Pick<RequestOptions, 'headers'>, context: RequestContext): void {\n const { headers = {} } = options\n const { init } = context\n\n // --- Merge the headers with the existing headers.\n for (const key in headers) {\n const value = headers[key]\n if (value === undefined) continue\n if (typeof value !== 'string') continue\n init.headers = init.headers ?? {}\n init.headers = { ...init.headers, [key]: value }\n }\n}\n","import type { RequestContext, RequestOptions } from './parseRequest'\nimport { isObjectLike } from './isObjectLike'\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 append\n * the path parameters to the URL based on the method and the data provided.\n *\n * @param route The name of the route to fetch. (ignored)\n * @param options The options to pass to the request.\n * @param context The request context to modify.\n * @example\n * // Using `express` style path parameters.\n * parseRequestParameters('GET /users/:id', { data: { id: 1 } }, context)\n *\n * // Using `OpenAPI` style path parameters.\n * parseRequestParameters('GET /users/{id}', { data: { id: 1 } }, context)\n */\nexport function parseRequestParameters(route: string, options: Pick<RequestOptions, 'data' | 'parameters'>, context: RequestContext): void {\n const { url } = context\n const { data, parameters = {} } = options\n\n // --- If the method has a parameter, fill the path with the data.\n if (!url) throw new Error('Could not resolve the `RequestInit` object: the `url` is missing.')\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\n // --- If the parameter is provided, replace the path with the value.\n const value = parameters[key]\n if (value !== undefined && typeof value === 'string') {\n url.pathname = url.pathname.replace(parameter, value)\n }\n\n // --- If the data contains the parameter, use it and remove it from the data.\n else if (isObjectLike(data) && data[key] !== undefined && typeof data[key] === 'string') {\n url.pathname = url.pathname.replace(parameter, data[key])\n delete data[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 searchArrayFormat?: 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 { searchArrayFormat = '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 (searchArrayFormat === 'brackets') for (const v of value) search.append(`${key}[]`, String(v))\n else if (searchArrayFormat === 'indices') for (const [i, v] of value.entries()) search.append(`${key}[${i}]`, String(v))\n else if (searchArrayFormat === 'comma') search.append(key, value.join(','))\n else if (searchArrayFormat === 'path') for (const [i, v] of value.entries()) search.append(`${key}.${i}`, String(v))\n else if (searchArrayFormat === '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 { RequestContext, RequestOptions } from './parseRequest'\nimport { isObjectLike } from './isObjectLike'\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 route The name of the route to fetch. (ignored)\n * @param options The options to pass to the request.\n * @param context The request context to modify.\n */\nexport function parseRequestQuery(route: string, options: Pick<RequestOptions, 'data' | 'query' | 'searchArrayFormat'>, context: RequestContext): void {\n const { url, init } = context\n const { data, query = {}, searchArrayFormat } = options\n if (!url) throw new Error('Could not resolve the `RequestInit` object: the `url` is missing.')\n\n // --- Append the `data` to the query parameters if the method does not expect a body.\n const isExpectingBody = ['post', 'put', 'patch'].includes(init.method ?? 'get')\n if (!isExpectingBody && isObjectLike(data)) {\n for (const key in data) {\n if (data[key] === undefined) continue\n if (query[key] !== undefined) continue\n // @ts-expect-error: Ignore type mismatch.\n query[key] = data[key]\n delete data[key]\n }\n }\n\n // --- Apply the query parameters to the URL.\n url.search = toSearchParams(query, { searchArrayFormat }).toString()\n}\n","import type { RequestContext, RequestOptions } 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 route The name of the route to fetch.\n * @param options The options to pass to the request.\n * @param context The request context to modify.\n * @example parseRequestUrl('GET /users', { baseUrl: 'https://api.example.com' }, context)\n */\nexport function parseRequestUrl(route: string, options: Pick<RequestOptions, 'baseUrl' | 'method'>, context: RequestContext): 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","/* eslint-disable unicorn/prevent-abbreviations */\nimport type { MaybeLiteral } from '@unshared/types'\nimport type { Override } from '@unshared/types'\nimport type { HttpHeader, HttpMethod } from '../types'\nimport type { SearchArrayFormat, SearchParamsObject } from './toSearchParams'\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 RequestMethod = Lowercase<keyof typeof HttpMethod> | Uppercase<keyof typeof HttpMethod>\n\n/** Headers to include in the request. */\nexport type RequestHeaders = Partial<Record<MaybeLiteral<HttpHeader>, string>>\n\n/** The types of data that can be passed to the request. */\nexport type RequestBody = File | FormData | ReadableStream | Record<string, unknown> | string\n\n/** Options to pass to the request. */\nexport type RequestOptions = Override<RequestInit, {\n\n /**\n * The method to use for the request.\n *\n * @example 'GET'\n */\n method?: RequestMethod\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?: string\n\n /**\n * The data to pass to the request. This data will be used to fill the path\n * parameters, query parameters, body, and form data of the request based on\n * the route method.\n */\n data?: RequestBody\n\n /**\n * The body to include in the request.\n */\n body?: RequestBody\n\n /**\n * The headers to include in the request.\n */\n headers?: RequestHeaders\n\n /**\n * Query parameters to include in the request.\n */\n query?: SearchParamsObject\n\n /**\n * The format to use when serializing the query parameters.\n */\n searchArrayFormat?: SearchArrayFormat\n\n /**\n * The path parameters to include in the request.\n */\n parameters?: Record<string, number | string>\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: RequestOptions): RequestContext {\n const { data, body, query, headers, parameters, baseUrl, method, searchArrayFormat, ...requestInit } = options\n const context: RequestContext = { init: requestInit }\n parseRequestUrl(route, { baseUrl, method }, context)\n parseRequestParameters(route, { data, parameters }, context)\n parseRequestQuery(route, { data, query, searchArrayFormat }, context)\n parseRequestBody(route, { data, body }, context)\n parseRequestHeaders(route, { headers }, context)\n return context\n}\n"],"names":[],"mappings":"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"}
@@ -134,7 +134,7 @@ declare namespace OpenAPIV3 {
134
134
  };
135
135
  } ? {
136
136
  [K in keyof V]: U;
137
- } : string : never;
137
+ } : never : never;
138
138
  type ServerQuery<T> = T extends {
139
139
  components: {
140
140
  securitySchemes: {
@@ -0,0 +1,50 @@
1
+ import { awaitable } from "@unshared/functions/awaitable";
2
+ async function* createResponseStreamJsonIterator(response, options) {
3
+ const { onError, onSuccess, onData, onEnd } = options;
4
+ try {
5
+ const body = response.body;
6
+ if (body === null) throw new Error("Could not read the response body, it is empty.");
7
+ const reader = body.getReader();
8
+ for (; ; ) {
9
+ const { done, value } = await reader.read();
10
+ if (done) break;
11
+ const parts = new TextDecoder().decode(value).trim().split("\0").filter(Boolean);
12
+ for (const part of parts) {
13
+ const payload = JSON.parse(part);
14
+ onData && onData(payload), yield payload;
15
+ }
16
+ }
17
+ onSuccess && onSuccess(response);
18
+ } catch (error) {
19
+ onError && onError(error);
20
+ } finally {
21
+ onEnd && onEnd(response);
22
+ }
23
+ }
24
+ function handleResponseStreamJson(response, options) {
25
+ const responseIterator = createResponseStreamJsonIterator(response, options);
26
+ return awaitable(responseIterator);
27
+ }
28
+ async function handleResponse(response, options) {
29
+ const { onError, onSuccess, onData, onEnd, onFailure } = options, contentType = response.headers.get("Content-Type");
30
+ if (!response.ok)
31
+ throw onFailure && onFailure(response), onEnd && onEnd(response), new Error(response.statusText);
32
+ if (response.status === 204) {
33
+ onSuccess && onSuccess(response), onEnd && onEnd(response);
34
+ return;
35
+ }
36
+ return contentType?.startsWith("text/") ? await response.text().then((data) => (onData && onData(data), onSuccess && onSuccess(response), data)).catch((error) => {
37
+ throw onError && onError(error), error;
38
+ }).finally(() => {
39
+ onEnd && onEnd(response);
40
+ }) : contentType === "application/json" ? await response.json().then((data) => (onData && onData(data), onSuccess && onSuccess(response), data)).catch((error) => {
41
+ throw onError && onError(error), error;
42
+ }).finally(() => {
43
+ onEnd && onEnd(response);
44
+ }) : contentType === "application/stream+json" ? handleResponseStreamJson(response, options) : (onSuccess && onSuccess(response), onEnd && onEnd(response), response.body);
45
+ }
46
+ export {
47
+ handleResponseStreamJson as a,
48
+ handleResponse as h
49
+ };
50
+ //# sourceMappingURL=CKfJvIQ8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CKfJvIQ8.js","sources":["../../utils/handleResponseStreamJson.ts","../../utils/handleResponse.ts"],"sourcesContent":["import type { Awaitable } from '@unshared/functions/awaitable'\nimport type { RequestHooks } from './handleResponse'\nimport { awaitable } from '@unshared/functions/awaitable'\n\nasync function * createResponseStreamJsonIterator(response: Response, options: RequestHooks) {\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<T>(response: Response, options: RequestHooks): Awaitable<AsyncIterable<T>, T[]> {\n const responseIterator = createResponseStreamJsonIterator(response, options)\n return awaitable(responseIterator) as Awaitable<AsyncIterable<T>, T[]>\n}\n","import { handleResponseStreamJson } from './handleResponseStreamJson'\n\nexport interface RequestHooks {\n\n /**\n * The callback that is called when an error occurs during the request.\n */\n onError?: (error: Error) => any\n\n /**\n * The callback that is called when data is received from the request. This callback\n * will be called for each chunk of data that is received from the request.\n */\n onData?: (data: unknown) => any\n\n /**\n * The callback that is called when the request is successful. This callback will be\n * called after the request is complete and all data has been received.\n */\n onSuccess?: (response: Response) => any\n\n /**\n * The callback that is called when the status code is not OK. This callback will be called\n * after the request is complete and before the data is consumed.\n */\n onFailure?: (response: Response) => any\n\n /**\n * The callback that is called when the request is complete. This callback will be called\n * after the request is complete and all data has been received.\n */\n onEnd?: (response: Response) => any\n}\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: RequestHooks): 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":";AAIA,gBAAiB,iCAAiC,UAAoB,SAAuB;AAC3F,QAAM,EAAE,SAAS,WAAW,QAAQ,MAAU,IAAA;AAC1C,MAAA;AACF,UAAM,OAAO,SAAS;AACtB,QAAI,SAAS,KAAY,OAAA,IAAI,MAAM,gDAAgD;AAC7E,UAAA,SAAS,KAAK,UAAU;AACjB,eAAA;AACX,YAAM,EAAE,MAAM,MAAU,IAAA,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,YAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,KAAK,EAAE,KAAA,EAAO,MAAM,IAAI,EAAE,OAAO,OAAO;AAG/E,iBAAW,QAAQ,OAAO;AAClB,cAAA,UAAU,KAAK,MAAM,IAAI;AAC3B,kBAAQ,OAAO,OAAO,GAC1B,MAAM;AAAA,MAAA;AAAA,IACR;AAEE,iBAAW,UAAU,QAAQ;AAAA,WAE5B,OAAO;AACR,eAAS,QAAQ,KAAc;AAAA,EAAA,UAErC;AACM,aAAO,MAAM,QAAQ;AAAA,EAAA;AAE7B;AAWgB,SAAA,yBAA4B,UAAoB,SAAyD;AACjH,QAAA,mBAAmB,iCAAiC,UAAU,OAAO;AAC3E,SAAO,UAAU,gBAAgB;AACnC;ACDsB,eAAA,eAAe,UAAoB,SAAyC;AAChG,QAAM,EAAE,SAAS,WAAW,QAAQ,OAAO,UAAA,IAAc,SACnD,cAAc,SAAS,QAAQ,IAAI,cAAc;AAGvD,MAAI,CAAC,SAAS;AACR,UAAA,aAAW,UAAU,QAAQ,GAC7B,SAAO,MAAM,QAAQ,GACnB,IAAI,MAAM,SAAS,UAAU;AAIjC,MAAA,SAAS,WAAW,KAAK;AACvB,iBAAW,UAAU,QAAQ,GAC7B,SAAO,MAAM,QAAQ;AACzB;AAAA,EAAA;AAIE,SAAA,aAAa,WAAW,OAAO,IAC1B,MAAM,SAAS,KACnB,EAAA,KAAK,CAAC,UACD,UAAQ,OAAO,IAAI,GACnB,aAAW,UAAU,QAAQ,GAC1B,KACR,EACA,MAAM,CAAC,UAAiB;AACnB,UAAA,WAAS,QAAQ,KAAK,GACpB;AAAA,EAAA,CACP,EACA,QAAQ,MAAM;AACT,aAAO,MAAM,QAAQ;AAAA,EAAA,CAC1B,IAID,gBAAgB,qBACX,MAAM,SAAS,OACnB,KAAK,CAAC,UACD,UAAQ,OAAO,IAAI,GACnB,aAAW,UAAU,QAAQ,GAC1B,KACR,EACA,MAAM,CAAC,UAAiB;AACnB,UAAA,WAAS,QAAQ,KAAK,GACpB;AAAA,EAAA,CACP,EACA,QAAQ,MAAM;AACT,aAAO,MAAM,QAAQ;AAAA,EAAA,CAC1B,IAID,gBAAgB,4BACX,yBAAyB,UAAU,OAAO,KAG/C,aAAW,UAAU,QAAQ,GAC7B,SAAO,MAAM,QAAQ,GAClB,SAAS;AAClB;"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var awaitable = require("@unshared/functions/awaitable");
3
+ async function* createResponseStreamJsonIterator(response, options) {
4
+ const { onError, onSuccess, onData, onEnd } = options;
5
+ try {
6
+ const body = response.body;
7
+ if (body === null) throw new Error("Could not read the response body, it is empty.");
8
+ const reader = body.getReader();
9
+ for (; ; ) {
10
+ const { done, value } = await reader.read();
11
+ if (done) break;
12
+ const parts = new TextDecoder().decode(value).trim().split("\0").filter(Boolean);
13
+ for (const part of parts) {
14
+ const payload = JSON.parse(part);
15
+ onData && onData(payload), yield payload;
16
+ }
17
+ }
18
+ onSuccess && onSuccess(response);
19
+ } catch (error) {
20
+ onError && onError(error);
21
+ } finally {
22
+ onEnd && onEnd(response);
23
+ }
24
+ }
25
+ function handleResponseStreamJson(response, options) {
26
+ const responseIterator = createResponseStreamJsonIterator(response, options);
27
+ return awaitable.awaitable(responseIterator);
28
+ }
29
+ async function handleResponse(response, options) {
30
+ const { onError, onSuccess, onData, onEnd, onFailure } = options, contentType = response.headers.get("Content-Type");
31
+ if (!response.ok)
32
+ throw onFailure && onFailure(response), onEnd && onEnd(response), new Error(response.statusText);
33
+ if (response.status === 204) {
34
+ onSuccess && onSuccess(response), onEnd && onEnd(response);
35
+ return;
36
+ }
37
+ return contentType?.startsWith("text/") ? await response.text().then((data) => (onData && onData(data), onSuccess && onSuccess(response), data)).catch((error) => {
38
+ throw onError && onError(error), error;
39
+ }).finally(() => {
40
+ onEnd && onEnd(response);
41
+ }) : contentType === "application/json" ? await response.json().then((data) => (onData && onData(data), onSuccess && onSuccess(response), data)).catch((error) => {
42
+ throw onError && onError(error), error;
43
+ }).finally(() => {
44
+ onEnd && onEnd(response);
45
+ }) : contentType === "application/stream+json" ? handleResponseStreamJson(response, options) : (onSuccess && onSuccess(response), onEnd && onEnd(response), response.body);
46
+ }
47
+ exports.handleResponse = handleResponse;
48
+ exports.handleResponseStreamJson = handleResponseStreamJson;
49
+ //# sourceMappingURL=Cx8m1YzL.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Cx8m1YzL.cjs","sources":["../../utils/handleResponseStreamJson.ts","../../utils/handleResponse.ts"],"sourcesContent":["import type { Awaitable } from '@unshared/functions/awaitable'\nimport type { RequestHooks } from './handleResponse'\nimport { awaitable } from '@unshared/functions/awaitable'\n\nasync function * createResponseStreamJsonIterator(response: Response, options: RequestHooks) {\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<T>(response: Response, options: RequestHooks): Awaitable<AsyncIterable<T>, T[]> {\n const responseIterator = createResponseStreamJsonIterator(response, options)\n return awaitable(responseIterator) as Awaitable<AsyncIterable<T>, T[]>\n}\n","import { handleResponseStreamJson } from './handleResponseStreamJson'\n\nexport interface RequestHooks {\n\n /**\n * The callback that is called when an error occurs during the request.\n */\n onError?: (error: Error) => any\n\n /**\n * The callback that is called when data is received from the request. This callback\n * will be called for each chunk of data that is received from the request.\n */\n onData?: (data: unknown) => any\n\n /**\n * The callback that is called when the request is successful. This callback will be\n * called after the request is complete and all data has been received.\n */\n onSuccess?: (response: Response) => any\n\n /**\n * The callback that is called when the status code is not OK. This callback will be called\n * after the request is complete and before the data is consumed.\n */\n onFailure?: (response: Response) => any\n\n /**\n * The callback that is called when the request is complete. This callback will be called\n * after the request is complete and all data has been received.\n */\n onEnd?: (response: Response) => any\n}\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: RequestHooks): 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":["awaitable"],"mappings":";;AAIA,gBAAiB,iCAAiC,UAAoB,SAAuB;AAC3F,QAAM,EAAE,SAAS,WAAW,QAAQ,MAAU,IAAA;AAC1C,MAAA;AACF,UAAM,OAAO,SAAS;AACtB,QAAI,SAAS,KAAY,OAAA,IAAI,MAAM,gDAAgD;AAC7E,UAAA,SAAS,KAAK,UAAU;AACjB,eAAA;AACX,YAAM,EAAE,MAAM,MAAU,IAAA,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,YAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,KAAK,EAAE,KAAA,EAAO,MAAM,IAAI,EAAE,OAAO,OAAO;AAG/E,iBAAW,QAAQ,OAAO;AAClB,cAAA,UAAU,KAAK,MAAM,IAAI;AAC3B,kBAAQ,OAAO,OAAO,GAC1B,MAAM;AAAA,MAAA;AAAA,IACR;AAEE,iBAAW,UAAU,QAAQ;AAAA,WAE5B,OAAO;AACR,eAAS,QAAQ,KAAc;AAAA,EAAA,UAErC;AACM,aAAO,MAAM,QAAQ;AAAA,EAAA;AAE7B;AAWgB,SAAA,yBAA4B,UAAoB,SAAyD;AACjH,QAAA,mBAAmB,iCAAiC,UAAU,OAAO;AAC3E,SAAOA,UAAAA,UAAU,gBAAgB;AACnC;ACDsB,eAAA,eAAe,UAAoB,SAAyC;AAChG,QAAM,EAAE,SAAS,WAAW,QAAQ,OAAO,UAAA,IAAc,SACnD,cAAc,SAAS,QAAQ,IAAI,cAAc;AAGvD,MAAI,CAAC,SAAS;AACR,UAAA,aAAW,UAAU,QAAQ,GAC7B,SAAO,MAAM,QAAQ,GACnB,IAAI,MAAM,SAAS,UAAU;AAIjC,MAAA,SAAS,WAAW,KAAK;AACvB,iBAAW,UAAU,QAAQ,GAC7B,SAAO,MAAM,QAAQ;AACzB;AAAA,EAAA;AAIE,SAAA,aAAa,WAAW,OAAO,IAC1B,MAAM,SAAS,KACnB,EAAA,KAAK,CAAC,UACD,UAAQ,OAAO,IAAI,GACnB,aAAW,UAAU,QAAQ,GAC1B,KACR,EACA,MAAM,CAAC,UAAiB;AACnB,UAAA,WAAS,QAAQ,KAAK,GACpB;AAAA,EAAA,CACP,EACA,QAAQ,MAAM;AACT,aAAO,MAAM,QAAQ;AAAA,EAAA,CAC1B,IAID,gBAAgB,qBACX,MAAM,SAAS,OACnB,KAAK,CAAC,UACD,UAAQ,OAAO,IAAI,GACnB,aAAW,UAAU,QAAQ,GAC1B,KACR,EACA,MAAM,CAAC,UAAiB;AACnB,UAAA,WAAS,QAAQ,KAAK,GACpB;AAAA,EAAA,CACP,EACA,QAAQ,MAAM;AACT,aAAO,MAAM,QAAQ;AAAA,EAAA,CAC1B,IAID,gBAAgB,4BACX,yBAAyB,UAAU,OAAO,KAG/C,aAAW,UAAU,QAAQ,GAC7B,SAAO,MAAM,QAAQ,GAClB,SAAS;AAClB;;;"}
@@ -0,0 +1,30 @@
1
+ function getBaseUrl(specification) {
2
+ if ("servers" in specification && Array.isArray(specification.servers) && specification.servers.length > 0)
3
+ return specification.servers[0].url;
4
+ if ("host" in specification && typeof specification.host == "string") {
5
+ const scheme = specification.schemes && specification.schemes.length > 0 ? specification.schemes[0] : "https", basePath = specification.basePath && typeof specification.basePath == "string" ? specification.basePath : "/";
6
+ return `${scheme}://${specification.host}${basePath}`;
7
+ }
8
+ throw new Error("No base URL found in the OpenAPI specification.");
9
+ }
10
+ const methods = ["get", "put", "post", "delete", "options", "head", "patch"];
11
+ function getOperationById(specification, operationId) {
12
+ if (!specification || typeof specification != "object" || specification === null || !("paths" in specification) || typeof specification.paths != "object" || specification.paths === null)
13
+ throw new Error("Missing paths object in the OpenAPI specification.");
14
+ const paths = specification.paths;
15
+ for (const path in paths) {
16
+ const route = paths[path];
17
+ if (!(typeof route != "object" || route === null))
18
+ for (const method of methods) {
19
+ const operation = route[method];
20
+ if (!(!(method in route) || typeof operation != "object" || operation === null || !("operationId" in operation) || operation.operationId !== operationId))
21
+ return { ...route[method], method, path };
22
+ }
23
+ }
24
+ throw new Error(`Operation "${operationId}" not found in specification.`);
25
+ }
26
+ export {
27
+ getOperationById as a,
28
+ getBaseUrl as g
29
+ };
30
+ //# sourceMappingURL=D-WqCFul.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"D-WqCFul.js","sources":["../../openapi/getBaseUrl.ts","../../openapi/getOperationById.ts"],"sourcesContent":["import type { OpenAPI } from 'openapi-types'\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 getBaseUrl(specification: OpenAPI.Document): string {\n\n // --- Handle OpenAPI 3.0 specifications.\n if ('servers' in specification && Array.isArray(specification.servers) && specification.servers.length > 0)\n return specification.servers[0].url\n\n // --- Handle OpenAPI 2.0 specifications.\n if ('host' in specification && typeof specification.host === 'string') {\n const scheme = specification.schemes && specification.schemes.length > 0 ? specification.schemes[0] : 'https'\n const basePath = specification.basePath && typeof specification.basePath === 'string' ? specification.basePath : '/'\n return `${scheme}://${specification.host}${basePath}`\n }\n\n throw new Error('No base URL found in the OpenAPI specification.')\n}\n","import type { OpenAPI } from 'openapi-types'\nimport type { OpenAPIV2 } from './OpenApiV2'\n\n/** The HTTP methods supported by OpenAPI. */\nconst methods = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch'] as const\n\n/**\n * Given an OpenAPI specification, find an operation by its operationId.\n *\n * @param specification The OpenAPI specification.\n * @param operationId The operationId of the operation to resolve.\n * @returns The resolved operation.\n * @example openapiGetOperation(specification, 'getUser') // { method: 'get', path: '/users/{username}', ... }\n */\nexport function getOperationById<T, U extends OpenAPIV2.OperationId<T>>(\n specification: T,\n operationId: U,\n): OpenAPIV2.OperationById<T, U> {\n\n // --- Validate the specification.\n if (!specification\n || typeof specification !== 'object'\n || specification === null\n || 'paths' in specification === false\n || typeof specification.paths !== 'object'\n || specification.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 = specification.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 OpenAPIV2.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":"AASO,SAAS,WAAW,eAAyC;AAG9D,MAAA,aAAa,iBAAiB,MAAM,QAAQ,cAAc,OAAO,KAAK,cAAc,QAAQ,SAAS;AAChG,WAAA,cAAc,QAAQ,CAAC,EAAE;AAGlC,MAAI,UAAU,iBAAiB,OAAO,cAAc,QAAS,UAAU;AAC/D,UAAA,SAAS,cAAc,WAAW,cAAc,QAAQ,SAAS,IAAI,cAAc,QAAQ,CAAC,IAAI,SAChG,WAAW,cAAc,YAAY,OAAO,cAAc,YAAa,WAAW,cAAc,WAAW;AACjH,WAAO,GAAG,MAAM,MAAM,cAAc,IAAI,GAAG,QAAQ;AAAA,EAAA;AAG/C,QAAA,IAAI,MAAM,iDAAiD;AACnE;ACnBA,MAAM,UAAU,CAAC,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,OAAO;AAU3D,SAAA,iBACd,eACA,aAC+B;AAG/B,MAAI,CAAC,iBACA,OAAO,iBAAkB,YACzB,kBAAkB,QAClB,EAAW,WAAA,kBACX,OAAO,cAAc,SAAU,YAC/B,cAAc,UAAU;AACrB,UAAA,IAAI,MAAM,oDAAoD;AAGtE,QAAM,QAAQ,cAAc;AAC5B,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;"}
@@ -24,14 +24,13 @@ function toFormData(object) {
24
24
  }
25
25
  function parseRequestBody(route, options, context) {
26
26
  const { data, body = data } = options, { init } = context;
27
- init.headers = init.headers ?? {}, !["get", "head", "delete"].includes(init.method ?? "get") && body != null && (isFormDataLike(body) ? (init.body = toFormData(body), init.headers = { ...init.headers, "Content-Type": "multipart/form-data" }) : body instanceof ReadableStream ? init.body = body : body instanceof File ? (init.body = body.stream(), init.headers = { ...init.headers, "Content-Type": "application/octet-stream" }) : isObjectLike(body) ? (init.body = JSON.stringify(body), init.headers = { ...init.headers, "Content-Type": "application/json" }) : init.body = body);
27
+ ["get", "head", "delete"].includes(init.method ?? "get") || body != null && (isFormDataLike(body) ? (init.body = toFormData(body), init.headers = init.headers ?? {}, init.headers = { ...init.headers, "Content-Type": "multipart/form-data" }) : body instanceof ReadableStream ? init.body = body : body instanceof File ? (init.body = body.stream(), init.headers = init.headers ?? {}, init.headers = { ...init.headers, "Content-Type": "application/octet-stream" }) : isObjectLike(body) ? (init.body = JSON.stringify(body), init.headers = init.headers ?? {}, init.headers = { ...init.headers, "Content-Type": "application/json" }) : init.body = body);
28
28
  }
29
29
  function parseRequestHeaders(route, options, context) {
30
30
  const { headers = {} } = options, { init } = context;
31
- init.headers = init.headers ?? {};
32
31
  for (const key in headers) {
33
32
  const value = headers[key];
34
- value !== void 0 && typeof value == "string" && (init.headers = { ...init.headers, [key]: value });
33
+ value !== void 0 && typeof value == "string" && (init.headers = init.headers ?? {}, init.headers = { ...init.headers, [key]: value });
35
34
  }
36
35
  }
37
36
  const EXP_PATH_PARAMETER = /:([\w-]+)|%7B([\w-]+)%7D/g;
@@ -39,17 +38,11 @@ function parseRequestParameters(route, options, context) {
39
38
  const { url } = context, { data, parameters = {} } = options;
40
39
  if (!url) throw new Error("Could not resolve the `RequestInit` object: the `url` is missing.");
41
40
  const pathParameters = url.pathname.match(EXP_PATH_PARAMETER);
42
- if (pathParameters) {
43
- if (isObjectLike(data))
44
- for (const key in data) {
45
- const value = data[key];
46
- value !== void 0 && typeof value == "string" && parameters[key] === void 0 && (parameters[key] = value, delete data[key]);
47
- }
41
+ if (pathParameters)
48
42
  for (const parameter of pathParameters.values()) {
49
43
  const key = parameter.replaceAll(EXP_PATH_PARAMETER, "$1$2"), value = parameters[key];
50
- value !== void 0 && typeof value == "string" && (url.pathname = url.pathname.replace(parameter, value));
44
+ value !== void 0 && typeof value == "string" ? url.pathname = url.pathname.replace(parameter, value) : isObjectLike(data) && data[key] !== void 0 && typeof data[key] == "string" && (url.pathname = url.pathname.replace(parameter, data[key]), delete data[key]);
51
45
  }
52
- }
53
46
  }
54
47
  function toSearchParams(object, options = {}) {
55
48
  const { searchArrayFormat = "flat" } = options, search = new URLSearchParams();
@@ -85,7 +78,7 @@ function parseRequestUrl(route, options, context) {
85
78
  if (!METHODS.has(methodLower)) throw new Error(`Could not resolve the \`RequestInit\` object:, the method \`${routeMethod}\` is invalid.`);
86
79
  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;
87
80
  }
88
- function parseRequest(route, options = {}) {
81
+ function parseRequest(route, options) {
89
82
  const { data, body, query, headers, parameters, baseUrl, method, searchArrayFormat, ...requestInit } = options, context = { init: requestInit };
90
83
  return parseRequestUrl(route, { baseUrl, method }, context), parseRequestParameters(route, { data, parameters }, context), parseRequestQuery(route, { data, query, searchArrayFormat }, context), parseRequestBody(route, { data, body }, context), parseRequestHeaders(route, { headers }, context), context;
91
84
  }
@@ -99,4 +92,4 @@ exports.parseRequestQuery = parseRequestQuery;
99
92
  exports.parseRequestUrl = parseRequestUrl;
100
93
  exports.toFormData = toFormData;
101
94
  exports.toSearchParams = toSearchParams;
102
- //# sourceMappingURL=Bul9W_0Q.cjs.map
95
+ //# sourceMappingURL=D8Tsm7xC.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"D8Tsm7xC.cjs","sources":["../../utils/isFormDataLike.ts","../../utils/isObjectLike.ts","../../utils/toFormData.ts","../../utils/parseRequestBody.ts","../../utils/parseRequestHeaders.ts","../../utils/parseRequestParameters.ts","../../utils/toSearchParams.ts","../../utils/parseRequestQuery.ts","../../utils/parseRequestUrl.ts","../../utils/parseRequest.ts"],"sourcesContent":["/**\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","/**\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 Record<string, unknown> {\n return typeof value === 'object' && value !== null && value.constructor === Object\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 { RequestContext, RequestOptions } 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 route The route path.\n * @param options The request options.\n * @param context The request context.\n */\nexport function parseRequestBody(route: string, options: Pick<RequestOptions, 'body' | 'data'>, context: RequestContext): void {\n const { data, body = data } = options\n const { init } = context\n\n // --- If the method is `GET`, `HEAD`, or `DELETE`, return early.\n if (['get', 'head', 'delete'].includes(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 init.body = toFormData(body)\n init.headers = init.headers ?? {}\n init.headers = { ...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 init.body = body\n }\n\n // --- If the data is a Blob, pass it directly to the body.\n else if (body instanceof File) {\n init.body = body.stream()\n init.headers = init.headers ?? {}\n init.headers = { ...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 init.body = JSON.stringify(body)\n init.headers = init.headers ?? {}\n init.headers = { ...init.headers, 'Content-Type': 'application/json' }\n }\n\n // --- For all other data types, set the body directly.\n else {\n init.body = body\n }\n}\n","import type { RequestContext, RequestOptions } from './parseRequest'\n\n/**\n * Parse the request headers based on the provided data and options.\n *\n * @param route The route path.\n * @param options The request options.\n * @param context The request context.\n */\nexport function parseRequestHeaders(route: string, options: Pick<RequestOptions, 'headers'>, context: RequestContext): void {\n const { headers = {} } = options\n const { init } = context\n\n // --- Merge the headers with the existing headers.\n for (const key in headers) {\n const value = headers[key]\n if (value === undefined) continue\n if (typeof value !== 'string') continue\n init.headers = init.headers ?? {}\n init.headers = { ...init.headers, [key]: value }\n }\n}\n","import type { RequestContext, RequestOptions } from './parseRequest'\nimport { isObjectLike } from './isObjectLike'\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 append\n * the path parameters to the URL based on the method and the data provided.\n *\n * @param route The name of the route to fetch. (ignored)\n * @param options The options to pass to the request.\n * @param context The request context to modify.\n * @example\n * // Using `express` style path parameters.\n * parseRequestParameters('GET /users/:id', { data: { id: 1 } }, context)\n *\n * // Using `OpenAPI` style path parameters.\n * parseRequestParameters('GET /users/{id}', { data: { id: 1 } }, context)\n */\nexport function parseRequestParameters(route: string, options: Pick<RequestOptions, 'data' | 'parameters'>, context: RequestContext): void {\n const { url } = context\n const { data, parameters = {} } = options\n\n // --- If the method has a parameter, fill the path with the data.\n if (!url) throw new Error('Could not resolve the `RequestInit` object: the `url` is missing.')\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\n // --- If the parameter is provided, replace the path with the value.\n const value = parameters[key]\n if (value !== undefined && typeof value === 'string') {\n url.pathname = url.pathname.replace(parameter, value)\n }\n\n // --- If the data contains the parameter, use it and remove it from the data.\n else if (isObjectLike(data) && data[key] !== undefined && typeof data[key] === 'string') {\n url.pathname = url.pathname.replace(parameter, data[key])\n delete data[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 searchArrayFormat?: 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 { searchArrayFormat = '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 (searchArrayFormat === 'brackets') for (const v of value) search.append(`${key}[]`, String(v))\n else if (searchArrayFormat === 'indices') for (const [i, v] of value.entries()) search.append(`${key}[${i}]`, String(v))\n else if (searchArrayFormat === 'comma') search.append(key, value.join(','))\n else if (searchArrayFormat === 'path') for (const [i, v] of value.entries()) search.append(`${key}.${i}`, String(v))\n else if (searchArrayFormat === '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 { RequestContext, RequestOptions } from './parseRequest'\nimport { isObjectLike } from './isObjectLike'\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 route The name of the route to fetch. (ignored)\n * @param options The options to pass to the request.\n * @param context The request context to modify.\n */\nexport function parseRequestQuery(route: string, options: Pick<RequestOptions, 'data' | 'query' | 'searchArrayFormat'>, context: RequestContext): void {\n const { url, init } = context\n const { data, query = {}, searchArrayFormat } = options\n if (!url) throw new Error('Could not resolve the `RequestInit` object: the `url` is missing.')\n\n // --- Append the `data` to the query parameters if the method does not expect a body.\n const isExpectingBody = ['post', 'put', 'patch'].includes(init.method ?? 'get')\n if (!isExpectingBody && isObjectLike(data)) {\n for (const key in data) {\n if (data[key] === undefined) continue\n if (query[key] !== undefined) continue\n // @ts-expect-error: Ignore type mismatch.\n query[key] = data[key]\n delete data[key]\n }\n }\n\n // --- Apply the query parameters to the URL.\n url.search = toSearchParams(query, { searchArrayFormat }).toString()\n}\n","import type { RequestContext, RequestOptions } 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 route The name of the route to fetch.\n * @param options The options to pass to the request.\n * @param context The request context to modify.\n * @example parseRequestUrl('GET /users', { baseUrl: 'https://api.example.com' }, context)\n */\nexport function parseRequestUrl(route: string, options: Pick<RequestOptions, 'baseUrl' | 'method'>, context: RequestContext): 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","/* eslint-disable unicorn/prevent-abbreviations */\nimport type { MaybeLiteral } from '@unshared/types'\nimport type { Override } from '@unshared/types'\nimport type { HttpHeader, HttpMethod } from '../types'\nimport type { SearchArrayFormat, SearchParamsObject } from './toSearchParams'\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 RequestMethod = Lowercase<keyof typeof HttpMethod> | Uppercase<keyof typeof HttpMethod>\n\n/** Headers to include in the request. */\nexport type RequestHeaders = Partial<Record<MaybeLiteral<HttpHeader>, string>>\n\n/** The types of data that can be passed to the request. */\nexport type RequestBody = File | FormData | ReadableStream | Record<string, unknown> | string\n\n/** Options to pass to the request. */\nexport type RequestOptions = Override<RequestInit, {\n\n /**\n * The method to use for the request.\n *\n * @example 'GET'\n */\n method?: RequestMethod\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?: string\n\n /**\n * The data to pass to the request. This data will be used to fill the path\n * parameters, query parameters, body, and form data of the request based on\n * the route method.\n */\n data?: RequestBody\n\n /**\n * The body to include in the request.\n */\n body?: RequestBody\n\n /**\n * The headers to include in the request.\n */\n headers?: RequestHeaders\n\n /**\n * Query parameters to include in the request.\n */\n query?: SearchParamsObject\n\n /**\n * The format to use when serializing the query parameters.\n */\n searchArrayFormat?: SearchArrayFormat\n\n /**\n * The path parameters to include in the request.\n */\n parameters?: Record<string, number | string>\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: RequestOptions): RequestContext {\n const { data, body, query, headers, parameters, baseUrl, method, searchArrayFormat, ...requestInit } = options\n const context: RequestContext = { init: requestInit }\n parseRequestUrl(route, { baseUrl, method }, context)\n parseRequestParameters(route, { data, parameters }, context)\n parseRequestQuery(route, { data, query, searchArrayFormat }, context)\n parseRequestBody(route, { data, body }, context)\n parseRequestHeaders(route, { headers }, context)\n return context\n}\n"],"names":[],"mappings":"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"}
@@ -148,6 +148,8 @@ interface ToSearchParamsOptions {
148
148
  */
149
149
  declare function toSearchParams(object: SearchParamsObject, options?: ToSearchParamsOptions): URLSearchParams;
150
150
 
151
+ /** The methods to use for the request. */
152
+ type RequestMethod = Lowercase<keyof typeof HttpMethod> | Uppercase<keyof typeof HttpMethod>;
151
153
  /** Headers to include in the request. */
152
154
  type RequestHeaders = Partial<Record<MaybeLiteral<HttpHeader>, string>>;
153
155
  /** The types of data that can be passed to the request. */
@@ -159,7 +161,7 @@ type RequestOptions = Override<RequestInit, {
159
161
  *
160
162
  * @example 'GET'
161
163
  */
162
- method?: Lowercase<keyof typeof HttpMethod> | Uppercase<keyof typeof HttpMethod>;
164
+ method?: RequestMethod;
163
165
  /**
164
166
  * The base URL to use for the request. This URL will be used to resolve the
165
167
  * path and query parameters of the request.
@@ -206,6 +208,6 @@ interface RequestContext {
206
208
  * @param options The options to pass to the request.
207
209
  * @returns The URL and the `RequestInit` object.
208
210
  */
209
- declare function parseRequest(route: string, options?: RequestOptions): RequestContext;
211
+ declare function parseRequest(route: string, options: RequestOptions): RequestContext;
210
212
 
211
- export { HttpMethod as H, type RequestHeaders as R, type SearchParamsObject as S, type ToSearchParamsOptions as T, type RequestBody as a, type RequestOptions as b, type RequestContext as c, type SearchArrayFormat as d, parseRequest as p, toSearchParams as t };
213
+ export { HttpMethod as H, type RequestMethod as R, type SearchParamsObject as S, type ToSearchParamsOptions as T, type RequestHeaders as a, type RequestBody as b, type RequestOptions as c, type RequestContext as d, type SearchArrayFormat as e, parseRequest as p, toSearchParams as t };
@@ -0,0 +1,38 @@
1
+ interface RequestHooks {
2
+ /**
3
+ * The callback that is called when an error occurs during the request.
4
+ */
5
+ onError?: (error: Error) => any;
6
+ /**
7
+ * The callback that is called when data is received from the request. This callback
8
+ * will be called for each chunk of data that is received from the request.
9
+ */
10
+ onData?: (data: unknown) => any;
11
+ /**
12
+ * The callback that is called when the request is successful. This callback will be
13
+ * called after the request is complete and all data has been received.
14
+ */
15
+ onSuccess?: (response: Response) => any;
16
+ /**
17
+ * The callback that is called when the status code is not OK. This callback will be called
18
+ * after the request is complete and before the data is consumed.
19
+ */
20
+ onFailure?: (response: Response) => any;
21
+ /**
22
+ * The callback that is called when the request is complete. This callback will be called
23
+ * after the request is complete and all data has been received.
24
+ */
25
+ onEnd?: (response: Response) => any;
26
+ }
27
+ /**
28
+ * Handle a request response. This function will parse the response based on the content type and
29
+ * return the data. If an error occurs, the `onError` callback will be called and the function will
30
+ * throw an error.
31
+ *
32
+ * @param response The response to handle.
33
+ * @param options The options to pass to the request.
34
+ * @returns The parsed data from the response.
35
+ */
36
+ declare function handleResponse(response: Response, options: RequestHooks): Promise<unknown>;
37
+
38
+ export { type RequestHooks as R, handleResponse as h };
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ function getBaseUrl(specification) {
3
+ if ("servers" in specification && Array.isArray(specification.servers) && specification.servers.length > 0)
4
+ return specification.servers[0].url;
5
+ if ("host" in specification && typeof specification.host == "string") {
6
+ const scheme = specification.schemes && specification.schemes.length > 0 ? specification.schemes[0] : "https", basePath = specification.basePath && typeof specification.basePath == "string" ? specification.basePath : "/";
7
+ return `${scheme}://${specification.host}${basePath}`;
8
+ }
9
+ throw new Error("No base URL found in the OpenAPI specification.");
10
+ }
11
+ const methods = ["get", "put", "post", "delete", "options", "head", "patch"];
12
+ function getOperationById(specification, operationId) {
13
+ if (!specification || typeof specification != "object" || specification === null || !("paths" in specification) || typeof specification.paths != "object" || specification.paths === null)
14
+ throw new Error("Missing paths object in the OpenAPI specification.");
15
+ const paths = specification.paths;
16
+ for (const path in paths) {
17
+ const route = paths[path];
18
+ if (!(typeof route != "object" || route === null))
19
+ for (const method of methods) {
20
+ const operation = route[method];
21
+ if (!(!(method in route) || typeof operation != "object" || operation === null || !("operationId" in operation) || operation.operationId !== operationId))
22
+ return { ...route[method], method, path };
23
+ }
24
+ }
25
+ throw new Error(`Operation "${operationId}" not found in specification.`);
26
+ }
27
+ exports.getBaseUrl = getBaseUrl;
28
+ exports.getOperationById = getOperationById;
29
+ //# sourceMappingURL=xRZPkxch.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xRZPkxch.cjs","sources":["../../openapi/getBaseUrl.ts","../../openapi/getOperationById.ts"],"sourcesContent":["import type { OpenAPI } from 'openapi-types'\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 getBaseUrl(specification: OpenAPI.Document): string {\n\n // --- Handle OpenAPI 3.0 specifications.\n if ('servers' in specification && Array.isArray(specification.servers) && specification.servers.length > 0)\n return specification.servers[0].url\n\n // --- Handle OpenAPI 2.0 specifications.\n if ('host' in specification && typeof specification.host === 'string') {\n const scheme = specification.schemes && specification.schemes.length > 0 ? specification.schemes[0] : 'https'\n const basePath = specification.basePath && typeof specification.basePath === 'string' ? specification.basePath : '/'\n return `${scheme}://${specification.host}${basePath}`\n }\n\n throw new Error('No base URL found in the OpenAPI specification.')\n}\n","import type { OpenAPI } from 'openapi-types'\nimport type { OpenAPIV2 } from './OpenApiV2'\n\n/** The HTTP methods supported by OpenAPI. */\nconst methods = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch'] as const\n\n/**\n * Given an OpenAPI specification, find an operation by its operationId.\n *\n * @param specification The OpenAPI specification.\n * @param operationId The operationId of the operation to resolve.\n * @returns The resolved operation.\n * @example openapiGetOperation(specification, 'getUser') // { method: 'get', path: '/users/{username}', ... }\n */\nexport function getOperationById<T, U extends OpenAPIV2.OperationId<T>>(\n specification: T,\n operationId: U,\n): OpenAPIV2.OperationById<T, U> {\n\n // --- Validate the specification.\n if (!specification\n || typeof specification !== 'object'\n || specification === null\n || 'paths' in specification === false\n || typeof specification.paths !== 'object'\n || specification.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 = specification.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 OpenAPIV2.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":";AASO,SAAS,WAAW,eAAyC;AAG9D,MAAA,aAAa,iBAAiB,MAAM,QAAQ,cAAc,OAAO,KAAK,cAAc,QAAQ,SAAS;AAChG,WAAA,cAAc,QAAQ,CAAC,EAAE;AAGlC,MAAI,UAAU,iBAAiB,OAAO,cAAc,QAAS,UAAU;AAC/D,UAAA,SAAS,cAAc,WAAW,cAAc,QAAQ,SAAS,IAAI,cAAc,QAAQ,CAAC,IAAI,SAChG,WAAW,cAAc,YAAY,OAAO,cAAc,YAAa,WAAW,cAAc,WAAW;AACjH,WAAO,GAAG,MAAM,MAAM,cAAc,IAAI,GAAG,QAAQ;AAAA,EAAA;AAG/C,QAAA,IAAI,MAAM,iDAAiD;AACnE;ACnBA,MAAM,UAAU,CAAC,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,OAAO;AAU3D,SAAA,iBACd,eACA,aAC+B;AAG/B,MAAI,CAAC,iBACA,OAAO,iBAAkB,YACzB,kBAAkB,QAClB,EAAW,WAAA,kBACX,OAAO,cAAc,SAAU,YAC/B,cAAc,UAAU;AACrB,UAAA,IAAI,MAAM,oDAAoD;AAGtE,QAAM,QAAQ,cAAc;AAC5B,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,20 +1,16 @@
1
1
  "use strict";
2
- var fetch = require("./fetch.cjs"), index = require("./chunks/BzqHK4CV.cjs");
3
- require("./chunks/Bul9W_0Q.cjs");
2
+ var fetch = require("./fetch.cjs"), getOperationById = require("./chunks/xRZPkxch.cjs"), handleResponse = require("./chunks/Cx8m1YzL.cjs");
3
+ require("./chunks/D8Tsm7xC.cjs");
4
+ require("@unshared/functions/awaitable");
4
5
  function createClient(documentOrUrl, initialOptions = {}) {
5
6
  const specifications = typeof documentOrUrl == "string" ? void 0 : documentOrUrl;
6
7
  typeof documentOrUrl == "string" && (initialOptions.baseUrl = documentOrUrl);
7
8
  async function fetchByOperationId(operationId, options) {
8
9
  if (!specifications) throw new Error("No OpenAPI specification provided.");
9
- const operation = index.getOperationById(specifications, operationId);
10
+ const operation = getOperationById.getOperationById(specifications, operationId);
10
11
  if (!operation) throw new Error(`Operation ID "${operationId}" not found.`);
11
- const { method, path, responses = {} } = operation, response = await fetch.fetch(path, {
12
- method,
13
- baseUrl: index.getBaseUrl(specifications),
14
- ...initialOptions,
15
- ...options
16
- });
17
- if (response.ok) return response.json();
12
+ const { method, path, responses = {} } = operation, fetchOptions = { method, baseUrl: getOperationById.getBaseUrl(specifications), ...initialOptions, ...options }, response = await fetch.fetch(path, fetchOptions);
13
+ if (response.ok) return handleResponse.handleResponse(response, fetchOptions);
18
14
  const status = response.status.toString();
19
15
  throw status in responses && typeof responses[status] == "object" && responses[status] !== null && "description" in responses[status] && typeof responses[status].description == "string" ? new Error(responses[status].description) : new Error(response.statusText);
20
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createClient.cjs","sources":["../createClient.ts"],"sourcesContent":["import type { MaybeLiteral, Override, Pretty } from '@unshared/types'\nimport type { OpenAPI, OpenAPIV2 as V2, OpenAPIV3 as V3, OpenAPIV3_1 as V3_1 } from 'openapi-types'\nimport type { RequestOptions } from './utils/index'\nimport { fetch } from './fetch'\nimport { getOperationById } from './openapi/getOperationById'\nimport { getBaseUrl, type OpenAPIV2, type OpenAPIV3 } from './openapi/index'\n\ntype ClientBaseUrl<T> =\n MaybeLiteral<\n T extends V2.Document ? OpenAPIV2.ServerUrl<T>\n : T extends V3.Document ? OpenAPIV3.ServerUrl<T>\n : T extends V3_1.Document ? OpenAPIV3.ServerUrl<T>\n : string\n >\n\ntype ClientFetch<T> =\n T extends V2.Document ? <P extends OpenAPIV2.Route<T>>(name: P, options: OpenAPIV2.RequestInit<T, OpenAPIV2.OperationByRoute<T, P>>) => Promise<OpenAPIV2.Response<OpenAPIV2.OperationByRoute<T, P>>>\n : T extends V3.Document ? <P extends OpenAPIV2.Route<T>>(name: P, options: OpenAPIV3.RequestInit<T, OpenAPIV2.OperationByRoute<T, P>>) => Promise<OpenAPIV3.Response<OpenAPIV2.OperationByRoute<T, P>>>\n : T extends V3_1.Document ? <P extends OpenAPIV2.Route<T>>(name: P, options: OpenAPIV3.RequestInit<T, OpenAPIV2.OperationByRoute<T, P>>) => Promise<OpenAPIV3.Response<OpenAPIV2.OperationByRoute<T, P>>>\n : typeof globalThis.fetch\n\ntype ClientFetchOperation<T, U extends OpenAPIV2.OperationId<T>> =\n T extends V2.Document ? (options: OpenAPIV2.RequestInit<T, OpenAPIV2.OperationById<T, U>>) => Promise<OpenAPIV2.ResponseBody<OpenAPIV2.OperationById<T, U>>>\n : T extends V3.Document ? (options: OpenAPIV3.RequestInit<T, OpenAPIV2.OperationById<T, U>>) => Promise<OpenAPIV3.ResponseBody<OpenAPIV2.OperationById<T, U>>>\n : T extends V3_1.Document ? (options: OpenAPIV3.RequestInit<T, OpenAPIV2.OperationById<T, U>>) => Promise<OpenAPIV3.ResponseBody<OpenAPIV2.OperationById<T, U>>>\n : (options: RequestOptions) => Promise<Response>\n\nexport type Client<T = OpenAPI.Document> =\n Pretty<\n & { [K in OpenAPIV2.OperationId<T>]: ClientFetchOperation<T, K> }\n & { fetch: ClientFetch<T> }\n >\n\nexport type ClientOptions<T = any> = Pretty<Override<RequestOptions, {\n baseUrl?: ClientBaseUrl<T>\n\n /**\n * The headers to include in every request made by the client.\n *\n * @example { 'Authorization': 'Bearer ...' }\n */\n headers?: T extends V3.Document\n ? OpenAPIV3.ServerHeaders<T>\n : Record<string, string>\n}>>\n\n/**\n * Create a new client instance for the given OpenAPI specification.\n *\n * @param document The OpenAPI specification document.\n * @param initialOptions The initial options to use for every request.\n * @returns The client instance.\n * @example\n * const client = createClient(document)\n * await client.fetch({ ... })\n */\n// @ts-expect-error: `ClientOptions` is not assignable to `ClientOptions<T>`.\nexport function createClient<T extends OpenAPI.Document>(document: Readonly<T>, initialOptions?: ClientOptions<T>): Client<T>\nexport function createClient<T extends OpenAPI.Document>(url: ClientBaseUrl<T>, initialOptions?: ClientOptions<T>): Client<T>\nexport function createClient(documentOrUrl: Readonly<OpenAPI.Document> | string, initialOptions: ClientOptions = {}): Client {\n const specifications = typeof documentOrUrl === 'string' ? undefined : documentOrUrl\n\n if (typeof documentOrUrl === 'string')\n initialOptions.baseUrl = documentOrUrl\n\n async function fetchByOperationId(operationId: string, options: ClientOptions<any>) {\n if (!specifications) throw new Error('No OpenAPI specification provided.')\n const operation = getOperationById(specifications, operationId) as { method: string; path: string } & OpenAPI.Operation\n if (!operation) throw new Error(`Operation ID \"${operationId}\" not found.`)\n const { method, path, responses = {} } = operation\n const response = await fetch(path, {\n method,\n baseUrl: getBaseUrl(specifications),\n ...initialOptions,\n ...options,\n })\n\n // --- Return the JSON response if successful.\n if (response.ok) return response.json() as Promise<unknown>\n\n // --- Throw an error if the response was not successful.\n const status = response.status.toString()\n if (status in responses\n && typeof responses[status] === 'object'\n && responses[status] !== null\n && 'description' in responses[status]\n && typeof responses[status].description === 'string')\n throw new Error(responses[status].description)\n\n // --- Throw a generic error if the response was not successful.\n throw new Error(response.statusText)\n }\n\n return new Proxy({}, {\n get(_, property: string) {\n if (property === 'fetch') return (route: string, options: RequestOptions) => fetch(route, ({ ...initialOptions, ...options }))\n return (options: Record<string, unknown>) => fetchByOperationId(property, options)\n },\n }) as unknown as Client\n}\n"],"names":["getOperationById","fetch","getBaseUrl"],"mappings":";;;AA2DO,SAAS,aAAa,eAAoD,iBAAgC,IAAY;AAC3H,QAAM,iBAAiB,OAAO,iBAAkB,WAAW,SAAY;AAEnE,SAAO,iBAAkB,aAC3B,eAAe,UAAU;AAEZ,iBAAA,mBAAmB,aAAqB,SAA6B;AAClF,QAAI,CAAC,eAAsB,OAAA,IAAI,MAAM,oCAAoC;AACnE,UAAA,YAAYA,MAAAA,iBAAiB,gBAAgB,WAAW;AAC9D,QAAI,CAAC,UAAW,OAAM,IAAI,MAAM,iBAAiB,WAAW,cAAc;AACpE,UAAA,EAAE,QAAQ,MAAM,YAAY,CAAA,MAAO,WACnC,WAAW,MAAMC,MAAA,MAAM,MAAM;AAAA,MACjC;AAAA,MACA,SAASC,iBAAW,cAAc;AAAA,MAClC,GAAG;AAAA,MACH,GAAG;AAAA,IAAA,CACJ;AAGD,QAAI,SAAS,GAAW,QAAA,SAAS,KAAK;AAGhC,UAAA,SAAS,SAAS,OAAO,SAAS;AACxC,UAAI,UAAU,aACT,OAAO,UAAU,MAAM,KAAM,YAC7B,UAAU,MAAM,MAAM,QACtB,iBAAiB,UAAU,MAAM,KACjC,OAAO,UAAU,MAAM,EAAE,eAAgB,WACtC,IAAI,MAAM,UAAU,MAAM,EAAE,WAAW,IAGzC,IAAI,MAAM,SAAS,UAAU;AAAA,EAAA;AAG9B,SAAA,IAAI,MAAM,IAAI;AAAA,IACnB,IAAI,GAAG,UAAkB;AACvB,aAAI,aAAa,UAAgB,CAAC,OAAe,YAA4BD,MAAA,MAAM,OAAQ,EAAE,GAAG,gBAAgB,GAAG,SAAU,IACtH,CAAC,YAAqC,mBAAmB,UAAU,OAAO;AAAA,IAAA;AAAA,EACnF,CACD;AACH;;"}
1
+ {"version":3,"file":"createClient.cjs","sources":["../createClient.ts"],"sourcesContent":["import type { MaybeLiteral, Override, Pretty } from '@unshared/types'\nimport type { OpenAPI, OpenAPIV2 as V2, OpenAPIV3 as V3, OpenAPIV3_1 as V3_1 } from 'openapi-types'\nimport type { OpenAPIV2, OpenAPIV3 } from './openapi/index'\nimport type { RequestHooks } from './utils/handleResponse'\nimport type { RequestHeaders, RequestMethod, RequestOptions } from './utils/parseRequest'\nimport { fetch } from './fetch'\nimport { getBaseUrl } from './openapi/getBaseUrl'\nimport { getOperationById } from './openapi/getOperationById'\nimport { handleResponse } from './utils/handleResponse'\n\ntype ClientBaseUrl<T> =\n MaybeLiteral<\n T extends V2.Document ? OpenAPIV2.ServerUrl<T>\n : T extends V3.Document ? OpenAPIV3.ServerUrl<T>\n : T extends V3_1.Document ? OpenAPIV3.ServerUrl<T>\n : string\n >\n\ntype ClientFetch<T> =\n T extends V2.Document ? <P extends OpenAPIV2.Route<T>>(name: P, options: OpenAPIV2.RequestInit<T, OpenAPIV2.OperationByRoute<T, P>>) => Promise<OpenAPIV2.Response<OpenAPIV2.OperationByRoute<T, P>>>\n : T extends V3.Document ? <P extends OpenAPIV2.Route<T>>(name: P, options: OpenAPIV3.RequestInit<T, OpenAPIV2.OperationByRoute<T, P>>) => Promise<OpenAPIV3.Response<OpenAPIV2.OperationByRoute<T, P>>>\n : T extends V3_1.Document ? <P extends OpenAPIV2.Route<T>>(name: P, options: OpenAPIV3.RequestInit<T, OpenAPIV2.OperationByRoute<T, P>>) => Promise<OpenAPIV3.Response<OpenAPIV2.OperationByRoute<T, P>>>\n : typeof globalThis.fetch\n\ntype ClientFetchOperation<T, U extends OpenAPIV2.OperationId<T>> =\n T extends V2.Document ? (options: OpenAPIV2.RequestInit<T, OpenAPIV2.OperationById<T, U>>) => Promise<OpenAPIV2.ResponseBody<OpenAPIV2.OperationById<T, U>>>\n : T extends V3.Document ? (options: OpenAPIV3.RequestInit<T, OpenAPIV2.OperationById<T, U>>) => Promise<OpenAPIV3.ResponseBody<OpenAPIV2.OperationById<T, U>>>\n : T extends V3_1.Document ? (options: OpenAPIV3.RequestInit<T, OpenAPIV2.OperationById<T, U>>) => Promise<OpenAPIV3.ResponseBody<OpenAPIV2.OperationById<T, U>>>\n : (options: RequestOptions) => Promise<Response>\n\nexport type Client<T = OpenAPI.Document> =\n Pretty<\n & { [K in OpenAPIV2.OperationId<T>]: ClientFetchOperation<T, K> }\n & { fetch: ClientFetch<T> }\n >\n\nexport type ClientOptions<T = any> = Override<RequestHooks & RequestOptions, {\n baseUrl?: ClientBaseUrl<T>\n\n /**\n * The headers to include in every request made by the client.\n *\n * @example { 'Authorization': 'Bearer ...' }\n */\n headers?: T extends V3.Document\n ? OpenAPIV3.ServerHeaders<T>\n : RequestHeaders\n}>\n\n/**\n * Create a new client instance for the given OpenAPI specification.\n *\n * @param document The OpenAPI specification document.\n * @param initialOptions The initial options to use for every request.\n * @returns The client instance.\n * @example\n * const client = createClient(document)\n * await client.fetch({ ... })\n */\n// @ts-expect-error: `ClientOptions` is not assignable to `ClientOptions<T>`.\nexport function createClient<T extends OpenAPI.Document>(document: Readonly<T>, initialOptions?: ClientOptions<T>): Client<T>\nexport function createClient<T extends OpenAPI.Document>(url: ClientBaseUrl<T>, initialOptions?: ClientOptions<T>): Client<T>\nexport function createClient(documentOrUrl: Readonly<OpenAPI.Document> | string, initialOptions: ClientOptions = {}): Client {\n const specifications = typeof documentOrUrl === 'string' ? undefined : documentOrUrl\n if (typeof documentOrUrl === 'string') initialOptions.baseUrl = documentOrUrl\n\n async function fetchByOperationId(operationId: string, options: ClientOptions<any>) {\n if (!specifications) throw new Error('No OpenAPI specification provided.')\n const operation = getOperationById(specifications, operationId) as { method: RequestMethod; path: string } & OpenAPI.Operation\n if (!operation) throw new Error(`Operation ID \"${operationId}\" not found.`)\n const { method, path, responses = {} } = operation\n const fetchOptions = { method, baseUrl: getBaseUrl(specifications), ...initialOptions, ...options }\n const response = await fetch(path, fetchOptions)\n\n // --- Return the JSON response if successful.\n if (response.ok) return handleResponse(response, fetchOptions)\n\n // --- Throw an error if the response was not successful.\n const status = response.status.toString()\n if (status in responses\n && typeof responses[status] === 'object'\n && responses[status] !== null\n && 'description' in responses[status]\n && typeof responses[status].description === 'string')\n throw new Error(responses[status].description)\n\n // --- Throw a generic error if the response was not successful.\n throw new Error(response.statusText)\n }\n\n return new Proxy({}, {\n get(_, property: string) {\n if (property === 'fetch') return (route: string, options: RequestOptions) => fetch(route, ({ ...initialOptions, ...options }))\n return (options: Record<string, unknown>) => fetchByOperationId(property, options)\n },\n }) as unknown as Client\n}\n"],"names":["getOperationById","getBaseUrl","fetch","handleResponse"],"mappings":";;;;AA8DO,SAAS,aAAa,eAAoD,iBAAgC,IAAY;AAC3H,QAAM,iBAAiB,OAAO,iBAAkB,WAAW,SAAY;AACnE,SAAO,iBAAkB,aAAU,eAAe,UAAU;AAEjD,iBAAA,mBAAmB,aAAqB,SAA6B;AAClF,QAAI,CAAC,eAAsB,OAAA,IAAI,MAAM,oCAAoC;AACnE,UAAA,YAAYA,iBAAAA,iBAAiB,gBAAgB,WAAW;AAC9D,QAAI,CAAC,UAAW,OAAM,IAAI,MAAM,iBAAiB,WAAW,cAAc;AACpE,UAAA,EAAE,QAAQ,MAAM,YAAY,CAAA,EAAO,IAAA,WACnC,eAAe,EAAE,QAAQ,SAASC,4BAAW,cAAc,GAAG,GAAG,gBAAgB,GAAG,QAAA,GACpF,WAAW,MAAMC,MAAAA,MAAM,MAAM,YAAY;AAG/C,QAAI,SAAS,GAAW,QAAAC,eAAAA,eAAe,UAAU,YAAY;AAGvD,UAAA,SAAS,SAAS,OAAO,SAAS;AACxC,UAAI,UAAU,aACT,OAAO,UAAU,MAAM,KAAM,YAC7B,UAAU,MAAM,MAAM,QACtB,iBAAiB,UAAU,MAAM,KACjC,OAAO,UAAU,MAAM,EAAE,eAAgB,WACtC,IAAI,MAAM,UAAU,MAAM,EAAE,WAAW,IAGzC,IAAI,MAAM,SAAS,UAAU;AAAA,EAAA;AAG9B,SAAA,IAAI,MAAM,IAAI;AAAA,IACnB,IAAI,GAAG,UAAkB;AACvB,aAAI,aAAa,UAAgB,CAAC,OAAe,YAA4BD,MAAA,MAAM,OAAQ,EAAE,GAAG,gBAAgB,GAAG,SAAU,IACtH,CAAC,YAAqC,mBAAmB,UAAU,OAAO;AAAA,IAAA;AAAA,EACnF,CACD;AACH;;"}