keq 2.8.10 → 3.0.0-alpha.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
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.8.11](https://github.com/keq-request/keq/compare/v2.8.10...v2.8.11) (2025-06-05)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * ensure proper cleanup of abort flow control function ([fc5ad5e](https://github.com/keq-request/keq/commit/fc5ad5ea34a1fcbd83a65f4906750113a424780d))
11
+
5
12
  ## [2.8.10](https://github.com/keq-request/keq/compare/v2.8.9...v2.8.10) (2024-12-26)
6
13
 
7
14
 
@@ -105,6 +105,22 @@ export class Core {
105
105
  }
106
106
  },
107
107
  };
108
+ Object.defineProperty(ctx, 'identifier', {
109
+ value: this.__identifier__,
110
+ writable: false,
111
+ });
112
+ Object.defineProperty(ctx, 'request', {
113
+ value: requestContext,
114
+ writable: false,
115
+ });
116
+ Object.defineProperty(ctx, 'emitter', {
117
+ value: emitter,
118
+ writable: false,
119
+ });
120
+ Object.defineProperty(ctx, 'global', {
121
+ value: this.__global__,
122
+ writable: false,
123
+ });
108
124
  const middleware = composeMiddleware([...this.__prepend_middlewares__, ...this.__append_middlewares__]);
109
125
  await middleware(ctx, async function emptyNext() { });
110
126
  const output = ctx[OUTPUT_PROPERTY];
@@ -5,11 +5,11 @@ import { KeqFlowControlMode, KeqFlowControlSignal } from './types/keq-flow-contr
5
5
  import type { KeqRetryOn, KeqRetryDelay } from './types/keq-retry.js';
6
6
  import type { KeqMiddleware } from './types/keq-middleware.js';
7
7
  import type { KeqOptionsParameter, KeqOptionsReturnType } from './types/keq-options.js';
8
- import type { KeqQueryValue } from './types/keq-query-value.js';
9
8
  import type { CommonContentType, ShorthandContentType } from './types/content-type.js';
10
9
  import type { KeqContextOptions } from './types/keq-context.js';
11
10
  import type { ExtractFields, ExtractFiles, KeqBaseOperation, KeqOperation } from './types/keq-operation.js';
12
11
  import type { KeqContextRequestBody } from './types/keq-context-request.js';
12
+ import { KeqQueryObject, KeqQueryValue } from './types/keq-query-value.js';
13
13
  /**
14
14
  * @description Keq 扩展 API,人性化的常用的API
15
15
  */
@@ -34,8 +34,8 @@ export declare class Keq<OUTPUT, OPERATION extends Omit<KeqOperation, 'responseB
34
34
  */
35
35
  query<K extends 'strict'>(key: OPERATION['requestQuery']): this;
36
36
  query<K extends 'strict', T extends keyof OPERATION['requestQuery']>(key: T, value: OPERATION['requestQuery'][T]): this;
37
- query(key: Record<string, KeqQueryValue | KeqQueryValue[]>): this;
38
- query(key: string, value: KeqQueryValue | KeqQueryValue[]): this;
37
+ query(key: KeqQueryObject): this;
38
+ query(key: string, value: KeqQueryValue): this;
39
39
  /**
40
40
  * Set request route params
41
41
  */
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
2
  /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ import qs from 'qs';
3
4
  import { Core } from './core.js';
4
5
  import { Exception } from './exception/exception.js';
5
6
  import { InvalidArgumentsExceptions } from './exception/invalid-arguments.exception.js';
@@ -15,6 +16,7 @@ import { fixContentType } from './util/fix-content-type.js';
15
16
  import { isValidHeaderValue } from './util/is-valid-header-value.js';
16
17
  import { isReadableStream } from './is/is-readable-stream.js';
17
18
  import { isArrayBuffer } from './is/is-array-buffer.js';
19
+ import { isObject } from './is/is-object.js';
18
20
  /**
19
21
  * @description Keq 扩展 API,人性化的常用的API
20
22
  */
@@ -55,29 +57,17 @@ export class Keq extends Core {
55
57
  return this;
56
58
  }
