api-def 0.10.1 → 0.11.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/cjs/ApiTypes.d.ts CHANGED
@@ -4,7 +4,7 @@ import type RequestContext from "./RequestContext";
4
4
  import type { Validation } from "./Validation";
5
5
  import type RequestBackend from "./backend/RequestBackend";
6
6
  export type AcceptableStatus = number | [min: number, max: number];
7
- export type Headers = Record<string, string | number | boolean | null | undefined>;
7
+ export type RawHeaders = Record<string, string | number | boolean | null | undefined>;
8
8
  export type Params = string;
9
9
  export type Query = string | undefined | Record<string, any>;
10
10
  export type Body = string | number | Record<string, any>;
@@ -14,7 +14,7 @@ export interface ApiResponse<T = any> {
14
14
  readonly url: string;
15
15
  readonly status: number;
16
16
  readonly data: T;
17
- readonly headers: Record<string, string>;
17
+ readonly headers: Headers;
18
18
  readonly state: State;
19
19
  }
20
20
  export type RequestLock = string | false;
@@ -35,7 +35,7 @@ export interface BaseRequestConfig {
35
35
  lock?: RequestLock;
36
36
  credentials?: "omit" | "same-origin" | "include";
37
37
  retry?: number | false | RetryOptions;
38
- headers?: Readonly<Headers>;
38
+ headers?: Readonly<RawHeaders>;
39
39
  acceptableStatus?: AcceptableStatus[];
40
40
  /**
41
41
  * @deprecated use `queryHandling.stringify` instead
@@ -1,4 +1,4 @@
1
- import type { ApiResponse, Body, Headers, Params, Query, State } from "./ApiTypes";
1
+ import type { ApiResponse, Body, Params, Query, RawHeaders, State } from "./ApiTypes";
2
2
  export interface ApiMockingConfig {
3
3
  enabled: boolean | (() => boolean);
4
4
  }
@@ -6,14 +6,14 @@ export interface MockRequest<TResponse = any, TParams extends Params | undefined
6
6
  params: TParams extends Params ? Record<TParams, string> : {};
7
7
  body: TBody;
8
8
  query: TQuery;
9
- headers: Readonly<Headers>;
9
+ headers: Readonly<RawHeaders>;
10
10
  url: string;
11
11
  state: TState;
12
12
  }
13
13
  export interface MockResponse<TResponse = any, TParams extends Params | undefined = Params | undefined, TQuery extends Query | undefined = Query | undefined, TBody extends Body | undefined = Body | undefined, TState extends State = State> {
14
14
  statusCode: number;
15
15
  response: TResponse | undefined;
16
- headers: Headers;
16
+ headers: RawHeaders;
17
17
  status(statusCode: number): this;
18
18
  send(response: TResponse): this;
19
19
  }
@@ -1,6 +1,6 @@
1
1
  import type { Api } from "./Api";
2
2
  import type { RequestEvent, RequestMethod, ResponseType } from "./ApiConstants";
3
- import type { ApiResponse, Body, ComputedRequestConfig, EventResult, Headers, Params, Query, RequestCacheInfo, RequestContextStats, RequestEventHandlers, RequestHost, State } from "./ApiTypes";
3
+ import type { ApiResponse, Body, ComputedRequestConfig, EventResult, Params, Query, RawHeaders, RequestCacheInfo, RequestContextStats, RequestEventHandlers, RequestHost, State } from "./ApiTypes";
4
4
  import type { EndpointMockingConfig } from "./MockingTypes";
5
5
  import type { RequestError } from "./RequestError";
6
6
  import type { Validation } from "./Validation";
@@ -36,7 +36,7 @@ export default class RequestContext<TResponse = any, TParams extends Params | un
36
36
  get responseType(): ResponseType | undefined;
37
37
  private initMiddleware;
38
38
  private generateKey;
39
- updateHeaders(newHeaders: Headers): this;
39
+ updateHeaders(newHeaders: RawHeaders): this;
40
40
  private parseRequestBody;
41
41
  getParsedBody(): any;
42
42
  updateQuery(newQuery: Partial<TQuery>): this;
@@ -14,13 +14,14 @@ export declare const RequestErrorCode: {
14
14
  readonly VALIDATION_RESPONSE_VALIDATE_ERROR: "validation/response-validate-error";
15
15
  };
16
16
  export type RequestErrorCode = EnumOf<typeof RequestErrorCode>;
17
+ declare const REQUEST_ERROR_SYMBOL: unique symbol;
17
18
  export interface RequestError extends Error {
18
- isRequestError: true;
19
+ [REQUEST_ERROR_SYMBOL]: true;
19
20
  response: ApiResponse | undefined | null;
20
21
  code: string;
21
22
  attempts: number;
22
23
  }
23
- export declare const isRequestError: (error: Error) => error is RequestError;
24
+ export declare const isRequestError: (error: any) => error is RequestError;
24
25
  export interface RequestErrorConfig {
25
26
  error: Error;
26
27
  code: string;
@@ -28,3 +29,4 @@ export interface RequestErrorConfig {
28
29
  response?: ApiResponse | null;
29
30
  }
30
31
  export declare const convertToRequestError: (config: RequestErrorConfig) => RequestError;
32
+ export {};
@@ -13,26 +13,35 @@ exports.RequestErrorCode = {
13
13
  VALIDATION_BODY_VALIDATE_ERROR: "validation/body-validate-error",
14
14
  VALIDATION_RESPONSE_VALIDATE_ERROR: "validation/response-validate-error",
15
15
  };
16
+ var REQUEST_ERROR_SYMBOL = Symbol("isRequestError");
16
17
  var isRequestError = function (error) {
17
- return "isRequestError" in error;
18
+ if (!error) {
19
+ return false;
20
+ }
21
+ if (typeof error !== "object") {
22
+ return false;
23
+ }
24
+ return error[REQUEST_ERROR_SYMBOL] === true;
18
25
  };
19
26
  exports.isRequestError = isRequestError;
20
27
  var convertToRequestError = function (config) {
28
+ var _a;
21
29
  var error = config.error, context = config.context, response = config.response, code = config.code;
22
30
  var body = context.getParsedBody();
23
- var resultError = Object.assign(error, {
24
- name: "RequestError",
25
- response: response,
26
- code: code,
27
- isRequestError: true,
28
- attempts: context.stats.attempt,
29
- request: {
31
+ var resultError = Object.assign(error, (_a = {
32
+ name: "RequestError",
33
+ response: response,
34
+ code: code
35
+ },
36
+ _a[REQUEST_ERROR_SYMBOL] = true,
37
+ _a.attempts = context.stats.attempt,
38
+ _a.request = {
30
39
  url: context.requestUrl.href,
31
40
  query: context.computedConfig.queryObject,
32
41
  headers: context.computedConfig.headers,
33
42
  body: body,
34
43
  },
35
- });
44
+ _a));
36
45
  try {
37
46
  Object.defineProperty(resultError, "message", {
38
47
  value: "Request failed".concat((response === null || response === void 0 ? void 0 : response.status) ? " with status code ".concat(response.status) : "", " [").concat(code, "]: ").concat(resultError.message),
package/cjs/Requester.js CHANGED
@@ -242,7 +242,7 @@ var makeRequest = function (context) { return __awaiter(void 0, void 0, void 0,
242
242
  });
243
243
  }); };
244
244
  var parseResponse = function (context, response, error) { return __awaiter(void 0, void 0, void 0, function () {
245
- var parsedResponse_1, contentType, inferredResponseType, data, decodedData;
245
+ var parsedResponse, contentType, inferredResponseType, data, decodedData;
246
246
  var _a;
247
247
  return __generator(this, function (_b) {
248
248
  switch (_b.label) {
@@ -250,15 +250,8 @@ var parseResponse = function (context, response, error) { return __awaiter(void
250
250
  if (!response) return [3 /*break*/, 2];
