@sinio/sdk 0.0.0-stage → 0.2.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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +136 -2
  3. package/dist/cjs/client.d.ts +75 -0
  4. package/dist/cjs/client.js +196 -0
  5. package/dist/cjs/client.js.map +1 -0
  6. package/dist/cjs/errors.d.ts +35 -0
  7. package/dist/cjs/errors.js +60 -0
  8. package/dist/cjs/errors.js.map +1 -0
  9. package/dist/cjs/http.d.ts +22 -0
  10. package/dist/cjs/http.js +139 -0
  11. package/dist/cjs/http.js.map +1 -0
  12. package/dist/cjs/index.d.ts +5 -0
  13. package/dist/cjs/index.js +27 -0
  14. package/dist/cjs/index.js.map +1 -0
  15. package/dist/cjs/package.json +1 -0
  16. package/dist/cjs/serialize.d.ts +49 -0
  17. package/dist/cjs/serialize.js +191 -0
  18. package/dist/cjs/serialize.js.map +1 -0
  19. package/dist/cjs/types.d.ts +126 -0
  20. package/dist/cjs/types.js +3 -0
  21. package/dist/cjs/types.js.map +1 -0
  22. package/dist/cjs/vocabularies.d.ts +23 -0
  23. package/dist/cjs/vocabularies.js +39 -0
  24. package/dist/cjs/vocabularies.js.map +1 -0
  25. package/dist/esm/client.d.ts +75 -0
  26. package/dist/esm/client.js +192 -0
  27. package/dist/esm/client.js.map +1 -0
  28. package/dist/esm/errors.d.ts +35 -0
  29. package/dist/esm/errors.js +49 -0
  30. package/dist/esm/errors.js.map +1 -0
  31. package/dist/esm/http.d.ts +22 -0
  32. package/dist/esm/http.js +134 -0
  33. package/dist/esm/http.js.map +1 -0
  34. package/dist/esm/index.d.ts +5 -0
  35. package/dist/esm/index.js +5 -0
  36. package/dist/esm/index.js.map +1 -0
  37. package/dist/esm/serialize.d.ts +49 -0
  38. package/dist/esm/serialize.js +179 -0
  39. package/dist/esm/serialize.js.map +1 -0
  40. package/dist/esm/types.d.ts +126 -0
  41. package/dist/esm/types.js +2 -0
  42. package/dist/esm/types.js.map +1 -0
  43. package/dist/esm/vocabularies.d.ts +23 -0
  44. package/dist/esm/vocabularies.js +35 -0
  45. package/dist/esm/vocabularies.js.map +1 -0
  46. package/package.json +43 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ternatek
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 CHANGED
@@ -1,3 +1,137 @@
1
- # Temporary Holding Version
1
+ # @sinio/sdk — Node.js
2
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.
3
+ Official client for the sinio.ai ingestion API. No runtime dependencies; Node 18+
4
+ (uses the global `fetch`). ESM and CommonJS, typed end to end.
5
+
6
+ ```bash
7
+ npm install @sinio/sdk
8
+ ```
9
+
10
+ ## Quick start
11
+
12
+ ```ts
13
+ import { SinioClient } from "@sinio/sdk";
14
+
15
+ const sinio = new SinioClient({
16
+ apiKey: process.env.SINIO_API_KEY!,
17
+ baseUrl: "https://api.sinio.ai",
18
+ });
19
+
20
+ const result = await sinio.sendEvents([
21
+ {
22
+ sourceEventId: "evt_88213",
23
+ type: "badge_in",
24
+ occurredAt: "2026-08-28T07:58:12+02:00",
25
+ roles: { device: "BORNE-A12", subject: "P-4582", location: "SITE-A.HALL" },
26
+ payload: { badge: "04A2B9C1", reader_firmware: "2.4.1" },
27
+ },
28
+ ]);
29
+
30
+ // The four roles (device, subject, location, actor) are read from `roles` only;
31
+ // any other key is refused by the API. `payload` is free and optional ({} by
32
+ // default); readings such as a battery level are read from it as the
33
+ // source declares them. `count` (1 by default) says how many units one event stands for.
34
+
35
+ console.log(result.accepted, result.duplicates, result.rejections);
36
+ ```
37
+
38
+ ## What the client does for you
39
+
40
+ - **Chunking.** Pass 50 000 events; the SDK splits them into calls of 500 (the API
41
+ limit) and merges the counters and rejections into one result.
42
+ - **Retries.** 429, 5xx and dropped connections are retried with exponential
43
+ backoff and full jitter, honouring `Retry-After`. This is safe because
44
+ a resend with the same `source_event_id` and the same content is counted in
45
+ `duplicates`, never stored twice.
46
+ - **Local validation.** What the API would refuse is refused before any call with a
47
+ `SinioValidationError` naming the field: a timestamp without a UTC offset (the API's own
48
+ rule), a kind or level outside its vocabulary, a missing required field, a `validTo` not after
49
+ `validFrom`, a role other than the four, a `payload` that is not an object.
50
+ - **Typed errors.** `SinioAuthError` (401/403, do not replay),
51
+ `SinioRequestError` (400/404/413, fix the request), `SinioRateLimitError`
52
+ (429, carries `retryAfterSeconds`), `SinioServerError` (5xx, replayable),
53
+ `SinioConnectionError`, `SinioValidationError`.
54
+
55
+ ## Partial acceptance
56
+
57
+ A 200 means the batch was **received**, not derived — derivation is asynchronous.
58
+ Within a batch, valid events are accepted even when others are rejected, so always
59
+ read `rejections`:
60
+
61
+ ```ts
62
+ for (const rejection of result.rejections) {
63
+ console.warn(rejection.sourceEventId, rejection.code, rejection.message);
64
+ }
65
+ ```
66
+
67
+ `duplicates` and `revisions` are successes, not failures.
68
+
69
+ The vocabularies are exported, so a value from elsewhere can be checked or a code handled
70
+ without retyping the lists. A rejection code added by a later API version is kept as is:
71
+
72
+ ```ts
73
+ import { ENTITY_KINDS, isKnownRejectionCode, type EntityKind } from "@sinio/sdk";
74
+
75
+ const kind = row.type as EntityKind;
76
+ if (!ENTITY_KINDS.includes(kind)) throw new Error(`unexpected kind ${row.type}`);
77
+
78
+ for (const { code } of result.rejections) {
79
+ if (!isKnownRejectionCode(code)) console.warn("new rejection code", code);
80
+ }
81
+ ```
82
+
83
+ Also exported: `INGESTION_MODES`, `LOCATION_LEVELS`, `ASSIGNMENT_RELATIONS`, `EVENT_ROLES`,
84
+ `REJECTION_CODES`.
85
+
86
+ ## Reference data
87
+
88
+ ```ts
89
+ await sinio.upsertLocations([
90
+ { externalId: "SITE-A", kind: "site", name: "Site A" },
91
+ { externalId: "SITE-A.HALL", kind: "zone", name: "Hall", parent: "SITE-A" },
92
+ ]);
93
+
94
+ await sinio.upsertEntities([
95
+ { externalId: "BORNE-A12", kind: "device", subkind: "nfc_kiosk", location: "SITE-A.HALL",
96
+ attributes: { firmware: "2.4.1" } },
97
+ ]);
98
+
99
+ await sinio.createAssignments([
100
+ { credential: "04A2B9C1", subject: "P-4582", relation: "assigned_to",
101
+ validFrom: "2026-01-01T00:00:00+01:00" },
102
+ ]);
103
+ ```
104
+
105
+ The reference is never a condition of acceptance: an event pointing at an unknown
106
+ device is still accepted. Upserting is how you enrich it, not how you gate it.
107
+
108
+ ## Backfill
109
+
110
+ ```ts
111
+ await sinio.backfillEvents(history);
112
+ ```
113
+
114
+ `mode: "backfill"` persists history without raising alerts; once it has arrived, the
115
+ project's processes replay it in a canonical order. Live catch-up after an outage should stay on
116
+ `sendEvents` — the declared mode decides alerting, not the age of the events.
117
+
118
+ ## Webhook key
119
+
120
+ For systems that can only be pointed at a URL and cannot set a header:
121
+
122
+ ```ts
123
+ const sinio = new SinioClient({ webhookKey: process.env.SINIO_WEBHOOK_KEY! });
124
+ await sinio.sendEvents(events); // POST /v1/webhooks/<key>
125
+ ```
126
+
127
+ In this mode only event ingestion is available; the reference endpoints require an
128
+ API key.
129
+
130
+
131
+ ## Development
132
+
133
+ ```bash
134
+ npm install
135
+ npm test # typecheck + node:test
136
+ npm run build
137
+ ```
@@ -0,0 +1,75 @@
1
+ import { type FetchLike } from "./http.ts";
2
+ import type { AssignmentInput, AssignmentsResult, EntityInput, LocationInput, SendEventsOptions, SendEventsResult, SinioEvent, ProjectOptions, UpsertResult } from "./types.ts";
3
+ export declare const SDK_VERSION = "0.2.0";
4
+ export interface SinioClientOptions {
5
+ /** Machine credential, sent as `Authorization: Bearer`. Mutually exclusive with `webhookKey`. */
6
+ readonly apiKey?: string;
7
+ /**
8
+ * Key carried in the URL instead of a header, for systems that can only be
9
+ * pointed at a webhook URL. Only `sendEvents` is available in this mode.
10
+ */
11
+ readonly webhookKey?: string;
12
+ /** Defaults to `https://api.sinio.ai`. */
13
+ readonly baseUrl?: string;
14
+ /**
15
+ * Sent as `X-Source-Code`. Only for keys not bound to a single source (organization-wide keys,
16
+ * issued on request); a source key already carries its source.
17
+ */
18
+ readonly sourceCode?: string;
19
+ /**
20
+ * Default project `external_id`. Only for organization-wide keys (issued on request) covering
21
+ * several projects; a project key already carries its project.
22
+ */
23
+ readonly project?: string;
24
+ /** Per-request timeout, default 30 s. */
25
+ readonly timeoutMs?: number;
26
+ /** Retries on 429, 5xx and dropped connections. Default 3. */
27
+ readonly maxRetries?: number;
28
+ /** First backoff ceiling, doubled per attempt with full jitter. Default 500 ms. */
29
+ readonly retryBaseDelayMs?: number;
30
+ /** Injectable transport, for tests or for Node < 18. */
31
+ readonly fetch?: FetchLike;
32
+ /** Injectable sleep, so tests do not wait on retries. */
33
+ readonly sleep?: (ms: number) => Promise<void>;
34
+ }
35
+ /**
36
+ * Client for the sinio.ai ingestion API.
37
+ *
38
+ * Every method accepts an arbitrarily long list and splits it into calls of
39
+ * 500 items, the API limit, merging the counters and rejections back into a
40
+ * single result. Sending the same events twice is safe: idempotency is keyed
41
+ * on `(project, source, source_event_id, revision)`, so a replay is counted as
42
+ * a duplicate rather than stored again.
43
+ */
44
+ export declare class SinioClient {
45
+ private readonly transport;
46
+ private readonly authHeaders;
47
+ private readonly eventsPath;
48
+ private readonly webhookMode;
49
+ private readonly sourceCode;
50
+ private readonly project;
51
+ constructor(options: SinioClientOptions);
52
+ /** `POST /v1/events` — live ingestion. Derivation is asynchronous: a 200 confirms receipt only. */
53
+ sendEvents(events: readonly SinioEvent[], options?: SendEventsOptions): Promise<SendEventsResult>;
54
+ /**
55
+ * Same endpoint with `mode: "backfill"`: history is persisted but nothing is
56
+ * alerted, and derivation is replayed later in a canonical order.
57
+ */
58
+ backfillEvents(events: readonly SinioEvent[], options?: Omit<SendEventsOptions, "mode">): Promise<SendEventsResult>;
59
+ /**
60
+ * `POST /v1/entities` — bulk upsert keyed on `(kind, external_id)`. An unknown
61
+ * `subkind` never fails the call: it is created undeclared, for someone
62
+ * to qualify in the console.
63
+ */
64
+ upsertEntities(entities: readonly EntityInput[], options?: ProjectOptions): Promise<UpsertResult>;
65
+ /** `POST /v1/locations` — bulk upsert of the location tree, keyed on `external_id`. */
66
+ upsertLocations(locations: readonly LocationInput[], options?: ProjectOptions): Promise<UpsertResult>;
67
+ /**
68
+ * `POST /v1/assignments` — `credential -> subject` with a validity range. An
69
+ * overlap is rejected with `overlapping_assignment`, never merged silently.
70
+ */
71
+ createAssignments(assignments: readonly AssignmentInput[], options?: ProjectOptions): Promise<AssignmentsResult>;
72
+ private upsertReference;
73
+ private withProject;
74
+ private assertBearerMode;
75
+ }
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SinioClient = exports.SDK_VERSION = void 0;
4
+ const errors_ts_1 = require("./errors.js");
5
+ const http_ts_1 = require("./http.js");
6
+ const serialize_ts_1 = require("./serialize.js");
7
+ exports.SDK_VERSION = "0.2.0";
8
+ /**
9
+ * Client for the sinio.ai ingestion API.
10
+ *
11
+ * Every method accepts an arbitrarily long list and splits it into calls of
12
+ * 500 items, the API limit, merging the counters and rejections back into a
13
+ * single result. Sending the same events twice is safe: idempotency is keyed
14
+ * on `(project, source, source_event_id, revision)`, so a replay is counted as
15
+ * a duplicate rather than stored again.
16
+ */
17
+ class SinioClient {
18
+ transport;
19
+ authHeaders;
20
+ eventsPath;
21
+ webhookMode;
22
+ sourceCode;
23
+ project;
24
+ constructor(options) {
25
+ const hasApiKey = typeof options.apiKey === "string" && options.apiKey.length > 0;
26
+ const hasWebhookKey = typeof options.webhookKey === "string" && options.webhookKey.length > 0;
27
+ if (hasApiKey === hasWebhookKey) {
28
+ throw new errors_ts_1.SinioValidationError("Provide exactly one of `apiKey` or `webhookKey`.");
29
+ }
30
+ this.webhookMode = hasWebhookKey;
31
+ this.authHeaders = hasApiKey ? { authorization: `Bearer ${options.apiKey}` } : {};
32
+ this.eventsPath = hasWebhookKey ? `/v1/webhooks/${encodeURIComponent(options.webhookKey)}` : "/v1/events";
33
+ this.sourceCode = options.sourceCode;
34
+ this.project = options.project;
35
+ this.transport = new http_ts_1.Transport({
36
+ baseUrl: options.baseUrl ?? "https://api.sinio.ai",
37
+ timeoutMs: options.timeoutMs ?? 30_000,
38
+ maxRetries: options.maxRetries ?? 3,
39
+ retryBaseDelayMs: options.retryBaseDelayMs ?? 500,
40
+ userAgent: `sinio-node/${exports.SDK_VERSION}`,
41
+ fetch: options.fetch,
42
+ sleep: options.sleep,
43
+ });
44
+ }
45
+ /** `POST /v1/events` — live ingestion. Derivation is asynchronous: a 200 confirms receipt only. */
46
+ async sendEvents(events, options = {}) {
47
+ const mode = (0, serialize_ts_1.toWireMode)(options.mode ?? "webhook");
48
+ const wire = (0, serialize_ts_1.requireList)(events, "events").map((event, index) => (0, serialize_ts_1.toWireEvent)(withDefaultProject(event, this.project), index));
49
+ const sourceCode = options.sourceCode ?? this.sourceCode;
50
+ const headers = sourceCode === undefined ? {} : { "x-source-code": sourceCode };
51
+ const merged = {
52
+ batchIds: [],
53
+ accepted: 0,
54
+ pendingClassification: 0,
55
+ duplicates: 0,
56
+ revisions: 0,
57
+ rejected: 0,
58
+ rejections: [],
59
+ testMode: false,
60
+ };
61
+ for (const part of (0, serialize_ts_1.chunk)(wire, serialize_ts_1.MAX_ITEMS_PER_CALL)) {
62
+ const response = asRecord(await this.transport.post(this.eventsPath, { events: part, mode }, { ...this.authHeaders, ...headers }));
63
+ const batchId = asString(response["batch_id"]);
64
+ if (batchId !== null) {
65
+ merged.batchIds.push(batchId);
66
+ }
67
+ merged.accepted += asNumber(response["accepted"]);
68
+ merged.pendingClassification += asNumber(response["pending_classification"]);
69
+ merged.duplicates += asNumber(response["duplicates"]);
70
+ merged.revisions += asNumber(response["revisions"]);
71
+ merged.rejected += asNumber(response["rejected"]);
72
+ merged.testMode = merged.testMode || response["test_mode"] === true;
73
+ for (const rejection of asArray(response["rejections"])) {
74
+ const item = asRecord(rejection);
75
+ merged.rejections.push({
76
+ sourceEventId: asString(item["source_event_id"]) ?? "",
77
+ code: asCode(item["code"]),
78
+ message: asString(item["message"]) ?? "",
79
+ });
80
+ }
81
+ }
82
+ return merged;
83
+ }
84
+ /**
85
+ * Same endpoint with `mode: "backfill"`: history is persisted but nothing is
86
+ * alerted, and derivation is replayed later in a canonical order.
87
+ */
88
+ async backfillEvents(events, options = {}) {
89
+ return this.sendEvents(events, { ...options, mode: "backfill" });
90
+ }
91
+ /**
92
+ * `POST /v1/entities` — bulk upsert keyed on `(kind, external_id)`. An unknown
93
+ * `subkind` never fails the call: it is created undeclared, for someone
94
+ * to qualify in the console.
95
+ */
96
+ async upsertEntities(entities, options = {}) {
97
+ this.assertBearerMode("upsertEntities");
98
+ return this.upsertReference("/v1/entities", "entities", (0, serialize_ts_1.requireList)(entities, "entities").map((entity, index) => (0, serialize_ts_1.toWireEntity)(entity, index)), options);
99
+ }
100
+ /** `POST /v1/locations` — bulk upsert of the location tree, keyed on `external_id`. */
101
+ async upsertLocations(locations, options = {}) {
102
+ this.assertBearerMode("upsertLocations");
103
+ return this.upsertReference("/v1/locations", "locations", (0, serialize_ts_1.requireList)(locations, "locations").map((location, index) => (0, serialize_ts_1.toWireLocation)(location, index)), options);
104
+ }
105
+ /**
106
+ * `POST /v1/assignments` — `credential -> subject` with a validity range. An
107
+ * overlap is rejected with `overlapping_assignment`, never merged silently.
108
+ */
109
+ async createAssignments(assignments, options = {}) {
110
+ this.assertBearerMode("createAssignments");
111
+ const wire = (0, serialize_ts_1.requireList)(assignments, "assignments").map((assignment, index) => (0, serialize_ts_1.toWireAssignment)(assignment, index));
112
+ const merged = {
113
+ accepted: 0,
114
+ rejected: 0,
115
+ rejections: [],
116
+ };
117
+ for (const part of (0, serialize_ts_1.chunk)(wire, serialize_ts_1.MAX_ITEMS_PER_CALL)) {
118
+ const response = asRecord(await this.transport.post("/v1/assignments", this.withProject({ assignments: part }, options), this.authHeaders));
119
+ merged.accepted += asNumber(response["accepted"]);
120
+ merged.rejected += asNumber(response["rejected"]);
121
+ for (const rejection of asArray(response["rejections"])) {
122
+ const item = asRecord(rejection);
123
+ merged.rejections.push({
124
+ credential: asString(item["credential"]) ?? "",
125
+ subject: asString(item["subject"]) ?? "",
126
+ code: asCode(item["code"]),
127
+ message: asString(item["message"]) ?? "",
128
+ });
129
+ }
130
+ }
131
+ return merged;
132
+ }
133
+ async upsertReference(path, key, wire, options) {
134
+ const merged = {
135
+ accepted: 0,
136
+ rejected: 0,
137
+ rejections: [],
138
+ };
139
+ for (const part of (0, serialize_ts_1.chunk)(wire, serialize_ts_1.MAX_ITEMS_PER_CALL)) {
140
+ const response = asRecord(await this.transport.post(path, this.withProject({ [key]: part }, options), this.authHeaders));
141
+ merged.accepted += asNumber(response["accepted"]);
142
+ merged.rejected += asNumber(response["rejected"]);
143
+ for (const rejection of asArray(response["rejections"])) {
144
+ const item = asRecord(rejection);
145
+ merged.rejections.push({
146
+ externalId: asString(item["external_id"]) ?? "",
147
+ code: asCode(item["code"]),
148
+ message: asString(item["message"]) ?? "",
149
+ });
150
+ }
151
+ }
152
+ return merged;
153
+ }
154
+ withProject(body, options) {
155
+ const project = optionalProject(options.project) ?? this.project;
156
+ return project === undefined ? body : { project, ...body };
157
+ }
158
+ assertBearerMode(operation) {
159
+ if (this.webhookMode) {
160
+ throw new errors_ts_1.SinioValidationError(`${operation} requires an API key: a webhook key only authenticates event ingestion.`);
161
+ }
162
+ }
163
+ }
164
+ exports.SinioClient = SinioClient;
165
+ /** The client-level project applies only to an event that does not name its own. */
166
+ function withDefaultProject(event, project) {
167
+ if (project === undefined || typeof event !== "object" || event === null || event.project !== undefined) {
168
+ return event;
169
+ }
170
+ return { ...event, project };
171
+ }
172
+ function optionalProject(value) {
173
+ if (value !== undefined && typeof value !== "string") {
174
+ throw new errors_ts_1.SinioValidationError(`project must be a string (got ${JSON.stringify(value)})`);
175
+ }
176
+ return value;
177
+ }
178
+ /** A known code or any code the API adds later, kept as is; never a reason to fail. */
179
+ function asCode(value) {
180
+ return asString(value) ?? "unknown";
181
+ }
182
+ function asRecord(value) {
183
+ return typeof value === "object" && value !== null && !Array.isArray(value)
184
+ ? value
185
+ : {};
186
+ }
187
+ function asArray(value) {
188
+ return Array.isArray(value) ? value : [];
189
+ }
190
+ function asNumber(value) {
191
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
192
+ }
193
+ function asString(value) {
194
+ return typeof value === "string" ? value : null;
195
+ }
196
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":";;;AAAA,2CAAmD;AACnD,uCAAsD;AACtD,iDASwB;AAiBX,QAAA,WAAW,GAAG,OAAO,CAAC;AAkCnC;;;;;;;;GAQG;AACH,MAAa,WAAW;IACL,SAAS,CAAY;IACrB,WAAW,CAAyB;IACpC,UAAU,CAAS;IACnB,WAAW,CAAU;IACrB,UAAU,CAAqB;IAC/B,OAAO,CAAqB;IAE7C,YAAY,OAA2B;QACrC,MAAM,SAAS,GAAG,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAClF,MAAM,aAAa,GAAG,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;QAC9F,IAAI,SAAS,KAAK,aAAa,EAAE,CAAC;YAChC,MAAM,IAAI,gCAAoB,CAAC,kDAAkD,CAAC,CAAC;QACrF,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,aAAa,CAAC;QACjC,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,IAAI,CAAC,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,gBAAgB,kBAAkB,CAAC,OAAO,CAAC,UAAW,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;QAC3G,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,SAAS,GAAG,IAAI,mBAAS,CAAC;YAC7B,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,sBAAsB;YAClD,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,MAAM;YACtC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC;YACnC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,GAAG;YACjD,SAAS,EAAE,cAAc,mBAAW,EAAE;YACtC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC;IACL,CAAC;IAED,mGAAmG;IACnG,KAAK,CAAC,UAAU,CAAC,MAA6B,EAAE,UAA6B,EAAE;QAC7E,MAAM,IAAI,GAAG,IAAA,yBAAU,EAAC,OAAO,CAAC,IAAI,IAAI,SAAS,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,IAAA,0BAAW,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAC9D,IAAA,0BAAW,EAAC,kBAAkB,CAAC,KAAmB,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,CAC1E,CAAC;QAEF,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC;QACzD,MAAM,OAAO,GAA2B,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,UAAU,EAAE,CAAC;QACxG,MAAM,MAAM,GAAqF;YAC/F,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE,CAAC;YACX,qBAAqB,EAAE,CAAC;YACxB,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,CAAC;YACZ,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,EAAE;YACd,QAAQ,EAAE,KAAK;SAChB,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,IAAA,oBAAK,EAAC,IAAI,EAAE,iCAAkB,CAAC,EAAE,CAAC;YACnD,MAAM,QAAQ,GAAG,QAAQ,CACvB,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,OAAO,EAAE,CAAC,CACxG,CAAC;YACF,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;YAC/C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;YACD,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;YAClD,MAAM,CAAC,qBAAqB,IAAI,QAAQ,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC,CAAC;YAC7E,MAAM,CAAC,UAAU,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;YACtD,MAAM,CAAC,SAAS,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;YACpD,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;YAClD,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;YACpE,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;gBACxD,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACjC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;oBACrB,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE;oBACtD,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAC1B,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE;iBACzC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAClB,MAA6B,EAC7B,UAA2C,EAAE;QAE7C,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IACnE,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc,CAAC,QAAgC,EAAE,UAA0B,EAAE;QACjF,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,eAAe,CAAC,cAAc,EAAE,UAAU,EAAE,IAAA,0BAAW,EAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,IAAA,2BAAY,EAAC,MAAqB,EAAE,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACzK,CAAC;IAED,uFAAuF;IACvF,KAAK,CAAC,eAAe,CAAC,SAAmC,EAAE,UAA0B,EAAE;QACrF,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,WAAW,EAAE,IAAA,0BAAW,EAAC,SAAS,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,IAAA,6BAAc,EAAC,QAAyB,EAAE,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACrL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,iBAAiB,CACrB,WAAuC,EACvC,UAA0B,EAAE;QAE5B,IAAI,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,IAAA,0BAAW,EAAC,WAAW,EAAE,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE,CAC7E,IAAA,+BAAgB,EAAC,UAA6B,EAAE,KAAK,CAAC,CACvD,CAAC;QACF,MAAM,MAAM,GAAuE;YACjF,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,EAAE;SACf,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,IAAA,oBAAK,EAAC,IAAI,EAAE,iCAAkB,CAAC,EAAE,CAAC;YACnD,MAAM,QAAQ,GAAG,QAAQ,CACvB,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CACjH,CAAC;YACF,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;YAClD,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;YAClD,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;gBACxD,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACjC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;oBACrB,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE;oBAC9C,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE;oBACxC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAC1B,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE;iBACzC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,eAAe,CAC3B,IAAY,EACZ,GAAW,EACX,IAAuB,EACvB,OAAuB;QAEvB,MAAM,MAAM,GAAiE;YAC3E,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,EAAE;SACf,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,IAAA,oBAAK,EAAC,IAAI,EAAE,iCAAkB,CAAC,EAAE,CAAC;YACnD,MAAM,QAAQ,GAAG,QAAQ,CACvB,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAC9F,CAAC;YACF,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;YAClD,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;YAClD,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;gBACxD,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACjC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;oBACrB,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,EAAE;oBAC/C,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAC1B,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE;iBACzC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,WAAW,CAAC,IAA6B,EAAE,OAAuB;QACxE,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC;QACjE,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;IAC7D,CAAC;IAEO,gBAAgB,CAAC,SAAiB;QACxC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,IAAI,gCAAoB,CAC5B,GAAG,SAAS,yEAAyE,CACtF,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AA1LD,kCA0LC;AAID,oFAAoF;AACpF,SAAS,kBAAkB,CAAC,KAAiB,EAAE,OAA2B;IACxE,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACxG,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrD,MAAM,IAAI,gCAAoB,CAAC,iCAAiC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,uFAAuF;AACvF,SAAS,MAAM,CAAC,KAAc;IAC5B,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC;AACtC,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACzE,CAAC,CAAE,KAAiC;QACpC,CAAC,CAAC,EAAE,CAAC;AACT,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { RejectionCodeValue } from "./types.ts";
2
+ /** Base class for every error the SDK throws. */
3
+ export declare class SinioError extends Error {
4
+ constructor(message: string);
5
+ }
6
+ /** The request never got a usable HTTP response (DNS, TCP, TLS, timeout). */
7
+ export declare class SinioConnectionError extends SinioError {
8
+ readonly reason: unknown;
9
+ constructor(message: string, reason?: unknown);
10
+ }
11
+ /** A 4xx or 5xx response. */
12
+ export declare class SinioApiError extends SinioError {
13
+ readonly status: number;
14
+ readonly body: unknown;
15
+ /** Rejection code returned by the API, when the body carries one (a known `RejectionCode` or a newer one). */
16
+ readonly code: RejectionCodeValue | null;
17
+ constructor(message: string, status: number, body: unknown, code?: RejectionCodeValue | null);
18
+ }
19
+ /** 401 / 403 — invalid, revoked, or insufficiently scoped key. Never replay. */
20
+ export declare class SinioAuthError extends SinioApiError {
21
+ }
22
+ /** 400 / 404 / 413 — the request itself is wrong. Fix it before replaying. */
23
+ export declare class SinioRequestError extends SinioApiError {
24
+ }
25
+ /** 429 — quota exceeded. `retryAfterSeconds` mirrors the `Retry-After` header. */
26
+ export declare class SinioRateLimitError extends SinioApiError {
27
+ readonly retryAfterSeconds: number | null;
28
+ constructor(message: string, status: number, body: unknown, retryAfterSeconds: number | null);
29
+ }
30
+ /** 5xx — temporary. Safe to replay verbatim: ingestion is idempotent. */
31
+ export declare class SinioServerError extends SinioApiError {
32
+ }
33
+ /** Raised before any network call, when the input cannot be a valid request. */
34
+ export declare class SinioValidationError extends SinioError {
35
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SinioValidationError = exports.SinioServerError = exports.SinioRateLimitError = exports.SinioRequestError = exports.SinioAuthError = exports.SinioApiError = exports.SinioConnectionError = exports.SinioError = void 0;
4
+ /** Base class for every error the SDK throws. */
5
+ class SinioError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = new.target.name;
9
+ }
10
+ }
11
+ exports.SinioError = SinioError;
12
+ /** The request never got a usable HTTP response (DNS, TCP, TLS, timeout). */
13
+ class SinioConnectionError extends SinioError {
14
+ reason;
15
+ constructor(message, reason) {
16
+ super(message);
17
+ this.reason = reason;
18
+ }
19
+ }
20
+ exports.SinioConnectionError = SinioConnectionError;
21
+ /** A 4xx or 5xx response. */
22
+ class SinioApiError extends SinioError {
23
+ status;
24
+ body;
25
+ /** Rejection code returned by the API, when the body carries one (a known `RejectionCode` or a newer one). */
26
+ code;
27
+ constructor(message, status, body, code = null) {
28
+ super(message);
29
+ this.status = status;
30
+ this.body = body;
31
+ this.code = code;
32
+ }
33
+ }
34
+ exports.SinioApiError = SinioApiError;
35
+ /** 401 / 403 — invalid, revoked, or insufficiently scoped key. Never replay. */
36
+ class SinioAuthError extends SinioApiError {
37
+ }
38
+ exports.SinioAuthError = SinioAuthError;
39
+ /** 400 / 404 / 413 — the request itself is wrong. Fix it before replaying. */
40
+ class SinioRequestError extends SinioApiError {
41
+ }
42
+ exports.SinioRequestError = SinioRequestError;
43
+ /** 429 — quota exceeded. `retryAfterSeconds` mirrors the `Retry-After` header. */
44
+ class SinioRateLimitError extends SinioApiError {
45
+ retryAfterSeconds;
46
+ constructor(message, status, body, retryAfterSeconds) {
47
+ super(message, status, body);
48
+ this.retryAfterSeconds = retryAfterSeconds;
49
+ }
50
+ }
51
+ exports.SinioRateLimitError = SinioRateLimitError;
52
+ /** 5xx — temporary. Safe to replay verbatim: ingestion is idempotent. */
53
+ class SinioServerError extends SinioApiError {
54
+ }
55
+ exports.SinioServerError = SinioServerError;
56
+ /** Raised before any network call, when the input cannot be a valid request. */
57
+ class SinioValidationError extends SinioError {
58
+ }
59
+ exports.SinioValidationError = SinioValidationError;
60
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":";;;AAEA,iDAAiD;AACjD,MAAa,UAAW,SAAQ,KAAK;IACnC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;IAC9B,CAAC;CACF;AALD,gCAKC;AAED,6EAA6E;AAC7E,MAAa,oBAAqB,SAAQ,UAAU;IACzC,MAAM,CAAU;IAEzB,YAAY,OAAe,EAAE,MAAgB;QAC3C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAPD,oDAOC;AAED,6BAA6B;AAC7B,MAAa,aAAc,SAAQ,UAAU;IAClC,MAAM,CAAS;IACf,IAAI,CAAU;IACvB,8GAA8G;IACrG,IAAI,CAA4B;IAEzC,YAAY,OAAe,EAAE,MAAc,EAAE,IAAa,EAAE,OAAkC,IAAI;QAChG,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAZD,sCAYC;AAED,gFAAgF;AAChF,MAAa,cAAe,SAAQ,aAAa;CAAG;AAApD,wCAAoD;AAEpD,8EAA8E;AAC9E,MAAa,iBAAkB,SAAQ,aAAa;CAAG;AAAvD,8CAAuD;AAEvD,kFAAkF;AAClF,MAAa,mBAAoB,SAAQ,aAAa;IAC3C,iBAAiB,CAAgB;IAE1C,YAAY,OAAe,EAAE,MAAc,EAAE,IAAa,EAAE,iBAAgC;QAC1F,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;IAC7C,CAAC;CACF;AAPD,kDAOC;AAED,yEAAyE;AACzE,MAAa,gBAAiB,SAAQ,aAAa;CAAG;AAAtD,4CAAsD;AAEtD,gFAAgF;AAChF,MAAa,oBAAqB,SAAQ,UAAU;CAAG;AAAvD,oDAAuD"}
@@ -0,0 +1,22 @@
1
+ export type FetchLike = (input: string, init: RequestInit) => Promise<Response>;
2
+ export interface TransportOptions {
3
+ readonly baseUrl: string;
4
+ readonly timeoutMs: number;
5
+ readonly maxRetries: number;
6
+ readonly retryBaseDelayMs: number;
7
+ readonly userAgent: string;
8
+ readonly fetch?: FetchLike | undefined;
9
+ /** Injected in tests so retries do not actually wait. */
10
+ readonly sleep?: ((ms: number) => Promise<void>) | undefined;
11
+ }
12
+ /** `Retry-After` is either a delay in seconds or an HTTP date. Both are accepted. */
13
+ export declare function parseRetryAfter(header: string | null, now?: number): number | null;
14
+ export declare class Transport {
15
+ private readonly options;
16
+ private readonly fetchImpl;
17
+ private readonly sleep;
18
+ constructor(options: TransportOptions);
19
+ post(path: string, body: unknown, headers: Record<string, string>): Promise<unknown>;
20
+ /** Exponential backoff with full jitter, unless the server told us how long to wait. */
21
+ private backoffMs;
22
+ }