keq 2.6.9 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
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.0](https://github.com/keq-request/keq/compare/v2.6.10...v2.7.0) (2024-07-05)
6
+
7
+
8
+ ### Features
9
+
10
+ * add ctx.request.__url__ that return a url merged routeParams ([896c029](https://github.com/keq-request/keq/commit/896c0293e8a0bd0243cd81b780ea2f9e09cbfeea))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * the default parameter of KeqRequest ([d7939d2](https://github.com/keq-request/keq/commit/d7939d2f2e1f79e719db3c663658c05586be10cf))
16
+
17
+ ## [2.6.10](https://github.com/keq-request/keq/compare/v2.6.9...v2.6.10) (2024-06-27)
18
+
19
+
20
+ ### Performance Improvements
21
+
22
+ * optimize the error message of the wrong header ([92f4aa6](https://github.com/keq-request/keq/commit/92f4aa6d58d258521ee0a2913a8cfb52597e9ed8))
23
+
5
24
  ## [2.6.9](https://github.com/keq-request/keq/compare/v2.6.8...v2.6.9) (2024-06-24)
6
25
 
7
26
 
package/README.md CHANGED
@@ -508,6 +508,7 @@ Keq's context object has many parameters. The following lists all the built-in c
508
508
  | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
509
509
  | `context.request` | Includes request options for [Fetch API][Fetch MDN]. |
510
510
  | `context.request.url` | [URL][URL MDN] Class |
511
+ | `context.request.__url__` | Readonly [URL][URL MDN] Class that merged routeParams |
511
512
  | `context.request.method` | One of 'get', 'post', 'put', 'patch', 'head', 'delete'. |
512
513
  | `context.request.body` | Object, Array, string or undefined. |
513
514
  | `context.request.headers` | The [`Headers`][Headers MDN] Object. |
@@ -9,7 +9,7 @@ import type { KeqContextRequest } from './types/keq-context-request.js';
9
9
  */
10
10
  export declare class Core<OUTPUT> {
11
11
  private requestPromise?;
12
- protected requestContext: Omit<KeqContextRequest, 'abort'>;
12
+ protected requestContext: Omit<KeqContextRequest, 'abort' | '__url__'>;
13
13
  protected __listeners__: KeqListeners;
14
14
  protected __global__: Record<string, any>;
15
15
  protected __prepend_middlewares__: KeqMiddleware[];
@@ -5,6 +5,7 @@ import { cloneBody } from './util/clone-body.js';
5
5
  import { ABORT_PROPERTY, NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from './constant.js';
6
6
  import { composeMiddleware } from './util/compose-middleware.js';
7
7
  import { shallowClone } from './util/shallow-clone.js';
8
+ import { compileUrl } from './util/compile-url.js';
8
9
  /**
9
10
  * @description Keq 核心 API,发送请求必要的原子化的API
10
11
  */
@@ -49,10 +50,13 @@ export class Core {
49
50
  headers.append(key, value);
50
51
  }
51
52
  const requestContext = {
52
- method: this.requestContext.method,
53
53
  url: new URL(this.requestContext.url.href),
54
- headers,
55
54
  routeParams: shallowClone(this.requestContext.routeParams),
55
+ get __url__() {
56
+ return compileUrl(this.url, this.routeParams);
57
+ },
58
+ method: this.requestContext.method,
59
+ headers,
56
60
  body: cloneBody(this.requestContext.body),
57
61
  cache: this.requestContext.cache,
58
62
  credentials: this.requestContext.credentials,
@@ -11,6 +11,7 @@ import { assignKeqRequestBody } from './util/assign-keq-request-body.js';
11
11
  import { base64Encode } from './util/base64.js';
12
12
  import { fixContentType } from './util/fix-content-type.js';
13
13
  import { getUniqueCodeIdentifier } from './util/get-unique-code-identifier.js';
14
+ import { isValidHeaderValue } from './util/is-valid-header-value.js';
14
15
  /**
15
16
  * @description Keq 扩展 API,人性化的常用的API
16
17
  */
@@ -35,10 +36,16 @@ export class Keq extends Core {
35
36
  });
36
37
  }
37
38
  else if (typeof headersOrName === 'string' && value) {
39
+ if (!isValidHeaderValue(value)) {
40
+ throw new Exception(`[Invalid header] Key: ${headersOrName} Value: ${value}`);
41
+ }
38
42
  this.requestContext.headers.set(headersOrName, value);
39
43
  }
40
44
  else if (typeof headersOrName === 'object') {
41
45
  for (const [key, value] of Object.entries(headersOrName)) {
46
+ if (!isValidHeaderValue(value)) {
47
+ throw new Exception(`[Invalid header] Key: ${key} Value: ${value}`);
48
+ }
42
49
  this.requestContext.headers.set(key, value);
43
50
  }
44
51
  }
@@ -1,18 +1,6 @@
1
- import { URL } from 'whatwg-url';
2
1
  import { Exception } from '../exception/exception.js';
3
- import { compilePathnameTemplate } from '../util/compile-pathname-template.js';
4
2
  import { ABORT_PROPERTY } from '../constant.js';
5
3
  import { isBuffer } from "../is/is-buffer.js";
6
- function compileUrl(obj, routeParams) {
7
- const url = new URL(typeof obj === 'string' ? obj : obj.href);
8
- try {
9
- url.pathname = compilePathnameTemplate(url.pathname, routeParams);
10
- }
11
- catch (e) {
12
- throw new Exception(`Cannot compile the params in ${url.pathname}, Because ${e?.message}.`);
13
- }
14
- return url.href;
15
- }
16
4
  function inferContentTypeByBody(body) {
17
5
  if (!body)
18
6
  return 'text/plain';
@@ -78,7 +66,7 @@ function compileBody(ctx) {
78
66
  export function fetchArgumentsMiddleware() {
79
67
  return async function fetchArgumentsMiddleware(ctx, next) {
80
68
  const request = ctx.request;
81
- const url = compileUrl(request.url, request.routeParams);
69
+ const url = ctx.request.__url__.href;
82
70
  if (!request.headers.has('Content-Type') && request.body) {
83
71
  request.headers.set('Content-Type', inferContentTypeByBody(ctx.request.body));
84
72
  }
@@ -3,9 +3,10 @@ export type KeqContextRequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head'
3
3
  export type KeqContextRequestBody = object | Array<any> | string | undefined;
4
4
  export interface KeqContextRequest {
5
5
  url: URL | globalThis.URL;
6
+ routeParams: Record<string, string>;
7
+ readonly __url__: Readonly<URL> | Readonly<globalThis.URL>;
6
8
  method: KeqContextRequestMethod;
7
9
  headers: Headers;
8
- routeParams: Record<string, string>;
9
10
  body: KeqContextRequestBody;
10
11
  cache?: RequestCache;
11
12
  credentials?: RequestCredentials;
@@ -16,7 +16,7 @@ type PickKeqOperationsProperty<T extends KeqOperations, P extends keyof T, X ext
16
16
  [Method in keyof T[Path] as T[Path][Method] extends KeqOperation ? Method : never]: infer R;
17
17
  };
18
18
  } ? R extends KeqOperation ? R[X] : never : never;
19
- export interface KeqRequest<OPERATIONS extends KeqOperations> {
19
+ export interface KeqRequest<OPERATIONS extends KeqOperations = KeqOperations> {
20
20
  <Path extends keyof OPERATIONS>(url: Path, init: Omit<KeqInit, 'global'>): Keq<Exclude<PickKeqOperationsProperty<OPERATIONS, Path, 'responseBody'>, undefined>>;
21
21
  <OUTPUT = any>(url: string, init: Omit<KeqInit, 'global'>): Keq<OUTPUT>;
22
22
  <OUTPUT = any>(url: URL, init: Omit<KeqInit, 'global'>): Keq<OUTPUT>;
@@ -0,0 +1,2 @@
1
+ import { URL } from 'whatwg-url';
2
+ export declare function compileUrl(obj: string | URL | globalThis.URL, routeParams: Record<string, string | number>): URL;
@@ -1,4 +1,5 @@
1
- export function compilePathnameTemplate(template, params) {
1
+ import { URL } from 'whatwg-url';
2
+ function compilePathnameTemplate(template, params) {
2
3
  return template
3
4
  .replace(/(^|\/)(?::([^/]+)|{([^/]+)}|%7B([^/]+)%7D)(?=$|\/)/g, (_, prefix, group1, group2, group3) => {
4
5
  if (group1 && params[group1]) {
@@ -13,3 +14,8 @@ export function compilePathnameTemplate(template, params) {
13
14
  return _;
14
15
  });
15
16
  }
17
+ export function compileUrl(obj, routeParams) {
18
+ const url = new URL(typeof obj === 'string' ? obj : obj.href);
19
+ url.pathname = compilePathnameTemplate(url.pathname, routeParams);
20
+ return url;
21
+ }
@@ -0,0 +1 @@
1
+ export declare function isValidHeaderValue(str: any): boolean;
@@ -0,0 +1,4 @@
1
+ export function isValidHeaderValue(str) {
2
+ const regex = /^[\t\x20-\x7E\x80-\xFF]*$/;
3
+ return regex.test(str);
4
+ }
@@ -9,7 +9,7 @@ import type { KeqContextRequest } from './types/keq-context-request.js';
9
9
  */
10
10
  export declare class Core<OUTPUT> {
11
11
  private requestPromise?;
12
- protected requestContext: Omit<KeqContextRequest, 'abort'>;
12
+ protected requestContext: Omit<KeqContextRequest, 'abort' | '__url__'>;
13
13
  protected __listeners__: KeqListeners;
14
14
  protected __global__: Record<string, any>;
15
15
  protected __prepend_middlewares__: KeqMiddleware[];
@@ -7,7 +7,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
7
7
  if (v !== undefined) module.exports = v;
8
8
  }
9
9
  else if (typeof define === "function" && define.amd) {
10
- define(["require", "exports", "mitt", "whatwg-url", "./exception/exception.js", "./util/clone-body.js", "./constant.js", "./util/compose-middleware.js", "./util/shallow-clone.js"], factory);
10
+ define(["require", "exports", "mitt", "whatwg-url", "./exception/exception.js", "./util/clone-body.js", "./constant.js", "./util/compose-middleware.js", "./util/shallow-clone.js", "./util/compile-url.js"], factory);
11
11
  }
12
12
  })(function (require, exports) {
13
13
  "use strict";
@@ -20,6 +20,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
20
20
  const constant_js_1 = require("./constant.js");
21
21
  const compose_middleware_js_1 = require("./util/compose-middleware.js");
22
22
  const shallow_clone_js_1 = require("./util/shallow-clone.js");
23
+ const compile_url_js_1 = require("./util/compile-url.js");
23
24
  /**
24
25
  * @description Keq 核心 API,发送请求必要的原子化的API
25
26
  */
@@ -64,10 +65,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
64
65
  headers.append(key, value);
65
66
  }
66
67
  const requestContext = {
67
- method: this.requestContext.method,
68
68
  url: new whatwg_url_1.URL(this.requestContext.url.href),
69
- headers,
70
69
  routeParams: (0, shallow_clone_js_1.shallowClone)(this.requestContext.routeParams),
70
+ get __url__() {
71
+ return (0, compile_url_js_1.compileUrl)(this.url, this.routeParams);
72
+ },
73
+ method: this.requestContext.method,
74
+ headers,
71
75
  body: (0, clone_body_js_1.cloneBody)(this.requestContext.body),
72
76
  cache: this.requestContext.cache,
73
77
  credentials: this.requestContext.credentials,
@@ -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", "./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/assign-keq-request-body.js", "./util/base64.js", "./util/fix-content-type.js", "./util/get-unique-code-identifier.js"], factory);
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/assign-keq-request-body.js", "./util/base64.js", "./util/fix-content-type.js", "./util/get-unique-code-identifier.js", "./util/is-valid-header-value.js"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
@@ -23,6 +23,7 @@
23
23
  const base64_js_1 = require("./util/base64.js");
24
24
  const fix_content_type_js_1 = require("./util/fix-content-type.js");
25
25
  const get_unique_code_identifier_js_1 = require("./util/get-unique-code-identifier.js");
26
+ const is_valid_header_value_js_1 = require("./util/is-valid-header-value.js");
26
27
  /**
27
28
  * @description Keq 扩展 API,人性化的常用的API
28
29
  */
@@ -47,10 +48,16 @@
47
48
  });
48
49
  }
49
50
  else if (typeof headersOrName === 'string' && value) {
51
+ if (!(0, is_valid_header_value_js_1.isValidHeaderValue)(value)) {
52
+ throw new exception_js_1.Exception(`[Invalid header] Key: ${headersOrName} Value: ${value}`);
53
+ }
50
54
  this.requestContext.headers.set(headersOrName, value);
51
55
  }
52
56
  else if (typeof headersOrName === 'object') {
53
57
  for (const [key, value] of Object.entries(headersOrName)) {
58
+ if (!(0, is_valid_header_value_js_1.isValidHeaderValue)(value)) {
59
+ throw new exception_js_1.Exception(`[Invalid header] Key: ${key} Value: ${value}`);
60
+ }
54
61
  this.requestContext.headers.set(key, value);
55
62
  }
56
63
  }
@@ -4,27 +4,15 @@
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", "../constant.js", "../is/is-buffer.js"], factory);
7
+ define(["require", "exports", "../exception/exception.js", "../constant.js", "../is/is-buffer.js"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.fetchArgumentsMiddleware = void 0;
13
- const whatwg_url_1 = require("whatwg-url");
14
13
  const exception_js_1 = require("../exception/exception.js");
15
- const compile_pathname_template_js_1 = require("../util/compile-pathname-template.js");
16
14
  const constant_js_1 = require("../constant.js");
17
15
  const is_buffer_js_1 = require("../is/is-buffer.js");
18
- function compileUrl(obj, routeParams) {
19
- const url = new whatwg_url_1.URL(typeof obj === 'string' ? obj : obj.href);
20
- try {
21
- url.pathname = (0, compile_pathname_template_js_1.compilePathnameTemplate)(url.pathname, routeParams);
22
- }
23
- catch (e) {
24
- throw new exception_js_1.Exception(`Cannot compile the params in ${url.pathname}, Because ${e?.message}.`);
25
- }
26
- return url.href;
27
- }
28
16
  function inferContentTypeByBody(body) {
29
17
  if (!body)
30
18
  return 'text/plain';
@@ -90,7 +78,7 @@
90
78
  function fetchArgumentsMiddleware() {
91
79
  return async function fetchArgumentsMiddleware(ctx, next) {
92
80
  const request = ctx.request;
93
- const url = compileUrl(request.url, request.routeParams);
81
+ const url = ctx.request.__url__.href;
94
82
  if (!request.headers.has('Content-Type') && request.body) {
95
83
  request.headers.set('Content-Type', inferContentTypeByBody(ctx.request.body));
96
84
  }
@@ -3,9 +3,10 @@ export type KeqContextRequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head'
3
3
  export type KeqContextRequestBody = object | Array<any> | string | undefined;
4
4
  export interface KeqContextRequest {
5
5
  url: URL | globalThis.URL;
6
+ routeParams: Record<string, string>;
7
+ readonly __url__: Readonly<URL> | Readonly<globalThis.URL>;
6
8
  method: KeqContextRequestMethod;
7
9
  headers: Headers;
8
- routeParams: Record<string, string>;
9
10
  body: KeqContextRequestBody;
10
11
  cache?: RequestCache;
11
12
  credentials?: RequestCredentials;
@@ -16,7 +16,7 @@ type PickKeqOperationsProperty<T extends KeqOperations, P extends keyof T, X ext
16
16
  [Method in keyof T[Path] as T[Path][Method] extends KeqOperation ? Method : never]: infer R;
17
17
  };
18
18
  } ? R extends KeqOperation ? R[X] : never : never;
19
- export interface KeqRequest<OPERATIONS extends KeqOperations> {
19
+ export interface KeqRequest<OPERATIONS extends KeqOperations = KeqOperations> {
20
20
  <Path extends keyof OPERATIONS>(url: Path, init: Omit<KeqInit, 'global'>): Keq<Exclude<PickKeqOperationsProperty<OPERATIONS, Path, 'responseBody'>, undefined>>;
21
21
  <OUTPUT = any>(url: string, init: Omit<KeqInit, 'global'>): Keq<OUTPUT>;
22
22
  <OUTPUT = any>(url: URL, init: Omit<KeqInit, 'global'>): Keq<OUTPUT>;
@@ -0,0 +1,2 @@
1
+ import { URL } from 'whatwg-url';
2
+ export declare function compileUrl(obj: string | URL | globalThis.URL, routeParams: Record<string, string | number>): URL;
@@ -4,12 +4,13 @@
4
4
  if (v !== undefined) module.exports = v;
5
5
  }
6
6
  else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports"], factory);
7
+ define(["require", "exports", "whatwg-url"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.compilePathnameTemplate = void 0;
12
+ exports.compileUrl = void 0;
13
+ const whatwg_url_1 = require("whatwg-url");
13
14
  function compilePathnameTemplate(template, params) {
14
15
  return template
15
16
  .replace(/(^|\/)(?::([^/]+)|{([^/]+)}|%7B([^/]+)%7D)(?=$|\/)/g, (_, prefix, group1, group2, group3) => {
@@ -25,5 +26,10 @@
25
26
  return _;
26
27
  });
27
28
  }
28
- exports.compilePathnameTemplate = compilePathnameTemplate;
29
+ function compileUrl(obj, routeParams) {
30
+ const url = new whatwg_url_1.URL(typeof obj === 'string' ? obj : obj.href);
31
+ url.pathname = compilePathnameTemplate(url.pathname, routeParams);
32
+ return url;
33
+ }
34
+ exports.compileUrl = compileUrl;
29
35
  });
@@ -0,0 +1 @@
1
+ export declare function isValidHeaderValue(str: any): boolean;
@@ -0,0 +1,18 @@
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
+ exports.isValidHeaderValue = void 0;
13
+ function isValidHeaderValue(str) {
14
+ const regex = /^[\t\x20-\x7E\x80-\xFF]*$/;
15
+ return regex.test(str);
16
+ }
17
+ exports.isValidHeaderValue = isValidHeaderValue;
18
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keq",
3
- "version": "2.6.9",
3
+ "version": "2.7.0",
4
4
  "description": "Request API write by Typescript for flexibility, readability, and a low learning curve.",
5
5
  "keywords": [
6
6
  "request",
@@ -1 +0,0 @@
1
- export declare function compilePathnameTemplate(template: string, params: Record<string, string | number>): string;
@@ -1 +0,0 @@
1
- export declare function compilePathnameTemplate(template: string, params: Record<string, string | number>): string;