57
59
  query(key, value) {
58
- if (typeof key === 'object') {
59
- for (const [k, v] of Object.entries(key)) {
60
- if (v === undefined)
61
- continue;
62
- this.query(k, v);
60
+ if (isObject(key)) {
61
+ const obj = qs.parse(qs.stringify(key, { encode: false, arrayFormat: 'brackets' }), { depth: 0 });
62
+ for (const [k, v] of Object.entries(obj)) {
63
+ for (const item of Array.isArray(v) ? v : [v]) {
64
+ this.requestContext.url.searchParams.append(k, item);
65
+ }
63
66
  }
64
67
  return this;
65
68
  }
66
69
  if (typeof key === 'string') {
67
- if (Array.isArray(value)) {
68
- for (const item of value) {
69
- this.query(key, item);
70
- }
71
- }
72
- else if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint') {
73
- this.requestContext.url.searchParams.append(key, String(value));
74
- }
75
- else if (value === 'undefined' || value === null || value === undefined) {
76
- // skip
77
- }
78
- else {
79
- console.warn(`query value type(${typeof value}) is invalid, key: ${key}`);
80
- }
70
+ this.query({ [key]: value });
81
71
  return this;
82
72
  }
83
73
  throw new TypeError('typeof key is invalid');
@@ -92,7 +82,7 @@ export class Keq extends Core {
92
82
  }
93
83
  }
94
84
  else {
95
- throw new Exception('please set params value');
85
+ throw new TypeError('Invalid Arguments for .params()');
96
86
  }
97
87
  return this;
98
88
  }
@@ -13,12 +13,15 @@ export function abortFlowControlMiddleware() {
13
13
  const reason = new DOMException('The previous request was not completed, so keq flowControl abort this request.', 'AbortError');
14
14
  abort(reason);
15
15
  }
16
- ctx.global.abortFlowControl[key] = ctx.abort.bind(ctx);
16
+ const fn = ctx.abort.bind(ctx);
17
+ ctx.global.abortFlowControl[key] = fn;
17
18
  try {
18
19
  await next();
19
20
  }
20
21
  finally {
21
- ctx.global.abortFlowControl[key] = undefined;
22
+ if (ctx.global.abortFlowControl[key] === fn) {
23
+ ctx.global.abortFlowControl[key] = undefined;
24
+ }
22
25
  }
23
26
  };
24
27
  }
