keq 2.5.4 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/.node-version +1 -0
  2. package/CHANGELOG.md +21 -0
  3. package/dist/esm/src/constant.d.ts +1 -0
  4. package/dist/esm/src/constant.js +1 -0
  5. package/dist/esm/src/core.d.ts +4 -1
  6. package/dist/esm/src/core.js +23 -2
  7. package/dist/esm/src/create-request.js +1 -1
  8. package/dist/esm/src/index.d.ts +12 -10
  9. package/dist/esm/src/is/is-url-search-params.js +3 -6
  10. package/dist/esm/src/keq.js +2 -4
  11. package/dist/esm/src/middlewares/abort-flow-control-middleware.js +11 -13
  12. package/dist/esm/src/middlewares/fetch-arguments-middleware.js +7 -1
  13. package/dist/esm/src/middlewares/fetch-middleware.js +1 -0
  14. package/dist/esm/src/middlewares/proxy-response-middleware.js +1 -1
  15. package/dist/esm/src/middlewares/retry-middleware.js +5 -0
  16. package/dist/esm/src/middlewares/timeout-middleware.js +6 -11
  17. package/dist/esm/src/types/keq-context.d.ts +17 -6
  18. package/dist/esm/src/types/keq-context.js +1 -1
  19. package/dist/esm/src/types/keq-events.d.ts +8 -0
  20. package/dist/esm/src/types/keq-events.js +1 -0
  21. package/dist/esm/src/types/keq-flow-control.d.ts +1 -1
  22. package/dist/esm/src/types/keq-global.d.ts +6 -0
  23. package/dist/esm/src/types/keq-global.js +1 -0
  24. package/dist/esm/src/types/keq-middleware.d.ts +2 -2
  25. package/dist/esm/src/types/keq-options.d.ts +6 -6
  26. package/dist/esm/src/types/keq-request-init.d.ts +1 -1
  27. package/dist/esm/src/types/keq-request.d.ts +5 -5
  28. package/dist/esm/src/types/keq-retry-delay.d.ts +1 -1
  29. package/dist/esm/src/types/keq-retry-on.d.ts +1 -1
  30. package/dist/esm/src/types/keq-route.d.ts +1 -1
  31. package/dist/umd/src/constant.d.ts +1 -0
  32. package/dist/umd/src/constant.js +2 -1
  33. package/dist/umd/src/core.d.ts +4 -1
  34. package/dist/umd/src/core.js +26 -2
  35. package/dist/umd/src/create-request.js +1 -1
  36. package/dist/umd/src/index.d.ts +12 -10
  37. package/dist/umd/src/is/is-url-search-params.js +3 -6
  38. package/dist/umd/src/keq.js +2 -4
  39. package/dist/umd/src/middlewares/abort-flow-control-middleware.js +11 -13
  40. package/dist/umd/src/middlewares/fetch-arguments-middleware.js +8 -2
  41. package/dist/umd/src/middlewares/fetch-middleware.js +1 -0
  42. package/dist/umd/src/middlewares/proxy-response-middleware.js +1 -1
  43. package/dist/umd/src/middlewares/retry-middleware.js +5 -0
  44. package/dist/umd/src/middlewares/timeout-middleware.js +6 -11
  45. package/dist/umd/src/types/keq-context.d.ts +17 -6
  46. package/dist/umd/src/types/keq-context.js +2 -2
  47. package/dist/umd/src/types/keq-events.d.ts +8 -0
  48. package/dist/umd/src/types/keq-events.js +12 -0
  49. package/dist/umd/src/types/keq-flow-control.d.ts +1 -1
  50. package/dist/umd/src/types/keq-global.d.ts +6 -0
  51. package/dist/umd/src/types/keq-global.js +12 -0
  52. package/dist/umd/src/types/keq-middleware.d.ts +2 -2
  53. package/dist/umd/src/types/keq-options.d.ts +6 -6
  54. package/dist/umd/src/types/keq-request-init.d.ts +1 -1
  55. package/dist/umd/src/types/keq-request.d.ts +5 -5
  56. package/dist/umd/src/types/keq-retry-delay.d.ts +1 -1
  57. package/dist/umd/src/types/keq-retry-on.d.ts +1 -1
  58. package/dist/umd/src/types/keq-route.d.ts +1 -1
  59. package/package.json +2 -1
  60. package/dist/esm/src/exception/file-expected.exception.d.ts +0 -4
  61. package/dist/esm/src/exception/file-expected.exception.js +0 -6
  62. package/dist/umd/src/exception/file-expected.exception.d.ts +0 -4
  63. package/dist/umd/src/exception/file-expected.exception.js +0 -20
