@syndroo/sdk 0.4.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js ADDED
@@ -0,0 +1,354 @@
1
+ /**
2
+ * `SyndrooClient` — a thin, dependency-free client for the Syndroo HTTP API.
3
+ *
4
+ * The client wraps the documented `/v1` contract. It deliberately does not add
5
+ * server features: it creates, reads, lists, and waits, and it never invents a
6
+ * delivery result that the server did not report.
7
+ */
8
+ import { SyndrooAbortError, SyndrooApiError, SyndrooConfigError, SyndrooError, SyndrooValidationError, SyndrooWaitTimeoutError, } from "./errors.js";
9
+ import { DEFAULT_MAX_RESPONSE_BYTES, DEFAULT_TIMEOUT_MS, MIN_MAX_RESPONSE_BYTES, sendRequest, unrefTimer, } from "./http.js";
10
+ import { isPostTerminal, parseHealth, parsePostDetail, parsePostList, parsePostReceipt, } from "./types.js";
11
+ export const DEFAULT_WAIT_TIMEOUT_MS = 60_000;
12
+ export const DEFAULT_POLL_INTERVAL_MS = 250;
13
+ export const DEFAULT_MAX_POLL_INTERVAL_MS = 2_000;
14
+ const IDEMPOTENCY_KEY_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
15
+ /**
16
+ * Client for one Syndroo instance.
17
+ *
18
+ * ```ts
19
+ * const syndroo = new SyndrooClient({
20
+ * baseUrl: process.env.SYNDROO_BASE_URL!,
21
+ * apiKey: process.env.SYNDROO_API_KEY!,
22
+ * });
23
+ *
24
+ * const receipt = await syndroo.posts.create(
25
+ * { content: "We just shipped a new release.", platforms: ["bluesky"] },
26
+ * { idempotencyKey: "release-announcement-001" },
27
+ * );
28
+ *
29
+ * const post = await syndroo.posts.get(receipt.id);
30
+ * ```
31
+ */
32
+ export class SyndrooClient {
33
+ posts;
34
+ #config;
35
+ #waitTimeoutMs;
36
+ constructor(options) {
37
+ this.#config = resolveConfig(options);
38
+ this.#waitTimeoutMs = options.waitTimeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;
39
+ validatePositiveDuration(this.#waitTimeoutMs, "waitTimeoutMs");
40
+ if (typeof globalThis.fetch !== "function") {
41
+ throw new SyndrooConfigError("This runtime has no global fetch(). The SDK requires Node.js 22 or newer.");
42
+ }
43
+ this.posts = new PostsResource(this.#config, this.#waitTimeoutMs);
44
+ }
45
+ /**
46
+ * `GET /health`. Syndroo's health endpoint is unauthenticated, so the client
47
+ * sends no Authorization header here. It proves reachability, not that the
48
+ * API key is correct or that the deployment can publish.
49
+ */
50
+ async health(options = {}) {
51
+ const response = await sendRequest(this.#config, {
52
+ method: "GET",
53
+ path: "/health",
54
+ authenticated: false,
55
+ signal: options.signal,
56
+ timeoutMs: options.timeoutMs,
57
+ });
58
+ return parseHealth(response.body, { status: response.status });
59
+ }
60
+ }
61
+ /** The posts resource: create, read, list, and bounded status wait. */
62
+ export class PostsResource {
63
+ #config;
64
+ #defaultWaitTimeoutMs;
65
+ constructor(config, defaultWaitTimeoutMs) {
66
+ this.#config = config;
67
+ this.#defaultWaitTimeoutMs = defaultWaitTimeoutMs;
68
+ }
69
+ /**
70
+ * `POST /v1/posts`. The returned receipt is an acceptance result: HTTP 202
71
+ * means the request is queued for processing, not that any platform
72
+ * published it. The SDK performs exactly one request and never retries it.
73
+ */
74
+ async create(input, options = {}) {
75
+ validateCreateInput(input);
76
+ const idempotencyKey = options.idempotencyKey === undefined
77
+ ? undefined
78
+ : validateIdempotencyKey(options.idempotencyKey);
79
+ const response = await sendRequest(this.#config, {
80
+ method: "POST",
81
+ path: "/v1/posts",
82
+ json: input,
83
+ idempotencyKey,
84
+ signal: options.signal,
85
+ timeoutMs: options.timeoutMs,
86
+ });
87
+ return parsePostReceipt(response.body, {
88
+ status: response.status,
89
+ requestMayHaveBeenApplied: true,
90
+ });
91
+ }
92
+ /** `GET /v1/posts/<id>`. Read-only, so repeating it is safe. */
93
+ async get(id, options = {}) {
94
+ const postId = validatePostId(id);
95
+ const response = await sendRequest(this.#config, {
96
+ method: "GET",
97
+ path: `/v1/posts/${encodeURIComponent(postId)}`,
98
+ signal: options.signal,
99
+ timeoutMs: options.timeoutMs,
100
+ });
101
+ return parsePostDetail(response.body, { status: response.status });
102
+ }
103
+ /** `GET /v1/posts`, newest first. */
104
+ async list(options = {}) {
105
+ const limit = options.limit === undefined ? undefined : validateLimit(options.limit);
106
+ const response = await sendRequest(this.#config, {
107
+ method: "GET",
108
+ path: "/v1/posts",
109
+ query: limit === undefined ? undefined : { limit: String(limit) },
110
+ signal: options.signal,
111
+ timeoutMs: options.timeoutMs,
112
+ });
113
+ return parsePostList(response.body, { status: response.status });
114
+ }
115
+ /**
116
+ * Reads the post until it reaches a terminal status (`published`, `partial`,
117
+ * or `failed`) or the wait budget runs out.
118
+ *
119
+ * Waiting is read-only: it never creates, cancels, or resends a post, so a
120
+ * timeout leaves the server-side work running and only stops this client from
121
+ * waiting. On timeout it throws `SyndrooWaitTimeoutError`, which keeps the
122
+ * post id, the last status, and the last transient error so a caller can
123
+ * resume instead of starting over.
124
+ */
125
+ async wait(id, options = {}) {
126
+ const postId = validatePostId(id);
127
+ const timeoutMs = options.timeoutMs ?? this.#defaultWaitTimeoutMs;
128
+ const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
129
+ const maxPollIntervalMs = options.maxPollIntervalMs ?? DEFAULT_MAX_POLL_INTERVAL_MS;
130
+ validatePositiveDuration(timeoutMs, "timeoutMs");
131
+ validatePositiveDuration(pollIntervalMs, "pollIntervalMs");
132
+ validatePositiveDuration(maxPollIntervalMs, "maxPollIntervalMs");
133
+ const deadline = Date.now() + timeoutMs;
134
+ let interval = Math.min(pollIntervalMs, maxPollIntervalMs);
135
+ let lastPost;
136
+ let lastError;
137
+ for (;;) {
138
+ const remaining = deadline - Date.now();
139
+ if (remaining <= 0) {
140
+ break;
141
+ }
142
+ try {
143
+ const post = await this.get(postId, {
144
+ signal: options.signal,
145
+ timeoutMs: Math.max(1, Math.min(remaining, this.#config.timeoutMs)),
146
+ });
147
+ lastPost = post;
148
+ lastError = undefined;
149
+ if (isPostTerminal(post.status)) {
150
+ return post;
151
+ }
152
+ }
153
+ catch (error) {
154
+ const failure = toSyndrooError(error);
155
+ if (isFatalWaitFailure(failure)) {
156
+ throw failure;
157
+ }
158
+ lastError = failure;
159
+ if (failure instanceof SyndrooApiError && failure.retryAfterMs !== undefined) {
160
+ interval = Math.max(interval, failure.retryAfterMs);
161
+ }
162
+ }
163
+ const pause = Math.min(interval, Math.max(0, deadline - Date.now()));
164
+ if (pause > 0) {
165
+ await sleep(pause, options.signal);
166
+ }
167
+ interval = Math.min(interval * 2, maxPollIntervalMs);
168
+ }
169
+ throw new SyndrooWaitTimeoutError(waitTimeoutMessage(postId, timeoutMs, lastPost, lastError), {
170
+ postId,
171
+ timeoutMs,
172
+ lastStatus: lastPost?.status,
173
+ lastPost,
174
+ lastError,
175
+ });
176
+ }
177
+ }
178
+ function waitTimeoutMessage(postId, timeoutMs, lastPost, lastError) {
179
+ const observed = lastPost === undefined
180
+ ? "no status was observed"
181
+ : `the last observed status was "${lastPost.status}"`;
182
+ const failure = lastError === undefined ? "" : ` The last status read failed with: ${lastError.message}`;
183
+ return (`Stopped waiting for post ${postId} after ${timeoutMs}ms: ${observed}. ` +
184
+ "Waiting only reads, so no post was created or cancelled and the server-side " +
185
+ "work continues; resume with posts.get or a longer posts.wait." +
186
+ failure);
187
+ }
188
+ /**
189
+ * Only transient conditions keep a wait going. Authentication, validation, and
190
+ * "not found" are configuration or state problems that will not fix themselves
191
+ * by polling, so they surface immediately.
192
+ */
193
+ function isFatalWaitFailure(error) {
194
+ if (error instanceof SyndrooAbortError ||
195
+ error instanceof SyndrooConfigError ||
196
+ error instanceof SyndrooValidationError) {
197
+ return true;
198
+ }
199
+ if (error instanceof SyndrooApiError) {
200
+ return error.status < 500 && error.status !== 429;
201
+ }
202
+ return false;
203
+ }
204
+ function toSyndrooError(error) {
205
+ if (error instanceof SyndrooError) {
206
+ return error;
207
+ }
208
+ return new SyndrooError(error instanceof Error ? error.message : "Unknown failure", { code: "UNKNOWN", cause: error });
209
+ }
210
+ function resolveConfig(options) {
211
+ const baseUrl = normalizeBaseUrl(options.baseUrl, options.allowInsecureHttp === true);
212
+ const apiKey = validateApiKey(options.apiKey);
213
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
214
+ const maxResponseBytes = options.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
215
+ validatePositiveDuration(timeoutMs, "timeoutMs");
216
+ if (!Number.isInteger(maxResponseBytes) ||
217
+ maxResponseBytes < MIN_MAX_RESPONSE_BYTES) {
218
+ throw new SyndrooConfigError(`maxResponseBytes must be an integer of at least ${MIN_MAX_RESPONSE_BYTES} bytes.`);
219
+ }
220
+ return { baseUrl, apiKey, timeoutMs, maxResponseBytes };
221
+ }
222
+ function normalizeBaseUrl(value, allowInsecureHttp) {
223
+ if (typeof value !== "string" || value.trim().length === 0) {
224
+ throw new SyndrooConfigError("baseUrl is required, for example https://syndroo.example.com.");
225
+ }
226
+ let url;
227
+ try {
228
+ url = new URL(value.trim());
229
+ }
230
+ catch {
231
+ throw new SyndrooConfigError(`baseUrl must be an absolute URL, received "${value.trim()}".`);
232
+ }
233
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
234
+ throw new SyndrooConfigError(`baseUrl must use http or https, received "${url.protocol}".`);
235
+ }
236
+ if (url.username !== "" || url.password !== "") {
237
+ throw new SyndrooConfigError("baseUrl must not embed credentials; pass the API key as apiKey so it is sent only as a Bearer header.");
238
+ }
239
+ if (url.search !== "" || url.hash !== "") {
240
+ throw new SyndrooConfigError("baseUrl must not include a query string or fragment.");
241
+ }
242
+ if (url.protocol === "http:" &&
243
+ !allowInsecureHttp &&
244
+ !isLoopbackHost(url.hostname)) {
245
+ throw new SyndrooConfigError("baseUrl must use https outside loopback: a bearer token sent over plaintext " +
246
+ "is readable on the path. Pass allowInsecureHttp: true only for a " +
247
+ "deliberate plaintext deployment.");
248
+ }
249
+ const path = url.pathname.replace(/\/+$/, "");
250
+ return `${url.origin}${path}`;
251
+ }
252
+ function isLoopbackHost(hostname) {
253
+ const host = hostname.toLowerCase().replace(/^\[/u, "").replace(/\]$/u, "");
254
+ return (host === "localhost" ||
255
+ host.endsWith(".localhost") ||
256
+ host === "::1" ||
257
+ host === "0:0:0:0:0:0:0:1" ||
258
+ host.startsWith("127."));
259
+ }
260
+ function validateApiKey(value) {
261
+ if (typeof value !== "string" || value.trim().length === 0) {
262
+ throw new SyndrooConfigError("apiKey is required. Keep it in a server, CLI, or CI credential store, " +
263
+ "never in client-side code or a NEXT_PUBLIC_* variable.");
264
+ }
265
+ if (/\s/u.test(value)) {
266
+ throw new SyndrooConfigError("apiKey must not contain whitespace or line breaks.");
267
+ }
268
+ return value;
269
+ }
270
+ function validatePositiveDuration(value, label) {
271
+ if (!Number.isFinite(value) || value <= 0) {
272
+ throw new SyndrooConfigError(`${label} must be a positive, finite number of milliseconds.`);
273
+ }
274
+ }
275
+ function validateCreateInput(input) {
276
+ if (input === null || typeof input !== "object") {
277
+ throw new SyndrooValidationError("A post requires a content string and a list of platforms.");
278
+ }
279
+ if (typeof input.content !== "string" || input.content.trim().length === 0) {
280
+ throw new SyndrooValidationError("content must be a non-empty string.");
281
+ }
282
+ if (!Array.isArray(input.platforms) || input.platforms.length === 0) {
283
+ throw new SyndrooValidationError("platforms must be a non-empty array of platform names.");
284
+ }
285
+ input.platforms.forEach((platform, index) => {
286
+ if (typeof platform !== "string" || platform.trim().length === 0) {
287
+ throw new SyndrooValidationError(`platforms[${index}] must be a non-empty string.`);
288
+ }
289
+ });
290
+ if (input.scheduledAt !== undefined) {
291
+ if (typeof input.scheduledAt !== "string" ||
292
+ Number.isNaN(Date.parse(input.scheduledAt))) {
293
+ throw new SyndrooValidationError("scheduledAt must be an ISO 8601 date-time string with an explicit " +
294
+ "offset, for example 2030-01-02T03:04:05.000Z.");
295
+ }
296
+ }
297
+ const overrides = input.overrides;
298
+ if (overrides !== undefined) {
299
+ if (overrides === null || typeof overrides !== "object") {
300
+ throw new SyndrooValidationError("overrides must be an object keyed by platform name.");
301
+ }
302
+ for (const [platform, override] of Object.entries(overrides)) {
303
+ if (override === null || typeof override !== "object") {
304
+ throw new SyndrooValidationError(`overrides.${platform} must be an object with an optional content string.`);
305
+ }
306
+ const content = override.content;
307
+ if (content !== undefined && typeof content !== "string") {
308
+ throw new SyndrooValidationError(`overrides.${platform}.content must be a string.`);
309
+ }
310
+ }
311
+ }
312
+ }
313
+ function validateIdempotencyKey(value) {
314
+ if (typeof value !== "string" || !IDEMPOTENCY_KEY_PATTERN.test(value)) {
315
+ throw new SyndrooValidationError("idempotencyKey must use 1-128 letters, digits, dots, underscores, colons, " +
316
+ "or hyphens, and must be reused for the same logical post.");
317
+ }
318
+ return value;
319
+ }
320
+ function validatePostId(value) {
321
+ if (typeof value !== "string" || value.length === 0) {
322
+ throw new SyndrooValidationError("A post id is required.");
323
+ }
324
+ return value;
325
+ }
326
+ function validateLimit(value) {
327
+ if (!Number.isInteger(value) || value < 1 || value > 100) {
328
+ throw new SyndrooValidationError("limit must be an integer between 1 and 100.");
329
+ }
330
+ return value;
331
+ }
332
+ function sleep(ms, signal) {
333
+ return new Promise((resolve, reject) => {
334
+ if (signal?.aborted === true) {
335
+ reject(new SyndrooAbortError("Waiting was aborted before the next status read. Nothing was created or cancelled.", { cause: signal.reason }));
336
+ return;
337
+ }
338
+ const handle = setTimeout(() => {
339
+ finish();
340
+ resolve();
341
+ }, ms);
342
+ const onAbort = () => {
343
+ finish();
344
+ reject(new SyndrooAbortError("Waiting was aborted. Nothing was created or cancelled; the post continues on the server.", { cause: signal?.reason }));
345
+ };
346
+ function finish() {
347
+ clearTimeout(handle);
348
+ signal?.removeEventListener("abort", onAbort);
349
+ }
350
+ unrefTimer(handle);
351
+ signal?.addEventListener("abort", onAbort, { once: true });
352
+ });
353
+ }
354
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Typed error hierarchy for the public Syndroo SDK.
3
+ *
4
+ * Every failure the SDK raises is a `SyndrooError`, so callers can narrow on
5
+ * one base class and still classify the outcome precisely. The
6
+ * `requestMayHaveBeenApplied` flag is the state that decides whether a resend
7
+ * is safe: it is true whenever a write may already have reached Syndroo, which
8
+ * is exactly the case where retrying with a new idempotency key could create a
9
+ * second post.
10
+ */
11
+ import type { PostDetail } from "./types.js";
12
+ export type SyndrooErrorCode = "CONFIG" | "VALIDATION" | "ABORTED" | "TIMEOUT" | "NETWORK" | "INVALID_RESPONSE" | "WAIT_TIMEOUT" | (string & {});
13
+ export interface SyndrooErrorInit {
14
+ cause?: unknown | undefined;
15
+ requestMayHaveBeenApplied?: boolean | undefined;
16
+ }
17
+ export declare class SyndrooError<Code extends SyndrooErrorCode = SyndrooErrorCode> extends Error {
18
+ readonly code: Code;
19
+ readonly requestMayHaveBeenApplied: boolean;
20
+ constructor(message: string, init: SyndrooErrorInit & {
21
+ code: Code;
22
+ });
23
+ }
24
+ /** The client configuration itself is unusable, so no request was sent. */
25
+ export declare class SyndrooConfigError extends SyndrooError<"CONFIG"> {
26
+ constructor(message: string);
27
+ }
28
+ /** The caller's argument cannot become a valid Syndroo request. */
29
+ export declare class SyndrooValidationError extends SyndrooError<"VALIDATION"> {
30
+ constructor(message: string);
31
+ }
32
+ /** The caller aborted through an AbortSignal. */
33
+ export declare class SyndrooAbortError extends SyndrooError<"ABORTED"> {
34
+ constructor(message: string, init?: SyndrooErrorInit);
35
+ }
36
+ /** The configured deadline elapsed before the response was received. */
37
+ export declare class SyndrooTimeoutError extends SyndrooError<"TIMEOUT"> {
38
+ readonly timeoutMs: number;
39
+ constructor(message: string, init: SyndrooErrorInit & {
40
+ timeoutMs: number;
41
+ });
42
+ }
43
+ /**
44
+ * The request never produced an HTTP response. `networkCode` carries the
45
+ * runtime's error code, such as `ECONNREFUSED`, when one is available.
46
+ */
47
+ export declare class SyndrooNetworkError extends SyndrooError<"NETWORK"> {
48
+ readonly networkCode?: string;
49
+ constructor(message: string, init: SyndrooErrorInit & {
50
+ networkCode?: string | undefined;
51
+ });
52
+ }
53
+ /**
54
+ * Syndroo answered, but the answer is not the documented JSON contract: a
55
+ * non-JSON body, a missing required field, or a body above the configured
56
+ * size limit. The outcome of a write is never inferred from a bad response.
57
+ */
58
+ export declare class SyndrooResponseError extends SyndrooError<"INVALID_RESPONSE"> {
59
+ readonly status?: number;
60
+ readonly preview?: string;
61
+ constructor(message: string, init?: SyndrooErrorInit & {
62
+ status?: number | undefined;
63
+ preview?: string | undefined;
64
+ });
65
+ }
66
+ /**
67
+ * Syndroo rejected the request with a documented error envelope. `code` is the
68
+ * server's code such as `UNAUTHORIZED`, `POST_NOT_FOUND`,
69
+ * `IDEMPOTENCY_CONFLICT`, or `PLATFORM_NOT_CONFIGURED`, and `HTTP_<status>`
70
+ * when the body did not carry one.
71
+ */
72
+ export declare class SyndrooApiError extends SyndrooError {
73
+ readonly status: number;
74
+ readonly retryAfterMs?: number;
75
+ constructor(message: string, init: SyndrooErrorInit & {
76
+ code: SyndrooErrorCode;
77
+ status: number;
78
+ retryAfterMs?: number | undefined;
79
+ });
80
+ /** Syndroo or an intermediary asked the client to slow down. */
81
+ get retryable(): boolean;
82
+ }
83
+ /** `posts.wait` reached its deadline before the post became terminal. */
84
+ export declare class SyndrooWaitTimeoutError extends SyndrooError<"WAIT_TIMEOUT"> {
85
+ readonly postId: string;
86
+ readonly timeoutMs: number;
87
+ readonly lastStatus?: string;
88
+ readonly lastPost?: PostDetail;
89
+ readonly lastError?: SyndrooError;
90
+ constructor(message: string, init: {
91
+ postId: string;
92
+ timeoutMs: number;
93
+ lastStatus?: string | undefined;
94
+ lastPost?: PostDetail | undefined;
95
+ lastError?: SyndrooError | undefined;
96
+ });
97
+ }
98
+ export declare function isSyndrooError(value: unknown): value is SyndrooError;
99
+ /**
100
+ * Internal helper for bounded diagnostics. Error messages and response
101
+ * previews must never grow with the size of an untrusted body.
102
+ */
103
+ export declare function truncate(value: string, limit: number): string;
104
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/dist/errors.js ADDED
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Typed error hierarchy for the public Syndroo SDK.
3
+ *
4
+ * Every failure the SDK raises is a `SyndrooError`, so callers can narrow on
5
+ * one base class and still classify the outcome precisely. The
6
+ * `requestMayHaveBeenApplied` flag is the state that decides whether a resend
7
+ * is safe: it is true whenever a write may already have reached Syndroo, which
8
+ * is exactly the case where retrying with a new idempotency key could create a
9
+ * second post.
10
+ */
11
+ export class SyndrooError extends Error {
12
+ code;
13
+ requestMayHaveBeenApplied;
14
+ constructor(message, init) {
15
+ super(message, { cause: init.cause });
16
+ this.name = "SyndrooError";
17
+ this.code = init.code;
18
+ this.requestMayHaveBeenApplied = init.requestMayHaveBeenApplied ?? false;
19
+ }
20
+ }
21
+ /** The client configuration itself is unusable, so no request was sent. */
22
+ export class SyndrooConfigError extends SyndrooError {
23
+ constructor(message) {
24
+ super(message, { code: "CONFIG" });
25
+ this.name = "SyndrooConfigError";
26
+ }
27
+ }
28
+ /** The caller's argument cannot become a valid Syndroo request. */
29
+ export class SyndrooValidationError extends SyndrooError {
30
+ constructor(message) {
31
+ super(message, { code: "VALIDATION" });
32
+ this.name = "SyndrooValidationError";
33
+ }
34
+ }
35
+ /** The caller aborted through an AbortSignal. */
36
+ export class SyndrooAbortError extends SyndrooError {
37
+ constructor(message, init = {}) {
38
+ super(message, {
39
+ code: "ABORTED",
40
+ cause: init.cause,
41
+ requestMayHaveBeenApplied: init.requestMayHaveBeenApplied,
42
+ });
43
+ this.name = "SyndrooAbortError";
44
+ }
45
+ }
46
+ /** The configured deadline elapsed before the response was received. */
47
+ export class SyndrooTimeoutError extends SyndrooError {
48
+ timeoutMs;
49
+ constructor(message, init) {
50
+ super(message, {
51
+ code: "TIMEOUT",
52
+ cause: init.cause,
53
+ requestMayHaveBeenApplied: init.requestMayHaveBeenApplied,
54
+ });
55
+ this.name = "SyndrooTimeoutError";
56
+ this.timeoutMs = init.timeoutMs;
57
+ }
58
+ }
59
+ /**
60
+ * The request never produced an HTTP response. `networkCode` carries the
61
+ * runtime's error code, such as `ECONNREFUSED`, when one is available.
62
+ */
63
+ export class SyndrooNetworkError extends SyndrooError {
64
+ networkCode;
65
+ constructor(message, init) {
66
+ super(message, {
67
+ code: "NETWORK",
68
+ cause: init.cause,
69
+ requestMayHaveBeenApplied: init.requestMayHaveBeenApplied,
70
+ });
71
+ this.name = "SyndrooNetworkError";
72
+ if (init.networkCode !== undefined) {
73
+ this.networkCode = init.networkCode;
74
+ }
75
+ }
76
+ }
77
+ /**
78
+ * Syndroo answered, but the answer is not the documented JSON contract: a
79
+ * non-JSON body, a missing required field, or a body above the configured
80
+ * size limit. The outcome of a write is never inferred from a bad response.
81
+ */
82
+ export class SyndrooResponseError extends SyndrooError {
83
+ status;
84
+ preview;
85
+ constructor(message, init = {}) {
86
+ super(message, {
87
+ code: "INVALID_RESPONSE",
88
+ cause: init.cause,
89
+ requestMayHaveBeenApplied: init.requestMayHaveBeenApplied,
90
+ });
91
+ this.name = "SyndrooResponseError";
92
+ if (init.status !== undefined) {
93
+ this.status = init.status;
94
+ }
95
+ if (init.preview !== undefined) {
96
+ this.preview = init.preview;
97
+ }
98
+ }
99
+ }
100
+ /**
101
+ * Syndroo rejected the request with a documented error envelope. `code` is the
102
+ * server's code such as `UNAUTHORIZED`, `POST_NOT_FOUND`,
103
+ * `IDEMPOTENCY_CONFLICT`, or `PLATFORM_NOT_CONFIGURED`, and `HTTP_<status>`
104
+ * when the body did not carry one.
105
+ */
106
+ export class SyndrooApiError extends SyndrooError {
107
+ status;
108
+ retryAfterMs;
109
+ constructor(message, init) {
110
+ super(message, {
111
+ code: init.code,
112
+ cause: init.cause,
113
+ requestMayHaveBeenApplied: init.requestMayHaveBeenApplied,
114
+ });
115
+ this.name = "SyndrooApiError";
116
+ this.status = init.status;
117
+ if (init.retryAfterMs !== undefined) {
118
+ this.retryAfterMs = init.retryAfterMs;
119
+ }
120
+ }
121
+ /** Syndroo or an intermediary asked the client to slow down. */
122
+ get retryable() {
123
+ return this.status === 429 || this.status >= 500;
124
+ }
125
+ }
126
+ /** `posts.wait` reached its deadline before the post became terminal. */
127
+ export class SyndrooWaitTimeoutError extends SyndrooError {
128
+ postId;
129
+ timeoutMs;
130
+ lastStatus;
131
+ lastPost;
132
+ lastError;
133
+ constructor(message, init) {
134
+ super(message, { code: "WAIT_TIMEOUT", requestMayHaveBeenApplied: false });
135
+ this.name = "SyndrooWaitTimeoutError";
136
+ this.postId = init.postId;
137
+ this.timeoutMs = init.timeoutMs;
138
+ if (init.lastStatus !== undefined) {
139
+ this.lastStatus = init.lastStatus;
140
+ }
141
+ if (init.lastPost !== undefined) {
142
+ this.lastPost = init.lastPost;
143
+ }
144
+ if (init.lastError !== undefined) {
145
+ this.lastError = init.lastError;
146
+ }
147
+ }
148
+ }
149
+ export function isSyndrooError(value) {
150
+ return value instanceof SyndrooError;
151
+ }
152
+ /**
153
+ * Internal helper for bounded diagnostics. Error messages and response
154
+ * previews must never grow with the size of an untrusted body.
155
+ */
156
+ export function truncate(value, limit) {
157
+ if (value.length <= limit) {
158
+ return value;
159
+ }
160
+ return `${value.slice(0, limit)}...[${value.length - limit} more characters]`;
161
+ }
162
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}