@nestia/fetcher 12.0.0-rc.2 → 12.0.0-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/LICENSE +21 -21
  2. package/lib/AesPkcs5.mjs +21 -3
  3. package/lib/AesPkcs5.mjs.map +1 -1
  4. package/lib/EncryptedFetcher.mjs +52 -3
  5. package/lib/EncryptedFetcher.mjs.map +1 -1
  6. package/lib/FormDataInput.mjs +0 -3
  7. package/lib/HttpError.mjs +2 -2
  8. package/lib/IConnection.mjs +0 -3
  9. package/lib/IEncryptionPassword.mjs +0 -3
  10. package/lib/IFetchEvent.mjs +0 -3
  11. package/lib/IFetchRoute.mjs +0 -3
  12. package/lib/IPropagation.mjs +0 -3
  13. package/lib/NestiaSimulator.mjs +36 -3
  14. package/lib/NestiaSimulator.mjs.map +1 -1
  15. package/lib/PlainFetcher.mjs +27 -3
  16. package/lib/PlainFetcher.mjs.map +1 -1
  17. package/lib/index.mjs +4 -2
  18. package/lib/internal/FetcherBase.mjs +117 -3
  19. package/lib/internal/FetcherBase.mjs.map +1 -1
  20. package/lib/internal/is_binary_response_content_type.mjs +10 -3
  21. package/lib/internal/is_binary_response_content_type.mjs.map +1 -1
  22. package/package.json +5 -9
  23. package/src/AesPkcs5.ts +41 -41
  24. package/src/EncryptedFetcher.ts +176 -176
  25. package/src/FormDataInput.ts +80 -80
  26. package/src/HttpError.ts +1 -1
  27. package/src/IConnection.ts +241 -241
  28. package/src/IEncryptionPassword.ts +44 -44
  29. package/src/IFetchEvent.ts +31 -31
  30. package/src/IFetchRoute.ts +61 -61
  31. package/src/IPropagation.ts +99 -99
  32. package/src/NestiaSimulator.ts +82 -82
  33. package/src/PlainFetcher.ts +105 -105
  34. package/src/index.ts +10 -10
  35. package/src/internal/FetcherBase.ts +243 -243
  36. package/src/internal/is_binary_response_content_type.ts +14 -14
  37. package/README.md +0 -93
  38. package/lib/AesPkcs52.mjs +0 -53
  39. package/lib/AesPkcs52.mjs.map +0 -1
  40. package/lib/EncryptedFetcher2.mjs +0 -105
  41. package/lib/EncryptedFetcher2.mjs.map +0 -1
  42. package/lib/FormDataInput.mjs.map +0 -1
  43. package/lib/FormDataInput2.mjs +0 -6
  44. package/lib/FormDataInput2.mjs.map +0 -1
  45. package/lib/HttpError.mjs.map +0 -1
  46. package/lib/HttpError2.mjs +0 -16
  47. package/lib/HttpError2.mjs.map +0 -1
  48. package/lib/IConnection.mjs.map +0 -1
  49. package/lib/IConnection2.mjs +0 -6
  50. package/lib/IConnection2.mjs.map +0 -1
  51. package/lib/IEncryptionPassword.mjs.map +0 -1
  52. package/lib/IEncryptionPassword2.mjs +0 -6
  53. package/lib/IEncryptionPassword2.mjs.map +0 -1
  54. package/lib/IFetchEvent.mjs.map +0 -1
  55. package/lib/IFetchEvent2.mjs +0 -6
  56. package/lib/IFetchEvent2.mjs.map +0 -1
  57. package/lib/IFetchRoute.mjs.map +0 -1
  58. package/lib/IFetchRoute2.mjs +0 -6
  59. package/lib/IFetchRoute2.mjs.map +0 -1
  60. package/lib/IPropagation.mjs.map +0 -1
  61. package/lib/IPropagation2.mjs +0 -6
  62. package/lib/IPropagation2.mjs.map +0 -1
  63. package/lib/NestiaSimulator2.mjs +0 -49
  64. package/lib/NestiaSimulator2.mjs.map +0 -1
  65. package/lib/PlainFetcher2.mjs +0 -63
  66. package/lib/PlainFetcher2.mjs.map +0 -1
  67. package/lib/_virtual/AesPkcs5.mjs +0 -4
  68. package/lib/_virtual/AesPkcs5.mjs.map +0 -1
  69. package/lib/_virtual/EncryptedFetcher.mjs +0 -4
  70. package/lib/_virtual/EncryptedFetcher.mjs.map +0 -1
  71. package/lib/_virtual/FetcherBase.mjs +0 -4
  72. package/lib/_virtual/FetcherBase.mjs.map +0 -1
  73. package/lib/_virtual/FormDataInput.mjs +0 -4
  74. package/lib/_virtual/FormDataInput.mjs.map +0 -1
  75. package/lib/_virtual/HttpError.mjs +0 -4
  76. package/lib/_virtual/HttpError.mjs.map +0 -1
  77. package/lib/_virtual/IConnection.mjs +0 -4
  78. package/lib/_virtual/IConnection.mjs.map +0 -1
  79. package/lib/_virtual/IEncryptionPassword.mjs +0 -4
  80. package/lib/_virtual/IEncryptionPassword.mjs.map +0 -1
  81. package/lib/_virtual/IFetchEvent.mjs +0 -4
  82. package/lib/_virtual/IFetchEvent.mjs.map +0 -1
  83. package/lib/_virtual/IFetchRoute.mjs +0 -4
  84. package/lib/_virtual/IFetchRoute.mjs.map +0 -1
  85. package/lib/_virtual/IPropagation.mjs +0 -4
  86. package/lib/_virtual/IPropagation.mjs.map +0 -1
  87. package/lib/_virtual/NestiaSimulator.mjs +0 -4
  88. package/lib/_virtual/NestiaSimulator.mjs.map +0 -1
  89. package/lib/_virtual/PlainFetcher.mjs +0 -4
  90. package/lib/_virtual/PlainFetcher.mjs.map +0 -1
  91. package/lib/_virtual/_commonjsHelpers.mjs +0 -35
  92. package/lib/_virtual/_commonjsHelpers.mjs.map +0 -1
  93. package/lib/_virtual/_node_crypto.mjs +0 -7
  94. package/lib/_virtual/_node_crypto.mjs.map +0 -1
  95. package/lib/_virtual/index.mjs +0 -4
  96. package/lib/_virtual/index.mjs.map +0 -1
  97. package/lib/_virtual/is_binary_response_content_type.mjs +0 -4
  98. package/lib/_virtual/is_binary_response_content_type.mjs.map +0 -1
  99. package/lib/_virtual/utils.mjs +0 -7
  100. package/lib/_virtual/utils.mjs.map +0 -1
  101. package/lib/index.mjs.map +0 -1
  102. package/lib/index2.mjs +0 -53
  103. package/lib/index2.mjs.map +0 -1
  104. package/lib/internal/FetcherBase2.mjs +0 -203
  105. package/lib/internal/FetcherBase2.mjs.map +0 -1
  106. package/lib/internal/is_binary_response_content_type2.mjs +0 -18
  107. package/lib/internal/is_binary_response_content_type2.mjs.map +0 -1
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2021 Jeongho Nam
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Jeongho Nam
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/lib/AesPkcs5.mjs CHANGED
@@ -1,3 +1,21 @@
1
- export { AesPkcs5 } from './AesPkcs52.mjs';
2
- export { __exports as default } from './_virtual/AesPkcs5.mjs';
3
- //# sourceMappingURL=AesPkcs5.mjs.map
1
+ import crypto from "crypto";
2
+ //#region src/AesPkcs5.ts
3
+ let AesPkcs5;
4
+ (function(_AesPkcs) {
5
+ function encrypt(data, key, iv) {
6
+ const bytes = key.length * 8;
7
+ const cipher = crypto.createCipheriv(`AES-${bytes}-CBC`, key, iv);
8
+ return cipher.update(data, "utf8", "base64") + cipher.final("base64");
9
+ }
10
+ _AesPkcs.encrypt = encrypt;
11
+ function decrypt(data, key, iv) {
12
+ const bytes = key.length * 8;
13
+ const decipher = crypto.createDecipheriv(`AES-${bytes}-CBC`, key, iv);
14
+ return decipher.update(data, "base64", "utf8") + decipher.final("utf8");
15
+ }
16
+ _AesPkcs.decrypt = decrypt;
17
+ })(AesPkcs5 || (AesPkcs5 = {}));
18
+ //#endregion
19
+ export { AesPkcs5 };
20
+
21
+ //# sourceMappingURL=AesPkcs5.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"AesPkcs5.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"AesPkcs5.mjs","names":[],"sources":["../src/AesPkcs5.ts"],"sourcesContent":["import crypto from \"crypto\";\n\n/**\n * Utility class for the AES-128/256 encryption.\n *\n * - AES-128/256\n * - CBC mode\n * - PKCS#5 Padding\n * - Base64 Encoding\n *\n * @author Jeongho Nam - https://github.com/samchon\n */\nexport namespace AesPkcs5 {\n /**\n * Encrypt data\n *\n * @param data Target data\n * @param key Key value of the encryption.\n * @param iv Initializer Vector for the encryption\n * @returns Encrypted data\n */\n export function encrypt(data: string, key: string, iv: string): string {\n const bytes: number = key.length * 8;\n const cipher = crypto.createCipheriv(`AES-${bytes}-CBC`, key, iv);\n return cipher.update(data, \"utf8\", \"base64\") + cipher.final(\"base64\");\n }\n\n /**\n * Decrypt data.\n *\n * @param data Target data\n * @param key Key value of the decryption.\n * @param iv Initializer Vector for the decryption\n * @returns Decrypted data.\n */\n export function decrypt(data: string, key: string, iv: string): string {\n const bytes: number = key.length * 8;\n const decipher = crypto.createDecipheriv(`AES-${bytes}-CBC`, key, iv);\n return decipher.update(data, \"base64\", \"utf8\") + decipher.final(\"utf8\");\n }\n}\n"],"mappings":";;AAYO,IAAA;;CASE,SAAS,QAAQ,MAAc,KAAa,IAAoB;EACrE,MAAM,QAAgB,IAAI,SAAS;EACnC,MAAM,SAAS,OAAO,eAAe,OAAO,MAAM,OAAO,KAAK,EAAE;EAChE,OAAO,OAAO,OAAO,MAAM,QAAQ,QAAQ,IAAI,OAAO,MAAM,QAAQ;CACtE;;CAUO,SAAS,QAAQ,MAAc,KAAa,IAAoB;EACrE,MAAM,QAAgB,IAAI,SAAS;EACnC,MAAM,WAAW,OAAO,iBAAiB,OAAO,MAAM,OAAO,KAAK,EAAE;EACpE,OAAO,SAAS,OAAO,MAAM,UAAU,MAAM,IAAI,SAAS,MAAM,MAAM;CACxE;;GACD,aAAA,WAAA,CAAA,EAAD"}
@@ -1,3 +1,52 @@
1
- export { EncryptedFetcher } from './EncryptedFetcher2.mjs';
2
- export { __exports as default } from './_virtual/EncryptedFetcher.mjs';
3
- //# sourceMappingURL=EncryptedFetcher.mjs.map
1
+ import { AesPkcs5 } from "./AesPkcs5.mjs";
2
+ import { FetcherBase } from "./internal/FetcherBase.mjs";
3
+ //#region src/EncryptedFetcher.ts
4
+ let EncryptedFetcher;
5
+ (function(_EncryptedFetcher) {
6
+ async function fetch(connection, route, input, stringify) {
7
+ if ((route.request?.encrypted === true || route.response?.encrypted) && connection.encryption === void 0) throw new Error("Error on EncryptedFetcher.fetch(): the encryption password has not been configured.");
8
+ const closure = typeof connection.encryption === "function" ? (direction) => (headers, body) => connection.encryption({
9
+ headers,
10
+ body,
11
+ direction
12
+ }) : () => () => connection.encryption;
13
+ return FetcherBase.request({
14
+ className: "EncryptedFetcher",
15
+ encode: route.request?.encrypted === true ? (input, headers) => {
16
+ const p = closure("encode")(headers, input);
17
+ return AesPkcs5.encrypt((stringify ?? JSON.stringify)(input), p.key, p.iv);
18
+ } : (input) => input,
19
+ decode: route.response?.encrypted === true ? (input, headers) => {
20
+ const p = closure("decode")(headers, input);
21
+ const s = AesPkcs5.decrypt(input, p.key, p.iv);
22
+ return s.length ? JSON.parse(s) : s;
23
+ } : (input) => input
24
+ })(connection, route, input, stringify);
25
+ }
26
+ _EncryptedFetcher.fetch = fetch;
27
+ async function propagate(connection, route, input, stringify) {
28
+ if ((route.request?.encrypted === true || route.response?.encrypted) && connection.encryption === void 0) throw new Error("Error on EncryptedFetcher.propagate(): the encryption password has not been configured.");
29
+ const closure = typeof connection.encryption === "function" ? (direction) => (headers, body) => connection.encryption({
30
+ headers,
31
+ body,
32
+ direction
33
+ }) : () => () => connection.encryption;
34
+ return FetcherBase.propagate({
35
+ className: "EncryptedFetcher",
36
+ encode: route.request?.encrypted === true ? (input, headers) => {
37
+ const p = closure("encode")(headers, input);
38
+ return AesPkcs5.encrypt((stringify ?? JSON.stringify)(input), p.key, p.iv);
39
+ } : (input) => input,
40
+ decode: route.response?.encrypted === true ? (input, headers) => {
41
+ const p = closure("decode")(headers, input);
42
+ const s = AesPkcs5.decrypt(input, p.key, p.iv);
43
+ return s.length ? JSON.parse(s) : s;
44
+ } : (input) => input
45
+ })(connection, route, input, stringify);
46
+ }
47
+ _EncryptedFetcher.propagate = propagate;
48
+ })(EncryptedFetcher || (EncryptedFetcher = {}));
49
+ //#endregion
50
+ export { EncryptedFetcher };
51
+
52
+ //# sourceMappingURL=EncryptedFetcher.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"EncryptedFetcher.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"EncryptedFetcher.mjs","names":[],"sources":["../src/EncryptedFetcher.ts"],"sourcesContent":["import { AesPkcs5 } from \"./AesPkcs5\";\nimport { IConnection } from \"./IConnection\";\nimport { IEncryptionPassword } from \"./IEncryptionPassword\";\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` with encryption.\n *\n * `EncryptedFetcher` 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 API encrypted by AES-PKCS algorithm. In other words, this is a\n * collection of dedicated `fetch()` functions for `@nestia/sdk` with\n * encryption.\n *\n * For reference, `EncryptedFetcher` class being used only when target\n * controller method is encrypting body data by `@EncryptedRoute` or\n * `@EncryptedBody` decorators. If those decorators are not used,\n * {@link PlainFetcher} class would be used instead.\n *\n * @author Jeongho Nam - https://github.com/samchon\n */\nexport namespace EncryptedFetcher {\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 */\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 (\n (route.request?.encrypted === true || route.response?.encrypted) &&\n connection.encryption === undefined\n )\n throw new Error(\n \"Error on EncryptedFetcher.fetch(): the encryption password has not been configured.\",\n );\n const closure =\n typeof connection.encryption === \"function\"\n ? (direction: \"encode\" | \"decode\") =>\n (\n headers: Record<string, IConnection.HeaderValue | undefined>,\n body: string,\n ) =>\n (connection.encryption as IEncryptionPassword.Closure)({\n headers,\n body,\n direction,\n })\n : () => () => connection.encryption as IEncryptionPassword;\n\n return FetcherBase.request({\n className: \"EncryptedFetcher\",\n encode:\n route.request?.encrypted === true\n ? (input, headers) => {\n const p: IEncryptionPassword = closure(\"encode\")(headers, input);\n return AesPkcs5.encrypt(\n (stringify ?? JSON.stringify)(input),\n p.key,\n p.iv,\n );\n }\n : (input) => input,\n decode:\n route.response?.encrypted === true\n ? (input, headers) => {\n const p: IEncryptionPassword = closure(\"decode\")(headers, input);\n const s: string = AesPkcs5.decrypt(input, p.key, p.iv);\n return s.length ? JSON.parse(s) : s;\n }\n : (input) => input,\n })(connection, route, input, stringify);\n }\n\n export function propagate<Output extends IPropagation<any, any>>(\n connection: IConnection,\n route: IFetchRoute<\"GET\" | \"HEAD\">,\n ): Promise<Output>;\n\n export function propagate<Input, Output extends IPropagation<any, any>>(\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<Input, Output extends IPropagation<any, any>>(\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 (\n (route.request?.encrypted === true || route.response?.encrypted) &&\n connection.encryption === undefined\n )\n throw new Error(\n \"Error on EncryptedFetcher.propagate(): the encryption password has not been configured.\",\n );\n const closure =\n typeof connection.encryption === \"function\"\n ? (direction: \"encode\" | \"decode\") =>\n (\n headers: Record<string, IConnection.HeaderValue | undefined>,\n body: string,\n ) =>\n (connection.encryption as IEncryptionPassword.Closure)({\n headers,\n body,\n direction,\n })\n : () => () => connection.encryption as IEncryptionPassword;\n\n return FetcherBase.propagate({\n className: \"EncryptedFetcher\",\n encode:\n route.request?.encrypted === true\n ? (input, headers) => {\n const p: IEncryptionPassword = closure(\"encode\")(headers, input);\n return AesPkcs5.encrypt(\n (stringify ?? JSON.stringify)(input),\n p.key,\n p.iv,\n );\n }\n : (input) => input,\n decode:\n route.response?.encrypted === true\n ? (input, headers) => {\n const p: IEncryptionPassword = closure(\"decode\")(headers, input);\n const s: string = AesPkcs5.decrypt(input, p.key, p.iv);\n return s.length ? JSON.parse(s) : s;\n }\n : (input) => input,\n })(connection, route, input, stringify) as Promise<Output>;\n }\n}\n"],"mappings":";;;AAuBO,IAAA;;CAuCE,eAAe,MACpB,YACA,OACA,OACA,WACiB;EACjB,KACG,MAAM,SAAS,cAAc,QAAQ,MAAM,UAAU,cACtD,WAAW,eAAe,KAAA,GAE1B,MAAM,IAAI,MACR,qFACF;EACF,MAAM,UACJ,OAAO,WAAW,eAAe,cAC5B,eAEG,SACA,SAEC,WAAW,WAA2C;GACrD;GACA;GACA;EACF,CAAC,gBACO,WAAW;EAE7B,OAAO,YAAY,QAAQ;GACzB,WAAW;GACX,QACE,MAAM,SAAS,cAAc,QACxB,OAAO,YAAY;IAClB,MAAM,IAAyB,QAAQ,QAAQ,CAAC,CAAC,SAAS,KAAK;IAC/D,OAAO,SAAS,SACb,aAAa,KAAK,UAAA,CAAW,KAAK,GACnC,EAAE,KACF,EAAE,EACJ;GACF,KACC,UAAU;GACjB,QACE,MAAM,UAAU,cAAc,QACzB,OAAO,YAAY;IAClB,MAAM,IAAyB,QAAQ,QAAQ,CAAC,CAAC,SAAS,KAAK;IAC/D,MAAM,IAAY,SAAS,QAAQ,OAAO,EAAE,KAAK,EAAE,EAAE;IACrD,OAAO,EAAE,SAAS,KAAK,MAAM,CAAC,IAAI;GACpC,KACC,UAAU;EACnB,CAAC,CAAC,CAAC,YAAY,OAAO,OAAO,SAAS;CACxC;;CAcO,eAAe,UACpB,YACA,OACA,OACA,WACiB;EACjB,KACG,MAAM,SAAS,cAAc,QAAQ,MAAM,UAAU,cACtD,WAAW,eAAe,KAAA,GAE1B,MAAM,IAAI,MACR,yFACF;EACF,MAAM,UACJ,OAAO,WAAW,eAAe,cAC5B,eAEG,SACA,SAEC,WAAW,WAA2C;GACrD;GACA;GACA;EACF,CAAC,gBACO,WAAW;EAE7B,OAAO,YAAY,UAAU;GAC3B,WAAW;GACX,QACE,MAAM,SAAS,cAAc,QACxB,OAAO,YAAY;IAClB,MAAM,IAAyB,QAAQ,QAAQ,CAAC,CAAC,SAAS,KAAK;IAC/D,OAAO,SAAS,SACb,aAAa,KAAK,UAAA,CAAW,KAAK,GACnC,EAAE,KACF,EAAE,EACJ;GACF,KACC,UAAU;GACjB,QACE,MAAM,UAAU,cAAc,QACzB,OAAO,YAAY;IAClB,MAAM,IAAyB,QAAQ,QAAQ,CAAC,CAAC,SAAS,KAAK;IAC/D,MAAM,IAAY,SAAS,QAAQ,OAAO,EAAE,KAAK,EAAE,EAAE;IACrD,OAAO,EAAE,SAAS,KAAK,MAAM,CAAC,IAAI;GACpC,KACC,UAAU;EACnB,CAAC,CAAC,CAAC,YAAY,OAAO,OAAO,SAAS;CACxC;;GACD,qBAAA,mBAAA,CAAA,EAAD"}
@@ -1,3 +0,0 @@
1
- import './FormDataInput2.mjs';
2
- export { __exports as default } from './_virtual/FormDataInput.mjs';
3
- //# sourceMappingURL=FormDataInput.mjs.map
package/lib/HttpError.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export { default } from './HttpError2.mjs';
2
- //# sourceMappingURL=HttpError.mjs.map
1
+ import { HttpError } from "@typia/utils";
2
+ export { HttpError };
@@ -1,3 +0,0 @@
1
- import './IConnection2.mjs';
2
- export { __exports as default } from './_virtual/IConnection.mjs';
3
- //# sourceMappingURL=IConnection.mjs.map
@@ -1,3 +0,0 @@
1
- import './IEncryptionPassword2.mjs';
2
- export { __exports as default } from './_virtual/IEncryptionPassword.mjs';
3
- //# sourceMappingURL=IEncryptionPassword.mjs.map
@@ -1,3 +0,0 @@
1
- import './IFetchEvent2.mjs';
2
- export { __exports as default } from './_virtual/IFetchEvent.mjs';
3
- //# sourceMappingURL=IFetchEvent.mjs.map
@@ -1,3 +0,0 @@
1
- import './IFetchRoute2.mjs';
2
- export { __exports as default } from './_virtual/IFetchRoute.mjs';
3
- //# sourceMappingURL=IFetchRoute.mjs.map
@@ -1,3 +0,0 @@
1
- import './IPropagation2.mjs';
2
- export { __exports as default } from './_virtual/IPropagation.mjs';
3
- //# sourceMappingURL=IPropagation.mjs.map
@@ -1,3 +1,36 @@
1
- export { NestiaSimulator } from './NestiaSimulator2.mjs';
2
- export { __exports as default } from './_virtual/NestiaSimulator.mjs';
3
- //# sourceMappingURL=NestiaSimulator.mjs.map
1
+ import { HttpError } from "./HttpError.mjs";
2
+ //#region src/NestiaSimulator.ts
3
+ let NestiaSimulator;
4
+ (function(_NestiaSimulator) {
5
+ _NestiaSimulator.assert = (props) => {
6
+ return {
7
+ param: param(props),
8
+ query: query(props),
9
+ body: body(props)
10
+ };
11
+ };
12
+ const param = (props) => (name) => (task) => {
13
+ validate((exp) => `URL parameter "${name}" is not ${exp.expected} type.`)(props)(task);
14
+ };
15
+ const query = (props) => (task) => validate(() => "Request query parameters are not following the promised type.")(props)(task);
16
+ const body = (props) => (task) => validate(() => "Request body is not following the promised type.")(props)(task);
17
+ const validate = (message, path) => (props) => (task) => {
18
+ try {
19
+ task();
20
+ } catch (exp) {
21
+ if (isTypeGuardError(exp)) throw new HttpError(props.method, props.host + props.path, 400, { "Content-Type": props.contentType }, JSON.stringify({
22
+ method: exp.method,
23
+ path: path ?? exp.path,
24
+ expected: exp.expected,
25
+ value: exp.value,
26
+ message: message(exp)
27
+ }));
28
+ throw exp;
29
+ }
30
+ };
31
+ })(NestiaSimulator || (NestiaSimulator = {}));
32
+ const isTypeGuardError = (input) => "string" === typeof input.method && (void 0 === input.path || "string" === typeof input.path) && "string" === typeof input.expected && "string" === typeof input.name && "string" === typeof input.message && (void 0 === input.stack || "string" === typeof input.stack);
33
+ //#endregion
34
+ export { NestiaSimulator };
35
+
36
+ //# sourceMappingURL=NestiaSimulator.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"NestiaSimulator.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"NestiaSimulator.mjs","names":[],"sources":["../src/NestiaSimulator.ts"],"sourcesContent":["import { HttpError } from \"./HttpError\";\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, path?: string) =>\n (props: IProps) =>\n <T>(task: () => T): void => {\n try {\n task();\n } catch (exp) {\n if (isTypeGuardError(exp))\n throw new HttpError(\n props.method,\n props.host + props.path,\n 400,\n {\n \"Content-Type\": props.contentType,\n },\n JSON.stringify({\n method: exp.method,\n path: path ?? exp.path,\n expected: exp.expected,\n value: exp.value,\n message: message(exp),\n }),\n );\n throw exp;\n }\n };\n}\n\nconst isTypeGuardError = (input: any): input is TypeGuardError =>\n \"string\" === typeof input.method &&\n (undefined === input.path || \"string\" === typeof input.path) &&\n \"string\" === typeof input.expected &&\n \"string\" === typeof input.name &&\n \"string\" === typeof input.message &&\n (undefined === input.stack || \"string\" === typeof input.stack);\n\ninterface TypeGuardError extends Error {\n method: string;\n path: string | undefined;\n expected: string;\n value: any;\n}\n"],"mappings":";;AAEO,IAAA;;4BAQkB,UAAkB;EACvC,OAAO;GACL,OAAO,MAAM,KAAK;GAClB,OAAO,MAAM,KAAK;GAClB,MAAM,KAAK,KAAK;EAClB;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,YACH,SAA0C,UAC1C,WACG,SAAwB;EAC1B,IAAI;GACF,KAAK;EACP,SAAS,KAAK;GACZ,IAAI,iBAAiB,GAAG,GACtB,MAAM,IAAI,UACR,MAAM,QACN,MAAM,OAAO,MAAM,MACnB,KACA,EACE,gBAAgB,MAAM,YACxB,GACA,KAAK,UAAU;IACb,QAAQ,IAAI;IACZ,MAAM,QAAQ,IAAI;IAClB,UAAU,IAAI;IACd,OAAO,IAAI;IACX,SAAS,QAAQ,GAAG;GACtB,CAAC,CACH;GACF,MAAM;EACR;CACF;GACH,oBAAA,kBAAA,CAAA,EAAD;AAEA,MAAM,oBAAoB,UACxB,aAAa,OAAO,MAAM,WACzB,KAAA,MAAc,MAAM,QAAQ,aAAa,OAAO,MAAM,SACvD,aAAa,OAAO,MAAM,YAC1B,aAAa,OAAO,MAAM,QAC1B,aAAa,OAAO,MAAM,YACzB,KAAA,MAAc,MAAM,SAAS,aAAa,OAAO,MAAM"}
@@ -1,3 +1,27 @@
1
- export { PlainFetcher } from './PlainFetcher2.mjs';
2
- export { __exports as default } from './_virtual/PlainFetcher.mjs';
3
- //# sourceMappingURL=PlainFetcher.mjs.map
1
+ import { FetcherBase } from "./internal/FetcherBase.mjs";
2
+ //#region src/PlainFetcher.ts
3
+ let PlainFetcher;
4
+ (function(_PlainFetcher) {
5
+ async function fetch(connection, route, input, stringify) {
6
+ if (route.request?.encrypted === true || route.response?.encrypted === true) throw new Error("Error on PlainFetcher.fetch(): PlainFetcher doesn't have encryption ability. Use EncryptedFetcher instead.");
7
+ return FetcherBase.request({
8
+ className: "PlainFetcher",
9
+ encode: (input) => input,
10
+ decode: (input) => input
11
+ })(connection, route, input, stringify);
12
+ }
13
+ _PlainFetcher.fetch = fetch;
14
+ async function propagate(connection, route, input, stringify) {
15
+ 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.");
16
+ return FetcherBase.propagate({
17
+ className: "PlainFetcher",
18
+ encode: (input) => input,
19
+ decode: (input) => input
20
+ })(connection, route, input, stringify);
21
+ }
22
+ _PlainFetcher.propagate = propagate;
23
+ })(PlainFetcher || (PlainFetcher = {}));
24
+ //#endregion
25
+ export { PlainFetcher };
26
+
27
+ //# sourceMappingURL=PlainFetcher.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"PlainFetcher.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
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 sever 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 {@liink EncryptedFetcher} class would be used instead.\n *\n * @author Jeongho Nam - https://github.com/samchon\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 */\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 export function propagate<Output extends IPropagation<any, any>>(\n connection: IConnection,\n route: IFetchRoute<\"GET\" | \"HEAD\">,\n ): Promise<Output>;\n\n export function propagate<Input, Output extends IPropagation<any, any>>(\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<Input, Output extends IPropagation<any, any>>(\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":";;AAoBO,IAAA;;CAuCE,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;;CAcO,eAAe,UACpB,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.mjs CHANGED
@@ -1,2 +1,4 @@
1
- export { default } from './index2.mjs';
2
- //# sourceMappingURL=index.mjs.map
1
+ import { HttpError } from "./HttpError.mjs";
2
+ import { NestiaSimulator } from "./NestiaSimulator.mjs";
3
+ import { PlainFetcher } from "./PlainFetcher.mjs";
4
+ export { HttpError, NestiaSimulator, PlainFetcher };
@@ -1,3 +1,117 @@
1
- export { FetcherBase } from './FetcherBase2.mjs';
2
- export { __exports as default } from '../_virtual/FetcherBase.mjs';
3
- //# sourceMappingURL=FetcherBase.mjs.map
1
+ import { HttpError } from "../HttpError.mjs";
2
+ import { is_binary_response_content_type } from "./is_binary_response_content_type.mjs";
3
+ //#region src/internal/FetcherBase.ts
4
+ let FetcherBase;
5
+ (function(_FetcherBase) {
6
+ _FetcherBase.request = (props) => async (connection, route, input, stringify) => {
7
+ const result = await _Propagate("fetch")(props)(connection, route, input, stringify);
8
+ if (result.success === false) throw new HttpError(route.method, route.path, result.status, result.headers, result.data);
9
+ return result.data;
10
+ };
11
+ _FetcherBase.propagate = (props) => async (connection, route, input, stringify) => _Propagate("propagate")(props)(connection, route, input, stringify);
12
+ /** @internal */
13
+ const _Propagate = (method) => (props) => async (connection, route, input, stringify) => {
14
+ const headers = { ...connection.headers ?? {} };
15
+ if (input !== void 0) {
16
+ if (route.request?.type === void 0) throw new Error(`Error on ${props.className}.fetch(): no content-type being configured.`);
17
+ else if (route.request.type !== "multipart/form-data") headers["Content-Type"] = route.request.type;
18
+ } else if (input === void 0 && headers["Content-Type"] !== void 0) delete headers["Content-Type"];
19
+ const init = {
20
+ ...connection.options ?? {},
21
+ method: route.method,
22
+ headers: (() => {
23
+ const output = [];
24
+ for (const [key, value] of Object.entries(headers)) if (value === void 0) continue;
25
+ else if (Array.isArray(value)) for (const v of value) output.push([key, String(v)]);
26
+ else output.push([key, String(value)]);
27
+ return output;
28
+ })()
29
+ };
30
+ if (input !== void 0) init.body = props.encode(route.request?.type === "application/x-www-form-urlencoded" ? request_query_body(input) : route.request?.type === "multipart/form-data" ? request_form_data_body(input) : route.request?.type !== "text/plain" ? (stringify ?? JSON.stringify)(input) : input, headers);
31
+ const path = connection.host[connection.host.length - 1] !== "/" && route.path[0] !== "/" ? `/${route.path}` : route.path;
32
+ const url = new URL(`${connection.host}${path}`);
33
+ const event = {
34
+ route,
35
+ path,
36
+ status: null,
37
+ input,
38
+ output: void 0,
39
+ started_at: /* @__PURE__ */ new Date(),
40
+ respond_at: null,
41
+ completed_at: null
42
+ };
43
+ try {
44
+ const response = await (connection.fetch ?? fetch)(url.href, init);
45
+ event.respond_at = /* @__PURE__ */ new Date();
46
+ event.status = response.status;
47
+ const result = {
48
+ success: response.status === 200 || response.status === 201 || response.status === route.status,
49
+ status: response.status,
50
+ headers: response_headers_to_object(response.headers),
51
+ data: void 0
52
+ };
53
+ if (result.success === false) {
54
+ result.data = await response.text();
55
+ const type = response.headers.get("content-type");
56
+ if (method !== "fetch" && type && type.indexOf("application/json") !== -1) try {
57
+ result.data = JSON.parse(result.data);
58
+ } catch {}
59
+ } else if (route.method === "HEAD") result.data = void 0;
60
+ else if (route.response?.type === "application/json") {
61
+ const text = await response.text();
62
+ result.data = text.length ? JSON.parse(text) : void 0;
63
+ } else if (route.response?.type === "application/x-www-form-urlencoded") {
64
+ const query = new URLSearchParams(await response.text());
65
+ result.data = route.parseQuery ? route.parseQuery(query) : query;
66
+ } else if (is_binary_response_content_type(route.response?.type)) result.data = response.body ?? new ReadableStream();
67
+ else result.data = props.decode(await response.text(), result.headers);
68
+ event.output = result.data;
69
+ return result;
70
+ } catch (exp) {
71
+ throw exp;
72
+ } finally {
73
+ event.completed_at = /* @__PURE__ */ new Date();
74
+ if (connection.logger) try {
75
+ await connection.logger(event);
76
+ } catch {}
77
+ }
78
+ };
79
+ })(FetcherBase || (FetcherBase = {}));
80
+ /** @internal */
81
+ const request_query_body = (input) => {
82
+ const q = new URLSearchParams();
83
+ for (const [key, value] of Object.entries(input)) if (value === void 0) continue;
84
+ else if (Array.isArray(value)) value.forEach((elem) => q.append(key, String(elem)));
85
+ else q.set(key, String(value));
86
+ return q;
87
+ };
88
+ /** @internal */
89
+ const request_form_data_body = (input) => {
90
+ const encoded = new FormData();
91
+ const append = (key) => (value) => {
92
+ if (value === void 0) return;
93
+ else if (typeof File === "function" && value instanceof File) encoded.append(key, value, value.name);
94
+ else encoded.append(key, value);
95
+ };
96
+ for (const [key, value] of Object.entries(input)) if (Array.isArray(value)) value.map(append(key));
97
+ else append(key)(value);
98
+ return encoded;
99
+ };
100
+ /** @internal */
101
+ const response_headers_to_object = (headers) => {
102
+ const output = {};
103
+ const cookieHeaders = typeof headers.getSetCookie === "function" ? headers.getSetCookie() : void 0;
104
+ if (cookieHeaders?.length) output["set-cookie"] = cookieHeaders;
105
+ headers.forEach((value, key) => {
106
+ if (key.toLowerCase() === "set-cookie") {
107
+ if (cookieHeaders?.length) return;
108
+ output[key] ??= [];
109
+ output[key].push(value);
110
+ } else output[key] = value;
111
+ });
112
+ return output;
113
+ };
114
+ //#endregion
115
+ export { FetcherBase };
116
+
117
+ //# sourceMappingURL=FetcherBase.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"FetcherBase.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
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\";\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 headers[\"Content-Type\"] = route.request.type;\n } else if (input === undefined && headers[\"Content-Type\"] !== undefined)\n delete 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 =\n connection.host[connection.host.length - 1] !== \"/\" &&\n route.path[0] !== \"/\"\n ? `/${route.path}`\n : route.path;\n const url: URL = new URL(`${connection.host}${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"],"mappings":"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"}
@@ -1,3 +1,10 @@
1
- export { is_binary_response_content_type } from './is_binary_response_content_type2.mjs';
2
- export { __exports as default } from '../_virtual/is_binary_response_content_type.mjs';
3
- //# sourceMappingURL=is_binary_response_content_type.mjs.map
1
+ //#region src/internal/is_binary_response_content_type.ts
2
+ const is_binary_response_content_type = (input) => {
3
+ if (typeof input !== "string") return false;
4
+ const value = input.split(";")[0].trim().toLowerCase();
5
+ return value.startsWith("image/") || value.startsWith("video/") || value.startsWith("audio/") || value === "application/octet-stream" || value === "application/pdf";
6
+ };
7
+ //#endregion
8
+ export { is_binary_response_content_type };
9
+
10
+ //# sourceMappingURL=is_binary_response_content_type.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"is_binary_response_content_type.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"is_binary_response_content_type.mjs","names":[],"sources":["../../src/internal/is_binary_response_content_type.ts"],"sourcesContent":["export const is_binary_response_content_type = (\n input: string | null | undefined,\n): input is string => {\n if (typeof input !== \"string\") return false;\n\n const value: string = input.split(\";\")[0]!.trim().toLowerCase();\n return (\n value.startsWith(\"image/\") ||\n value.startsWith(\"video/\") ||\n value.startsWith(\"audio/\") ||\n value === \"application/octet-stream\" ||\n value === \"application/pdf\"\n );\n};\n"],"mappings":";AAAA,MAAa,mCACX,UACoB;CACpB,IAAI,OAAO,UAAU,UAAU,OAAO;CAEtC,MAAM,QAAgB,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,CAAE,KAAK,CAAC,CAAC,YAAY;CAC9D,OACE,MAAM,WAAW,QAAQ,KACzB,MAAM,WAAW,QAAQ,KACzB,MAAM,WAAW,QAAQ,KACzB,UAAU,8BACV,UAAU;AAEd"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestia/fetcher",
3
- "version": "12.0.0-rc.2",
3
+ "version": "12.0.0-rc.4",
4
4
  "description": "Fetcher library of Nestia SDK",
