@nestia/fetcher 14.0.0 → 14.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/AesPkcs5.d.ts +19 -2
- package/lib/AesPkcs5.js +21 -4
- package/lib/AesPkcs5.js.map +1 -1
- package/lib/AesPkcs5.mjs +2 -2
- package/lib/AesPkcs5.mjs.map +1 -1
- package/lib/EncryptedFetcher.d.ts +34 -3
- package/lib/EncryptedFetcher.js +44 -54
- package/lib/EncryptedFetcher.js.map +1 -1
- package/lib/EncryptedFetcher.mjs +30 -25
- package/lib/EncryptedFetcher.mjs.map +1 -1
- package/lib/FormDataInput.d.ts +21 -8
- package/lib/IConnection.d.ts +49 -14
- package/lib/IEncryptionPassword.d.ts +18 -2
- package/lib/IFetchEvent.d.ts +25 -0
- package/lib/IFetchEvent.js +0 -18
- package/lib/IFetchEvent.js.map +1 -1
- package/lib/IFetchRoute.d.ts +19 -0
- package/lib/IPropagation.d.ts +34 -11
- package/lib/NestiaSimulator.d.ts +45 -2
- package/lib/NestiaSimulator.js +65 -14
- package/lib/NestiaSimulator.js.map +1 -1
- package/lib/NestiaSimulator.mjs +39 -9
- package/lib/NestiaSimulator.mjs.map +1 -1
- package/lib/PathParameter.d.ts +31 -0
- package/lib/PathParameter.js +41 -0
- package/lib/PathParameter.js.map +1 -0
- package/lib/PathParameter.mjs +13 -0
- package/lib/PathParameter.mjs.map +1 -0
- package/lib/PlainFetcher.d.ts +36 -5
- package/lib/PlainFetcher.js +6 -2
- package/lib/PlainFetcher.js.map +1 -1
- package/lib/PlainFetcher.mjs.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +2 -1
- package/lib/internal/FetcherBase.js +35 -12
- package/lib/internal/FetcherBase.js.map +1 -1
- package/lib/internal/FetcherBase.mjs +14 -10
- package/lib/internal/FetcherBase.mjs.map +1 -1
- package/lib/internal/is_binary_response_content_type.d.ts +12 -0
- package/lib/internal/is_binary_response_content_type.js +12 -0
- package/lib/internal/is_binary_response_content_type.js.map +1 -1
- package/lib/internal/is_binary_response_content_type.mjs +12 -0
- package/lib/internal/is_binary_response_content_type.mjs.map +1 -1
- package/package.json +4 -3
- package/src/AesPkcs5.ts +21 -4
- package/src/EncryptedFetcher.ts +77 -57
- package/src/FormDataInput.ts +26 -10
- package/src/IConnection.ts +54 -18
- package/src/IEncryptionPassword.ts +18 -2
- package/src/IFetchEvent.ts +32 -19
- package/src/IFetchRoute.ts +19 -0
- package/src/IPropagation.ts +41 -17
- package/src/NestiaSimulator.ts +83 -17
- package/src/PathParameter.ts +40 -0
- package/src/PlainFetcher.ts +50 -5
- package/src/index.ts +1 -0
- package/src/internal/FetcherBase.ts +49 -10
- package/src/internal/is_binary_response_content_type.ts +12 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NestiaSimulator.mjs","names":[],"sources":["../src/NestiaSimulator.ts"],"sourcesContent":["import { HttpError } from \"./HttpError\";\nimport { join_host_and_path } from \"./internal/join_host_and_path\";\n\nexport namespace NestiaSimulator {\n export interface IProps {\n host: string;\n path: string;\n method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\";\n contentType: string;\n }\n\n export const assert = (props: IProps) => {\n return {\n param: param(props),\n query: query(props),\n body: body(props),\n };\n };\n const param =\n (props: IProps) =>\n (name: string) =>\n <T>(task: () => T): void => {\n validate((exp) => `URL parameter \"${name}\" is not ${exp.expected} type.`)(\n props,\n )(task);\n };\n\n const query =\n (props: IProps) =>\n <T>(task: () => T): void =>\n validate(\n () => \"Request query parameters are not following the promised type.\",\n )(props)(task);\n\n const body =\n (props: IProps) =>\n <T>(task: () => T): void =>\n validate(() => \"Request body is not following the promised type.\")(props)(\n task,\n );\n\n const validate =\n (message: (exp: TypeGuardError) => string
|
|
1
|
+
{"version":3,"file":"NestiaSimulator.mjs","names":[],"sources":["../src/NestiaSimulator.ts"],"sourcesContent":["import { HttpError } from \"./HttpError\";\nimport { join_host_and_path } from \"./internal/join_host_and_path\";\n\n/**\n * Request validation for the mockup simulator of a generated SDK.\n *\n * A simulated function does not call a server. It validates its input with\n * typia and, when the input is wrong, throws the `HttpError` with status 400\n * that the real server would answer with.\n *\n * @evidence contracts/common.md#principled-implementation Each validator runs the caller's assertion and converts a readable typia `TypeGuardError` shape into an `HttpError` 400 whose JSON body carries the method, path, expected type and value plus a message naming the failing part. A shared snapshot reads each needed property once; malformed or unreadable shapes rethrow the caller's original value. Payload values must support JSON serialization, whose errors still propagate.\n * @evidence contracts/common.md#clear-and-simple-design One public entry point, `assert`, returns four validators that differ only in their message, sharing one private conversion; the shape snapshot reader and the error interface are module-private.\n * @evidence contracts/common.md#prohibited-implementation-shortcuts Classification checks the readable error structure (method, path, expected type, name, message and stack) rather than its class, then captures the payload value. A value that lacks any of those fields with the expected types, or whose property access throws, is not classified as a type guard failure and is rethrown unchanged; unrelated task errors are neither replaced nor swallowed.\n * @evidence contracts/common.md#meaningful-documentation The comment states what the simulator validates and what it throws.\n */\nexport namespace NestiaSimulator {\n /**\n * Route facts the simulator needs to build its 400 error: the host, the path,\n * and the method.\n *\n * `contentType` is the content type of the route's success response, which\n * the generated code answers with; the simulated 400 is JSON whatever it is.\n *\n * @evidence contracts/common.md#principled-implementation The host, path, and method identify the request in the error, and the content type describes the success response of the generated function, which the generated code answers with.\n * @evidence contracts/common.md#clear-and-simple-design A four-field record with no behavior.\n * @evidence contracts/common.md#prohibited-implementation-shortcuts The values are supplied by the generated SDK for its own route.\n * @evidence contracts/common.md#meaningful-documentation The comment says what each part is used for, with the `contentType` member documenting when it is `null`.\n */\n export interface IProps {\n host: string;\n path: string;\n method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\" | \"HEAD\";\n\n /**\n * Content type of the route's success response, `null` for one without a\n * body such as `HEAD`'s. The simulated 400 is JSON whatever it is, as the\n * server's is.\n */\n contentType: string | null;\n }\n\n /**\n * Creates the validators of one simulated route: `param(name)`, `query`,\n * `body`, and `headers`.\n *\n * Each validator takes the closure that performs the typia assertion. A\n * failed assertion throws an `HttpError` with status 400 and a JSON body; any\n * other error is rethrown as it is.\n *\n * @evidence contracts/common.md#principled-implementation The four validators share the conversion in `validate` and differ in the message they attach, which names the URL parameter or states that the query, body, or headers do not follow the promised type.\n * @evidence contracts/common.md#clear-and-simple-design One function returning the four validators as an object, so a generated simulator has one import.\n * @evidence contracts/common.md#prohibited-implementation-shortcuts The HTTP error is the one the real server returns; nothing is simulated beyond running the assertion.\n * @evidence contracts/common.md#meaningful-documentation The comment states what it returns and what each validator throws.\n */\n export const assert = (props: IProps) => {\n return {\n param: param(props),\n query: query(props),\n body: body(props),\n headers: headers(props),\n };\n };\n const param =\n (props: IProps) =>\n (name: string) =>\n <T>(task: () => T): void => {\n validate((exp) => `URL parameter \"${name}\" is not ${exp.expected} type.`)(\n props,\n )(task);\n };\n\n const query =\n (props: IProps) =>\n <T>(task: () => T): void =>\n validate(\n () => \"Request query parameters are not following the promised type.\",\n )(props)(task);\n\n const body =\n (props: IProps) =>\n <T>(task: () => T): void =>\n validate(() => \"Request body is not following the promised type.\")(props)(\n task,\n );\n\n const headers =\n (props: IProps) =>\n <T>(task: () => T): void =>\n validate(() => \"Request headers are not following the promised type.\")(\n props,\n )(task);\n\n const validate =\n (message: (exp: TypeGuardError) => string) =>\n (props: IProps) =>\n <T>(task: () => T): void => {\n try {\n task();\n } catch (exp) {\n const guard: TypeGuardError | null = readTypeGuardError(exp);\n if (guard !== null)\n throw new HttpError(\n props.method,\n join_host_and_path(props.host, props.path),\n 400,\n {\n \"Content-Type\": \"application/json\",\n },\n JSON.stringify({\n method: guard.method,\n path: guard.path,\n expected: guard.expected,\n value: guard.value,\n message: message(guard),\n }),\n );\n throw exp;\n }\n };\n}\n\nconst readTypeGuardError = (input: any): TypeGuardError | null => {\n if (typeof input !== \"object\" || input === null) return null;\n try {\n const method: unknown = input.method;\n if (typeof method !== \"string\") return null;\n const path: unknown = input.path;\n if (path !== undefined && typeof path !== \"string\") return null;\n const expected: unknown = input.expected;\n if (typeof expected !== \"string\") return null;\n const name: unknown = input.name;\n if (typeof name !== \"string\") return null;\n const message: unknown = input.message;\n if (typeof message !== \"string\") return null;\n const stack: unknown = input.stack;\n if (stack !== undefined && typeof stack !== \"string\") return null;\n const value: unknown = input.value;\n return { method, path, expected, name, message, stack, value };\n } catch {\n return null;\n }\n};\n\ninterface TypeGuardError extends Error {\n method: string;\n path: string | undefined;\n expected: string;\n value: any;\n}\n"],"mappings":";;;AAeO,IAAA;;4BAuCkB,UAAkB;EACvC,OAAO;GACL,OAAO,MAAM,KAAK;GAClB,OAAO,MAAM,KAAK;GAClB,MAAM,KAAK,KAAK;GAChB,SAAS,QAAQ,KAAK;EACxB;CACF;CACA,MAAM,SACH,WACA,UACG,SAAwB;EAC1B,UAAU,QAAQ,kBAAkB,KAAK,WAAW,IAAI,SAAS,OAAO,CAAC,CACvE,KACF,CAAC,CAAC,IAAI;CACR;CAEF,MAAM,SACH,WACG,SACF,eACQ,+DACR,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI;CAEjB,MAAM,QACH,WACG,SACF,eAAe,kDAAkD,CAAC,CAAC,KAAK,CAAC,CACvE,IACF;CAEJ,MAAM,WACH,WACG,SACF,eAAe,sDAAsD,CAAC,CACpE,KACF,CAAC,CAAC,IAAI;CAEV,MAAM,YACH,aACA,WACG,SAAwB;EAC1B,IAAI;GACF,KAAK;EACP,SAAS,KAAK;GACZ,MAAM,QAA+B,mBAAmB,GAAG;GAC3D,IAAI,UAAU,MACZ,MAAM,IAAI,UACR,MAAM,QACN,mBAAmB,MAAM,MAAM,MAAM,IAAI,GACzC,KACA,EACE,gBAAgB,mBAClB,GACA,KAAK,UAAU;IACb,QAAQ,MAAM;IACd,MAAM,MAAM;IACZ,UAAU,MAAM;IAChB,OAAO,MAAM;IACb,SAAS,QAAQ,KAAK;GACxB,CAAC,CACH;GACF,MAAM;EACR;CACF;GACH,oBAAA,kBAAA,CAAA,EAAD;AAEA,MAAM,sBAAsB,UAAsC;CAChE,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,IAAI;EACF,MAAM,SAAkB,MAAM;EAC9B,IAAI,OAAO,WAAW,UAAU,OAAO;EACvC,MAAM,OAAgB,MAAM;EAC5B,IAAI,SAAS,KAAA,KAAa,OAAO,SAAS,UAAU,OAAO;EAC3D,MAAM,WAAoB,MAAM;EAChC,IAAI,OAAO,aAAa,UAAU,OAAO;EACzC,MAAM,OAAgB,MAAM;EAC5B,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,MAAM,UAAmB,MAAM;EAC/B,IAAI,OAAO,YAAY,UAAU,OAAO;EACxC,MAAM,QAAiB,MAAM;EAC7B,IAAI,UAAU,KAAA,KAAa,OAAO,UAAU,UAAU,OAAO;EAE7D,OAAO;GAAE;GAAQ;GAAM;GAAU;GAAM;GAAS;GAAO,OADhC,MAAM;EACgC;CAC/D,QAAQ;EACN,OAAO;CACT;AACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The path parameters of a generated SDK function, as its URL carries them.
|
|
3
|
+
*
|
|
4
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
5
|
+
* @evidence contracts/common.md#principled-implementation A path parameter is one URL path segment, so the value must be encoded as one segment and must never spell a dot segment, which the URL parser would resolve away.
|
|
6
|
+
* @evidence contracts/common.md#clear-and-simple-design One namespace with one function, kept apart so both the SDK generator's output and hand-written callers use the same rule.
|
|
7
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The rule applies to every value; no parameter name is special-cased.
|
|
8
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the purpose of the namespace and the function documents the dot-segment refusal.
|
|
9
|
+
*/
|
|
10
|
+
export declare namespace PathParameter {
|
|
11
|
+
/**
|
|
12
|
+
* The parameter's value as one URL path segment: its text URI-encoded, or
|
|
13
|
+
* `"null"` when the value is nullish.
|
|
14
|
+
*
|
|
15
|
+
* `.` and `..` are refused. `encodeURIComponent` leaves them as they are, and
|
|
16
|
+
* the URL parser that `fetch` and `new URL()` share resolves them as dot
|
|
17
|
+
* segments, so the request would reach the parent path instead of the route,
|
|
18
|
+
* with the value gone. Their percent-encoded form is a dot segment by the
|
|
19
|
+
* same standard, so no spelling carries them.
|
|
20
|
+
*
|
|
21
|
+
* @param name Name of the parameter, for the error
|
|
22
|
+
* @param value Value of the parameter
|
|
23
|
+
* @returns The URI-encoded segment
|
|
24
|
+
* @throws Error when the value is `.` or `..`
|
|
25
|
+
* @evidence contracts/common.md#principled-implementation encodeURIComponent produces a single segment for well-formed Unicode text and throws URIError for unpaired surrogates; nullish input becomes the text null. The encoded text . or .. is refused because the WHATWG URL parser treats it and its percent-encoded spelling as a dot segment.
|
|
26
|
+
* @evidence contracts/common.md#clear-and-simple-design One conversion and one guard, with the reason for the guard stated in the comment.
|
|
27
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The guard prevents a request from silently reaching a different route, so it is a correctness check rather than a workaround for a test.
|
|
28
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the encoding, the nullish rule, the refused segments, their reason, and the thrown error.
|
|
29
|
+
*/
|
|
30
|
+
const encode: (name: string, value: unknown) => string;
|
|
31
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PathParameter = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The path parameters of a generated SDK function, as its URL carries them.
|
|
6
|
+
*
|
|
7
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
8
|
+
* @evidence contracts/common.md#principled-implementation A path parameter is one URL path segment, so the value must be encoded as one segment and must never spell a dot segment, which the URL parser would resolve away.
|
|
9
|
+
* @evidence contracts/common.md#clear-and-simple-design One namespace with one function, kept apart so both the SDK generator's output and hand-written callers use the same rule.
|
|
10
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The rule applies to every value; no parameter name is special-cased.
|
|
11
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the purpose of the namespace and the function documents the dot-segment refusal.
|
|
12
|
+
*/
|
|
13
|
+
var PathParameter;
|
|
14
|
+
(function (PathParameter) {
|
|
15
|
+
/**
|
|
16
|
+
* The parameter's value as one URL path segment: its text URI-encoded, or
|
|
17
|
+
* `"null"` when the value is nullish.
|
|
18
|
+
*
|
|
19
|
+
* `.` and `..` are refused. `encodeURIComponent` leaves them as they are, and
|
|
20
|
+
* the URL parser that `fetch` and `new URL()` share resolves them as dot
|
|
21
|
+
* segments, so the request would reach the parent path instead of the route,
|
|
22
|
+
* with the value gone. Their percent-encoded form is a dot segment by the
|
|
23
|
+
* same standard, so no spelling carries them.
|
|
24
|
+
*
|
|
25
|
+
* @param name Name of the parameter, for the error
|
|
26
|
+
* @param value Value of the parameter
|
|
27
|
+
* @returns The URI-encoded segment
|
|
28
|
+
* @throws Error when the value is `.` or `..`
|
|
29
|
+
* @evidence contracts/common.md#principled-implementation encodeURIComponent produces a single segment for well-formed Unicode text and throws URIError for unpaired surrogates; nullish input becomes the text null. The encoded text . or .. is refused because the WHATWG URL parser treats it and its percent-encoded spelling as a dot segment.
|
|
30
|
+
* @evidence contracts/common.md#clear-and-simple-design One conversion and one guard, with the reason for the guard stated in the comment.
|
|
31
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The guard prevents a request from silently reaching a different route, so it is a correctness check rather than a workaround for a test.
|
|
32
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the encoding, the nullish rule, the refused segments, their reason, and the thrown error.
|
|
33
|
+
*/
|
|
34
|
+
PathParameter.encode = (name, value) => {
|
|
35
|
+
const encoded = encodeURIComponent(value === null || value === undefined ? "null" : String(value));
|
|
36
|
+
if (encoded === "." || encoded === "..")
|
|
37
|
+
throw new Error(`Error on PathParameter.encode(): path parameter "${name}" is ${JSON.stringify(encoded)}, a dot segment the URL resolves away, which would send the request to another path.`);
|
|
38
|
+
return encoded;
|
|
39
|
+
};
|
|
40
|
+
})(PathParameter || (exports.PathParameter = PathParameter = {}));
|
|
41
|
+
//# sourceMappingURL=PathParameter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PathParameter.js","sourceRoot":"","sources":["../src/PathParameter.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,IAAiB,aAAa,CA8B7B;AA9BD,WAAiB,aAAa;IAC5B;;;;;;;;;;;;;;;;;;OAkBG;IACU,oBAAM,GAAG,CAAC,IAAY,EAAE,KAAc,EAAU,EAAE;QAC7D,MAAM,OAAO,GAAW,kBAAkB,CACxC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAC/D,CAAC;QACF,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI;YACrC,MAAM,IAAI,KAAK,CACb,oDAAoD,IAAI,QAAQ,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,sFAAsF,CAC9K,CAAC;QACJ,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;AACJ,CAAC,EA9BgB,aAAa,aAAb,aAAa,GAAb,aAAa,QA8B7B"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/PathParameter.ts
|
|
2
|
+
let PathParameter;
|
|
3
|
+
(function(_PathParameter) {
|
|
4
|
+
_PathParameter.encode = (name, value) => {
|
|
5
|
+
const encoded = encodeURIComponent(value === null || value === void 0 ? "null" : String(value));
|
|
6
|
+
if (encoded === "." || encoded === "..") throw new Error(`Error on PathParameter.encode(): path parameter "${name}" is ${JSON.stringify(encoded)}, a dot segment the URL resolves away, which would send the request to another path.`);
|
|
7
|
+
return encoded;
|
|
8
|
+
};
|
|
9
|
+
})(PathParameter || (PathParameter = {}));
|
|
10
|
+
//#endregion
|
|
11
|
+
export { PathParameter };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=PathParameter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PathParameter.mjs","names":[],"sources":["../src/PathParameter.ts"],"sourcesContent":["/**\n * The path parameters of a generated SDK function, as its URL carries them.\n *\n * @author Jeongho Nam - https://github.com/samchon\n * @evidence contracts/common.md#principled-implementation A path parameter is one URL path segment, so the value must be encoded as one segment and must never spell a dot segment, which the URL parser would resolve away.\n * @evidence contracts/common.md#clear-and-simple-design One namespace with one function, kept apart so both the SDK generator's output and hand-written callers use the same rule.\n * @evidence contracts/common.md#prohibited-implementation-shortcuts The rule applies to every value; no parameter name is special-cased.\n * @evidence contracts/common.md#meaningful-documentation The comment states the purpose of the namespace and the function documents the dot-segment refusal.\n */\nexport namespace PathParameter {\n /**\n * The parameter's value as one URL path segment: its text URI-encoded, or\n * `\"null\"` when the value is nullish.\n *\n * `.` and `..` are refused. `encodeURIComponent` leaves them as they are, and\n * the URL parser that `fetch` and `new URL()` share resolves them as dot\n * segments, so the request would reach the parent path instead of the route,\n * with the value gone. Their percent-encoded form is a dot segment by the\n * same standard, so no spelling carries them.\n *\n * @param name Name of the parameter, for the error\n * @param value Value of the parameter\n * @returns The URI-encoded segment\n * @throws Error when the value is `.` or `..`\n * @evidence contracts/common.md#principled-implementation encodeURIComponent produces a single segment for well-formed Unicode text and throws URIError for unpaired surrogates; nullish input becomes the text null. The encoded text . or .. is refused because the WHATWG URL parser treats it and its percent-encoded spelling as a dot segment.\n * @evidence contracts/common.md#clear-and-simple-design One conversion and one guard, with the reason for the guard stated in the comment.\n * @evidence contracts/common.md#prohibited-implementation-shortcuts The guard prevents a request from silently reaching a different route, so it is a correctness check rather than a workaround for a test.\n * @evidence contracts/common.md#meaningful-documentation The comment states the encoding, the nullish rule, the refused segments, their reason, and the thrown error.\n */\n export const encode = (name: string, value: unknown): string => {\n const encoded: string = encodeURIComponent(\n value === null || value === undefined ? \"null\" : String(value),\n );\n if (encoded === \".\" || encoded === \"..\")\n throw new Error(\n `Error on PathParameter.encode(): path parameter \"${name}\" is ${JSON.stringify(encoded)}, a dot segment the URL resolves away, which would send the request to another path.`,\n );\n return encoded;\n };\n}\n"],"mappings":";AASO,IAAA;;0BAoBkB,MAAc,UAA2B;EAC9D,MAAM,UAAkB,mBACtB,UAAU,QAAQ,UAAU,KAAA,IAAY,SAAS,OAAO,KAAK,CAC/D;EACA,IAAI,YAAY,OAAO,YAAY,MACjC,MAAM,IAAI,MACR,oDAAoD,KAAK,OAAO,KAAK,UAAU,OAAO,EAAE,qFAC1F;EACF,OAAO;CACT;GACD,kBAAA,gBAAA,CAAA,EAAD"}
|
package/lib/PlainFetcher.d.ts
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import { IConnection } from "./IConnection";
|
|
2
2
|
import { IFetchRoute } from "./IFetchRoute";
|
|
3
|
-
import { IPropagation } from "./IPropagation";
|
|
4
3
|
/**
|
|
5
4
|
* Utility class for `fetch` functions used in `@nestia/sdk`.
|
|
6
5
|
*
|
|
7
6
|
* `PlainFetcher` is a utility class designed for SDK functions generated by
|
|
8
7
|
* [`@nestia/sdk`](https://nestia.io/docs/sdk/sdk), interacting with the remote
|
|
9
|
-
* HTTP
|
|
8
|
+
* HTTP server API. In other words, this is a collection of dedicated `fetch()`
|
|
10
9
|
* functions for `@nestia/sdk`.
|
|
11
10
|
*
|
|
12
11
|
* For reference, `PlainFetcher` class does not encrypt or decrypt the body data
|
|
13
12
|
* at all. It just delivers plain data without any post processing. If you've
|
|
14
13
|
* defined a controller method through `@EncryptedRoute` or `@EncryptedBody`
|
|
15
|
-
* decorator, then {@
|
|
14
|
+
* decorator, then {@link EncryptedFetcher} class would be used instead.
|
|
16
15
|
*
|
|
17
16
|
* @author Jeongho Nam - https://github.com/samchon
|
|
17
|
+
* @evidence contracts/common.md#principled-implementation The codecs preserve transformed bodies, while FetcherBase owns JSON, form and binary handling. Encrypted metadata is refused before transport. The shared pipeline removes caller Content-Type case-insensitively so multipart boundaries remain fetch-owned, normalizes only host/path separator boundaries, and classifies 200, 201 and the route's configured success status.
|
|
18
|
+
* @evidence contracts/common.md#clear-and-simple-design Two public operations that mirror `EncryptedFetcher`, with the encryption guard as their only own logic.
|
|
19
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The refusal is the contract with the generated SDK, which chooses `EncryptedFetcher` for encrypted routes; no route or header is special-cased.
|
|
20
|
+
* @evidence contracts/common.md#meaningful-documentation The namespace prose says when the generated SDK uses this fetcher and that it does no encryption.
|
|
18
21
|
*/
|
|
19
22
|
export declare namespace PlainFetcher {
|
|
20
23
|
/**
|
|
@@ -23,6 +26,10 @@ export declare namespace PlainFetcher {
|
|
|
23
26
|
* @param connection Connection information for the remote HTTP server
|
|
24
27
|
* @param route Route information about the target API
|
|
25
28
|
* @returns Nothing because of `HEAD` method
|
|
29
|
+
* @evidence contracts/common.md#principled-implementation The overloads narrow arguments by method; the implementation refuses encryption metadata and delegates to FetcherBase.request. Failed statuses become HttpError with their original text, successful HEAD has no data, and binary successes transfer response.body unchanged or create a synchronously closed empty stream if absent. Stream consumption and cancellation belong to the caller.
|
|
30
|
+
* @evidence contracts/common.md#clear-and-simple-design One guard and one delegation, with the overloads only splitting the types.
|
|
31
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The guard follows the route metadata, not a path or a connection.
|
|
32
|
+
* @evidence contracts/common.md#meaningful-documentation Each overload documents its parameters and return value.
|
|
26
33
|
*/
|
|
27
34
|
function fetch(connection: IConnection, route: IFetchRoute<"HEAD">): Promise<void>;
|
|
28
35
|
/**
|
|
@@ -41,6 +48,30 @@ export declare namespace PlainFetcher {
|
|
|
41
48
|
* @returns Response body data from the remote API
|
|
42
49
|
*/
|
|
43
50
|
function fetch<Input, Output>(connection: IConnection, route: IFetchRoute<"POST" | "PUT" | "PATCH" | "DELETE">, input?: Input, stringify?: (input: Input) => string): Promise<Output>;
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Fetch function that returns every response as an {@link IPropagation}.
|
|
53
|
+
*
|
|
54
|
+
* An HTTP failure status is returned as a failed branch instead of being
|
|
55
|
+
* thrown. A route that declares an encrypted body and a transport failure
|
|
56
|
+
* still throw. The output must describe numeric status branches with boolean
|
|
57
|
+
* success and string or string-array headers; its data type remains
|
|
58
|
+
* caller-owned.
|
|
59
|
+
*
|
|
60
|
+
* @evidence contracts/common.md#principled-implementation The implementation refuses an encrypted route and delegates to `FetcherBase.propagate`. Its structural branch constraint accepts numeric literal successes, numeric range failures and unknown-status fallback without instantiating a status map with any, while requiring boolean success and actual numeric status/header shapes.
|
|
61
|
+
* @evidence contracts/common.md#clear-and-simple-design One guard and one delegation, with the overloads only splitting the types.
|
|
62
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The function adds no status-specific branch: the success flag comes from the status rules in `FetcherBase`.
|
|
63
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states what the returned union carries and which failures still throw.
|
|
64
|
+
*/
|
|
65
|
+
function propagate<Output extends {
|
|
66
|
+
success: boolean;
|
|
67
|
+
status: number;
|
|
68
|
+
headers: Record<string, string | string[]>;
|
|
69
|
+
data: unknown;
|
|
70
|
+
}>(connection: IConnection, route: IFetchRoute<"GET" | "HEAD">): Promise<Output>;
|
|
71
|
+
function propagate<Input, Output extends {
|
|
72
|
+
success: boolean;
|
|
73
|
+
status: number;
|
|
74
|
+
headers: Record<string, string | string[]>;
|
|
75
|
+
data: unknown;
|
|
76
|
+
}>(connection: IConnection, route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">, input?: Input, stringify?: (input: Input) => string): Promise<Output>;
|
|
46
77
|
}
|
package/lib/PlainFetcher.js
CHANGED
|
@@ -16,15 +16,19 @@ const FetcherBase_1 = require("./internal/FetcherBase");
|
|
|
16
16
|
*
|
|
17
17
|
* `PlainFetcher` is a utility class designed for SDK functions generated by
|
|
18
18
|
* [`@nestia/sdk`](https://nestia.io/docs/sdk/sdk), interacting with the remote
|
|
19
|
-
* HTTP
|
|
19
|
+
* HTTP server API. In other words, this is a collection of dedicated `fetch()`
|
|
20
20
|
* functions for `@nestia/sdk`.
|
|
21
21
|
*
|
|
22
22
|
* For reference, `PlainFetcher` class does not encrypt or decrypt the body data
|
|
23
23
|
* at all. It just delivers plain data without any post processing. If you've
|
|
24
24
|
* defined a controller method through `@EncryptedRoute` or `@EncryptedBody`
|
|
25
|
-
* decorator, then {@
|
|
25
|
+
* decorator, then {@link EncryptedFetcher} class would be used instead.
|
|
26
26
|
*
|
|
27
27
|
* @author Jeongho Nam - https://github.com/samchon
|
|
28
|
+
* @evidence contracts/common.md#principled-implementation The codecs preserve transformed bodies, while FetcherBase owns JSON, form and binary handling. Encrypted metadata is refused before transport. The shared pipeline removes caller Content-Type case-insensitively so multipart boundaries remain fetch-owned, normalizes only host/path separator boundaries, and classifies 200, 201 and the route's configured success status.
|
|
29
|
+
* @evidence contracts/common.md#clear-and-simple-design Two public operations that mirror `EncryptedFetcher`, with the encryption guard as their only own logic.
|
|
30
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The refusal is the contract with the generated SDK, which chooses `EncryptedFetcher` for encrypted routes; no route or header is special-cased.
|
|
31
|
+
* @evidence contracts/common.md#meaningful-documentation The namespace prose says when the generated SDK uses this fetcher and that it does no encryption.
|
|
28
32
|
*/
|
|
29
33
|
var PlainFetcher;
|
|
30
34
|
(function (PlainFetcher) {
|
package/lib/PlainFetcher.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlainFetcher.js","sourceRoot":"","sources":["../src/PlainFetcher.ts"],"names":[],"mappings":";;;;;;;;;;;;AAGA,wDAAqD;AAErD
|
|
1
|
+
{"version":3,"file":"PlainFetcher.js","sourceRoot":"","sources":["../src/PlainFetcher.ts"],"names":[],"mappings":";;;;;;;;;;;;AAGA,wDAAqD;AAErD;;;;;;;;;;;;;;;;;;GAkBG;AACH,IAAiB,YAAY,CA6H5B;AA7HD,WAAiB,YAAY;IA2C3B,SAAsB,KAAK,CACzB,UAAuB,EACvB,KAAwE,EACxE,KAAa,EACb,SAAoC;;;YAEpC,IAAI,CAAA,MAAA,KAAK,CAAC,OAAO,0CAAE,SAAS,MAAK,IAAI,IAAI,CAAA,MAAA,KAAK,CAAC,QAAQ,0CAAE,SAAS,MAAK,IAAI;gBACzE,MAAM,IAAI,KAAK,CACb,4GAA4G,CAC7G,CAAC;YACJ,OAAO,yBAAW,CAAC,OAAO,CAAC;gBACzB,SAAS,EAAE,cAAc;gBACzB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;gBACxB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;aACzB,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;QAC1C,CAAC;KAAA;IAfqB,aAAA,KAAK,QAe1B,CAAA;IA2CD,SAAsB,SAAS,CAS7B,UAAuB,EACvB,KAAwE,EACxE,KAAa,EACb,SAAoC;;;YAEpC,IAAI,CAAA,MAAA,KAAK,CAAC,OAAO,0CAAE,SAAS,MAAK,IAAI,IAAI,CAAA,MAAA,KAAK,CAAC,QAAQ,0CAAE,SAAS,MAAK,IAAI;gBACzE,MAAM,IAAI,KAAK,CACb,gHAAgH,CACjH,CAAC;YACJ,OAAO,yBAAW,CAAC,SAAS,CAAC;gBAC3B,SAAS,EAAE,cAAc;gBACzB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;gBACxB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;aACzB,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAoB,CAAC;QAC7D,CAAC;KAAA;IAvBqB,aAAA,SAAS,YAuB9B,CAAA;AACH,CAAC,EA7HgB,YAAY,aAAZ,YAAY,GAAZ,YAAY,QA6H5B"}
|
package/lib/PlainFetcher.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlainFetcher.mjs","names":[],"sources":["../src/PlainFetcher.ts"],"sourcesContent":["import { IConnection } from \"./IConnection\";\nimport { IFetchRoute } from \"./IFetchRoute\";\nimport { IPropagation } from \"./IPropagation\";\nimport { FetcherBase } from \"./internal/FetcherBase\";\n\n/**\n * Utility class for `fetch` functions used in `@nestia/sdk`.\n *\n * `PlainFetcher` is a utility class designed for SDK functions generated by\n * [`@nestia/sdk`](https://nestia.io/docs/sdk/sdk), interacting with the remote\n * HTTP
|
|
1
|
+
{"version":3,"file":"PlainFetcher.mjs","names":[],"sources":["../src/PlainFetcher.ts"],"sourcesContent":["import { IConnection } from \"./IConnection\";\nimport { IFetchRoute } from \"./IFetchRoute\";\nimport { IPropagation } from \"./IPropagation\";\nimport { FetcherBase } from \"./internal/FetcherBase\";\n\n/**\n * Utility class for `fetch` functions used in `@nestia/sdk`.\n *\n * `PlainFetcher` is a utility class designed for SDK functions generated by\n * [`@nestia/sdk`](https://nestia.io/docs/sdk/sdk), interacting with the remote\n * HTTP server API. In other words, this is a collection of dedicated `fetch()`\n * functions for `@nestia/sdk`.\n *\n * For reference, `PlainFetcher` class does not encrypt or decrypt the body data\n * at all. It just delivers plain data without any post processing. If you've\n * defined a controller method through `@EncryptedRoute` or `@EncryptedBody`\n * decorator, then {@link EncryptedFetcher} class would be used instead.\n *\n * @author Jeongho Nam - https://github.com/samchon\n * @evidence contracts/common.md#principled-implementation The codecs preserve transformed bodies, while FetcherBase owns JSON, form and binary handling. Encrypted metadata is refused before transport. The shared pipeline removes caller Content-Type case-insensitively so multipart boundaries remain fetch-owned, normalizes only host/path separator boundaries, and classifies 200, 201 and the route's configured success status.\n * @evidence contracts/common.md#clear-and-simple-design Two public operations that mirror `EncryptedFetcher`, with the encryption guard as their only own logic.\n * @evidence contracts/common.md#prohibited-implementation-shortcuts The refusal is the contract with the generated SDK, which chooses `EncryptedFetcher` for encrypted routes; no route or header is special-cased.\n * @evidence contracts/common.md#meaningful-documentation The namespace prose says when the generated SDK uses this fetcher and that it does no encryption.\n */\nexport namespace PlainFetcher {\n /**\n * Fetch function only for `HEAD` method.\n *\n * @param connection Connection information for the remote HTTP server\n * @param route Route information about the target API\n * @returns Nothing because of `HEAD` method\n * @evidence contracts/common.md#principled-implementation The overloads narrow arguments by method; the implementation refuses encryption metadata and delegates to FetcherBase.request. Failed statuses become HttpError with their original text, successful HEAD has no data, and binary successes transfer response.body unchanged or create a synchronously closed empty stream if absent. Stream consumption and cancellation belong to the caller.\n * @evidence contracts/common.md#clear-and-simple-design One guard and one delegation, with the overloads only splitting the types.\n * @evidence contracts/common.md#prohibited-implementation-shortcuts The guard follows the route metadata, not a path or a connection.\n * @evidence contracts/common.md#meaningful-documentation Each overload documents its parameters and return value.\n */\n export function fetch(\n connection: IConnection,\n route: IFetchRoute<\"HEAD\">,\n ): Promise<void>;\n\n /**\n * Fetch function only for `GET` method.\n *\n * @param connection Connection information for the remote HTTP server\n * @param route Route information about the target API\n * @returns Response body data from the remote API\n */\n export function fetch<Output>(\n connection: IConnection,\n route: IFetchRoute<\"GET\">,\n ): Promise<Output>;\n\n /**\n * Fetch function for the `POST`, `PUT`, `PATCH` and `DELETE` methods.\n *\n * @param connection Connection information for the remote HTTP server\n * @param route Route information about the target API\n * @returns Response body data from the remote API\n */\n export function fetch<Input, Output>(\n connection: IConnection,\n route: IFetchRoute<\"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\">,\n input?: Input,\n stringify?: (input: Input) => string,\n ): Promise<Output>;\n\n export async function fetch<Input, Output>(\n connection: IConnection,\n route: IFetchRoute<\"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\">,\n input?: Input,\n stringify?: (input: Input) => string,\n ): Promise<Output> {\n if (route.request?.encrypted === true || route.response?.encrypted === true)\n throw new Error(\n \"Error on PlainFetcher.fetch(): PlainFetcher doesn't have encryption ability. Use EncryptedFetcher instead.\",\n );\n return FetcherBase.request({\n className: \"PlainFetcher\",\n encode: (input) => input,\n decode: (input) => input,\n })(connection, route, input, stringify);\n }\n\n /**\n * Fetch function that returns every response as an {@link IPropagation}.\n *\n * An HTTP failure status is returned as a failed branch instead of being\n * thrown. A route that declares an encrypted body and a transport failure\n * still throw. The output must describe numeric status branches with boolean\n * success and string or string-array headers; its data type remains\n * caller-owned.\n *\n * @evidence contracts/common.md#principled-implementation The implementation refuses an encrypted route and delegates to `FetcherBase.propagate`. Its structural branch constraint accepts numeric literal successes, numeric range failures and unknown-status fallback without instantiating a status map with any, while requiring boolean success and actual numeric status/header shapes.\n * @evidence contracts/common.md#clear-and-simple-design One guard and one delegation, with the overloads only splitting the types.\n * @evidence contracts/common.md#prohibited-implementation-shortcuts The function adds no status-specific branch: the success flag comes from the status rules in `FetcherBase`.\n * @evidence contracts/common.md#meaningful-documentation The comment states what the returned union carries and which failures still throw.\n */\n export function propagate<\n Output extends {\n success: boolean;\n status: number;\n headers: Record<string, string | string[]>;\n data: unknown;\n },\n >(\n connection: IConnection,\n route: IFetchRoute<\"GET\" | \"HEAD\">,\n ): Promise<Output>;\n\n export function propagate<\n Input,\n Output extends {\n success: boolean;\n status: number;\n headers: Record<string, string | string[]>;\n data: unknown;\n },\n >(\n connection: IConnection,\n route: IFetchRoute<\"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\">,\n input?: Input,\n stringify?: (input: Input) => string,\n ): Promise<Output>;\n\n export async function propagate<\n Input,\n Output extends {\n success: boolean;\n status: number;\n headers: Record<string, string | string[]>;\n data: unknown;\n },\n >(\n connection: IConnection,\n route: IFetchRoute<\"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\">,\n input?: Input,\n stringify?: (input: Input) => string,\n ): Promise<Output> {\n if (route.request?.encrypted === true || route.response?.encrypted === true)\n throw new Error(\n \"Error on PlainFetcher.propagate(): PlainFetcher doesn't have encryption ability. Use EncryptedFetcher instead.\",\n );\n return FetcherBase.propagate({\n className: \"PlainFetcher\",\n encode: (input) => input,\n decode: (input) => input,\n })(connection, route, input, stringify) as Promise<Output>;\n }\n}\n"],"mappings":";;AAwBO,IAAA;;CA2CE,eAAe,MACpB,YACA,OACA,OACA,WACiB;EACjB,IAAI,MAAM,SAAS,cAAc,QAAQ,MAAM,UAAU,cAAc,MACrE,MAAM,IAAI,MACR,4GACF;EACF,OAAO,YAAY,QAAQ;GACzB,WAAW;GACX,SAAS,UAAU;GACnB,SAAS,UAAU;EACrB,CAAC,CAAC,CAAC,YAAY,OAAO,OAAO,SAAS;CACxC;;CA2CO,eAAe,UASpB,YACA,OACA,OACA,WACiB;EACjB,IAAI,MAAM,SAAS,cAAc,QAAQ,MAAM,UAAU,cAAc,MACrE,MAAM,IAAI,MACR,gHACF;EACF,OAAO,YAAY,UAAU;GAC3B,WAAW;GACX,SAAS,UAAU;GACnB,SAAS,UAAU;EACrB,CAAC,CAAC,CAAC,YAAY,OAAO,OAAO,SAAS;CACxC;;GACD,iBAAA,eAAA,CAAA,EAAD"}
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -22,5 +22,6 @@ __exportStar(require("./IPropagation"), exports);
|
|
|
22
22
|
__exportStar(require("./FormDataInput"), exports);
|
|
23
23
|
__exportStar(require("./HttpError"), exports);
|
|
24
24
|
__exportStar(require("./NestiaSimulator"), exports);
|
|
25
|
+
__exportStar(require("./PathParameter"), exports);
|
|
25
26
|
__exportStar(require("./PlainFetcher"), exports);
|
|
26
27
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,wDAAsC;AACtC,gDAA8B;AAC9B,gDAA8B;AAC9B,iDAA+B;AAC/B,kDAAgC;AAEhC,8CAA4B;AAC5B,oDAAkC;AAClC,iDAA+B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,wDAAsC;AACtC,gDAA8B;AAC9B,gDAA8B;AAC9B,iDAA+B;AAC/B,kDAAgC;AAEhC,8CAA4B;AAC5B,oDAAkC;AAClC,kDAAgC;AAChC,iDAA+B"}
|
package/lib/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HttpError } from "./HttpError.mjs";
|
|
2
2
|
import { NestiaSimulator } from "./NestiaSimulator.mjs";
|
|
3
|
+
import { PathParameter } from "./PathParameter.mjs";
|
|
3
4
|
import { PlainFetcher } from "./PlainFetcher.mjs";
|
|
4
|
-
export { HttpError, NestiaSimulator, PlainFetcher };
|
|
5
|
+
export { HttpError, NestiaSimulator, PathParameter, PlainFetcher };
|
|
@@ -13,17 +13,42 @@ exports.FetcherBase = void 0;
|
|
|
13
13
|
const HttpError_1 = require("../HttpError");
|
|
14
14
|
const is_binary_response_content_type_1 = require("./is_binary_response_content_type");
|
|
15
15
|
const join_host_and_path_1 = require("./join_host_and_path");
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* Shared transport pipeline with injected body codecs.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
17
21
|
var FetcherBase;
|
|
18
22
|
(function (FetcherBase) {
|
|
23
|
+
/**
|
|
24
|
+
* Return successful response data and throw HttpError for a failed status.
|
|
25
|
+
*
|
|
26
|
+
* Binary response streams transfer to the caller for reading or cancellation;
|
|
27
|
+
* an absent binary body is represented by a closed empty stream.
|
|
28
|
+
*/
|
|
19
29
|
FetcherBase.request = (props) => (connection, route, input, stringify) => __awaiter(this, void 0, void 0, function* () {
|
|
20
30
|
const result = yield _Propagate("fetch")(props)(connection, route, input, stringify);
|
|
21
31
|
if (result.success === false)
|
|
22
32
|
throw new HttpError_1.HttpError(route.method, route.path, result.status, result.headers, result.data);
|
|
23
33
|
return result.data;
|
|
24
34
|
});
|
|
35
|
+
/**
|
|
36
|
+
* Return the classified HTTP response, including failed status payloads.
|
|
37
|
+
*
|
|
38
|
+
* Failed JSON responses are parsed when readable; malformed JSON remains
|
|
39
|
+
* text. Transport and successful-body decoding errors still reject. Binary
|
|
40
|
+
* response streams transfer to the caller for consumption or cancellation.
|
|
41
|
+
*/
|
|
25
42
|
FetcherBase.propagate = (props) => (connection, route, input, stringify) => __awaiter(this, void 0, void 0, function* () { return _Propagate("propagate")(props)(connection, route, input, stringify); });
|
|
26
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* Executes one request and transfers binary stream ownership to its caller.
|
|
45
|
+
*
|
|
46
|
+
* A null successful binary body has no producer or bytes, so its replacement
|
|
47
|
+
* stream must start closed. Actual response streams retain their identity;
|
|
48
|
+
* reading and cancellation remain the caller's responsibility.
|
|
49
|
+
*
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
27
52
|
const _Propagate = (method) => (props) => (connection, route, input, stringify) => __awaiter(this, void 0, void 0, function* () {
|
|
28
53
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
29
54
|
var _h, _j, _k, _l;
|
|
@@ -32,16 +57,15 @@ var FetcherBase;
|
|
|
32
57
|
//----
|
|
33
58
|
// METHOD & HEADERS
|
|
34
59
|
const headers = Object.assign({}, ((_h = connection.headers) !== null && _h !== void 0 ? _h : {}));
|
|
60
|
+
// a request carries its route's own content type, never the caller's:
|
|
61
|
+
// multipart sets none at all, as fetch writes it with the boundary
|
|
62
|
+
deleteHeader(headers, "content-type");
|
|
35
63
|
if (input !== undefined) {
|
|
36
64
|
if (((_a = route.request) === null || _a === void 0 ? void 0 : _a.type) === undefined)
|
|
37
65
|
throw new Error(`Error on ${props.className}.fetch(): no content-type being configured.`);
|
|
38
|
-
else if (route.request.type !== "multipart/form-data")
|
|
39
|
-
deleteHeader(headers, "content-type");
|
|
66
|
+
else if (route.request.type !== "multipart/form-data")
|
|
40
67
|
headers["Content-Type"] = route.request.type;
|
|
41
|
-
}
|
|
42
68
|
}
|
|
43
|
-
else if (input === undefined)
|
|
44
|
-
deleteHeader(headers, "content-type");
|
|
45
69
|
// INIT REQUEST DATA
|
|
46
70
|
const init = Object.assign(Object.assign({}, ((_j = connection.options) !== null && _j !== void 0 ? _j : {})), { method: route.method, headers: (() => {
|
|
47
71
|
const output = [];
|
|
@@ -122,16 +146,15 @@ var FetcherBase;
|
|
|
122
146
|
result.data = route.parseQuery ? route.parseQuery(query) : query;
|
|
123
147
|
}
|
|
124
148
|
else if ((0, is_binary_response_content_type_1.is_binary_response_content_type)((_g = route.response) === null || _g === void 0 ? void 0 : _g.type))
|
|
125
|
-
result.data = (_l = response.body) !== null && _l !== void 0 ? _l : new ReadableStream(
|
|
149
|
+
result.data = (_l = response.body) !== null && _l !== void 0 ? _l : new ReadableStream({
|
|
150
|
+
start: (controller) => controller.close(),
|
|
151
|
+
});
|
|
126
152
|
else
|
|
127
153
|
result.data = props.decode(yield response.text(), result.headers);
|
|
128
154
|
}
|
|
129
155
|
event.output = result.data;
|
|
130
156
|
return result;
|
|
131
157
|
}
|
|
132
|
-
catch (exp) {
|
|
133
|
-
throw exp;
|
|
134
|
-
}
|
|
135
158
|
finally {
|
|
136
159
|
event.completed_at = new Date();
|
|
137
160
|
if (connection.logger)
|
|
@@ -167,7 +190,7 @@ const request_form_data_body = (input) => {
|
|
|
167
190
|
};
|
|
168
191
|
for (const [key, value] of Object.entries(input))
|
|
169
192
|
if (Array.isArray(value))
|
|
170
|
-
value.
|
|
193
|
+
value.forEach(append(key));
|
|
171
194
|
else
|
|
172
195
|
append(key)(value);
|
|
173
196
|
return encoded;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FetcherBase.js","sourceRoot":"","sources":["../../src/internal/FetcherBase.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4CAAyC;AAKzC,uFAAoF;AACpF,6DAAgF;AAEhF
|
|
1
|
+
{"version":3,"file":"FetcherBase.js","sourceRoot":"","sources":["../../src/internal/FetcherBase.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,16 +10,22 @@ let FetcherBase;
|
|
|
10
10
|
return result.data;
|
|
11
11
|
};
|
|
12
12
|
_FetcherBase.propagate = (props) => async (connection, route, input, stringify) => _Propagate("propagate")(props)(connection, route, input, stringify);
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Executes one request and transfers binary stream ownership to its caller.
|
|
15
|
+
*
|
|
16
|
+
* A null successful binary body has no producer or bytes, so its replacement
|
|
17
|
+
* stream must start closed. Actual response streams retain their identity;
|
|
18
|
+
* reading and cancellation remain the caller's responsibility.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
14
22
|
const _Propagate = (method) => (props) => async (connection, route, input, stringify) => {
|
|
15
23
|
const headers = { ...connection.headers ?? {} };
|
|
24
|
+
deleteHeader(headers, "content-type");
|
|
16
25
|
if (input !== void 0) {
|
|
17
26
|
if (route.request?.type === void 0) throw new Error(`Error on ${props.className}.fetch(): no content-type being configured.`);
|
|
18
|
-
else if (route.request.type !== "multipart/form-data")
|
|
19
|
-
|
|
20
|
-
headers["Content-Type"] = route.request.type;
|
|
21
|
-
}
|
|
22
|
-
} else if (input === void 0) deleteHeader(headers, "content-type");
|
|
27
|
+
else if (route.request.type !== "multipart/form-data") headers["Content-Type"] = route.request.type;
|
|
28
|
+
}
|
|
23
29
|
const init = {
|
|
24
30
|
...connection.options ?? {},
|
|
25
31
|
method: route.method,
|
|
@@ -67,12 +73,10 @@ let FetcherBase;
|
|
|
67
73
|
} else if (route.response?.type === "application/x-www-form-urlencoded") {
|
|
68
74
|
const query = new URLSearchParams(await response.text());
|
|
69
75
|
result.data = route.parseQuery ? route.parseQuery(query) : query;
|
|
70
|
-
} else if (is_binary_response_content_type(route.response?.type)) result.data = response.body ?? new ReadableStream();
|
|
76
|
+
} else if (is_binary_response_content_type(route.response?.type)) result.data = response.body ?? new ReadableStream({ start: (controller) => controller.close() });
|
|
71
77
|
else result.data = props.decode(await response.text(), result.headers);
|
|
72
78
|
event.output = result.data;
|
|
73
79
|
return result;
|
|
74
|
-
} catch (exp) {
|
|
75
|
-
throw exp;
|
|
76
80
|
} finally {
|
|
77
81
|
event.completed_at = /* @__PURE__ */ new Date();
|
|
78
82
|
if (connection.logger) try {
|
|
@@ -97,7 +101,7 @@ const request_form_data_body = (input) => {
|
|
|
97
101
|
else if (typeof File === "function" && value instanceof File) encoded.append(key, value, value.name);
|
|
98
102
|
else encoded.append(key, value);
|
|
99
103
|
};
|
|
100
|
-
for (const [key, value] of Object.entries(input)) if (Array.isArray(value)) value.
|
|
104
|
+
for (const [key, value] of Object.entries(input)) if (Array.isArray(value)) value.forEach(append(key));
|
|
101
105
|
else append(key)(value);
|
|
102
106
|
return encoded;
|
|
103
107
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FetcherBase.mjs","names":[],"sources":["../../src/internal/FetcherBase.ts"],"sourcesContent":["import { HttpError } from \"../HttpError\";\nimport { IConnection } from \"../IConnection\";\nimport { IFetchEvent } from \"../IFetchEvent\";\nimport { IFetchRoute } from \"../IFetchRoute\";\nimport { IPropagation } from \"../IPropagation\";\nimport { is_binary_response_content_type } from \"./is_binary_response_content_type\";\nimport { join_host_and_path, normalize_route_path } from \"./join_host_and_path\";\n\n/** @internal */\nexport namespace FetcherBase {\n export interface IProps {\n className: string;\n encode: (\n input: any,\n headers: Record<string, IConnection.HeaderValue | undefined>,\n ) => string;\n decode: (\n input: string,\n headers: Record<string, IConnection.HeaderValue | undefined>,\n ) => any;\n }\n\n export const request =\n (props: IProps) =>\n async <Input, Output>(\n connection: IConnection,\n route: IFetchRoute<\"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\">,\n input?: Input,\n stringify?: (input: Input) => string,\n ): Promise<Output> => {\n const result = await _Propagate(\"fetch\")(props)(\n connection,\n route,\n input,\n stringify,\n );\n if ((result as any).success === false)\n throw new HttpError(\n route.method,\n route.path,\n result.status as any as number,\n result.headers,\n result.data as string,\n );\n return result.data as Output;\n };\n\n export const propagate =\n (props: IProps) =>\n async <Input>(\n connection: IConnection,\n route: IFetchRoute<\"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\">,\n input?: Input,\n stringify?: (input: Input) => string,\n ): Promise<IPropagation<any, any>> =>\n _Propagate(\"propagate\")(props)(connection, route, input, stringify);\n\n /** @internal */\n const _Propagate =\n (method: string) =>\n (props: IProps) =>\n async <Input>(\n connection: IConnection,\n route: IFetchRoute<\"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\">,\n input?: Input,\n stringify?: (input: Input) => string,\n ): Promise<IPropagation<any, any>> => {\n //----\n // REQUEST MESSAGE\n //----\n // METHOD & HEADERS\n const headers: Record<string, IConnection.HeaderValue | undefined> = {\n ...(connection.headers ?? {}),\n };\n if (input !== undefined) {\n if (route.request?.type === undefined)\n throw new Error(\n `Error on ${props.className}.fetch(): no content-type being configured.`,\n );\n else if (route.request.type !== \"multipart/form-data\") {\n deleteHeader(headers, \"content-type\");\n headers[\"Content-Type\"] = route.request.type;\n }\n } else if (input === undefined) deleteHeader(headers, \"content-type\");\n\n // INIT REQUEST DATA\n const init: RequestInit = {\n ...(connection.options ?? {}),\n method: route.method,\n headers: (() => {\n const output: [string, string][] = [];\n for (const [key, value] of Object.entries(headers))\n if (value === undefined) continue;\n else if (Array.isArray(value))\n for (const v of value) output.push([key, String(v)]);\n else output.push([key, String(value)]);\n return output;\n })(),\n };\n\n // CONSTRUCT BODY DATA\n if (input !== undefined)\n init.body = props.encode(\n // BODY TRANSFORM\n route.request?.type === \"application/x-www-form-urlencoded\"\n ? request_query_body(input)\n : route.request?.type === \"multipart/form-data\"\n ? request_form_data_body(input as any)\n : route.request?.type !== \"text/plain\"\n ? (stringify ?? JSON.stringify)(input)\n : input,\n headers,\n );\n\n //----\n // RESPONSE MESSAGE\n //----\n // URL SPECIFICATION\n const path: string = normalize_route_path(route.path);\n const url: URL = new URL(join_host_and_path(connection.host, route.path));\n\n // DO FETCH\n const event: IFetchEvent = {\n route,\n path,\n status: null,\n input,\n output: undefined,\n started_at: new Date(),\n respond_at: null,\n completed_at: null!,\n };\n try {\n // TRY FETCH\n const response: Response = await (connection.fetch ?? fetch)(\n url.href,\n init,\n );\n event.respond_at = new Date();\n event.status = response.status;\n\n // CONSTRUCT RESULT DATA\n const result: IPropagation<any, any> = {\n success:\n response.status === 200 ||\n response.status === 201 ||\n response.status === route.status,\n status: response.status,\n headers: response_headers_to_object(response.headers),\n data: undefined!,\n } as any;\n if ((result as any).success === false) {\n // WHEN FAILED\n result.data = await response.text();\n const type = response.headers.get(\"content-type\");\n if (\n method !== \"fetch\" &&\n type &&\n type.indexOf(\"application/json\") !== -1\n )\n try {\n result.data = JSON.parse(result.data);\n } catch {}\n } else {\n // WHEN SUCCESS\n if (route.method === \"HEAD\") result.data = undefined!;\n else if (route.response?.type === \"application/json\") {\n const text: string = await response.text();\n result.data = text.length ? JSON.parse(text) : undefined;\n } else if (\n route.response?.type === \"application/x-www-form-urlencoded\"\n ) {\n const query: URLSearchParams = new URLSearchParams(\n await response.text(),\n );\n result.data = route.parseQuery ? route.parseQuery(query) : query;\n } else if (is_binary_response_content_type(route.response?.type))\n result.data = response.body ?? new ReadableStream<Uint8Array>();\n else\n result.data = props.decode(await response.text(), result.headers);\n }\n event.output = result.data;\n return result;\n } catch (exp) {\n throw exp;\n } finally {\n event.completed_at = new Date();\n if (connection.logger)\n try {\n await connection.logger(event);\n } catch {}\n }\n };\n}\n\n/** @internal */\nconst request_query_body = (input: any): URLSearchParams => {\n const q: URLSearchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(input))\n if (value === undefined) continue;\n else if (Array.isArray(value))\n value.forEach((elem) => q.append(key, String(elem)));\n else q.set(key, String(value));\n return q;\n};\n\n/** @internal */\nconst request_form_data_body = (input: Record<string, any>): FormData => {\n const encoded: FormData = new FormData();\n const append = (key: string) => (value: any) => {\n if (value === undefined) return;\n else if (typeof File === \"function\" && value instanceof File)\n encoded.append(key, value, value.name);\n else encoded.append(key, value);\n };\n for (const [key, value] of Object.entries(input))\n if (Array.isArray(value)) value.map(append(key));\n else append(key)(value);\n return encoded;\n};\n\n/** @internal */\nconst response_headers_to_object = (\n headers: Headers,\n): Record<string, string | string[]> => {\n const output: Record<string, string | string[]> = {};\n const cookieHeaders: string[] | undefined =\n typeof (headers as any).getSetCookie === \"function\"\n ? (headers as any).getSetCookie()\n : undefined;\n if (cookieHeaders?.length) output[\"set-cookie\"] = cookieHeaders;\n\n headers.forEach((value, key) => {\n if (key.toLowerCase() === \"set-cookie\") {\n if (cookieHeaders?.length) return;\n output[key] ??= [];\n (output[key] as string[]).push(value);\n } else output[key] = value;\n });\n return output;\n};\n\nconst deleteHeader = (\n headers: Record<string, IConnection.HeaderValue | undefined>,\n name: string,\n): void => {\n const normalized: string = name.toLowerCase();\n for (const key of Object.keys(headers))\n if (key.toLowerCase() === normalized) delete headers[key];\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FetcherBase.mjs","names":[],"sources":["../../src/internal/FetcherBase.ts"],"sourcesContent":["import { HttpError } from \"../HttpError\";\nimport { IConnection } from \"../IConnection\";\nimport { IFetchEvent } from \"../IFetchEvent\";\nimport { IFetchRoute } from \"../IFetchRoute\";\nimport { IPropagation } from \"../IPropagation\";\nimport { is_binary_response_content_type } from \"./is_binary_response_content_type\";\nimport { join_host_and_path, normalize_route_path } from \"./join_host_and_path\";\n\n/**\n * Shared transport pipeline with injected body codecs.\n *\n * @internal\n */\nexport namespace FetcherBase {\n /**\n * Body transformations supplied by the plain or encrypted fetcher.\n *\n * The encode input has already undergone the route's body transformation.\n * Header records describe the corresponding request or response.\n */\n export interface IProps {\n /** Fetcher name used in request configuration errors. */\n className: string;\n\n /** Convert a transformed request body into its wire representation. */\n encode: (\n input: any,\n headers: Record<string, IConnection.HeaderValue | undefined>,\n ) => string;\n\n /** Decode a textual response not handled by a structured media branch. */\n decode: (\n input: string,\n headers: Record<string, IConnection.HeaderValue | undefined>,\n ) => any;\n }\n\n /**\n * Return successful response data and throw HttpError for a failed status.\n *\n * Binary response streams transfer to the caller for reading or cancellation;\n * an absent binary body is represented by a closed empty stream.\n */\n export const request =\n (props: IProps) =>\n async <Input, Output>(\n connection: IConnection,\n route: IFetchRoute<\"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\">,\n input?: Input,\n stringify?: (input: Input) => string,\n ): Promise<Output> => {\n const result = await _Propagate(\"fetch\")(props)(\n connection,\n route,\n input,\n stringify,\n );\n if ((result as any).success === false)\n throw new HttpError(\n route.method,\n route.path,\n result.status as any as number,\n result.headers,\n result.data as string,\n );\n return result.data as Output;\n };\n\n /**\n * Return the classified HTTP response, including failed status payloads.\n *\n * Failed JSON responses are parsed when readable; malformed JSON remains\n * text. Transport and successful-body decoding errors still reject. Binary\n * response streams transfer to the caller for consumption or cancellation.\n */\n export const propagate =\n (props: IProps) =>\n async <Input>(\n connection: IConnection,\n route: IFetchRoute<\"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\">,\n input?: Input,\n stringify?: (input: Input) => string,\n ): Promise<IPropagation<any, any>> =>\n _Propagate(\"propagate\")(props)(connection, route, input, stringify);\n\n /**\n * Executes one request and transfers binary stream ownership to its caller.\n *\n * A null successful binary body has no producer or bytes, so its replacement\n * stream must start closed. Actual response streams retain their identity;\n * reading and cancellation remain the caller's responsibility.\n *\n * @internal\n */\n const _Propagate =\n (method: string) =>\n (props: IProps) =>\n async <Input>(\n connection: IConnection,\n route: IFetchRoute<\"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\">,\n input?: Input,\n stringify?: (input: Input) => string,\n ): Promise<IPropagation<any, any>> => {\n //----\n // REQUEST MESSAGE\n //----\n // METHOD & HEADERS\n const headers: Record<string, IConnection.HeaderValue | undefined> = {\n ...(connection.headers ?? {}),\n };\n // a request carries its route's own content type, never the caller's:\n // multipart sets none at all, as fetch writes it with the boundary\n deleteHeader(headers, \"content-type\");\n if (input !== undefined) {\n if (route.request?.type === undefined)\n throw new Error(\n `Error on ${props.className}.fetch(): no content-type being configured.`,\n );\n else if (route.request.type !== \"multipart/form-data\")\n headers[\"Content-Type\"] = route.request.type;\n }\n\n // INIT REQUEST DATA\n const init: RequestInit = {\n ...(connection.options ?? {}),\n method: route.method,\n headers: (() => {\n const output: [string, string][] = [];\n for (const [key, value] of Object.entries(headers))\n if (value === undefined) continue;\n else if (Array.isArray(value))\n for (const v of value) output.push([key, String(v)]);\n else output.push([key, String(value)]);\n return output;\n })(),\n };\n\n // CONSTRUCT BODY DATA\n if (input !== undefined)\n init.body = props.encode(\n // BODY TRANSFORM\n route.request?.type === \"application/x-www-form-urlencoded\"\n ? request_query_body(input)\n : route.request?.type === \"multipart/form-data\"\n ? request_form_data_body(input as any)\n : route.request?.type !== \"text/plain\"\n ? (stringify ?? JSON.stringify)(input)\n : input,\n headers,\n );\n\n //----\n // RESPONSE MESSAGE\n //----\n // URL SPECIFICATION\n const path: string = normalize_route_path(route.path);\n const url: URL = new URL(join_host_and_path(connection.host, route.path));\n\n // DO FETCH\n const event: IFetchEvent = {\n route,\n path,\n status: null,\n input,\n output: undefined,\n started_at: new Date(),\n respond_at: null,\n completed_at: null!,\n };\n try {\n // TRY FETCH\n const response: Response = await (connection.fetch ?? fetch)(\n url.href,\n init,\n );\n event.respond_at = new Date();\n event.status = response.status;\n\n // CONSTRUCT RESULT DATA\n const result: IPropagation<any, any> = {\n success:\n response.status === 200 ||\n response.status === 201 ||\n response.status === route.status,\n status: response.status,\n headers: response_headers_to_object(response.headers),\n data: undefined!,\n } as any;\n if ((result as any).success === false) {\n // WHEN FAILED\n result.data = await response.text();\n const type = response.headers.get(\"content-type\");\n if (\n method !== \"fetch\" &&\n type &&\n type.indexOf(\"application/json\") !== -1\n )\n try {\n result.data = JSON.parse(result.data);\n } catch {}\n } else {\n // WHEN SUCCESS\n if (route.method === \"HEAD\") result.data = undefined!;\n else if (route.response?.type === \"application/json\") {\n const text: string = await response.text();\n result.data = text.length ? JSON.parse(text) : undefined;\n } else if (\n route.response?.type === \"application/x-www-form-urlencoded\"\n ) {\n const query: URLSearchParams = new URLSearchParams(\n await response.text(),\n );\n result.data = route.parseQuery ? route.parseQuery(query) : query;\n } else if (is_binary_response_content_type(route.response?.type))\n result.data =\n response.body ??\n new ReadableStream<Uint8Array>({\n start: (controller) => controller.close(),\n });\n else\n result.data = props.decode(await response.text(), result.headers);\n }\n event.output = result.data;\n return result;\n } finally {\n event.completed_at = new Date();\n if (connection.logger)\n try {\n await connection.logger(event);\n } catch {}\n }\n };\n}\n\n/** @internal */\nconst request_query_body = (input: any): URLSearchParams => {\n const q: URLSearchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(input))\n if (value === undefined) continue;\n else if (Array.isArray(value))\n value.forEach((elem) => q.append(key, String(elem)));\n else q.set(key, String(value));\n return q;\n};\n\n/** @internal */\nconst request_form_data_body = (input: Record<string, any>): FormData => {\n const encoded: FormData = new FormData();\n const append = (key: string) => (value: any) => {\n if (value === undefined) return;\n else if (typeof File === \"function\" && value instanceof File)\n encoded.append(key, value, value.name);\n else encoded.append(key, value);\n };\n for (const [key, value] of Object.entries(input))\n if (Array.isArray(value)) value.forEach(append(key));\n else append(key)(value);\n return encoded;\n};\n\n/** @internal */\nconst response_headers_to_object = (\n headers: Headers,\n): Record<string, string | string[]> => {\n const output: Record<string, string | string[]> = {};\n const cookieHeaders: string[] | undefined =\n typeof (headers as any).getSetCookie === \"function\"\n ? (headers as any).getSetCookie()\n : undefined;\n if (cookieHeaders?.length) output[\"set-cookie\"] = cookieHeaders;\n\n headers.forEach((value, key) => {\n if (key.toLowerCase() === \"set-cookie\") {\n if (cookieHeaders?.length) return;\n output[key] ??= [];\n (output[key] as string[]).push(value);\n } else output[key] = value;\n });\n return output;\n};\n\nconst deleteHeader = (\n headers: Record<string, IConnection.HeaderValue | undefined>,\n name: string,\n): void => {\n const normalized: string = name.toLowerCase();\n for (const key of Object.keys(headers))\n if (key.toLowerCase() === normalized) delete headers[key];\n};\n"],"mappings":";;;;AAaO,IAAA;;yBA+BF,UACD,OACE,YACA,OACA,OACA,cACoB;EACpB,MAAM,SAAS,MAAM,WAAW,OAAO,CAAC,CAAC,KAAK,CAAC,CAC7C,YACA,OACA,OACA,SACF;EACA,IAAK,OAAe,YAAY,OAC9B,MAAM,IAAI,UACR,MAAM,QACN,MAAM,MACN,OAAO,QACP,OAAO,SACP,OAAO,IACT;EACF,OAAO,OAAO;CAChB;2BAUC,UACD,OACE,YACA,OACA,OACA,cAEA,WAAW,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,OAAO,OAAO,SAAS;;;;;;;;;;CAWtE,MAAM,cACH,YACA,UACD,OACE,YACA,OACA,OACA,cACoC;EAKpC,MAAM,UAA+D,EACnE,GAAI,WAAW,WAAW,CAAC,EAC7B;EAGA,aAAa,SAAS,cAAc;EACpC,IAAI,UAAU,KAAA;OACR,MAAM,SAAS,SAAS,KAAA,GAC1B,MAAM,IAAI,MACR,YAAY,MAAM,UAAU,4CAC9B;QACG,IAAI,MAAM,QAAQ,SAAS,uBAC9B,QAAQ,kBAAkB,MAAM,QAAQ;EAAA;EAI5C,MAAM,OAAoB;GACxB,GAAI,WAAW,WAAW,CAAC;GAC3B,QAAQ,MAAM;GACd,gBAAgB;IACd,MAAM,SAA6B,CAAC;IACpC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,GAC/C,IAAI,UAAU,KAAA,GAAW;SACpB,IAAI,MAAM,QAAQ,KAAK,GAC1B,KAAK,MAAM,KAAK,OAAO,OAAO,KAAK,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC;SAChD,OAAO,KAAK,CAAC,KAAK,OAAO,KAAK,CAAC,CAAC;IACvC,OAAO;GACT,EAAA,CAAG;EACL;EAGA,IAAI,UAAU,KAAA,GACZ,KAAK,OAAO,MAAM,OAEhB,MAAM,SAAS,SAAS,sCACpB,mBAAmB,KAAK,IACxB,MAAM,SAAS,SAAS,wBACtB,uBAAuB,KAAY,IACnC,MAAM,SAAS,SAAS,gBACrB,aAAa,KAAK,UAAA,CAAW,KAAK,IACnC,OACR,OACF;EAMF,MAAM,OAAe,qBAAqB,MAAM,IAAI;EACpD,MAAM,MAAW,IAAI,IAAI,mBAAmB,WAAW,MAAM,MAAM,IAAI,CAAC;EAGxE,MAAM,QAAqB;GACzB;GACA;GACA,QAAQ;GACR;GACA,QAAQ,KAAA;GACR,4BAAY,IAAI,KAAK;GACrB,YAAY;GACZ,cAAc;EAChB;EACA,IAAI;GAEF,MAAM,WAAqB,OAAO,WAAW,SAAS,MAAA,CACpD,IAAI,MACJ,IACF;GACA,MAAM,6BAAa,IAAI,KAAK;GAC5B,MAAM,SAAS,SAAS;GAGxB,MAAM,SAAiC;IACrC,SACE,SAAS,WAAW,OACpB,SAAS,WAAW,OACpB,SAAS,WAAW,MAAM;IAC5B,QAAQ,SAAS;IACjB,SAAS,2BAA2B,SAAS,OAAO;IACpD,MAAM,KAAA;GACR;GACA,IAAK,OAAe,YAAY,OAAO;IAErC,OAAO,OAAO,MAAM,SAAS,KAAK;IAClC,MAAM,OAAO,SAAS,QAAQ,IAAI,cAAc;IAChD,IACE,WAAW,WACX,QACA,KAAK,QAAQ,kBAAkB,MAAM,IAErC,IAAI;KACF,OAAO,OAAO,KAAK,MAAM,OAAO,IAAI;IACtC,QAAQ,CAAC;GACb,OAEE,IAAI,MAAM,WAAW,QAAQ,OAAO,OAAO,KAAA;QACtC,IAAI,MAAM,UAAU,SAAS,oBAAoB;IACpD,MAAM,OAAe,MAAM,SAAS,KAAK;IACzC,OAAO,OAAO,KAAK,SAAS,KAAK,MAAM,IAAI,IAAI,KAAA;GACjD,OAAO,IACL,MAAM,UAAU,SAAS,qCACzB;IACA,MAAM,QAAyB,IAAI,gBACjC,MAAM,SAAS,KAAK,CACtB;IACA,OAAO,OAAO,MAAM,aAAa,MAAM,WAAW,KAAK,IAAI;GAC7D,OAAO,IAAI,gCAAgC,MAAM,UAAU,IAAI,GAC7D,OAAO,OACL,SAAS,QACT,IAAI,eAA2B,EAC7B,QAAQ,eAAe,WAAW,MAAM,EAC1C,CAAC;QAEH,OAAO,OAAO,MAAM,OAAO,MAAM,SAAS,KAAK,GAAG,OAAO,OAAO;GAEpE,MAAM,SAAS,OAAO;GACtB,OAAO;EACT,UAAU;GACR,MAAM,+BAAe,IAAI,KAAK;GAC9B,IAAI,WAAW,QACb,IAAI;IACF,MAAM,WAAW,OAAO,KAAK;GAC/B,QAAQ,CAAC;EACb;CACF;GACH,gBAAA,cAAA,CAAA,EAAD;;AAGA,MAAM,sBAAsB,UAAgC;CAC1D,MAAM,IAAqB,IAAI,gBAAgB;CAC/C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAC7C,IAAI,UAAU,KAAA,GAAW;MACpB,IAAI,MAAM,QAAQ,KAAK,GAC1B,MAAM,SAAS,SAAS,EAAE,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC;MAChD,EAAE,IAAI,KAAK,OAAO,KAAK,CAAC;CAC/B,OAAO;AACT;;AAGA,MAAM,0BAA0B,UAAyC;CACvE,MAAM,UAAoB,IAAI,SAAS;CACvC,MAAM,UAAU,SAAiB,UAAe;EAC9C,IAAI,UAAU,KAAA,GAAW;OACpB,IAAI,OAAO,SAAS,cAAc,iBAAiB,MACtD,QAAQ,OAAO,KAAK,OAAO,MAAM,IAAI;OAClC,QAAQ,OAAO,KAAK,KAAK;CAChC;CACA,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAC7C,IAAI,MAAM,QAAQ,KAAK,GAAG,MAAM,QAAQ,OAAO,GAAG,CAAC;MAC9C,OAAO,GAAG,CAAC,CAAC,KAAK;CACxB,OAAO;AACT;;AAGA,MAAM,8BACJ,YACsC;CACtC,MAAM,SAA4C,CAAC;CACnD,MAAM,gBACJ,OAAQ,QAAgB,iBAAiB,aACpC,QAAgB,aAAa,IAC9B,KAAA;CACN,IAAI,eAAe,QAAQ,OAAO,gBAAgB;CAElD,QAAQ,SAAS,OAAO,QAAQ;EAC9B,IAAI,IAAI,YAAY,MAAM,cAAc;GACtC,IAAI,eAAe,QAAQ;GAC3B,OAAO,SAAS,CAAC;GACjB,OAAQ,IAAI,CAAc,KAAK,KAAK;EACtC,OAAO,OAAO,OAAO;CACvB,CAAC;CACD,OAAO;AACT;AAEA,MAAM,gBACJ,SACA,SACS;CACT,MAAM,aAAqB,KAAK,YAAY;CAC5C,KAAK,MAAM,OAAO,OAAO,KAAK,OAAO,GACnC,IAAI,IAAI,YAAY,MAAM,YAAY,OAAO,QAAQ;AACzD"}
|
|
@@ -1 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reports whether a response content type carries a binary body.
|
|
3
|
+
*
|
|
4
|
+
* The parameters of the type (`; charset=...`) and its case are ignored. Image,
|
|
5
|
+
* video, and audio types, `application/octet-stream`, and `application/pdf` are
|
|
6
|
+
* binary, and the fetcher returns their body as a stream instead of text.
|
|
7
|
+
*
|
|
8
|
+
* @evidence contracts/common.md#principled-implementation The media type is the text before the first `;`, trimmed and lower-cased as HTTP defines, and is matched against the binary families and two exact types, so a parameter or a case variant cannot change the decision.
|
|
9
|
+
* @evidence contracts/common.md#clear-and-simple-design One predicate with a type guard, so the caller can narrow the route's content type.
|
|
10
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The rule is a list of media-type families from the HTTP registry rather than a list of routes.
|
|
11
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the normalization and the binary types.
|
|
12
|
+
*/
|
|
1
13
|
export declare const is_binary_response_content_type: (input: string | null | undefined) => input is string;
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.is_binary_response_content_type = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Reports whether a response content type carries a binary body.
|
|
6
|
+
*
|
|
7
|
+
* The parameters of the type (`; charset=...`) and its case are ignored. Image,
|
|
8
|
+
* video, and audio types, `application/octet-stream`, and `application/pdf` are
|
|
9
|
+
* binary, and the fetcher returns their body as a stream instead of text.
|
|
10
|
+
*
|
|
11
|
+
* @evidence contracts/common.md#principled-implementation The media type is the text before the first `;`, trimmed and lower-cased as HTTP defines, and is matched against the binary families and two exact types, so a parameter or a case variant cannot change the decision.
|
|
12
|
+
* @evidence contracts/common.md#clear-and-simple-design One predicate with a type guard, so the caller can narrow the route's content type.
|
|
13
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The rule is a list of media-type families from the HTTP registry rather than a list of routes.
|
|
14
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the normalization and the binary types.
|
|
15
|
+
*/
|
|
4
16
|
const is_binary_response_content_type = (input) => {
|
|
5
17
|
if (typeof input !== "string")
|
|
6
18
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is_binary_response_content_type.js","sourceRoot":"","sources":["../../src/internal/is_binary_response_content_type.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"is_binary_response_content_type.js","sourceRoot":"","sources":["../../src/internal/is_binary_response_content_type.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;GAWG;AACI,MAAM,+BAA+B,GAAG,CAC7C,KAAgC,EACf,EAAE;IACnB,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5C,MAAM,KAAK,GAAW,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAChE,OAAO,CACL,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC;QAC1B,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC;QAC1B,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC;QAC1B,KAAK,KAAK,0BAA0B;QACpC,KAAK,KAAK,iBAAiB,CAC5B,CAAC;AACJ,CAAC,CAAC;AAbW,QAAA,+BAA+B,GAA/B,+BAA+B,CAa1C"}
|