@jamx/http 0.1.0 → 0.1.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.
@@ -1,4 +1,4 @@
1
- import { defineInterceptor, TimeoutError } from "./core.js";
1
+ import { defineInterceptor } from "./core.js";
2
2
  import { isErr, isOk, ok } from "./either.js";
3
3
  /**
4
4
  * Rebases a request URL onto a configured base URL while preserving the
@@ -6,79 +6,102 @@ import { isErr, isOk, ok } from "./either.js";
6
6
  *
7
7
  * @example
8
8
  * ```ts
9
- * import { composeInterceptors, defaultFetch, withBaseUrl } from "@jamx/http";
9
+ * import { compose, defaultFetch, withBaseUrl } from "@jamx/http";
10
10
  *
11
- * const fetcher = composeInterceptors(
12
- * withBaseUrl("https://api.example.com/v1"),
13
- * )(defaultFetch);
11
+ * const fetcher = compose(withBaseUrl("https://api.example.com/v1"))(defaultFetch);
14
12
  * ```
15
13
  */
16
- export const withBaseUrl = (baseUrl) => defineInterceptor(async ({ request, next }) => {
17
- const currentUrl = new URL(request.url);
18
- const url = new URL(`${trimTrailingSlash(baseUrl.toString())}/${trimLeadingSlash(`${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`)}`);
19
- return next(new Request(url, request));
20
- });
14
+ export function withBaseUrl(base_url) {
15
+ return defineInterceptor(async ({ request, next }) => {
16
+ const { input, init } = request;
17
+ const current_url = getUrl(input, base_url);
18
+ const url = new URL(`${trimTrailingSlash(base_url.toString())}/${trimLeadingSlash(`${current_url.pathname}${current_url.search}${current_url.hash}`)}`);
19
+ return next({
20
+ input: input instanceof Request ? new Request(url, input) : url,
21
+ init,
22
+ });
23
+ });
24
+ }
21
25
  /**
22
26
  * Merges additional headers into the outgoing request.
23
27
  *
24
28
  * @example
25
29
  * ```ts
26
- * import { composeInterceptors, defaultFetch, withHeaders } from "@jamx/http";
30
+ * import { compose, defaultFetch, withHeaders } from "@jamx/http";
27
31
  *
28
- * const fetcher = composeInterceptors(
32
+ * const fetcher = compose(
29
33
  * withHeaders({ accept: "application/json" }),
30
34
  * )(defaultFetch);
31
35
  * ```
32
36
  */
33
- export const withHeaders = (headers) => defineInterceptor(async ({ request, next }) => {
34
- const nextHeaders = new Headers(request.headers);
35
- const extraHeaders = typeof headers === "function" ? headers(request) : headers;
36
- new Headers(extraHeaders).forEach((value, key) => {
37
- nextHeaders.set(key, value);
37
+ export function withHeaders(headers) {
38
+ return defineInterceptor(async ({ request, next }) => {
39
+ const { input, init } = request;
40
+ const next_headers = getHeaders(input, init);
41
+ const extra_headers = typeof headers === "function"
42
+ ? headers(new Request(input, init))
43
+ : headers;
44
+ new Headers(extra_headers).forEach((value, key) => {
45
+ next_headers.set(key, value);
46
+ });
47
+ return next({
48
+ input,
49
+ init: { ...init, headers: next_headers },
50
+ });
38
51
  });
39
- return next(new Request(request, { headers: nextHeaders }));
40
- });
52
+ }
41
53
  /**
42
54
  * Adds an `Authorization` header using the given token and scheme.
43
55
  *
44
56
  * @example
45
57
  * ```ts
46
- * import { composeInterceptors, defaultFetch, withAuth } from "@jamx/http";
58
+ * import { compose, defaultFetch, withAuth } from "@jamx/http";
47
59
  *
48
- * const fetcher = composeInterceptors(withAuth("demo-token"))(defaultFetch);
60
+ * const fetcher = compose(withAuth("demo-token"))(defaultFetch);
49
61
  * ```
50
62
  */
51
- export const withAuth = (token, scheme = "Bearer") => defineInterceptor(async ({ request, next }) => {
52
- const resolvedToken = typeof token === "function" ? token(request) : token;
53
- const headers = new Headers(request.headers);
54
- headers.set("authorization", `${scheme} ${resolvedToken}`);
55
- return next(new Request(request, { headers }));
56
- });
63
+ export function withAuth(token, scheme = "Bearer") {
64
+ return defineInterceptor(async ({ request, next }) => {
65
+ const { input, init } = request;
66
+ const resolvedToken = typeof token === "function" ? token(new Request(input, init)) : token;
67
+ const headers = getHeaders(input, init);
68
+ headers.set("authorization", `${scheme} ${resolvedToken}`);
69
+ return next({ input, init: { ...init, headers } });
70
+ });
71
+ }
57
72
  /**
58
73
  * Aborts requests that take longer than the given timeout.
59
74
  *
60
75
  * @example
61
76
  * ```ts
62
- * import { composeInterceptors, defaultFetch, withTimeout } from "@jamx/http";
77
+ * import { compose, defaultFetch, withTimeout } from "@jamx/http";
63
78
  *
64
- * const fetcher = composeInterceptors(withTimeout(500))(defaultFetch);
79
+ * const fetcher = compose(withTimeout(500))(defaultFetch);
65
80
  * ```
66
81
  */
82
+ export class TimeoutError extends Error {
83
+ constructor(timeoutMs, cause) {
84
+ super(`Fetch request timed out after ${timeoutMs}ms.`, { cause });
85
+ this.name = "TimeoutError";
86
+ this._tag = "FetchError";
87
+ this.timeoutMs = timeoutMs;
88
+ }
89
+ }
67
90
  export const withTimeout = (timeoutMs) => defineInterceptor(async ({ request, next }) => {
91
+ const { input, init } = request;
68
92
  const controller = new AbortController();
69
93
  const timeout = setTimeout(() => controller.abort(), timeoutMs);
70
- const timedRequest = new Request(request, {
71
- signal: mergeSignals(request.signal, controller.signal),
72
- });
94
+ const signal = mergeSignals(getSignal(input, init), controller.signal);
95
+ const timed_request = {
96
+ input,
97
+ init: { ...init, signal },
98
+ };
73
99
  try {
74
100
  return await Promise.race([
75
- next(timedRequest),
101
+ next(timed_request),
76
102
  new Promise((resolve) => {
77
- timedRequest.signal.addEventListener("abort", () => {
78
- resolve({
79
- ok: false,
80
- error: new TimeoutError(timeoutMs),
81
- });
103
+ signal.addEventListener("abort", () => {
104
+ resolve({ ok: false, error: new TimeoutError(timeoutMs) });
82
105
  }, { once: true });
83
106
  }),
84
107
  ]);
@@ -87,10 +110,9 @@ export const withTimeout = (timeoutMs) => defineInterceptor(async ({ request, ne
87
110
  clearTimeout(timeout);
88
111
  }
89
112
  });
90
- const mergeSignals = (left, right) => {
91
- if (!left) {
113
+ function mergeSignals(left, right) {
114
+ if (!left)
92
115
  return right;
93
- }
94
116
  const anySignal = AbortSignal;
95
117
  if (typeof anySignal.any === "function") {
96
118
  return anySignal.any([left, right]);
@@ -104,71 +126,50 @@ const mergeSignals = (left, right) => {
104
126
  left.addEventListener("abort", abort, { once: true });
105
127
  right.addEventListener("abort", abort, { once: true });
106
128
  return controller.signal;
107
- };
108
- /**
109
- * Retries idempotent requests when they fail with transport errors or `5xx`
110
- * responses.
111
- *
112
- * @example
113
- * ```ts
114
- * import { composeInterceptors, defaultFetch, withRetry } from "@jamx/http";
115
- *
116
- * const fetcher = composeInterceptors(withRetry({ retries: 2 }))(defaultFetch);
117
- * ```
118
- */
119
- export const withRetry = (options) => defineInterceptor(async ({ request, next }) => {
120
- for (let attempt = 0; attempt <= options.retries; attempt += 1) {
121
- const attemptRequest = new Request(request);
122
- const result = await next(attemptRequest);
123
- const shouldRetry = await shouldRetryResult(result, attempt, request, options);
124
- if (!shouldRetry) {
125
- return result;
129
+ }
130
+ export function withRetry(options) {
131
+ return defineInterceptor(async ({ request, next }) => {
132
+ for (let attempt = 0; attempt <= options.retries; attempt += 1) {
133
+ const attempt_request = cloneInput(request);
134
+ const result = await next(attempt_request);
135
+ const should_retry = await shouldRetryResult(result, attempt, request, options);
136
+ if (!should_retry)
137
+ return result;
126
138
  }
127
- }
128
- return next(new Request(request));
129
- });
130
- const shouldRetryResult = async (result, attempt, request, options) => {
139
+ return next(cloneInput(request));
140
+ });
141
+ }
142
+ async function shouldRetryResult(result, attempt, request, options) {
131
143
  if (attempt >= options.retries) {
132
144
  return false;
133
145
  }
134
- if (!isRetryableMethod(request.method, options.methods)) {
146
+ if (!isRetryableMethod(getMethod(request.input, request.init), options.methods)) {
135
147
  return false;
136
148
  }
137
149
  if (options.shouldRetry) {
138
150
  return options.shouldRetry(result, attempt, request);
139
151
  }
140
152
  return isErr(result) || (isOk(result) && result.value.status >= 500);
141
- };
142
- /**
143
- * Caches successful `GET` responses in a store.
144
- *
145
- * @example
146
- * ```ts
147
- * import { composeInterceptors, createMemoryCacheStore, defaultFetch, withCache } from "@jamx/http";
148
- *
149
- * const store = createMemoryCacheStore();
150
- * const fetcher = composeInterceptors(withCache({ store }))(defaultFetch);
151
- * ```
152
- */
153
- export const withCache = (options = {}) => {
153
+ }
154
+ export function withCache(options = {}) {
154
155
  const store = options.store ?? createMemoryCacheStore();
155
156
  return defineInterceptor(async ({ request, next }) => {
157
+ const { input, init } = request;
156
158
  const key = (options.key ?? defaultCacheKey)(request);
157
- if (request.method === "GET") {
159
+ if (getMethod(input, init) === "GET") {
158
160
  const cached = await store.get(key);
159
- if (cached) {
161
+ if (cached)
160
162
  return ok(cached.clone());
161
- }
162
163
  }
163
- const result = await next(new Request(request));
164
- if (request.method === "GET" &&
164
+ const result = await next(cloneInput(request));
165
+ if (getMethod(input, init) === "GET" &&
165
166
  isOk(result) &&
166
167
  (options.shouldCache ?? defaultShouldCache)(result, request)) {
167
168
  await store.set(key, result.value.clone());
168
169
  }
169
170
  return result;
170
171
  });
171
- };
172
+ }
172
173
  /**
173
174
  * Creates an in-memory cache store compatible with `withCache`.
174
175
  *
@@ -179,7 +180,7 @@ export const withCache = (options = {}) => {
179
180
  * const store = createMemoryCacheStore();
180
181
  * ```
181
182
  */
182
- export const createMemoryCacheStore = () => {
183
+ export function createMemoryCacheStore() {
183
184
  const store = new Map();
184
185
  return {
185
186
  get(key) {
@@ -190,16 +191,20 @@ export const createMemoryCacheStore = () => {
190
191
  store.set(key, response.clone());
191
192
  },
192
193
  };
194
+ }
195
+ const defaultShouldCache = (result) => {
196
+ return isOk(result) && result.value.ok;
197
+ };
198
+ const defaultCacheKey = (request) => {
199
+ return `${getMethod(request.input, request.init)}:${getUrl(request.input).href}:${serializeHeaders(getHeaders(request.input, request.init))}`;
193
200
  };
194
- const defaultShouldCache = (result) => isOk(result) && result.value.ok;
195
- const defaultCacheKey = (request) => `${request.method}:${request.url}:${serializeHeaders(request.headers)}`;
196
201
  const DEFAULT_RETRY_METHODS = new Set([
197
- "DELETE",
198
202
  "GET",
199
- "HEAD",
200
- "OPTIONS",
201
203
  "PUT",
204
+ "HEAD",
202
205
  "TRACE",
206
+ "DELETE",
207
+ "OPTIONS",
203
208
  ]);
204
209
  const isRetryableMethod = (method, methods) => {
205
210
  const normalizedMethod = method.toUpperCase();
@@ -217,3 +222,30 @@ const serializeHeaders = (headers) => {
217
222
  };
218
223
  const trimLeadingSlash = (value) => value.replace(/^\/+/, "");
219
224
  const trimTrailingSlash = (value) => value.replace(/\/+$/, "");
225
+ const getUrl = (input, base) => {
226
+ if (input instanceof Request) {
227
+ return new URL(input.url);
228
+ }
229
+ return new URL(input, base);
230
+ };
231
+ const getHeaders = (input, init) => {
232
+ const headers = new Headers(input instanceof Request ? input.headers : init?.headers);
233
+ if (input instanceof Request && init?.headers) {
234
+ new Headers(init.headers).forEach((value, key) => {
235
+ headers.set(key, value);
236
+ });
237
+ }
238
+ return headers;
239
+ };
240
+ const getSignal = (input, init) => {
241
+ return init?.signal ?? (input instanceof Request ? input.signal : null);
242
+ };
243
+ const getMethod = (input, init) => {
244
+ return (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase();
245
+ };
246
+ const cloneInput = (request) => {
247
+ return {
248
+ input: request.input instanceof Request ? request.input.clone() : request.input,
249
+ init: request.init,
250
+ };
251
+ };
@@ -1,4 +1,4 @@
1
- import { Either } from "../either.js";
1
+ import { type Either } from "../either.js";
2
2
  export declare class StatusError extends Error {
3
3
  name: string;
4
4
  readonly status: number;
@@ -18,7 +18,7 @@ export declare class StatusError extends Error {
18
18
  * const result = expectStatus(ok(new Response(null, { status: 200 })), 200);
19
19
  * ```
20
20
  */
21
- export declare const expectStatus: <TError>(result: Either<TError, Response>, expected: number | readonly number[]) => Either<TError | StatusError, Response>;
21
+ export declare function expectStatus<TError>(result: Either<TError, Response>, expected: number | readonly number[]): Either<TError | StatusError, Response>;
22
22
  /**
23
23
  * Asserts that a response status satisfies a custom predicate.
24
24
  *
@@ -33,14 +33,14 @@ export declare const expectStatus: <TError>(result: Either<TError, Response>, ex
33
33
  * );
34
34
  * ```
35
35
  */
36
- export declare const expectStatusRange: <TError>(result: Either<TError, Response>, predicate: (status: number) => boolean, description?: string) => Either<TError | StatusError, Response>;
37
- export declare const isInformationalStatus: (status: number) => boolean;
38
- export declare const isOkStatus: (status: number) => boolean;
39
- export declare const isRedirectStatus: (status: number) => boolean;
40
- export declare const isClientErrorStatus: (status: number) => boolean;
41
- export declare const isServerErrorStatus: (status: number) => boolean;
42
- export declare const isErrorStatus: (status: number) => boolean;
43
- export declare const expectInformationalStatus: <TError>(result: Either<TError, Response>) => Either<TError | StatusError, Response>;
36
+ export declare function expectStatusRange<TError>(result: Either<TError, Response>, predicate: (status: number) => boolean, description?: string): Either<TError | StatusError, Response>;
37
+ export declare function isInformationalStatus(status: number): boolean;
38
+ export declare function isOkStatus(status: number): boolean;
39
+ export declare function isRedirectStatus(status: number): boolean;
40
+ export declare function isClientErrorStatus(status: number): boolean;
41
+ export declare function isServerErrorStatus(status: number): boolean;
42
+ export declare function isErrorStatus(status: number): boolean;
43
+ export declare function expectInformationalStatus<TError>(result: Either<TError, Response>): Either<TError | StatusError, Response>;
44
44
  /**
45
45
  * Asserts that a response has a successful `2xx` status.
46
46
  *
@@ -51,9 +51,9 @@ export declare const expectInformationalStatus: <TError>(result: Either<TError,
51
51
  * const result = expectOKStatus(ok(new Response(null, { status: 204 })));
52
52
  * ```
53
53
  */
54
- export declare const expectOKStatus: <TError>(result: Either<TError, Response>) => Either<TError | StatusError, Response>;
55
- export declare const expectRedirectStatus: <TError>(result: Either<TError, Response>) => Either<TError | StatusError, Response>;
56
- export declare const expectClientErrorStatus: <TError>(result: Either<TError, Response>) => Either<TError | StatusError, Response>;
57
- export declare const expectServerErrorStatus: <TError>(result: Either<TError, Response>) => Either<TError | StatusError, Response>;
58
- export declare const expectErrorStatus: <TError>(result: Either<TError, Response>) => Either<TError | StatusError, Response>;
54
+ export declare function expectOKStatus<TError>(result: Either<TError, Response>): Either<TError | StatusError, Response>;
55
+ export declare function expectRedirectStatus<TError>(result: Either<TError, Response>): Either<TError | StatusError, Response>;
56
+ export declare function expectClientErrorStatus<TError>(result: Either<TError, Response>): Either<TError | StatusError, Response>;
57
+ export declare function expectServerErrorStatus<TError>(result: Either<TError, Response>): Either<TError | StatusError, Response>;
58
+ export declare function expectErrorStatus<TError>(result: Either<TError, Response>): Either<TError | StatusError, Response>;
59
59
  //# sourceMappingURL=validators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../src/internal/statuses/validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,cAAc,CAAC;AAElD,qBAAa,WAAY,SAAQ,KAAK;IACpC,IAAI,SAAiB;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC;gBAGrD,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,MAAM,EAC7C,OAAO,SAA+C;CAQzD;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,EACjC,QAAQ,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EAChC,UAAU,MAAM,GAAG,SAAS,MAAM,EAAE,KACnC,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAgBvC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,EACtC,QAAQ,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EAChC,WAAW,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,EACtC,oBAAiC,KAChC,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAYvC,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,QAAQ,MAAM,YACrB,CAAC;AAEhC,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,YAAkC,CAAC;AAE5E,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,YAChB,CAAC;AAEhC,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM,YACnB,CAAC;AAEhC,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM,YACnB,CAAC;AAEhC,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,YACgB,CAAC;AAE7D,eAAO,MAAM,yBAAyB,GAAI,MAAM,EAC9C,QAAQ,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,KAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAKrC,CAAC;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,EACnC,QAAQ,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,KAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAC4B,CAAC;AAErE,eAAO,MAAM,oBAAoB,GAAI,MAAM,EACzC,QAAQ,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,KAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CACgC,CAAC;AAEzE,eAAO,MAAM,uBAAuB,GAAI,MAAM,EAC5C,QAAQ,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,KAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CACuC,CAAC;AAEhF,eAAO,MAAM,uBAAuB,GAAI,MAAM,EAC5C,QAAQ,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,KAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CACuC,CAAC;AAEhF,eAAO,MAAM,iBAAiB,GAAI,MAAM,EACtC,QAAQ,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,KAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CACkC,CAAC"}
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../src/internal/statuses/validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAc,MAAM,cAAc,CAAC;AAEvD,qBAAa,WAAY,SAAQ,KAAK;IACpC,IAAI,SAAiB;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC;gBAGrD,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,MAAM,EAC7C,OAAO,SAA+C;CAQzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,MAAM,EACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EAChC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GACnC,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAAC,CAgBxC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EAChC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,EACtC,WAAW,SAAsB,GAChC,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAAC,CAYxC;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,WAEnD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,WAExC;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,WAE9C;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,WAEjD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,WAEjD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,WAE3C;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAC9C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAAC,CAMxC;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,MAAM,EACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAAC,CAExC;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EACzC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAAC,CAExC;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAC5C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAAC,CAMxC;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAC5C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAAC,CAMxC;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC/B,MAAM,CAAC,MAAM,GAAG,WAAW,EAAE,QAAQ,CAAC,CAMxC"}
@@ -20,7 +20,7 @@ export class StatusError extends Error {
20
20
  * const result = expectStatus(ok(new Response(null, { status: 200 })), 200);
21
21
  * ```
22
22
  */
23
- export const expectStatus = (result, expected) => {
23
+ export function expectStatus(result, expected) {
24
24
  if (isErr(result))
25
25
  return result;
26
26
  const matches = Array.isArray(expected)
@@ -29,7 +29,7 @@ export const expectStatus = (result, expected) => {
29
29
  return matches
30
30
  ? result
31
31
  : err(new StatusError(result.value, expected, `Expected status ${formatExpectedStatus(expected)} but received ${result.value.status}.`));
32
- };
32
+ }
33
33
  /**
34
34
  * Asserts that a response status satisfies a custom predicate.
35
35
  *
@@ -44,20 +44,34 @@ export const expectStatus = (result, expected) => {
44
44
  * );
45
45
  * ```
46
46
  */
47
- export const expectStatusRange = (result, predicate, description = "a matching status") => {
47
+ export function expectStatusRange(result, predicate, description = "a matching status") {
48
48
  if (isErr(result))
49
49
  return result;
50
50
  return predicate(result.value.status)
51
51
  ? result
52
52
  : err(new StatusError(result.value, description, `Expected ${description} but received ${result.value.status}.`));
53
- };
54
- export const isInformationalStatus = (status) => status >= 100 && status < 200;
55
- export const isOkStatus = (status) => status >= 200 && status < 300;
56
- export const isRedirectStatus = (status) => status >= 300 && status < 400;
57
- export const isClientErrorStatus = (status) => status >= 400 && status < 500;
58
- export const isServerErrorStatus = (status) => status >= 500 && status < 600;
59
- export const isErrorStatus = (status) => isClientErrorStatus(status) || isServerErrorStatus(status);
60
- export const expectInformationalStatus = (result) => expectStatusRange(result, isInformationalStatus, "an informational status (1xx)");
53
+ }
54
+ export function isInformationalStatus(status) {
55
+ return status >= 100 && status < 200;
56
+ }
57
+ export function isOkStatus(status) {
58
+ return status >= 200 && status < 300;
59
+ }
60
+ export function isRedirectStatus(status) {
61
+ return status >= 300 && status < 400;
62
+ }
63
+ export function isClientErrorStatus(status) {
64
+ return status >= 400 && status < 500;
65
+ }
66
+ export function isServerErrorStatus(status) {
67
+ return status >= 500 && status < 600;
68
+ }
69
+ export function isErrorStatus(status) {
70
+ return isClientErrorStatus(status) || isServerErrorStatus(status);
71
+ }
72
+ export function expectInformationalStatus(result) {
73
+ return expectStatusRange(result, isInformationalStatus, "an informational status (1xx)");
74
+ }
61
75
  /**
62
76
  * Asserts that a response has a successful `2xx` status.
63
77
  *
@@ -68,11 +82,21 @@ export const expectInformationalStatus = (result) => expectStatusRange(result, i
68
82
  * const result = expectOKStatus(ok(new Response(null, { status: 204 })));
69
83
  * ```
70
84
  */
71
- export const expectOKStatus = (result) => expectStatusRange(result, isOkStatus, "a successful status (2xx)");
72
- export const expectRedirectStatus = (result) => expectStatusRange(result, isRedirectStatus, "a redirect status (3xx)");
73
- export const expectClientErrorStatus = (result) => expectStatusRange(result, isClientErrorStatus, "a client error status (4xx)");
74
- export const expectServerErrorStatus = (result) => expectStatusRange(result, isServerErrorStatus, "a server error status (5xx)");
75
- export const expectErrorStatus = (result) => expectStatusRange(result, isErrorStatus, "an error status (4xx or 5xx)");
85
+ export function expectOKStatus(result) {
86
+ return expectStatusRange(result, isOkStatus, "a successful status (2xx)");
87
+ }
88
+ export function expectRedirectStatus(result) {
89
+ return expectStatusRange(result, isRedirectStatus, "a redirect status (3xx)");
90
+ }
91
+ export function expectClientErrorStatus(result) {
92
+ return expectStatusRange(result, isClientErrorStatus, "a client error status (4xx)");
93
+ }
94
+ export function expectServerErrorStatus(result) {
95
+ return expectStatusRange(result, isServerErrorStatus, "a server error status (5xx)");
96
+ }
97
+ export function expectErrorStatus(result) {
98
+ return expectStatusRange(result, isErrorStatus, "an error status (4xx or 5xx)");
99
+ }
76
100
  function formatExpectedStatus(expected) {
77
101
  return Array.isArray(expected) ? expected.join(", ") : String(expected);
78
102
  }
@@ -1,3 +1,3 @@
1
- import { Either } from "./either.js";
1
+ import type { Either } from "./either.js";
2
2
  export type AnyEither = Either<any, any>;
3
3
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/internal/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/internal/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC"}