package/.node-version ADDED
@@ -0,0 +1 @@
1
+ v20.13.1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,27 @@
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.6.0](https://github.com/keq-request/keq/compare/v2.5.5...v2.6.0) (2024-05-28)
6
+
7
+
8
+ ### Features
9
+
10
+ * use .on(eventName, listener) add event listener ([500ef14](https://github.com/keq-request/keq/commit/500ef140b513d614c3454d0e9023dd501e5d1ef6))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * esm import syntax ([c312146](https://github.com/keq-request/keq/commit/c312146ffeb456bcfb1e0e6e2f2a3c8c773e6003))
16
+ * the body is undeifned when send plain/text request ([ed24ba6](https://github.com/keq-request/keq/commit/ed24ba6f5ef3a565fb3eb6be496be09ed0fa40f9))
17
+
18
+ ## [2.5.5](https://github.com/keq-request/keq/compare/v2.5.4...v2.5.5) (2024-05-26)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * avoid conflicts between flowController and timeout middleware ([a075602](https://github.com/keq-request/keq/commit/a075602ed868812955001df7ed15f2351f899f33))
24
+ * retry timeout and flowControll not triggered ([846c884](https://github.com/keq-request/keq/commit/846c8845334f61fdca7a6cd3b718e135d23bfb18))
25
+
5
26
  ## [2.5.4](https://github.com/keq-request/keq/compare/v2.5.3...v2.5.4) (2024-05-23)
6
27
 
7
28
 
@@ -1,2 +1,3 @@
1
1
  export declare const OUTPUT_PROPERTY: unique symbol;
2
2
  export declare const NEXT_INVOKED_PROPERTY: unique symbol;
3
+ export declare const ABORT_PROPERTY: unique symbol;
@@ -1,2 +1,3 @@
1
1
  export const OUTPUT_PROPERTY = Symbol('outputProperty');
2
2
  export const NEXT_INVOKED_PROPERTY = Symbol('nextInvokedProperty');
3
+ export const ABORT_PROPERTY = Symbol('abortProperty');
@@ -2,12 +2,14 @@ import { URL } from 'whatwg-url';
2
2
  import type { KeqContextOptions, KeqRequestContext } from './types/keq-context.js';
3
3
  import type { KeqMiddleware } from './types/keq-middleware.js';
4
4
  import type { KeqRequestInit } from './types/keq-request-init.js';
5
+ import { KeqEvents, KeqListeners } from './types/keq-events.js';
5
6
  /**
6
7
  * @description Keq 核心 API,发送请求必要的原子化的API
7
8
  */
8
9
  export declare class Core<T> {
9
10
  private requestPromise?;
10
- protected requestContext: KeqRequestContext;
11
+ protected requestContext: Omit<KeqRequestContext, 'abort'>;
12
+ protected __listeners__: KeqListeners;
11
13
  protected __global__: Record<string, any>;
12
14
  protected __prepend_middlewares__: KeqMiddleware[];
13
15
  protected __append_middlewares__: KeqMiddleware[];
@@ -15,6 +17,7 @@ export declare class Core<T> {
15
17
  constructor(url: (URL | globalThis.URL), init: KeqRequestInit, global?: Record<string, any>);
16
18
  prependMiddlewares(...middlewares: KeqMiddleware[]): this;
17
19
  appendMiddlewares(...middlewares: KeqMiddleware[]): this;
20
+ on<K extends keyof KeqEvents>(event: K, listener: (data: KeqEvents[K]) => void): this;
18
21
  private run;
19
22
  end(): Promise<T>;
20
23
  /**
@@ -1,15 +1,17 @@
1
1
  import { URL } from 'whatwg-url';
2
2
  import { Exception } from "./exception/exception.js";
3
3
  import { clone } from "./util/clone.js";
4
- import { NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from './constant.js';
4
+ import { ABORT_PROPERTY, NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from './constant.js';
5
5
  import { composeMiddleware } from './util/compose-middleware.js';
6
6
  import { shadowClone } from './util/shadow-clone.js';
7
+ import mitt from 'mitt';
7
8
  /**
8
9
  * @description Keq 核心 API,发送请求必要的原子化的API
9
10
  */
10
11
  export class Core {
11
12
  requestPromise;
12
13
  requestContext;
14
+ __listeners__ = {};
13
15
  __global__;
14
16
  __prepend_middlewares__ = [];
15
17
  __append_middlewares__ = [];
@@ -36,6 +38,11 @@ export class Core {
36
38
  this.__append_middlewares__.unshift(...middlewares);
37
39
  return this;
38
40
  }
41
+ on(event, listener) {
42
+ this.__listeners__[event] = this.__listeners__[event] || [];
43
+ this.__listeners__[event].push(listener);
44
+ return this;
45
+ }
39
46
  async run() {
40
47
  const headers = new Headers();
41
48
  for (const [key, value] of this.requestContext.headers.entries()) {
@@ -55,15 +62,22 @@ export class Core {
55
62
  redirect: this.requestContext.redirect,
56
63
  referrer: this.requestContext.referrer,
57
64
  referrerPolicy: this.requestContext.referrerPolicy,
58
- signal: this.requestContext.signal,
59
65
  };
60
66
  const options = shadowClone(this.__options__);
67
+ const emitter = mitt();
68
+ for (const eventName in this.__listeners__) {
69
+ const listeners = this.__listeners__[eventName];
70
+ for (const listener of listeners) {
71
+ emitter.on(eventName, listener);
72
+ }
73
+ }
61
74
  const ctx = {
62
75
  [NEXT_INVOKED_PROPERTY]: {
63
76
  finished: false,
64
77
  entryNextTimes: 0,
65
78
  outNextTimes: 0,
66
79
  },
80
+ emitter,
67
81
  request: requestContext,
68
82
  options,
69
83
  global: this.__global__,
@@ -73,6 +87,13 @@ export class Core {
73
87
  set output(value) {
74
88
  this[OUTPUT_PROPERTY] = value;
75
89
  },
90
+ [ABORT_PROPERTY]: undefined,
91
+ abort(reason) {
92
+ const abortController = this[ABORT_PROPERTY];
93
+ if (abortController) {
94
+ abortController.abort(reason);
95
+ }
96
+ },
76
97
  };
77
98
  const middleware = composeMiddleware([...this.__prepend_middlewares__, ...this.__append_middlewares__]);
78
99
  // eslint-disable-next-line @typescript-eslint/no-empty-function
@@ -21,12 +21,12 @@ export function createRequest(options) {
21
21
  }
22
22
  }
23
23
  const appendMiddlewares = options?.initMiddlewares ? [...options.initMiddlewares] : [
24
+ retryMiddleware(),
24
25
  serialFlowControlMiddleware(),
25
26
  abortFlowControlMiddleware(),
26
27
  timeoutMiddleware(),
27
28
  proxyResponseMiddleware(),
28
29
  fetchArgumentsMiddleware(),
29
- retryMiddleware(),
30
30
  fetchMiddleware(),
31
31
  ];
32
32
  const prependMiddlewares = [];
@@ -3,16 +3,18 @@ export { Keq } from './keq.js';
3
3
  export { request } from './request.js';
4
4
  export { composeMiddleware } from './util/compose-middleware.js';
5
5
  export { composeRoute } from './util/compose-route.js';
6
- export { KeqContext, KeqContextOptions } from './types/keq-context.js';
7
- export { KeqMiddleware } from './types/keq-middleware.js';
8
- export { KeqNext } from './types/keq-next.js';
9
- export { KeqOptions } from './types/keq-options.js';
10
- export { KeqRequestBody } from './types/keq-request-body.js';
11
- export { KeqRequestInit } from './types/keq-request-init.js';
12
- export { KeqRequest } from './types/keq-request.js';
13
- export { KeqRetryDelay } from './types/keq-retry-delay.js';
14
- export { KeqRetryOn } from './types/keq-retry-on.js';
15
- export { KeqRoute } from './types/keq-route.js';
6
+ export type { KeqContext, KeqContextOptions } from './types/keq-context.js';
7
+ export type { KeqMiddleware } from './types/keq-middleware.js';
8
+ export type { KeqNext } from './types/keq-next.js';
9
+ export type { KeqOptions } from './types/keq-options.js';
10
+ export type { KeqRequestBody } from './types/keq-request-body.js';
11
+ export type { KeqRequestInit } from './types/keq-request-init.js';
12
+ export type { KeqRequest } from './types/keq-request.js';
13
+ export type { KeqRetryDelay } from './types/keq-retry-delay.js';
14
+ export type { KeqRetryOn } from './types/keq-retry-on.js';
15
+ export type { KeqRoute } from './types/keq-route.js';
16
+ export type { KeqGlobal } from './types/keq-global.js';
17
+ export type { KeqEvents } from './types/keq-events.js';
16
18
  export { keqHostRoute } from './router/keq-host-route.js';
17
19
  export { keqLocationRoute } from './router/keq-location-route.js';
18
20
  export { keqMethodRoute } from './router/keq-method-route.js';
@@ -3,10 +3,10 @@ import { isObject } from './is-object.js';
3
3
  export function isUrlSearchParams(obj) {
4
4
  if (obj instanceof URLSearchParams)
5
5
  return true;
6
- if (isObject(obj) &&
6
+ return (isObject(obj) &&
7
7
  isFunction(obj.append) &&
8
8
  isFunction(obj.delete) &&
9
- isFunction(obj.entrie) &&
9
+ isFunction(obj.entries) &&
10
10
  isFunction(obj.forEac) &&
11
11
  isFunction(obj.get) &&
12
12
  isFunction(obj.getAll) &&
@@ -15,8 +15,5 @@ export function isUrlSearchParams(obj) {
15
15
  isFunction(obj.set) &&
16
16
  isFunction(obj.values) &&
17
17
  isFunction(obj.sort) &&
18
- isFunction(obj.toStri)) {
19
- return true;
20
- }
21
- return false;
18
+ isFunction(obj.toString));
22
19
  }
@@ -168,12 +168,10 @@ export class Keq extends Core {
168
168
  * @param retryDelay Initial value used to calculate the retry in milliseconds (This is still randomized following the randomization factor)
169
169
  * @param retryCallback Will be called after request failed
170
170
  */
171
- retry(retryTimes, retryDelay, retryOn) {
171
+ retry(retryTimes, retryDelay = 0, retryOn = (attempt, error) => !!error) {
172
172
  this.option('retryTimes', retryTimes);
173
173
  this.option('retryDelay', retryDelay);
174
- if (retryOn !== undefined) {
175
- this.option('retryOn', retryOn);
176
- }
174
+ this.option('retryOn', retryOn);
177
175
  return this;
178
176
  }
179
177
  redirect(mod) {
@@ -4,23 +4,21 @@ export function abortFlowControlMiddleware() {
4
4
  await next();
5
5
  return;
6
6
  }
7
- if (ctx.request.signal) {
8
- console.warn('[keq] request signal had be set manual, abort follow control will not take effect');
9
- await next();
10
- return;
11
- }
12
7
  const { signal } = ctx.options.flowControl;
13
8
  const key = typeof signal === 'string' ? signal : signal(ctx);
14
9
  if (!ctx.global.abortFlowControl)
15
10
  ctx.global.abortFlowControl = {};
16
- if (ctx.global.abortFlowControl[key]) {
17
- const abortController = ctx.global.abortFlowControl[key];
18
- abortController.abort(new DOMException('The previous request was not completed, so keq flowControl abort this request.', 'AbortError'));
11
+ const abort = ctx.global.abortFlowControl[key];
12
+ if (abort) {
13
+ const reason = new DOMException('The previous request was not completed, so keq flowControl abort this request.', 'AbortError');
14
+ abort(reason);
15
+ }
16
+ ctx.global.abortFlowControl[key] = ctx.abort.bind(ctx);
17
+ try {
18
+ await next();
19
+ }
20
+ finally {
21
+ ctx.global.abortFlowControl[key] = undefined;
19
22
  }
20
- const abortController = new AbortController();
21
- ctx.global.abortFlowControl[key] = abortController;
22
- ctx.request.signal = abortController.signal;
23
- await next();
24
- ctx.global.abortFlowControl[key] = undefined;
25
23
  };
26
24
  }
@@ -1,6 +1,7 @@
1
1
  import { URL } from 'whatwg-url';
2
2
  import { Exception } from "../exception/exception.js";
3
3
  import { compilePathnameTemplate } from "../util/compile-pathname-template.js";
4
+ import { ABORT_PROPERTY } from "../constant.js";
4
5
  function compileUrl(obj, routeParams) {
5
6
  const url = new URL(typeof obj === 'string' ? obj : obj.href);
6
7
  try {
@@ -62,6 +63,9 @@ function compileBody(ctx) {
62
63
  request.headers.delete('content-type');
63
64
  return form;
64
65
  }
66
+ if (body instanceof Buffer)
67
+ return body;
68
+ return String(body);
65
69
  }
66
70
  export function fetchArgumentsMiddleware() {
67
71
  return async function fetchArgumentsMiddleware(ctx, next) {
@@ -70,6 +74,8 @@ export function fetchArgumentsMiddleware() {
70
74
  if (!request.headers.has('Content-Type') && request.body) {
71
75
  request.headers.set('Content-Type', inferContentTypeByBody(ctx.request.body));
72
76
  }
77
+ const abortController = new AbortController();
78
+ ctx[ABORT_PROPERTY] = abortController;
73
79
  const requestInit = {
74
80
  method: request.method.toUpperCase(),
75
81
  headers: request.headers,
@@ -82,7 +88,7 @@ export function fetchArgumentsMiddleware() {
82
88
  redirect: request.redirect,
83
89
  referrer: request.referrer,
84
90
  referrerPolicy: request.referrerPolicy,
85
- signal: request.signal,
91
+ signal: abortController.signal,
86
92
  };
87
93
  ctx.fetchArguments = [url, requestInit];
88
94
  await next();
@@ -8,6 +8,7 @@ export function fetchMiddleware() {
8
8
  if (!fetchArguments) {
9
9
  throw new Exception('fetchArguments is required');
10
10
  }
11
+ ctx.emitter.emit('fetch', ctx);
11
12
  const fetch = ctx.options.fetchAPI || globalThis.fetch;
12
13
  const response = await fetch(...fetchArguments);
13
14
  ctx.res = response;
@@ -2,7 +2,7 @@ export function proxyResponseMiddleware() {
2
2
  return async function proxyResponseMiddleware(ctx, next) {
3
3
  await next();
4
4
  const res = ctx.res;
5
- if (res && !('response' in ctx)) {
5
+ if (res) {
6
6
  ctx.response = new Proxy(res, {
7
7
  get(res, prop) {
8
8
  if (typeof prop === 'string') {
@@ -29,6 +29,9 @@ export function retryMiddleware() {
29
29
  for (let i = 0; i < retryTimes; i++) {
30
30
  let err = null;
31
31
  try {
32
+ ctx.fetchArguments = undefined;
33
+ ctx.response = undefined;
34
+ ctx.req = undefined;
32
35
  ctx[NEXT_INVOKED_PROPERTY].entryNextTimes = 0;
33
36
  ctx[NEXT_INVOKED_PROPERTY].outNextTimes = 0;
34
37
  await next();
@@ -47,6 +50,8 @@ export function retryMiddleware() {
47
50
  break;
48
51
  }
49
52
  const delay = await retryDelay(i, err, ctx);
53
+ ctx.retry = { attempt: i, error: err, delay };
54
+ ctx.emitter.emit('retry', ctx);
50
55
  if (delay > 0)
51
56
  await sleep(delay);
52
57
  }
@@ -4,18 +4,13 @@ export function timeoutMiddleware() {
4
4
  await next();
5
5
  return;
6
6
  }
7
- if (ctx.request.signal) {
8
- console.warn('[keq] request signal had be set manual, abort follow control will not take effect');
9
- await next();
10
- return;
11
- }
12
- const timeoutSignal = new AbortController();
13
- ctx.request.signal = timeoutSignal.signal;
14
7
  const millisecond = ctx.options.timeout.millisecond;
15
- setTimeout(() => {
16
- const err = new DOMException(`keq request timeout(${millisecond}ms)`, 'AbortError');
17
- timeoutSignal.abort(err);
18
- }, millisecond);
8
+ ctx.emitter.on('fetch', (ctx) => {
9
+ setTimeout(() => {
10
+ const err = new DOMException(`keq request timeout(${millisecond}ms)`, 'AbortError');
11
+ ctx.abort(err);
12
+ }, millisecond);
13
+ });
19
14
  await next();
20
15
  };
21
16
  }
@@ -1,8 +1,11 @@
1
+ import { Emitter } from 'mitt';
1
2
  import { URL } from 'whatwg-url';
2
- import { NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from "../constant";
3
- import { KeqRequestBody } from './keq-request-body';
4
- import { KeqRequestMethod } from './keq-request-method';
5
- import { KeqOptionsParameter } from './keq-options.js';
3
+ import { ABORT_PROPERTY, NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from "../constant.js";
4
+ import type { KeqRequestBody } from './keq-request-body.js';
5
+ import type { KeqRequestMethod } from './keq-request-method.js';
6
+ import type { KeqOptionsParameter } from './keq-options.js';
7
+ import type { KeqEvents } from './keq-events.js';
8
+ import type { KeqGlobal } from './keq-global.js';
6
9
  export interface KeqContextOptions extends KeqOptionsParameter {
7
10
  [key: string]: any;
8
11
  }
@@ -20,7 +23,6 @@ export interface KeqRequestContext {
20
23
  redirect?: RequestRedirect;
21
24
  referrer?: string;
22
25
  referrerPolicy?: ReferrerPolicy;
23
- signal?: AbortSignal | null;
24
26
  }
25
27
  export interface KeqContext {
26
28
  /**
@@ -34,6 +36,9 @@ export interface KeqContext {
34
36
  entryNextTimes: number;
35
37
  outNextTimes: number;
36
38
  };
39
+ [ABORT_PROPERTY]?: AbortController;
40
+ abort: (reason: any) => void;
41
+ emitter: Emitter<Omit<KeqEvents, never>>;
37
42
  options: KeqContextOptions;
38
43
  /**
39
44
  * Fetch API Arguments
@@ -51,7 +56,13 @@ export interface KeqContext {
51
56
  output: any;
52
57
  [OUTPUT_PROPERTY]?: any;
53
58
  /** share data between requests */
54
- global: Record<string, any>;
59
+ global: KeqGlobal;
60
+ /** retry information, undefined is no retry */
61
+ retry?: {
62
+ attempt: number;
63
+ error: unknown | null;
64
+ delay: number;
65
+ };
55
66
  /** extends by middleware */
56
67
  [key: string]: any;
57
68
  }
@@ -1 +1 @@
1
- import { NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from "../constant";
1
+ import { ABORT_PROPERTY, NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from "../constant.js";
@@ -0,0 +1,8 @@
1
+ import type { KeqContext } from './keq-context.js';
2
+ export interface KeqEvents {
3
+ fetch: KeqContext;
4
+ retry: KeqContext;
5
+ }
6
+ export type KeqListeners = {
7
+ [K in keyof KeqEvents]?: ((data: KeqEvents[K]) => void)[];
8
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
- import { KeqContext } from './keq-context.js';
1
+ import type { KeqContext } from './keq-context.js';
2
2
  export interface KeqFlowControl {
3
3
  mode: 'abort' | 'serial';
4
4
  signal: string | ((ctx: KeqContext) => string);
@@ -0,0 +1,6 @@
1
+ import type { queueAsPromised } from 'fastq';
2
+ import type { KeqNext } from './keq-next.js';
3
+ export interface KeqGlobal {
4
+ abortFlowControl?: Record<string, ((reason: any) => void) | undefined>;
5
+ serialFlowControl?: Record<string, queueAsPromised<KeqNext, void>>;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,3 @@
1
- import { KeqContext } from './keq-context';
2
- import { KeqNext } from './keq-next';
1
+ import type { KeqContext } from './keq-context.js';
2
+ import type { KeqNext } from './keq-next.js';
3
3
  export type KeqMiddleware = (ctx: KeqContext, next: KeqNext) => Promise<void>;
@@ -1,9 +1,9 @@
1
- import { Keq } from "../keq.js";
2
- import { KeqFlowControl } from './keq-flow-control.js';
3
- import { KeqResolveMethod } from './keq-resolve-with-mode.js';
4
- import { KeqRetryDelay } from './keq-retry-delay';
5
- import { KeqRetryOn } from './keq-retry-on';
6
- import { KeqTimeout } from './keq-timeout.js';
1
+ import type { Keq } from "../keq.js";
2
+ import type { KeqFlowControl } from './keq-flow-control.js';
3
+ import type { KeqResolveMethod } from './keq-resolve-with-mode.js';
4
+ import type { KeqRetryDelay } from './keq-retry-delay.js';
5
+ import type { KeqRetryOn } from './keq-retry-on.js';
6
+ import type { KeqTimeout } from './keq-timeout.js';
7
7
  export interface KeqOptions<T> {
8
8
  /**
9
9
  * replace the default fetch api
@@ -1,2 +1,2 @@
1
- import { KeqRequestContext } from './keq-context';
1
+ import type { KeqRequestContext } from './keq-context.js';
2
2
  export type KeqRequestInit = Partial<Omit<KeqRequestContext, 'url'>>;
@@ -1,8 +1,8 @@
1
- import { URL } from 'whatwg-url';
2
- import { Keq } from "../keq.js";
3
- import { KeqRouter } from "../router/keq-router.js";
4
- import { KeqMiddleware } from './keq-middleware';
5
- import { KeqRequestInit } from './keq-request-init';
1
+ import type { URL } from 'whatwg-url';
2
+ import type { KeqRouter } from "../router/keq-router.js";
3
+ import type { Keq } from "../keq.js";
4
+ import type { KeqMiddleware } from './keq-middleware.js';
5
+ import type { KeqRequestInit } from './keq-request-init.js';
6
6
  type KeqRequestFn = <T = any>(url: string | URL | globalThis.URL) => Keq<T>;
7
7
  type GlobalURL = globalThis.URL;
8
8
  export interface KeqRequest {
@@ -1,2 +1,2 @@
1
- import { KeqContext } from './keq-context';
1
+ import type { KeqContext } from './keq-context';
2
2
  export type KeqRetryDelay = number | ((attempt: number, error: unknown | null, ctx: KeqContext) => number | Promise<number>);
@@ -1,2 +1,2 @@
1
- import { KeqContext } from './keq-context';
1
+ import type { KeqContext } from './keq-context.js';
2
2
  export type KeqRetryOn = (attempt: number, error: unknown | null, ctx: KeqContext) => (boolean | Promise<boolean>);
@@ -1,2 +1,2 @@
1
- import { KeqContext } from './keq-context.js';
1
+ import type { KeqContext } from './keq-context.js';
2
2
  export type KeqRoute = (ctx: KeqContext) => Promise<boolean> | boolean;
@@ -1,2 +1,3 @@
1
1
  export declare const OUTPUT_PROPERTY: unique symbol;
2
2
  export declare const NEXT_INVOKED_PROPERTY: unique symbol;
3
+ export declare const ABORT_PROPERTY: unique symbol;
@@ -9,7 +9,8 @@
9
9
  })(function (require, exports) {
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.NEXT_INVOKED_PROPERTY = exports.OUTPUT_PROPERTY = void 0;
12
+ exports.ABORT_PROPERTY = exports.NEXT_INVOKED_PROPERTY = exports.OUTPUT_PROPERTY = void 0;
13
13
  exports.OUTPUT_PROPERTY = Symbol('outputProperty');
14
14
  exports.NEXT_INVOKED_PROPERTY = Symbol('nextInvokedProperty');
15
+ exports.ABORT_PROPERTY = Symbol('abortProperty');
15
16
  });
@@ -2,12 +2,14 @@ import { URL } from 'whatwg-url';
2
2
  import type { KeqContextOptions, KeqRequestContext } from './types/keq-context.js';
3
3
  import type { KeqMiddleware } from './types/keq-middleware.js';
4
4
  import type { KeqRequestInit } from './types/keq-request-init.js';
5
+ import { KeqEvents, KeqListeners } from './types/keq-events.js';
5
6
  /**
6
7
  * @description Keq 核心 API,发送请求必要的原子化的API
7
8
  */
8
9
  export declare class Core<T> {
9
10
  private requestPromise?;
10
- protected requestContext: KeqRequestContext;
11
+ protected requestContext: Omit<KeqRequestContext, 'abort'>;
12
+ protected __listeners__: KeqListeners;
11
13
  protected __global__: Record<string, any>;
12
14
  protected __prepend_middlewares__: KeqMiddleware[];
13
15
  protected __append_middlewares__: KeqMiddleware[];
@@ -15,6 +17,7 @@ export declare class Core<T> {
15
17
  constructor(url: (URL | globalThis.URL), init: KeqRequestInit, global?: Record<string, any>);
16
18
  prependMiddlewares(...middlewares: KeqMiddleware[]): this;
17
19
  appendMiddlewares(...middlewares: KeqMiddleware[]): this;
20
+ on<K extends keyof KeqEvents>(event: K, listener: (data: KeqEvents[K]) => void): this;
18
21
  private run;
19
22
  end(): Promise<T>;
20
23
  /**
@@ -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", "whatwg-url", "./exception/exception.js", "./util/clone.js", "./constant.js", "./util/compose-middleware.js", "./util/shadow-clone.js"], factory);
10
+ define(["require", "exports", "whatwg-url", "./exception/exception.js", "./util/clone.js", "./constant.js", "./util/compose-middleware.js", "./util/shadow-clone.js", "mitt"], factory);
8
11
  }
9
12
  })(function (require, exports) {
10
13
  "use strict";
@@ -16,12 +19,14 @@
16
19
  const constant_js_1 = require("./constant.js");
17
20
  const compose_middleware_js_1 = require("./util/compose-middleware.js");
18
21
  const shadow_clone_js_1 = require("./util/shadow-clone.js");
22
+ const mitt_1 = __importDefault(require("mitt"));
19
23
  /**
20
24
  * @description Keq 核心 API,发送请求必要的原子化的API
21
25
  */
22
26
  class Core {
23
27
  requestPromise;
24
28
  requestContext;
29
+ __listeners__ = {};
25
30
  __global__;
26
31
  __prepend_middlewares__ = [];
27
32
  __append_middlewares__ = [];
@@ -48,6 +53,11 @@
48
53
  this.__append_middlewares__.unshift(...middlewares);
49
54
  return this;
50
55
  }
56
+ on(event, listener) {
57
+ this.__listeners__[event] = this.__listeners__[event] || [];
58
+ this.__listeners__[event].push(listener);
59
+ return this;
60
+ }
51
61
  async run() {
52
62
  const headers = new Headers();
53
63
  for (const [key, value] of this.requestContext.headers.entries()) {
@@ -67,15 +77,22 @@
67
77
  redirect: this.requestContext.redirect,
68
78
  referrer: this.requestContext.referrer,
69
79
  referrerPolicy: this.requestContext.referrerPolicy,
70
- signal: this.requestContext.signal,
71
80
  };
72
81
  const options = (0, shadow_clone_js_1.shadowClone)(this.__options__);
82
+ const emitter = (0, mitt_1.default)();
83
+ for (const eventName in this.__listeners__) {
84
+ const listeners = this.__listeners__[eventName];
85
+ for (const listener of listeners) {
86
+ emitter.on(eventName, listener);
87
+ }
88
+ }
73
89
  const ctx = {
74
90
  [constant_js_1.NEXT_INVOKED_PROPERTY]: {
75
91
  finished: false,
76
92
  entryNextTimes: 0,
77
93
  outNextTimes: 0,
78
94
  },
95
+ emitter,
79
96
  request: requestContext,
80
97
  options,
81
98
  global: this.__global__,
@@ -85,6 +102,13 @@
85
102
  set output(value) {
86
103
  this[constant_js_1.OUTPUT_PROPERTY] = value;
87
104
  },
105
+ [constant_js_1.ABORT_PROPERTY]: undefined,
106
+ abort(reason) {
107
+ const abortController = this[constant_js_1.ABORT_PROPERTY];
108
+ if (abortController) {
109
+ abortController.abort(reason);
110
+ }
111
+ },
88
112
  };
89
113
  const middleware = (0, compose_middleware_js_1.composeMiddleware)([...this.__prepend_middlewares__, ...this.__append_middlewares__]);
90
114
  // eslint-disable-next-line @typescript-eslint/no-empty-function
@@ -33,12 +33,12 @@
33
33
  }
34
34
  }
35
35
  const appendMiddlewares = options?.initMiddlewares ? [...options.initMiddlewares] : [
36
+ (0, retry_middleware_js_1.retryMiddleware)(),
36
37
  (0, serial_flow_control_middleware_js_1.serialFlowControlMiddleware)(),
37
38
  (0, abort_flow_control_middleware_js_1.abortFlowControlMiddleware)(),
38
39
  (0, timeout_middleware_js_1.timeoutMiddleware)(),
39
40
  (0, proxy_response_middleware_js_1.proxyResponseMiddleware)(),
40
41
  (0, fetch_arguments_middleware_js_1.fetchArgumentsMiddleware)(),
41
- (0, retry_middleware_js_1.retryMiddleware)(),
42
42
  (0, fetch_middleware_js_1.fetchMiddleware)(),
43
43
  ];
44
44
  const prependMiddlewares = [];
@@ -3,16 +3,18 @@ export { Keq } from './keq.js';
3
3
  export { request } from './request.js';
4
4
  export { composeMiddleware } from './util/compose-middleware.js';
5
5
  export { composeRoute } from './util/compose-route.js';
6
- export { KeqContext, KeqContextOptions } from './types/keq-context.js';
7
- export { KeqMiddleware } from './types/keq-middleware.js';
8
- export { KeqNext } from './types/keq-next.js';
9
- export { KeqOptions } from './types/keq-options.js';
10
- export { KeqRequestBody } from './types/keq-request-body.js';
11
- export { KeqRequestInit } from './types/keq-request-init.js';
12
- export { KeqRequest } from './types/keq-request.js';
13
- export { KeqRetryDelay } from './types/keq-retry-delay.js';
14
- export { KeqRetryOn } from './types/keq-retry-on.js';
15
- export { KeqRoute } from './types/keq-route.js';
6
+ export type { KeqContext, KeqContextOptions } from './types/keq-context.js';
7
+ export type { KeqMiddleware } from './types/keq-middleware.js';
8
+ export type { KeqNext } from './types/keq-next.js';
9
+ export type { KeqOptions } from './types/keq-options.js';
10
+ export type { KeqRequestBody } from './types/keq-request-body.js';
11
+ export type { KeqRequestInit } from './types/keq-request-init.js';
12
+ export type { KeqRequest } from './types/keq-request.js';
13
+ export type { KeqRetryDelay } from './types/keq-retry-delay.js';
14
+ export type { KeqRetryOn } from './types/keq-retry-on.js';
15
+ export type { KeqRoute } from './types/keq-route.js';
16
+ export type { KeqGlobal } from './types/keq-global.js';
17
+ export type { KeqEvents } from './types/keq-events.js';
16
18
  export { keqHostRoute } from './router/keq-host-route.js';
17
19
  export { keqLocationRoute } from './router/keq-location-route.js';
18
20
  export { keqMethodRoute } from './router/keq-method-route.js';
@@ -15,10 +15,10 @@
15
15
  function isUrlSearchParams(obj) {
16
16
  if (obj instanceof URLSearchParams)
17
17
  return true;
18
- if ((0, is_object_js_1.isObject)(obj) &&
18
+ return ((0, is_object_js_1.isObject)(obj) &&
19
19
  (0, is_function_js_1.isFunction)(obj.append) &&
20
20
  (0, is_function_js_1.isFunction)(obj.delete) &&
21
- (0, is_function_js_1.isFunction)(obj.entrie) &&
21
+ (0, is_function_js_1.isFunction)(obj.entries) &&
22
22
  (0, is_function_js_1.isFunction)(obj.forEac) &&
23
23
  (0, is_function_js_1.isFunction)(obj.get) &&
24
24
  (0, is_function_js_1.isFunction)(obj.getAll) &&
@@ -27,10 +27,7 @@
27
27
  (0, is_function_js_1.isFunction)(obj.set) &&
28
28
  (0, is_function_js_1.isFunction)(obj.values) &&
29
29
  (0, is_function_js_1.isFunction)(obj.sort) &&
30
- (0, is_function_js_1.isFunction)(obj.toStri)) {
31
- return true;
32
- }
33
- return false;
30
+ (0, is_function_js_1.isFunction)(obj.toString));
34
31
  }
35
32
  exports.isUrlSearchParams = isUrlSearchParams;
36
33
  });
@@ -180,12 +180,10 @@
180
180
  * @param retryDelay Initial value used to calculate the retry in milliseconds (This is still randomized following the randomization factor)
181
181
  * @param retryCallback Will be called after request failed
182
182
  */
183
- retry(retryTimes, retryDelay, retryOn) {
183
+ retry(retryTimes, retryDelay = 0, retryOn = (attempt, error) => !!error) {
184
184
  this.option('retryTimes', retryTimes);
185
185
  this.option('retryDelay', retryDelay);
186
- if (retryOn !== undefined) {
187
- this.option('retryOn', retryOn);
188
- }
186
+ this.option('retryOn', retryOn);
189
187
  return this;
190
188
  }
191
189
  redirect(mod) {
@@ -16,24 +16,22 @@
16
16
  await next();
17
17
  return;
18
18
  }
19
- if (ctx.request.signal) {
20
- console.warn('[keq] request signal had be set manual, abort follow control will not take effect');
21
- await next();
22
- return;
23
- }
24
19
  const { signal } = ctx.options.flowControl;
25
20
  const key = typeof signal === 'string' ? signal : signal(ctx);
26
21
  if (!ctx.global.abortFlowControl)
27
22
  ctx.global.abortFlowControl = {};
28
- if (ctx.global.abortFlowControl[key]) {
29
- const abortController = ctx.global.abortFlowControl[key];
30
- abortController.abort(new DOMException('The previous request was not completed, so keq flowControl abort this request.', 'AbortError'));
23
+ const abort = ctx.global.abortFlowControl[key];
24
+ if (abort) {
25
+ const reason = new DOMException('The previous request was not completed, so keq flowControl abort this request.', 'AbortError');
26
+ abort(reason);
27
+ }
28
+ ctx.global.abortFlowControl[key] = ctx.abort.bind(ctx);
29
+ try {
30
+ await next();
31
+ }
32
+ finally {
33
+ ctx.global.abortFlowControl[key] = undefined;
31
34
  }
32
- const abortController = new AbortController();
33
- ctx.global.abortFlowControl[key] = abortController;
34
- ctx.request.signal = abortController.signal;
35
- await next();
36
- ctx.global.abortFlowControl[key] = undefined;
37
35
  };
38
36
  }
39
37
  exports.abortFlowControlMiddleware = abortFlowControlMiddleware;
@@ -4,7 +4,7 @@
4
4
  if (v !== undefined) module.exports = v;
5
5
  }
6
6
  else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports", "whatwg-url", "../exception/exception.js", "../util/compile-pathname-template.js"], factory);
7
+ define(["require", "exports", "whatwg-url", "../exception/exception.js", "../util/compile-pathname-template.js", "../constant.js"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
@@ -13,6 +13,7 @@
13
13
  const whatwg_url_1 = require("whatwg-url");
14
14
  const exception_js_1 = require("../exception/exception.js");
15
15
  const compile_pathname_template_js_1 = require("../util/compile-pathname-template.js");
16
+ const constant_js_1 = require("../constant.js");
16
17
  function compileUrl(obj, routeParams) {
17
18
  const url = new whatwg_url_1.URL(typeof obj === 'string' ? obj : obj.href);
18
19
  try {
@@ -74,6 +75,9 @@
74
75
  request.headers.delete('content-type');
75
76
  return form;
76
77
  }
78
+ if (body instanceof Buffer)
79
+ return body;
80
+ return String(body);
77
81
  }
78
82
  function fetchArgumentsMiddleware() {
79
83
  return async function fetchArgumentsMiddleware(ctx, next) {
@@ -82,6 +86,8 @@
82
86
  if (!request.headers.has('Content-Type') && request.body) {
83
87
  request.headers.set('Content-Type', inferContentTypeByBody(ctx.request.body));
84
88
  }
89
+ const abortController = new AbortController();
90
+ ctx[constant_js_1.ABORT_PROPERTY] = abortController;
85
91
  const requestInit = {
86
92
  method: request.method.toUpperCase(),
87
93
  headers: request.headers,
@@ -94,7 +100,7 @@
94
100
  redirect: request.redirect,
95
101
  referrer: request.referrer,
96
102
  referrerPolicy: request.referrerPolicy,
97
- signal: request.signal,
103
+ signal: abortController.signal,
98
104
  };
99
105
  ctx.fetchArguments = [url, requestInit];
100
106
  await next();
@@ -20,6 +20,7 @@
20
20
  if (!fetchArguments) {
21
21
  throw new exception_js_1.Exception('fetchArguments is required');
22
22
  }
23
+ ctx.emitter.emit('fetch', ctx);
23
24
  const fetch = ctx.options.fetchAPI || globalThis.fetch;
24
25
  const response = await fetch(...fetchArguments);
25
26
  ctx.res = response;
@@ -14,7 +14,7 @@
14
14
  return async function proxyResponseMiddleware(ctx, next) {
15
15
  await next();
16
16
  const res = ctx.res;
17
- if (res && !('response' in ctx)) {
17
+ if (res) {
18
18
  ctx.response = new Proxy(res, {
19
19
  get(res, prop) {
20
20
  if (typeof prop === 'string') {
@@ -41,6 +41,9 @@
41
41
  for (let i = 0; i < retryTimes; i++) {
42
42
  let err = null;
43
43
  try {
44
+ ctx.fetchArguments = undefined;
45
+ ctx.response = undefined;
46
+ ctx.req = undefined;
44
47
  ctx[constant_js_1.NEXT_INVOKED_PROPERTY].entryNextTimes = 0;
45
48
  ctx[constant_js_1.NEXT_INVOKED_PROPERTY].outNextTimes = 0;
46
49
  await next();
@@ -59,6 +62,8 @@
59
62
  break;
60
63
  }
61
64
  const delay = await retryDelay(i, err, ctx);
65
+ ctx.retry = { attempt: i, error: err, delay };
66
+ ctx.emitter.emit('retry', ctx);
62
67
  if (delay > 0)
63
68
  await sleep(delay);
64
69
  }
@@ -16,18 +16,13 @@
16
16
  await next();
17
17
  return;
18
18
  }
19
- if (ctx.request.signal) {
20
- console.warn('[keq] request signal had be set manual, abort follow control will not take effect');
21
- await next();
22
- return;
23
- }
24
- const timeoutSignal = new AbortController();
25
- ctx.request.signal = timeoutSignal.signal;
26
19
  const millisecond = ctx.options.timeout.millisecond;
27
- setTimeout(() => {
28
- const err = new DOMException(`keq request timeout(${millisecond}ms)`, 'AbortError');
29
- timeoutSignal.abort(err);
30
- }, millisecond);
20
+ ctx.emitter.on('fetch', (ctx) => {
21
+ setTimeout(() => {
22
+ const err = new DOMException(`keq request timeout(${millisecond}ms)`, 'AbortError');
23
+ ctx.abort(err);
24
+ }, millisecond);
25
+ });
31
26
  await next();
32
27
  };
33
28
  }
@@ -1,8 +1,11 @@
1
+ import { Emitter } from 'mitt';
1
2
  import { URL } from 'whatwg-url';
2
- import { NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from "../constant";
3
- import { KeqRequestBody } from './keq-request-body';
4
- import { KeqRequestMethod } from './keq-request-method';
5
- import { KeqOptionsParameter } from './keq-options.js';
3
+ import { ABORT_PROPERTY, NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from "../constant.js";
4
+ import type { KeqRequestBody } from './keq-request-body.js';
5
+ import type { KeqRequestMethod } from './keq-request-method.js';
6
+ import type { KeqOptionsParameter } from './keq-options.js';
7
+ import type { KeqEvents } from './keq-events.js';
8
+ import type { KeqGlobal } from './keq-global.js';
6
9
  export interface KeqContextOptions extends KeqOptionsParameter {
7
10
  [key: string]: any;
8
11
  }
@@ -20,7 +23,6 @@ export interface KeqRequestContext {
20
23
  redirect?: RequestRedirect;
21
24
  referrer?: string;
22
25
  referrerPolicy?: ReferrerPolicy;
23
- signal?: AbortSignal | null;
24
26
  }
25
27
  export interface KeqContext {
26
28
  /**
@@ -34,6 +36,9 @@ export interface KeqContext {
34
36
  entryNextTimes: number;
35
37
  outNextTimes: number;
36
38
  };
39
+ [ABORT_PROPERTY]?: AbortController;
40
+ abort: (reason: any) => void;
41
+ emitter: Emitter<Omit<KeqEvents, never>>;
37
42
  options: KeqContextOptions;
38
43
  /**
39
44
  * Fetch API Arguments
@@ -51,7 +56,13 @@ export interface KeqContext {
51
56
  output: any;
52
57
  [OUTPUT_PROPERTY]?: any;
53
58
  /** share data between requests */
54
- global: Record<string, any>;
59
+ global: KeqGlobal;
60
+ /** retry information, undefined is no retry */
61
+ retry?: {
62
+ attempt: number;
63
+ error: unknown | null;
64
+ delay: number;
65
+ };
55
66
  /** extends by middleware */
56
67
  [key: string]: any;
57
68
  }
@@ -4,10 +4,10 @@
4
4
  if (v !== undefined) module.exports = v;
5
5
  }
6
6
  else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports", "../constant"], factory);
7
+ define(["require", "exports", "../constant.js"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- const constant_1 = require("../constant");
12
+ const constant_js_1 = require("../constant.js");
13
13
  });
@@ -0,0 +1,8 @@
1
+ import type { KeqContext } from './keq-context.js';
2
+ export interface KeqEvents {
3
+ fetch: KeqContext;
4
+ retry: KeqContext;
5
+ }
6
+ export type KeqListeners = {
7
+ [K in keyof KeqEvents]?: ((data: KeqEvents[K]) => void)[];
8
+ };
@@ -0,0 +1,12 @@
1
+ (function (factory) {
2
+ if (typeof module === "object" && typeof module.exports === "object") {
3
+ var v = factory(require, exports);
4
+ if (v !== undefined) module.exports = v;
5
+ }
6
+ else if (typeof define === "function" && define.amd) {
7
+ define(["require", "exports"], factory);
8
+ }
9
+ })(function (require, exports) {
10
+ "use strict";
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ });
@@ -1,4 +1,4 @@
1
- import { KeqContext } from './keq-context.js';
1
+ import type { KeqContext } from './keq-context.js';
2
2
  export interface KeqFlowControl {
3
3
  mode: 'abort' | 'serial';
4
4
  signal: string | ((ctx: KeqContext) => string);
@@ -0,0 +1,6 @@
1
+ import type { queueAsPromised } from 'fastq';
2
+ import type { KeqNext } from './keq-next.js';
3
+ export interface KeqGlobal {
4
+ abortFlowControl?: Record<string, ((reason: any) => void) | undefined>;
5
+ serialFlowControl?: Record<string, queueAsPromised<KeqNext, void>>;
6
+ }
@@ -0,0 +1,12 @@
1
+ (function (factory) {
2
+ if (typeof module === "object" && typeof module.exports === "object") {
3
+ var v = factory(require, exports);
4
+ if (v !== undefined) module.exports = v;
5
+ }
6
+ else if (typeof define === "function" && define.amd) {
7
+ define(["require", "exports"], factory);
8
+ }
9
+ })(function (require, exports) {
10
+ "use strict";
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ });
@@ -1,3 +1,3 @@
1
- import { KeqContext } from './keq-context';
2
- import { KeqNext } from './keq-next';
1
+ import type { KeqContext } from './keq-context.js';
2
+ import type { KeqNext } from './keq-next.js';
3
3
  export type KeqMiddleware = (ctx: KeqContext, next: KeqNext) => Promise<void>;
@@ -1,9 +1,9 @@
1
- import { Keq } from "../keq.js";
2
- import { KeqFlowControl } from './keq-flow-control.js';
3
- import { KeqResolveMethod } from './keq-resolve-with-mode.js';
4
- import { KeqRetryDelay } from './keq-retry-delay';
5
- import { KeqRetryOn } from './keq-retry-on';
6
- import { KeqTimeout } from './keq-timeout.js';
1
+ import type { Keq } from "../keq.js";
2
+ import type { KeqFlowControl } from './keq-flow-control.js';
3
+ import type { KeqResolveMethod } from './keq-resolve-with-mode.js';
4
+ import type { KeqRetryDelay } from './keq-retry-delay.js';
5
+ import type { KeqRetryOn } from './keq-retry-on.js';
6
+ import type { KeqTimeout } from './keq-timeout.js';
7
7
  export interface KeqOptions<T> {
8
8
  /**
9
9
  * replace the default fetch api
@@ -1,2 +1,2 @@
1
- import { KeqRequestContext } from './keq-context';
1
+ import type { KeqRequestContext } from './keq-context.js';
2
2
  export type KeqRequestInit = Partial<Omit<KeqRequestContext, 'url'>>;
@@ -1,8 +1,8 @@
1
- import { URL } from 'whatwg-url';
2
- import { Keq } from "../keq.js";
3
- import { KeqRouter } from "../router/keq-router.js";
4
- import { KeqMiddleware } from './keq-middleware';
5
- import { KeqRequestInit } from './keq-request-init';
1
+ import type { URL } from 'whatwg-url';
2
+ import type { KeqRouter } from "../router/keq-router.js";
3
+ import type { Keq } from "../keq.js";
4
+ import type { KeqMiddleware } from './keq-middleware.js';
5
+ import type { KeqRequestInit } from './keq-request-init.js';
6
6
  type KeqRequestFn = <T = any>(url: string | URL | globalThis.URL) => Keq<T>;
7
7
  type GlobalURL = globalThis.URL;
8
8
  export interface KeqRequest {
@@ -1,2 +1,2 @@
1
- import { KeqContext } from './keq-context';
1
+ import type { KeqContext } from './keq-context';
2
2
  export type KeqRetryDelay = number | ((attempt: number, error: unknown | null, ctx: KeqContext) => number | Promise<number>);
@@ -1,2 +1,2 @@
1
- import { KeqContext } from './keq-context';
1
+ import type { KeqContext } from './keq-context.js';
2
2
  export type KeqRetryOn = (attempt: number, error: unknown | null, ctx: KeqContext) => (boolean | Promise<boolean>);
@@ -1,2 +1,2 @@
1
- import { KeqContext } from './keq-context.js';
1
+ import type { KeqContext } from './keq-context.js';
2
2
  export type KeqRoute = (ctx: KeqContext) => Promise<boolean> | boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keq",
3
- "version": "2.5.4",
3
+ "version": "2.6.0",
4
4
  "description": "Request API write by Typescript for flexibility, readability, and a low learning curve.",
5
5
  "keywords": [
6
6
  "request",
@@ -44,6 +44,7 @@
44
44
  "clone": "^2.1.2",
45
45
  "fastq": "^1.17.1",
46
46
  "minimatch": "^9.0.4",
47
+ "mitt": "^3.0.1",
47
48
  "object.fromentries": "^2.0.8",
48
49
  "ts-custom-error": "^3.3.1",
49
50
  "whatwg-url": "^14.0.0"
@@ -1,4 +0,0 @@
1
- import { Exception } from './exception.js';
2
- export declare class FileExpectedException extends Exception {
3
- constructor();
4
- }
@@ -1,6 +0,0 @@
1
- import { Exception } from './exception.js';
2
- export class FileExpectedException extends Exception {
3
- constructor() {
4
- super('File/Blob (Browser) or Buffer (NodeJS) expected');
5
- }
6
- }
@@ -1,4 +0,0 @@
1
- import { Exception } from './exception.js';
2
- export declare class FileExpectedException extends Exception {
3
- constructor();
4
- }
@@ -1,20 +0,0 @@
1
- (function (factory) {
2
- if (typeof module === "object" && typeof module.exports === "object") {
3
- var v = factory(require, exports);
4
- if (v !== undefined) module.exports = v;
5
- }
6
- else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports", "./exception.js"], factory);
8
- }
9
- })(function (require, exports) {
10
- "use strict";
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.FileExpectedException = void 0;
13
- const exception_js_1 = require("./exception.js");
14
- class FileExpectedException extends exception_js_1.Exception {
15
- constructor() {
16
- super('File/Blob (Browser) or Buffer (NodeJS) expected');
17
- }
18
- }
19
- exports.FileExpectedException = FileExpectedException;
20
- });