@nestia/fetcher 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -0
- package/lib/AesPkcs5.d.ts +30 -0
- package/lib/AesPkcs5.js +49 -0
- package/lib/AesPkcs5.js.map +1 -0
- package/lib/Fetcher.d.ts +68 -0
- package/lib/Fetcher.js +190 -0
- package/lib/Fetcher.js.map +1 -0
- package/lib/HttpError.d.ts +21 -0
- package/lib/HttpError.js +53 -0
- package/lib/HttpError.js.map +1 -0
- package/lib/IConnection.d.ts +29 -0
- package/lib/IConnection.js +3 -0
- package/lib/IConnection.js.map +1 -0
- package/lib/IEncryptionPassword.d.ts +56 -0
- package/lib/IEncryptionPassword.js +3 -0
- package/lib/IEncryptionPassword.js.map +1 -0
- package/lib/Primitive.d.ts +45 -0
- package/lib/Primitive.js +3 -0
- package/lib/Primitive.js.map +1 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +23 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/Singleton.d.ts +1 -0
- package/lib/internal/Singleton.js +24 -0
- package/lib/internal/Singleton.js.map +1 -0
- package/package.json +48 -0
- package/src/AesPkcs5.ts +51 -0
- package/src/Fetcher.ts +241 -0
- package/src/HttpError.ts +30 -0
- package/src/IConnection.ts +32 -0
- package/src/IEncryptionPassword.ts +64 -0
- package/src/Primitive.ts +85 -0
- package/src/index.ts +7 -0
- package/src/internal/Singleton.ts +20 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Primitive type.
|
|
3
|
+
*
|
|
4
|
+
* `Primitive` is a type of TMP (Type Meta Programming) type who converts its argument as a
|
|
5
|
+
* primitive type.
|
|
6
|
+
*
|
|
7
|
+
* If the target argument is a built-in class who returns its origin primitive type through
|
|
8
|
+
* the `valueOf()` method like the `String` or `Number`, its return type would be the
|
|
9
|
+
* `string` or `number`.
|
|
10
|
+
*
|
|
11
|
+
* Otherwise, the target argument is a type of custom class, all of its custom method would
|
|
12
|
+
* be erased and its prototype would be changed to the primitive `object`. Therefore, return
|
|
13
|
+
* type of the TMP type finally be the primitive object.
|
|
14
|
+
*
|
|
15
|
+
* In addition, if the target argument is a type of custom class and it has a special
|
|
16
|
+
* method `toJSON()`, return type of this `Primitive` would be not `Primitive<Instance>`
|
|
17
|
+
* but `Primitive<ReturnType<Instance.toJSON>>`.
|
|
18
|
+
*
|
|
19
|
+
* Before | After
|
|
20
|
+
* ------------------------|----------------------------------------
|
|
21
|
+
* `Boolean` | `boolean`
|
|
22
|
+
* `Number` | `number`
|
|
23
|
+
* `String` | `string`
|
|
24
|
+
* `Class` | `object`
|
|
25
|
+
* `Class` with `toJSON()` | `Primitive<ReturnType<Class.toJSON>>`
|
|
26
|
+
* Others | No change
|
|
27
|
+
*
|
|
28
|
+
* @template Instance Target argument type.
|
|
29
|
+
* @author Jenogho Nam - https://github.com/samchon
|
|
30
|
+
*/
|
|
31
|
+
export declare type Primitive<Instance> = _Equal<Instance, _Primitive<Instance>> extends true ? Instance : _Primitive<Instance>;
|
|
32
|
+
declare type _Equal<X, Y> = X extends Y ? (Y extends X ? true : false) : false;
|
|
33
|
+
declare type _Primitive<Instance> = _ValueOf<Instance> extends object ? Instance extends object ? Instance extends IJsonable<infer Raw> ? _ValueOf<Raw> extends object ? Raw extends object ? _PrimitiveObject<Raw> : never : _ValueOf<Raw> : _PrimitiveObject<Instance> : never : _ValueOf<Instance>;
|
|
34
|
+
declare type _PrimitiveObject<Instance extends object> = Instance extends Array<infer T> ? _Primitive<T>[] : {
|
|
35
|
+
[P in keyof Instance]: Instance[P] extends Function ? never : _Primitive<Instance[P]>;
|
|
36
|
+
};
|
|
37
|
+
declare type _ValueOf<Instance> = _IsValueOf<Instance, Boolean> extends true ? boolean : _IsValueOf<Instance, Number> extends true ? number : _IsValueOf<Instance, String> extends true ? string : Instance;
|
|
38
|
+
declare type _IsValueOf<Instance, Object extends IValueOf<any>> = Instance extends Object ? Object extends IValueOf<infer Primitive> ? Instance extends Primitive ? false : true : false : false;
|
|
39
|
+
interface IValueOf<T> {
|
|
40
|
+
valueOf(): T;
|
|
41
|
+
}
|
|
42
|
+
interface IJsonable<T> {
|
|
43
|
+
toJSON(): T;
|
|
44
|
+
}
|
|
45
|
+
export {};
|
package/lib/Primitive.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Primitive.js","sourceRoot":"","sources":["../src/Primitive.ts"],"names":[],"mappings":""}
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./IConnection"), exports);
|
|
18
|
+
__exportStar(require("./IEncryptionPassword"), exports);
|
|
19
|
+
__exportStar(require("./Primitive"), exports);
|
|
20
|
+
__exportStar(require("./AesPkcs5"), exports);
|
|
21
|
+
__exportStar(require("./Fetcher"), exports);
|
|
22
|
+
__exportStar(require("./HttpError"), exports);
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,wDAAsC;AACtC,8CAA4B;AAE5B,6CAA2B;AAC3B,4CAA0B;AAC1B,8CAA4B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Singleton = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
var Singleton = /** @class */ (function () {
|
|
8
|
+
function Singleton(closure_) {
|
|
9
|
+
this.closure_ = closure_;
|
|
10
|
+
this.value_ = NOT_MOUNTED_YET;
|
|
11
|
+
}
|
|
12
|
+
Singleton.prototype.get = function () {
|
|
13
|
+
if (this.value_ === NOT_MOUNTED_YET)
|
|
14
|
+
this.value_ = this.closure_();
|
|
15
|
+
return this.value_;
|
|
16
|
+
};
|
|
17
|
+
return Singleton;
|
|
18
|
+
}());
|
|
19
|
+
exports.Singleton = Singleton;
|
|
20
|
+
/**
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
var NOT_MOUNTED_YET = {};
|
|
24
|
+
//# sourceMappingURL=Singleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Singleton.js","sourceRoot":"","sources":["../../src/internal/Singleton.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH;IAGI,mBAAoC,QAAiB;QAAjB,aAAQ,GAAR,QAAQ,CAAS;QACjD,IAAI,CAAC,MAAM,GAAG,eAAe,CAAC;IAClC,CAAC;IAEM,uBAAG,GAAV;QACI,IAAI,IAAI,CAAC,MAAM,KAAK,eAAe;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnE,OAAO,IAAI,CAAC,MAAW,CAAC;IAC5B,CAAC;IACL,gBAAC;AAAD,CAAC,AAXD,IAWC;AAXY,8BAAS;AAatB;;GAEG;AACH,IAAM,eAAe,GAAG,EAAE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nestia/fetcher",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Fetcher library of Nestia SDK",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"typings": "lib/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "rimraf lib && tsc",
|
|
9
|
+
"dev": "npm run build -- --watch",
|
|
10
|
+
"eslint": "eslint src",
|
|
11
|
+
"eslint:fix": "eslint src --fix",
|
|
12
|
+
"prettier": "prettier src --write"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/samchon/nestia"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"nestia",
|
|
20
|
+
"fetcher",
|
|
21
|
+
"sdk"
|
|
22
|
+
],
|
|
23
|
+
"author": "Jeongho Nam",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/samchon/nestia/issues"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/samchon/nestia/packages/fetcher",
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^18.11.14",
|
|
31
|
+
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
|
32
|
+
"@typescript-eslint/parser": "^5.46.1",
|
|
33
|
+
"prettier": "^2.8.1",
|
|
34
|
+
"rimraf": "^3.0.2",
|
|
35
|
+
"typescript": "^4.9.4"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"import2": "^1.0.3",
|
|
39
|
+
"node-fetch": "^3.3.0"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"README.md",
|
|
43
|
+
"LICENSE",
|
|
44
|
+
"package.json",
|
|
45
|
+
"lib",
|
|
46
|
+
"src"
|
|
47
|
+
]
|
|
48
|
+
}
|
package/src/AesPkcs5.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Utility class for the AES-128/256 encryption.
|
|
5
|
+
*
|
|
6
|
+
* - AES-128/256
|
|
7
|
+
* - CBC mode
|
|
8
|
+
* - PKCS#5 Padding
|
|
9
|
+
* - Base64 Encoding
|
|
10
|
+
*
|
|
11
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
12
|
+
*/
|
|
13
|
+
export namespace AesPkcs5 {
|
|
14
|
+
/**
|
|
15
|
+
* Encrypt data
|
|
16
|
+
*
|
|
17
|
+
* @param data Target data
|
|
18
|
+
* @param key Key value of the encryption.
|
|
19
|
+
* @param iv Initializer Vector for the encryption
|
|
20
|
+
* @return Encrypted data
|
|
21
|
+
*/
|
|
22
|
+
export function encrypt(data: string, key: string, iv: string): string {
|
|
23
|
+
const bytes: number = key.length * 8;
|
|
24
|
+
const cipher: crypto.Cipher = crypto.createCipheriv(
|
|
25
|
+
`AES-${bytes}-CBC`,
|
|
26
|
+
key,
|
|
27
|
+
iv,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return cipher.update(data, "utf8", "base64") + cipher.final("base64");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Decrypt data.
|
|
35
|
+
*
|
|
36
|
+
* @param data Target data
|
|
37
|
+
* @param key Key value of the decryption.
|
|
38
|
+
* @param iv Initializer Vector for the decryption
|
|
39
|
+
* @return Decrypted data.
|
|
40
|
+
*/
|
|
41
|
+
export function decrypt(data: string, key: string, iv: string): string {
|
|
42
|
+
const bytes: number = key.length * 8;
|
|
43
|
+
const decipher: crypto.Decipher = crypto.createDecipheriv(
|
|
44
|
+
`AES-${bytes}-CBC`,
|
|
45
|
+
key,
|
|
46
|
+
iv,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
return decipher.update(data, "base64", "utf8") + decipher.final("utf8");
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/Fetcher.ts
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import import2 from "import2";
|
|
2
|
+
|
|
3
|
+
import { IConnection } from "./IConnection";
|
|
4
|
+
import { IEncryptionPassword } from "./IEncryptionPassword";
|
|
5
|
+
import { Primitive } from "./Primitive";
|
|
6
|
+
|
|
7
|
+
import { AesPkcs5 } from "./AesPkcs5";
|
|
8
|
+
import { HttpError } from "./HttpError";
|
|
9
|
+
import { Singleton } from "./internal/Singleton";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Fetcher, utility class for the [**Nestia**](https://github.com/samchon/nestia) fetch.
|
|
13
|
+
*
|
|
14
|
+
* `Fetcher` is a utility class providing the {@link Fetcher.fetch} functions who're being
|
|
15
|
+
* used by all of the SDK libraries, interacting with the remote HTTP servers, who are
|
|
16
|
+
* generated by the [**Nestia**](https://github.com/samchon/nestia).
|
|
17
|
+
*
|
|
18
|
+
* As this `Fetcher` be used only by the [**Nestia**](https://github.com/samchon/nestia)
|
|
19
|
+
* generated SDK libraries, you don't need to handle this class directly. It may only be
|
|
20
|
+
* appeared in the source codes of the [**Nestia**](https://github.com/samchon/nestia)
|
|
21
|
+
* generated SDK libraries.
|
|
22
|
+
*
|
|
23
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
24
|
+
*/
|
|
25
|
+
export class Fetcher {
|
|
26
|
+
/**
|
|
27
|
+
* Fetch function for the `GET` or `DELETE` methods.
|
|
28
|
+
*
|
|
29
|
+
* @param connection Connection information for the remote HTTP server
|
|
30
|
+
* @param encrypted Whether the request/response body be encrypted or not
|
|
31
|
+
* @param method Method of the HTTP request
|
|
32
|
+
* @param path Path of the HTTP request
|
|
33
|
+
* @return Response body data from the remote HTTP server
|
|
34
|
+
*/
|
|
35
|
+
public static fetch<Output>(
|
|
36
|
+
connection: IConnection,
|
|
37
|
+
encrypted: Fetcher.IEncrypted,
|
|
38
|
+
method: "GET" | "DELETE",
|
|
39
|
+
path: string,
|
|
40
|
+
): Promise<Primitive<Output>>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Fetch function for the `POST`, `PUT` and `PATCH` methods.
|
|
44
|
+
*
|
|
45
|
+
* @param connection Connection information for the remote HTTP server
|
|
46
|
+
* @param encrypted Whether the request/response body be encrypted or not
|
|
47
|
+
* @param method Method of the HTTP request
|
|
48
|
+
* @param path Path of the HTTP request
|
|
49
|
+
* @param input Request body data for the HTTP request
|
|
50
|
+
* @param stringify JSON string conversion function, default is the `JSON.stringify`
|
|
51
|
+
* @return Response body data from the remote HTTP server
|
|
52
|
+
*/
|
|
53
|
+
public static fetch<Input, Output>(
|
|
54
|
+
connection: IConnection,
|
|
55
|
+
encrypted: Fetcher.IEncrypted,
|
|
56
|
+
method: "POST" | "PUT" | "PATCH",
|
|
57
|
+
path: string,
|
|
58
|
+
input: Input,
|
|
59
|
+
stringify?: (input: Input) => string,
|
|
60
|
+
): Promise<Primitive<Output>>;
|
|
61
|
+
|
|
62
|
+
public static async fetch<Output>(
|
|
63
|
+
connection: IConnection,
|
|
64
|
+
encrypted: Fetcher.IEncrypted,
|
|
65
|
+
method: "GET" | "DELETE" | "POST" | "PUT" | "PATCH",
|
|
66
|
+
path: string,
|
|
67
|
+
input?: object,
|
|
68
|
+
stringify?: (input: object) => string,
|
|
69
|
+
): Promise<Primitive<Output>> {
|
|
70
|
+
if (encrypted.request === true || encrypted.response === true)
|
|
71
|
+
if (connection.encryption === undefined)
|
|
72
|
+
throw new Error(
|
|
73
|
+
"Error on nestia.Fetcher.encrypt(): the encryption password has not been configured.",
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
//----
|
|
77
|
+
// REQUEST MESSSAGE
|
|
78
|
+
//----
|
|
79
|
+
// METHOD & HEADERS
|
|
80
|
+
const init: RequestInit = {
|
|
81
|
+
method,
|
|
82
|
+
headers:
|
|
83
|
+
encrypted.request === false &&
|
|
84
|
+
input !== undefined &&
|
|
85
|
+
typeof input === "object"
|
|
86
|
+
? {
|
|
87
|
+
...connection.headers,
|
|
88
|
+
"Content-Type": "application/json",
|
|
89
|
+
}
|
|
90
|
+
: connection.headers,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// REQUEST BODY (WITH ENCRYPTION)
|
|
94
|
+
if (input !== undefined) {
|
|
95
|
+
let body: string = (stringify || JSON.stringify)(input);
|
|
96
|
+
if (encrypted.request === true) {
|
|
97
|
+
const headers: Singleton<Record<string, string>> =
|
|
98
|
+
new Singleton(() => init.headers as Record<string, string>);
|
|
99
|
+
const password:
|
|
100
|
+
| IEncryptionPassword
|
|
101
|
+
| IEncryptionPassword.Closure =
|
|
102
|
+
connection.encryption instanceof Function
|
|
103
|
+
? connection.encryption!(
|
|
104
|
+
{ headers: headers.get(), body },
|
|
105
|
+
true,
|
|
106
|
+
)
|
|
107
|
+
: connection.encryption!;
|
|
108
|
+
if (is_disabled(password, headers, body, true) === false)
|
|
109
|
+
body = AesPkcs5.encrypt(body, password.key, password.iv);
|
|
110
|
+
}
|
|
111
|
+
init.body = body;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
//----
|
|
115
|
+
// RESPONSE MESSAGE
|
|
116
|
+
//----
|
|
117
|
+
// URL SPECIFICATION
|
|
118
|
+
if (
|
|
119
|
+
connection.host[connection.host.length - 1] !== "/" &&
|
|
120
|
+
path[0] !== "/"
|
|
121
|
+
)
|
|
122
|
+
path = "/" + path;
|
|
123
|
+
|
|
124
|
+
const url: URL = new URL(`${connection.host}${path}`);
|
|
125
|
+
|
|
126
|
+
// DO FETCH
|
|
127
|
+
const response: Response = await (await polyfill.get())(url.href, init);
|
|
128
|
+
let body: string = await response.text();
|
|
129
|
+
if (!body) return undefined!;
|
|
130
|
+
|
|
131
|
+
// CHECK THE STATUS CODE
|
|
132
|
+
if (response.status !== 200 && response.status !== 201)
|
|
133
|
+
throw new HttpError(method, path, response.status, body);
|
|
134
|
+
|
|
135
|
+
// FINALIZATION (WITH DECODING)
|
|
136
|
+
if (encrypted.response === true) {
|
|
137
|
+
const headers: Singleton<Record<string, string>> = new Singleton(
|
|
138
|
+
() => headers_to_object(response.headers),
|
|
139
|
+
);
|
|
140
|
+
const password: IEncryptionPassword | IEncryptionPassword.Closure =
|
|
141
|
+
connection.encryption instanceof Function
|
|
142
|
+
? connection.encryption!(
|
|
143
|
+
{ headers: headers.get(), body },
|
|
144
|
+
false,
|
|
145
|
+
)
|
|
146
|
+
: connection.encryption!;
|
|
147
|
+
if (is_disabled(password, headers, body, false) === false)
|
|
148
|
+
body = AesPkcs5.decrypt(body, password.key, password.iv);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
//----
|
|
152
|
+
// OUTPUT
|
|
153
|
+
//----
|
|
154
|
+
let ret: { __set_headers__: Record<string, any> } & Primitive<Output> =
|
|
155
|
+
body as any;
|
|
156
|
+
try {
|
|
157
|
+
// PARSE RESPONSE BODY
|
|
158
|
+
ret = JSON.parse(ret as any);
|
|
159
|
+
|
|
160
|
+
// FIND __SET_HEADERS__ FIELD
|
|
161
|
+
if (
|
|
162
|
+
ret.__set_headers__ !== undefined &&
|
|
163
|
+
typeof ret.__set_headers__ === "object"
|
|
164
|
+
) {
|
|
165
|
+
if (connection.headers === undefined) connection.headers = {};
|
|
166
|
+
Object.assign(connection.headers, ret.__set_headers__);
|
|
167
|
+
}
|
|
168
|
+
} catch {}
|
|
169
|
+
|
|
170
|
+
// RETURNS
|
|
171
|
+
return ret;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export namespace Fetcher {
|
|
176
|
+
/**
|
|
177
|
+
* Whether be encrypted or not.
|
|
178
|
+
*
|
|
179
|
+
* `Fetcher.IEncrypted` is a type of interface who represents whether the HTTP request
|
|
180
|
+
* and response body must be encrypted or not.
|
|
181
|
+
*
|
|
182
|
+
* Like the {@link Fetcher} who are being used by all of the SDK libraries that are
|
|
183
|
+
* generated by the [Nestia](https://github.com/samchon/nestia), this `IEncrypted`
|
|
184
|
+
* interface would be used by the [Nestia](https://github.com/samchon/nestia) generated
|
|
185
|
+
* SDK libaries.
|
|
186
|
+
*
|
|
187
|
+
* As this `Fetcher` be used only by the [**Nestia**](https://github.com/samchon/nestia)
|
|
188
|
+
* generated SDK libraries, you don't need to handle this class directly. It may only be
|
|
189
|
+
* appeared in the source codes of the [**Nestia**](https://github.com/samchon/nestia)
|
|
190
|
+
* generated SDK libraries.
|
|
191
|
+
*/
|
|
192
|
+
export interface IEncrypted {
|
|
193
|
+
/**
|
|
194
|
+
* Whether the request body be encrypted or not.
|
|
195
|
+
*/
|
|
196
|
+
request?: boolean;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Whether the response body be encrypted or not.
|
|
200
|
+
*/
|
|
201
|
+
response: boolean;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const polyfill = new Singleton(async (): Promise<typeof fetch> => {
|
|
206
|
+
if (
|
|
207
|
+
typeof global === "object" &&
|
|
208
|
+
typeof global.process === "object" &&
|
|
209
|
+
typeof global.process.versions === "object" &&
|
|
210
|
+
typeof global.process.versions.node !== undefined
|
|
211
|
+
) {
|
|
212
|
+
if (global.fetch === undefined)
|
|
213
|
+
global.fetch = ((await import2("node-fetch")) as any).default;
|
|
214
|
+
return (global as any).fetch;
|
|
215
|
+
}
|
|
216
|
+
return window.fetch;
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
function is_disabled(
|
|
220
|
+
password: IEncryptionPassword,
|
|
221
|
+
headers: Singleton<Record<string, string>>,
|
|
222
|
+
body: string,
|
|
223
|
+
encoded: boolean,
|
|
224
|
+
): boolean {
|
|
225
|
+
if (password.disabled === undefined) return false;
|
|
226
|
+
if (typeof password.disabled === "function")
|
|
227
|
+
return password.disabled(
|
|
228
|
+
{
|
|
229
|
+
headers: headers.get(),
|
|
230
|
+
body,
|
|
231
|
+
},
|
|
232
|
+
encoded,
|
|
233
|
+
);
|
|
234
|
+
return password.disabled;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function headers_to_object(headers: Headers): Record<string, string> {
|
|
238
|
+
const output: Record<string, string> = {};
|
|
239
|
+
headers.forEach((value, key) => (output[key] = value));
|
|
240
|
+
return output;
|
|
241
|
+
}
|
package/src/HttpError.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Error.
|
|
3
|
+
*
|
|
4
|
+
* `HttpError` is a type of error class who've been thrown by the remote HTTP server.
|
|
5
|
+
*
|
|
6
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
7
|
+
*/
|
|
8
|
+
export class HttpError extends Error {
|
|
9
|
+
/**
|
|
10
|
+
* Initializer Constructor.
|
|
11
|
+
*
|
|
12
|
+
* @param method Method of the HTTP request.
|
|
13
|
+
* @param path Path of the HTTP request.
|
|
14
|
+
* @param status Status code from the remote HTTP server.
|
|
15
|
+
* @param message Error message from the remote HTTP server.
|
|
16
|
+
*/
|
|
17
|
+
public constructor(
|
|
18
|
+
public readonly method: "GET" | "DELETE" | "POST" | "PUT" | "PATCH",
|
|
19
|
+
public readonly path: string,
|
|
20
|
+
public readonly status: number,
|
|
21
|
+
message: string,
|
|
22
|
+
) {
|
|
23
|
+
super(message);
|
|
24
|
+
|
|
25
|
+
// INHERITANCE POLYFILL
|
|
26
|
+
const proto: HttpError = new.target.prototype;
|
|
27
|
+
if (Object.setPrototypeOf) Object.setPrototypeOf(this, proto);
|
|
28
|
+
else (this as any).__proto__ = proto;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { IEncryptionPassword } from "./IEncryptionPassword";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Connection information.
|
|
5
|
+
*
|
|
6
|
+
* `IConnection` is a type of interface who represents connection information of the remote
|
|
7
|
+
* HTTP server. You can target the remote HTTP server by wring the {@link IConnection.host}
|
|
8
|
+
* variable down. Also, you can configure special header values by specializing the
|
|
9
|
+
* {@link IConnection.headers} variable.
|
|
10
|
+
*
|
|
11
|
+
* If the remote HTTP server encrypts or decrypts its body data through the AES-128/256
|
|
12
|
+
* algorithm, specify the {@link IConnection.encryption} with {@link IEncryptionPassword}
|
|
13
|
+
* or {@link IEncryptionPassword.Closure} variable.
|
|
14
|
+
*
|
|
15
|
+
* @author Jenogho Nam - https://github.com/samchon
|
|
16
|
+
*/
|
|
17
|
+
export interface IConnection {
|
|
18
|
+
/**
|
|
19
|
+
* Host address of the remote HTTP server.
|
|
20
|
+
*/
|
|
21
|
+
host: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Header values delivered to the remote HTTP server.
|
|
25
|
+
*/
|
|
26
|
+
headers?: Record<string, string>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Encryption password of its closure function.
|
|
30
|
+
*/
|
|
31
|
+
encryption?: IEncryptionPassword | IEncryptionPassword.Closure;
|
|
32
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encryption password.
|
|
3
|
+
*
|
|
4
|
+
* `IEncryptionPassword` is a type of interface who represents encryption password used by
|
|
5
|
+
* the {@link Fetcher} with AES-128/256 algorithm. If your encryption password is not fixed
|
|
6
|
+
* but changes according to the input content, you can utilize the
|
|
7
|
+
* {@link IEncryptionPassword.Closure} function type.
|
|
8
|
+
*
|
|
9
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
10
|
+
*/
|
|
11
|
+
export interface IEncryptionPassword {
|
|
12
|
+
/**
|
|
13
|
+
* Secret key.
|
|
14
|
+
*/
|
|
15
|
+
key: string;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Initialization vector.
|
|
19
|
+
*/
|
|
20
|
+
iv: string;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Disable encryption to let content as plain.
|
|
24
|
+
*
|
|
25
|
+
* When you configure this `disabled` variable to be `false`, encryption and decryption
|
|
26
|
+
* algorithm would be disabled. Therefore, content like request or response body
|
|
27
|
+
* would be considered as a plain text instead.
|
|
28
|
+
*
|
|
29
|
+
* Default is `false`.
|
|
30
|
+
*/
|
|
31
|
+
disabled?:
|
|
32
|
+
| boolean
|
|
33
|
+
| ((
|
|
34
|
+
param: IEncryptionPassword.IParameter,
|
|
35
|
+
encoded: boolean,
|
|
36
|
+
) => boolean);
|
|
37
|
+
}
|
|
38
|
+
export namespace IEncryptionPassword {
|
|
39
|
+
/**
|
|
40
|
+
* Type of a closure function returning the {@link IEncryptionPassword} object.
|
|
41
|
+
*
|
|
42
|
+
* `IEncryptionPassword.Closure` is a type of closure function who are returning the
|
|
43
|
+
* {@link IEncryptionPassword} object. It would be used when your encryption password
|
|
44
|
+
* be changed according to the input content.
|
|
45
|
+
*/
|
|
46
|
+
export interface Closure {
|
|
47
|
+
/**
|
|
48
|
+
* Encryption password getter.
|
|
49
|
+
*
|
|
50
|
+
* @param param Request or response headers and body content
|
|
51
|
+
* @param encoded Be encoded or to be decoded
|
|
52
|
+
* @returns Encryption password
|
|
53
|
+
*/
|
|
54
|
+
(param: IParameter, encoded: boolean): IEncryptionPassword;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Parameter for the closure.
|
|
59
|
+
*/
|
|
60
|
+
export interface IParameter {
|
|
61
|
+
headers: Record<string, string>;
|
|
62
|
+
body: string;
|
|
63
|
+
}
|
|
64
|
+
}
|
package/src/Primitive.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Primitive type.
|
|
3
|
+
*
|
|
4
|
+
* `Primitive` is a type of TMP (Type Meta Programming) type who converts its argument as a
|
|
5
|
+
* primitive type.
|
|
6
|
+
*
|
|
7
|
+
* If the target argument is a built-in class who returns its origin primitive type through
|
|
8
|
+
* the `valueOf()` method like the `String` or `Number`, its return type would be the
|
|
9
|
+
* `string` or `number`.
|
|
10
|
+
*
|
|
11
|
+
* Otherwise, the target argument is a type of custom class, all of its custom method would
|
|
12
|
+
* be erased and its prototype would be changed to the primitive `object`. Therefore, return
|
|
13
|
+
* type of the TMP type finally be the primitive object.
|
|
14
|
+
*
|
|
15
|
+
* In addition, if the target argument is a type of custom class and it has a special
|
|
16
|
+
* method `toJSON()`, return type of this `Primitive` would be not `Primitive<Instance>`
|
|
17
|
+
* but `Primitive<ReturnType<Instance.toJSON>>`.
|
|
18
|
+
*
|
|
19
|
+
* Before | After
|
|
20
|
+
* ------------------------|----------------------------------------
|
|
21
|
+
* `Boolean` | `boolean`
|
|
22
|
+
* `Number` | `number`
|
|
23
|
+
* `String` | `string`
|
|
24
|
+
* `Class` | `object`
|
|
25
|
+
* `Class` with `toJSON()` | `Primitive<ReturnType<Class.toJSON>>`
|
|
26
|
+
* Others | No change
|
|
27
|
+
*
|
|
28
|
+
* @template Instance Target argument type.
|
|
29
|
+
* @author Jenogho Nam - https://github.com/samchon
|
|
30
|
+
*/
|
|
31
|
+
export type Primitive<Instance> = _Equal<
|
|
32
|
+
Instance,
|
|
33
|
+
_Primitive<Instance>
|
|
34
|
+
> extends true
|
|
35
|
+
? Instance
|
|
36
|
+
: _Primitive<Instance>;
|
|
37
|
+
|
|
38
|
+
type _Equal<X, Y> = X extends Y ? (Y extends X ? true : false) : false;
|
|
39
|
+
|
|
40
|
+
type _Primitive<Instance> = _ValueOf<Instance> extends object
|
|
41
|
+
? Instance extends object
|
|
42
|
+
? Instance extends IJsonable<infer Raw>
|
|
43
|
+
? _ValueOf<Raw> extends object
|
|
44
|
+
? Raw extends object
|
|
45
|
+
? _PrimitiveObject<Raw> // object would be primitified
|
|
46
|
+
: never // cannot be
|
|
47
|
+
: _ValueOf<Raw> // atomic value
|
|
48
|
+
: _PrimitiveObject<Instance> // object would be primitified
|
|
49
|
+
: never // cannot be
|
|
50
|
+
: _ValueOf<Instance>;
|
|
51
|
+
|
|
52
|
+
type _PrimitiveObject<Instance extends object> = Instance extends Array<infer T>
|
|
53
|
+
? _Primitive<T>[]
|
|
54
|
+
: {
|
|
55
|
+
[P in keyof Instance]: Instance[P] extends Function
|
|
56
|
+
? never
|
|
57
|
+
: _Primitive<Instance[P]>;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
type _ValueOf<Instance> = _IsValueOf<Instance, Boolean> extends true
|
|
61
|
+
? boolean
|
|
62
|
+
: _IsValueOf<Instance, Number> extends true
|
|
63
|
+
? number
|
|
64
|
+
: _IsValueOf<Instance, String> extends true
|
|
65
|
+
? string
|
|
66
|
+
: Instance;
|
|
67
|
+
|
|
68
|
+
type _IsValueOf<
|
|
69
|
+
Instance,
|
|
70
|
+
Object extends IValueOf<any>,
|
|
71
|
+
> = Instance extends Object
|
|
72
|
+
? Object extends IValueOf<infer Primitive>
|
|
73
|
+
? Instance extends Primitive
|
|
74
|
+
? false
|
|
75
|
+
: true // not Primitive, but Object
|
|
76
|
+
: false // cannot be
|
|
77
|
+
: false;
|
|
78
|
+
|
|
79
|
+
interface IValueOf<T> {
|
|
80
|
+
valueOf(): T;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface IJsonable<T> {
|
|
84
|
+
toJSON(): T;
|
|
85
|
+
}
|