@@ -51,16 +51,6 @@ export interface KeqContext {
51
51
  * share data between requests
52
52
  */
53
53
  readonly global: KeqGlobal;
54
- /**
55
- * retry information, undefined is no retry
56
- *
57
- * @deprecated
58
- */
59
- retry?: {
60
- attempt: number;
61
- error: unknown | null;
62
- delay: number;
63
- };
64
54
  /**
65
55
  * Fetch API Arguments
66
56
  */
@@ -2,13 +2,12 @@
2
2
  /// <reference types="node" />
3
3
  import { ExtractProperty } from './extract-property.js';
4
4
  import { KeqContextRequestMethod } from './keq-context-request.js';
5
+ import { KeqQueryObject } from './keq-query-value.js';
5
6
  export interface KeqOperation {
6
7
  requestParams: {
7
8
  [key: string]: string | number;
8
9
  };
9
- requestQuery: {
10
- [key: string]: string | string[] | number;
11
- };
10
+ requestQuery: KeqQueryObject;
12
11
  requestHeaders: {
13
12
  [key: string]: string | number;
14
13
  };
@@ -32,9 +31,7 @@ export interface KeqBaseOperation extends KeqOperation {
32
31
  requestParams: {
33
32
  [key: string]: string;
34
33
  };
35
- requestQuery: {
36
- [key: string]: string | string[];
37
- };
34
+ requestQuery: KeqQueryObject;
38
35
  requestHeaders: {
39
36
  'content-type': string;
40
37
  cookie: string;
@@ -1 +1,6 @@
1
- export type KeqQueryValue = string | number | bigint | undefined;
1
+ export type KeqQueryPrimitive = string | number | null | bigint | undefined;
2
+ export type KeqQueryObject = {
3
+ [Key in string]: KeqQueryValue | undefined;
4
+ };
5
+ export type KeqQueryArray = KeqQueryValue[];
6
+ export type KeqQueryValue = KeqQueryPrimitive | KeqQueryArray | KeqQueryObject;
@@ -2,15 +2,15 @@ function compilePathnameTemplate(template, params) {
2
2
  return template
3
3
  .replace(/(^|\/)(?::([^/]+)|{([^/]+)}|%7B([^/]+)%7D)(?=$|\/)/g, (_, prefix, group1, group2, group3) => {
4
4
  if (group1 && params[group1]) {
5
- return `${prefix}${encodeURIComponent(params[group1])}`;
5
+ return `${prefix}${params[group1]}`;
6
6
  }
7
7
  else if (group2 && params[group2]) {
8
- return `${prefix}${encodeURIComponent(params[group2])}`;
8
+ return `${prefix}${params[group2]}`;
9
9
  }
10
10
  else if (group3 && params[group3]) {
11
- return `${prefix}${encodeURIComponent(params[group3])}`;
11
+ return `${prefix}${params[group3]}`;
12
12
  }
13
- return _;
13
+ return '';
14
14
  });
15
15
  }
16
16
  export function compileUrl(obj, routeParams) {
@@ -120,6 +120,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
120
120
  }
121
121
  },
122
122
  };
123
+ Object.defineProperty(ctx, 'identifier', {
124
+ value: this.__identifier__,
125
+ writable: false,
126
+ });
127
+ Object.defineProperty(ctx, 'request', {
128
+ value: requestContext,
129
+ writable: false,
130
+ });
131
+ Object.defineProperty(ctx, 'emitter', {
132
+ value: emitter,
133
+ writable: false,
134
+ });
135
+ Object.defineProperty(ctx, 'global', {
136
+ value: this.__global__,
137
+ writable: false,
138
+ });
123
139
  const middleware = (0, compose_middleware_js_1.composeMiddleware)([...this.__prepend_middlewares__, ...this.__append_middlewares__]);
124
140
  await middleware(ctx, async function emptyNext() { });
125
141
  const output = ctx[constant_js_1.OUTPUT_PROPERTY];
@@ -5,11 +5,11 @@ import { KeqFlowControlMode, KeqFlowControlSignal } from './types/keq-flow-contr
5
5
  import type { KeqRetryOn, KeqRetryDelay } from './types/keq-retry.js';
6
6
  import type { KeqMiddleware } from './types/keq-middleware.js';
7
7
  import type { KeqOptionsParameter, KeqOptionsReturnType } from './types/keq-options.js';
8
- import type { KeqQueryValue } from './types/keq-query-value.js';
9
8
  import type { CommonContentType, ShorthandContentType } from './types/content-type.js';
10
9
  import type { KeqContextOptions } from './types/keq-context.js';
11
10
  import type { ExtractFields, ExtractFiles, KeqBaseOperation, KeqOperation } from './types/keq-operation.js';
12
11
  import type { KeqContextRequestBody } from './types/keq-context-request.js';
12
+ import { KeqQueryObject, KeqQueryValue } from './types/keq-query-value.js';
13
13
  /**
14
14
  * @description Keq 扩展 API,人性化的常用的API
15
15
  */
@@ -34,8 +34,8 @@ export declare class Keq<OUTPUT, OPERATION extends Omit<KeqOperation, 'responseB
34
34
  */
35
35
  query<K extends 'strict'>(key: OPERATION['requestQuery']): this;
36
36
  query<K extends 'strict', T extends keyof OPERATION['requestQuery']>(key: T, value: OPERATION['requestQuery'][T]): this;
37
- query(key: Record<string, KeqQueryValue | KeqQueryValue[]>): this;
38
- query(key: string, value: KeqQueryValue | KeqQueryValue[]): this;
37
+ query(key: KeqQueryObject): this;
38
+ query(key: string, value: KeqQueryValue): this;
39
39
  /**
40
40
  * Set request route params
41
41
  */
@@ -1,10 +1,13 @@
1
+ var __importDefault = (this && this.__importDefault) || function (mod) {
2
+ return (mod && mod.__esModule) ? mod : { "default": mod };
3
+ };
1
4
  (function (factory) {
2
5
  if (typeof module === "object" && typeof module.exports === "object") {
3
6
  var v = factory(require, exports);
4
7
  if (v !== undefined) module.exports = v;
5
8
  }
6
9
  else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports", "./core.js", "./exception/exception.js", "./exception/invalid-arguments.exception.js", "./is/is-blob.js", "./is/is-file.js", "./is/is-form-data.js", "./is/is-headers.js", "./is/is-buffer.js", "./is/is-url-search-params.js", "./util/merge-keq-request-body.js", "./util/base64.js", "./util/fix-content-type.js", "./util/is-valid-header-value.js", "./is/is-readable-stream.js", "./is/is-array-buffer.js"], factory);
10
+ define(["require", "exports", "qs", "./core.js", "./exception/exception.js", "./exception/invalid-arguments.exception.js", "./is/is-blob.js", "./is/is-file.js", "./is/is-form-data.js", "./is/is-headers.js", "./is/is-buffer.js", "./is/is-url-search-params.js", "./util/merge-keq-request-body.js", "./util/base64.js", "./util/fix-content-type.js", "./util/is-valid-header-value.js", "./is/is-readable-stream.js", "./is/is-array-buffer.js", "./is/is-object.js"], factory);
8
11
  }
9
12
  })(function (require, exports) {
10
13
  "use strict";
@@ -12,6 +15,7 @@
12
15
  exports.Keq = void 0;
13
16
  /* eslint-disable @typescript-eslint/no-unused-vars */
14
17
  /* eslint-disable @typescript-eslint/no-explicit-any */
18
+ const qs_1 = __importDefault(require("qs"));
15
19
  const core_js_1 = require("./core.js");
16
20
  const exception_js_1 = require("./exception/exception.js");
17
21
  const invalid_arguments_exception_js_1 = require("./exception/invalid-arguments.exception.js");
@@ -27,6 +31,7 @@
27
31
  const is_valid_header_value_js_1 = require("./util/is-valid-header-value.js");
28
32
  const is_readable_stream_js_1 = require("./is/is-readable-stream.js");
29
33
  const is_array_buffer_js_1 = require("./is/is-array-buffer.js");
34
+ const is_object_js_1 = require("./is/is-object.js");
30
35
  /**
31
36
  * @description Keq 扩展 API,人性化的常用的API
32
37
  */
@@ -67,29 +72,17 @@
67
72
  return this;
68
73
  }
69
74
  query(key, value) {
70
- if (typeof key === 'object') {
71
- for (const [k, v] of Object.entries(key)) {
72
- if (v === undefined)
73
- continue;
74
- this.query(k, v);
75
+ if ((0, is_object_js_1.isObject)(key)) {
76
+ const obj = qs_1.default.parse(qs_1.default.stringify(key, { encode: false, arrayFormat: 'brackets' }), { depth: 0 });
77
+ for (const [k, v] of Object.entries(obj)) {
78
+ for (const item of Array.isArray(v) ? v : [v]) {
79
+ this.requestContext.url.searchParams.append(k, item);
80
+ }
75
81
  }
76
82
  return this;
77
83
  }
78
84
  if (typeof key === 'string') {
79
- if (Array.isArray(value)) {
80
- for (const item of value) {
81
- this.query(key, item);
82
- }
83
- }
84
- else if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint') {
85
- this.requestContext.url.searchParams.append(key, String(value));
86
- }
87
- else if (value === 'undefined' || value === null || value === undefined) {
88
- // skip
89
- }
90
- else {
91
- console.warn(`query value type(${typeof value}) is invalid, key: ${key}`);
92
- }
85
+ this.query({ [key]: value });
93
86
  return this;
94
87
  }
95
88
  throw new TypeError('typeof key is invalid');
@@ -104,7 +97,7 @@
104
97
  }
105
98
  }
106
99
  else {
107
- throw new exception_js_1.Exception('please set params value');
100
+ throw new TypeError('Invalid Arguments for .params()');
108
101
  }
109
102
  return this;
110
103
  }
@@ -25,12 +25,15 @@
25
25
  const reason = new DOMException('The previous request was not completed, so keq flowControl abort this request.', 'AbortError');
26
26
  abort(reason);
27
27
  }