5
5
  "types": "lib/index.d.ts",
6
6
  "main": "lib/index.js",
@@ -38,17 +38,13 @@
38
38
  },
39
39
  "homepage": "https://nestia.io",
40
40
  "dependencies": {
41
- "@typia/interface": "^13.0.0-rc.1",
42
- "@typia/utils": "^13.0.0-rc.1"
41
+ "@typia/interface": "^13.0.1",
42
+ "@typia/utils": "^13.0.1"
43
43
  },
44
44
  "devDependencies": {
45
- "@rollup/plugin-commonjs": "^29.0.0",
46
- "@rollup/plugin-esm-shim": "^0.1.8",
47
- "@rollup/plugin-node-resolve": "^16.0.3",
48
45
  "@types/node": "^25.3.3",
49
46
  "rimraf": "^6.1.3",
50
- "rollup": "^4.56.0",
51
- "rollup-plugin-node-externals": "^8.1.2"
47
+ "rolldown": "^1.1.5"
52
48
  },
53
49
  "files": [
54
50
  "README.md",
@@ -61,7 +57,7 @@
61
57
  "access": "public"
62
58
  },
63
59
  "scripts": {
64
- "build": "rimraf lib && ttsc && rollup -c rollup.config.mjs && node ../../deploy/verify-package-exports.cjs --require-main",
60
+ "build": "rimraf lib && ttsc && rolldown -c && node ../../deploy/verify-package-exports.cjs --require-main --esm",
65
61
  "dev": "rimraf lib && ttsc --watch"
66
62
  }
