@ci-kit/http 0.0.0-stage → 0.0.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.
@@ -0,0 +1,18 @@
1
+ interface RequestOptions {
2
+ timeoutMs?: number;
3
+ retries?: number;
4
+ retryDelayMs?: number;
5
+ }
6
+ declare class HttpError extends Error {
7
+ readonly url: string;
8
+ readonly status: number;
9
+ readonly body: string;
10
+ constructor(url: string, status: number, body: string);
11
+ }
12
+ declare function isRetryable(error: unknown): boolean;
13
+ declare function request(url: string, init?: RequestInit, options?: RequestOptions): Promise<Response>;
14
+ declare function requestJson<T>(url: string, init?: RequestInit, options?: RequestOptions): Promise<T>;
15
+ declare function requestBuffer(url: string, init?: RequestInit, options?: RequestOptions): Promise<Uint8Array>;
16
+
17
+ export { HttpError, isRetryable, request, requestBuffer, requestJson };
18
+ export type { RequestOptions };
@@ -0,0 +1,18 @@
1
+ interface RequestOptions {
2
+ timeoutMs?: number;
3
+ retries?: number;
4
+ retryDelayMs?: number;
5
+ }
6
+ declare class HttpError extends Error {
7
+ readonly url: string;
8
+ readonly status: number;
9
+ readonly body: string;
10
+ constructor(url: string, status: number, body: string);
11
+ }
12
+ declare function isRetryable(error: unknown): boolean;
13
+ declare function request(url: string, init?: RequestInit, options?: RequestOptions): Promise<Response>;
14
+ declare function requestJson<T>(url: string, init?: RequestInit, options?: RequestOptions): Promise<T>;
15
+ declare function requestBuffer(url: string, init?: RequestInit, options?: RequestOptions): Promise<Uint8Array>;
16
+
17
+ export { HttpError, isRetryable, request, requestBuffer, requestJson };
18
+ export type { RequestOptions };
package/dist/index.mjs ADDED
@@ -0,0 +1,62 @@
1
+ class HttpError extends Error {
2
+ constructor(url, status, body) {
3
+ super(`HTTP ${status} ${url}`);
4
+ this.url = url;
5
+ this.status = status;
6
+ this.body = body;
7
+ this.name = "HttpError";
8
+ }
9
+ }
10
+ const DEFAULT_TIMEOUT_MS = 6e4;
11
+ const DEFAULT_RETRIES = 2;
12
+ const DEFAULT_RETRY_DELAY_MS = 800;
13
+ function isRetryable(error) {
14
+ if (error instanceof HttpError) {
15
+ return error.status === 408 || error.status === 429 || error.status >= 500;
16
+ }
17
+ if (error instanceof Error) {
18
+ if (error.name === "TimeoutError" || error.name === "AbortError") {
19
+ return true;
20
+ }
21
+ return /fetch failed|ECONNRESET|ECONNREFUSED|ETIMEDOUT|EAI_AGAIN/i.test(error.message);
22
+ }
23
+ return false;
24
+ }
25
+ async function request(url, init = {}, options = {}) {
26
+ const {
27
+ timeoutMs = DEFAULT_TIMEOUT_MS,
28
+ retries = DEFAULT_RETRIES,
29
+ retryDelayMs = DEFAULT_RETRY_DELAY_MS
30
+ } = options;
31
+ let lastError;
32
+ for (let attempt = 0; attempt <= retries; attempt++) {
33
+ try {
34
+ const response = await fetch(url, {
35
+ ...init,
36
+ signal: AbortSignal.timeout(timeoutMs)
37
+ });
38
+ if (!response.ok) {
39
+ const body = await response.text().catch(() => "");
40
+ throw new HttpError(url, response.status, body.slice(0, 500));
41
+ }
42
+ return response;
43
+ } catch (error) {
44
+ lastError = error;
45
+ if (attempt === retries || !isRetryable(error)) {
46
+ throw error;
47
+ }
48
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs * 2 ** attempt));
49
+ }
50
+ }
51
+ throw lastError;
52
+ }
53
+ async function requestJson(url, init = {}, options = {}) {
54
+ const response = await request(url, init, options);
55
+ return await response.json();
56
+ }
57
+ async function requestBuffer(url, init = {}, options = {}) {
58
+ const response = await request(url, init, options);
59
+ return new Uint8Array(await response.arrayBuffer());
60
+ }
61
+
62
+ export { HttpError, isRetryable, request, requestBuffer, requestJson };
package/package.json CHANGED
@@ -1,6 +1,36 @@
1
1
  {
2
2
  "name": "@ci-kit/http",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "type": "module",
4
+ "version": "0.0.0",
5
+ "description": "Tiny fetch wrapper with timeout, retry and typed errors",
6
+ "author": "imba97",
7
+ "license": "MIT",
8
+ "homepage": "https://github.com/cikit-js/ci-kit#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/cikit-js/ci-kit.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/cikit-js/ci-kit/issues"
15
+ },
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.mts",
19
+ "import": "./dist/index.mjs"
20
+ }
21
+ },
22
+ "main": "./dist/index.mjs",
23
+ "module": "./dist/index.mjs",
24
+ "types": "./dist/index.d.mts",
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "scripts": {
32
+ "build": "unbuild",
33
+ "typecheck": "tsc --noEmit",
34
+ "stub": "unbuild --stub"
35
+ }
6
36
  }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.