@ethitrust/sdk 1.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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -0
  3. package/dist/client.d.ts +42 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +45 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/errors.d.ts +66 -0
  8. package/dist/errors.d.ts.map +1 -0
  9. package/dist/errors.js +115 -0
  10. package/dist/errors.js.map +1 -0
  11. package/dist/http.d.ts +49 -0
  12. package/dist/http.d.ts.map +1 -0
  13. package/dist/http.js +193 -0
  14. package/dist/http.js.map +1 -0
  15. package/dist/index.d.ts +10 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +7 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/resources/orgEscrows.d.ts +53 -0
  20. package/dist/resources/orgEscrows.d.ts.map +1 -0
  21. package/dist/resources/orgEscrows.js +168 -0
  22. package/dist/resources/orgEscrows.js.map +1 -0
  23. package/dist/types.d.ts +229 -0
  24. package/dist/types.d.ts.map +1 -0
  25. package/dist/types.js +6 -0
  26. package/dist/types.js.map +1 -0
  27. package/dist/utils/idempotency.d.ts +9 -0
  28. package/dist/utils/idempotency.d.ts.map +1 -0
  29. package/dist/utils/idempotency.js +25 -0
  30. package/dist/utils/idempotency.js.map +1 -0
  31. package/dist/utils/query.d.ts +8 -0
  32. package/dist/utils/query.d.ts.map +1 -0
  33. package/dist/utils/query.js +35 -0
  34. package/dist/utils/query.js.map +1 -0
  35. package/package.json +51 -0
  36. package/src/client.ts +69 -0
  37. package/src/errors.ts +140 -0
  38. package/src/http.ts +246 -0
  39. package/src/index.ts +23 -0
  40. package/src/resources/orgEscrows.ts +246 -0
  41. package/src/types.ts +286 -0
  42. package/src/utils/idempotency.ts +23 -0
  43. package/src/utils/query.ts +31 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ethitrust
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # @ethitrust/sdk
2
+
3
+ Official **TypeScript / Node** SDK for the Ethitrust **org-escrows** API.
4
+
5
+ * Strongly typed against the OpenAPI spec (`ethi-mono v0.1.0`)
6
+ * Hand-crafted ergonomic surface — no codegen runtime
7
+ * Built-in retries, timeouts, and idempotency-key generation
8
+ * Async pagination iterator
9
+ * Rich error hierarchy mapped from HTTP status codes
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pnpm add @ethitrust/sdk
15
+ # or
16
+ npm install @ethitrust/sdk
17
+ ```
18
+
19
+ Requires **Node 18+** (uses the global `fetch`).
20
+
21
+ ## Quick start
22
+
23
+ ```ts
24
+ import { EthitrustClient } from '@ethitrust/sdk';
25
+
26
+ const client = new EthitrustClient({
27
+ apiKey: process.env.ETHITRUST_API_KEY!, // sent as X-API-Key
28
+ baseUrl: 'https://api.ethitrust.me', // default
29
+ });
30
+
31
+ const escrow = await client.orgEscrows.create({
32
+ invitee_email: 'buyer@example.com',
33
+ title: 'Website redesign',
34
+ amount: 5000,
35
+ currency: 'ETB',
36
+ escrow_type: 'milestone',
37
+ who_pays_fees: 'split',
38
+ milestones: [
39
+ { title: 'Wireframes', amount: 1500 },
40
+ { title: 'Final delivery', amount: 3500 },
41
+ ],
42
+ });
43
+ ```
44
+
45
+ ## Configuration
46
+
47
+ | Option | Default | Description |
48
+ |---|---|---|
49
+ | `apiKey` | — *(required)* | Organization API key. |
50
+ | `baseUrl` | `https://api.ethitrust.me` | API host. Bare hostnames are auto-prefixed with `https://`. |
51
+ | `apiKeyHeader` | `X-API-Key` | Header name carrying the key. |
52
+ | `timeoutMs` | `30000` | Per-request timeout. |
53
+ | `maxRetries` | `2` | Retries for transient failures (GET / `429` / `5xx`). |
54
+ | `fetch` | global `fetch` | Custom fetch implementation. |
55
+ | `defaultHeaders` | `{}` | Extra headers on every request. |
56
+ | `userAgent` | `@ethitrust/sdk/1.0.0 node` | Override the User-Agent. |
57
+
58
+ ## API surface
59
+
60
+ Every method lives on `client.orgEscrows`.
61
+
62
+ | Method | HTTP | Endpoint |
63
+ |---|---|---|
64
+ | `create(body, extras?)` | POST | `/api/v1/org-escrows` |
65
+ | `list(params?, extras?)` | GET | `/api/v1/org-escrows` |
66
+ | `iter(params?, extras?)` *(async iterator)* | GET | `/api/v1/org-escrows` (auto-paginated) |
67
+ | `getStatus(id, extras?)` | GET | `/api/v1/org-escrows/{id}` |
68
+ | `getDetail(id, extras?)` | GET | `/api/v1/org-escrows/{id}/detail` |
69
+ | `getEvents(id, extras?)` | GET | `/api/v1/org-escrows/{id}/events` |
70
+ | `getHealth(id, extras?)` | GET | `/api/v1/org-escrows/{id}/health` |
71
+ | `cancel(id, extras?)` | POST | `/api/v1/org-escrows/{id}/cancel` |
72
+ | `resendInvitation(id, extras?)` | POST | `/api/v1/org-escrows/{id}/resend` |
73
+ | `getReport(params?, extras?)` | GET | `/api/v1/org-escrows/reports/summary` |
74
+ | `listEscrowWebhookLogs(id, extras?)` | GET | `/api/v1/org-escrows/{id}/webhooks` |
75
+ | `listWebhookLogs(extras?)` | GET | `/api/v1/org-escrows/webhooks` |
76
+ | `testWebhook(extras?)` | POST | `/api/v1/org-escrows/webhooks/test` |
77
+
78
+ ### Pagination iterator
79
+
80
+ ```ts
81
+ for await (const item of client.orgEscrows.iter({ status: 'active' })) {
82
+ console.log(item.escrow_id, item.title);
83
+ }
84
+ ```
85
+
86
+ ### Idempotency keys
87
+
88
+ Every write method (`create`, `cancel`, `resendInvitation`, `testWebhook`) **auto-generates** a UUID v4 idempotency key and sends it as `X-Idempotency-Key`. Override it (e.g. to dedupe a retried business operation) or disable it explicitly:
89
+
90
+ ```ts
91
+ await client.orgEscrows.create(body, { idempotencyKey: 'order-42' });
92
+ await client.orgEscrows.create(body, { idempotencyKey: null }); // disable
93
+ ```
94
+
95
+ Or generate one yourself:
96
+
97
+ ```ts
98
+ import { generateIdempotencyKey } from '@ethitrust/sdk';
99
+ const key = generateIdempotencyKey('order');
100
+ ```
101
+
102
+ ### Timeouts & cancellation
103
+
104
+ ```ts
105
+ const ac = new AbortController();
106
+ setTimeout(() => ac.abort(), 5000);
107
+
108
+ await client.orgEscrows.list({ status: 'active' }, {
109
+ signal: ac.signal,
110
+ timeoutMs: 10_000,
111
+ });
112
+ ```
113
+
114
+ ### Error handling
115
+
116
+ ```ts
117
+ import {
118
+ EthitrustApiError,
119
+ EthitrustAuthError,
120
+ EthitrustNotFoundError,
121
+ EthitrustValidationError,
122
+ EthitrustRateLimitError,
123
+ EthitrustNetworkError,
124
+ } from '@ethitrust/sdk';
125
+
126
+ try {
127
+ await client.orgEscrows.create(/* … */);
128
+ } catch (err) {
129
+ if (err instanceof EthitrustValidationError) {
130
+ for (const e of err.errors) console.error(e.loc.join('.'), e.msg);
131
+ } else if (err instanceof EthitrustAuthError) {
132
+ // invalid / expired API key
133
+ } else if (err instanceof EthitrustRateLimitError) {
134
+ console.warn('Retry after', err.retryAfter, 'seconds');
135
+ } else if (err instanceof EthitrustApiError) {
136
+ console.error(err.status, err.body);
137
+ } else if (err instanceof EthitrustNetworkError) {
138
+ // DNS / TCP / timeout
139
+ }
140
+ }
141
+ ```
142
+
143
+ Mapping:
144
+
145
+ | HTTP | Error class |
146
+ |---|---|
147
+ | 401 / 403 | `EthitrustAuthError` |
148
+ | 404 | `EthitrustNotFoundError` |
149
+ | 409 | `EthitrustConflictError` |
150
+ | 422 | `EthitrustValidationError` |
151
+ | 429 | `EthitrustRateLimitError` (auto-retried with `Retry-After`) |
152
+ | other 4xx | `EthitrustApiError` |
153
+ | 5xx | `EthitrustApiError` (GETs auto-retried) |
154
+ | fetch/timeout | `EthitrustNetworkError` / `EthitrustAbortError` |
155
+
156
+ ### Retries
157
+
158
+ By default the SDK retries:
159
+ * **GET** requests on `5xx` responses, network errors and timeouts,
160
+ * **any method** on `429`, honoring `Retry-After`,
161
+
162
+ up to `maxRetries` (default `2`) with exponential backoff + jitter capped at 10 s.
163
+
164
+ POST / PATCH / DELETE are **not** retried on `5xx` automatically; combined with the auto-generated idempotency key, you can safely retry them yourself.
165
+
166
+ ## Development
167
+
168
+ ```bash
169
+ pnpm install
170
+ pnpm build
171
+ pnpm test # runs node --test against ./dist (build first)
172
+ pnpm example # runs examples/basic.ts via tsx
173
+ ```
174
+
175
+ ## License
176
+
177
+ MIT
@@ -0,0 +1,42 @@
1
+ import { HttpClient } from './http.js';
2
+ import { OrgEscrowsResource } from './resources/orgEscrows.js';
3
+ export interface EthitrustClientOptions {
4
+ /** Organization API key. Sent as `X-API-Key` (configurable). */
5
+ apiKey: string;
6
+ /**
7
+ * Base URL. Defaults to `https://api.ethitrust.me`. Accepts host with or
8
+ * without scheme — if missing, `https://` is assumed.
9
+ */
10
+ baseUrl?: string;
11
+ /** Header carrying the API key. Defaults to `X-API-Key`. */
12
+ apiKeyHeader?: string;
13
+ /** Per-request timeout (ms). Defaults to 30 000. */
14
+ timeoutMs?: number;
15
+ /** Max retries for transient failures (GET / 429 / 5xx). Defaults to 2. */
16
+ maxRetries?: number;
17
+ /** Custom fetch (e.g. undici, node-fetch). */
18
+ fetch?: typeof fetch;
19
+ /** Extra headers applied to every request. */
20
+ defaultHeaders?: Record<string, string>;
21
+ /** User agent string. */
22
+ userAgent?: string;
23
+ }
24
+ /**
25
+ * Top-level entry point.
26
+ *
27
+ * ```ts
28
+ * import { EthitrustClient } from '@ethitrust/sdk';
29
+ * const client = new EthitrustClient({ apiKey: process.env.ETHITRUST_API_KEY! });
30
+ * const escrow = await client.orgEscrows.create({
31
+ * invitee_email: 'buyer@example.com',
32
+ * title: 'Website redesign',
33
+ * amount: 5000,
34
+ * });
35
+ * ```
36
+ */
37
+ export declare class EthitrustClient {
38
+ readonly http: HttpClient;
39
+ readonly orgEscrows: OrgEscrowsResource;
40
+ constructor(opts: EthitrustClientOptions);
41
+ }
42
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA0B,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACrC,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID;;;;;;;;;;;;GAYG;AACH,qBAAa,eAAe;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;gBAE5B,IAAI,EAAE,sBAAsB;CAkBzC"}
package/dist/client.js ADDED
@@ -0,0 +1,45 @@
1
+ import { HttpClient } from './http.js';
2
+ import { OrgEscrowsResource } from './resources/orgEscrows.js';
3
+ const DEFAULT_BASE_URL = 'https://api.ethitrust.me';
4
+ /**
5
+ * Top-level entry point.
6
+ *
7
+ * ```ts
8
+ * import { EthitrustClient } from '@ethitrust/sdk';
9
+ * const client = new EthitrustClient({ apiKey: process.env.ETHITRUST_API_KEY! });
10
+ * const escrow = await client.orgEscrows.create({
11
+ * invitee_email: 'buyer@example.com',
12
+ * title: 'Website redesign',
13
+ * amount: 5000,
14
+ * });
15
+ * ```
16
+ */
17
+ export class EthitrustClient {
18
+ http;
19
+ orgEscrows;
20
+ constructor(opts) {
21
+ if (!opts.apiKey) {
22
+ throw new Error('EthitrustClient: `apiKey` is required.');
23
+ }
24
+ const baseUrl = normaliseBaseUrl(opts.baseUrl ?? DEFAULT_BASE_URL);
25
+ const httpOpts = {
26
+ apiKey: opts.apiKey,
27
+ apiKeyHeader: opts.apiKeyHeader,
28
+ baseUrl,
29
+ timeoutMs: opts.timeoutMs,
30
+ maxRetries: opts.maxRetries,
31
+ fetch: opts.fetch,
32
+ defaultHeaders: opts.defaultHeaders,
33
+ userAgent: opts.userAgent,
34
+ };
35
+ this.http = new HttpClient(httpOpts);
36
+ this.orgEscrows = new OrgEscrowsResource(this.http);
37
+ }
38
+ }
39
+ function normaliseBaseUrl(input) {
40
+ const trimmed = input.trim();
41
+ if (/^https?:\/\//i.test(trimmed))
42
+ return trimmed;
43
+ return `https://${trimmed}`;
44
+ }
45
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA0B,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAwB/D,MAAM,gBAAgB,GAAG,0BAA0B,CAAC;AAEpD;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,eAAe;IACjB,IAAI,CAAa;IACjB,UAAU,CAAqB;IAExC,YAAY,IAA4B;QACtC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,IAAI,gBAAgB,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAsB;YAClC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,OAAO;YACP,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC;CACF;AAED,SAAS,gBAAgB,CAAC,KAAa;IACrC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAClD,OAAO,WAAW,OAAO,EAAE,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,66 @@
1
+ import type { ValidationErrorItem } from './types.js';
2
+ /** Base class for every error thrown by the SDK. */
3
+ export declare class EthitrustError extends Error {
4
+ constructor(message: string);
5
+ }
6
+ /** Thrown when the server returns a non-2xx HTTP status. */
7
+ export declare class EthitrustApiError extends EthitrustError {
8
+ readonly status: number;
9
+ readonly statusText: string;
10
+ readonly requestId?: string;
11
+ readonly url: string;
12
+ readonly method: string;
13
+ readonly body: unknown;
14
+ constructor(opts: {
15
+ status: number;
16
+ statusText: string;
17
+ url: string;
18
+ method: string;
19
+ body: unknown;
20
+ requestId?: string;
21
+ message?: string;
22
+ });
23
+ }
24
+ /** 422 Unprocessable Entity (FastAPI validation failure). */
25
+ export declare class EthitrustValidationError extends EthitrustApiError {
26
+ readonly errors: ValidationErrorItem[];
27
+ constructor(opts: ConstructorParameters<typeof EthitrustApiError>[0]);
28
+ }
29
+ /** 401 / 403 — invalid or insufficient credentials. */
30
+ export declare class EthitrustAuthError extends EthitrustApiError {
31
+ constructor(opts: ConstructorParameters<typeof EthitrustApiError>[0]);
32
+ }
33
+ /** 404. */
34
+ export declare class EthitrustNotFoundError extends EthitrustApiError {
35
+ constructor(opts: ConstructorParameters<typeof EthitrustApiError>[0]);
36
+ }
37
+ /** 409 — idempotency or business-rule conflict. */
38
+ export declare class EthitrustConflictError extends EthitrustApiError {
39
+ constructor(opts: ConstructorParameters<typeof EthitrustApiError>[0]);
40
+ }
41
+ /** 429 — too many requests. */
42
+ export declare class EthitrustRateLimitError extends EthitrustApiError {
43
+ readonly retryAfter?: number;
44
+ constructor(opts: ConstructorParameters<typeof EthitrustApiError>[0] & {
45
+ retryAfter?: number;
46
+ });
47
+ }
48
+ /** Network / fetch / timeout level failure. */
49
+ export declare class EthitrustNetworkError extends EthitrustError {
50
+ readonly cause?: unknown;
51
+ constructor(message: string, cause?: unknown);
52
+ }
53
+ /** Request was aborted (timeout or user signal). */
54
+ export declare class EthitrustAbortError extends EthitrustError {
55
+ constructor(message?: string);
56
+ }
57
+ export declare function buildApiError(opts: {
58
+ status: number;
59
+ statusText: string;
60
+ url: string;
61
+ method: string;
62
+ body: unknown;
63
+ requestId?: string;
64
+ retryAfter?: number;
65
+ }): EthitrustApiError;
66
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE3E,oDAAoD;AACpD,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED,4DAA4D;AAC5D,qBAAa,iBAAkB,SAAQ,cAAc;IACnD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;gBAEX,IAAI,EAAE;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,OAAO,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;CAcF;AAED,6DAA6D;AAC7D,qBAAa,wBAAyB,SAAQ,iBAAiB;IAC7D,QAAQ,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC;gBAE3B,IAAI,EAAE,qBAAqB,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC;CAMrE;AAED,uDAAuD;AACvD,qBAAa,kBAAmB,SAAQ,iBAAiB;gBAC3C,IAAI,EAAE,qBAAqB,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC;CAIrE;AAED,WAAW;AACX,qBAAa,sBAAuB,SAAQ,iBAAiB;gBAC/C,IAAI,EAAE,qBAAqB,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC;CAIrE;AAED,mDAAmD;AACnD,qBAAa,sBAAuB,SAAQ,iBAAiB;gBAC/C,IAAI,EAAE,qBAAqB,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC;CAIrE;AAED,+BAA+B;AAC/B,qBAAa,uBAAwB,SAAQ,iBAAiB;IAC5D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAE3B,IAAI,EAAE,qBAAqB,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,GAAG;QACzD,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB;CAMJ;AAED,+CAA+C;AAC/C,qBAAa,qBAAsB,SAAQ,cAAc;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;gBACb,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAK7C;AAED,oDAAoD;AACpD,qBAAa,mBAAoB,SAAQ,cAAc;gBACzC,OAAO,SAAoB;CAIxC;AAeD,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,iBAAiB,CAOpB"}
package/dist/errors.js ADDED
@@ -0,0 +1,115 @@
1
+ /** Base class for every error thrown by the SDK. */
2
+ export class EthitrustError extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = 'EthitrustError';
6
+ }
7
+ }
8
+ /** Thrown when the server returns a non-2xx HTTP status. */
9
+ export class EthitrustApiError extends EthitrustError {
10
+ status;
11
+ statusText;
12
+ requestId;
13
+ url;
14
+ method;
15
+ body;
16
+ constructor(opts) {
17
+ const detail = opts.message ??
18
+ extractMessage(opts.body) ??
19
+ `${opts.status} ${opts.statusText}`;
20
+ super(`Ethitrust API error ${opts.status}: ${detail}`);
21
+ this.name = 'EthitrustApiError';
22
+ this.status = opts.status;
23
+ this.statusText = opts.statusText;
24
+ this.url = opts.url;
25
+ this.method = opts.method;
26
+ this.body = opts.body;
27
+ this.requestId = opts.requestId;
28
+ }
29
+ }
30
+ /** 422 Unprocessable Entity (FastAPI validation failure). */
31
+ export class EthitrustValidationError extends EthitrustApiError {
32
+ errors;
33
+ constructor(opts) {
34
+ super(opts);
35
+ this.name = 'EthitrustValidationError';
36
+ const body = opts.body;
37
+ this.errors = body?.detail ?? [];
38
+ }
39
+ }
40
+ /** 401 / 403 — invalid or insufficient credentials. */
41
+ export class EthitrustAuthError extends EthitrustApiError {
42
+ constructor(opts) {
43
+ super(opts);
44
+ this.name = 'EthitrustAuthError';
45
+ }
46
+ }
47
+ /** 404. */
48
+ export class EthitrustNotFoundError extends EthitrustApiError {
49
+ constructor(opts) {
50
+ super(opts);
51
+ this.name = 'EthitrustNotFoundError';
52
+ }
53
+ }
54
+ /** 409 — idempotency or business-rule conflict. */
55
+ export class EthitrustConflictError extends EthitrustApiError {
56
+ constructor(opts) {
57
+ super(opts);
58
+ this.name = 'EthitrustConflictError';
59
+ }
60
+ }
61
+ /** 429 — too many requests. */
62
+ export class EthitrustRateLimitError extends EthitrustApiError {
63
+ retryAfter;
64
+ constructor(opts) {
65
+ super(opts);
66
+ this.name = 'EthitrustRateLimitError';
67
+ this.retryAfter = opts.retryAfter;
68
+ }
69
+ }
70
+ /** Network / fetch / timeout level failure. */
71
+ export class EthitrustNetworkError extends EthitrustError {
72
+ cause;
73
+ constructor(message, cause) {
74
+ super(message);
75
+ this.name = 'EthitrustNetworkError';
76
+ this.cause = cause;
77
+ }
78
+ }
79
+ /** Request was aborted (timeout or user signal). */
80
+ export class EthitrustAbortError extends EthitrustError {
81
+ constructor(message = 'Request aborted') {
82
+ super(message);
83
+ this.name = 'EthitrustAbortError';
84
+ }
85
+ }
86
+ function extractMessage(body) {
87
+ if (!body || typeof body !== 'object')
88
+ return undefined;
89
+ const b = body;
90
+ if (typeof b.message === 'string')
91
+ return b.message;
92
+ if (typeof b.error === 'string')
93
+ return b.error;
94
+ if (typeof b.detail === 'string')
95
+ return b.detail;
96
+ if (Array.isArray(b.detail) && b.detail.length > 0) {
97
+ const first = b.detail[0];
98
+ return `${first.msg} (at ${first.loc?.join('.') ?? '?'})`;
99
+ }
100
+ return undefined;
101
+ }
102
+ export function buildApiError(opts) {
103
+ if (opts.status === 401 || opts.status === 403)
104
+ return new EthitrustAuthError(opts);
105
+ if (opts.status === 404)
106
+ return new EthitrustNotFoundError(opts);
107
+ if (opts.status === 409)
108
+ return new EthitrustConflictError(opts);
109
+ if (opts.status === 422)
110
+ return new EthitrustValidationError(opts);
111
+ if (opts.status === 429)
112
+ return new EthitrustRateLimitError(opts);
113
+ return new EthitrustApiError(opts);
114
+ }
115
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ export interface HttpClientOptions {
2
+ apiKey: string;
3
+ baseUrl: string;
4
+ /** Header name carrying the API key. Defaults to `X-API-Key`. */
5
+ apiKeyHeader?: string;
6
+ /** Per-request timeout in milliseconds. Defaults to 30 000. */
7
+ timeoutMs?: number;
8
+ /** Max retries for transient failures (network, 429, 5xx). Defaults to 2. */
9
+ maxRetries?: number;
10
+ /** Base delay (ms) for exponential backoff. Defaults to 300. */
11
+ retryBaseDelayMs?: number;
12
+ /** Custom fetch implementation. Defaults to global `fetch`. */
13
+ fetch?: typeof fetch;
14
+ /** Extra headers added to every request. */
15
+ defaultHeaders?: Record<string, string>;
16
+ /** User agent appended to `User-Agent` (Node only). */
17
+ userAgent?: string;
18
+ }
19
+ export interface RequestOptions {
20
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
21
+ path: string;
22
+ query?: Record<string, unknown>;
23
+ body?: unknown;
24
+ /** Adds an `X-Idempotency-Key` header. */
25
+ idempotencyKey?: string;
26
+ /** Overrides per-request timeout. */
27
+ timeoutMs?: number;
28
+ /** Abort signal supplied by the caller. */
29
+ signal?: AbortSignal;
30
+ /** Extra headers for this request. */
31
+ headers?: Record<string, string>;
32
+ }
33
+ export declare class HttpClient {
34
+ readonly baseUrl: string;
35
+ private readonly apiKey;
36
+ private readonly apiKeyHeader;
37
+ private readonly timeoutMs;
38
+ private readonly maxRetries;
39
+ private readonly retryBaseDelayMs;
40
+ private readonly fetchImpl;
41
+ private readonly defaultHeaders;
42
+ constructor(opts: HttpClientOptions);
43
+ request<T>(opts: RequestOptions): Promise<T>;
44
+ private buildUrl;
45
+ private buildHeaders;
46
+ private shouldRetry;
47
+ private backoff;
48
+ }
49
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0CAA0C;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,qBAAa,UAAU;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;gBAE5C,IAAI,EAAE,iBAAiB;IAuB7B,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IA+ElD,OAAO,CAAC,QAAQ;IAMhB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,OAAO;CAKhB"}