@chronos.sh/sdk 0.0.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.
@@ -0,0 +1,323 @@
1
+ //#region src/types.d.ts
2
+ /**
3
+ * Result returned by a {@link ChronosHandler}. Plain objects are recorded on
4
+ * the execution; `void` / `undefined` records no result.
5
+ */
6
+ type ChronosHandlerResult = Record<string, unknown> | void;
7
+ /**
8
+ * Custom fetch implementation. Compatible with `globalThis.fetch`. Pass via
9
+ * {@link ChronosOptions.fetch} to inject middleware (logging, tracing, custom
10
+ * timeouts) or run in environments without a global `fetch`.
11
+ */
12
+ type FetchLike = (input: string | URL, init?: RequestInit) => Promise<Response>;
13
+ /**
14
+ * Logger interface. Pass via {@link ChronosOptions.logger} to integrate with
15
+ * your app's logging stack.
16
+ *
17
+ * Note: signature is `(message, meta?)` — message string first, optional
18
+ * structured metadata second. If adapting from pino-style `(obj, message)`,
19
+ * swap the argument order.
20
+ */
21
+ type ChronosLogger = {
22
+ debug(message: string, meta?: Record<string, unknown>): void;
23
+ info(message: string, meta?: Record<string, unknown>): void;
24
+ warn(message: string, meta?: Record<string, unknown>): void;
25
+ error(message: string, meta?: Record<string, unknown>): void;
26
+ };
27
+ /** Options for constructing a {@link Chronos} client. */
28
+ type ChronosOptions = {
29
+ /** API key for authentication. Sent as `Authorization: Bearer <key>`. */apiKey: string;
30
+ /**
31
+ * Override the API base URL. Defaults to `https://api.chronos.sh`. Useful
32
+ * for local development or self-hosted Chronos instances.
33
+ */
34
+ baseUrl?: string; /** Custom fetch implementation. Defaults to `globalThis.fetch`. */
35
+ fetch?: FetchLike; /** Custom logger. Defaults to a console-backed logger. */
36
+ logger?: ChronosLogger;
37
+ /**
38
+ * Worker long-poll wait time in seconds. Must be an integer between 0 and
39
+ * 20 inclusive. Defaults to 20 (the API maximum).
40
+ */
41
+ pollWaitTimeSeconds?: number;
42
+ /**
43
+ * Worker retry delay in milliseconds. Used between failed result-report
44
+ * attempts and between poll-loop iterations after a claim error. Defaults
45
+ * to 1000.
46
+ */
47
+ retryDelayMs?: number;
48
+ };
49
+ /** Schedule that produced a job. */
50
+ type ChronosSchedule = {
51
+ /** Schedule identifier. */id: string; /** Human-readable schedule name. */
52
+ name: string;
53
+ };
54
+ /**
55
+ * Context passed to a {@link ChronosHandler} when a job is claimed. Type the
56
+ * payload by supplying a generic argument.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * type SendEmailPayload = { to: string; subject: string };
61
+ *
62
+ * chronos.worker.handle<SendEmailPayload>('send-email', async (ctx) => {
63
+ * await sendEmail(ctx.payload.to, ctx.payload.subject);
64
+ * return { sent: true };
65
+ * });
66
+ * ```
67
+ */
68
+ type ChronosContext<TPayload = unknown> = {
69
+ /** Stable identifier for the job (the schedule run). */jobId: string; /** Identifier for this specific execution attempt. Use for idempotency. */
70
+ executionId: string; /** Handler name, matching the one registered with `worker.handle()`. */
71
+ handler: string; /** Job payload, typed as `TPayload`. */
72
+ payload: TPayload; /** When the job was scheduled to run. */
73
+ scheduledFor: Date; /** Attempt number. 1 for the first attempt, increments on retries. */
74
+ attempt: number; /** Soft timeout for the handler in seconds. Informational; the SDK does not enforce. */
75
+ timeout: number; /** Schedule that produced this job, or `null` for ad-hoc jobs. */
76
+ schedule: ChronosSchedule | null;
77
+ };
78
+ /**
79
+ * Async function that processes a Chronos job. Return a plain object to
80
+ * record a result on the execution, or `undefined` for no result.
81
+ */
82
+ type ChronosHandler<TPayload = unknown> = (ctx: ChronosContext<TPayload>) => ChronosHandlerResult | Promise<ChronosHandlerResult>;
83
+ //#endregion
84
+ //#region src/client.d.ts
85
+ /** Default Chronos API base URL. */
86
+ declare const DEFAULT_BASE_URL = "https://api.chronos.sh";
87
+ declare class BaseClient {
88
+ readonly apiKey: string;
89
+ readonly baseUrl: string;
90
+ readonly fetch: FetchLike;
91
+ readonly logger: ChronosLogger;
92
+ private readonly headers;
93
+ constructor(options: ChronosOptions);
94
+ request<T>(path: string, body: Record<string, unknown>, signal?: AbortSignal): Promise<T>;
95
+ }
96
+ //#endregion
97
+ //#region src/worker.d.ts
98
+ /** Default worker long-poll wait time in seconds. Equal to the API maximum. */
99
+ declare const DEFAULT_POLL_WAIT_TIME_SECONDS = 20;
100
+ /**
101
+ * Long-poll worker. Claims jobs from the Chronos API, dispatches them to
102
+ * registered handlers, and reports results.
103
+ *
104
+ * Construct via `new Chronos({ apiKey }).worker` rather than directly.
105
+ */
106
+ declare class Worker {
107
+ private readonly client;
108
+ private readonly pollWaitTimeSeconds;
109
+ private readonly retryDelayMs;
110
+ private readonly handlers;
111
+ private handlerNames;
112
+ private startPromise?;
113
+ private pollController?;
114
+ constructor(client: BaseClient, options: ChronosOptions);
115
+ /**
116
+ * Register a handler for a named job type. Invoked when the Chronos API
117
+ * claims a job whose `handler` field matches `name`. Names are trimmed and
118
+ * must be 1–255 characters.
119
+ *
120
+ * @param name - Handler name. Must match the schedule's `handler` on the API side.
121
+ * @param handler - Async function invoked with the job context. Return a
122
+ * plain object to record a result, or `undefined` for none.
123
+ * @returns The Worker, for chaining.
124
+ * @throws {ChronosError} If the name is invalid, already registered, or `handler` is not a function.
125
+ *
126
+ * @example
127
+ * ```ts
128
+ * chronos.worker
129
+ * .handle('send-email', async (ctx) => ({ sent: true }))
130
+ * .handle('cleanup', async () => undefined);
131
+ * ```
132
+ */
133
+ handle<TPayload = unknown>(name: string, handler: ChronosHandler<TPayload>): this;
134
+ /**
135
+ * Begin long-polling for jobs. The returned promise resolves when
136
+ * {@link Worker.stop} is called and any in-flight job completes.
137
+ *
138
+ * @throws {ChronosError} Synchronously, if no handlers are registered or the worker is already running.
139
+ */
140
+ start(): Promise<void>;
141
+ /**
142
+ * Request graceful shutdown. The poll loop is aborted immediately; any
143
+ * in-flight handler and result-report are allowed to complete to preserve
144
+ * at-least-once delivery. Returns the same promise as the active
145
+ * {@link Worker.start}, or a resolved promise if the worker isn't running.
146
+ */
147
+ stop(): Promise<void>;
148
+ private get isStopped();
149
+ private runLoop;
150
+ private claimJob;
151
+ private processJob;
152
+ private handleUnregisteredJob;
153
+ private safeReportFailed;
154
+ private reportCompleted;
155
+ private reportFailed;
156
+ private reportResultWithRetry;
157
+ private logResultReportFailure;
158
+ }
159
+ //#endregion
160
+ //#region src/errors.d.ts
161
+ /**
162
+ * Base class for all errors thrown by the Chronos SDK. Catch this in a
163
+ * single `catch` to handle any SDK failure generically; use the subclasses
164
+ * to branch on cause.
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * import { Chronos, ChronosError } from '@chronos.sh/sdk';
169
+ *
170
+ * const chronos = new Chronos({ apiKey: 'chrns_...' });
171
+ * try {
172
+ * await chronos.worker.start();
173
+ * } catch (err) {
174
+ * if (err instanceof ChronosError) {
175
+ * console.error('Chronos failed:', err.message);
176
+ * }
177
+ * }
178
+ * ```
179
+ */
180
+ declare class ChronosError extends Error {
181
+ /** Original error/value that caused this SDK error, when one is available. */
182
+ readonly cause?: unknown;
183
+ constructor(message: string, options?: {
184
+ cause?: unknown;
185
+ });
186
+ }
187
+ /**
188
+ * Thrown when SDK options fail validation at `new Chronos({ ... })`. Covers
189
+ * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, and `retryDelayMs`.
190
+ *
191
+ * @example
192
+ * ```ts
193
+ * import { Chronos, ChronosConfigError } from '@chronos.sh/sdk';
194
+ *
195
+ * try {
196
+ * const chronos = new Chronos({ apiKey: '' });
197
+ * } catch (err) {
198
+ * if (err instanceof ChronosConfigError) {
199
+ * console.error('Invalid Chronos config:', err.message);
200
+ * }
201
+ * }
202
+ * ```
203
+ */
204
+ declare class ChronosConfigError extends ChronosError {
205
+ constructor(message: string);
206
+ }
207
+ /** Options for constructing a {@link ChronosApiError}. */
208
+ type ChronosApiErrorOptions = {
209
+ /** HTTP status code returned by the Chronos API. */status: number; /** Application-level error code from the response envelope, when present. */
210
+ code?: string; /** Full parsed response payload (envelope + data, or whatever the server returned). */
211
+ body?: unknown; /** Value of the `X-Request-Id` response header, when present. Pair with server logs. */
212
+ requestId?: string;
213
+ };
214
+ /**
215
+ * Thrown when the Chronos API responds with a non-2xx status or a
216
+ * `success: false` envelope. Carries HTTP `status`, the application
217
+ * `code`, parsed `body`, and the API's `X-Request-Id`.
218
+ *
219
+ * `instanceof ChronosApiError` means the server replied;
220
+ * network/transport failures throw {@link ChronosNetworkError} instead.
221
+ *
222
+ * @example
223
+ * ```ts
224
+ * import { ChronosApiError } from '@chronos.sh/sdk';
225
+ *
226
+ * function handleSdkError(err: unknown) {
227
+ * if (err instanceof ChronosApiError) {
228
+ * if (err.status === 401) return refreshAuth();
229
+ * console.error('API error', { status: err.status, requestId: err.requestId });
230
+ * }
231
+ * }
232
+ * ```
233
+ */
234
+ declare class ChronosApiError extends ChronosError {
235
+ /** HTTP status code returned by the Chronos API. */
236
+ readonly status: number;
237
+ /** Application-level error code from the response envelope, when present. */
238
+ readonly code?: string;
239
+ /** Full parsed response payload (envelope + data, or whatever the server returned). */
240
+ readonly body?: unknown;
241
+ /** Value of the `X-Request-Id` response header, when present. */
242
+ readonly requestId?: string;
243
+ constructor(message: string, options: ChronosApiErrorOptions);
244
+ }
245
+ /**
246
+ * Thrown when the underlying `fetch` rejects before the server replies —
247
+ * DNS failure, TCP reset, connection refused, etc. The original error is
248
+ * available on `.cause`.
249
+ *
250
+ * Abort signals propagate unwrapped — `instanceof ChronosNetworkError`
251
+ * always means a real transport failure, not a graceful shutdown.
252
+ *
253
+ * @example
254
+ * ```ts
255
+ * import { ChronosNetworkError } from '@chronos.sh/sdk';
256
+ *
257
+ * function handleSdkError(err: unknown) {
258
+ * if (err instanceof ChronosNetworkError) {
259
+ * console.warn('Transport blip', { cause: err.cause });
260
+ * }
261
+ * }
262
+ * ```
263
+ */
264
+ declare class ChronosNetworkError extends ChronosError {
265
+ /** Original error/value rejected by the underlying `fetch`. */
266
+ readonly cause: unknown;
267
+ constructor(message: string, options: {
268
+ cause: unknown;
269
+ });
270
+ }
271
+ /**
272
+ * Wraps an exception thrown by a user-supplied {@link ChronosHandler}. The
273
+ * original error is on `.cause`; `.message` is copied from the original so
274
+ * the SDK reports it to the API as the failure reason.
275
+ *
276
+ * @example
277
+ * ```ts
278
+ * import { ChronosHandlerError } from '@chronos.sh/sdk';
279
+ *
280
+ * if (err instanceof ChronosHandlerError) {
281
+ * console.error('Handler threw', err.cause);
282
+ * }
283
+ * ```
284
+ */
285
+ declare class ChronosHandlerError extends ChronosError {
286
+ /** Original error/value thrown by the user-supplied handler. */
287
+ readonly cause: unknown;
288
+ constructor(message: string, options: {
289
+ cause: unknown;
290
+ });
291
+ }
292
+ //#endregion
293
+ //#region src/index.d.ts
294
+ /**
295
+ * The Chronos SDK client. Composes worker and (future) REST resource
296
+ * subclients from a single instance.
297
+ *
298
+ * @example
299
+ * ```ts
300
+ * import { Chronos } from '@chronos.sh/sdk';
301
+ *
302
+ * const chronos = new Chronos({ apiKey: process.env.CHRONOS_API_KEY! });
303
+ *
304
+ * chronos.worker.handle<{ to: string }>('send-email', async (ctx) => {
305
+ * await sendEmail(ctx.payload.to);
306
+ * return { sent: true };
307
+ * });
308
+ *
309
+ * await chronos.worker.start();
310
+ * ```
311
+ */
312
+ declare class Chronos {
313
+ /** Long-poll worker for executing pull-mode jobs. */
314
+ readonly worker: Worker;
315
+ /**
316
+ * @param options - Client configuration. Only `apiKey` is required.
317
+ * @throws {ChronosConfigError} If `apiKey` is missing or any option fails validation.
318
+ */
319
+ constructor(options: ChronosOptions);
320
+ }
321
+ //#endregion
322
+ export { Chronos, ChronosApiError, type ChronosApiErrorOptions, ChronosConfigError, type ChronosContext, ChronosError, type ChronosHandler, ChronosHandlerError, type ChronosHandlerResult, type ChronosLogger, ChronosNetworkError, type ChronosOptions, type ChronosSchedule, DEFAULT_BASE_URL, DEFAULT_POLL_WAIT_TIME_SECONDS, type FetchLike };
323
+ //# sourceMappingURL=index.d.ts.map