@fragno-dev/core 0.1.7 → 0.1.9
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/.turbo/turbo-build.log +131 -64
- package/CHANGELOG.md +19 -0
- package/dist/api/api.d.ts +38 -2
- package/dist/api/api.d.ts.map +1 -0
- package/dist/api/api.js +9 -2
- package/dist/api/api.js.map +1 -0
- package/dist/api/bind-services.d.ts +6 -0
- package/dist/api/bind-services.d.ts.map +1 -0
- package/dist/api/bind-services.js +20 -0
- package/dist/api/bind-services.js.map +1 -0
- package/dist/api/error.d.ts +26 -0
- package/dist/api/error.d.ts.map +1 -0
- package/dist/{api-DngJDcmO.js → api/error.js} +2 -8
- package/dist/api/error.js.map +1 -0
- package/dist/api/fragment-definition-builder.d.ts +313 -0
- package/dist/api/fragment-definition-builder.d.ts.map +1 -0
- package/dist/api/fragment-definition-builder.js +326 -0
- package/dist/api/fragment-definition-builder.js.map +1 -0
- package/dist/api/fragment-instantiator.d.ts +216 -0
- package/dist/api/fragment-instantiator.d.ts.map +1 -0
- package/dist/api/fragment-instantiator.js +487 -0
- package/dist/api/fragment-instantiator.js.map +1 -0
- package/dist/api/fragno-response.d.ts +30 -0
- package/dist/api/fragno-response.d.ts.map +1 -0
- package/dist/api/fragno-response.js +73 -0
- package/dist/api/fragno-response.js.map +1 -0
- package/dist/api/internal/path.d.ts +50 -0
- package/dist/api/internal/path.d.ts.map +1 -0
- package/dist/api/internal/path.js +76 -0
- package/dist/api/internal/path.js.map +1 -0
- package/dist/api/internal/response-stream.d.ts +43 -0
- package/dist/api/internal/response-stream.d.ts.map +1 -0
- package/dist/api/internal/response-stream.js +81 -0
- package/dist/api/internal/response-stream.js.map +1 -0
- package/dist/api/internal/route.js +10 -0
- package/dist/api/internal/route.js.map +1 -0
- package/dist/api/mutable-request-state.d.ts +82 -0
- package/dist/api/mutable-request-state.d.ts.map +1 -0
- package/dist/api/mutable-request-state.js +97 -0
- package/dist/api/mutable-request-state.js.map +1 -0
- package/dist/api/request-context-storage.d.ts +42 -0
- package/dist/api/request-context-storage.d.ts.map +1 -0
- package/dist/api/request-context-storage.js +43 -0
- package/dist/api/request-context-storage.js.map +1 -0
- package/dist/api/request-input-context.d.ts +89 -0
- package/dist/api/request-input-context.d.ts.map +1 -0
- package/dist/api/request-input-context.js +118 -0
- package/dist/api/request-input-context.js.map +1 -0
- package/dist/api/request-middleware.d.ts +50 -0
- package/dist/api/request-middleware.d.ts.map +1 -0
- package/dist/api/request-middleware.js +83 -0
- package/dist/api/request-middleware.js.map +1 -0
- package/dist/api/request-output-context.d.ts +41 -0
- package/dist/api/request-output-context.d.ts.map +1 -0
- package/dist/api/request-output-context.js +119 -0
- package/dist/api/request-output-context.js.map +1 -0
- package/dist/api/route-handler-input-options.d.ts +21 -0
- package/dist/api/route-handler-input-options.d.ts.map +1 -0
- package/dist/api/route.d.ts +54 -3
- package/dist/api/route.d.ts.map +1 -0
- package/dist/api/route.js +29 -2
- package/dist/api/route.js.map +1 -0
- package/dist/api/shared-types.d.ts +47 -0
- package/dist/api/shared-types.d.ts.map +1 -0
- package/dist/api/shared-types.js +1 -0
- package/dist/client/client-error.d.ts +60 -0
- package/dist/client/client-error.d.ts.map +1 -0
- package/dist/client/client-error.js +92 -0
- package/dist/client/client-error.js.map +1 -0
- package/dist/client/client.d.ts +210 -4
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +397 -6
- package/dist/client/client.js.map +1 -0
- package/dist/client/client.svelte.d.ts +5 -3
- package/dist/client/client.svelte.d.ts.map +1 -1
- package/dist/client/client.svelte.js +1 -5
- package/dist/client/client.svelte.js.map +1 -1
- package/dist/client/internal/fetcher-merge.js +36 -0
- package/dist/client/internal/fetcher-merge.js.map +1 -0
- package/dist/client/internal/ndjson-streaming.js +139 -0
- package/dist/client/internal/ndjson-streaming.js.map +1 -0
- package/dist/client/react.d.ts +5 -3
- package/dist/client/react.d.ts.map +1 -1
- package/dist/client/react.js +3 -5
- package/dist/client/react.js.map +1 -1
- package/dist/client/solid.d.ts +5 -3
- package/dist/client/solid.d.ts.map +1 -1
- package/dist/client/solid.js +2 -5
- package/dist/client/solid.js.map +1 -1
- package/dist/client/vanilla.d.ts +5 -3
- package/dist/client/vanilla.d.ts.map +1 -1
- package/dist/client/vanilla.js +2 -43
- package/dist/client/vanilla.js.map +1 -1
- package/dist/client/vue.d.ts +5 -3
- package/dist/client/vue.d.ts.map +1 -1
- package/dist/client/vue.js +1 -5
- package/dist/client/vue.js.map +1 -1
- package/dist/http/http-status.d.ts +26 -0
- package/dist/http/http-status.d.ts.map +1 -0
- package/dist/integrations/react-ssr.js +1 -1
- package/dist/internal/symbols.d.ts +9 -0
- package/dist/internal/symbols.d.ts.map +1 -0
- package/dist/internal/symbols.js +10 -0
- package/dist/internal/symbols.js.map +1 -0
- package/dist/mod-client.d.ts +36 -0
- package/dist/mod-client.d.ts.map +1 -0
- package/dist/mod-client.js +21 -0
- package/dist/mod-client.js.map +1 -0
- package/dist/mod.d.ts +7 -4
- package/dist/mod.js +4 -6
- package/dist/request/request.d.ts +4 -0
- package/dist/request/request.js +5 -0
- package/dist/test/test.d.ts +62 -35
- package/dist/test/test.d.ts.map +1 -1
- package/dist/test/test.js +75 -40
- package/dist/test/test.js.map +1 -1
- package/dist/util/async.js +40 -0
- package/dist/util/async.js.map +1 -0
- package/dist/util/content-type.js +49 -0
- package/dist/util/content-type.js.map +1 -0
- package/dist/util/nanostores.js +31 -0
- package/dist/util/nanostores.js.map +1 -0
- package/dist/{ssr-BByDVfFD.js → util/ssr.js} +2 -2
- package/dist/util/ssr.js.map +1 -0
- package/dist/util/types-util.d.ts +8 -0
- package/dist/util/types-util.d.ts.map +1 -0
- package/package.json +19 -12
- package/src/api/api.ts +41 -6
- package/src/api/bind-services.ts +42 -0
- package/src/api/fragment-definition-builder.extend.test.ts +810 -0
- package/src/api/fragment-definition-builder.test.ts +499 -0
- package/src/api/fragment-definition-builder.ts +1088 -0
- package/src/api/fragment-instantiator.test.ts +1488 -0
- package/src/api/fragment-instantiator.ts +1053 -0
- package/src/api/fragment-services.test.ts +727 -0
- package/src/api/request-context-storage.ts +64 -0
- package/src/api/request-middleware.test.ts +301 -225
- package/src/api/route.test.ts +87 -1
- package/src/api/route.ts +345 -24
- package/src/api/shared-types.ts +43 -0
- package/src/client/client-builder.test.ts +23 -23
- package/src/client/client.ssr.test.ts +3 -3
- package/src/client/client.svelte.test.ts +15 -15
- package/src/client/client.test.ts +22 -22
- package/src/client/client.ts +72 -12
- package/src/client/internal/fetcher-merge.ts +1 -1
- package/src/client/react.test.ts +2 -2
- package/src/client/solid.test.ts +2 -2
- package/src/client/vanilla.test.ts +2 -2
- package/src/client/vue.test.ts +2 -2
- package/src/internal/symbols.ts +5 -0
- package/src/mod-client.ts +59 -0
- package/src/mod.ts +26 -9
- package/src/request/request.ts +8 -0
- package/src/test/test.test.ts +200 -381
- package/src/test/test.ts +190 -117
- package/tsdown.config.ts +8 -5
- package/dist/api/fragment-builder.d.ts +0 -4
- package/dist/api/fragment-builder.js +0 -3
- package/dist/api/fragment-instantiation.d.ts +0 -4
- package/dist/api/fragment-instantiation.js +0 -6
- package/dist/api-BWN97TOr.d.ts +0 -377
- package/dist/api-BWN97TOr.d.ts.map +0 -1
- package/dist/api-DngJDcmO.js.map +0 -1
- package/dist/client-C5LsYHEI.js +0 -782
- package/dist/client-C5LsYHEI.js.map +0 -1
- package/dist/fragment-builder-DOnCVBqc.js +0 -47
- package/dist/fragment-builder-DOnCVBqc.js.map +0 -1
- package/dist/fragment-builder-MGr68GNb.d.ts +0 -409
- package/dist/fragment-builder-MGr68GNb.d.ts.map +0 -1
- package/dist/fragment-instantiation-C4wvwl6V.js +0 -446
- package/dist/fragment-instantiation-C4wvwl6V.js.map +0 -1
- package/dist/request-output-context-CdIjwmEN.js +0 -320
- package/dist/request-output-context-CdIjwmEN.js.map +0 -1
- package/dist/route-Bl9Zr1Yv.d.ts +0 -26
- package/dist/route-Bl9Zr1Yv.d.ts.map +0 -1
- package/dist/route-C5Uryylh.js +0 -21
- package/dist/route-C5Uryylh.js.map +0 -1
- package/dist/ssr-BByDVfFD.js.map +0 -1
- package/src/api/fragment-builder.ts +0 -80
- package/src/api/fragment-instantiation.test.ts +0 -460
- package/src/api/fragment-instantiation.ts +0 -499
- package/src/api/fragment.test.ts +0 -537
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
//#region src/api/fragno-response.ts
|
|
2
|
+
/**
|
|
3
|
+
* Parse a Response object into a FragnoResponse discriminated union
|
|
4
|
+
*/
|
|
5
|
+
async function parseFragnoResponse(response) {
|
|
6
|
+
const status = response.status;
|
|
7
|
+
const headers = response.headers;
|
|
8
|
+
if ((headers.get("content-type") || "").includes("application/x-ndjson")) return {
|
|
9
|
+
type: "jsonStream",
|
|
10
|
+
status,
|
|
11
|
+
headers,
|
|
12
|
+
stream: parseNDJSONStream(response)
|
|
13
|
+
};
|
|
14
|
+
const text = await response.text();
|
|
15
|
+
if (!text || text === "null") return {
|
|
16
|
+
type: "empty",
|
|
17
|
+
status,
|
|
18
|
+
headers
|
|
19
|
+
};
|
|
20
|
+
const data = JSON.parse(text);
|
|
21
|
+
if (data && typeof data === "object" && "code" in data) {
|
|
22
|
+
if ("message" in data) return {
|
|
23
|
+
type: "error",
|
|
24
|
+
status,
|
|
25
|
+
headers,
|
|
26
|
+
error: {
|
|
27
|
+
message: data.message,
|
|
28
|
+
code: data.code
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
if ("error" in data) return {
|
|
32
|
+
type: "error",
|
|
33
|
+
status,
|
|
34
|
+
headers,
|
|
35
|
+
error: {
|
|
36
|
+
message: data.error,
|
|
37
|
+
code: data.code
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
type: "json",
|
|
43
|
+
status,
|
|
44
|
+
headers,
|
|
45
|
+
data
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Parse an NDJSON stream into an async generator
|
|
50
|
+
*/
|
|
51
|
+
async function* parseNDJSONStream(response) {
|
|
52
|
+
if (!response.body) return;
|
|
53
|
+
const reader = response.body.getReader();
|
|
54
|
+
const decoder = new TextDecoder();
|
|
55
|
+
let buffer = "";
|
|
56
|
+
try {
|
|
57
|
+
while (true) {
|
|
58
|
+
const { done, value } = await reader.read();
|
|
59
|
+
if (done) break;
|
|
60
|
+
buffer += decoder.decode(value, { stream: true });
|
|
61
|
+
const lines = buffer.split("\n");
|
|
62
|
+
buffer = lines.pop() || "";
|
|
63
|
+
for (const line of lines) if (line.trim()) yield JSON.parse(line);
|
|
64
|
+
}
|
|
65
|
+
if (buffer.trim()) yield JSON.parse(buffer);
|
|
66
|
+
} finally {
|
|
67
|
+
reader.releaseLock();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
export { parseFragnoResponse };
|
|
73
|
+
//# sourceMappingURL=fragno-response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fragno-response.js","names":[],"sources":["../../src/api/fragno-response.ts"],"sourcesContent":["/**\n * Discriminated union representing all possible Fragno response types\n */\nexport type FragnoResponse<T> =\n | {\n type: \"empty\";\n status: number;\n headers: Headers;\n }\n | {\n type: \"error\";\n status: number;\n headers: Headers;\n error: { message: string; code: string };\n }\n | {\n type: \"json\";\n status: number;\n headers: Headers;\n data: T;\n }\n | {\n type: \"jsonStream\";\n status: number;\n headers: Headers;\n stream: AsyncGenerator<T extends unknown[] ? T[number] : T>;\n };\n\n/**\n * Parse a Response object into a FragnoResponse discriminated union\n */\nexport async function parseFragnoResponse<T>(response: Response): Promise<FragnoResponse<T>> {\n const status = response.status;\n const headers = response.headers;\n const contentType = headers.get(\"content-type\") || \"\";\n\n // Check for streaming response\n if (contentType.includes(\"application/x-ndjson\")) {\n return {\n type: \"jsonStream\",\n status,\n headers,\n stream: parseNDJSONStream<T>(response),\n };\n }\n\n // Parse JSON body\n const text = await response.text();\n\n // Empty response\n if (!text || text === \"null\") {\n return {\n type: \"empty\",\n status,\n headers,\n };\n }\n\n const data = JSON.parse(text);\n\n // Error response (has message and code, or error and code)\n if (data && typeof data === \"object\" && \"code\" in data) {\n if (\"message\" in data) {\n return {\n type: \"error\",\n status,\n headers,\n error: { message: data.message, code: data.code },\n };\n }\n if (\"error\" in data) {\n return {\n type: \"error\",\n status,\n headers,\n error: { message: data.error, code: data.code },\n };\n }\n }\n\n // JSON response\n return {\n type: \"json\",\n status,\n headers,\n data: data as T,\n };\n}\n\n/**\n * Parse an NDJSON stream into an async generator\n */\nasync function* parseNDJSONStream<T>(\n response: Response,\n): AsyncGenerator<T extends unknown[] ? T[number] : T> {\n if (!response.body) {\n return;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n\n // Keep the last incomplete line in the buffer\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (line.trim()) {\n yield JSON.parse(line) as T extends unknown[] ? T[number] : T;\n }\n }\n }\n\n // Process any remaining data in the buffer\n if (buffer.trim()) {\n yield JSON.parse(buffer) as T extends unknown[] ? T[number] : T;\n }\n } finally {\n reader.releaseLock();\n }\n}\n"],"mappings":";;;;AA+BA,eAAsB,oBAAuB,UAAgD;CAC3F,MAAM,SAAS,SAAS;CACxB,MAAM,UAAU,SAAS;AAIzB,MAHoB,QAAQ,IAAI,eAAe,IAAI,IAGnC,SAAS,uBAAuB,CAC9C,QAAO;EACL,MAAM;EACN;EACA;EACA,QAAQ,kBAAqB,SAAS;EACvC;CAIH,MAAM,OAAO,MAAM,SAAS,MAAM;AAGlC,KAAI,CAAC,QAAQ,SAAS,OACpB,QAAO;EACL,MAAM;EACN;EACA;EACD;CAGH,MAAM,OAAO,KAAK,MAAM,KAAK;AAG7B,KAAI,QAAQ,OAAO,SAAS,YAAY,UAAU,MAAM;AACtD,MAAI,aAAa,KACf,QAAO;GACL,MAAM;GACN;GACA;GACA,OAAO;IAAE,SAAS,KAAK;IAAS,MAAM,KAAK;IAAM;GAClD;AAEH,MAAI,WAAW,KACb,QAAO;GACL,MAAM;GACN;GACA;GACA,OAAO;IAAE,SAAS,KAAK;IAAO,MAAM,KAAK;IAAM;GAChD;;AAKL,QAAO;EACL,MAAM;EACN;EACA;EACM;EACP;;;;;AAMH,gBAAgB,kBACd,UACqD;AACrD,KAAI,CAAC,SAAS,KACZ;CAGF,MAAM,SAAS,SAAS,KAAK,WAAW;CACxC,MAAM,UAAU,IAAI,aAAa;CACjC,IAAI,SAAS;AAEb,KAAI;AACF,SAAO,MAAM;GACX,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAE3C,OAAI,KACF;AAGF,aAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,MAAM,CAAC;GACjD,MAAM,QAAQ,OAAO,MAAM,KAAK;AAGhC,YAAS,MAAM,KAAK,IAAI;AAExB,QAAK,MAAM,QAAQ,MACjB,KAAI,KAAK,MAAM,CACb,OAAM,KAAK,MAAM,KAAK;;AAM5B,MAAI,OAAO,MAAM,CACf,OAAM,KAAK,MAAM,OAAO;WAElB;AACR,SAAO,aAAa"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/api/internal/path.d.ts
|
|
2
|
+
type SplitPath<T extends string> = T extends `${infer First}/${infer Rest}` ? First extends "" ? SplitPath<Rest> : [First, ...SplitPath<Rest>] : T extends "" ? [] : [T];
|
|
3
|
+
type ExtractParam<T extends string> = T extends `:${infer Name}` ? Name : T extends `**:${infer Name}` ? Name : T extends "**" ? "**" : never;
|
|
4
|
+
type ExtractParamsFromSegments<T extends readonly string[]> = T extends readonly [infer First, ...infer Rest] ? First extends string ? Rest extends readonly string[] ? ExtractParam<First> | ExtractParamsFromSegments<Rest> : ExtractParam<First> : never : never;
|
|
5
|
+
/**
|
|
6
|
+
* Type helper to extract path parameters from a const string path
|
|
7
|
+
*
|
|
8
|
+
* Supports:
|
|
9
|
+
* - Regular paths: "/path" -> never
|
|
10
|
+
* - Named parameters: "/path/:name" -> "name"
|
|
11
|
+
* - Wildcard paths: "/path/foo/**" -> "**"
|
|
12
|
+
* - Named wildcard paths: "/path/foo/**:name" -> "name"
|
|
13
|
+
* - String (narrows): string -> never
|
|
14
|
+
*/
|
|
15
|
+
type ExtractPathParams<T extends string, ValueType = string> = ExtractParamsFromSegments<SplitPath<T>> extends never ? Record<string, never> : Record<ExtractParamsFromSegments<SplitPath<T>>, ValueType>;
|
|
16
|
+
/**
|
|
17
|
+
* Same as @see ExtractPathParams, but returns `Record<string, ValueType>` when a string is
|
|
18
|
+
* passed in.
|
|
19
|
+
*/
|
|
20
|
+
type ExtractPathParamsOrWiden<T extends string, ValueType = string> = string extends T ? Record<string, ValueType> : ExtractPathParams<T, ValueType>;
|
|
21
|
+
/**
|
|
22
|
+
* Same as @see ExtractPathParamsOrWiden, but returns `undefined` when no path parameters in the
|
|
23
|
+
* const.
|
|
24
|
+
*/
|
|
25
|
+
type MaybeExtractPathParamsOrWiden<T extends string, ValueType = string> = HasPathParams<T> extends true ? ExtractPathParamsOrWiden<T, ValueType> : undefined;
|
|
26
|
+
type ExtractPathParamNames<T extends string> = ExtractParamsFromSegments<SplitPath<T>>;
|
|
27
|
+
type HasPathParams<T extends string> = ExtractPathParamNames<T> extends never ? false : true;
|
|
28
|
+
/**
|
|
29
|
+
* Creates a query parameters type where the specified keys are hints (optional)
|
|
30
|
+
* and additional string keys are also allowed.
|
|
31
|
+
*
|
|
32
|
+
* This allows for flexible query parameter typing where:
|
|
33
|
+
* - All hinted parameters are optional
|
|
34
|
+
* - Additional parameters beyond the hints are allowed
|
|
35
|
+
* - Values can be of any specified type (defaults to string)
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* type MyQuery = QueryParamsHint<"page" | "limit", string>;
|
|
40
|
+
* // Allows: { page?: string, limit?: string, [key: string]: string }
|
|
41
|
+
*
|
|
42
|
+
* const query1: MyQuery = {}; // Valid - no params required
|
|
43
|
+
* const query2: MyQuery = { page: "1" }; // Valid - hinted param
|
|
44
|
+
* const query3: MyQuery = { page: "1", sort: "asc" }; // Valid - additional param
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
type QueryParamsHint<TQueryParameters extends string, ValueType = string> = Partial<Record<TQueryParameters, ValueType>> & Record<string, ValueType | undefined>;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { ExtractPathParams, ExtractPathParamsOrWiden, HasPathParams, MaybeExtractPathParamsOrWiden, QueryParamsHint };
|
|
50
|
+
//# sourceMappingURL=path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.d.ts","names":[],"sources":["../../../src/api/internal/path.ts"],"sourcesContent":[],"mappings":";KACK,8BAA8B,2CAC/B,mBACE,UAAU,SACT,UAAU,UAAU,SACvB,qBAEG;KAGF,YATS,CAAA,UAAA,MAAA,CAAA,GASwB,CATxB,SAAA,IAAA,KAAA,KAAA,EAAA,GAUV,IAVU,GAWV,CAXU,SAAA,MAAA,KAAA,KAAA,EAAA,GAYR,IAZQ,GAaR,CAbQ,SAAA,IAAA,GAAA,IAAA,GAAA,KAAA;KAkBT,yBAlB8B,CAAA,UAAA,SAAA,MAAA,EAAA,CAAA,GAkB2B,CAlB3B,SAAA,SAAA,CAC/B,KAAA,MAAA,EACY,GAAA,KAAA,KAAA,CAAV,GAoBF,KApBE,SAAA,MAAA,GAqBA,IArBA,SAAA,SAAA,MAAA,EAAA,GAsBE,YAtBF,CAsBe,KAtBf,CAAA,GAsBwB,yBAtBxB,CAsBkD,IAtBlD,CAAA,GAuBE,YAvBF,CAuBe,KAvBf,CAAA,GAAA,KAAA,GAAA,KAAA;;;;;;;AAIE;;;;AAMF,KA2BM,iBA3BN,CAAA,UAAA,MAAA,EAAA,YAAA,MAAA,CAAA,GA4BJ,yBA5BI,CA4BsB,SA5BtB,CA4BgC,CA5BhC,CAAA,CAAA,SAAA,KAAA,GA6BA,MA7BA,CAAA,MAAA,EAAA,KAAA,CAAA,GA8BA,MA9BA,CA8BO,yBA9BP,CA8BiC,SA9BjC,CA8B2C,CA9B3C,CAAA,CAAA,EA8BgD,SA9BhD,CAAA;;;AACC;;AASH,KA0BQ,wBA1BR,CAAA,UAAA,MAAA,EAAA,YAAA,MAAA,CAAA,GAAA,MAAA,SA0BwF,CA1BxF,GA2BA,MA3BA,CAAA,MAAA,EA2Be,SA3Bf,CAAA,GA4BA,iBA5BA,CA4BkB,CA5BlB,EA4BqB,SA5BrB,CAAA;;;;;AAE0B,KAiClB,6BAjCkB,CAAA,UAAA,MAAA,EAAA,YAAA,MAAA,CAAA,GAkC5B,aAlC4B,CAkCd,CAlCc,CAAA,SAAA,IAAA,GAkCI,wBAlCJ,CAkC6B,CAlC7B,EAkCgC,SAlChC,CAAA,GAAA,SAAA;AACT,KAoCT,qBApCS,CAAA,UAAA,MAAA,CAAA,GAoCiC,yBApCjC,CAoC2D,SApC3D,CAoCqE,CApCrE,CAAA,CAAA;AAuBuE,KAqDhF,aArDgF,CAAA,UAAA,MAAA,CAAA,GAqD9C,qBArD8C,CAqDxB,CArDwB,CAAA,SAAA,KAAA,GAAA,KAAA,GAAA,IAAA;;;;;;;AAS5F;;;;;;;AAIA;;;;;AAwCA;AAqBY,KAAA,eAAe,CAAA,yBAAA,MAAA,EAAA,YAAA,MAAA,CAAA,GAAwD,OAAxD,CACzB,MADyB,CAClB,gBADkB,EACA,SADA,CAAA,CAAA,GAGzB,MAHyB,CAAA,MAAA,EAGV,SAHU,GAAA,SAAA,CAAA"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
//#region src/api/internal/path.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extract parameter names from a path pattern at runtime.
|
|
4
|
+
* Examples:
|
|
5
|
+
* - "/users/:id" => ["id"]
|
|
6
|
+
* - "/files/**" => ["**"]
|
|
7
|
+
* - "/files/**:rest" => ["rest"]
|
|
8
|
+
*/
|
|
9
|
+
function extractPathParams(pathPattern) {
|
|
10
|
+
const segments = pathPattern.split("/").filter((s) => s.length > 0);
|
|
11
|
+
const names = [];
|
|
12
|
+
for (const segment of segments) {
|
|
13
|
+
if (segment.startsWith(":")) {
|
|
14
|
+
names.push(segment.slice(1));
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (segment === "**") {
|
|
18
|
+
names.push("**");
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (segment.startsWith("**:")) {
|
|
22
|
+
names.push(segment.slice(3));
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return names;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build a concrete path by replacing placeholders in a path pattern with values.
|
|
30
|
+
*
|
|
31
|
+
* Supports the same placeholder syntax as the matcher:
|
|
32
|
+
* - Named parameter ":name" is URL-encoded as a single segment
|
|
33
|
+
* - Anonymous wildcard "**" inserts the remainder as-is (slashes preserved)
|
|
34
|
+
* - Named wildcard "**:name" inserts the remainder from the named key
|
|
35
|
+
*
|
|
36
|
+
* Examples:
|
|
37
|
+
* - buildPath("/users/:id", { id: "123" }) => "/users/123"
|
|
38
|
+
* - buildPath("/files/**", { "**": "a/b" }) => "/files/a/b"
|
|
39
|
+
* - buildPath("/files/**:rest", { rest: "a/b" }) => "/files/a/b"
|
|
40
|
+
*/
|
|
41
|
+
function buildPath(pathPattern, params) {
|
|
42
|
+
const patternSegments = pathPattern.split("/");
|
|
43
|
+
const builtSegments = [];
|
|
44
|
+
for (const segment of patternSegments) {
|
|
45
|
+
if (segment.length === 0) {
|
|
46
|
+
builtSegments.push("");
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (segment.startsWith(":")) {
|
|
50
|
+
const name = segment.slice(1);
|
|
51
|
+
const value = params[name];
|
|
52
|
+
if (value === void 0) throw new Error(`Missing value for path parameter :${name}`);
|
|
53
|
+
builtSegments.push(encodeURIComponent(value));
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (segment === "**") {
|
|
57
|
+
const value = params["**"];
|
|
58
|
+
if (value === void 0) throw new Error("Missing value for path wildcard **");
|
|
59
|
+
builtSegments.push(value);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (segment.startsWith("**:")) {
|
|
63
|
+
const name = segment.slice(3);
|
|
64
|
+
const value = params[name];
|
|
65
|
+
if (value === void 0) throw new Error(`Missing value for path wildcard **:${name}`);
|
|
66
|
+
builtSegments.push(value);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
builtSegments.push(segment);
|
|
70
|
+
}
|
|
71
|
+
return builtSegments.join("/");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
export { buildPath, extractPathParams };
|
|
76
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","names":["names: string[]","builtSegments: string[]"],"sources":["../../../src/api/internal/path.ts"],"sourcesContent":["// Helper type to split a string by '/'\ntype SplitPath<T extends string> = T extends `${infer First}/${infer Rest}`\n ? First extends \"\"\n ? SplitPath<Rest>\n : [First, ...SplitPath<Rest>]\n : T extends \"\"\n ? []\n : [T];\n\n// Helper type to extract parameter name from a single segment\ntype ExtractParam<T extends string> = T extends `:${infer Name}`\n ? Name\n : T extends `**:${infer Name}`\n ? Name\n : T extends \"**\"\n ? \"**\"\n : never;\n\n// Helper type to extract all parameter names from path segments\ntype ExtractParamsFromSegments<T extends readonly string[]> = T extends readonly [\n infer First,\n ...infer Rest,\n]\n ? First extends string\n ? Rest extends readonly string[]\n ? ExtractParam<First> | ExtractParamsFromSegments<Rest>\n : ExtractParam<First>\n : never\n : never;\n\n/**\n * Type helper to extract path parameters from a const string path\n *\n * Supports:\n * - Regular paths: \"/path\" -> never\n * - Named parameters: \"/path/:name\" -> \"name\"\n * - Wildcard paths: \"/path/foo/**\" -> \"**\"\n * - Named wildcard paths: \"/path/foo/**:name\" -> \"name\"\n * - String (narrows): string -> never\n */\nexport type ExtractPathParams<T extends string, ValueType = string> =\n ExtractParamsFromSegments<SplitPath<T>> extends never\n ? Record<string, never>\n : Record<ExtractParamsFromSegments<SplitPath<T>>, ValueType>;\n\n/**\n * Same as @see ExtractPathParams, but returns `Record<string, ValueType>` when a string is\n * passed in.\n */\nexport type ExtractPathParamsOrWiden<T extends string, ValueType = string> = string extends T\n ? Record<string, ValueType>\n : ExtractPathParams<T, ValueType>;\n\n// TODO: MaybeExtractPathParamsOrWiden<string> --> undefined, should that be Record<string, string>?\n/**\n * Same as @see ExtractPathParamsOrWiden, but returns `undefined` when no path parameters in the\n * const.\n */\nexport type MaybeExtractPathParamsOrWiden<T extends string, ValueType = string> =\n HasPathParams<T> extends true ? ExtractPathParamsOrWiden<T, ValueType> : undefined;\n\n// Alternative version that returns the parameter names as a union type\nexport type ExtractPathParamNames<T extends string> = ExtractParamsFromSegments<SplitPath<T>>;\n\n// Helper type to extract parameter names as an ordered tuple from path segments\ntype ExtractParamNamesAsTuple<T extends readonly string[]> = T extends readonly [\n infer First,\n ...infer Rest,\n]\n ? First extends string\n ? Rest extends readonly string[]\n ? ExtractParam<First> extends never\n ? ExtractParamNamesAsTuple<Rest>\n : [ExtractParam<First>, ...ExtractParamNamesAsTuple<Rest>]\n : ExtractParam<First> extends never\n ? []\n : [ExtractParam<First>]\n : []\n : [];\n\n// Type to convert ExtractPathParamNames result to a string tuple with the same number of elements\nexport type ExtractPathParamNamesAsTuple<T extends string> = ExtractParamNamesAsTuple<SplitPath<T>>;\n\n// Helper type to create labeled tuple from parameter names\ntype CreateLabeledTuple<T extends readonly string[], ElementType = string> = T extends readonly [\n infer First,\n ...infer Rest,\n]\n ? First extends string\n ? Rest extends readonly string[]\n ? [{ [K in First]: ElementType }[First], ...CreateLabeledTuple<Rest, ElementType>]\n : [{ [K in First]: ElementType }[First]]\n : []\n : [];\n\n// Type to convert path parameters to a labeled tuple\nexport type ExtractPathParamsAsLabeledTuple<\n T extends string,\n ElementType = string,\n> = CreateLabeledTuple<ExtractParamNamesAsTuple<SplitPath<T>>, ElementType>;\n\n// Type to check if a path has parameters\nexport type HasPathParams<T extends string> = ExtractPathParamNames<T> extends never ? false : true;\n\n/**\n * Creates a query parameters type where the specified keys are hints (optional)\n * and additional string keys are also allowed.\n *\n * This allows for flexible query parameter typing where:\n * - All hinted parameters are optional\n * - Additional parameters beyond the hints are allowed\n * - Values can be of any specified type (defaults to string)\n *\n * @example\n * ```ts\n * type MyQuery = QueryParamsHint<\"page\" | \"limit\", string>;\n * // Allows: { page?: string, limit?: string, [key: string]: string }\n *\n * const query1: MyQuery = {}; // Valid - no params required\n * const query2: MyQuery = { page: \"1\" }; // Valid - hinted param\n * const query3: MyQuery = { page: \"1\", sort: \"asc\" }; // Valid - additional param\n * ```\n */\nexport type QueryParamsHint<TQueryParameters extends string, ValueType = string> = Partial<\n Record<TQueryParameters, ValueType>\n> &\n Record<string, ValueType | undefined>;\n\n// Runtime utilities\n\n/**\n * Extract parameter names from a path pattern at runtime.\n * Examples:\n * - \"/users/:id\" => [\"id\"]\n * - \"/files/**\" => [\"**\"]\n * - \"/files/**:rest\" => [\"rest\"]\n */\nexport function extractPathParams<TPath extends string>(\n pathPattern: TPath,\n): ExtractPathParamNames<TPath>[] {\n const segments = pathPattern.split(\"/\").filter((s) => s.length > 0);\n const names: string[] = [];\n\n for (const segment of segments) {\n if (segment.startsWith(\":\")) {\n names.push(segment.slice(1));\n continue;\n }\n\n if (segment === \"**\") {\n names.push(\"**\");\n continue;\n }\n\n if (segment.startsWith(\"**:\")) {\n names.push(segment.slice(3));\n continue;\n }\n }\n\n return names as ExtractPathParamNames<TPath>[];\n}\n\n/**\n * Match an actual path against a path pattern and return extracted params.\n *\n * Notes and limitations:\n * - Named segment \":name\" captures a single path segment.\n * - Wildcard \"**\" or \"**:name\" greedily captures the remainder of the path and\n * should be placed at the end of the pattern.\n * - If the path does not match the pattern, an empty object is returned.\n */\nexport function matchPathParams<TPath extends string>(\n pathPattern: TPath,\n actualPath: string,\n): ExtractPathParams<TPath> {\n const patternSegments = pathPattern.split(\"/\").filter((s) => s.length > 0);\n const actualSegments = actualPath.split(\"/\").filter((s) => s.length > 0);\n\n const params: Record<string, string> = {};\n\n let i = 0;\n let j = 0;\n\n while (i < patternSegments.length && j < actualSegments.length) {\n const patternSegment = patternSegments[i];\n const actualSegment = actualSegments[j];\n\n if (patternSegment.startsWith(\":\")) {\n const name = patternSegment.slice(1);\n params[name] = decodeURIComponent(actualSegment);\n i += 1;\n j += 1;\n continue;\n }\n\n if (patternSegment === \"**\") {\n const remainder = actualSegments.slice(j).join(\"/\");\n params[\"**\"] = remainder ? decodeURIComponent(remainder) : \"\";\n // Wildcard consumes the rest; pattern should end here\n i = patternSegments.length;\n j = actualSegments.length;\n break;\n }\n\n if (patternSegment.startsWith(\"**:\")) {\n const name = patternSegment.slice(3);\n const remainder = actualSegments.slice(j).join(\"/\");\n params[name] = remainder ? decodeURIComponent(remainder) : \"\";\n // Wildcard consumes the rest; pattern should end here\n i = patternSegments.length;\n j = actualSegments.length;\n break;\n }\n\n // Literal segment must match exactly\n if (patternSegment === actualSegment) {\n i += 1;\n j += 1;\n continue;\n }\n\n // Mismatch\n return {} as ExtractPathParams<TPath>;\n }\n\n // If there are remaining pattern segments\n while (i < patternSegments.length) {\n const remaining = patternSegments[i];\n if (remaining === \"**\") {\n params[\"**\"] = \"\";\n i += 1;\n continue;\n }\n if (remaining.startsWith(\":\")) {\n const name = remaining.slice(1);\n params[name] = \"\";\n i += 1;\n continue;\n }\n if (remaining.startsWith(\"**:\")) {\n const name = remaining.slice(3);\n params[name] = \"\";\n i += 1;\n continue;\n }\n // Non-parameter remaining segment without corresponding actual segment → mismatch\n return {} as ExtractPathParams<TPath>;\n }\n\n // If there are remaining actual segments without pattern to match → mismatch\n if (j < actualSegments.length) {\n return {} as ExtractPathParams<TPath>;\n }\n\n return params as ExtractPathParams<TPath>;\n}\n\n/**\n * Build a concrete path by replacing placeholders in a path pattern with values.\n *\n * Supports the same placeholder syntax as the matcher:\n * - Named parameter \":name\" is URL-encoded as a single segment\n * - Anonymous wildcard \"**\" inserts the remainder as-is (slashes preserved)\n * - Named wildcard \"**:name\" inserts the remainder from the named key\n *\n * Examples:\n * - buildPath(\"/users/:id\", { id: \"123\" }) => \"/users/123\"\n * - buildPath(\"/files/**\", { \"**\": \"a/b\" }) => \"/files/a/b\"\n * - buildPath(\"/files/**:rest\", { rest: \"a/b\" }) => \"/files/a/b\"\n */\nexport function buildPath<TPath extends string>(\n pathPattern: TPath,\n params: ExtractPathParams<TPath>,\n): string {\n const patternSegments = pathPattern.split(\"/\");\n\n const builtSegments: string[] = [];\n\n for (const segment of patternSegments) {\n if (segment.length === 0) {\n // Preserve leading/trailing/duplicate slashes\n builtSegments.push(\"\");\n continue;\n }\n\n if (segment.startsWith(\":\")) {\n const name = segment.slice(1);\n const value = (params as Record<string, string | undefined>)[name];\n if (value === undefined) {\n throw new Error(`Missing value for path parameter :${name}`);\n }\n builtSegments.push(encodeURIComponent(value));\n continue;\n }\n\n if (segment === \"**\") {\n const value = (params as Record<string, string | undefined>)[\"**\"];\n if (value === undefined) {\n throw new Error(\"Missing value for path wildcard **\");\n }\n builtSegments.push(value);\n continue;\n }\n\n if (segment.startsWith(\"**:\")) {\n const name = segment.slice(3);\n const value = (params as Record<string, string | undefined>)[name];\n if (value === undefined) {\n throw new Error(`Missing value for path wildcard **:${name}`);\n }\n builtSegments.push(value);\n continue;\n }\n\n // Literal segment\n builtSegments.push(segment);\n }\n\n // Join with '/'. Empty segments preserve leading/trailing slashes\n return builtSegments.join(\"/\");\n}\n"],"mappings":";;;;;;;;AAyIA,SAAgB,kBACd,aACgC;CAChC,MAAM,WAAW,YAAY,MAAM,IAAI,CAAC,QAAQ,MAAM,EAAE,SAAS,EAAE;CACnE,MAAMA,QAAkB,EAAE;AAE1B,MAAK,MAAM,WAAW,UAAU;AAC9B,MAAI,QAAQ,WAAW,IAAI,EAAE;AAC3B,SAAM,KAAK,QAAQ,MAAM,EAAE,CAAC;AAC5B;;AAGF,MAAI,YAAY,MAAM;AACpB,SAAM,KAAK,KAAK;AAChB;;AAGF,MAAI,QAAQ,WAAW,MAAM,EAAE;AAC7B,SAAM,KAAK,QAAQ,MAAM,EAAE,CAAC;AAC5B;;;AAIJ,QAAO;;;;;;;;;;;;;;;AA+GT,SAAgB,UACd,aACA,QACQ;CACR,MAAM,kBAAkB,YAAY,MAAM,IAAI;CAE9C,MAAMC,gBAA0B,EAAE;AAElC,MAAK,MAAM,WAAW,iBAAiB;AACrC,MAAI,QAAQ,WAAW,GAAG;AAExB,iBAAc,KAAK,GAAG;AACtB;;AAGF,MAAI,QAAQ,WAAW,IAAI,EAAE;GAC3B,MAAM,OAAO,QAAQ,MAAM,EAAE;GAC7B,MAAM,QAAS,OAA8C;AAC7D,OAAI,UAAU,OACZ,OAAM,IAAI,MAAM,qCAAqC,OAAO;AAE9D,iBAAc,KAAK,mBAAmB,MAAM,CAAC;AAC7C;;AAGF,MAAI,YAAY,MAAM;GACpB,MAAM,QAAS,OAA8C;AAC7D,OAAI,UAAU,OACZ,OAAM,IAAI,MAAM,qCAAqC;AAEvD,iBAAc,KAAK,MAAM;AACzB;;AAGF,MAAI,QAAQ,WAAW,MAAM,EAAE;GAC7B,MAAM,OAAO,QAAQ,MAAM,EAAE;GAC7B,MAAM,QAAS,OAA8C;AAC7D,OAAI,UAAU,OACZ,OAAM,IAAI,MAAM,sCAAsC,OAAO;AAE/D,iBAAc,KAAK,MAAM;AACzB;;AAIF,gBAAc,KAAK,QAAQ;;AAI7B,QAAO,cAAc,KAAK,IAAI"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region src/api/internal/response-stream.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* @module
|
|
4
|
+
* Stream utility.
|
|
5
|
+
*
|
|
6
|
+
* Modified from honojs/hono
|
|
7
|
+
* Original source: https://github.com/honojs/hono/blob/0e3db674ad3f40be215a55a18062dd8e387ce525/src/utils/stream.ts
|
|
8
|
+
* License: MIT
|
|
9
|
+
* Date obtained: August 28 2025
|
|
10
|
+
* Copyright (c) 2021-present Yusuke Wada and Hono contributors
|
|
11
|
+
*/
|
|
12
|
+
type Error<Message extends string> = {
|
|
13
|
+
__errorMessage: Message;
|
|
14
|
+
};
|
|
15
|
+
declare class ResponseStream<TArray> {
|
|
16
|
+
#private;
|
|
17
|
+
/**
|
|
18
|
+
* Whether the stream has been aborted.
|
|
19
|
+
*/
|
|
20
|
+
get aborted(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Whether the stream has been closed normally.
|
|
23
|
+
*/
|
|
24
|
+
get closed(): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* The readable stream that the response is piped to.
|
|
27
|
+
*/
|
|
28
|
+
get responseReadable(): ReadableStream;
|
|
29
|
+
constructor(writable: WritableStream, readable: ReadableStream);
|
|
30
|
+
writeRaw(input: Uint8Array | string): Promise<void>;
|
|
31
|
+
write(input: TArray extends (infer U)[] ? U : Error<"To use a streaming response, outputSchema must be an array.">): Promise<void>;
|
|
32
|
+
sleep(ms: number): Promise<unknown>;
|
|
33
|
+
close(): Promise<void>;
|
|
34
|
+
onAbort(listener: () => void | Promise<void>): void;
|
|
35
|
+
/**
|
|
36
|
+
* Abort the stream.
|
|
37
|
+
* You can call this method when stream is aborted by external event.
|
|
38
|
+
*/
|
|
39
|
+
abort(): void;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { ResponseStream };
|
|
43
|
+
//# sourceMappingURL=response-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-stream.d.ts","names":[],"sources":["../../../src/api/internal/response-stream.ts"],"sourcesContent":[],"mappings":";;;AAaA;;;;;;;;KAFK,KAyEG,CAAA,gBAAA,MAAA,CAAA,GAAA;EACH,cAAA,EA1EkD,OA0ElD;CAIgB;AAIR,cAhFA,cAgFA,CAAA,MAAA,CAAA,CAAA;EAUoB,CAAA,OAAA;EAAO;;;;;;;;;;;0BAhEd;wBAIF,0BAA0B;kBA2B1B,sBAAsB;eAYnC,6BACH,IACA,uEACH;qBAIgB;WAIR;iCAUoB"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//#region src/api/internal/response-stream.ts
|
|
2
|
+
var ResponseStream = class {
|
|
3
|
+
#writer;
|
|
4
|
+
#encoder;
|
|
5
|
+
#abortSubscribers = [];
|
|
6
|
+
#responseReadable;
|
|
7
|
+
#aborted = false;
|
|
8
|
+
#closed = false;
|
|
9
|
+
/**
|
|
10
|
+
* Whether the stream has been aborted.
|
|
11
|
+
*/
|
|
12
|
+
get aborted() {
|
|
13
|
+
return this.#aborted;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Whether the stream has been closed normally.
|
|
17
|
+
*/
|
|
18
|
+
get closed() {
|
|
19
|
+
return this.#closed;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The readable stream that the response is piped to.
|
|
23
|
+
*/
|
|
24
|
+
get responseReadable() {
|
|
25
|
+
return this.#responseReadable;
|
|
26
|
+
}
|
|
27
|
+
constructor(writable, readable) {
|
|
28
|
+
this.#writer = writable.getWriter();
|
|
29
|
+
this.#encoder = new TextEncoder();
|
|
30
|
+
const reader = readable.getReader();
|
|
31
|
+
this.#abortSubscribers.push(async () => {
|
|
32
|
+
await reader.cancel();
|
|
33
|
+
});
|
|
34
|
+
this.#responseReadable = new ReadableStream({
|
|
35
|
+
async pull(controller) {
|
|
36
|
+
const { done, value } = await reader.read();
|
|
37
|
+
if (done) controller.close();
|
|
38
|
+
else controller.enqueue(value);
|
|
39
|
+
},
|
|
40
|
+
cancel: () => {
|
|
41
|
+
this.abort();
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async writeRaw(input) {
|
|
46
|
+
try {
|
|
47
|
+
if (typeof input === "string") input = this.#encoder.encode(input);
|
|
48
|
+
await this.#writer.write(input);
|
|
49
|
+
} catch {}
|
|
50
|
+
}
|
|
51
|
+
write(input) {
|
|
52
|
+
return this.writeRaw(JSON.stringify(input) + "\n");
|
|
53
|
+
}
|
|
54
|
+
sleep(ms) {
|
|
55
|
+
return new Promise((res) => setTimeout(res, ms));
|
|
56
|
+
}
|
|
57
|
+
async close() {
|
|
58
|
+
try {
|
|
59
|
+
await this.#writer.close();
|
|
60
|
+
} catch {} finally {
|
|
61
|
+
this.#closed = true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
onAbort(listener) {
|
|
65
|
+
this.#abortSubscribers.push(listener);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Abort the stream.
|
|
69
|
+
* You can call this method when stream is aborted by external event.
|
|
70
|
+
*/
|
|
71
|
+
abort() {
|
|
72
|
+
if (!this.aborted) {
|
|
73
|
+
this.#aborted = true;
|
|
74
|
+
this.#abortSubscribers.forEach((subscriber) => subscriber());
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
//#endregion
|
|
80
|
+
export { ResponseStream };
|
|
81
|
+
//# sourceMappingURL=response-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-stream.js","names":["#aborted","#closed","#responseReadable","#writer","#encoder","#abortSubscribers"],"sources":["../../../src/api/internal/response-stream.ts"],"sourcesContent":["/**\n * @module\n * Stream utility.\n *\n * Modified from honojs/hono\n * Original source: https://github.com/honojs/hono/blob/0e3db674ad3f40be215a55a18062dd8e387ce525/src/utils/stream.ts\n * License: MIT\n * Date obtained: August 28 2025\n * Copyright (c) 2021-present Yusuke Wada and Hono contributors\n */\n\ntype Error<Message extends string> = { __errorMessage: Message };\n\nexport class ResponseStream<TArray> {\n #writer: WritableStreamDefaultWriter<Uint8Array>;\n #encoder: TextEncoder;\n #abortSubscribers: (() => void | Promise<void>)[] = [];\n #responseReadable: ReadableStream;\n\n #aborted: boolean = false;\n #closed: boolean = false;\n\n /**\n * Whether the stream has been aborted.\n */\n get aborted(): boolean {\n return this.#aborted;\n }\n\n /**\n * Whether the stream has been closed normally.\n */\n get closed(): boolean {\n return this.#closed;\n }\n\n /**\n * The readable stream that the response is piped to.\n */\n get responseReadable(): ReadableStream {\n return this.#responseReadable;\n }\n\n constructor(writable: WritableStream, readable: ReadableStream) {\n this.#writer = writable.getWriter();\n this.#encoder = new TextEncoder();\n const reader = readable.getReader();\n\n // in case the user disconnects, let the reader know to cancel\n // this in-turn results in responseReadable being closed\n // and writeSSE method no longer blocks indefinitely\n this.#abortSubscribers.push(async () => {\n await reader.cancel();\n });\n\n this.#responseReadable = new ReadableStream({\n async pull(controller) {\n const { done, value } = await reader.read();\n if (done) {\n controller.close();\n } else {\n controller.enqueue(value);\n }\n },\n cancel: () => {\n this.abort();\n },\n });\n }\n\n async writeRaw(input: Uint8Array | string): Promise<void> {\n try {\n if (typeof input === \"string\") {\n input = this.#encoder.encode(input);\n }\n await this.#writer.write(input);\n } catch {\n // Do nothing.\n }\n }\n\n write(\n input: TArray extends (infer U)[]\n ? U\n : Error<\"To use a streaming response, outputSchema must be an array.\">,\n ): Promise<void> {\n return this.writeRaw(JSON.stringify(input) + \"\\n\");\n }\n\n sleep(ms: number): Promise<unknown> {\n return new Promise((res) => setTimeout(res, ms));\n }\n\n async close() {\n try {\n await this.#writer.close();\n } catch {\n // Do nothing. If you want to handle errors, create a stream by yourself.\n } finally {\n this.#closed = true;\n }\n }\n\n onAbort(listener: () => void | Promise<void>) {\n this.#abortSubscribers.push(listener);\n }\n\n /**\n * Abort the stream.\n * You can call this method when stream is aborted by external event.\n */\n abort() {\n if (!this.aborted) {\n this.#aborted = true;\n this.#abortSubscribers.forEach((subscriber) => subscriber());\n }\n }\n}\n"],"mappings":";AAaA,IAAa,iBAAb,MAAoC;CAClC;CACA;CACA,oBAAoD,EAAE;CACtD;CAEA,WAAoB;CACpB,UAAmB;;;;CAKnB,IAAI,UAAmB;AACrB,SAAO,MAAKA;;;;;CAMd,IAAI,SAAkB;AACpB,SAAO,MAAKC;;;;;CAMd,IAAI,mBAAmC;AACrC,SAAO,MAAKC;;CAGd,YAAY,UAA0B,UAA0B;AAC9D,QAAKC,SAAU,SAAS,WAAW;AACnC,QAAKC,UAAW,IAAI,aAAa;EACjC,MAAM,SAAS,SAAS,WAAW;AAKnC,QAAKC,iBAAkB,KAAK,YAAY;AACtC,SAAM,OAAO,QAAQ;IACrB;AAEF,QAAKH,mBAAoB,IAAI,eAAe;GAC1C,MAAM,KAAK,YAAY;IACrB,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAC3C,QAAI,KACF,YAAW,OAAO;QAElB,YAAW,QAAQ,MAAM;;GAG7B,cAAc;AACZ,SAAK,OAAO;;GAEf,CAAC;;CAGJ,MAAM,SAAS,OAA2C;AACxD,MAAI;AACF,OAAI,OAAO,UAAU,SACnB,SAAQ,MAAKE,QAAS,OAAO,MAAM;AAErC,SAAM,MAAKD,OAAQ,MAAM,MAAM;UACzB;;CAKV,MACE,OAGe;AACf,SAAO,KAAK,SAAS,KAAK,UAAU,MAAM,GAAG,KAAK;;CAGpD,MAAM,IAA8B;AAClC,SAAO,IAAI,SAAS,QAAQ,WAAW,KAAK,GAAG,CAAC;;CAGlD,MAAM,QAAQ;AACZ,MAAI;AACF,SAAM,MAAKA,OAAQ,OAAO;UACpB,WAEE;AACR,SAAKF,SAAU;;;CAInB,QAAQ,UAAsC;AAC5C,QAAKI,iBAAkB,KAAK,SAAS;;;;;;CAOvC,QAAQ;AACN,MAAI,CAAC,KAAK,SAAS;AACjB,SAAKL,UAAW;AAChB,SAAKK,iBAAkB,SAAS,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/api/internal/route.ts
|
|
2
|
+
function getMountRoute(opts) {
|
|
3
|
+
const mountRoute = opts.mountRoute ?? `/api/${opts.name}`;
|
|
4
|
+
if (mountRoute.endsWith("/")) return mountRoute.slice(0, -1);
|
|
5
|
+
return mountRoute;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
export { getMountRoute };
|
|
10
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.js","names":[],"sources":["../../../src/api/internal/route.ts"],"sourcesContent":["export function getMountRoute(opts: { mountRoute?: string; name: string }) {\n const mountRoute = opts.mountRoute ?? `/api/${opts.name}`;\n\n if (mountRoute.endsWith(\"/\")) {\n return mountRoute.slice(0, -1);\n }\n\n return mountRoute;\n}\n"],"mappings":";AAAA,SAAgB,cAAc,MAA6C;CACzE,MAAM,aAAa,KAAK,cAAc,QAAQ,KAAK;AAEnD,KAAI,WAAW,SAAS,IAAI,CAC1B,QAAO,WAAW,MAAM,GAAG,GAAG;AAGhC,QAAO"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { RequestBodyType } from "./request-input-context.js";
|
|
2
|
+
|
|
3
|
+
//#region src/api/mutable-request-state.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Holds mutable request state that can be modified by middleware and consumed by handlers.
|
|
7
|
+
*
|
|
8
|
+
* This class provides a structural way for middleware to modify request data:
|
|
9
|
+
* - Path parameters can be modified
|
|
10
|
+
* - Query/search parameters can be modified
|
|
11
|
+
* - Request body can be overridden
|
|
12
|
+
* - Request headers can be modified
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* // In middleware
|
|
17
|
+
* const state = new MutableRequestState({
|
|
18
|
+
* pathParams: { id: "123" },
|
|
19
|
+
* searchParams: new URLSearchParams("?role=user"),
|
|
20
|
+
* body: { name: "John" },
|
|
21
|
+
* headers: new Headers()
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* // Modify query parameters
|
|
25
|
+
* state.searchParams.set("role", "admin");
|
|
26
|
+
*
|
|
27
|
+
* // Override body
|
|
28
|
+
* state.setBody({ name: "Jane" });
|
|
29
|
+
*
|
|
30
|
+
* // Modify headers
|
|
31
|
+
* state.headers.set("X-Custom", "value");
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
declare class MutableRequestState {
|
|
35
|
+
#private;
|
|
36
|
+
constructor(config: {
|
|
37
|
+
pathParams: Record<string, string>;
|
|
38
|
+
searchParams: URLSearchParams;
|
|
39
|
+
body: RequestBodyType;
|
|
40
|
+
headers: Headers;
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* Path parameters extracted from the route.
|
|
44
|
+
* Can be modified directly (e.g., `state.pathParams.id = "456"`).
|
|
45
|
+
*/
|
|
46
|
+
get pathParams(): Record<string, string>;
|
|
47
|
+
/**
|
|
48
|
+
* URLSearchParams for query parameters.
|
|
49
|
+
* Can be modified using URLSearchParams API (e.g., `state.searchParams.set("key", "value")`).
|
|
50
|
+
*/
|
|
51
|
+
get searchParams(): URLSearchParams;
|
|
52
|
+
/**
|
|
53
|
+
* Request headers.
|
|
54
|
+
* Can be modified using Headers API (e.g., `state.headers.set("X-Custom", "value")`).
|
|
55
|
+
*/
|
|
56
|
+
get headers(): Headers;
|
|
57
|
+
/**
|
|
58
|
+
* Get the current body value.
|
|
59
|
+
* Returns the override if set, otherwise the initial body.
|
|
60
|
+
*/
|
|
61
|
+
get body(): RequestBodyType;
|
|
62
|
+
/**
|
|
63
|
+
* Override the request body.
|
|
64
|
+
* This allows middleware to replace the body that will be seen by the handler.
|
|
65
|
+
*
|
|
66
|
+
* @param body - The new body value
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* // In middleware
|
|
71
|
+
* state.setBody({ modifiedField: "new value" });
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
setBody(body: RequestBodyType): void;
|
|
75
|
+
/**
|
|
76
|
+
* Check if the body has been overridden by middleware.
|
|
77
|
+
*/
|
|
78
|
+
get hasBodyOverride(): boolean;
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { MutableRequestState };
|
|
82
|
+
//# sourceMappingURL=mutable-request-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutable-request-state.d.ts","names":[],"sources":["../../src/api/mutable-request-state.ts"],"sourcesContent":[],"mappings":";;;;;;AA+BA;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,mBAAA;;;gBASG;kBACE;UACR;aACG;;;;;;oBAaO;;;;;sBAQE;;;;;iBAQL;;;;;cAQH;;;;;;;;;;;;;gBAgBE"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
//#region src/api/mutable-request-state.ts
|
|
2
|
+
/**
|
|
3
|
+
* Holds mutable request state that can be modified by middleware and consumed by handlers.
|
|
4
|
+
*
|
|
5
|
+
* This class provides a structural way for middleware to modify request data:
|
|
6
|
+
* - Path parameters can be modified
|
|
7
|
+
* - Query/search parameters can be modified
|
|
8
|
+
* - Request body can be overridden
|
|
9
|
+
* - Request headers can be modified
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* // In middleware
|
|
14
|
+
* const state = new MutableRequestState({
|
|
15
|
+
* pathParams: { id: "123" },
|
|
16
|
+
* searchParams: new URLSearchParams("?role=user"),
|
|
17
|
+
* body: { name: "John" },
|
|
18
|
+
* headers: new Headers()
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Modify query parameters
|
|
22
|
+
* state.searchParams.set("role", "admin");
|
|
23
|
+
*
|
|
24
|
+
* // Override body
|
|
25
|
+
* state.setBody({ name: "Jane" });
|
|
26
|
+
*
|
|
27
|
+
* // Modify headers
|
|
28
|
+
* state.headers.set("X-Custom", "value");
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
var MutableRequestState = class {
|
|
32
|
+
#pathParams;
|
|
33
|
+
#searchParams;
|
|
34
|
+
#headers;
|
|
35
|
+
#initialBody;
|
|
36
|
+
#bodyOverride;
|
|
37
|
+
constructor(config) {
|
|
38
|
+
this.#pathParams = config.pathParams;
|
|
39
|
+
this.#searchParams = config.searchParams;
|
|
40
|
+
this.#headers = config.headers;
|
|
41
|
+
this.#initialBody = config.body;
|
|
42
|
+
this.#bodyOverride = void 0;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Path parameters extracted from the route.
|
|
46
|
+
* Can be modified directly (e.g., `state.pathParams.id = "456"`).
|
|
47
|
+
*/
|
|
48
|
+
get pathParams() {
|
|
49
|
+
return this.#pathParams;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* URLSearchParams for query parameters.
|
|
53
|
+
* Can be modified using URLSearchParams API (e.g., `state.searchParams.set("key", "value")`).
|
|
54
|
+
*/
|
|
55
|
+
get searchParams() {
|
|
56
|
+
return this.#searchParams;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Request headers.
|
|
60
|
+
* Can be modified using Headers API (e.g., `state.headers.set("X-Custom", "value")`).
|
|
61
|
+
*/
|
|
62
|
+
get headers() {
|
|
63
|
+
return this.#headers;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get the current body value.
|
|
67
|
+
* Returns the override if set, otherwise the initial body.
|
|
68
|
+
*/
|
|
69
|
+
get body() {
|
|
70
|
+
return this.#bodyOverride !== void 0 ? this.#bodyOverride : this.#initialBody;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Override the request body.
|
|
74
|
+
* This allows middleware to replace the body that will be seen by the handler.
|
|
75
|
+
*
|
|
76
|
+
* @param body - The new body value
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* // In middleware
|
|
81
|
+
* state.setBody({ modifiedField: "new value" });
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
setBody(body) {
|
|
85
|
+
this.#bodyOverride = body;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if the body has been overridden by middleware.
|
|
89
|
+
*/
|
|
90
|
+
get hasBodyOverride() {
|
|
91
|
+
return this.#bodyOverride !== void 0;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
export { MutableRequestState };
|
|
97
|
+
//# sourceMappingURL=mutable-request-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutable-request-state.js","names":["#pathParams","#searchParams","#headers","#initialBody","#bodyOverride"],"sources":["../../src/api/mutable-request-state.ts"],"sourcesContent":["import type { RequestBodyType } from \"./request-input-context\";\n\n/**\n * Holds mutable request state that can be modified by middleware and consumed by handlers.\n *\n * This class provides a structural way for middleware to modify request data:\n * - Path parameters can be modified\n * - Query/search parameters can be modified\n * - Request body can be overridden\n * - Request headers can be modified\n *\n * @example\n * ```typescript\n * // In middleware\n * const state = new MutableRequestState({\n * pathParams: { id: \"123\" },\n * searchParams: new URLSearchParams(\"?role=user\"),\n * body: { name: \"John\" },\n * headers: new Headers()\n * });\n *\n * // Modify query parameters\n * state.searchParams.set(\"role\", \"admin\");\n *\n * // Override body\n * state.setBody({ name: \"Jane\" });\n *\n * // Modify headers\n * state.headers.set(\"X-Custom\", \"value\");\n * ```\n */\nexport class MutableRequestState {\n readonly #pathParams: Record<string, string>;\n readonly #searchParams: URLSearchParams;\n readonly #headers: Headers;\n // oxlint-disable-next-line no-unused-private-class-members False Positive?\n readonly #initialBody: RequestBodyType;\n #bodyOverride: RequestBodyType | undefined;\n\n constructor(config: {\n pathParams: Record<string, string>;\n searchParams: URLSearchParams;\n body: RequestBodyType;\n headers: Headers;\n }) {\n this.#pathParams = config.pathParams;\n this.#searchParams = config.searchParams;\n this.#headers = config.headers;\n this.#initialBody = config.body;\n this.#bodyOverride = undefined;\n }\n\n /**\n * Path parameters extracted from the route.\n * Can be modified directly (e.g., `state.pathParams.id = \"456\"`).\n */\n get pathParams(): Record<string, string> {\n return this.#pathParams;\n }\n\n /**\n * URLSearchParams for query parameters.\n * Can be modified using URLSearchParams API (e.g., `state.searchParams.set(\"key\", \"value\")`).\n */\n get searchParams(): URLSearchParams {\n return this.#searchParams;\n }\n\n /**\n * Request headers.\n * Can be modified using Headers API (e.g., `state.headers.set(\"X-Custom\", \"value\")`).\n */\n get headers(): Headers {\n return this.#headers;\n }\n\n /**\n * Get the current body value.\n * Returns the override if set, otherwise the initial body.\n */\n get body(): RequestBodyType {\n return this.#bodyOverride !== undefined ? this.#bodyOverride : this.#initialBody;\n }\n\n /**\n * Override the request body.\n * This allows middleware to replace the body that will be seen by the handler.\n *\n * @param body - The new body value\n *\n * @example\n * ```typescript\n * // In middleware\n * state.setBody({ modifiedField: \"new value\" });\n * ```\n */\n setBody(body: RequestBodyType): void {\n this.#bodyOverride = body;\n }\n\n /**\n * Check if the body has been overridden by middleware.\n */\n get hasBodyOverride(): boolean {\n return this.#bodyOverride !== undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,IAAa,sBAAb,MAAiC;CAC/B,CAASA;CACT,CAASC;CACT,CAASC;CAET,CAASC;CACT;CAEA,YAAY,QAKT;AACD,QAAKH,aAAc,OAAO;AAC1B,QAAKC,eAAgB,OAAO;AAC5B,QAAKC,UAAW,OAAO;AACvB,QAAKC,cAAe,OAAO;AAC3B,QAAKC,eAAgB;;;;;;CAOvB,IAAI,aAAqC;AACvC,SAAO,MAAKJ;;;;;;CAOd,IAAI,eAAgC;AAClC,SAAO,MAAKC;;;;;;CAOd,IAAI,UAAmB;AACrB,SAAO,MAAKC;;;;;;CAOd,IAAI,OAAwB;AAC1B,SAAO,MAAKE,iBAAkB,SAAY,MAAKA,eAAgB,MAAKD;;;;;;;;;;;;;;CAetE,QAAQ,MAA6B;AACnC,QAAKC,eAAgB;;;;;CAMvB,IAAI,kBAA2B;AAC7B,SAAO,MAAKA,iBAAkB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//#region src/api/request-context-storage.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Typed wrapper around AsyncLocalStorage for managing per-request data storage.
|
|
4
|
+
* Each fragment instance has its own storage to ensure proper isolation.
|
|
5
|
+
*
|
|
6
|
+
* TRequestStorage represents the type of data stored per-request (e.g., { userId: string, requestId: number })
|
|
7
|
+
*
|
|
8
|
+
* Note: The data stored should be an object that can be mutated during the request lifecycle.
|
|
9
|
+
* For example, you can store { uow: UnitOfWork } and modify properties on that object.
|
|
10
|
+
*
|
|
11
|
+
* @internal - Used by @fragno-dev/db, not part of public API
|
|
12
|
+
*/
|
|
13
|
+
declare class RequestContextStorage<TRequestStorage> {
|
|
14
|
+
#private;
|
|
15
|
+
constructor();
|
|
16
|
+
/**
|
|
17
|
+
* Run a callback with the given data available via getStore().
|
|
18
|
+
* This establishes the async context for the duration of the callback.
|
|
19
|
+
*/
|
|
20
|
+
run<T>(data: TRequestStorage, callback: () => T): T;
|
|
21
|
+
run<T>(data: TRequestStorage, callback: () => Promise<T>): Promise<T>;
|
|
22
|
+
/**
|
|
23
|
+
* Get the current stored data from AsyncLocalStorage.
|
|
24
|
+
* @throws an error if called outside of a run() callback.
|
|
25
|
+
*
|
|
26
|
+
* Note: The returned object can be mutated. Changes will be visible to all code
|
|
27
|
+
* running within the same async context.
|
|
28
|
+
*/
|
|
29
|
+
getStore(): TRequestStorage;
|
|
30
|
+
/**
|
|
31
|
+
* Enter a new async context with fresh storage.
|
|
32
|
+
* This is typically called at the start of a request handler.
|
|
33
|
+
*
|
|
34
|
+
* @param initializer Function that returns the initial storage data
|
|
35
|
+
* @param callback The request handler to execute with the storage
|
|
36
|
+
*/
|
|
37
|
+
runWithInitializer<T>(initializer: () => TRequestStorage, callback: () => T): T;
|
|
38
|
+
runWithInitializer<T>(initializer: () => TRequestStorage, callback: () => Promise<T>): Promise<T>;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { RequestContextStorage };
|
|
42
|
+
//# sourceMappingURL=request-context-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-context-storage.d.ts","names":[],"sources":["../../src/api/request-context-storage.ts"],"sourcesContent":[],"mappings":";;AAaA;;;;;;;;;;AAyC2C,cAzC9B,qBAyC8B,CAAA,eAAA,CAAA,CAAA;EAAiC,CAAA,OAAA;EAAI,WAAA,CAAA;EACrC;;;;EAA8C,GAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EA/B1E,eA+B0E,EAAA,QAAA,EAAA,GAAA,GA/BzC,CA+ByC,CAAA,EA/BrC,CA+BqC;EAAO,GAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EA9BjF,eA8BiF,EAAA,QAAA,EAAA,GAAA,GA9BhD,OA8BgD,CA9BxC,CA8BwC,CAAA,CAAA,EA9BnC,OA8BmC,CA9B3B,CA8B2B,CAAA;;;;;;;;cAlBlF;;;;;;;;2CAiB6B,iCAAiC,IAAI;2CACrC,iCAAiC,QAAQ,KAAK,QAAQ"}
|