67
63
  }
package/src/AesPkcs5.ts CHANGED
@@ -1,41 +1,41 @@
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
- * @returns 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.createCipheriv(`AES-${bytes}-CBC`, key, iv);
25
- return cipher.update(data, "utf8", "base64") + cipher.final("base64");
26
- }
27
-
28
- /**
29
- * Decrypt data.
30
- *
31
- * @param data Target data
32
- * @param key Key value of the decryption.
33
- * @param iv Initializer Vector for the decryption
34
- * @returns Decrypted data.
35
- */
36
- export function decrypt(data: string, key: string, iv: string): string {
37
- const bytes: number = key.length * 8;
38
- const decipher = crypto.createDecipheriv(`AES-${bytes}-CBC`, key, iv);
39
- return decipher.update(data, "base64", "utf8") + decipher.final("utf8");
40
- }
41
- }
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
+ * @returns 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.createCipheriv(`AES-${bytes}-CBC`, key, iv);
25
+ return cipher.update(data, "utf8", "base64") + cipher.final("base64");
26
+ }
27
+
28
+ /**
29
+ * Decrypt data.
30
+ *
31
+ * @param data Target data
32
+ * @param key Key value of the decryption.
33
+ * @param iv Initializer Vector for the decryption
34
+ * @returns Decrypted data.
35
+ */
36
+ export function decrypt(data: string, key: string, iv: string): string {
37
+ const bytes: number = key.length * 8;
38
+ const decipher = crypto.createDecipheriv(`AES-${bytes}-CBC`, key, iv);
39
+ return decipher.update(data, "base64", "utf8") + decipher.final("utf8");
40
+ }
41
+ }