Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@nestia/fetcher

Package Overview
Dependencies
Maintainers
1
Versions
414
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nestia/fetcher - npm Package Compare versions

Comparing version 2.0.0-dev.20230906 to 2.0.0-dev.20230907

lib/IPropagation.d.ts

3

lib/EncryptedFetcher.d.ts
import { IConnection } from "./IConnection";
import { IPropagation } from "./IPropagation";
import { Primitive } from "./Primitive";

@@ -43,2 +44,4 @@ import { IFetchRoute } from "./internal/IFetchRoute";

function fetch<Input, Output>(connection: IConnection, route: IFetchRoute<"POST" | "PUT" | "PATCH" | "DELETE">, input?: Input, stringify?: (input: Input) => string): Promise<Primitive<Output>>;
function propagate<Output extends IPropagation<number, any, boolean>>(connection: IConnection, route: IFetchRoute<"HEAD">): Promise<Output>;
function propagate<Input, Output extends IPropagation<number, any, boolean>>(connection: IConnection, route: IFetchRoute<"HEAD">, input?: Input, stringify?: (input: Input) => string): Promise<Output>;
}

@@ -97,3 +97,42 @@ "use strict";

EncryptedFetcher.fetch = fetch;
function propagate(connection, route, input, stringify) {
var _a, _b, _c, _d;
return __awaiter(this, void 0, void 0, function () {
var closure;
return __generator(this, function (_e) {
if ((((_a = route.request) === null || _a === void 0 ? void 0 : _a.encrypted) === true || ((_b = route.response) === null || _b === void 0 ? void 0 : _b.encrypted)) &&
connection.encryption === undefined)
throw new Error("Error on EncryptedFetcher.propagate(): the encryption password has not been configured.");
closure = typeof connection.encryption === "function"
? function (direction) {
return function (headers, body) {
return connection.encryption({
headers: headers,
body: body,
direction: direction,
});
};
}
: function () { return function () { return connection.encryption; }; };
return [2 /*return*/, FetcherBase_1.FetcherBase.propagate({
className: "EncryptedFetcher",
encode: ((_c = route.request) === null || _c === void 0 ? void 0 : _c.encrypted) === true
? function (input, headers) {
var p = closure("encode")(headers, input);
return AesPkcs5_1.AesPkcs5.encrypt(JSON.stringify(input), p.key, p.iv);
}
: function (input) { return input; },
decode: ((_d = route.response) === null || _d === void 0 ? void 0 : _d.encrypted) === true
? function (input, headers) {
var p = closure("decode")(headers, input);
var str = AesPkcs5_1.AesPkcs5.decrypt(input, p.key, p.iv);
return str.length ? JSON.parse(str) : str;
}
: function (input) { return input; },
})(connection, route, input, stringify)];
});
});
}
EncryptedFetcher.propagate = propagate;
})(EncryptedFetcher || (exports.EncryptedFetcher = EncryptedFetcher = {}));
//# sourceMappingURL=EncryptedFetcher.js.map

4

lib/HttpError.d.ts