251
251
  return [4 /*yield*/, context.backend.convertResponse(context, response)];
252
252
  case 1:
253
- parsedResponse_1 = _b.sent();
254
- // lowercase all header names
255
- parsedResponse_1.headers =
256
- parsedResponse_1.__lowercaseHeaders ||
257
- Object.keys(parsedResponse_1.headers).reduce(function (headers, header) {
258
- headers[header.toLowerCase()] = parsedResponse_1.headers[header];
259
- return headers;
260
- }, {});
261
- contentType = parsedResponse_1.headers["content-type"];
253
+ parsedResponse = _b.sent();
254
+ contentType = parsedResponse.headers.get("content-type");
262
255
  inferredResponseType = (0, ApiUtils_1.inferResponseType)(contentType);
263
256
  if (!error) {
264
257
  // expand to array buffer once we support that in inferResponseType
@@ -266,13 +259,13 @@ var parseResponse = function (context, response, error) { return __awaiter(void
266
259
  throw (0, RequestError_1.convertToRequestError)({
267
260
  error: new Error("[api-def] Expected '".concat(context.responseType, "' response, got '").concat(inferredResponseType, "' (from 'Content-Type' of '").concat(contentType, "')")),
268
261
  code: RequestError_1.RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
269
- response: parsedResponse_1,
262
+ response: parsedResponse,
270
263
  context: context,
271
264
  });
272
265
  }
273
266
  // transform arrayBuffer to json
274
267
  if (inferredResponseType === "arraybuffer" && context.responseType === "json") {
275
- if (parsedResponse_1.data && typeof parsedResponse_1.data === "object") {
268
+ if (parsedResponse.data && typeof parsedResponse.data === "object") {
276
269
  data = response.data;
277
270
  if (((_a = data.constructor) === null || _a === void 0 ? void 0 : _a.name) === "ArrayBuffer") {
278
271
  try {
@@ -283,7 +276,7 @@ var parseResponse = function (context, response, error) { return __awaiter(void
283
276
  throw (0, RequestError_1.convertToRequestError)({
284
277
  error: new Error("[api-def] Expected '".concat(context.responseType, "' response, got '").concat(inferredResponseType, "' (from 'Content-Type' of '").concat(contentType, "')")),
285
278
  code: RequestError_1.RequestErrorCode.REQUEST_MISMATCH_RESPONSE_TYPE,
286
- response: parsedResponse_1,
279
+ response: parsedResponse,
287
280
  context: context,
288
281
  });
289
282
  }
@@ -291,7 +284,7 @@ var parseResponse = function (context, response, error) { return __awaiter(void
291
284
  }
292
285
  }
293
286
  }
294
- return [2 /*return*/, parsedResponse_1];
287
+ return [2 /*return*/, parsedResponse];
295
288
  case 2: return [2 /*return*/, response];
296
289
  }
297
290
  });
@@ -88,23 +88,18 @@ var FetchRequestBackend = /** @class */ (function () {
88
88
  };
89
89
  FetchRequestBackend.prototype.convertResponse = function (context, response) {
90
90
  return __awaiter(this, void 0, void 0, function () {
91
- var status, headers, processedHeaders, convertedResponse, responseType, text, data, error_1;
91
+ var status, headers, convertedResponse, responseType, text, data, error_1;
92
92
  var _a;
93
93
  return __generator(this, function (_b) {
94
94
  switch (_b.label) {
95
95
  case 0:
96
96
  status = response.status, headers = response.headers;
97
- processedHeaders = {};
98
- headers.forEach(function (value, key) {
99
- processedHeaders[key] = value;
100
- });
101
97
  convertedResponse = {
102
- __lowercaseHeaders: processedHeaders,
103
98
  method: context.method,
104
99
  url: response.url,
105
100
  data: undefined,
106
101
  status: status,
107
- headers: processedHeaders,
102
+ headers: headers,
108
103
  state: context.requestConfig.state,
109
104
  };
110
105
  responseType = (_a = context.responseType) !== null && _a !== void 0 ? _a : (0, ApiUtils_1.inferResponseType)(response.headers.get("Content-Type"));
@@ -137,9 +137,9 @@ var MockRequestBackend = /** @class */ (function () {
137
137
  });
138
138
  }
139
139
  parsedHeaders = Object.keys(res.headers).reduce(function (parsedHeaders, key) {
140
- parsedHeaders[key] = res.headers[key].toString();
140
+ parsedHeaders.set(key, res.headers[key].toString());
141
141
  return parsedHeaders;
142
- }, {});
142
+ }, new Headers());
143
143
  return [2 /*return*/, {
144
144
  url: context.requestUrl.href,
145
145
  method: context.method,
package/cjs/index.d.ts CHANGED
@@ -2,8 +2,8 @@ export * from "./Api";
2
2
  export * from "./ApiTypes";
3
3
  export * from "./UtilTypes";
4
4
  export * from "./ApiConstants";
5
- export { isRequestError } from "./RequestError";
6
- export { default as Endpoint, EndpointConfig } from "./Endpoint";
5
+ export { isRequestError, type RequestError } from "./RequestError";
6
+ export { default as Endpoint, type EndpointConfig } from "./Endpoint";
7
7
  export { clearCache, setCacheBackend } from "./cache/Caching";
8
8
  export { default as LocalStorageCacheBackend } from "./cache/LocalStorageCacheBackend";
9
9
  export { default as LocaleForageCacheBackend } from "./cache/LocalForageCacheBackend";
package/esm/ApiTypes.d.ts CHANGED
@@ -4,7 +4,7 @@ import type RequestContext from "./RequestContext";
4
4
  import type { Validation } from "./Validation";
5
5
  import type RequestBackend from "./backend/RequestBackend";
6
6
  export type AcceptableStatus = number | [min: number, max: number];
7
- export type Headers = Record<string, string | number | boolean | null | undefined>;
7
+ export type RawHeaders = Record<string, string | number | boolean | null | undefined>;
8
8
  export type Params = string;
9
9
  export type Query = string | undefined | Record<string, any>;
10
10
  export type Body = string | number | Record<string, any>;
@@ -14,7 +14,7 @@ export interface ApiResponse<T = any> {
14
14
  readonly url: string;
15
15
  readonly status: number;
16
16
  readonly data: T;
17
- readonly headers: Record<string, string>;
17
+ readonly headers: Headers;
18
18
  readonly state: State;
19
19
  }
20
20
  export type RequestLock = string | false;
@@ -35,7 +35,7 @@ export interface BaseRequestConfig {
35
35
  lock?: RequestLock;
36
36
  credentials?: "omit" | "same-origin" | "include";
37
37
  retry?: number | false | RetryOptions;
38
- headers?: Readonly<Headers>;
38
+ headers?: Readonly<RawHeaders>;
39
39
  acceptableStatus?: AcceptableStatus[];
40
40
  /**
41
41
  * @deprecated use `queryHandling.stringify` instead
@@ -1,4 +1,4 @@
1
- import type { ApiResponse, Body, Headers, Params, Query, State } from "./ApiTypes";
1
+ import type { ApiResponse, Body, Params, Query, RawHeaders, State } from "./ApiTypes";
2
2
  export interface ApiMockingConfig {
3
3
  enabled: boolean | (() => boolean);
4
4
  }
@@ -6,14 +6,14 @@ export interface MockRequest<TResponse = any, TParams extends Params | undefined
6
6
  params: TParams extends Params ? Record<TParams, string> : {};
7
7
  body: TBody;
8
8
  query: TQuery;
9
- headers: Readonly<Headers>;
9
+ headers: Readonly<RawHeaders>;
10
10
  url: string;
11
11
  state: TState;
12
12
  }
13
13
  export interface MockResponse<TResponse = any, TParams extends Params | undefined = Params | undefined, TQuery extends Query | undefined = Query | undefined, TBody extends Body | undefined = Body | undefined, TState extends State = State> {
14
14
  statusCode: number;
15
15
  response: TResponse | undefined;
16
- headers: Headers;
16
+ headers: RawHeaders;
17
17
  status(statusCode: number): this;
18
18
  send(response: TResponse): this;
19
19
  }
@@ -1,6 +1,6 @@
1
1
  import type { Api } from "./Api";
2
2
  import type { RequestEvent, RequestMethod, ResponseType } from "./ApiConstants";
3
- import type { ApiResponse, Body, ComputedRequestConfig, EventResult, Headers, Params, Query, RequestCacheInfo, RequestContextStats, RequestEventHandlers, RequestHost, State } from "./ApiTypes";
3
+ import type { ApiResponse, Body, ComputedRequestConfig, EventResult, Params, Query, RawHeaders, RequestCacheInfo, RequestContextStats, RequestEventHandlers, RequestHost, State } from "./ApiTypes";
4
4
  import type { EndpointMockingConfig } from "./MockingTypes";
5
5
  import type { RequestError } from "./RequestError";
6
6
  import type { Validation } from "./Validation";
@@ -36,7 +36,7 @@ export default class RequestContext<TResponse = any, TParams extends Params | un
36
36
  get responseType(): ResponseType | undefined;
37
37
  private initMiddleware;
38
38
  private generateKey;
39
- updateHeaders(newHeaders: Headers): this;
39
+ updateHeaders(newHeaders: RawHeaders): this;
40
40
  private parseRequestBody;
41
41
  getParsedBody(): any;
42
42
  updateQuery(newQuery: Partial<TQuery>): this;
@@ -14,13 +14,14 @@ export declare const RequestErrorCode: {
14
14
  readonly VALIDATION_RESPONSE_VALIDATE_ERROR: "validation/response-validate-error";
15
15
  };
16
16
  export type RequestErrorCode = EnumOf<typeof RequestErrorCode>;
17
+ declare const REQUEST_ERROR_SYMBOL: unique symbol;
17
18
  export interface RequestError extends Error {
18
- isRequestError: true;
19
+ [REQUEST_ERROR_SYMBOL]: true;
19
20
  response: ApiResponse | undefined | null;
20
21
  code: string;
21
22
  attempts: number;
22
23
  }
23
- export declare const isRequestError: (error: Error) => error is RequestError;
24
+ export declare const isRequestError: (error: any) => error is RequestError;
24
25
  export interface RequestErrorConfig {
25
26
  error: Error;
26
27
  code: string;
@@ -28,3 +29,4 @@ export interface RequestErrorConfig {
28
29
  response?: ApiResponse | null;
29
30
  }
30
31
  export declare const convertToRequestError: (config: RequestErrorConfig) => RequestError;
32
+ export {};
@@ -10,8 +10,15 @@ export const RequestErrorCode = {
10
10
  VALIDATION_BODY_VALIDATE_ERROR: "validation/body-validate-error",
11
11
  VALIDATION_RESPONSE_VALIDATE_ERROR: "validation/response-validate-error",
12
12
  };
13
+ const REQUEST_ERROR_SYMBOL = Symbol("isRequestError");
13
14
  export const isRequestError = (error) => {
14
- return "isRequestError" in error;
15
+ if (!error) {
16
+ return false;
17
+ }
18
+ if (typeof error !== "object") {
19
+ return false;
20
+ }
21
+ return error[REQUEST_ERROR_SYMBOL] === true;
15
22
  };
16
23
  export const convertToRequestError = (config) => {
17
24
  const { error, context, response, code } = config;
@@ -20,7 +27,7 @@ export const convertToRequestError = (config) => {
20
27
  name: "RequestError",
21
28
  response: response,
22
29
  code: code,
23
- isRequestError: true,
30
+ [REQUEST_ERROR_SYMBOL]: true,
24
31
  attempts: context.stats.attempt,
25
32
  request: {
26
33
  url: context.requestUrl.href,
package/esm/Requester.js CHANGED
@@ -178,14 +178,7 @@ const parseResponse = (context, response, error) => __awaiter(void 0, void 0, vo
178
178
  var _d;
179
179
  if (response) {
180
180
  const parsedResponse = yield context.backend.convertResponse(context, response);
181
- // lowercase all header names
182
- parsedResponse.headers =
183
- parsedResponse.__lowercaseHeaders ||
184
- Object.keys(parsedResponse.headers).reduce((headers, header) => {
185
- headers[header.toLowerCase()] = parsedResponse.headers[header];
186
- return headers;
187
- }, {});
188
- const contentType = parsedResponse.headers["content-type"];
181
+ const contentType = parsedResponse.headers.get("content-type");
189
182
  const inferredResponseType = inferResponseType(contentType);
190
183
  if (!error) {
191
184
  // expand to array buffer once we support that in inferResponseType
@@ -38,17 +38,12 @@ export default class FetchRequestBackend {
38
38
  return __awaiter(this, void 0, void 0, function* () {
39
39
  var _a;
40
40
  const { status, headers } = response;
41
- const processedHeaders = {};
42
- headers.forEach((value, key) => {
43
- processedHeaders[key] = value;
44
- });
45
41
  const convertedResponse = {
46
- __lowercaseHeaders: processedHeaders,
47
42
  method: context.method,
48
43
  url: response.url,
49
44
  data: undefined,
50
45
  status: status,
51
- headers: processedHeaders,
46
+ headers: headers,
52
47
  state: context.requestConfig.state,
53
48
  };
54
49
  const responseType = (_a = context.responseType) !== null && _a !== void 0 ? _a : inferResponseType(response.headers.get("Content-Type"));
@@ -93,9 +93,9 @@ export default class MockRequestBackend {
93
93
  });
94
94
  }
95
95
  const parsedHeaders = Object.keys(res.headers).reduce((parsedHeaders, key) => {
96
- parsedHeaders[key] = res.headers[key].toString();
96
+ parsedHeaders.set(key, res.headers[key].toString());
97
97
  return parsedHeaders;
98
- }, {});
98
+ }, new Headers());
99
99
  return {
100
100
  url: context.requestUrl.href,
101
101
  method: context.method,
package/esm/index.d.ts CHANGED
@@ -2,8 +2,8 @@ export * from "./Api";
2
2
  export * from "./ApiTypes";
3
3
  export * from "./UtilTypes";
4
4
  export * from "./ApiConstants";
5
- export { isRequestError } from "./RequestError";
6
- export { default as Endpoint, EndpointConfig } from "./Endpoint";
5
+ export { isRequestError, type RequestError } from "./RequestError";
6
+ export { default as Endpoint, type EndpointConfig } from "./Endpoint";
7
7
  export { clearCache, setCacheBackend } from "./cache/Caching";
8
8
  export { default as LocalStorageCacheBackend } from "./cache/LocalStorageCacheBackend";
9
9
  export { default as LocaleForageCacheBackend } from "./cache/LocalForageCacheBackend";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-def",
3
- "version": "0.10.1",
3
+ "version": "0.11.0-alpha.1",
4
4
  "description": "Typed API definitions with middleware support",
5
5
  "main": "cjs/index.js",
6
6
  "types": "esm/index.d.ts",
@@ -30,19 +30,19 @@
30
30
  },
31
31
  "repository": "https://github.com/Censkh/api-def",
32
32
  "devDependencies": {
33
- "@biomejs/biome": "1.7.3",
33
+ "@biomejs/biome": "1.8.1",
34
34
  "@swc/core": "latest",
35
35
  "@swc/jest": "latest",
36
36
  "@types/axios": "0.14.0",
37
37
  "@types/jest": "^29.5.12",
38
- "@types/node": "20.12.11",
38
+ "@types/node": "20.14.2",
39
39
  "@types/qs": "6.9.15",
40
- "axios": "1.6.8",
40
+ "axios": "1.7.2",
41
41
  "cross-env": "7.0.3",
42
42
  "jest": "latest",
43
43
  "npm-run-all": "4.1.5",
44
44
  "qs": "6.12.1",
45
- "rimraf": "5.0.6",
45
+ "rimraf": "5.0.7",
46
46
  "typescript": "5.4.5",
47
47
  "zod": "3.23.8"
48
48
  }