28
- ctx.global.abortFlowControl[key] = ctx.abort.bind(ctx);
28
+ const fn = ctx.abort.bind(ctx);
29
+ ctx.global.abortFlowControl[key] = fn;
29
30
  try {
30
31
  await next();
31
32
  }
32
33
  finally {
33
- ctx.global.abortFlowControl[key] = undefined;
34
+ if (ctx.global.abortFlowControl[key] === fn) {
35
+ ctx.global.abortFlowControl[key] = undefined;
36
+ }
34
37
  }
35
38
  };
36
39
  }
@@ -51,16 +51,6 @@ export interface KeqContext {
51
51
  * share data between requests
52
52
  */
53
53
  readonly global: KeqGlobal;
54
- /**
55
- * retry information, undefined is no retry
56
- *
57
- * @deprecated
58
- */
59
- retry?: {
60
- attempt: number;
61
- error: unknown | null;
62
- delay: number;
63
- };
64
54
  /**
65
55
  * Fetch API Arguments
66
56
  */
@@ -2,13 +2,12 @@
2
2
  /// <reference types="node" />
3
3
  import { ExtractProperty } from './extract-property.js';
4
4
  import { KeqContextRequestMethod } from './keq-context-request.js';
5
+ import { KeqQueryObject } from './keq-query-value.js';
5
6
  export interface KeqOperation {
6
7
  requestParams: {
7
8
  [key: string]: string | number;
8
9
  };
9
- requestQuery: {
10
- [key: string]: string | string[] | number;
11
- };
10
+ requestQuery: KeqQueryObject;
12
11
  requestHeaders: {
13
12
  [key: string]: string | number;
14
13
  };
@@ -32,9 +31,7 @@ export interface KeqBaseOperation extends KeqOperation {
32
31
  requestParams: {
33
32
  [key: string]: string;
34
33
  };
35
- requestQuery: {
36
- [key: string]: string | string[];
37
- };
34
+ requestQuery: KeqQueryObject;
38
35
  requestHeaders: {
39
36
  'content-type': string;
40
37
  cookie: string;
@@ -1 +1,6 @@
1
- export type KeqQueryValue = string | number | bigint | undefined;
1
+ export type KeqQueryPrimitive = string | number | null | bigint | undefined;
2
+ export type KeqQueryObject = {
3
+ [Key in string]: KeqQueryValue | undefined;
4
+ };
5
+ export type KeqQueryArray = KeqQueryValue[];
6
+ export type KeqQueryValue = KeqQueryPrimitive | KeqQueryArray | KeqQueryObject;
@@ -14,15 +14,15 @@
14
14
  return template
15
15
  .replace(/(^|\/)(?::([^/]+)|{([^/]+)}|%7B([^/]+)%7D)(?=$|\/)/g, (_, prefix, group1, group2, group3) => {
16
16
  if (group1 && params[group1]) {
17
- return `${prefix}${encodeURIComponent(params[group1])}`;
17
+ return `${prefix}${params[group1]}`;
18
18
  }
19
19
  else if (group2 && params[group2]) {
20
- return `${prefix}${encodeURIComponent(params[group2])}`;
20
+ return `${prefix}${params[group2]}`;
21
21
  }
22
22
  else if (group3 && params[group3]) {
23
- return `${prefix}${encodeURIComponent(params[group3])}`;
23
+ return `${prefix}${params[group3]}`;
24
24
  }
25
- return _;
25
+ return '';
26
26
  });
27
27
  }
28
28
  function compileUrl(obj, routeParams) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keq",
3
- "version": "2.8.10",
3
+ "version": "3.0.0-alpha.1",
4
4
  "description": "Request API write by Typescript for flexibility, readability, and a low learning curve.",
5
5
  "keywords": [
6
6
  "request",
@@ -45,7 +45,9 @@
45
45
  "fastq": "^1.17.1",
46
46
  "minimatch": "^9.0.4",
47
47
  "mitt": "^3.0.1",
48
- "ts-custom-error": "^3.3.1"
48
+ "qs": "^6.13.1",
49
+ "ts-custom-error": "^3.3.1",
50
+ "type-fest": "^4.30.2"
49
51
  },
50
52
  "devDependencies": {
51
53
  "@buka/eslint-config": "^2.1.1",
@@ -55,12 +57,14 @@
55
57
  "@types/clone": "^2.1.4",
56
58
  "@types/minimatch": "^5.1.2",
57
59
  "@types/node": "^20.14.1",
60
+ "@types/qs": "^6.9.17",
58
61
  "eslint": "^9.13.0",
59
62
  "husky": "^9.1.6",
60
63
  "is-ci": "^3.0.1",
61
64
  "jest": "^29.7.0",
62
65
  "jest-environment-jsdom": "^29.7.0",
63
66
  "jest-mock": "^29.7.0",
67
+ "semantic-release": "^24.2.8",
64
68
  "standard-version": "^9.5.0",
65
69
  "ts-jest": "^29.1.5",
66
70
  "ts-node": "^10.9.2",
@@ -68,8 +72,8 @@
68
72
  "typescript": "5.4.5",
69
73
  "typescript-transform-paths": "^3.5.1"
70
74
  },
71
- "packageManager": "pnpm@9.15.1",
75
+ "packageManager": "pnpm@10.15.1+sha256.8c53af02ae3ec1fb0ae75377f8d4d6217c2d7cbe6f03c16350cabf7493de6eff",
72
76
  "engines": {
73
- "node": ">=18.0.0"
77
+ "node": ">=20.0.0"
74
78
  }
75
79
  }