@@ -12,2 +12,3 @@ /**

readonly status: number;
readonly headers: Record<string, string | string[]>;
/**

@@ -21,3 +22,3 @@ * Initializer Constructor.

*/
constructor(method: "GET" | "DELETE" | "POST" | "PUT" | "PATCH" | "HEAD", path: string, status: number, message: string);
constructor(method: "GET" | "DELETE" | "POST" | "PUT" | "PATCH" | "HEAD", path: string, status: number, headers: Record<string, string | string[]>, message: string);
/**

@@ -46,4 +47,5 @@ * `HttpError` to JSON.

status: number;
headers: Record<string, string | string[]>;
message: T;
}
}

@@ -36,3 +36,3 @@ "use strict";

*/
function HttpError(method, path, status, message) {
function HttpError(method, path, status, headers, message) {
var _newTarget = this.constructor;

@@ -43,2 +43,3 @@ var _this = _super.call(this, message) || this;

_this.status = status;
_this.headers = headers;
/**

@@ -81,2 +82,3 @@ * @internal

status: this.status,
headers: this.headers,
message: this.body_,

@@ -83,0 +85,0 @@ };

export * from "./IConnection";
export * from "./IEncryptionPassword";
export * from "./IPropagation";
export * from "./IRandomGenerator";
export * from "./HttpError";
export * from "./Primitive";
export * from "./HttpError";
export * from "./Resolved";

@@ -19,5 +19,7 @@ "use strict";

__exportStar(require("./IEncryptionPassword"), exports);
__exportStar(require("./IPropagation"), exports);
__exportStar(require("./IRandomGenerator"), exports);
__exportStar(require("./HttpError"), exports);
__exportStar(require("./Primitive"), exports);
__exportStar(require("./HttpError"), exports);
__exportStar(require("./Resolved"), exports);
//# sourceMappingURL=index.js.map
import { IConnection } from "../IConnection";
import { Primitive } from "../Primitive";
import { IFetchRoute } from "./IFetchRoute";
import { IPropagation } from "../IPropagation";
export declare namespace FetcherBase {

@@ -11,2 +12,3 @@ interface IProps {

const fetch: (props: IProps) => <Input, Output>(connection: IConnection, route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">, input?: Input | undefined, stringify?: ((input: Input) => string) | undefined) => Promise<Primitive<Output>>;
const propagate: (props: IProps) => <Input>(connection: IConnection, route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">, input?: Input | undefined, stringify?: ((input: Input) => string) | undefined) => Promise<IPropagation<any, any, any>>;
}

@@ -98,101 +98,145 @@ "use strict";

return function (connection, route, input, stringify) { return __awaiter(_this, void 0, void 0, function () {
var headers, init, path, url, response, _a, _b, text, _c, _d;
var _e, _f, _g, _h, _j, _k, _l, _m;
return __generator(this, function (_o) {
switch (_o.label) {
case 0:
headers = __assign({}, ((_e = connection.headers) !== null && _e !== void 0 ? _e : {}));
if (input !== undefined) {
if (((_f = route.request) === null || _f === void 0 ? void 0 : _f.type) === undefined)
throw new Error("Error on ".concat(props.className, ".fetch(): no content-type being configured."));
headers["Content-Type"] = route.request.type;
}
init = __assign(__assign({}, ((_g = connection.options) !== null && _g !== void 0 ? _g : {})), { method: route.method, headers: (function () {
var e_1, _a, e_2, _b;
var output = [];
try {
for (var _c = __values(Object.entries(headers)), _d = _c.next(); !_d.done; _d = _c.next()) {
var _e = __read(_d.value, 2), key = _e[0], value = _e[1];
if (value === undefined)
continue;
else if (Array.isArray(value))
try {
for (var value_1 = (e_2 = void 0, __values(value)), value_1_1 = value_1.next(); !value_1_1.done; value_1_1 = value_1.next()) {
var v = value_1_1.value;
output.push([key, String(v)]);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
var result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, _Propagate("fetch")(props)(connection, route, input, stringify)];
case 1:
result = _a.sent();
if (result.success === false)
throw new HttpError_1.HttpError(route.method, route.path, result.status, result.headers, result.data);
return [2 /*return*/, result.data];
}
});
}); };
};
FetcherBase.propagate = function (props) {
return function (connection, route, input, stringify) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/, _Propagate("propagate")(props)(connection, route, input, stringify)];
}); }); };
};
/**
* @internal
*/
var _Propagate = function (method) {
return function (props) {
return function (connection, route, input, stringify) { return __awaiter(_this, void 0, void 0, function () {
var headers, init, path, url, response, result, _a, type, text, _b, _c, _d;
var _e, _f, _g, _h, _j;
return __generator(this, function (_k) {
switch (_k.label) {
case 0:
headers = __assign({}, ((_e = connection.headers) !== null && _e !== void 0 ? _e : {}));
if (input !== undefined) {
if (((_f = route.request) === null || _f === void 0 ? void 0 : _f.type) === undefined)
throw new Error("Error on ".concat(props.className, ".fetch(): no content-type being configured."));
headers["Content-Type"] = route.request.type;
}
init = __assign(__assign({}, ((_g = connection.options) !== null && _g !== void 0 ? _g : {})), { method: route.method, headers: (function () {
var e_1, _a, e_2, _b;
var output = [];
try {
for (var _c = __values(Object.entries(headers)), _d = _c.next(); !_d.done; _d = _c.next()) {
var _e = __read(_d.value, 2), key = _e[0], value = _e[1];
if (value === undefined)
continue;
else if (Array.isArray(value))
try {
if (value_1_1 && !value_1_1.done && (_b = value_1.return)) _b.call(value_1);
for (var value_1 = (e_2 = void 0, __values(value)), value_1_1 = value_1.next(); !value_1_1.done; value_1_1 = value_1.next()) {
var v = value_1_1.value;
output.push([key, String(v)]);
}
}
finally { if (e_2) throw e_2.error; }
}
else
output.push([key, String(value)]);
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (value_1_1 && !value_1_1.done && (_b = value_1.return)) _b.call(value_1);
}
finally { if (e_2) throw e_2.error; }
}
else
output.push([key, String(value)]);
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_1) throw e_1.error; }
}
finally { if (e_1) throw e_1.error; }
return output;
})() });
// CONSTRUCT BODY DATA
if (input !== undefined)
init.body = props.encode(
// BODY TRANSFORM
((_h = route.request) === null || _h === void 0 ? void 0 : _h.type) !== "text/plain"
? (stringify !== null && stringify !== void 0 ? stringify : JSON.stringify)(input)
: input, headers);
path = connection.host[connection.host.length - 1] !== "/" &&
route.path[0] !== "/"
? "/".concat(route.path)
: route.path;
url = new URL("".concat(connection.host).concat(path));
return [4 /*yield*/, polyfill.get()];
case 1: return [4 /*yield*/, (_k.sent())(url.href, init)];
case 2:
response = _k.sent();
result = {
success: response.status === 200 ||
response.status === 201 ||
response.status == route.status,
status: route.status,
headers: response_headers_to_object(response.headers),
data: undefined,
};
if (!(result.success === false)) return [3 /*break*/, 4];
// WHEN FAILED
_a = result;
return [4 /*yield*/, response.text()];
case 3:
// WHEN FAILED
_a.data = _k.sent();
type = response.headers.get("content-type");
if (method !== "fetch" &&
type &&
type.indexOf("application/json") !== -1)
try {
result.data = JSON.parse(result.data);
}
return output;
})() });
// CONSTRUCT BODY DATA
if (input !== undefined)
init.body = props.encode(
// BODY TRANSFORM
((_h = route.request) === null || _h === void 0 ? void 0 : _h.type) !== "text/plain"
? (stringify !== null && stringify !== void 0 ? stringify : JSON.stringify)(input)
: input, headers);
path = connection.host[connection.host.length - 1] !== "/" &&
route.path[0] !== "/"
? "/".concat(route.path)
: route.path;
url = new URL("".concat(connection.host).concat(path));
return [4 /*yield*/, polyfill.get()];
case 1: return [4 /*yield*/, (_o.sent())(url.href, init)];
case 2:
response = _o.sent();
if (!((route.status !== null && response.status !== route.status) ||
(route.status === null &&
response.status !== 200 &&
response.status !== 201))) return [3 /*break*/, 4];
_a = HttpError_1.HttpError.bind;
_b = [void 0, route.method,
path,
response.status];
return [4 /*yield*/, response.text()];
case 3: throw new (_a.apply(HttpError_1.HttpError, _b.concat([_o.sent()])))();
case 4:
if (((_j = route.response) === null || _j === void 0 ? void 0 : _j.type) &&
((_l = ((_k = response.headers.get("content-type")) !== null && _k !== void 0 ? _k : route.response.type)) === null || _l === void 0 ? void 0 : _l.indexOf(route.response.type)) === -1)
throw new Error("Error on ".concat(props.className, ".fetch(): response type mismatched - expected ").concat(route.response.type, ", but ").concat(response.headers.get("content-type"), "."));
_o.label = 5;
case 5:
if (!(route.method === "HEAD")) return [3 /*break*/, 6];
return [2 /*return*/, undefined];
case 6:
if (!(((_m = route.response) === null || _m === void 0 ? void 0 : _m.type) === "application/json")) return [3 /*break*/, 8];
return [4 /*yield*/, response.text()];
case 7:
text = _o.sent();
return [2 /*return*/, text.length ? JSON.parse(text) : undefined];
case 8:
_d = (_c = props).decode;
return [4 /*yield*/, response.text()];
case 9: return [2 /*return*/, _d.apply(_c, [_o.sent(), response_headers_to_object(response.headers)])];
}
});
}); };
catch (_l) { }
return [3 /*break*/, 9];
case 4:
if (!(route.method === "HEAD")) return [3 /*break*/, 5];
result.data = undefined;
return [3 /*break*/, 9];
case 5:
if (!(((_j = route.response) === null || _j === void 0 ? void 0 : _j.type) === "application/json")) return [3 /*break*/, 7];
return [4 /*yield*/, response.text()];
case 6:
text = _k.sent();
result.data = text.length ? JSON.parse(text) : undefined;
return [3 /*break*/, 9];
case 7:
_b = result;
_d = (_c = props).decode;
return [4 /*yield*/, response.text()];
case 8:
_b.data = _d.apply(_c, [_k.sent(), result.headers]);
_k.label = 9;
case 9: return [2 /*return*/, result];
}
});
}); };
};
};
})(FetcherBase || (exports.FetcherBase = FetcherBase = {}));
/**
* @internal
*/
var polyfill = new Singleton_1.Singleton(function () { return __awaiter(void 0, void 0, void 0, function () {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
var _a, _b;
var _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:

@@ -202,14 +246,24 @@ if (!(typeof global === "object" &&

typeof global.process.versions === "object" &&
typeof global.process.versions.node !== undefined)) return [3 /*break*/, 3];
if (!(global.fetch === undefined)) return [3 /*break*/, 2];
_a = global;
typeof global.process.versions.node !== undefined)) return [3 /*break*/, 5];
if (!(global.fetch === undefined)) return [3 /*break*/, 4];
if (!((_c = global.fetch) !== null && _c !== void 0)) return [3 /*break*/, 1];
_a = _c;
return [3 /*break*/, 3];
case 1:
_b = global;
return [4 /*yield*/, (0, import2_1.default)("node-fetch")];
case 1:
_a.fetch = (_b.sent()).default;
_b.label = 2;
case 2: return [2 /*return*/, global.fetch];
case 3: return [2 /*return*/, window.fetch];
case 2:
_a = (_b.fetch = (_d.sent()).default);
_d.label = 3;
case 3:
_a;
_d.label = 4;
case 4: return [2 /*return*/, global.fetch];
case 5: return [2 /*return*/, window.fetch];
}
});
}); });
/**
* @internal
*/
var response_headers_to_object = function (headers) {

@@ -216,0 +270,0 @@ var output = {};

import { IConnection } from "./IConnection";
import { Primitive } from "./Primitive";
import { IFetchRoute } from "./internal/IFetchRoute";
import { IPropagation } from "./IPropagation";
/**

@@ -44,2 +45,4 @@ * Utility class for `fetch` functions used in `@nestia/sdk`.

function fetch<Input, Output>(connection: IConnection, route: IFetchRoute<"POST" | "PUT" | "PATCH" | "DELETE">, input?: Input, stringify?: (input: Input) => string): Promise<Primitive<Output>>;
function propagate<Output extends IPropagation<number, any, boolean>>(connection: IConnection, route: IFetchRoute<"HEAD">): Promise<Output>;
function propagate<Input, Output extends IPropagation<number, any, boolean>>(connection: IConnection, route: IFetchRoute<"HEAD">, input?: Input, stringify?: (input: Input) => string): Promise<Output>;
}

@@ -74,3 +74,19 @@ "use strict";

PlainFetcher.fetch = fetch;
function propagate(connection, route, input, stringify) {
var _a, _b;
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_c) {
if (((_a = route.request) === null || _a === void 0 ? void 0 : _a.encrypted) === true ||
((_b = route.response) === null || _b === void 0 ? void 0 : _b.encrypted) === true)
throw new Error("Error on PlainFetcher.propagate(): PlainFetcher doesn't have encryption ability. Use EncryptedFetcher instead.");
return [2 /*return*/, FetcherBase_1.FetcherBase.propagate({
className: "PlainFetcher",
encode: function (input) { return input; },
decode: function (input) { return input; },
})(connection, route, input, stringify)];
});
});
}
PlainFetcher.propagate = propagate;
})(PlainFetcher || (exports.PlainFetcher = PlainFetcher = {}));
//# sourceMappingURL=PlainFetcher.js.map
/**
* Primitive type.
* Primitive type of JSON.
*
* `Primitive` is a type of TMP (Type Meta Programming) type who converts its argument as a
* primitive type.
* `Primitive<T>` is a TMP (Type Meta Programming) type which converts
* its argument as a primitive type within framework JSON.
*
* If the target argument is a built-in class who returns its origin primitive type through
* the `valueOf()` method like the `String` or `Number`, its return type would be the
* `string` or `number`.
* If the target argument is a built-in class which returns its origin primitive type
* through the `valueOf()` method like the `String` or `Number`, its return type would
* be the `string` or `number`. Otherwise, the built-in class does not have the
* `valueOf()` method, the return type would be an empty object (`{}`).
*
* Otherwise, the target argument is a type of custom class, all of its custom method would
* be erased and its prototype would be changed to the primitive `object`. Therefore, return
* type of the TMP type finally be the primitive object.
* Otherwise, the target argument is a type of custom class, all of its custom method
* would be erased and its prototype would be changed to the primitive `object`.
* Therefore, return type of the TMP type finally be the primitive object.
*

@@ -26,6 +27,7 @@ * In addition, if the target argument is a type of custom class and it has a special

* `Class` with `toJSON()` | `Primitive<ReturnType<Class.toJSON>>`
* Native Class | `{}`
* Others | No change
*
* @template Instance Target argument type.
* @author Jenogho Nam - https://github.com/samchon
* @author Jeongho Nam - https://github.com/samchon
* @author Kyungsu Kang - https://github.com/kakasoo

@@ -36,5 +38,5 @@ * @author Michael - https://github.com/8471919

type Equal<X, Y> = X extends Y ? (Y extends X ? true : false) : false;
type PrimitiveMain<Instance> = Instance extends [never] ? never : ValueOf<Instance> extends boolean | number | bigint | string ? ValueOf<Instance> : ValueOf<Instance> extends object ? Instance extends object ? Instance extends NativeClass ? {} : Instance extends IJsonable<infer Raw> ? ValueOf<Raw> extends object ? Raw extends object ? PrimitiveObject<Raw> : never : ValueOf<Raw> : PrimitiveObject<Instance> : never : ValueOf<Instance>;
type PrimitiveMain<Instance> = Instance extends [never] ? never : ValueOf<Instance> extends bigint ? never : ValueOf<Instance> extends boolean | number | string ? ValueOf<Instance> : Instance extends Function ? never : ValueOf<Instance> extends object ? Instance extends object ? Instance extends NativeClass ? {} : Instance extends IJsonable<infer Raw> ? ValueOf<Raw> extends object ? Raw extends object ? PrimitiveObject<Raw> : never : ValueOf<Raw> : PrimitiveObject<Instance> : never : ValueOf<Instance>;
type PrimitiveObject<Instance extends object> = Instance extends Array<infer T> ? IsTuple<Instance> extends true ? PrimitiveTuple<Instance> : PrimitiveMain<T>[] : {
[P in keyof Instance]: Instance[P] extends Function ? never : PrimitiveMain<Instance[P]>;
[P in keyof Instance]: PrimitiveMain<Instance[P]>;
};

@@ -49,3 +51,3 @@ type PrimitiveTuple<T extends readonly any[]> = T extends [] ? [] : T extends [infer F] ? [PrimitiveMain<F>] : T extends [infer F, ...infer Rest extends readonly any[]] ? [PrimitiveMain<F>, ...PrimitiveTuple<Rest>] : T extends [(infer F)?] ? [PrimitiveMain<F>?] : T extends [(infer F)?, ...infer Rest extends readonly any[]] ? [PrimitiveMain<F>?, ...PrimitiveTuple<Rest>] : [];

] ? false : T extends readonly any[] ? number extends T["length"] ? false : true : false;
type IsValueOf<Instance, Object extends IValueOf<any>> = Instance extends Object ? Object extends IValueOf<infer Primitive> ? Instance extends Primitive ? false : true : false : false;
type IsValueOf<Instance, Object extends IValueOf<any>> = Instance extends Object ? Object extends IValueOf<infer U> ? Instance extends U ? false : true : false : false;
interface IValueOf<T> {

@@ -52,0 +54,0 @@ valueOf(): T;

{
"name": "@nestia/fetcher",
"version": "2.0.0-dev.20230906",
"version": "2.0.0-dev.20230907",
"description": "Fetcher library of Nestia SDK",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

import { AesPkcs5 } from "./AesPkcs5";
import { IConnection } from "./IConnection";
import { IEncryptionPassword } from "./IEncryptionPassword";
import { IPropagation } from "./IPropagation";
import { Primitive } from "./Primitive";

@@ -118,2 +119,77 @@ import { FetcherBase } from "./internal/FetcherBase";

}
export function propagate<
Output extends IPropagation<number, any, boolean>,
>(connection: IConnection, route: IFetchRoute<"HEAD">): Promise<Output>;
export function propagate<
Input,
Output extends IPropagation<number, any, boolean>,
>(
connection: IConnection,
route: IFetchRoute<"HEAD">,
input?: Input,
stringify?: (input: Input) => string,
): Promise<Output>;
export async function propagate<
Input,
Output extends IPropagation<number, any, boolean>,
>(
connection: IConnection,
route: IFetchRoute<
"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT"
>,
input?: Input,
stringify?: (input: Input) => string,
): Promise<Output> {
if (
(route.request?.encrypted === true || route.response?.encrypted) &&
connection.encryption === undefined
)
throw new Error(
"Error on EncryptedFetcher.propagate(): the encryption password has not been configured.",
);
const closure =
typeof connection.encryption === "function"
? (direction: "encode" | "decode") =>
(
headers: Record<
string,
IConnection.HeaderValue | undefined
>,
body: string,
) =>
(
connection.encryption as IEncryptionPassword.Closure
)({
headers,
body,
direction,
})
: () => () => connection.encryption as IEncryptionPassword;
return FetcherBase.propagate({
className: "EncryptedFetcher",
encode:
route.request?.encrypted === true
? (input, headers) => {
const p = closure("encode")(headers, input);
return AesPkcs5.encrypt(
JSON.stringify(input),
p.key,
p.iv,
);
}
: (input) => input,
decode:
route.response?.encrypted === true
? (input, headers) => {
const p = closure("decode")(headers, input);
const str = AesPkcs5.decrypt(input, p.key, p.iv);
return str.length ? JSON.parse(str) : str;
}
: (input) => input,
})(connection, route, input, stringify) as Promise<Output>;
}
}

@@ -32,2 +32,3 @@ /**

public readonly status: number,
public readonly headers: Record<string, string | string[]>,
message: string,

@@ -67,2 +68,3 @@ ) {

status: this.status,
headers: this.headers,
message: this.body_,

@@ -80,2 +82,3 @@ };

status: number;
headers: Record<string, string | string[]>;
message: T;

@@ -82,0 +85,0 @@ }

export * from "./IConnection";
export * from "./IEncryptionPassword";
export * from "./IPropagation";
export * from "./IRandomGenerator";
export * from "./HttpError";
export * from "./Primitive";
export * from "./HttpError";
export * from "./Resolved";

@@ -7,2 +7,3 @@ import import2 from "import2";

import { HttpError } from "../HttpError";
import { IPropagation } from "../IPropagation";

@@ -32,2 +33,45 @@ export namespace FetcherBase {

): Promise<Primitive<Output>> => {
const result = await _Propagate("fetch")(props)(
connection,
route,
input,
stringify,
);
if (result.success === false)
throw new HttpError(
route.method,
route.path,
result.status,
result.headers,
result.data as string,
);
return result.data as Primitive<Output>;
};
export const propagate =
(props: IProps) =>
async <Input>(
connection: IConnection,
route: IFetchRoute<
"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT"
>,
input?: Input,
stringify?: (input: Input) => string,
): Promise<IPropagation<any, any, any>> =>
_Propagate("propagate")(props)(connection, route, input, stringify);
/**
* @internal
*/
const _Propagate =
(method: string) =>
(props: IProps) =>
async <Input>(
connection: IConnection,
route: IFetchRoute<
"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT"
>,
input?: Input,
stringify?: (input: Input) => string,
): Promise<IPropagation<any, any, any>> => {
//----

@@ -91,42 +135,43 @@ // REQUEST MESSSAGE

// VALIDATE RESPONSE
if (
(route.status !== null && response.status !== route.status) ||
(route.status === null &&
response.status !== 200 &&
response.status !== 201)
)
throw new HttpError(
route.method,
path,
response.status,
await response.text(),
);
else if (
route.response?.type &&
(
response.headers.get("content-type") ?? route.response.type
)?.indexOf(route.response.type) === -1
)
throw new Error(
`Error on ${
props.className
}.fetch(): response type mismatched - expected ${
route.response.type
}, but ${response.headers.get("content-type")}.`,
);
// RETURNS
if (route.method === "HEAD") return undefined!;
else if (route.response?.type === "application/json") {
const text: string = await response.text();
return text.length ? JSON.parse(text) : undefined;
// CONSTRUCT RESULT DATA
const result: IPropagation<any, any, any> = {
success:
response.status === 200 ||
response.status === 201 ||
response.status == route.status,
status: route.status,
headers: response_headers_to_object(response.headers),
data: undefined!,
};
if (result.success === false) {
// WHEN FAILED
result.data = await response.text();
const type = response.headers.get("content-type");
if (
method !== "fetch" &&
type &&
type.indexOf("application/json") !== -1
)
try {
result.data = JSON.parse(result.data);
} catch {}
} else {
// WHEN SUCCESS
if (route.method === "HEAD") result.data = undefined!;
else if (route.response?.type === "application/json") {
const text: string = await response.text();
result.data = text.length ? JSON.parse(text) : undefined;
} else
result.data = props.decode(
await response.text(),
result.headers,
);
}
return props.decode(
await response.text(),
response_headers_to_object(response.headers),
) as Primitive<Output>;
return result;
};
}
/**
* @internal
*/
const polyfill = new Singleton(async (): Promise<typeof fetch> => {

@@ -140,3 +185,3 @@ if (

if (global.fetch === undefined)
global.fetch = ((await import2("node-fetch")) as any).default;
global.fetch ??= ((await import2("node-fetch")) as any).default;
return (global as any).fetch;

@@ -147,6 +192,9 @@ }

/**
* @internal
*/
const response_headers_to_object = (
headers: Headers,
): Record<string, IConnection.HeaderValue | undefined> => {
const output: Record<string, IConnection.HeaderValue> = {};
): Record<string, string | string[]> => {
const output: Record<string, string | string[]> = {};
headers.forEach((value, key) => {

@@ -153,0 +201,0 @@ if (key === "set-cookie") {

@@ -6,2 +6,3 @@ import { IConnection } from "./IConnection";

import { FetcherBase } from "./internal/FetcherBase";
import { IPropagation } from "./IPropagation";

@@ -83,2 +84,41 @@ /**

}
export function propagate<
Output extends IPropagation<number, any, boolean>,
>(connection: IConnection, route: IFetchRoute<"HEAD">): Promise<Output>;
export function propagate<
Input,
Output extends IPropagation<number, any, boolean>,
>(
connection: IConnection,
route: IFetchRoute<"HEAD">,
input?: Input,
stringify?: (input: Input) => string,
): Promise<Output>;
export async function propagate<
Input,
Output extends IPropagation<number, any, boolean>,
>(
connection: IConnection,
route: IFetchRoute<
"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT"
>,
input?: Input,
stringify?: (input: Input) => string,
): Promise<Output> {
if (
route.request?.encrypted === true ||
route.response?.encrypted === true
)
throw new Error(
"Error on PlainFetcher.propagate(): PlainFetcher doesn't have encryption ability. Use EncryptedFetcher instead.",
);
return FetcherBase.propagate({
className: "PlainFetcher",
encode: (input) => input,
decode: (input) => input,
})(connection, route, input, stringify) as Promise<Output>;
}
}
/**
* Primitive type.
* Primitive type of JSON.
*
* `Primitive` is a type of TMP (Type Meta Programming) type who converts its argument as a
* primitive type.
* `Primitive<T>` is a TMP (Type Meta Programming) type which converts
* its argument as a primitive type within framework JSON.
*
* If the target argument is a built-in class who returns its origin primitive type through
* the `valueOf()` method like the `String` or `Number`, its return type would be the
* `string` or `number`.
* If the target argument is a built-in class which returns its origin primitive type
* through the `valueOf()` method like the `String` or `Number`, its return type would
* be the `string` or `number`. Otherwise, the built-in class does not have the
* `valueOf()` method, the return type would be an empty object (`{}`).
*
* Otherwise, the target argument is a type of custom class, all of its custom method would
* be erased and its prototype would be changed to the primitive `object`. Therefore, return
* type of the TMP type finally be the primitive object.
* Otherwise, the target argument is a type of custom class, all of its custom method
* would be erased and its prototype would be changed to the primitive `object`.
* Therefore, return type of the TMP type finally be the primitive object.
*

@@ -26,6 +27,7 @@ * In addition, if the target argument is a type of custom class and it has a special

* `Class` with `toJSON()` | `Primitive<ReturnType<Class.toJSON>>`
* Native Class | `{}`
* Others | No change
*
* @template Instance Target argument type.
* @author Jenogho Nam - https://github.com/samchon
* @author Jeongho Nam - https://github.com/samchon
* @author Kyungsu Kang - https://github.com/kakasoo

@@ -42,4 +44,8 @@ * @author Michael - https://github.com/8471919

? never // (special trick for jsonable | null) type
: ValueOf<Instance> extends boolean | number | bigint | string
: ValueOf<Instance> extends bigint
? never
: ValueOf<Instance> extends boolean | number | string
? ValueOf<Instance>
: Instance extends Function
? never
: ValueOf<Instance> extends object

@@ -64,5 +70,3 @@ ? Instance extends object

: {
[P in keyof Instance]: Instance[P] extends Function
? never
: PrimitiveMain<Instance[P]>;
[P in keyof Instance]: PrimitiveMain<Instance[P]>;
};

@@ -121,4 +125,4 @@

type IsValueOf<Instance, Object extends IValueOf<any>> = Instance extends Object
? Object extends IValueOf<infer Primitive>
? Instance extends Primitive
? Object extends IValueOf<infer U>
? Instance extends U
? false

@@ -125,0 +129,0 @@ : true // not Primitive, but Object

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc