keq 2.7.3 → 2.7.5

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 (48) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/esm/package.json +1 -0
  3. package/dist/esm/src/core.js +1 -1
  4. package/dist/esm/src/create-request.js +7 -1
  5. package/dist/esm/src/is/is-blob.js +1 -0
  6. package/dist/esm/src/is/is-buffer.js +1 -0
  7. package/dist/esm/src/is/is-file.js +1 -0
  8. package/dist/esm/src/is/is-form-data.js +1 -0
  9. package/dist/esm/src/is/is-function.js +1 -0
  10. package/dist/esm/src/is/is-headers.js +1 -0
  11. package/dist/esm/src/is/is-object.js +1 -0
  12. package/dist/esm/src/is/is-url-search-params.js +1 -0
  13. package/dist/esm/src/keq.js +1 -1
  14. package/dist/esm/src/types/keq-context-request.d.ts +1 -1
  15. package/dist/esm/src/types/keq-context.js +1 -0
  16. package/dist/esm/src/types/keq-request.d.ts +1 -0
  17. package/dist/esm/src/util/assign-keq-request-body.js +1 -1
  18. package/dist/esm/src/util/clone-body.js +1 -0
  19. package/dist/esm/src/util/shallow-clone.js +1 -0
  20. package/dist/umd/package.json +1 -0
  21. package/dist/umd/src/core.js +1 -1
  22. package/dist/umd/src/create-request.js +7 -1
  23. package/dist/umd/src/is/is-blob.js +1 -0
  24. package/dist/umd/src/is/is-buffer.js +1 -0
  25. package/dist/umd/src/is/is-file.js +1 -0
  26. package/dist/umd/src/is/is-form-data.js +1 -0
  27. package/dist/umd/src/is/is-function.js +1 -0
  28. package/dist/umd/src/is/is-headers.js +1 -0
  29. package/dist/umd/src/is/is-object.js +1 -0
  30. package/dist/umd/src/is/is-url-search-params.js +1 -0
  31. package/dist/umd/src/keq.js +1 -1
  32. package/dist/umd/src/types/keq-context-request.d.ts +1 -1
  33. package/dist/umd/src/types/keq-context.js +1 -0
  34. package/dist/umd/src/types/keq-request.d.ts +1 -0
  35. package/dist/umd/src/util/assign-keq-request-body.js +1 -1
  36. package/dist/umd/src/util/clone-body.js +1 -0
  37. package/dist/umd/src/util/shallow-clone.js +1 -0
  38. package/package.json +15 -16
  39. package/.node-version +0 -1
  40. package/.vscode/settings.json +0 -5
  41. package/__tests__/node/abort.spec.ts +0 -110
  42. package/__tests__/node/request.ts +0 -51
  43. package/__tests__/node/resolve-with-mode.spec.ts +0 -48
  44. package/__tests__/node/retry.spec.ts +0 -35
  45. package/__tests__/node/send-request-with-body.spec.ts +0 -107
  46. package/__tests__/node/send-simple-request.spec.ts +0 -121
  47. package/__tests__/node/timeout.spec.ts +0 -48
  48. package/__tests__/setup.ts +0 -32
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [2.7.5](https://github.com/keq-request/keq/compare/v2.7.4...v2.7.5) (2024-09-10)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * cannot import esm ([e6c1cfb](https://github.com/keq-request/keq/commit/e6c1cfb3c283e7cd3d44cd7d60d30aaf7a380ecc))
11
+
12
+ ## [2.7.4](https://github.com/keq-request/keq/compare/v2.7.3...v2.7.4) (2024-08-19)
13
+
14
+
15
+ ### Performance Improvements
16
+
17
+ * add options method support ([bfc7ae4](https://github.com/keq-request/keq/commit/bfc7ae45f4ad1e14bfca4ec7d6c599915424df43))
18
+
5
19
  ## [2.7.3](https://github.com/keq-request/keq/compare/v2.7.2...v2.7.3) (2024-08-13)
6
20
 
7
21
 
@@ -0,0 +1 @@
1
+ {"type": "module"}
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import mitt from 'mitt';
2
3
  import { Exception } from './exception/exception.js';
3
4
  import { cloneBody } from './util/clone-body.js';
@@ -99,7 +100,6 @@ export class Core {
99
100
  },
100
101
  };
101
102
  const middleware = composeMiddleware([...this.__prepend_middlewares__, ...this.__append_middlewares__]);
102
- // eslint-disable-next-line @typescript-eslint/no-empty-function
103
103
  await middleware(ctx, async function emptyNext() { });
104
104
  const output = ctx[OUTPUT_PROPERTY];
105
105
  if (ctx.options.resolveWithFullResponse || ctx.options.resolveWith === 'response') {
@@ -1,4 +1,4 @@
1
- /* eslint-disable @typescript-eslint/no-unsafe-return */
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { isBrowser } from './is/is-browser.js';
3
3
  import { Keq } from './keq.js';
4
4
  import { abortFlowControlMiddleware } from './middlewares/abort-flow-control-middleware.js';
@@ -91,6 +91,12 @@ export function createRequest(options) {
91
91
  keq.prependMiddlewares(...prependMiddlewares);
92
92
  return keq;
93
93
  };
94
+ request.options = function (url) {
95
+ const keq = new Keq(formatUrl(url), { method: 'options' }, global);
96
+ keq.appendMiddlewares(...appendMiddlewares);
97
+ keq.prependMiddlewares(...prependMiddlewares);
98
+ return keq;
99
+ };
94
100
  request.use = function use(middleware, ...middlewares) {
95
101
  prependMiddlewares.push(middleware, ...middlewares);
96
102
  return request;
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { isFunction } from './is-function.js';
2
3
  import { isObject } from './is-object.js';
3
4
  import { isString } from './is-string.js';
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { isBrowser } from './is-browser';
2
3
  export function isBuffer(obj) {
3
4
  return isBrowser() ? false : Buffer.isBuffer(obj);
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { isBlob } from './is-blob.js';
2
3
  import { isBrowser } from './is-browser.js';
3
4
  export function isFile(object) {
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { isFunction } from './is-function.js';
2
3
  import { isObject } from './is-object.js';
3
4
  export function isFormData(object) {
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  export function isFunction(value) {
2
3
  return typeof value === 'function';
3
4
  }
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { isFunction } from './is-function.js';
2
3
  import { isObject } from './is-object.js';
3
4
  export function isHeaders(obj) {
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  export function isObject(value) {
2
3
  return typeof value === 'object' && value !== null;
3
4
  }
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { isFunction } from './is-function.js';
2
3
  import { isObject } from './is-object.js';
3
4
  export function isUrlSearchParams(obj) {
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { Core } from './core.js';
2
3
  import { Exception } from './exception/exception.js';
3
4
  import { InvalidArgumentsExceptions } from './exception/invalid-arguments.exception.js';
@@ -206,7 +207,6 @@ export class Keq extends Core {
206
207
  }
207
208
  resolveWith(m) {
208
209
  this.option('resolveWith', m);
209
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
210
210
  return this;
211
211
  }
212
212
  }
@@ -1,4 +1,4 @@
1
- export type KeqContextRequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head' | 'patch';
1
+ export type KeqContextRequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head' | 'patch' | 'options';
2
2
  export type KeqContextRequestBody = object | Array<any> | string | undefined;
3
3
  export interface KeqContextRequest {
4
4
  url: URL;
@@ -1 +1,2 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { ABORT_PROPERTY, NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from '../constant.js';
@@ -25,6 +25,7 @@ export interface KeqRequest<OPERATIONS extends KeqOperations = KeqOperations> {
25
25
  put: KeqRequestFn<FlattenOperations<OPERATIONS, 'put'>>;
26
26
  patch: KeqRequestFn<FlattenOperations<OPERATIONS, 'patch'>>;
27
27
  head: KeqRequestFn<FlattenOperations<OPERATIONS, 'head'>>;
28
+ options: KeqRequestFn<FlattenOperations<OPERATIONS, 'options'>>;
28
29
  use(firstMiddleware: KeqMiddleware, ...middleware: KeqMiddleware[]): this;
29
30
  useRouter(): KeqRouter;
30
31
  }
@@ -1,4 +1,4 @@
1
- /* eslint-disable @typescript-eslint/no-unsafe-return */
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { Exception } from '../exception/exception.js';
3
3
  import { OverwriteArrayBodyException } from '../exception/overwrite-array-body.exception.js';
4
4
  import { isFormData } from '../is/is-form-data.js';
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { isBuffer } from '../is/is-buffer.js';
2
3
  import { isBlob } from '../is/is-blob.js';
3
4
  import { isFile } from '../is/is-file.js';
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { isObject } from '../is/is-object.js';
2
3
  /**
3
4
  * @description 浅拷贝
@@ -0,0 +1 @@
1
+ {"type": "commonjs"}
@@ -13,6 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13
13
  "use strict";
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.Core = void 0;
16
+ /* eslint-disable @typescript-eslint/no-explicit-any */
16
17
  const mitt_1 = __importDefault(require("mitt"));
17
18
  const exception_js_1 = require("./exception/exception.js");
18
19
  const clone_body_js_1 = require("./util/clone-body.js");
@@ -114,7 +115,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
114
115
  },
115
116
  };
116
117
  const middleware = (0, compose_middleware_js_1.composeMiddleware)([...this.__prepend_middlewares__, ...this.__append_middlewares__]);
117
- // eslint-disable-next-line @typescript-eslint/no-empty-function
118
118
  await middleware(ctx, async function emptyNext() { });
119
119
  const output = ctx[constant_js_1.OUTPUT_PROPERTY];
120
120
  if (ctx.options.resolveWithFullResponse || ctx.options.resolveWith === 'response') {
@@ -10,7 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.createRequest = void 0;
13
- /* eslint-disable @typescript-eslint/no-unsafe-return */
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
14
14
  const is_browser_js_1 = require("./is/is-browser.js");
15
15
  const keq_js_1 = require("./keq.js");
16
16
  const abort_flow_control_middleware_js_1 = require("./middlewares/abort-flow-control-middleware.js");
@@ -103,6 +103,12 @@
103
103
  keq.prependMiddlewares(...prependMiddlewares);
104
104
  return keq;
105
105
  };
106
+ request.options = function (url) {
107
+ const keq = new keq_js_1.Keq(formatUrl(url), { method: 'options' }, global);
108
+ keq.appendMiddlewares(...appendMiddlewares);
109
+ keq.prependMiddlewares(...prependMiddlewares);
110
+ return keq;
111
+ };
106
112
  request.use = function use(middleware, ...middlewares) {
107
113
  prependMiddlewares.push(middleware, ...middlewares);
108
114
  return request;
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.isBlob = void 0;
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
  const is_function_js_1 = require("./is-function.js");
14
15
  const is_object_js_1 = require("./is-object.js");
15
16
  const is_string_js_1 = require("./is-string.js");
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.isBuffer = void 0;
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
  const is_browser_1 = require("./is-browser");
14
15
  function isBuffer(obj) {
15
16
  return (0, is_browser_1.isBrowser)() ? false : Buffer.isBuffer(obj);
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.isFile = void 0;
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
  const is_blob_js_1 = require("./is-blob.js");
14
15
  const is_browser_js_1 = require("./is-browser.js");
15
16
  function isFile(object) {
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.isFormData = void 0;
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
  const is_function_js_1 = require("./is-function.js");
14
15
  const is_object_js_1 = require("./is-object.js");
15
16
  function isFormData(object) {
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.isFunction = void 0;
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
  function isFunction(value) {
14
15
  return typeof value === 'function';
15
16
  }
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.isHeaders = void 0;
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
  const is_function_js_1 = require("./is-function.js");
14
15
  const is_object_js_1 = require("./is-object.js");
15
16
  function isHeaders(obj) {
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.isObject = void 0;
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
  function isObject(value) {
14
15
  return typeof value === 'object' && value !== null;
15
16
  }
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.isUrlSearchParams = void 0;
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
  const is_function_js_1 = require("./is-function.js");
14
15
  const is_object_js_1 = require("./is-object.js");
15
16
  function isUrlSearchParams(obj) {
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.Keq = void 0;
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
  const core_js_1 = require("./core.js");
14
15
  const exception_js_1 = require("./exception/exception.js");
15
16
  const invalid_arguments_exception_js_1 = require("./exception/invalid-arguments.exception.js");
@@ -218,7 +219,6 @@
218
219
  }
219
220
  resolveWith(m) {
220
221
  this.option('resolveWith', m);
221
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
222
222
  return this;
223
223
  }
224
224
  }
@@ -1,4 +1,4 @@
1
- export type KeqContextRequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head' | 'patch';
1
+ export type KeqContextRequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head' | 'patch' | 'options';
2
2
  export type KeqContextRequestBody = object | Array<any> | string | undefined;
3
3
  export interface KeqContextRequest {
4
4
  url: URL;
@@ -9,5 +9,6 @@
9
9
  })(function (require, exports) {
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
+ /* eslint-disable @typescript-eslint/no-explicit-any */
12
13
  const constant_js_1 = require("../constant.js");
13
14
  });
@@ -25,6 +25,7 @@ export interface KeqRequest<OPERATIONS extends KeqOperations = KeqOperations> {
25
25
  put: KeqRequestFn<FlattenOperations<OPERATIONS, 'put'>>;
26
26
  patch: KeqRequestFn<FlattenOperations<OPERATIONS, 'patch'>>;
27
27
  head: KeqRequestFn<FlattenOperations<OPERATIONS, 'head'>>;
28
+ options: KeqRequestFn<FlattenOperations<OPERATIONS, 'options'>>;
28
29
  use(firstMiddleware: KeqMiddleware, ...middleware: KeqMiddleware[]): this;
29
30
  useRouter(): KeqRouter;
30
31
  }
@@ -10,7 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.assignKeqRequestBody = void 0;
13
- /* eslint-disable @typescript-eslint/no-unsafe-return */
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
14
14
  const exception_js_1 = require("../exception/exception.js");
15
15
  const overwrite_array_body_exception_js_1 = require("../exception/overwrite-array-body.exception.js");
16
16
  const is_form_data_js_1 = require("../is/is-form-data.js");
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.cloneBody = void 0;
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
  const is_buffer_js_1 = require("../is/is-buffer.js");
14
15
  const is_blob_js_1 = require("../is/is-blob.js");
15
16
  const is_file_js_1 = require("../is/is-file.js");
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.shallowClone = void 0;
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
  const is_object_js_1 = require("../is/is-object.js");
14
15
  /**
15
16
  * @description 浅拷贝
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keq",
3
- "version": "2.7.3",
3
+ "version": "2.7.5",
4
4
  "description": "Request API write by Typescript for flexibility, readability, and a low learning curve.",
5
5
  "keywords": [
6
6
  "request",
@@ -10,8 +10,19 @@
10
10
  "nodejs",
11
11
  "browser",
12
12
  "middleware",
13
- "middlewares"
13
+ "middlewares",
14
+ "axios",
15
+ "got"
14
16
  ],
17
+ "license": "MIT",
18
+ "author": "Val.istar.Guo <val.istar.guo@gmail.com>",
19
+ "main": "dist/umd/src/index.js",
20
+ "module": "dist/esm/src/index.js",
21
+ "types": "dist/esm/src/index.d.ts",
22
+ "exports": {
23
+ "require": "./dist/umd/src/index.js",
24
+ "import": "./dist/esm/src/index.js"
25
+ },
15
26
  "homepage": "https://github.com/keq-request/keq#readme",
16
27
  "bugs": {
17
28
  "url": "https://github.com/keq-request/keq/issues"
@@ -20,15 +31,6 @@
20
31
  "type": "git",
21
32
  "url": "git+https://github.com/keq-request/keq.git"
22
33
  },
23
- "license": "MIT",
24
- "author": "Val.istar.Guo <val.istar.guo@gmail.com>",
25
- "main": "dist/umd/src/index.js",
26
- "module": "dist/esm/src/index.js",
27
- "types": "dist/esm/src/index.d.ts",
28
- "directories": {
29
- "doc": "doc",
30
- "test": "test"
31
- },
32
34
  "scripts": {
33
35
  "build": "npm run clean && ./build/build.sh",
34
36
  "clean": "rm -rf ./dist/*",
@@ -46,17 +48,14 @@
46
48
  "ts-custom-error": "^3.3.1"
47
49
  },
48
50
  "devDependencies": {
49
- "@buka/eslint-config": "^1.6.4",
51
+ "@buka/eslint-config": "^2.1.1",
50
52
  "@commitlint/cli": "^19.3.0",
51
53
  "@commitlint/config-conventional": "^19.2.2",
52
54
  "@jest/globals": "^29.7.0",
53
- "@rushstack/eslint-patch": "^1.10.3",
54
55
  "@types/clone": "^2.1.4",
55
56
  "@types/minimatch": "^5.1.2",
56
57
  "@types/node": "^20.14.1",
57
- "@typescript-eslint/eslint-plugin": "^7.12.0",
58
- "@typescript-eslint/parser": "^7.12.0",
59
- "eslint": "^8.57.0",
58
+ "eslint": "^9.10.0",
60
59
  "husky": "^9.0.11",
61
60
  "is-ci": "^3.0.1",
62
61
  "jest": "^29.7.0",
package/.node-version DELETED
@@ -1 +0,0 @@
1
- v20.13.1
@@ -1,5 +0,0 @@
1
- {
2
- "[markdown]": {
3
- "editor.formatOnSave": false
4
- }
5
- }
@@ -1,110 +0,0 @@
1
- import { expect, jest, test } from '@jest/globals'
2
- import { request } from './request.js'
3
-
4
-
5
- test('abort flowController request', async () => {
6
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
7
- const mockedFetch = jest.fn((input: RequestInfo | URL, init?: RequestInit) => new Promise((resolve, reject) => {
8
- let finished = false
9
-
10
- if (init?.signal) {
11
- const signal = init.signal
12
- signal.onabort = () => {
13
- if (finished) return
14
- finished = true
15
- if (signal.reason) reject(signal.reason)
16
- reject(new DOMException('AbortError', 'AbortError'))
17
- }
18
- }
19
-
20
- // sleet 500ms
21
- setTimeout(
22
- () => {
23
- if (finished) return
24
- finished = true
25
-
26
- resolve(new Response(
27
- JSON.stringify({ code: '200' }),
28
- {
29
- headers: {
30
- 'content-type': 'application/json',
31
- },
32
- }
33
- ))
34
- },
35
- 100,
36
- )
37
- }))
38
-
39
- async function abortRequest(): Promise<void> {
40
- try {
41
- await request
42
- .get('http://test.com')
43
- .option('fetchAPI', mockedFetch)
44
- .flowControl('abort', 'test')
45
- } catch (e) {
46
- expect(e).toBeInstanceOf(DOMException)
47
- expect((e as DOMException).name).toBe('AbortError')
48
- }
49
- }
50
-
51
- void abortRequest()
52
-
53
- await request
54
- .get('http://test.com')
55
- .option('fetchAPI', mockedFetch)
56
- .flowControl('abort', 'test')
57
-
58
- expect(mockedFetch).toBeCalledTimes(2)
59
- })
60
-
61
- test('serial flowController request', async () => {
62
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
63
- const mockedFetch = jest.fn((input: RequestInfo | URL, init?: RequestInit) => new Promise((resolve, reject) => {
64
- let finished = false
65
-
66
- if (init?.signal) {
67
- const signal = init.signal
68
- signal.onabort = () => {
69
- if (finished) return
70
- finished = true
71
- if (signal.reason) reject(signal.reason)
72
- reject(new DOMException('AbortError', 'AbortError'))
73
- }
74
- }
75
-
76
- // sleet 500ms
77
- setTimeout(
78
- () => {
79
- if (finished) return
80
- finished = true
81
-
82
- resolve(new Response(
83
- JSON.stringify({ code: '200' }),
84
- {
85
- headers: {
86
- 'content-type': 'application/json',
87
- },
88
- }
89
- ))
90
- },
91
- 100,
92
- )
93
- }))
94
-
95
- async function serialRequest(): Promise<void> {
96
- await request
97
- .get('http://test.com')
98
- .option('fetchAPI', mockedFetch)
99
- .flowControl('serial', 'test')
100
- }
101
-
102
- void serialRequest()
103
-
104
- await request
105
- .get('http://test.com')
106
- .option('fetchAPI', mockedFetch)
107
- .flowControl('abort', 'test')
108
-
109
- expect(mockedFetch).toBeCalledTimes(2)
110
- })
@@ -1,51 +0,0 @@
1
- /* eslint-disable @typescript-eslint/ban-types */
2
- import { createRequest } from '~/index.js'
3
-
4
- import type { KeqBaseOperation, KeqOperations } from '~/types/keq-operation.js'
5
-
6
-
7
- interface TestModule extends KeqOperations {
8
- 'http://test.com': {
9
- get: {
10
- requestParams: {}
11
- requestQuery: {
12
- q: string
13
- }
14
- requestHeaders: KeqBaseOperation['requestHeaders']
15
- requestBody: {}
16
- responseBody: {
17
- data: 'test get'
18
- }
19
- }
20
- post: {
21
- requestParams: {}
22
- requestQuery: {
23
- q: string
24
- }
25
- requestHeaders: {
26
- 'x-test': 'test'
27
- }
28
- requestBody: {
29
- id: number
30
- name: string
31
- file: Buffer
32
- }
33
- responseBody: {
34
- data: 'test post'
35
- }
36
- }
37
- }
38
- 'http://example.com': {
39
- get: {
40
- requestParams: {}
41
- requestQuery: {}
42
- requestHeaders: KeqBaseOperation['requestHeaders']
43
- requestBody: {}
44
- responseBody: {
45
- data: 'example get'
46
- }
47
- }
48
- }
49
- }
50
-
51
- export const request = createRequest<TestModule>()
@@ -1,48 +0,0 @@
1
- import { expect, test } from '@jest/globals'
2
- import { request } from './request.js'
3
-
4
-
5
- test('resolve response body by text', async () => {
6
- const result = await request
7
- .get('http://test.com')
8
- .auth('username', 'password')
9
- .resolveWith('text')
10
-
11
- expect(result).toEqual('{"code":"200"}')
12
- })
13
-
14
- test('resolve response body by json', async () => {
15
- const result = await request
16
- .get('http://test.com')
17
- .auth('username', 'password')
18
- .resolveWith<{ code: string }>('json')
19
-
20
- expect(result).toEqual({ code: '200' })
21
- })
22
-
23
- test('resolve response body by blob', async () => {
24
- const result = await request
25
- .get('http://test.com')
26
- .auth('username', 'password')
27
- .resolveWith('blob')
28
-
29
- expect(result).toBeInstanceOf(Blob)
30
- })
31
-
32
- test('resolve response body by arrayBuffer', async () => {
33
- const result = await request
34
- .get('http://test.com')
35
- .auth('username', 'password')
36
- .resolveWith('array-buffer')
37
-
38
- expect(result).toBeInstanceOf(ArrayBuffer)
39
- })
40
-
41
- test('resolve response body', async () => {
42
- const result = await request
43
- .get('http://test.com')
44
- .auth('username', 'password')
45
- .resolveWith('response')
46
-
47
- expect(result).toBeInstanceOf(Response)
48
- })
@@ -1,35 +0,0 @@
1
- import { expect, jest, test } from '@jest/globals'
2
- import { KeqRetryOn } from '~/index.js'
3
- import { request } from './request.js'
4
-
5
-
6
- test('send request retry twice', async () => {
7
- const mockedFetch = jest.fn()
8
- const retryOn = jest.fn<KeqRetryOn>(() => true)
9
- const mockedListener = jest.fn()
10
-
11
- await request
12
- .get('http://test.com')
13
- .retry(2, 10, retryOn)
14
- .option('fetchAPI', mockedFetch)
15
- .on('retry', mockedListener)
16
-
17
- expect(mockedFetch.mock.calls).toHaveLength(3)
18
- expect(mockedListener.mock.calls).toHaveLength(2)
19
-
20
- expect(retryOn.mock.calls.length).toBe(2)
21
- expect(retryOn.mock.calls[0][0]).toBe(0)
22
- expect(retryOn.mock.calls[1][0]).toBe(1)
23
- expect(retryOn.mock.calls[1][2].retry?.delay).toBe(10)
24
- })
25
-
26
- test('send request retry once', async () => {
27
- const mockedFetch = jest.fn()
28
-
29
- await request
30
- .get('http://test.com')
31
- .retry(2, 0)
32
- .option('fetchAPI', mockedFetch)
33
-
34
- expect(mockedFetch.mock.calls).toHaveLength(1)
35
- })
@@ -1,107 +0,0 @@
1
- import { describe, expect, test } from '@jest/globals'
2
- import { Mock } from 'jest-mock'
3
- import { request } from './request.js'
4
-
5
-
6
- describe('send multipart/form-data request', () => {
7
- test('use FormData Class', async () => {
8
- const mockedFetch = global.fetch as Mock<typeof global.fetch>
9
-
10
- const formData = new FormData()
11
-
12
- const resumeFile = new Blob(['test'], { type: 'text/plain' })
13
- formData.append('name', 'John')
14
- formData.append('resume', resumeFile, 'test.txt')
15
- formData.append('friends', 'Tom')
16
- formData.append('friends', 'Bob')
17
-
18
- await request
19
- .post('http://test.com')
20
- .send(formData)
21
-
22
- const init = mockedFetch.mock.calls[0][1]
23
- expect(init).toBeDefined()
24
-
25
- const headers = init?.headers as Headers
26
-
27
- // FormData 需要自动删除 Content-Type
28
- expect(headers.get('Content-Type')).toBeNull()
29
-
30
- const body = init?.body as FormData
31
-
32
- expect(body.getAll('name')).toEqual(['John'])
33
- expect(body.getAll('friends')).toEqual(['Tom', 'Bob'])
34
- expect((body.get('resume') as File).name).toBe('test.txt')
35
- })
36
-
37
- test('use keq API', async () => {
38
- const mockedFetch = global.fetch as Mock<typeof global.fetch>
39
-
40
- await request
41
- .post('http://test.com')
42
- .field('name', 'John')
43
- .field('friends', ['Tom', 'Bob'])
44
- .field({ age: '12' })
45
- .attach('file1', new Blob(['test'], { type: 'text/plain' }), 'file1.txt')
46
-
47
- const init = mockedFetch.mock.calls[0][1]
48
- expect(init).toBeDefined()
49
-
50
- const headers = init?.headers as Headers
51
-
52
- // FormData 需要自动删除 Content-Type
53
- expect(headers.get('Content-Type')).toBeNull()
54
-
55
- const body = init?.body as FormData
56
-
57
- expect(body.getAll('name')).toEqual(['John'])
58
- expect(body.getAll('friends')).toEqual(['Tom', 'Bob'])
59
- expect(body.getAll('age')).toEqual(['12'])
60
- expect((body.get('file1') as File).name).toBe('file1.txt')
61
- })
62
- })
63
-
64
-
65
- test('send application/json request', async () => {
66
- const mockedFetch = global.fetch as Mock<typeof global.fetch>
67
-
68
- const requestBody = {
69
- name: 'John',
70
- friends: ['Tom', 'Bob'],
71
- }
72
- await request
73
- .post('http://test.com')
74
- .send(requestBody)
75
-
76
- const init = mockedFetch.mock.calls[0][1]
77
- expect(init).toBeDefined()
78
-
79
- const headers = init?.headers as Headers
80
- expect(headers.get('Content-Type')).toBe('application/json')
81
-
82
- const body = init?.body as string
83
- expect(body).toBe(JSON.stringify(requestBody))
84
- })
85
-
86
-
87
- test('send application/x-www-form-urlencoded request', async () => {
88
- const mockedFetch = global.fetch as Mock<typeof global.fetch>
89
-
90
- await request
91
- .post('http://test.com')
92
- .type('form')
93
- .send({
94
- name: 'John',
95
- friends: ['Tom', 'Bob'],
96
- })
97
-
98
- const init = mockedFetch.mock.calls[0][1]
99
- expect(init).toBeDefined()
100
-
101
- const headers = init?.headers as Headers
102
- expect(headers.get('Content-Type')).toBe('application/x-www-form-urlencoded')
103
-
104
- const body = init?.body as URLSearchParams
105
- expect(body).toBeInstanceOf(URLSearchParams)
106
- expect(body.toString()).toBe('name=John&friends=Tom&friends=Bob')
107
- })
@@ -1,121 +0,0 @@
1
- import { expect, test } from '@jest/globals'
2
- import { Mock } from 'jest-mock'
3
- import { request } from './request.js'
4
-
5
-
6
- test('send get request', async () => {
7
- const mockedFetch = global.fetch as Mock<typeof global.fetch>
8
-
9
- await request
10
- .get('http://test.com')
11
-
12
-
13
- expect(mockedFetch.mock.calls).toHaveLength(1)
14
-
15
- const url = mockedFetch.mock.calls[0][0]
16
- const init = mockedFetch.mock.calls[0][1]
17
-
18
- expect(url).toBe('http://test.com/')
19
- expect(init?.method).toBe('GET')
20
- })
21
-
22
-
23
- test('send post request', async () => {
24
- const mockedFetch = global.fetch as Mock<typeof global.fetch>
25
-
26
- await request
27
- .post('http://test.com')
28
-
29
- expect(mockedFetch.mock.calls).toHaveLength(1)
30
-
31
- const url = mockedFetch.mock.calls[0][0]
32
- const init = mockedFetch.mock.calls[0][1]
33
-
34
- expect(url).toBe('http://test.com/')
35
- expect(init?.method).toBe('POST')
36
-
37
- expect(init?.headers).toBeInstanceOf(Headers)
38
-
39
- const headers = init?.headers as Headers
40
- expect(headers.get('content-type')).toBeNull()
41
- })
42
-
43
- test('send put request', async () => {
44
- const mockedFetch = global.fetch as Mock<typeof global.fetch>
45
-
46
- await request
47
- .put('http://test.com')
48
-
49
- expect(mockedFetch.mock.calls).toHaveLength(1)
50
-
51
- const url = mockedFetch.mock.calls[0][0]
52
- const init = mockedFetch.mock.calls[0][1]
53
-
54
- expect(url).toBe('http://test.com/')
55
- expect(init?.method).toBe('PUT')
56
-
57
- expect(init?.headers).toBeInstanceOf(Headers)
58
-
59
- const headers = init?.headers as Headers
60
- expect(headers.get('content-type')).toBeNull()
61
- })
62
-
63
- test('send patch request', async () => {
64
- const mockedFetch = global.fetch as Mock<typeof global.fetch>
65
-
66
- await request
67
- .patch('http://test.com')
68
-
69
- expect(mockedFetch.mock.calls).toHaveLength(1)
70
-
71
- const url = mockedFetch.mock.calls[0][0]
72
- const init = mockedFetch.mock.calls[0][1]
73
-
74
- expect(url).toBe('http://test.com/')
75
- expect(init?.method).toBe('PATCH')
76
-
77
- expect(init?.headers).toBeInstanceOf(Headers)
78
-
79
- const headers = init?.headers as Headers
80
- expect(headers.get('content-type')).toBeNull()
81
- })
82
-
83
- test('send head request', async () => {
84
- const mockedFetch = global.fetch as Mock<typeof global.fetch>
85
-
86
- await request
87
- .head('http://test.com')
88
-
89
- expect(mockedFetch.mock.calls).toHaveLength(1)
90
-
91
- const url = mockedFetch.mock.calls[0][0]
92
- const init = mockedFetch.mock.calls[0][1]
93
-
94
- expect(url).toBe('http://test.com/')
95
- expect(init?.method).toBe('HEAD')
96
-
97
- expect(init?.headers).toBeInstanceOf(Headers)
98
-
99
- const headers = init?.headers as Headers
100
- expect(headers.get('content-type')).toBeNull()
101
- })
102
-
103
- test('send DELETE request', async () => {
104
- const mockedFetch = global.fetch as Mock<typeof global.fetch>
105
-
106
- await request
107
- .del('http://test.com')
108
-
109
- expect(mockedFetch.mock.calls).toHaveLength(1)
110
-
111
- const url = mockedFetch.mock.calls[0][0]
112
- const init = mockedFetch.mock.calls[0][1]
113
-
114
- expect(url).toBe('http://test.com/')
115
- expect(init?.method).toBe('DELETE')
116
-
117
- expect(init?.headers).toBeInstanceOf(Headers)
118
-
119
- const headers = init?.headers as Headers
120
- expect(headers.get('content-type')).toBeNull()
121
- })
@@ -1,48 +0,0 @@
1
- import { expect, jest, test } from '@jest/globals'
2
- import { request } from './request.js'
3
-
4
-
5
- test('timeout request', async () => {
6
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
7
- const mockedFetch = jest.fn((input: RequestInfo | URL, init?: RequestInit) => new Promise((resolve, reject) => {
8
- let finished = false
9
-
10
- if (init?.signal) {
11
- const signal = init.signal
12
- signal.onabort = () => {
13
- if (finished) return
14
- finished = true
15
- if (signal.reason) reject(signal.reason)
16
- reject(new DOMException('AbortError', 'AbortError'))
17
- }
18
- }
19
-
20
- // sleet 500ms
21
- setTimeout(
22
- () => {
23
- if (finished) return
24
- finished = true
25
-
26
- resolve(new Response(
27
- JSON.stringify({ code: '200' }),
28
- {
29
- headers: {
30
- 'content-type': 'application/json',
31
- },
32
- }
33
- ))
34
- },
35
- 500,
36
- )
37
- }))
38
-
39
- try {
40
- await request
41
- .get('http://test.com')
42
- .option('fetchAPI', mockedFetch)
43
- .timeout(100)
44
- } catch (e) {
45
- expect(e).toBeInstanceOf(DOMException)
46
- expect((e as DOMException).name).toBe('AbortError')
47
- }
48
- })
@@ -1,32 +0,0 @@
1
- import { afterAll, beforeAll, beforeEach, jest } from '@jest/globals'
2
- // import { TextEncoder, TextDecoder } from 'util'
3
-
4
-
5
- // https://github.com/inrupt/solid-client-authn-js/issues/1676
6
- // global.TextEncoder = TextEncoder
7
- // global.TextDecoder = TextDecoder as any
8
-
9
-
10
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
11
- const mockedFetch = jest.fn((input: RequestInfo | URL, init?: RequestInit) => Promise.resolve(new Response(
12
- JSON.stringify({ code: '200' }),
13
- {
14
- headers: {
15
- 'content-type': 'application/json',
16
- },
17
- }
18
- )))
19
-
20
- const unMockedFetch = global.fetch
21
-
22
- beforeAll(() => {
23
- global.fetch = mockedFetch as unknown as typeof fetch
24
- })
25
-
26
- afterAll(() => {
27
- global.fetch = unMockedFetch
28
- })
29
-
30
- beforeEach(() => {
31
- mockedFetch.mockClear()
32
- })