@chronos.sh/sdk 0.1.1 → 0.1.2-canary.2deb3ad

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/index.cjs CHANGED
@@ -32,7 +32,8 @@ var ChronosError = class extends Error {
32
32
  };
33
33
  /**
34
34
  * Thrown when SDK options fail validation at `new Chronos({ ... })`. Covers
35
- * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, and `retryDelayMs`.
35
+ * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, `retryDelayMs`, `timeoutMs`, and
36
+ * `workerId`.
36
37
  *
37
38
  * @example
38
39
  * ```ts
@@ -389,7 +390,7 @@ function detectRuntime() {
389
390
  }
390
391
  //#endregion
391
392
  //#region src/internal/version.ts
392
- const SDK_VERSION = "0.1.1";
393
+ const SDK_VERSION = "0.1.2-canary.2deb3ad";
393
394
  //#endregion
394
395
  //#region src/worker.ts
395
396
  /** Default worker long-poll wait time in seconds. Equal to the API maximum. */
@@ -473,15 +474,10 @@ var Worker = class {
473
474
  return this.startPromise;
474
475
  }
475
476
  /**
476
- * Request graceful shutdown. The poll loop is aborted immediately; any
477
- * in-flight handler that has not exceeded its timeout, along with the
478
- * subsequent result-report, is allowed to complete. Timed-out handlers
479
- * are abandoned (their {@link ChronosContext.signal} fires, but the SDK
480
- * does not wait for them). Every HTTP request is bounded by the `timeoutMs`
481
- * transport timeout and retry waits are skipped once stop is requested, so
482
- * the returned promise resolves in bounded time. Returns the same promise
483
- * as the active {@link Worker.start}, or a resolved promise if the worker
484
- * isn't running.
477
+ * Request graceful shutdown: abort the poll, let an in-flight handler
478
+ * finish (up to its timeout) and report its result, then resolve. Bounded
479
+ * by that timeout plus `timeoutMs` per report attempt. Never rejects; a
480
+ * credential rejection surfaces on {@link Worker.start} instead.
485
481
  */
486
482
  stop() {
487
483
  this.pollController?.abort();
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/errors.ts","../src/internal/logger.ts","../src/internal/validate.ts","../src/client.ts","../src/internal/id.ts","../src/internal/runtime.ts","../src/internal/version.ts","../src/worker.ts","../src/webhook.ts","../src/index.ts"],"sourcesContent":["/**\n * Base class for all errors thrown by the Chronos SDK. Catch this in a\n * single `catch` to handle any SDK failure generically; use the subclasses\n * to branch on cause.\n *\n * @example\n * ```ts\n * import { Chronos, ChronosError } from '@chronos.sh/sdk';\n *\n * const chronos = new Chronos({ apiKey: 'chrns_...' });\n * try {\n * await chronos.worker.start();\n * } catch (err) {\n * if (err instanceof ChronosError) {\n * console.error('Chronos failed:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosError extends Error {\n /** Original error/value that caused this SDK error, when one is available. */\n declare readonly cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'ChronosError';\n\n if (options && !('cause' in this)) {\n Object.defineProperty(this, 'cause', {\n value: options.cause,\n configurable: true,\n writable: true,\n });\n }\n }\n}\n\n/**\n * Thrown when SDK options fail validation at `new Chronos({ ... })`. Covers\n * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, and `retryDelayMs`.\n *\n * @example\n * ```ts\n * import { Chronos, ChronosConfigError } from '@chronos.sh/sdk';\n *\n * try {\n * const chronos = new Chronos({ apiKey: '' });\n * } catch (err) {\n * if (err instanceof ChronosConfigError) {\n * console.error('Invalid Chronos config:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosConfigError extends ChronosError {\n constructor(message: string) {\n super(message);\n this.name = 'ChronosConfigError';\n }\n}\n\n/** Rate-limit budget from `X-RateLimit-*` response headers. Present on non-429 responses. */\nexport type RateLimitInfo = {\n /** Maximum requests allowed per window. */\n limit: number;\n /** Requests remaining in the current window. */\n remaining: number;\n /** Seconds until the current window resets. */\n reset: number;\n};\n\n/** Options for constructing a {@link ChronosApiError}. */\nexport type ChronosApiErrorOptions = {\n /** HTTP status code returned by the Chronos API. */\n status: number;\n /** Application-level error code from the response envelope, when present. */\n code?: string;\n /** Full parsed response payload (envelope + data, or whatever the server returned). */\n body?: unknown;\n /** Value of the `X-Request-Id` response header, when present. Pair with server logs. */\n requestId?: string;\n /** Seconds to wait before retrying, from the `Retry-After` response header. Present on 429 and 5xx responses that include the header. */\n retryAfterSeconds?: number;\n /** Rate-limit budget from `X-RateLimit-*` headers. Present on non-429 responses. */\n rateLimit?: RateLimitInfo;\n};\n\n/**\n * Thrown when the Chronos API responds with a non-2xx status or a\n * `success: false` envelope. Carries HTTP `status`, the application\n * `code`, parsed `body`, the API's `X-Request-Id`, and — when the\n * relevant headers are present — rate-limit metadata\n * (`retryAfterSeconds` on 429 and 5xx, `rateLimit` on non-429 errors).\n *\n * `instanceof ChronosApiError` means the server replied;\n * network/transport failures throw {@link ChronosNetworkError} instead.\n * For 429 specifically, see {@link ChronosRateLimitError}.\n *\n * @example\n * ```ts\n * import { ChronosApiError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosApiError) {\n * if (err.status === 401) return refreshAuth();\n * console.error('API error', { status: err.status, requestId: err.requestId });\n * }\n * }\n * ```\n */\nexport class ChronosApiError extends ChronosError {\n /** HTTP status code returned by the Chronos API. */\n readonly status: number;\n /** Application-level error code from the response envelope, when present. */\n readonly code?: string;\n /** Full parsed response payload (envelope + data, or whatever the server returned). */\n readonly body?: unknown;\n /** Value of the `X-Request-Id` response header, when present. */\n readonly requestId?: string;\n /** Seconds to wait before retrying, from the `Retry-After` response header. Present on 429 and 5xx responses that include the header. */\n readonly retryAfterSeconds?: number;\n /** Rate-limit budget from `X-RateLimit-*` headers. Present on non-429 responses. */\n readonly rateLimit?: RateLimitInfo;\n\n constructor(message: string, options: ChronosApiErrorOptions) {\n super(message);\n this.name = 'ChronosApiError';\n this.status = options.status;\n this.code = options.code;\n this.body = options.body;\n this.requestId = options.requestId;\n this.retryAfterSeconds = options.retryAfterSeconds;\n this.rateLimit = options.rateLimit;\n }\n}\n\n/**\n * Thrown when the Chronos API responds with `429 Too Many Requests`.\n * Subclass of {@link ChronosApiError} — `instanceof ChronosRateLimitError`\n * narrows to a rate-limited response. `retryAfterSeconds` is set when the\n * response includes a `Retry-After` header; otherwise it is `undefined`.\n *\n * @example\n * ```ts\n * import { ChronosRateLimitError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosRateLimitError && err.retryAfterSeconds) {\n * console.warn(`Rate limited — retry after ${err.retryAfterSeconds}s`);\n * }\n * }\n * ```\n */\nexport class ChronosRateLimitError extends ChronosApiError {\n constructor(message: string, options: ChronosApiErrorOptions) {\n super(message, options);\n this.name = 'ChronosRateLimitError';\n }\n}\n\n/**\n * Thrown when a request fails at the transport layer — DNS failure, TCP\n * reset, connection refused, or a connection dropped mid-response. The\n * original error is available on `.cause`.\n *\n * Caller-supplied abort signals propagate unwrapped — `instanceof\n * ChronosNetworkError` always means a transport failure, not a graceful\n * shutdown. The SDK's own transport timeout throws the\n * {@link ChronosTimeoutError} subclass.\n *\n * @example\n * ```ts\n * import { ChronosNetworkError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosNetworkError) {\n * console.warn('Transport blip', { cause: err.cause });\n * }\n * }\n * ```\n */\nexport class ChronosNetworkError extends ChronosError {\n /** Original error/value rejected by the underlying `fetch`. */\n declare readonly cause: unknown;\n\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosNetworkError';\n }\n}\n\n/**\n * Thrown when an HTTP request exceeds the configured `timeoutMs` before the\n * response completes. Subclass of {@link ChronosNetworkError}, so generic\n * transport-failure handling catches it; the underlying rejection is on\n * `.cause`.\n *\n * @example\n * ```ts\n * import { ChronosTimeoutError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosTimeoutError) {\n * console.warn('Chronos request timed out', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosTimeoutError extends ChronosNetworkError {\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosTimeoutError';\n }\n}\n\n/**\n * Wraps an exception thrown by a user-supplied {@link ChronosHandler}. The\n * original error is on `.cause`; `.message` is copied from the original so\n * the SDK reports it to the API as the failure reason.\n *\n * @example\n * ```ts\n * import { ChronosHandlerError } from '@chronos.sh/sdk';\n *\n * if (err instanceof ChronosHandlerError) {\n * console.error('Handler threw', err.cause);\n * }\n * ```\n */\nexport class ChronosHandlerError extends ChronosError {\n /** Original error/value thrown by the user-supplied handler. */\n declare readonly cause: unknown;\n\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosHandlerError';\n }\n}\n\n/**\n * Thrown by {@link Webhook.verify} when signature verification fails.\n * Covers missing or malformed headers, expired timestamps, and signature\n * mismatches.\n *\n * @example\n * ```ts\n * import { Webhook, ChronosWebhookVerificationError } from '@chronos.sh/sdk';\n *\n * const wh = new Webhook(process.env.CHRONOS_SIGNING_SECRET!);\n * try {\n * const payload = await wh.verify(rawBody, headers);\n * } catch (err) {\n * if (err instanceof ChronosWebhookVerificationError) {\n * console.error('Webhook verification failed:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosWebhookVerificationError extends ChronosError {\n constructor(message: string) {\n super(message);\n this.name = 'ChronosWebhookVerificationError';\n }\n}\n","import type { ChronosLogger } from '../types';\n\nexport const defaultLogger: ChronosLogger = {\n debug: (message, meta) => logToConsole(console.debug, message, meta),\n info: (message, meta) => logToConsole(console.info, message, meta),\n warn: (message, meta) => logToConsole(console.warn, message, meta),\n error: (message, meta) => logToConsole(console.error, message, meta),\n};\n\nfunction logToConsole(\n method: (message?: unknown, ...optionalParams: unknown[]) => void,\n message: string,\n meta?: Record<string, unknown>,\n): void {\n if (meta) {\n method(message, meta);\n } else {\n method(message);\n }\n}\n","import { ChronosConfigError, ChronosError } from '../errors';\n\nexport const MAX_HANDLER_NAME_LENGTH = 255;\nexport const MAX_POLL_WAIT_TIME_SECONDS = 20;\n\nexport function validateApiKey(apiKey: string | undefined): string {\n const trimmed = apiKey?.trim();\n if (!trimmed) {\n throw new ChronosConfigError('Chronos apiKey is required');\n }\n return trimmed;\n}\n\nexport function validatePollWaitTime(seconds: number): void {\n if (!Number.isInteger(seconds) || seconds < 0 || seconds > MAX_POLL_WAIT_TIME_SECONDS) {\n throw new ChronosConfigError(\n `pollWaitTimeSeconds must be an integer between 0 and ${MAX_POLL_WAIT_TIME_SECONDS}`,\n );\n }\n}\n\nexport function validateRetryDelayMs(ms: number): void {\n if (!Number.isFinite(ms) || ms < 0) {\n throw new ChronosConfigError('retryDelayMs must be a non-negative number');\n }\n}\n\n// setTimeout silently clamps delays above 2^31-1 to 1ms.\nexport const MAX_TIMEOUT_MS = 2_147_483_647;\n\nexport function validateTimeoutMs(ms: number): void {\n if (!Number.isInteger(ms) || ms <= 0 || ms > MAX_TIMEOUT_MS) {\n throw new ChronosConfigError(\n `timeoutMs must be a positive integer no greater than ${MAX_TIMEOUT_MS}`,\n );\n }\n}\n\nexport function validateWorkerId(id: string): string {\n const trimmed = id.trim();\n if (trimmed.length === 0 || trimmed.length > 255) {\n throw new ChronosConfigError('workerId must be 1-255 characters');\n }\n return trimmed;\n}\n\nexport function normalizeHandlerName(name: string): string {\n const normalized = name.trim();\n\n if (!normalized) {\n throw new ChronosError('Handler name is required');\n }\n\n if (normalized.length > MAX_HANDLER_NAME_LENGTH) {\n throw new ChronosError(`Handler name must be ${MAX_HANDLER_NAME_LENGTH} characters or fewer`);\n }\n\n return normalized;\n}\n","import {\n ChronosApiError,\n ChronosConfigError,\n ChronosError,\n ChronosNetworkError,\n ChronosRateLimitError,\n ChronosTimeoutError,\n type RateLimitInfo,\n} from './errors';\nimport { defaultLogger } from './internal/logger';\nimport { validateApiKey, validateTimeoutMs } from './internal/validate';\nimport type { ChronosLogger, ChronosOptions, FetchLike } from './types';\n\n/** Default Chronos API base URL. */\nexport const DEFAULT_BASE_URL = 'https://api.chronos.sh';\n\n/** Default per-request transport timeout in milliseconds. */\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\ntype ApiResponse<T> = {\n success: boolean;\n message?: string;\n code?: string;\n data: T;\n};\n\ntype RequestOptions = {\n signal?: AbortSignal;\n timeoutMs?: number;\n};\n\nexport class BaseClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly fetch: FetchLike;\n readonly logger: ChronosLogger;\n readonly timeoutMs: number;\n private readonly headers: Record<string, string>;\n\n constructor(options: ChronosOptions) {\n this.apiKey = validateApiKey(options.apiKey);\n this.baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL);\n this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.logger = options.logger ?? defaultLogger;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateTimeoutMs(this.timeoutMs);\n this.headers = {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.apiKey}`,\n };\n }\n\n async request<T>(\n path: string,\n body: Record<string, unknown>,\n options: RequestOptions = {},\n ): Promise<T> {\n const { signal } = options;\n const timeoutMs = options.timeoutMs ?? this.timeoutMs;\n\n // Not AbortSignal.any: Node pins each composite onto long-lived source\n // signals (like the poll signal) forever, leaking per claim.\n const controller = new AbortController();\n let timedOut = false;\n const timer = setTimeout(() => {\n if (controller.signal.aborted) {\n return;\n }\n timedOut = true;\n controller.abort(\n new DOMException(`Chronos API request timed out after ${timeoutMs}ms`, 'TimeoutError'),\n );\n }, timeoutMs);\n const onCallerAbort = () => controller.abort(signal?.reason);\n if (signal?.aborted) {\n onCallerAbort();\n } else {\n signal?.addEventListener('abort', onCallerAbort, { once: true });\n }\n\n try {\n let response: Response;\n try {\n response = await this.fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n if (signal?.aborted && !timedOut) {\n throw err;\n }\n if (timedOut) {\n throw timeoutError(timeoutMs, err);\n }\n const message = err instanceof Error ? err.message : String(err);\n throw new ChronosNetworkError(`Chronos API request failed: ${message}`, { cause: err });\n }\n\n // A half-open connection can stall after headers arrive, so the\n // timeout must cover the body read too.\n let payload: ApiResponse<T> | null;\n try {\n payload = (await response.json()) as ApiResponse<T>;\n } catch (err) {\n // Aborted-state check, not reason identity: some runtimes wrap the\n // abort reason during body reads.\n if (signal?.aborted && !timedOut) {\n throw err;\n }\n if (timedOut) {\n throw timeoutError(timeoutMs, err);\n }\n if (err instanceof SyntaxError) {\n payload = null;\n } else {\n const message = err instanceof Error ? err.message : String(err);\n throw new ChronosNetworkError(`Chronos API response failed: ${message}`, { cause: err });\n }\n }\n\n const envelope = isEnvelope(payload) ? (payload as ApiResponse<T>) : undefined;\n\n if (!response.ok || (envelope && !envelope.success)) {\n const is429 = response.status === 429;\n const retryAfterApplies = is429 || response.status >= 500;\n const ErrorClass = is429 ? ChronosRateLimitError : ChronosApiError;\n throw new ErrorClass(apiErrorMessage(response, envelope), {\n status: response.status,\n code: typeof envelope?.code === 'string' ? envelope.code : undefined,\n body: payload,\n requestId: response.headers.get('x-request-id') ?? undefined,\n retryAfterSeconds: retryAfterApplies\n ? parseIntHeader(response.headers, 'retry-after')\n : undefined,\n rateLimit: is429 ? undefined : parseRateLimitHeaders(response.headers),\n });\n }\n\n if (!envelope) {\n // Plain ChronosError, not ChronosApiError — a malformed 200 body is\n // an infrastructure anomaly that should be retried, not a definitive\n // API rejection.\n throw new ChronosError('Chronos API returned an invalid response');\n }\n\n return envelope.data;\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener('abort', onCallerAbort);\n }\n }\n}\n\nfunction timeoutError(timeoutMs: number, cause: unknown): ChronosTimeoutError {\n return new ChronosTimeoutError(`Chronos API request timed out after ${timeoutMs}ms`, { cause });\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n const normalized = baseUrl.trim().replace(/\\/+$/, '');\n if (!normalized) {\n throw new ChronosConfigError('Chronos baseUrl is required');\n }\n return normalized;\n}\n\nfunction apiErrorMessage(\n response: Response,\n envelope: Record<string, unknown> | undefined,\n): string {\n if (typeof envelope?.message === 'string' && envelope.message.trim()) {\n return envelope.message;\n }\n\n return response.ok\n ? 'Chronos API returned an invalid response'\n : `Chronos API request failed with status ${response.status}`;\n}\n\nfunction parseIntHeader(headers: Headers, name: string): number | undefined {\n const raw = headers.get(name);\n if (raw === null || !/^\\d+$/.test(raw)) {\n return undefined;\n }\n return Number.parseInt(raw, 10);\n}\n\nfunction parseRateLimitHeaders(headers: Headers): RateLimitInfo | undefined {\n const limit = parseIntHeader(headers, 'x-ratelimit-limit');\n const remaining = parseIntHeader(headers, 'x-ratelimit-remaining');\n const reset = parseIntHeader(headers, 'x-ratelimit-reset');\n\n if (limit === undefined || remaining === undefined || reset === undefined) {\n return undefined;\n }\n return { limit, remaining, reset };\n}\n\n// Malformed bodies (arrays, primitives, missing `success`) are routed to the\n// invalid-response path, not classified as API errors.\nfunction isEnvelope(value: unknown): value is Record<string, unknown> & { success: boolean } {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n return typeof (value as Record<string, unknown>).success === 'boolean';\n}\n","export function generateWorkerId(): string {\n const bytes = crypto.getRandomValues(new Uint8Array(8));\n let hex = '';\n for (const b of bytes) {\n hex += b.toString(16).padStart(2, '0');\n }\n return `w_${hex}`;\n}\n","export function detectRuntime(): string {\n const g = globalThis as unknown as Record<string, Record<string, unknown> | undefined>;\n\n if (g.Bun != null) {\n return `bun/${(g.Bun.version as string | undefined) ?? 'unknown'}`;\n }\n\n if (g.Deno != null) {\n const version = g.Deno.version as Record<string, string> | undefined;\n return `deno/${version?.deno ?? 'unknown'}`;\n }\n\n if (typeof process !== 'undefined' && process.versions?.node) {\n return `node/${process.versions.node}`;\n }\n\n return 'unknown';\n}\n","declare const __SDK_VERSION__: string;\n\nexport const SDK_VERSION: string = __SDK_VERSION__;\n","import type { BaseClient } from './client';\nimport { ChronosApiError, ChronosError, ChronosHandlerError, ChronosNetworkError } from './errors';\nimport { generateWorkerId } from './internal/id';\nimport { detectRuntime } from './internal/runtime';\nimport {\n MAX_TIMEOUT_MS,\n normalizeHandlerName,\n validatePollWaitTime,\n validateRetryDelayMs,\n validateWorkerId,\n} from './internal/validate';\nimport { SDK_VERSION } from './internal/version';\nimport type {\n ChronosContext,\n ChronosHandler,\n ChronosHandlerResult,\n ChronosOptions,\n ChronosSchedule,\n} from './types';\n\n/** Default worker long-poll wait time in seconds. Equal to the API maximum. */\nexport const DEFAULT_POLL_WAIT_TIME_SECONDS = 20;\nconst DEFAULT_RETRY_DELAY_MS = 1_000;\n// Retry-After on 5xx often comes from proxies/CDNs with browser-oriented\n// values (e.g. 3600); uncapped it would park the worker for hours.\nconst MAX_RETRY_AFTER_MS = 60_000;\nconst RESULT_REPORT_MAX_ATTEMPTS = 3;\nconst MAX_REPORTED_ERROR_LENGTH = 4_096;\nconst DEFAULT_HANDLER_ERROR = 'Chronos handler failed';\n\ntype ResultStatus = 'completed' | 'failed' | 'timeout';\n\ntype HandlerOutcome = { timedOut: false; result: ChronosHandlerResult } | { timedOut: true };\n\ntype ClaimedJob = {\n job_id: string;\n execution_id: string;\n handler: string;\n scheduled_for: string;\n attempt: number;\n timeout: number;\n payload: unknown;\n schedule: ChronosSchedule | null;\n};\n\n/**\n * Long-poll worker. Claims jobs from the Chronos API, dispatches them to\n * registered handlers, and reports results.\n *\n * Construct via `new Chronos({ apiKey }).worker` rather than directly.\n */\nexport class Worker {\n private readonly client: BaseClient;\n private readonly pollWaitTimeSeconds: number;\n private readonly retryDelayMs: number;\n private readonly workerId: string;\n private readonly runtime: string;\n private readonly handlers = new Map<string, ChronosHandler<unknown>>();\n private handlerNames: string[] = [];\n private startPromise?: Promise<void>;\n private pollController?: AbortController;\n private startedAt = 0;\n\n constructor(client: BaseClient, options: ChronosOptions) {\n this.client = client;\n this.pollWaitTimeSeconds = options.pollWaitTimeSeconds ?? DEFAULT_POLL_WAIT_TIME_SECONDS;\n this.retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n this.workerId =\n options.workerId !== undefined ? validateWorkerId(options.workerId) : generateWorkerId();\n this.runtime = detectRuntime();\n\n validatePollWaitTime(this.pollWaitTimeSeconds);\n validateRetryDelayMs(this.retryDelayMs);\n }\n\n /**\n * Register a handler for a named job type. Invoked when the Chronos API\n * claims a job whose `handler` field matches `name`. Names are trimmed and\n * must be 1–255 characters.\n *\n * @param name - Handler name. Must match the schedule's `handler` on the API side.\n * @param handler - Async function invoked with the job context. Return a\n * plain object to record a result, or `undefined` for none.\n * @returns The Worker, for chaining.\n * @throws {ChronosError} If the name is invalid, already registered, or `handler` is not a function.\n *\n * @example\n * ```ts\n * chronos.worker\n * .handle('send-email', async (ctx) => ({ sent: true }))\n * .handle('cleanup', async () => undefined);\n * ```\n */\n handle<TPayload = unknown>(name: string, handler: ChronosHandler<TPayload>): this {\n const normalizedName = normalizeHandlerName(name);\n\n if (this.handlers.has(normalizedName)) {\n throw new ChronosError(`Handler \"${normalizedName}\" is already registered`);\n }\n\n if (typeof handler !== 'function') {\n throw new ChronosError(`Handler \"${normalizedName}\" must be a function`);\n }\n\n this.handlers.set(normalizedName, handler as ChronosHandler<unknown>);\n this.handlerNames.push(normalizedName);\n return this;\n }\n\n /**\n * Begin long-polling for jobs. The returned promise resolves when\n * {@link Worker.stop} is called and any in-flight job completes, and\n * rejects if the API rejects the worker's credentials (a 401 with the\n * `unauthorized` error code) — a misconfigured key is not recoverable by\n * retrying.\n *\n * @throws {ChronosError} Synchronously, if no handlers are registered or the worker is already running.\n * @throws {ChronosApiError} Via the returned promise, when the API rejects the worker's credentials.\n */\n start(): Promise<void> {\n if (this.startPromise) {\n throw new ChronosError('Chronos worker is already started');\n }\n\n if (this.handlers.size === 0) {\n throw new ChronosError('Register at least one handler before starting Chronos');\n }\n\n this.startedAt = performance.now();\n this.pollController = new AbortController();\n this.startPromise = this.runLoop().finally(() => {\n this.startPromise = undefined;\n this.pollController = undefined;\n });\n\n return this.startPromise;\n }\n\n /**\n * Request graceful shutdown. The poll loop is aborted immediately; any\n * in-flight handler that has not exceeded its timeout, along with the\n * subsequent result-report, is allowed to complete. Timed-out handlers\n * are abandoned (their {@link ChronosContext.signal} fires, but the SDK\n * does not wait for them). Every HTTP request is bounded by the `timeoutMs`\n * transport timeout and retry waits are skipped once stop is requested, so\n * the returned promise resolves in bounded time. Returns the same promise\n * as the active {@link Worker.start}, or a resolved promise if the worker\n * isn't running.\n */\n stop(): Promise<void> {\n this.pollController?.abort();\n return this.startPromise ?? Promise.resolve();\n }\n\n private get isStopped(): boolean {\n return this.pollController?.signal.aborted ?? true;\n }\n\n private async runLoop(): Promise<void> {\n while (!this.isStopped) {\n try {\n const job = await this.claimJob();\n if (job) {\n await this.processJob(job);\n }\n } catch (err) {\n if (this.isStopped) {\n break;\n }\n\n if (err instanceof ChronosApiError && isCredentialRejection(err)) {\n this.client.logger.error('Chronos worker stopped; API rejected credentials', {\n err: errorToLogValue(err),\n });\n throw err;\n }\n\n this.client.logger.error('Chronos poll loop error', { err: errorToLogValue(err) });\n await sleep(retryDelayFor(err, this.retryDelayMs), this.pollController?.signal);\n }\n }\n }\n\n private async claimJob(): Promise<ClaimedJob | null> {\n if (this.handlerNames.length === 0) {\n throw new ChronosError('Cannot claim jobs without registered handlers');\n }\n\n return this.client.request<ClaimedJob | null>(\n '/v1/workers/jobs/claim',\n {\n wait_time_seconds: this.pollWaitTimeSeconds,\n handlers: this.handlerNames,\n worker: {\n id: this.workerId,\n sdk_version: SDK_VERSION,\n runtime: this.runtime,\n uptime_ms: Math.round(performance.now() - this.startedAt),\n },\n },\n {\n signal: this.pollController?.signal,\n // The intentional long-poll wait must not count against the\n // transport bound.\n timeoutMs: Math.min(\n this.pollWaitTimeSeconds * 1_000 + this.client.timeoutMs,\n MAX_TIMEOUT_MS,\n ),\n },\n );\n }\n\n private async processJob(job: ClaimedJob): Promise<void> {\n const handler = this.handlers.get(job.handler);\n if (!handler) {\n return this.handleUnregisteredJob(job);\n }\n\n const controller = new AbortController();\n let outcome: HandlerOutcome;\n try {\n outcome = await this.runHandlerWithTimeout(\n handler,\n createContext(job, controller.signal),\n job.timeout * 1_000,\n controller,\n );\n } catch (err) {\n const message = errorMessage(err);\n const handlerErr = new ChronosHandlerError(message, { cause: err });\n this.client.logger.error('Chronos handler failed', {\n ...jobLogMeta(job),\n err: errorToLogValue(handlerErr),\n });\n await this.safeReportFailed(job, message);\n return;\n }\n\n if (outcome.timedOut) {\n this.client.logger.error('Chronos handler timed out', {\n ...jobLogMeta(job),\n timeout: job.timeout,\n });\n try {\n await this.reportTimeout(job.execution_id);\n } catch (err) {\n this.logResultReportFailure(err, job, 'timeout');\n }\n return;\n }\n\n let result: Record<string, unknown> | undefined;\n try {\n result = normalizeHandlerResult(outcome.result);\n } catch (err) {\n this.client.logger.error('Chronos handler returned invalid result', {\n ...jobLogMeta(job),\n err: errorToLogValue(err),\n });\n await this.safeReportFailed(job, errorMessage(err));\n return;\n }\n\n try {\n await this.reportCompleted(job.execution_id, result);\n } catch (err) {\n this.logResultReportFailure(err, job, 'completed');\n }\n }\n\n private runHandlerWithTimeout(\n handler: ChronosHandler<unknown>,\n ctx: ChronosContext<unknown>,\n timeoutMs: number,\n controller: AbortController,\n ): Promise<HandlerOutcome> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const handlerPromise = Promise.resolve(handler(ctx)).then(\n (result): HandlerOutcome => ({ timedOut: false, result }),\n );\n handlerPromise.catch(() => {});\n\n const timeoutPromise = new Promise<HandlerOutcome>((resolve) => {\n timer = setTimeout(() => {\n controller.abort();\n resolve({ timedOut: true });\n }, timeoutMs);\n });\n\n return Promise.race([handlerPromise, timeoutPromise]).finally(() => {\n clearTimeout(timer);\n });\n }\n\n private async handleUnregisteredJob(job: ClaimedJob): Promise<void> {\n const message = `Chronos SDK received job for unregistered handler \"${job.handler}\"`;\n this.client.logger.error(message, jobLogMeta(job));\n await this.safeReportFailed(job, message);\n }\n\n private async safeReportFailed(job: ClaimedJob, message: string): Promise<void> {\n try {\n await this.reportFailed(job.execution_id, message);\n } catch (err) {\n this.logResultReportFailure(err, job, 'failed');\n }\n }\n\n private async reportCompleted(\n executionId: string,\n result: Record<string, unknown> | undefined,\n ): Promise<void> {\n await this.reportResultWithRetry(executionId, {\n status: 'completed',\n ...(result === undefined ? {} : { result }),\n });\n }\n\n private async reportTimeout(executionId: string): Promise<void> {\n await this.reportResultWithRetry(executionId, { status: 'timeout' });\n }\n\n private async reportFailed(executionId: string, error: string): Promise<void> {\n await this.reportResultWithRetry(executionId, {\n status: 'failed',\n error: truncate(error, MAX_REPORTED_ERROR_LENGTH),\n });\n }\n\n private async reportResultWithRetry(\n executionId: string,\n body: Record<string, unknown>,\n ): Promise<void> {\n let lastErr: unknown;\n\n for (let attempt = 1; attempt <= RESULT_REPORT_MAX_ATTEMPTS; attempt++) {\n try {\n await this.client.request(\n `/v1/workers/executions/${encodeURIComponent(executionId)}/result`,\n body,\n );\n return;\n } catch (err) {\n const apiErr = err instanceof ChronosApiError ? err : undefined;\n\n if (apiErr?.status === 409) {\n this.client.logger.warn('Chronos result discarded; execution already terminal', {\n executionId,\n status: body.status,\n code: apiErr.code,\n });\n return;\n }\n\n if (apiErr && isTerminalReportError(apiErr.status)) {\n throw apiErr;\n }\n\n lastErr = err;\n if (attempt === RESULT_REPORT_MAX_ATTEMPTS) {\n break;\n }\n\n this.client.logger.warn('Chronos result report failed; retrying', {\n err: errorToLogValue(err),\n executionId,\n status: body.status,\n attempt,\n maxAttempts: RESULT_REPORT_MAX_ATTEMPTS,\n });\n // The signal skips the wait after stop(), never the retry itself:\n // the report is still allowed to complete.\n await sleep(retryDelayFor(err, this.retryDelayMs), this.pollController?.signal);\n }\n }\n\n throw lastErr;\n }\n\n private logResultReportFailure(err: unknown, job: ClaimedJob, status: ResultStatus): void {\n const isTerminal = err instanceof ChronosApiError && isTerminalReportError(err.status);\n this.client.logger.error(\n isTerminal\n ? 'Chronos result report rejected by API'\n : 'Chronos result report failed after retries',\n { ...jobLogMeta(job), err: errorToLogValue(err), status },\n );\n }\n}\n\nfunction createContext(job: ClaimedJob, signal: AbortSignal): ChronosContext<unknown> {\n return {\n jobId: job.job_id,\n executionId: job.execution_id,\n handler: job.handler,\n payload: job.payload,\n scheduledFor: new Date(job.scheduled_for),\n attempt: job.attempt,\n timeout: job.timeout,\n signal,\n schedule: job.schedule,\n };\n}\n\nfunction jobLogMeta(job: ClaimedJob): Record<string, unknown> {\n return {\n jobId: job.job_id,\n executionId: job.execution_id,\n handler: job.handler,\n };\n}\n\nfunction normalizeHandlerResult(result: ChronosHandlerResult): Record<string, unknown> | undefined {\n if (result === undefined) {\n return undefined;\n }\n\n if (!isPlainObject(result)) {\n throw new ChronosError('Chronos handler result must be a plain object or undefined');\n }\n\n try {\n JSON.stringify(result);\n } catch (err) {\n const reason = err instanceof Error ? err.message : 'value is not JSON-encodable';\n throw new ChronosError(`Chronos handler result is not JSON-encodable: ${reason}`);\n }\n\n return result;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction errorMessage(err: unknown): string {\n const message = err instanceof Error ? err.message : String(err);\n return message.trim() || DEFAULT_HANDLER_ERROR;\n}\n\nfunction errorToLogValue(err: unknown): unknown {\n if (!(err instanceof Error)) {\n return err;\n }\n\n const base = { name: err.name, message: err.message, stack: err.stack };\n\n if (err instanceof ChronosApiError) {\n return {\n ...base,\n status: err.status,\n code: err.code,\n requestId: err.requestId,\n ...(err.retryAfterSeconds !== undefined && { retryAfterSeconds: err.retryAfterSeconds }),\n ...(err.rateLimit !== undefined && { rateLimit: err.rateLimit }),\n };\n }\n if (err instanceof ChronosNetworkError || err instanceof ChronosHandlerError) {\n return { ...base, cause: errorToLogValue(err.cause) };\n }\n return base;\n}\n\nfunction truncate(value: string, maxLength: number): string {\n return value.length <= maxLength ? value : value.slice(0, maxLength);\n}\n\n// Floored at fallbackMs: a proxy's Retry-After: 0 would otherwise hot-loop\n// against a down origin.\nfunction retryDelayFor(err: unknown, fallbackMs: number): number {\n if (err instanceof ChronosApiError && err.retryAfterSeconds !== undefined) {\n return Math.max(Math.min(err.retryAfterSeconds * 1_000, MAX_RETRY_AFTER_MS), fallbackMs);\n }\n return fallbackMs;\n}\n\nfunction isCredentialRejection(err: ChronosApiError): boolean {\n return err.status === 401 && err.code === 'unauthorized';\n}\n\n// 409 is handled by the caller before reaching here; 408/429 are transient.\nconst NON_TERMINAL_4XX = new Set([408, 409, 429]);\n\n// 200 reaches here only via an explicit `{ success: false }` envelope from BaseClient.\nfunction isTerminalReportError(status: number): boolean {\n if (status === 200) {\n return true;\n }\n if (NON_TERMINAL_4XX.has(status)) {\n return false;\n }\n return status >= 400 && status < 500;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n const timeout: ReturnType<typeof setTimeout> = setTimeout(done, ms);\n\n function done() {\n clearTimeout(timeout);\n signal?.removeEventListener('abort', done);\n resolve();\n }\n\n signal?.addEventListener('abort', done, { once: true });\n });\n}\n","import { ChronosWebhookVerificationError } from './errors';\nimport type { WebhookOptions } from './types';\n\nexport const DEFAULT_TIMESTAMP_TOLERANCE_SECONDS = 300;\n\nconst SIGNATURE_PREFIX = 'sha256=';\nconst REQUIRED_HEADERS = [\n 'x-chronos-signature',\n 'x-chronos-timestamp',\n 'x-chronos-delivery-id',\n] as const;\n\n/**\n * Verifies webhook signatures on Chronos push deliveries.\n *\n * @example\n * ```ts\n * import { Webhook } from '@chronos.sh/sdk';\n *\n * const wh = new Webhook(process.env.CHRONOS_SIGNING_SECRET!);\n *\n * // In your request handler:\n * const payload = await wh.verify(rawBody, {\n * 'x-chronos-signature': req.headers['x-chronos-signature'],\n * 'x-chronos-timestamp': req.headers['x-chronos-timestamp'],\n * 'x-chronos-delivery-id': req.headers['x-chronos-delivery-id'],\n * });\n * ```\n */\nexport class Webhook {\n private readonly secrets: string[];\n private readonly toleranceSeconds: number;\n private keysPromise?: Promise<CryptoKey[]>;\n\n /**\n * @param secret - Signing secret or array of secrets (for key rotation).\n * @param options - Optional configuration.\n * @throws {ChronosWebhookVerificationError} If no valid secret is provided.\n */\n constructor(secret: string | string[], options?: WebhookOptions) {\n const secrets = Array.isArray(secret) ? secret : [secret];\n this.secrets = secrets\n .filter((s) => typeof s === 'string' && s.trim().length > 0)\n .map((s) => s.trim());\n\n if (this.secrets.length === 0) {\n throw new ChronosWebhookVerificationError(\n 'At least one non-empty signing secret is required',\n );\n }\n\n const tolerance = options?.toleranceSeconds ?? DEFAULT_TIMESTAMP_TOLERANCE_SECONDS;\n if (!Number.isFinite(tolerance) || tolerance < 0) {\n throw new ChronosWebhookVerificationError(\n 'toleranceSeconds must be a finite non-negative number',\n );\n }\n this.toleranceSeconds = tolerance;\n }\n\n /**\n * Verifies the webhook signature and returns the parsed request body.\n *\n * @param body - Raw request body as a string. Must be the exact bytes received — not re-serialized.\n * @param headers - Request headers. Keys are matched case-insensitively.\n * @returns The parsed JSON body on successful verification.\n * @throws {ChronosWebhookVerificationError} If any verification step fails.\n */\n async verify(\n body: string,\n headers: Record<string, string | undefined> | Headers,\n ): Promise<unknown> {\n const normalized = normalizeHeaders(headers);\n\n for (const name of REQUIRED_HEADERS) {\n const value = normalized[name];\n if (!value || typeof value !== 'string') {\n throw new ChronosWebhookVerificationError(`Missing required header: ${name}`);\n }\n }\n\n const signature = normalized['x-chronos-signature'] as string;\n const timestamp = normalized['x-chronos-timestamp'] as string;\n const deliveryId = normalized['x-chronos-delivery-id'] as string;\n\n if (!/^[0-9]+$/.test(timestamp)) {\n throw new ChronosWebhookVerificationError('Invalid timestamp');\n }\n\n const ts = Number(timestamp);\n if (ts <= 0) {\n throw new ChronosWebhookVerificationError('Invalid timestamp');\n }\n\n const now = Math.floor(Date.now() / 1000);\n const isStale = Math.abs(now - ts) > this.toleranceSeconds;\n if (this.toleranceSeconds > 0 && isStale) {\n throw new ChronosWebhookVerificationError('Timestamp outside tolerance');\n }\n\n if (!signature.startsWith(SIGNATURE_PREFIX)) {\n throw new ChronosWebhookVerificationError(\n `Invalid signature format: expected ${SIGNATURE_PREFIX}<hex>`,\n );\n }\n\n const expectedHex = signature.slice(SIGNATURE_PREFIX.length);\n if (expectedHex.length === 0) {\n throw new ChronosWebhookVerificationError(\n 'Invalid signature: expected 32-byte SHA-256 digest',\n );\n }\n\n let expectedBytes: ArrayBuffer;\n try {\n expectedBytes = hexDecode(expectedHex);\n } catch {\n throw new ChronosWebhookVerificationError('Invalid signature: malformed hex');\n }\n\n if (expectedBytes.byteLength !== 32) {\n throw new ChronosWebhookVerificationError(\n 'Invalid signature: expected 32-byte SHA-256 digest',\n );\n }\n\n const signedPayload = `${deliveryId}.${timestamp}.${body}`;\n const data = new TextEncoder().encode(signedPayload);\n\n try {\n const keys = await this.ensureKeys();\n for (const key of keys) {\n const valid = await globalThis.crypto.subtle.verify('HMAC', key, expectedBytes, data);\n if (valid) {\n try {\n return JSON.parse(body);\n } catch {\n throw new ChronosWebhookVerificationError('Verified payload is not valid JSON');\n }\n }\n }\n } catch (err) {\n if (err instanceof ChronosWebhookVerificationError) {\n throw err;\n }\n throw new ChronosWebhookVerificationError('Signature verification failed');\n }\n\n throw new ChronosWebhookVerificationError('Signature verification failed');\n }\n\n private ensureKeys(): Promise<CryptoKey[]> {\n if (!this.keysPromise) {\n const encoder = new TextEncoder();\n this.keysPromise = Promise.all(\n this.secrets.map((s) =>\n globalThis.crypto.subtle.importKey(\n 'raw',\n encoder.encode(s),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['verify'],\n ),\n ),\n );\n }\n return this.keysPromise;\n }\n}\n\nfunction normalizeHeaders(\n headers: Record<string, string | undefined> | Headers,\n): Record<string, string | undefined> {\n const result: Record<string, string | undefined> = {};\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n result[key.toLowerCase()] = value;\n });\n } else {\n for (const key of Object.keys(headers)) {\n result[key.toLowerCase()] = headers[key];\n }\n }\n return result;\n}\n\nfunction hexDecode(hex: string): ArrayBuffer {\n if (hex.length % 2 !== 0 || !/^[0-9a-f]+$/i.test(hex)) {\n throw new Error('Invalid hex string');\n }\n const length = hex.length / 2;\n const buffer = new ArrayBuffer(length);\n const view = new DataView(buffer);\n for (let i = 0; i < length; i++) {\n view.setUint8(i, Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16));\n }\n return buffer;\n}\n","import { BaseClient, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS } from './client';\nimport type { ChronosOptions } from './types';\nimport { DEFAULT_POLL_WAIT_TIME_SECONDS, Worker } from './worker';\n\n/**\n * The Chronos SDK client. Composes worker and (future) REST resource\n * subclients from a single instance.\n *\n * @example\n * ```ts\n * import { Chronos } from '@chronos.sh/sdk';\n *\n * const chronos = new Chronos({ apiKey: process.env.CHRONOS_API_KEY! });\n *\n * chronos.worker.handle<{ to: string }>('send-email', async (ctx) => {\n * await sendEmail(ctx.payload.to);\n * return { sent: true };\n * });\n *\n * await chronos.worker.start();\n * ```\n */\nexport class Chronos {\n /** Long-poll worker for executing pull-mode jobs. */\n readonly worker: Worker;\n\n /**\n * @param options - Client configuration. Only `apiKey` is required.\n * @throws {ChronosConfigError} If `apiKey` is missing or any option fails validation.\n */\n constructor(options: ChronosOptions) {\n const client = new BaseClient(options);\n this.worker = new Worker(client, options);\n }\n}\n\nexport {\n ChronosApiError,\n type ChronosApiErrorOptions,\n ChronosConfigError,\n ChronosError,\n ChronosHandlerError,\n ChronosNetworkError,\n ChronosRateLimitError,\n ChronosTimeoutError,\n ChronosWebhookVerificationError,\n type RateLimitInfo,\n} from './errors';\nexport { SDK_VERSION } from './internal/version';\nexport type {\n ChronosContext,\n ChronosHandler,\n ChronosHandlerResult,\n ChronosLogger,\n ChronosOptions,\n ChronosSchedule,\n FetchLike,\n WebhookOptions,\n} from './types';\nexport { DEFAULT_TIMESTAMP_TOLERANCE_SECONDS, Webhook } from './webhook';\nexport { DEFAULT_BASE_URL, DEFAULT_POLL_WAIT_TIME_SECONDS, DEFAULT_TIMEOUT_MS };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/errors.ts","../src/internal/logger.ts","../src/internal/validate.ts","../src/client.ts","../src/internal/id.ts","../src/internal/runtime.ts","../src/internal/version.ts","../src/worker.ts","../src/webhook.ts","../src/index.ts"],"sourcesContent":["/**\n * Base class for all errors thrown by the Chronos SDK. Catch this in a\n * single `catch` to handle any SDK failure generically; use the subclasses\n * to branch on cause.\n *\n * @example\n * ```ts\n * import { Chronos, ChronosError } from '@chronos.sh/sdk';\n *\n * const chronos = new Chronos({ apiKey: 'chrns_...' });\n * try {\n * await chronos.worker.start();\n * } catch (err) {\n * if (err instanceof ChronosError) {\n * console.error('Chronos failed:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosError extends Error {\n /** Original error/value that caused this SDK error, when one is available. */\n declare readonly cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'ChronosError';\n\n if (options && !('cause' in this)) {\n Object.defineProperty(this, 'cause', {\n value: options.cause,\n configurable: true,\n writable: true,\n });\n }\n }\n}\n\n/**\n * Thrown when SDK options fail validation at `new Chronos({ ... })`. Covers\n * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, `retryDelayMs`, `timeoutMs`, and\n * `workerId`.\n *\n * @example\n * ```ts\n * import { Chronos, ChronosConfigError } from '@chronos.sh/sdk';\n *\n * try {\n * const chronos = new Chronos({ apiKey: '' });\n * } catch (err) {\n * if (err instanceof ChronosConfigError) {\n * console.error('Invalid Chronos config:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosConfigError extends ChronosError {\n constructor(message: string) {\n super(message);\n this.name = 'ChronosConfigError';\n }\n}\n\n/** Rate-limit budget from `X-RateLimit-*` response headers. Present on non-429 responses. */\nexport type RateLimitInfo = {\n /** Maximum requests allowed per window. */\n limit: number;\n /** Requests remaining in the current window. */\n remaining: number;\n /** Seconds until the current window resets. */\n reset: number;\n};\n\n/** Options for constructing a {@link ChronosApiError}. */\nexport type ChronosApiErrorOptions = {\n /** HTTP status code returned by the Chronos API. */\n status: number;\n /** Application-level error code from the response envelope, when present. */\n code?: string;\n /** Full parsed response payload (envelope + data, or whatever the server returned). */\n body?: unknown;\n /** Value of the `X-Request-Id` response header, when present. Pair with server logs. */\n requestId?: string;\n /** Seconds to wait before retrying, from the `Retry-After` response header. Present on 429 and 5xx responses that include the header. */\n retryAfterSeconds?: number;\n /** Rate-limit budget from `X-RateLimit-*` headers. Present on non-429 responses. */\n rateLimit?: RateLimitInfo;\n};\n\n/**\n * Thrown when the Chronos API responds with a non-2xx status or a\n * `success: false` envelope. Carries HTTP `status`, the application\n * `code`, parsed `body`, the API's `X-Request-Id`, and — when the\n * relevant headers are present — rate-limit metadata\n * (`retryAfterSeconds` on 429 and 5xx, `rateLimit` on non-429 errors).\n *\n * `instanceof ChronosApiError` means the server replied;\n * network/transport failures throw {@link ChronosNetworkError} instead.\n * For 429 specifically, see {@link ChronosRateLimitError}.\n *\n * @example\n * ```ts\n * import { ChronosApiError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosApiError) {\n * if (err.status === 401) return refreshAuth();\n * console.error('API error', { status: err.status, requestId: err.requestId });\n * }\n * }\n * ```\n */\nexport class ChronosApiError extends ChronosError {\n /** HTTP status code returned by the Chronos API. */\n readonly status: number;\n /** Application-level error code from the response envelope, when present. */\n readonly code?: string;\n /** Full parsed response payload (envelope + data, or whatever the server returned). */\n readonly body?: unknown;\n /** Value of the `X-Request-Id` response header, when present. */\n readonly requestId?: string;\n /** Seconds to wait before retrying, from the `Retry-After` response header. Present on 429 and 5xx responses that include the header. */\n readonly retryAfterSeconds?: number;\n /** Rate-limit budget from `X-RateLimit-*` headers. Present on non-429 responses. */\n readonly rateLimit?: RateLimitInfo;\n\n constructor(message: string, options: ChronosApiErrorOptions) {\n super(message);\n this.name = 'ChronosApiError';\n this.status = options.status;\n this.code = options.code;\n this.body = options.body;\n this.requestId = options.requestId;\n this.retryAfterSeconds = options.retryAfterSeconds;\n this.rateLimit = options.rateLimit;\n }\n}\n\n/**\n * Thrown when the Chronos API responds with `429 Too Many Requests`.\n * Subclass of {@link ChronosApiError} — `instanceof ChronosRateLimitError`\n * narrows to a rate-limited response. `retryAfterSeconds` is set when the\n * response includes a `Retry-After` header; otherwise it is `undefined`.\n *\n * @example\n * ```ts\n * import { ChronosRateLimitError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosRateLimitError && err.retryAfterSeconds) {\n * console.warn(`Rate limited — retry after ${err.retryAfterSeconds}s`);\n * }\n * }\n * ```\n */\nexport class ChronosRateLimitError extends ChronosApiError {\n constructor(message: string, options: ChronosApiErrorOptions) {\n super(message, options);\n this.name = 'ChronosRateLimitError';\n }\n}\n\n/**\n * Thrown when a request fails at the transport layer — DNS failure, TCP\n * reset, connection refused, or a connection dropped mid-response. The\n * original error is available on `.cause`.\n *\n * Caller-supplied abort signals propagate unwrapped — `instanceof\n * ChronosNetworkError` always means a transport failure, not a graceful\n * shutdown. The SDK's own transport timeout throws the\n * {@link ChronosTimeoutError} subclass.\n *\n * @example\n * ```ts\n * import { ChronosNetworkError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosNetworkError) {\n * console.warn('Transport blip', { cause: err.cause });\n * }\n * }\n * ```\n */\nexport class ChronosNetworkError extends ChronosError {\n /** Original error/value rejected by the underlying `fetch`. */\n declare readonly cause: unknown;\n\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosNetworkError';\n }\n}\n\n/**\n * Thrown when an HTTP request exceeds the configured `timeoutMs` before the\n * response completes. Subclass of {@link ChronosNetworkError}, so generic\n * transport-failure handling catches it; the underlying rejection is on\n * `.cause`.\n *\n * @example\n * ```ts\n * import { ChronosTimeoutError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosTimeoutError) {\n * console.warn('Chronos request timed out', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosTimeoutError extends ChronosNetworkError {\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosTimeoutError';\n }\n}\n\n/**\n * Wraps an exception thrown by a user-supplied {@link ChronosHandler}. The\n * original error is on `.cause`; `.message` is copied from the original so\n * the SDK reports it to the API as the failure reason.\n *\n * @example\n * ```ts\n * import { ChronosHandlerError } from '@chronos.sh/sdk';\n *\n * if (err instanceof ChronosHandlerError) {\n * console.error('Handler threw', err.cause);\n * }\n * ```\n */\nexport class ChronosHandlerError extends ChronosError {\n /** Original error/value thrown by the user-supplied handler. */\n declare readonly cause: unknown;\n\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosHandlerError';\n }\n}\n\n/**\n * Thrown by {@link Webhook.verify} when signature verification fails.\n * Covers missing or malformed headers, expired timestamps, and signature\n * mismatches.\n *\n * @example\n * ```ts\n * import { Webhook, ChronosWebhookVerificationError } from '@chronos.sh/sdk';\n *\n * const wh = new Webhook(process.env.CHRONOS_SIGNING_SECRET!);\n * try {\n * const payload = await wh.verify(rawBody, headers);\n * } catch (err) {\n * if (err instanceof ChronosWebhookVerificationError) {\n * console.error('Webhook verification failed:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosWebhookVerificationError extends ChronosError {\n constructor(message: string) {\n super(message);\n this.name = 'ChronosWebhookVerificationError';\n }\n}\n","import type { ChronosLogger } from '../types';\n\nexport const defaultLogger: ChronosLogger = {\n debug: (message, meta) => logToConsole(console.debug, message, meta),\n info: (message, meta) => logToConsole(console.info, message, meta),\n warn: (message, meta) => logToConsole(console.warn, message, meta),\n error: (message, meta) => logToConsole(console.error, message, meta),\n};\n\nfunction logToConsole(\n method: (message?: unknown, ...optionalParams: unknown[]) => void,\n message: string,\n meta?: Record<string, unknown>,\n): void {\n if (meta) {\n method(message, meta);\n } else {\n method(message);\n }\n}\n","import { ChronosConfigError, ChronosError } from '../errors';\n\nexport const MAX_HANDLER_NAME_LENGTH = 255;\nexport const MAX_POLL_WAIT_TIME_SECONDS = 20;\n\nexport function validateApiKey(apiKey: string | undefined): string {\n const trimmed = apiKey?.trim();\n if (!trimmed) {\n throw new ChronosConfigError('Chronos apiKey is required');\n }\n return trimmed;\n}\n\nexport function validatePollWaitTime(seconds: number): void {\n if (!Number.isInteger(seconds) || seconds < 0 || seconds > MAX_POLL_WAIT_TIME_SECONDS) {\n throw new ChronosConfigError(\n `pollWaitTimeSeconds must be an integer between 0 and ${MAX_POLL_WAIT_TIME_SECONDS}`,\n );\n }\n}\n\nexport function validateRetryDelayMs(ms: number): void {\n if (!Number.isFinite(ms) || ms < 0) {\n throw new ChronosConfigError('retryDelayMs must be a non-negative number');\n }\n}\n\n// setTimeout silently clamps delays above 2^31-1 to 1ms.\nexport const MAX_TIMEOUT_MS = 2_147_483_647;\n\nexport function validateTimeoutMs(ms: number): void {\n if (!Number.isInteger(ms) || ms <= 0 || ms > MAX_TIMEOUT_MS) {\n throw new ChronosConfigError(\n `timeoutMs must be a positive integer no greater than ${MAX_TIMEOUT_MS}`,\n );\n }\n}\n\nexport function validateWorkerId(id: string): string {\n const trimmed = id.trim();\n if (trimmed.length === 0 || trimmed.length > 255) {\n throw new ChronosConfigError('workerId must be 1-255 characters');\n }\n return trimmed;\n}\n\nexport function normalizeHandlerName(name: string): string {\n const normalized = name.trim();\n\n if (!normalized) {\n throw new ChronosError('Handler name is required');\n }\n\n if (normalized.length > MAX_HANDLER_NAME_LENGTH) {\n throw new ChronosError(`Handler name must be ${MAX_HANDLER_NAME_LENGTH} characters or fewer`);\n }\n\n return normalized;\n}\n","import {\n ChronosApiError,\n ChronosConfigError,\n ChronosError,\n ChronosNetworkError,\n ChronosRateLimitError,\n ChronosTimeoutError,\n type RateLimitInfo,\n} from './errors';\nimport { defaultLogger } from './internal/logger';\nimport { validateApiKey, validateTimeoutMs } from './internal/validate';\nimport type { ChronosLogger, ChronosOptions, FetchLike } from './types';\n\n/** Default Chronos API base URL. */\nexport const DEFAULT_BASE_URL = 'https://api.chronos.sh';\n\n/** Default per-request transport timeout in milliseconds. */\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\ntype ApiResponse<T> = {\n success: boolean;\n message?: string;\n code?: string;\n data: T;\n};\n\ntype RequestOptions = {\n signal?: AbortSignal;\n timeoutMs?: number;\n};\n\nexport class BaseClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly fetch: FetchLike;\n readonly logger: ChronosLogger;\n readonly timeoutMs: number;\n private readonly headers: Record<string, string>;\n\n constructor(options: ChronosOptions) {\n this.apiKey = validateApiKey(options.apiKey);\n this.baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL);\n this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.logger = options.logger ?? defaultLogger;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateTimeoutMs(this.timeoutMs);\n this.headers = {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.apiKey}`,\n };\n }\n\n async request<T>(\n path: string,\n body: Record<string, unknown>,\n options: RequestOptions = {},\n ): Promise<T> {\n const { signal } = options;\n const timeoutMs = options.timeoutMs ?? this.timeoutMs;\n\n // Not AbortSignal.any: Node pins each composite onto long-lived source\n // signals (like the poll signal) forever, leaking per claim.\n const controller = new AbortController();\n let timedOut = false;\n const timer = setTimeout(() => {\n if (controller.signal.aborted) {\n return;\n }\n timedOut = true;\n controller.abort(\n new DOMException(`Chronos API request timed out after ${timeoutMs}ms`, 'TimeoutError'),\n );\n }, timeoutMs);\n const onCallerAbort = () => controller.abort(signal?.reason);\n if (signal?.aborted) {\n onCallerAbort();\n } else {\n signal?.addEventListener('abort', onCallerAbort, { once: true });\n }\n\n try {\n let response: Response;\n try {\n response = await this.fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n if (signal?.aborted && !timedOut) {\n throw err;\n }\n if (timedOut) {\n throw timeoutError(timeoutMs, err);\n }\n const message = err instanceof Error ? err.message : String(err);\n throw new ChronosNetworkError(`Chronos API request failed: ${message}`, { cause: err });\n }\n\n // A half-open connection can stall after headers arrive, so the\n // timeout must cover the body read too.\n let payload: ApiResponse<T> | null;\n try {\n payload = (await response.json()) as ApiResponse<T>;\n } catch (err) {\n // Aborted-state check, not reason identity: some runtimes wrap the\n // abort reason during body reads.\n if (signal?.aborted && !timedOut) {\n throw err;\n }\n if (timedOut) {\n throw timeoutError(timeoutMs, err);\n }\n if (err instanceof SyntaxError) {\n payload = null;\n } else {\n const message = err instanceof Error ? err.message : String(err);\n throw new ChronosNetworkError(`Chronos API response failed: ${message}`, { cause: err });\n }\n }\n\n const envelope = isEnvelope(payload) ? (payload as ApiResponse<T>) : undefined;\n\n if (!response.ok || (envelope && !envelope.success)) {\n const is429 = response.status === 429;\n const retryAfterApplies = is429 || response.status >= 500;\n const ErrorClass = is429 ? ChronosRateLimitError : ChronosApiError;\n throw new ErrorClass(apiErrorMessage(response, envelope), {\n status: response.status,\n code: typeof envelope?.code === 'string' ? envelope.code : undefined,\n body: payload,\n requestId: response.headers.get('x-request-id') ?? undefined,\n retryAfterSeconds: retryAfterApplies\n ? parseIntHeader(response.headers, 'retry-after')\n : undefined,\n rateLimit: is429 ? undefined : parseRateLimitHeaders(response.headers),\n });\n }\n\n if (!envelope) {\n // Plain ChronosError, not ChronosApiError — a malformed 200 body is\n // an infrastructure anomaly that should be retried, not a definitive\n // API rejection.\n throw new ChronosError('Chronos API returned an invalid response');\n }\n\n return envelope.data;\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener('abort', onCallerAbort);\n }\n }\n}\n\nfunction timeoutError(timeoutMs: number, cause: unknown): ChronosTimeoutError {\n return new ChronosTimeoutError(`Chronos API request timed out after ${timeoutMs}ms`, { cause });\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n const normalized = baseUrl.trim().replace(/\\/+$/, '');\n if (!normalized) {\n throw new ChronosConfigError('Chronos baseUrl is required');\n }\n return normalized;\n}\n\nfunction apiErrorMessage(\n response: Response,\n envelope: Record<string, unknown> | undefined,\n): string {\n if (typeof envelope?.message === 'string' && envelope.message.trim()) {\n return envelope.message;\n }\n\n return response.ok\n ? 'Chronos API returned an invalid response'\n : `Chronos API request failed with status ${response.status}`;\n}\n\nfunction parseIntHeader(headers: Headers, name: string): number | undefined {\n const raw = headers.get(name);\n if (raw === null || !/^\\d+$/.test(raw)) {\n return undefined;\n }\n return Number.parseInt(raw, 10);\n}\n\nfunction parseRateLimitHeaders(headers: Headers): RateLimitInfo | undefined {\n const limit = parseIntHeader(headers, 'x-ratelimit-limit');\n const remaining = parseIntHeader(headers, 'x-ratelimit-remaining');\n const reset = parseIntHeader(headers, 'x-ratelimit-reset');\n\n if (limit === undefined || remaining === undefined || reset === undefined) {\n return undefined;\n }\n return { limit, remaining, reset };\n}\n\n// Malformed bodies (arrays, primitives, missing `success`) are routed to the\n// invalid-response path, not classified as API errors.\nfunction isEnvelope(value: unknown): value is Record<string, unknown> & { success: boolean } {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n return typeof (value as Record<string, unknown>).success === 'boolean';\n}\n","export function generateWorkerId(): string {\n const bytes = crypto.getRandomValues(new Uint8Array(8));\n let hex = '';\n for (const b of bytes) {\n hex += b.toString(16).padStart(2, '0');\n }\n return `w_${hex}`;\n}\n","export function detectRuntime(): string {\n const g = globalThis as unknown as Record<string, Record<string, unknown> | undefined>;\n\n if (g.Bun != null) {\n return `bun/${(g.Bun.version as string | undefined) ?? 'unknown'}`;\n }\n\n if (g.Deno != null) {\n const version = g.Deno.version as Record<string, string> | undefined;\n return `deno/${version?.deno ?? 'unknown'}`;\n }\n\n if (typeof process !== 'undefined' && process.versions?.node) {\n return `node/${process.versions.node}`;\n }\n\n return 'unknown';\n}\n","declare const __SDK_VERSION__: string;\n\nexport const SDK_VERSION: string = __SDK_VERSION__;\n","import type { BaseClient } from './client';\nimport { ChronosApiError, ChronosError, ChronosHandlerError, ChronosNetworkError } from './errors';\nimport { generateWorkerId } from './internal/id';\nimport { detectRuntime } from './internal/runtime';\nimport {\n MAX_TIMEOUT_MS,\n normalizeHandlerName,\n validatePollWaitTime,\n validateRetryDelayMs,\n validateWorkerId,\n} from './internal/validate';\nimport { SDK_VERSION } from './internal/version';\nimport type {\n ChronosContext,\n ChronosHandler,\n ChronosHandlerResult,\n ChronosOptions,\n ChronosSchedule,\n} from './types';\n\n/** Default worker long-poll wait time in seconds. Equal to the API maximum. */\nexport const DEFAULT_POLL_WAIT_TIME_SECONDS = 20;\nconst DEFAULT_RETRY_DELAY_MS = 1_000;\n// Retry-After on 5xx often comes from proxies/CDNs with browser-oriented\n// values (e.g. 3600); uncapped it would park the worker for hours.\nconst MAX_RETRY_AFTER_MS = 60_000;\nconst RESULT_REPORT_MAX_ATTEMPTS = 3;\nconst MAX_REPORTED_ERROR_LENGTH = 4_096;\nconst DEFAULT_HANDLER_ERROR = 'Chronos handler failed';\n\ntype ResultStatus = 'completed' | 'failed' | 'timeout';\n\ntype HandlerOutcome = { timedOut: false; result: ChronosHandlerResult } | { timedOut: true };\n\ntype ClaimedJob = {\n job_id: string;\n execution_id: string;\n handler: string;\n scheduled_for: string;\n attempt: number;\n timeout: number;\n payload: unknown;\n schedule: ChronosSchedule | null;\n};\n\n/**\n * Long-poll worker. Claims jobs from the Chronos API, dispatches them to\n * registered handlers, and reports results.\n *\n * Construct via `new Chronos({ apiKey }).worker` rather than directly.\n */\nexport class Worker {\n private readonly client: BaseClient;\n private readonly pollWaitTimeSeconds: number;\n private readonly retryDelayMs: number;\n private readonly workerId: string;\n private readonly runtime: string;\n private readonly handlers = new Map<string, ChronosHandler<unknown>>();\n private handlerNames: string[] = [];\n private startPromise?: Promise<void>;\n private pollController?: AbortController;\n private startedAt = 0;\n\n constructor(client: BaseClient, options: ChronosOptions) {\n this.client = client;\n this.pollWaitTimeSeconds = options.pollWaitTimeSeconds ?? DEFAULT_POLL_WAIT_TIME_SECONDS;\n this.retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n this.workerId =\n options.workerId !== undefined ? validateWorkerId(options.workerId) : generateWorkerId();\n this.runtime = detectRuntime();\n\n validatePollWaitTime(this.pollWaitTimeSeconds);\n validateRetryDelayMs(this.retryDelayMs);\n }\n\n /**\n * Register a handler for a named job type. Invoked when the Chronos API\n * claims a job whose `handler` field matches `name`. Names are trimmed and\n * must be 1–255 characters.\n *\n * @param name - Handler name. Must match the schedule's `handler` on the API side.\n * @param handler - Async function invoked with the job context. Return a\n * plain object to record a result, or `undefined` for none.\n * @returns The Worker, for chaining.\n * @throws {ChronosError} If the name is invalid, already registered, or `handler` is not a function.\n *\n * @example\n * ```ts\n * chronos.worker\n * .handle('send-email', async (ctx) => ({ sent: true }))\n * .handle('cleanup', async () => undefined);\n * ```\n */\n handle<TPayload = unknown>(name: string, handler: ChronosHandler<TPayload>): this {\n const normalizedName = normalizeHandlerName(name);\n\n if (this.handlers.has(normalizedName)) {\n throw new ChronosError(`Handler \"${normalizedName}\" is already registered`);\n }\n\n if (typeof handler !== 'function') {\n throw new ChronosError(`Handler \"${normalizedName}\" must be a function`);\n }\n\n this.handlers.set(normalizedName, handler as ChronosHandler<unknown>);\n this.handlerNames.push(normalizedName);\n return this;\n }\n\n /**\n * Begin long-polling for jobs. The returned promise resolves when\n * {@link Worker.stop} is called and any in-flight job completes, and\n * rejects if the API rejects the worker's credentials (a 401 with the\n * `unauthorized` error code) — a misconfigured key is not recoverable by\n * retrying.\n *\n * @throws {ChronosError} Synchronously, if no handlers are registered or the worker is already running.\n * @throws {ChronosApiError} Via the returned promise, when the API rejects the worker's credentials.\n */\n start(): Promise<void> {\n if (this.startPromise) {\n throw new ChronosError('Chronos worker is already started');\n }\n\n if (this.handlers.size === 0) {\n throw new ChronosError('Register at least one handler before starting Chronos');\n }\n\n this.startedAt = performance.now();\n this.pollController = new AbortController();\n this.startPromise = this.runLoop().finally(() => {\n this.startPromise = undefined;\n this.pollController = undefined;\n });\n\n return this.startPromise;\n }\n\n /**\n * Request graceful shutdown: abort the poll, let an in-flight handler\n * finish (up to its timeout) and report its result, then resolve. Bounded\n * by that timeout plus `timeoutMs` per report attempt. Never rejects; a\n * credential rejection surfaces on {@link Worker.start} instead.\n */\n stop(): Promise<void> {\n this.pollController?.abort();\n return this.startPromise ?? Promise.resolve();\n }\n\n private get isStopped(): boolean {\n return this.pollController?.signal.aborted ?? true;\n }\n\n private async runLoop(): Promise<void> {\n while (!this.isStopped) {\n try {\n const job = await this.claimJob();\n if (job) {\n await this.processJob(job);\n }\n } catch (err) {\n if (this.isStopped) {\n break;\n }\n\n if (err instanceof ChronosApiError && isCredentialRejection(err)) {\n this.client.logger.error('Chronos worker stopped; API rejected credentials', {\n err: errorToLogValue(err),\n });\n throw err;\n }\n\n this.client.logger.error('Chronos poll loop error', { err: errorToLogValue(err) });\n await sleep(retryDelayFor(err, this.retryDelayMs), this.pollController?.signal);\n }\n }\n }\n\n private async claimJob(): Promise<ClaimedJob | null> {\n if (this.handlerNames.length === 0) {\n throw new ChronosError('Cannot claim jobs without registered handlers');\n }\n\n return this.client.request<ClaimedJob | null>(\n '/v1/workers/jobs/claim',\n {\n wait_time_seconds: this.pollWaitTimeSeconds,\n handlers: this.handlerNames,\n worker: {\n id: this.workerId,\n sdk_version: SDK_VERSION,\n runtime: this.runtime,\n uptime_ms: Math.round(performance.now() - this.startedAt),\n },\n },\n {\n signal: this.pollController?.signal,\n // The intentional long-poll wait must not count against the\n // transport bound.\n timeoutMs: Math.min(\n this.pollWaitTimeSeconds * 1_000 + this.client.timeoutMs,\n MAX_TIMEOUT_MS,\n ),\n },\n );\n }\n\n private async processJob(job: ClaimedJob): Promise<void> {\n const handler = this.handlers.get(job.handler);\n if (!handler) {\n return this.handleUnregisteredJob(job);\n }\n\n const controller = new AbortController();\n let outcome: HandlerOutcome;\n try {\n outcome = await this.runHandlerWithTimeout(\n handler,\n createContext(job, controller.signal),\n job.timeout * 1_000,\n controller,\n );\n } catch (err) {\n const message = errorMessage(err);\n const handlerErr = new ChronosHandlerError(message, { cause: err });\n this.client.logger.error('Chronos handler failed', {\n ...jobLogMeta(job),\n err: errorToLogValue(handlerErr),\n });\n await this.safeReportFailed(job, message);\n return;\n }\n\n if (outcome.timedOut) {\n this.client.logger.error('Chronos handler timed out', {\n ...jobLogMeta(job),\n timeout: job.timeout,\n });\n try {\n await this.reportTimeout(job.execution_id);\n } catch (err) {\n this.logResultReportFailure(err, job, 'timeout');\n }\n return;\n }\n\n let result: Record<string, unknown> | undefined;\n try {\n result = normalizeHandlerResult(outcome.result);\n } catch (err) {\n this.client.logger.error('Chronos handler returned invalid result', {\n ...jobLogMeta(job),\n err: errorToLogValue(err),\n });\n await this.safeReportFailed(job, errorMessage(err));\n return;\n }\n\n try {\n await this.reportCompleted(job.execution_id, result);\n } catch (err) {\n this.logResultReportFailure(err, job, 'completed');\n }\n }\n\n private runHandlerWithTimeout(\n handler: ChronosHandler<unknown>,\n ctx: ChronosContext<unknown>,\n timeoutMs: number,\n controller: AbortController,\n ): Promise<HandlerOutcome> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const handlerPromise = Promise.resolve(handler(ctx)).then(\n (result): HandlerOutcome => ({ timedOut: false, result }),\n );\n handlerPromise.catch(() => {});\n\n const timeoutPromise = new Promise<HandlerOutcome>((resolve) => {\n timer = setTimeout(() => {\n controller.abort();\n resolve({ timedOut: true });\n }, timeoutMs);\n });\n\n return Promise.race([handlerPromise, timeoutPromise]).finally(() => {\n clearTimeout(timer);\n });\n }\n\n private async handleUnregisteredJob(job: ClaimedJob): Promise<void> {\n const message = `Chronos SDK received job for unregistered handler \"${job.handler}\"`;\n this.client.logger.error(message, jobLogMeta(job));\n await this.safeReportFailed(job, message);\n }\n\n private async safeReportFailed(job: ClaimedJob, message: string): Promise<void> {\n try {\n await this.reportFailed(job.execution_id, message);\n } catch (err) {\n this.logResultReportFailure(err, job, 'failed');\n }\n }\n\n private async reportCompleted(\n executionId: string,\n result: Record<string, unknown> | undefined,\n ): Promise<void> {\n await this.reportResultWithRetry(executionId, {\n status: 'completed',\n ...(result === undefined ? {} : { result }),\n });\n }\n\n private async reportTimeout(executionId: string): Promise<void> {\n await this.reportResultWithRetry(executionId, { status: 'timeout' });\n }\n\n private async reportFailed(executionId: string, error: string): Promise<void> {\n await this.reportResultWithRetry(executionId, {\n status: 'failed',\n error: truncate(error, MAX_REPORTED_ERROR_LENGTH),\n });\n }\n\n private async reportResultWithRetry(\n executionId: string,\n body: Record<string, unknown>,\n ): Promise<void> {\n let lastErr: unknown;\n\n for (let attempt = 1; attempt <= RESULT_REPORT_MAX_ATTEMPTS; attempt++) {\n try {\n await this.client.request(\n `/v1/workers/executions/${encodeURIComponent(executionId)}/result`,\n body,\n );\n return;\n } catch (err) {\n const apiErr = err instanceof ChronosApiError ? err : undefined;\n\n if (apiErr?.status === 409) {\n this.client.logger.warn('Chronos result discarded; execution already terminal', {\n executionId,\n status: body.status,\n code: apiErr.code,\n });\n return;\n }\n\n if (apiErr && isTerminalReportError(apiErr.status)) {\n throw apiErr;\n }\n\n lastErr = err;\n if (attempt === RESULT_REPORT_MAX_ATTEMPTS) {\n break;\n }\n\n this.client.logger.warn('Chronos result report failed; retrying', {\n err: errorToLogValue(err),\n executionId,\n status: body.status,\n attempt,\n maxAttempts: RESULT_REPORT_MAX_ATTEMPTS,\n });\n // The signal skips the wait after stop(), never the retry itself:\n // the report is still allowed to complete.\n await sleep(retryDelayFor(err, this.retryDelayMs), this.pollController?.signal);\n }\n }\n\n throw lastErr;\n }\n\n private logResultReportFailure(err: unknown, job: ClaimedJob, status: ResultStatus): void {\n const isTerminal = err instanceof ChronosApiError && isTerminalReportError(err.status);\n this.client.logger.error(\n isTerminal\n ? 'Chronos result report rejected by API'\n : 'Chronos result report failed after retries',\n { ...jobLogMeta(job), err: errorToLogValue(err), status },\n );\n }\n}\n\nfunction createContext(job: ClaimedJob, signal: AbortSignal): ChronosContext<unknown> {\n return {\n jobId: job.job_id,\n executionId: job.execution_id,\n handler: job.handler,\n payload: job.payload,\n scheduledFor: new Date(job.scheduled_for),\n attempt: job.attempt,\n timeout: job.timeout,\n signal,\n schedule: job.schedule,\n };\n}\n\nfunction jobLogMeta(job: ClaimedJob): Record<string, unknown> {\n return {\n jobId: job.job_id,\n executionId: job.execution_id,\n handler: job.handler,\n };\n}\n\nfunction normalizeHandlerResult(result: ChronosHandlerResult): Record<string, unknown> | undefined {\n if (result === undefined) {\n return undefined;\n }\n\n if (!isPlainObject(result)) {\n throw new ChronosError('Chronos handler result must be a plain object or undefined');\n }\n\n try {\n JSON.stringify(result);\n } catch (err) {\n const reason = err instanceof Error ? err.message : 'value is not JSON-encodable';\n throw new ChronosError(`Chronos handler result is not JSON-encodable: ${reason}`);\n }\n\n return result;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction errorMessage(err: unknown): string {\n const message = err instanceof Error ? err.message : String(err);\n return message.trim() || DEFAULT_HANDLER_ERROR;\n}\n\nfunction errorToLogValue(err: unknown): unknown {\n if (!(err instanceof Error)) {\n return err;\n }\n\n const base = { name: err.name, message: err.message, stack: err.stack };\n\n if (err instanceof ChronosApiError) {\n return {\n ...base,\n status: err.status,\n code: err.code,\n requestId: err.requestId,\n ...(err.retryAfterSeconds !== undefined && { retryAfterSeconds: err.retryAfterSeconds }),\n ...(err.rateLimit !== undefined && { rateLimit: err.rateLimit }),\n };\n }\n if (err instanceof ChronosNetworkError || err instanceof ChronosHandlerError) {\n return { ...base, cause: errorToLogValue(err.cause) };\n }\n return base;\n}\n\nfunction truncate(value: string, maxLength: number): string {\n return value.length <= maxLength ? value : value.slice(0, maxLength);\n}\n\n// Floored at fallbackMs: a proxy's Retry-After: 0 would otherwise hot-loop\n// against a down origin.\nfunction retryDelayFor(err: unknown, fallbackMs: number): number {\n if (err instanceof ChronosApiError && err.retryAfterSeconds !== undefined) {\n return Math.max(Math.min(err.retryAfterSeconds * 1_000, MAX_RETRY_AFTER_MS), fallbackMs);\n }\n return fallbackMs;\n}\n\nfunction isCredentialRejection(err: ChronosApiError): boolean {\n return err.status === 401 && err.code === 'unauthorized';\n}\n\n// 409 is handled by the caller before reaching here; 408/429 are transient.\nconst NON_TERMINAL_4XX = new Set([408, 409, 429]);\n\n// 200 reaches here only via an explicit `{ success: false }` envelope from BaseClient.\nfunction isTerminalReportError(status: number): boolean {\n if (status === 200) {\n return true;\n }\n if (NON_TERMINAL_4XX.has(status)) {\n return false;\n }\n return status >= 400 && status < 500;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n const timeout: ReturnType<typeof setTimeout> = setTimeout(done, ms);\n\n function done() {\n clearTimeout(timeout);\n signal?.removeEventListener('abort', done);\n resolve();\n }\n\n signal?.addEventListener('abort', done, { once: true });\n });\n}\n","import { ChronosWebhookVerificationError } from './errors';\nimport type { WebhookOptions } from './types';\n\nexport const DEFAULT_TIMESTAMP_TOLERANCE_SECONDS = 300;\n\nconst SIGNATURE_PREFIX = 'sha256=';\nconst REQUIRED_HEADERS = [\n 'x-chronos-signature',\n 'x-chronos-timestamp',\n 'x-chronos-delivery-id',\n] as const;\n\n/**\n * Verifies webhook signatures on Chronos push deliveries.\n *\n * @example\n * ```ts\n * import { Webhook } from '@chronos.sh/sdk';\n *\n * const wh = new Webhook(process.env.CHRONOS_SIGNING_SECRET!);\n *\n * // In your request handler:\n * const payload = await wh.verify(rawBody, {\n * 'x-chronos-signature': req.headers['x-chronos-signature'],\n * 'x-chronos-timestamp': req.headers['x-chronos-timestamp'],\n * 'x-chronos-delivery-id': req.headers['x-chronos-delivery-id'],\n * });\n * ```\n */\nexport class Webhook {\n private readonly secrets: string[];\n private readonly toleranceSeconds: number;\n private keysPromise?: Promise<CryptoKey[]>;\n\n /**\n * @param secret - Signing secret or array of secrets (for key rotation).\n * @param options - Optional configuration.\n * @throws {ChronosWebhookVerificationError} If no valid secret is provided.\n */\n constructor(secret: string | string[], options?: WebhookOptions) {\n const secrets = Array.isArray(secret) ? secret : [secret];\n this.secrets = secrets\n .filter((s) => typeof s === 'string' && s.trim().length > 0)\n .map((s) => s.trim());\n\n if (this.secrets.length === 0) {\n throw new ChronosWebhookVerificationError(\n 'At least one non-empty signing secret is required',\n );\n }\n\n const tolerance = options?.toleranceSeconds ?? DEFAULT_TIMESTAMP_TOLERANCE_SECONDS;\n if (!Number.isFinite(tolerance) || tolerance < 0) {\n throw new ChronosWebhookVerificationError(\n 'toleranceSeconds must be a finite non-negative number',\n );\n }\n this.toleranceSeconds = tolerance;\n }\n\n /**\n * Verifies the webhook signature and returns the parsed request body.\n *\n * @param body - Raw request body as a string. Must be the exact bytes received — not re-serialized.\n * @param headers - Request headers. Keys are matched case-insensitively.\n * @returns The parsed JSON body on successful verification.\n * @throws {ChronosWebhookVerificationError} If any verification step fails.\n */\n async verify(\n body: string,\n headers: Record<string, string | undefined> | Headers,\n ): Promise<unknown> {\n const normalized = normalizeHeaders(headers);\n\n for (const name of REQUIRED_HEADERS) {\n const value = normalized[name];\n if (!value || typeof value !== 'string') {\n throw new ChronosWebhookVerificationError(`Missing required header: ${name}`);\n }\n }\n\n const signature = normalized['x-chronos-signature'] as string;\n const timestamp = normalized['x-chronos-timestamp'] as string;\n const deliveryId = normalized['x-chronos-delivery-id'] as string;\n\n if (!/^[0-9]+$/.test(timestamp)) {\n throw new ChronosWebhookVerificationError('Invalid timestamp');\n }\n\n const ts = Number(timestamp);\n if (ts <= 0) {\n throw new ChronosWebhookVerificationError('Invalid timestamp');\n }\n\n const now = Math.floor(Date.now() / 1000);\n const isStale = Math.abs(now - ts) > this.toleranceSeconds;\n if (this.toleranceSeconds > 0 && isStale) {\n throw new ChronosWebhookVerificationError('Timestamp outside tolerance');\n }\n\n if (!signature.startsWith(SIGNATURE_PREFIX)) {\n throw new ChronosWebhookVerificationError(\n `Invalid signature format: expected ${SIGNATURE_PREFIX}<hex>`,\n );\n }\n\n const expectedHex = signature.slice(SIGNATURE_PREFIX.length);\n if (expectedHex.length === 0) {\n throw new ChronosWebhookVerificationError(\n 'Invalid signature: expected 32-byte SHA-256 digest',\n );\n }\n\n let expectedBytes: ArrayBuffer;\n try {\n expectedBytes = hexDecode(expectedHex);\n } catch {\n throw new ChronosWebhookVerificationError('Invalid signature: malformed hex');\n }\n\n if (expectedBytes.byteLength !== 32) {\n throw new ChronosWebhookVerificationError(\n 'Invalid signature: expected 32-byte SHA-256 digest',\n );\n }\n\n const signedPayload = `${deliveryId}.${timestamp}.${body}`;\n const data = new TextEncoder().encode(signedPayload);\n\n try {\n const keys = await this.ensureKeys();\n for (const key of keys) {\n const valid = await globalThis.crypto.subtle.verify('HMAC', key, expectedBytes, data);\n if (valid) {\n try {\n return JSON.parse(body);\n } catch {\n throw new ChronosWebhookVerificationError('Verified payload is not valid JSON');\n }\n }\n }\n } catch (err) {\n if (err instanceof ChronosWebhookVerificationError) {\n throw err;\n }\n throw new ChronosWebhookVerificationError('Signature verification failed');\n }\n\n throw new ChronosWebhookVerificationError('Signature verification failed');\n }\n\n private ensureKeys(): Promise<CryptoKey[]> {\n if (!this.keysPromise) {\n const encoder = new TextEncoder();\n this.keysPromise = Promise.all(\n this.secrets.map((s) =>\n globalThis.crypto.subtle.importKey(\n 'raw',\n encoder.encode(s),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['verify'],\n ),\n ),\n );\n }\n return this.keysPromise;\n }\n}\n\nfunction normalizeHeaders(\n headers: Record<string, string | undefined> | Headers,\n): Record<string, string | undefined> {\n const result: Record<string, string | undefined> = {};\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n result[key.toLowerCase()] = value;\n });\n } else {\n for (const key of Object.keys(headers)) {\n result[key.toLowerCase()] = headers[key];\n }\n }\n return result;\n}\n\nfunction hexDecode(hex: string): ArrayBuffer {\n if (hex.length % 2 !== 0 || !/^[0-9a-f]+$/i.test(hex)) {\n throw new Error('Invalid hex string');\n }\n const length = hex.length / 2;\n const buffer = new ArrayBuffer(length);\n const view = new DataView(buffer);\n for (let i = 0; i < length; i++) {\n view.setUint8(i, Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16));\n }\n return buffer;\n}\n","import { BaseClient, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS } from './client';\nimport type { ChronosOptions } from './types';\nimport { DEFAULT_POLL_WAIT_TIME_SECONDS, Worker } from './worker';\n\n/**\n * The Chronos SDK client. Composes worker and (future) REST resource\n * subclients from a single instance.\n *\n * @example\n * ```ts\n * import { Chronos } from '@chronos.sh/sdk';\n *\n * const chronos = new Chronos({ apiKey: process.env.CHRONOS_API_KEY! });\n *\n * chronos.worker.handle<{ to: string }>('send-email', async (ctx) => {\n * await sendEmail(ctx.payload.to);\n * return { sent: true };\n * });\n *\n * await chronos.worker.start();\n * ```\n */\nexport class Chronos {\n /** Long-poll worker for executing pull-mode jobs. */\n readonly worker: Worker;\n\n /**\n * @param options - Client configuration. Only `apiKey` is required.\n * @throws {ChronosConfigError} If `apiKey` is missing or any option fails validation.\n */\n constructor(options: ChronosOptions) {\n const client = new BaseClient(options);\n this.worker = new Worker(client, options);\n }\n}\n\nexport {\n ChronosApiError,\n type ChronosApiErrorOptions,\n ChronosConfigError,\n ChronosError,\n ChronosHandlerError,\n ChronosNetworkError,\n ChronosRateLimitError,\n ChronosTimeoutError,\n ChronosWebhookVerificationError,\n type RateLimitInfo,\n} from './errors';\nexport { SDK_VERSION } from './internal/version';\nexport type {\n ChronosContext,\n ChronosHandler,\n ChronosHandlerResult,\n ChronosLogger,\n ChronosOptions,\n ChronosSchedule,\n FetchLike,\n WebhookOptions,\n} from './types';\nexport { DEFAULT_TIMESTAMP_TOLERANCE_SECONDS, Webhook } from './webhook';\nexport { DEFAULT_BASE_URL, DEFAULT_POLL_WAIT_TIME_SECONDS, DEFAULT_TIMEOUT_MS };\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -180,15 +180,10 @@ declare class Worker {
180
180
  */
181
181
  start(): Promise<void>;
182
182
  /**
183
- * Request graceful shutdown. The poll loop is aborted immediately; any
184
- * in-flight handler that has not exceeded its timeout, along with the
185
- * subsequent result-report, is allowed to complete. Timed-out handlers
186
- * are abandoned (their {@link ChronosContext.signal} fires, but the SDK
187
- * does not wait for them). Every HTTP request is bounded by the `timeoutMs`
188
- * transport timeout and retry waits are skipped once stop is requested, so
189
- * the returned promise resolves in bounded time. Returns the same promise
190
- * as the active {@link Worker.start}, or a resolved promise if the worker
191
- * isn't running.
183
+ * Request graceful shutdown: abort the poll, let an in-flight handler
184
+ * finish (up to its timeout) and report its result, then resolve. Bounded
185
+ * by that timeout plus `timeoutMs` per report attempt. Never rejects; a
186
+ * credential rejection surfaces on {@link Worker.start} instead.
192
187
  */
193
188
  stop(): Promise<void>;
194
189
  private get isStopped();
@@ -234,7 +229,8 @@ declare class ChronosError extends Error {
234
229
  }
235
230
  /**
236
231
  * Thrown when SDK options fail validation at `new Chronos({ ... })`. Covers
237
- * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, and `retryDelayMs`.
232
+ * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, `retryDelayMs`, `timeoutMs`, and
233
+ * `workerId`.
238
234
  *
239
235
  * @example
240
236
  * ```ts
package/dist/index.d.ts CHANGED
@@ -180,15 +180,10 @@ declare class Worker {
180
180
  */
181
181
  start(): Promise<void>;
182
182
  /**
183
- * Request graceful shutdown. The poll loop is aborted immediately; any
184
- * in-flight handler that has not exceeded its timeout, along with the
185
- * subsequent result-report, is allowed to complete. Timed-out handlers
186
- * are abandoned (their {@link ChronosContext.signal} fires, but the SDK
187
- * does not wait for them). Every HTTP request is bounded by the `timeoutMs`
188
- * transport timeout and retry waits are skipped once stop is requested, so
189
- * the returned promise resolves in bounded time. Returns the same promise
190
- * as the active {@link Worker.start}, or a resolved promise if the worker
191
- * isn't running.
183
+ * Request graceful shutdown: abort the poll, let an in-flight handler
184
+ * finish (up to its timeout) and report its result, then resolve. Bounded
185
+ * by that timeout plus `timeoutMs` per report attempt. Never rejects; a
186
+ * credential rejection surfaces on {@link Worker.start} instead.
192
187
  */
193
188
  stop(): Promise<void>;
194
189
  private get isStopped();
@@ -234,7 +229,8 @@ declare class ChronosError extends Error {
234
229
  }
235
230
  /**
236
231
  * Thrown when SDK options fail validation at `new Chronos({ ... })`. Covers
237
- * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, and `retryDelayMs`.
232
+ * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, `retryDelayMs`, `timeoutMs`, and
233
+ * `workerId`.
238
234
  *
239
235
  * @example
240
236
  * ```ts
package/dist/index.js CHANGED
@@ -31,7 +31,8 @@ var ChronosError = class extends Error {
31
31
  };
32
32
  /**
33
33
  * Thrown when SDK options fail validation at `new Chronos({ ... })`. Covers
34
- * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, and `retryDelayMs`.
34
+ * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, `retryDelayMs`, `timeoutMs`, and
35
+ * `workerId`.
35
36
  *
36
37
  * @example
37
38
  * ```ts
@@ -388,7 +389,7 @@ function detectRuntime() {
388
389
  }
389
390
  //#endregion
390
391
  //#region src/internal/version.ts
391
- const SDK_VERSION = "0.1.1";
392
+ const SDK_VERSION = "0.1.2-canary.2deb3ad";
392
393
  //#endregion
393
394
  //#region src/worker.ts
394
395
  /** Default worker long-poll wait time in seconds. Equal to the API maximum. */
@@ -472,15 +473,10 @@ var Worker = class {
472
473
  return this.startPromise;
473
474
  }
474
475
  /**
475
- * Request graceful shutdown. The poll loop is aborted immediately; any
476
- * in-flight handler that has not exceeded its timeout, along with the
477
- * subsequent result-report, is allowed to complete. Timed-out handlers
478
- * are abandoned (their {@link ChronosContext.signal} fires, but the SDK
479
- * does not wait for them). Every HTTP request is bounded by the `timeoutMs`
480
- * transport timeout and retry waits are skipped once stop is requested, so
481
- * the returned promise resolves in bounded time. Returns the same promise
482
- * as the active {@link Worker.start}, or a resolved promise if the worker
483
- * isn't running.
476
+ * Request graceful shutdown: abort the poll, let an in-flight handler
477
+ * finish (up to its timeout) and report its result, then resolve. Bounded
478
+ * by that timeout plus `timeoutMs` per report attempt. Never rejects; a
479
+ * credential rejection surfaces on {@link Worker.start} instead.
484
480
  */
485
481
  stop() {
486
482
  this.pollController?.abort();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/errors.ts","../src/internal/logger.ts","../src/internal/validate.ts","../src/client.ts","../src/internal/id.ts","../src/internal/runtime.ts","../src/internal/version.ts","../src/worker.ts","../src/webhook.ts","../src/index.ts"],"sourcesContent":["/**\n * Base class for all errors thrown by the Chronos SDK. Catch this in a\n * single `catch` to handle any SDK failure generically; use the subclasses\n * to branch on cause.\n *\n * @example\n * ```ts\n * import { Chronos, ChronosError } from '@chronos.sh/sdk';\n *\n * const chronos = new Chronos({ apiKey: 'chrns_...' });\n * try {\n * await chronos.worker.start();\n * } catch (err) {\n * if (err instanceof ChronosError) {\n * console.error('Chronos failed:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosError extends Error {\n /** Original error/value that caused this SDK error, when one is available. */\n declare readonly cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'ChronosError';\n\n if (options && !('cause' in this)) {\n Object.defineProperty(this, 'cause', {\n value: options.cause,\n configurable: true,\n writable: true,\n });\n }\n }\n}\n\n/**\n * Thrown when SDK options fail validation at `new Chronos({ ... })`. Covers\n * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, and `retryDelayMs`.\n *\n * @example\n * ```ts\n * import { Chronos, ChronosConfigError } from '@chronos.sh/sdk';\n *\n * try {\n * const chronos = new Chronos({ apiKey: '' });\n * } catch (err) {\n * if (err instanceof ChronosConfigError) {\n * console.error('Invalid Chronos config:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosConfigError extends ChronosError {\n constructor(message: string) {\n super(message);\n this.name = 'ChronosConfigError';\n }\n}\n\n/** Rate-limit budget from `X-RateLimit-*` response headers. Present on non-429 responses. */\nexport type RateLimitInfo = {\n /** Maximum requests allowed per window. */\n limit: number;\n /** Requests remaining in the current window. */\n remaining: number;\n /** Seconds until the current window resets. */\n reset: number;\n};\n\n/** Options for constructing a {@link ChronosApiError}. */\nexport type ChronosApiErrorOptions = {\n /** HTTP status code returned by the Chronos API. */\n status: number;\n /** Application-level error code from the response envelope, when present. */\n code?: string;\n /** Full parsed response payload (envelope + data, or whatever the server returned). */\n body?: unknown;\n /** Value of the `X-Request-Id` response header, when present. Pair with server logs. */\n requestId?: string;\n /** Seconds to wait before retrying, from the `Retry-After` response header. Present on 429 and 5xx responses that include the header. */\n retryAfterSeconds?: number;\n /** Rate-limit budget from `X-RateLimit-*` headers. Present on non-429 responses. */\n rateLimit?: RateLimitInfo;\n};\n\n/**\n * Thrown when the Chronos API responds with a non-2xx status or a\n * `success: false` envelope. Carries HTTP `status`, the application\n * `code`, parsed `body`, the API's `X-Request-Id`, and — when the\n * relevant headers are present — rate-limit metadata\n * (`retryAfterSeconds` on 429 and 5xx, `rateLimit` on non-429 errors).\n *\n * `instanceof ChronosApiError` means the server replied;\n * network/transport failures throw {@link ChronosNetworkError} instead.\n * For 429 specifically, see {@link ChronosRateLimitError}.\n *\n * @example\n * ```ts\n * import { ChronosApiError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosApiError) {\n * if (err.status === 401) return refreshAuth();\n * console.error('API error', { status: err.status, requestId: err.requestId });\n * }\n * }\n * ```\n */\nexport class ChronosApiError extends ChronosError {\n /** HTTP status code returned by the Chronos API. */\n readonly status: number;\n /** Application-level error code from the response envelope, when present. */\n readonly code?: string;\n /** Full parsed response payload (envelope + data, or whatever the server returned). */\n readonly body?: unknown;\n /** Value of the `X-Request-Id` response header, when present. */\n readonly requestId?: string;\n /** Seconds to wait before retrying, from the `Retry-After` response header. Present on 429 and 5xx responses that include the header. */\n readonly retryAfterSeconds?: number;\n /** Rate-limit budget from `X-RateLimit-*` headers. Present on non-429 responses. */\n readonly rateLimit?: RateLimitInfo;\n\n constructor(message: string, options: ChronosApiErrorOptions) {\n super(message);\n this.name = 'ChronosApiError';\n this.status = options.status;\n this.code = options.code;\n this.body = options.body;\n this.requestId = options.requestId;\n this.retryAfterSeconds = options.retryAfterSeconds;\n this.rateLimit = options.rateLimit;\n }\n}\n\n/**\n * Thrown when the Chronos API responds with `429 Too Many Requests`.\n * Subclass of {@link ChronosApiError} — `instanceof ChronosRateLimitError`\n * narrows to a rate-limited response. `retryAfterSeconds` is set when the\n * response includes a `Retry-After` header; otherwise it is `undefined`.\n *\n * @example\n * ```ts\n * import { ChronosRateLimitError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosRateLimitError && err.retryAfterSeconds) {\n * console.warn(`Rate limited — retry after ${err.retryAfterSeconds}s`);\n * }\n * }\n * ```\n */\nexport class ChronosRateLimitError extends ChronosApiError {\n constructor(message: string, options: ChronosApiErrorOptions) {\n super(message, options);\n this.name = 'ChronosRateLimitError';\n }\n}\n\n/**\n * Thrown when a request fails at the transport layer — DNS failure, TCP\n * reset, connection refused, or a connection dropped mid-response. The\n * original error is available on `.cause`.\n *\n * Caller-supplied abort signals propagate unwrapped — `instanceof\n * ChronosNetworkError` always means a transport failure, not a graceful\n * shutdown. The SDK's own transport timeout throws the\n * {@link ChronosTimeoutError} subclass.\n *\n * @example\n * ```ts\n * import { ChronosNetworkError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosNetworkError) {\n * console.warn('Transport blip', { cause: err.cause });\n * }\n * }\n * ```\n */\nexport class ChronosNetworkError extends ChronosError {\n /** Original error/value rejected by the underlying `fetch`. */\n declare readonly cause: unknown;\n\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosNetworkError';\n }\n}\n\n/**\n * Thrown when an HTTP request exceeds the configured `timeoutMs` before the\n * response completes. Subclass of {@link ChronosNetworkError}, so generic\n * transport-failure handling catches it; the underlying rejection is on\n * `.cause`.\n *\n * @example\n * ```ts\n * import { ChronosTimeoutError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosTimeoutError) {\n * console.warn('Chronos request timed out', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosTimeoutError extends ChronosNetworkError {\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosTimeoutError';\n }\n}\n\n/**\n * Wraps an exception thrown by a user-supplied {@link ChronosHandler}. The\n * original error is on `.cause`; `.message` is copied from the original so\n * the SDK reports it to the API as the failure reason.\n *\n * @example\n * ```ts\n * import { ChronosHandlerError } from '@chronos.sh/sdk';\n *\n * if (err instanceof ChronosHandlerError) {\n * console.error('Handler threw', err.cause);\n * }\n * ```\n */\nexport class ChronosHandlerError extends ChronosError {\n /** Original error/value thrown by the user-supplied handler. */\n declare readonly cause: unknown;\n\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosHandlerError';\n }\n}\n\n/**\n * Thrown by {@link Webhook.verify} when signature verification fails.\n * Covers missing or malformed headers, expired timestamps, and signature\n * mismatches.\n *\n * @example\n * ```ts\n * import { Webhook, ChronosWebhookVerificationError } from '@chronos.sh/sdk';\n *\n * const wh = new Webhook(process.env.CHRONOS_SIGNING_SECRET!);\n * try {\n * const payload = await wh.verify(rawBody, headers);\n * } catch (err) {\n * if (err instanceof ChronosWebhookVerificationError) {\n * console.error('Webhook verification failed:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosWebhookVerificationError extends ChronosError {\n constructor(message: string) {\n super(message);\n this.name = 'ChronosWebhookVerificationError';\n }\n}\n","import type { ChronosLogger } from '../types';\n\nexport const defaultLogger: ChronosLogger = {\n debug: (message, meta) => logToConsole(console.debug, message, meta),\n info: (message, meta) => logToConsole(console.info, message, meta),\n warn: (message, meta) => logToConsole(console.warn, message, meta),\n error: (message, meta) => logToConsole(console.error, message, meta),\n};\n\nfunction logToConsole(\n method: (message?: unknown, ...optionalParams: unknown[]) => void,\n message: string,\n meta?: Record<string, unknown>,\n): void {\n if (meta) {\n method(message, meta);\n } else {\n method(message);\n }\n}\n","import { ChronosConfigError, ChronosError } from '../errors';\n\nexport const MAX_HANDLER_NAME_LENGTH = 255;\nexport const MAX_POLL_WAIT_TIME_SECONDS = 20;\n\nexport function validateApiKey(apiKey: string | undefined): string {\n const trimmed = apiKey?.trim();\n if (!trimmed) {\n throw new ChronosConfigError('Chronos apiKey is required');\n }\n return trimmed;\n}\n\nexport function validatePollWaitTime(seconds: number): void {\n if (!Number.isInteger(seconds) || seconds < 0 || seconds > MAX_POLL_WAIT_TIME_SECONDS) {\n throw new ChronosConfigError(\n `pollWaitTimeSeconds must be an integer between 0 and ${MAX_POLL_WAIT_TIME_SECONDS}`,\n );\n }\n}\n\nexport function validateRetryDelayMs(ms: number): void {\n if (!Number.isFinite(ms) || ms < 0) {\n throw new ChronosConfigError('retryDelayMs must be a non-negative number');\n }\n}\n\n// setTimeout silently clamps delays above 2^31-1 to 1ms.\nexport const MAX_TIMEOUT_MS = 2_147_483_647;\n\nexport function validateTimeoutMs(ms: number): void {\n if (!Number.isInteger(ms) || ms <= 0 || ms > MAX_TIMEOUT_MS) {\n throw new ChronosConfigError(\n `timeoutMs must be a positive integer no greater than ${MAX_TIMEOUT_MS}`,\n );\n }\n}\n\nexport function validateWorkerId(id: string): string {\n const trimmed = id.trim();\n if (trimmed.length === 0 || trimmed.length > 255) {\n throw new ChronosConfigError('workerId must be 1-255 characters');\n }\n return trimmed;\n}\n\nexport function normalizeHandlerName(name: string): string {\n const normalized = name.trim();\n\n if (!normalized) {\n throw new ChronosError('Handler name is required');\n }\n\n if (normalized.length > MAX_HANDLER_NAME_LENGTH) {\n throw new ChronosError(`Handler name must be ${MAX_HANDLER_NAME_LENGTH} characters or fewer`);\n }\n\n return normalized;\n}\n","import {\n ChronosApiError,\n ChronosConfigError,\n ChronosError,\n ChronosNetworkError,\n ChronosRateLimitError,\n ChronosTimeoutError,\n type RateLimitInfo,\n} from './errors';\nimport { defaultLogger } from './internal/logger';\nimport { validateApiKey, validateTimeoutMs } from './internal/validate';\nimport type { ChronosLogger, ChronosOptions, FetchLike } from './types';\n\n/** Default Chronos API base URL. */\nexport const DEFAULT_BASE_URL = 'https://api.chronos.sh';\n\n/** Default per-request transport timeout in milliseconds. */\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\ntype ApiResponse<T> = {\n success: boolean;\n message?: string;\n code?: string;\n data: T;\n};\n\ntype RequestOptions = {\n signal?: AbortSignal;\n timeoutMs?: number;\n};\n\nexport class BaseClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly fetch: FetchLike;\n readonly logger: ChronosLogger;\n readonly timeoutMs: number;\n private readonly headers: Record<string, string>;\n\n constructor(options: ChronosOptions) {\n this.apiKey = validateApiKey(options.apiKey);\n this.baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL);\n this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.logger = options.logger ?? defaultLogger;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateTimeoutMs(this.timeoutMs);\n this.headers = {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.apiKey}`,\n };\n }\n\n async request<T>(\n path: string,\n body: Record<string, unknown>,\n options: RequestOptions = {},\n ): Promise<T> {\n const { signal } = options;\n const timeoutMs = options.timeoutMs ?? this.timeoutMs;\n\n // Not AbortSignal.any: Node pins each composite onto long-lived source\n // signals (like the poll signal) forever, leaking per claim.\n const controller = new AbortController();\n let timedOut = false;\n const timer = setTimeout(() => {\n if (controller.signal.aborted) {\n return;\n }\n timedOut = true;\n controller.abort(\n new DOMException(`Chronos API request timed out after ${timeoutMs}ms`, 'TimeoutError'),\n );\n }, timeoutMs);\n const onCallerAbort = () => controller.abort(signal?.reason);\n if (signal?.aborted) {\n onCallerAbort();\n } else {\n signal?.addEventListener('abort', onCallerAbort, { once: true });\n }\n\n try {\n let response: Response;\n try {\n response = await this.fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n if (signal?.aborted && !timedOut) {\n throw err;\n }\n if (timedOut) {\n throw timeoutError(timeoutMs, err);\n }\n const message = err instanceof Error ? err.message : String(err);\n throw new ChronosNetworkError(`Chronos API request failed: ${message}`, { cause: err });\n }\n\n // A half-open connection can stall after headers arrive, so the\n // timeout must cover the body read too.\n let payload: ApiResponse<T> | null;\n try {\n payload = (await response.json()) as ApiResponse<T>;\n } catch (err) {\n // Aborted-state check, not reason identity: some runtimes wrap the\n // abort reason during body reads.\n if (signal?.aborted && !timedOut) {\n throw err;\n }\n if (timedOut) {\n throw timeoutError(timeoutMs, err);\n }\n if (err instanceof SyntaxError) {\n payload = null;\n } else {\n const message = err instanceof Error ? err.message : String(err);\n throw new ChronosNetworkError(`Chronos API response failed: ${message}`, { cause: err });\n }\n }\n\n const envelope = isEnvelope(payload) ? (payload as ApiResponse<T>) : undefined;\n\n if (!response.ok || (envelope && !envelope.success)) {\n const is429 = response.status === 429;\n const retryAfterApplies = is429 || response.status >= 500;\n const ErrorClass = is429 ? ChronosRateLimitError : ChronosApiError;\n throw new ErrorClass(apiErrorMessage(response, envelope), {\n status: response.status,\n code: typeof envelope?.code === 'string' ? envelope.code : undefined,\n body: payload,\n requestId: response.headers.get('x-request-id') ?? undefined,\n retryAfterSeconds: retryAfterApplies\n ? parseIntHeader(response.headers, 'retry-after')\n : undefined,\n rateLimit: is429 ? undefined : parseRateLimitHeaders(response.headers),\n });\n }\n\n if (!envelope) {\n // Plain ChronosError, not ChronosApiError — a malformed 200 body is\n // an infrastructure anomaly that should be retried, not a definitive\n // API rejection.\n throw new ChronosError('Chronos API returned an invalid response');\n }\n\n return envelope.data;\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener('abort', onCallerAbort);\n }\n }\n}\n\nfunction timeoutError(timeoutMs: number, cause: unknown): ChronosTimeoutError {\n return new ChronosTimeoutError(`Chronos API request timed out after ${timeoutMs}ms`, { cause });\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n const normalized = baseUrl.trim().replace(/\\/+$/, '');\n if (!normalized) {\n throw new ChronosConfigError('Chronos baseUrl is required');\n }\n return normalized;\n}\n\nfunction apiErrorMessage(\n response: Response,\n envelope: Record<string, unknown> | undefined,\n): string {\n if (typeof envelope?.message === 'string' && envelope.message.trim()) {\n return envelope.message;\n }\n\n return response.ok\n ? 'Chronos API returned an invalid response'\n : `Chronos API request failed with status ${response.status}`;\n}\n\nfunction parseIntHeader(headers: Headers, name: string): number | undefined {\n const raw = headers.get(name);\n if (raw === null || !/^\\d+$/.test(raw)) {\n return undefined;\n }\n return Number.parseInt(raw, 10);\n}\n\nfunction parseRateLimitHeaders(headers: Headers): RateLimitInfo | undefined {\n const limit = parseIntHeader(headers, 'x-ratelimit-limit');\n const remaining = parseIntHeader(headers, 'x-ratelimit-remaining');\n const reset = parseIntHeader(headers, 'x-ratelimit-reset');\n\n if (limit === undefined || remaining === undefined || reset === undefined) {\n return undefined;\n }\n return { limit, remaining, reset };\n}\n\n// Malformed bodies (arrays, primitives, missing `success`) are routed to the\n// invalid-response path, not classified as API errors.\nfunction isEnvelope(value: unknown): value is Record<string, unknown> & { success: boolean } {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n return typeof (value as Record<string, unknown>).success === 'boolean';\n}\n","export function generateWorkerId(): string {\n const bytes = crypto.getRandomValues(new Uint8Array(8));\n let hex = '';\n for (const b of bytes) {\n hex += b.toString(16).padStart(2, '0');\n }\n return `w_${hex}`;\n}\n","export function detectRuntime(): string {\n const g = globalThis as unknown as Record<string, Record<string, unknown> | undefined>;\n\n if (g.Bun != null) {\n return `bun/${(g.Bun.version as string | undefined) ?? 'unknown'}`;\n }\n\n if (g.Deno != null) {\n const version = g.Deno.version as Record<string, string> | undefined;\n return `deno/${version?.deno ?? 'unknown'}`;\n }\n\n if (typeof process !== 'undefined' && process.versions?.node) {\n return `node/${process.versions.node}`;\n }\n\n return 'unknown';\n}\n","declare const __SDK_VERSION__: string;\n\nexport const SDK_VERSION: string = __SDK_VERSION__;\n","import type { BaseClient } from './client';\nimport { ChronosApiError, ChronosError, ChronosHandlerError, ChronosNetworkError } from './errors';\nimport { generateWorkerId } from './internal/id';\nimport { detectRuntime } from './internal/runtime';\nimport {\n MAX_TIMEOUT_MS,\n normalizeHandlerName,\n validatePollWaitTime,\n validateRetryDelayMs,\n validateWorkerId,\n} from './internal/validate';\nimport { SDK_VERSION } from './internal/version';\nimport type {\n ChronosContext,\n ChronosHandler,\n ChronosHandlerResult,\n ChronosOptions,\n ChronosSchedule,\n} from './types';\n\n/** Default worker long-poll wait time in seconds. Equal to the API maximum. */\nexport const DEFAULT_POLL_WAIT_TIME_SECONDS = 20;\nconst DEFAULT_RETRY_DELAY_MS = 1_000;\n// Retry-After on 5xx often comes from proxies/CDNs with browser-oriented\n// values (e.g. 3600); uncapped it would park the worker for hours.\nconst MAX_RETRY_AFTER_MS = 60_000;\nconst RESULT_REPORT_MAX_ATTEMPTS = 3;\nconst MAX_REPORTED_ERROR_LENGTH = 4_096;\nconst DEFAULT_HANDLER_ERROR = 'Chronos handler failed';\n\ntype ResultStatus = 'completed' | 'failed' | 'timeout';\n\ntype HandlerOutcome = { timedOut: false; result: ChronosHandlerResult } | { timedOut: true };\n\ntype ClaimedJob = {\n job_id: string;\n execution_id: string;\n handler: string;\n scheduled_for: string;\n attempt: number;\n timeout: number;\n payload: unknown;\n schedule: ChronosSchedule | null;\n};\n\n/**\n * Long-poll worker. Claims jobs from the Chronos API, dispatches them to\n * registered handlers, and reports results.\n *\n * Construct via `new Chronos({ apiKey }).worker` rather than directly.\n */\nexport class Worker {\n private readonly client: BaseClient;\n private readonly pollWaitTimeSeconds: number;\n private readonly retryDelayMs: number;\n private readonly workerId: string;\n private readonly runtime: string;\n private readonly handlers = new Map<string, ChronosHandler<unknown>>();\n private handlerNames: string[] = [];\n private startPromise?: Promise<void>;\n private pollController?: AbortController;\n private startedAt = 0;\n\n constructor(client: BaseClient, options: ChronosOptions) {\n this.client = client;\n this.pollWaitTimeSeconds = options.pollWaitTimeSeconds ?? DEFAULT_POLL_WAIT_TIME_SECONDS;\n this.retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n this.workerId =\n options.workerId !== undefined ? validateWorkerId(options.workerId) : generateWorkerId();\n this.runtime = detectRuntime();\n\n validatePollWaitTime(this.pollWaitTimeSeconds);\n validateRetryDelayMs(this.retryDelayMs);\n }\n\n /**\n * Register a handler for a named job type. Invoked when the Chronos API\n * claims a job whose `handler` field matches `name`. Names are trimmed and\n * must be 1–255 characters.\n *\n * @param name - Handler name. Must match the schedule's `handler` on the API side.\n * @param handler - Async function invoked with the job context. Return a\n * plain object to record a result, or `undefined` for none.\n * @returns The Worker, for chaining.\n * @throws {ChronosError} If the name is invalid, already registered, or `handler` is not a function.\n *\n * @example\n * ```ts\n * chronos.worker\n * .handle('send-email', async (ctx) => ({ sent: true }))\n * .handle('cleanup', async () => undefined);\n * ```\n */\n handle<TPayload = unknown>(name: string, handler: ChronosHandler<TPayload>): this {\n const normalizedName = normalizeHandlerName(name);\n\n if (this.handlers.has(normalizedName)) {\n throw new ChronosError(`Handler \"${normalizedName}\" is already registered`);\n }\n\n if (typeof handler !== 'function') {\n throw new ChronosError(`Handler \"${normalizedName}\" must be a function`);\n }\n\n this.handlers.set(normalizedName, handler as ChronosHandler<unknown>);\n this.handlerNames.push(normalizedName);\n return this;\n }\n\n /**\n * Begin long-polling for jobs. The returned promise resolves when\n * {@link Worker.stop} is called and any in-flight job completes, and\n * rejects if the API rejects the worker's credentials (a 401 with the\n * `unauthorized` error code) — a misconfigured key is not recoverable by\n * retrying.\n *\n * @throws {ChronosError} Synchronously, if no handlers are registered or the worker is already running.\n * @throws {ChronosApiError} Via the returned promise, when the API rejects the worker's credentials.\n */\n start(): Promise<void> {\n if (this.startPromise) {\n throw new ChronosError('Chronos worker is already started');\n }\n\n if (this.handlers.size === 0) {\n throw new ChronosError('Register at least one handler before starting Chronos');\n }\n\n this.startedAt = performance.now();\n this.pollController = new AbortController();\n this.startPromise = this.runLoop().finally(() => {\n this.startPromise = undefined;\n this.pollController = undefined;\n });\n\n return this.startPromise;\n }\n\n /**\n * Request graceful shutdown. The poll loop is aborted immediately; any\n * in-flight handler that has not exceeded its timeout, along with the\n * subsequent result-report, is allowed to complete. Timed-out handlers\n * are abandoned (their {@link ChronosContext.signal} fires, but the SDK\n * does not wait for them). Every HTTP request is bounded by the `timeoutMs`\n * transport timeout and retry waits are skipped once stop is requested, so\n * the returned promise resolves in bounded time. Returns the same promise\n * as the active {@link Worker.start}, or a resolved promise if the worker\n * isn't running.\n */\n stop(): Promise<void> {\n this.pollController?.abort();\n return this.startPromise ?? Promise.resolve();\n }\n\n private get isStopped(): boolean {\n return this.pollController?.signal.aborted ?? true;\n }\n\n private async runLoop(): Promise<void> {\n while (!this.isStopped) {\n try {\n const job = await this.claimJob();\n if (job) {\n await this.processJob(job);\n }\n } catch (err) {\n if (this.isStopped) {\n break;\n }\n\n if (err instanceof ChronosApiError && isCredentialRejection(err)) {\n this.client.logger.error('Chronos worker stopped; API rejected credentials', {\n err: errorToLogValue(err),\n });\n throw err;\n }\n\n this.client.logger.error('Chronos poll loop error', { err: errorToLogValue(err) });\n await sleep(retryDelayFor(err, this.retryDelayMs), this.pollController?.signal);\n }\n }\n }\n\n private async claimJob(): Promise<ClaimedJob | null> {\n if (this.handlerNames.length === 0) {\n throw new ChronosError('Cannot claim jobs without registered handlers');\n }\n\n return this.client.request<ClaimedJob | null>(\n '/v1/workers/jobs/claim',\n {\n wait_time_seconds: this.pollWaitTimeSeconds,\n handlers: this.handlerNames,\n worker: {\n id: this.workerId,\n sdk_version: SDK_VERSION,\n runtime: this.runtime,\n uptime_ms: Math.round(performance.now() - this.startedAt),\n },\n },\n {\n signal: this.pollController?.signal,\n // The intentional long-poll wait must not count against the\n // transport bound.\n timeoutMs: Math.min(\n this.pollWaitTimeSeconds * 1_000 + this.client.timeoutMs,\n MAX_TIMEOUT_MS,\n ),\n },\n );\n }\n\n private async processJob(job: ClaimedJob): Promise<void> {\n const handler = this.handlers.get(job.handler);\n if (!handler) {\n return this.handleUnregisteredJob(job);\n }\n\n const controller = new AbortController();\n let outcome: HandlerOutcome;\n try {\n outcome = await this.runHandlerWithTimeout(\n handler,\n createContext(job, controller.signal),\n job.timeout * 1_000,\n controller,\n );\n } catch (err) {\n const message = errorMessage(err);\n const handlerErr = new ChronosHandlerError(message, { cause: err });\n this.client.logger.error('Chronos handler failed', {\n ...jobLogMeta(job),\n err: errorToLogValue(handlerErr),\n });\n await this.safeReportFailed(job, message);\n return;\n }\n\n if (outcome.timedOut) {\n this.client.logger.error('Chronos handler timed out', {\n ...jobLogMeta(job),\n timeout: job.timeout,\n });\n try {\n await this.reportTimeout(job.execution_id);\n } catch (err) {\n this.logResultReportFailure(err, job, 'timeout');\n }\n return;\n }\n\n let result: Record<string, unknown> | undefined;\n try {\n result = normalizeHandlerResult(outcome.result);\n } catch (err) {\n this.client.logger.error('Chronos handler returned invalid result', {\n ...jobLogMeta(job),\n err: errorToLogValue(err),\n });\n await this.safeReportFailed(job, errorMessage(err));\n return;\n }\n\n try {\n await this.reportCompleted(job.execution_id, result);\n } catch (err) {\n this.logResultReportFailure(err, job, 'completed');\n }\n }\n\n private runHandlerWithTimeout(\n handler: ChronosHandler<unknown>,\n ctx: ChronosContext<unknown>,\n timeoutMs: number,\n controller: AbortController,\n ): Promise<HandlerOutcome> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const handlerPromise = Promise.resolve(handler(ctx)).then(\n (result): HandlerOutcome => ({ timedOut: false, result }),\n );\n handlerPromise.catch(() => {});\n\n const timeoutPromise = new Promise<HandlerOutcome>((resolve) => {\n timer = setTimeout(() => {\n controller.abort();\n resolve({ timedOut: true });\n }, timeoutMs);\n });\n\n return Promise.race([handlerPromise, timeoutPromise]).finally(() => {\n clearTimeout(timer);\n });\n }\n\n private async handleUnregisteredJob(job: ClaimedJob): Promise<void> {\n const message = `Chronos SDK received job for unregistered handler \"${job.handler}\"`;\n this.client.logger.error(message, jobLogMeta(job));\n await this.safeReportFailed(job, message);\n }\n\n private async safeReportFailed(job: ClaimedJob, message: string): Promise<void> {\n try {\n await this.reportFailed(job.execution_id, message);\n } catch (err) {\n this.logResultReportFailure(err, job, 'failed');\n }\n }\n\n private async reportCompleted(\n executionId: string,\n result: Record<string, unknown> | undefined,\n ): Promise<void> {\n await this.reportResultWithRetry(executionId, {\n status: 'completed',\n ...(result === undefined ? {} : { result }),\n });\n }\n\n private async reportTimeout(executionId: string): Promise<void> {\n await this.reportResultWithRetry(executionId, { status: 'timeout' });\n }\n\n private async reportFailed(executionId: string, error: string): Promise<void> {\n await this.reportResultWithRetry(executionId, {\n status: 'failed',\n error: truncate(error, MAX_REPORTED_ERROR_LENGTH),\n });\n }\n\n private async reportResultWithRetry(\n executionId: string,\n body: Record<string, unknown>,\n ): Promise<void> {\n let lastErr: unknown;\n\n for (let attempt = 1; attempt <= RESULT_REPORT_MAX_ATTEMPTS; attempt++) {\n try {\n await this.client.request(\n `/v1/workers/executions/${encodeURIComponent(executionId)}/result`,\n body,\n );\n return;\n } catch (err) {\n const apiErr = err instanceof ChronosApiError ? err : undefined;\n\n if (apiErr?.status === 409) {\n this.client.logger.warn('Chronos result discarded; execution already terminal', {\n executionId,\n status: body.status,\n code: apiErr.code,\n });\n return;\n }\n\n if (apiErr && isTerminalReportError(apiErr.status)) {\n throw apiErr;\n }\n\n lastErr = err;\n if (attempt === RESULT_REPORT_MAX_ATTEMPTS) {\n break;\n }\n\n this.client.logger.warn('Chronos result report failed; retrying', {\n err: errorToLogValue(err),\n executionId,\n status: body.status,\n attempt,\n maxAttempts: RESULT_REPORT_MAX_ATTEMPTS,\n });\n // The signal skips the wait after stop(), never the retry itself:\n // the report is still allowed to complete.\n await sleep(retryDelayFor(err, this.retryDelayMs), this.pollController?.signal);\n }\n }\n\n throw lastErr;\n }\n\n private logResultReportFailure(err: unknown, job: ClaimedJob, status: ResultStatus): void {\n const isTerminal = err instanceof ChronosApiError && isTerminalReportError(err.status);\n this.client.logger.error(\n isTerminal\n ? 'Chronos result report rejected by API'\n : 'Chronos result report failed after retries',\n { ...jobLogMeta(job), err: errorToLogValue(err), status },\n );\n }\n}\n\nfunction createContext(job: ClaimedJob, signal: AbortSignal): ChronosContext<unknown> {\n return {\n jobId: job.job_id,\n executionId: job.execution_id,\n handler: job.handler,\n payload: job.payload,\n scheduledFor: new Date(job.scheduled_for),\n attempt: job.attempt,\n timeout: job.timeout,\n signal,\n schedule: job.schedule,\n };\n}\n\nfunction jobLogMeta(job: ClaimedJob): Record<string, unknown> {\n return {\n jobId: job.job_id,\n executionId: job.execution_id,\n handler: job.handler,\n };\n}\n\nfunction normalizeHandlerResult(result: ChronosHandlerResult): Record<string, unknown> | undefined {\n if (result === undefined) {\n return undefined;\n }\n\n if (!isPlainObject(result)) {\n throw new ChronosError('Chronos handler result must be a plain object or undefined');\n }\n\n try {\n JSON.stringify(result);\n } catch (err) {\n const reason = err instanceof Error ? err.message : 'value is not JSON-encodable';\n throw new ChronosError(`Chronos handler result is not JSON-encodable: ${reason}`);\n }\n\n return result;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction errorMessage(err: unknown): string {\n const message = err instanceof Error ? err.message : String(err);\n return message.trim() || DEFAULT_HANDLER_ERROR;\n}\n\nfunction errorToLogValue(err: unknown): unknown {\n if (!(err instanceof Error)) {\n return err;\n }\n\n const base = { name: err.name, message: err.message, stack: err.stack };\n\n if (err instanceof ChronosApiError) {\n return {\n ...base,\n status: err.status,\n code: err.code,\n requestId: err.requestId,\n ...(err.retryAfterSeconds !== undefined && { retryAfterSeconds: err.retryAfterSeconds }),\n ...(err.rateLimit !== undefined && { rateLimit: err.rateLimit }),\n };\n }\n if (err instanceof ChronosNetworkError || err instanceof ChronosHandlerError) {\n return { ...base, cause: errorToLogValue(err.cause) };\n }\n return base;\n}\n\nfunction truncate(value: string, maxLength: number): string {\n return value.length <= maxLength ? value : value.slice(0, maxLength);\n}\n\n// Floored at fallbackMs: a proxy's Retry-After: 0 would otherwise hot-loop\n// against a down origin.\nfunction retryDelayFor(err: unknown, fallbackMs: number): number {\n if (err instanceof ChronosApiError && err.retryAfterSeconds !== undefined) {\n return Math.max(Math.min(err.retryAfterSeconds * 1_000, MAX_RETRY_AFTER_MS), fallbackMs);\n }\n return fallbackMs;\n}\n\nfunction isCredentialRejection(err: ChronosApiError): boolean {\n return err.status === 401 && err.code === 'unauthorized';\n}\n\n// 409 is handled by the caller before reaching here; 408/429 are transient.\nconst NON_TERMINAL_4XX = new Set([408, 409, 429]);\n\n// 200 reaches here only via an explicit `{ success: false }` envelope from BaseClient.\nfunction isTerminalReportError(status: number): boolean {\n if (status === 200) {\n return true;\n }\n if (NON_TERMINAL_4XX.has(status)) {\n return false;\n }\n return status >= 400 && status < 500;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n const timeout: ReturnType<typeof setTimeout> = setTimeout(done, ms);\n\n function done() {\n clearTimeout(timeout);\n signal?.removeEventListener('abort', done);\n resolve();\n }\n\n signal?.addEventListener('abort', done, { once: true });\n });\n}\n","import { ChronosWebhookVerificationError } from './errors';\nimport type { WebhookOptions } from './types';\n\nexport const DEFAULT_TIMESTAMP_TOLERANCE_SECONDS = 300;\n\nconst SIGNATURE_PREFIX = 'sha256=';\nconst REQUIRED_HEADERS = [\n 'x-chronos-signature',\n 'x-chronos-timestamp',\n 'x-chronos-delivery-id',\n] as const;\n\n/**\n * Verifies webhook signatures on Chronos push deliveries.\n *\n * @example\n * ```ts\n * import { Webhook } from '@chronos.sh/sdk';\n *\n * const wh = new Webhook(process.env.CHRONOS_SIGNING_SECRET!);\n *\n * // In your request handler:\n * const payload = await wh.verify(rawBody, {\n * 'x-chronos-signature': req.headers['x-chronos-signature'],\n * 'x-chronos-timestamp': req.headers['x-chronos-timestamp'],\n * 'x-chronos-delivery-id': req.headers['x-chronos-delivery-id'],\n * });\n * ```\n */\nexport class Webhook {\n private readonly secrets: string[];\n private readonly toleranceSeconds: number;\n private keysPromise?: Promise<CryptoKey[]>;\n\n /**\n * @param secret - Signing secret or array of secrets (for key rotation).\n * @param options - Optional configuration.\n * @throws {ChronosWebhookVerificationError} If no valid secret is provided.\n */\n constructor(secret: string | string[], options?: WebhookOptions) {\n const secrets = Array.isArray(secret) ? secret : [secret];\n this.secrets = secrets\n .filter((s) => typeof s === 'string' && s.trim().length > 0)\n .map((s) => s.trim());\n\n if (this.secrets.length === 0) {\n throw new ChronosWebhookVerificationError(\n 'At least one non-empty signing secret is required',\n );\n }\n\n const tolerance = options?.toleranceSeconds ?? DEFAULT_TIMESTAMP_TOLERANCE_SECONDS;\n if (!Number.isFinite(tolerance) || tolerance < 0) {\n throw new ChronosWebhookVerificationError(\n 'toleranceSeconds must be a finite non-negative number',\n );\n }\n this.toleranceSeconds = tolerance;\n }\n\n /**\n * Verifies the webhook signature and returns the parsed request body.\n *\n * @param body - Raw request body as a string. Must be the exact bytes received — not re-serialized.\n * @param headers - Request headers. Keys are matched case-insensitively.\n * @returns The parsed JSON body on successful verification.\n * @throws {ChronosWebhookVerificationError} If any verification step fails.\n */\n async verify(\n body: string,\n headers: Record<string, string | undefined> | Headers,\n ): Promise<unknown> {\n const normalized = normalizeHeaders(headers);\n\n for (const name of REQUIRED_HEADERS) {\n const value = normalized[name];\n if (!value || typeof value !== 'string') {\n throw new ChronosWebhookVerificationError(`Missing required header: ${name}`);\n }\n }\n\n const signature = normalized['x-chronos-signature'] as string;\n const timestamp = normalized['x-chronos-timestamp'] as string;\n const deliveryId = normalized['x-chronos-delivery-id'] as string;\n\n if (!/^[0-9]+$/.test(timestamp)) {\n throw new ChronosWebhookVerificationError('Invalid timestamp');\n }\n\n const ts = Number(timestamp);\n if (ts <= 0) {\n throw new ChronosWebhookVerificationError('Invalid timestamp');\n }\n\n const now = Math.floor(Date.now() / 1000);\n const isStale = Math.abs(now - ts) > this.toleranceSeconds;\n if (this.toleranceSeconds > 0 && isStale) {\n throw new ChronosWebhookVerificationError('Timestamp outside tolerance');\n }\n\n if (!signature.startsWith(SIGNATURE_PREFIX)) {\n throw new ChronosWebhookVerificationError(\n `Invalid signature format: expected ${SIGNATURE_PREFIX}<hex>`,\n );\n }\n\n const expectedHex = signature.slice(SIGNATURE_PREFIX.length);\n if (expectedHex.length === 0) {\n throw new ChronosWebhookVerificationError(\n 'Invalid signature: expected 32-byte SHA-256 digest',\n );\n }\n\n let expectedBytes: ArrayBuffer;\n try {\n expectedBytes = hexDecode(expectedHex);\n } catch {\n throw new ChronosWebhookVerificationError('Invalid signature: malformed hex');\n }\n\n if (expectedBytes.byteLength !== 32) {\n throw new ChronosWebhookVerificationError(\n 'Invalid signature: expected 32-byte SHA-256 digest',\n );\n }\n\n const signedPayload = `${deliveryId}.${timestamp}.${body}`;\n const data = new TextEncoder().encode(signedPayload);\n\n try {\n const keys = await this.ensureKeys();\n for (const key of keys) {\n const valid = await globalThis.crypto.subtle.verify('HMAC', key, expectedBytes, data);\n if (valid) {\n try {\n return JSON.parse(body);\n } catch {\n throw new ChronosWebhookVerificationError('Verified payload is not valid JSON');\n }\n }\n }\n } catch (err) {\n if (err instanceof ChronosWebhookVerificationError) {\n throw err;\n }\n throw new ChronosWebhookVerificationError('Signature verification failed');\n }\n\n throw new ChronosWebhookVerificationError('Signature verification failed');\n }\n\n private ensureKeys(): Promise<CryptoKey[]> {\n if (!this.keysPromise) {\n const encoder = new TextEncoder();\n this.keysPromise = Promise.all(\n this.secrets.map((s) =>\n globalThis.crypto.subtle.importKey(\n 'raw',\n encoder.encode(s),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['verify'],\n ),\n ),\n );\n }\n return this.keysPromise;\n }\n}\n\nfunction normalizeHeaders(\n headers: Record<string, string | undefined> | Headers,\n): Record<string, string | undefined> {\n const result: Record<string, string | undefined> = {};\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n result[key.toLowerCase()] = value;\n });\n } else {\n for (const key of Object.keys(headers)) {\n result[key.toLowerCase()] = headers[key];\n }\n }\n return result;\n}\n\nfunction hexDecode(hex: string): ArrayBuffer {\n if (hex.length % 2 !== 0 || !/^[0-9a-f]+$/i.test(hex)) {\n throw new Error('Invalid hex string');\n }\n const length = hex.length / 2;\n const buffer = new ArrayBuffer(length);\n const view = new DataView(buffer);\n for (let i = 0; i < length; i++) {\n view.setUint8(i, Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16));\n }\n return buffer;\n}\n","import { BaseClient, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS } from './client';\nimport type { ChronosOptions } from './types';\nimport { DEFAULT_POLL_WAIT_TIME_SECONDS, Worker } from './worker';\n\n/**\n * The Chronos SDK client. Composes worker and (future) REST resource\n * subclients from a single instance.\n *\n * @example\n * ```ts\n * import { Chronos } from '@chronos.sh/sdk';\n *\n * const chronos = new Chronos({ apiKey: process.env.CHRONOS_API_KEY! });\n *\n * chronos.worker.handle<{ to: string }>('send-email', async (ctx) => {\n * await sendEmail(ctx.payload.to);\n * return { sent: true };\n * });\n *\n * await chronos.worker.start();\n * ```\n */\nexport class Chronos {\n /** Long-poll worker for executing pull-mode jobs. */\n readonly worker: Worker;\n\n /**\n * @param options - Client configuration. Only `apiKey` is required.\n * @throws {ChronosConfigError} If `apiKey` is missing or any option fails validation.\n */\n constructor(options: ChronosOptions) {\n const client = new BaseClient(options);\n this.worker = new Worker(client, options);\n }\n}\n\nexport {\n ChronosApiError,\n type ChronosApiErrorOptions,\n ChronosConfigError,\n ChronosError,\n ChronosHandlerError,\n ChronosNetworkError,\n ChronosRateLimitError,\n ChronosTimeoutError,\n ChronosWebhookVerificationError,\n type RateLimitInfo,\n} from './errors';\nexport { SDK_VERSION } from './internal/version';\nexport type {\n ChronosContext,\n ChronosHandler,\n ChronosHandlerResult,\n ChronosLogger,\n ChronosOptions,\n ChronosSchedule,\n FetchLike,\n WebhookOptions,\n} from './types';\nexport { DEFAULT_TIMESTAMP_TOLERANCE_SECONDS, Webhook } from './webhook';\nexport { DEFAULT_BASE_URL, DEFAULT_POLL_WAIT_TIME_SECONDS, DEFAULT_TIMEOUT_MS };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/errors.ts","../src/internal/logger.ts","../src/internal/validate.ts","../src/client.ts","../src/internal/id.ts","../src/internal/runtime.ts","../src/internal/version.ts","../src/worker.ts","../src/webhook.ts","../src/index.ts"],"sourcesContent":["/**\n * Base class for all errors thrown by the Chronos SDK. Catch this in a\n * single `catch` to handle any SDK failure generically; use the subclasses\n * to branch on cause.\n *\n * @example\n * ```ts\n * import { Chronos, ChronosError } from '@chronos.sh/sdk';\n *\n * const chronos = new Chronos({ apiKey: 'chrns_...' });\n * try {\n * await chronos.worker.start();\n * } catch (err) {\n * if (err instanceof ChronosError) {\n * console.error('Chronos failed:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosError extends Error {\n /** Original error/value that caused this SDK error, when one is available. */\n declare readonly cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'ChronosError';\n\n if (options && !('cause' in this)) {\n Object.defineProperty(this, 'cause', {\n value: options.cause,\n configurable: true,\n writable: true,\n });\n }\n }\n}\n\n/**\n * Thrown when SDK options fail validation at `new Chronos({ ... })`. Covers\n * `apiKey`, `baseUrl`, `pollWaitTimeSeconds`, `retryDelayMs`, `timeoutMs`, and\n * `workerId`.\n *\n * @example\n * ```ts\n * import { Chronos, ChronosConfigError } from '@chronos.sh/sdk';\n *\n * try {\n * const chronos = new Chronos({ apiKey: '' });\n * } catch (err) {\n * if (err instanceof ChronosConfigError) {\n * console.error('Invalid Chronos config:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosConfigError extends ChronosError {\n constructor(message: string) {\n super(message);\n this.name = 'ChronosConfigError';\n }\n}\n\n/** Rate-limit budget from `X-RateLimit-*` response headers. Present on non-429 responses. */\nexport type RateLimitInfo = {\n /** Maximum requests allowed per window. */\n limit: number;\n /** Requests remaining in the current window. */\n remaining: number;\n /** Seconds until the current window resets. */\n reset: number;\n};\n\n/** Options for constructing a {@link ChronosApiError}. */\nexport type ChronosApiErrorOptions = {\n /** HTTP status code returned by the Chronos API. */\n status: number;\n /** Application-level error code from the response envelope, when present. */\n code?: string;\n /** Full parsed response payload (envelope + data, or whatever the server returned). */\n body?: unknown;\n /** Value of the `X-Request-Id` response header, when present. Pair with server logs. */\n requestId?: string;\n /** Seconds to wait before retrying, from the `Retry-After` response header. Present on 429 and 5xx responses that include the header. */\n retryAfterSeconds?: number;\n /** Rate-limit budget from `X-RateLimit-*` headers. Present on non-429 responses. */\n rateLimit?: RateLimitInfo;\n};\n\n/**\n * Thrown when the Chronos API responds with a non-2xx status or a\n * `success: false` envelope. Carries HTTP `status`, the application\n * `code`, parsed `body`, the API's `X-Request-Id`, and — when the\n * relevant headers are present — rate-limit metadata\n * (`retryAfterSeconds` on 429 and 5xx, `rateLimit` on non-429 errors).\n *\n * `instanceof ChronosApiError` means the server replied;\n * network/transport failures throw {@link ChronosNetworkError} instead.\n * For 429 specifically, see {@link ChronosRateLimitError}.\n *\n * @example\n * ```ts\n * import { ChronosApiError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosApiError) {\n * if (err.status === 401) return refreshAuth();\n * console.error('API error', { status: err.status, requestId: err.requestId });\n * }\n * }\n * ```\n */\nexport class ChronosApiError extends ChronosError {\n /** HTTP status code returned by the Chronos API. */\n readonly status: number;\n /** Application-level error code from the response envelope, when present. */\n readonly code?: string;\n /** Full parsed response payload (envelope + data, or whatever the server returned). */\n readonly body?: unknown;\n /** Value of the `X-Request-Id` response header, when present. */\n readonly requestId?: string;\n /** Seconds to wait before retrying, from the `Retry-After` response header. Present on 429 and 5xx responses that include the header. */\n readonly retryAfterSeconds?: number;\n /** Rate-limit budget from `X-RateLimit-*` headers. Present on non-429 responses. */\n readonly rateLimit?: RateLimitInfo;\n\n constructor(message: string, options: ChronosApiErrorOptions) {\n super(message);\n this.name = 'ChronosApiError';\n this.status = options.status;\n this.code = options.code;\n this.body = options.body;\n this.requestId = options.requestId;\n this.retryAfterSeconds = options.retryAfterSeconds;\n this.rateLimit = options.rateLimit;\n }\n}\n\n/**\n * Thrown when the Chronos API responds with `429 Too Many Requests`.\n * Subclass of {@link ChronosApiError} — `instanceof ChronosRateLimitError`\n * narrows to a rate-limited response. `retryAfterSeconds` is set when the\n * response includes a `Retry-After` header; otherwise it is `undefined`.\n *\n * @example\n * ```ts\n * import { ChronosRateLimitError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosRateLimitError && err.retryAfterSeconds) {\n * console.warn(`Rate limited — retry after ${err.retryAfterSeconds}s`);\n * }\n * }\n * ```\n */\nexport class ChronosRateLimitError extends ChronosApiError {\n constructor(message: string, options: ChronosApiErrorOptions) {\n super(message, options);\n this.name = 'ChronosRateLimitError';\n }\n}\n\n/**\n * Thrown when a request fails at the transport layer — DNS failure, TCP\n * reset, connection refused, or a connection dropped mid-response. The\n * original error is available on `.cause`.\n *\n * Caller-supplied abort signals propagate unwrapped — `instanceof\n * ChronosNetworkError` always means a transport failure, not a graceful\n * shutdown. The SDK's own transport timeout throws the\n * {@link ChronosTimeoutError} subclass.\n *\n * @example\n * ```ts\n * import { ChronosNetworkError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosNetworkError) {\n * console.warn('Transport blip', { cause: err.cause });\n * }\n * }\n * ```\n */\nexport class ChronosNetworkError extends ChronosError {\n /** Original error/value rejected by the underlying `fetch`. */\n declare readonly cause: unknown;\n\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosNetworkError';\n }\n}\n\n/**\n * Thrown when an HTTP request exceeds the configured `timeoutMs` before the\n * response completes. Subclass of {@link ChronosNetworkError}, so generic\n * transport-failure handling catches it; the underlying rejection is on\n * `.cause`.\n *\n * @example\n * ```ts\n * import { ChronosTimeoutError } from '@chronos.sh/sdk';\n *\n * function handleSdkError(err: unknown) {\n * if (err instanceof ChronosTimeoutError) {\n * console.warn('Chronos request timed out', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosTimeoutError extends ChronosNetworkError {\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosTimeoutError';\n }\n}\n\n/**\n * Wraps an exception thrown by a user-supplied {@link ChronosHandler}. The\n * original error is on `.cause`; `.message` is copied from the original so\n * the SDK reports it to the API as the failure reason.\n *\n * @example\n * ```ts\n * import { ChronosHandlerError } from '@chronos.sh/sdk';\n *\n * if (err instanceof ChronosHandlerError) {\n * console.error('Handler threw', err.cause);\n * }\n * ```\n */\nexport class ChronosHandlerError extends ChronosError {\n /** Original error/value thrown by the user-supplied handler. */\n declare readonly cause: unknown;\n\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'ChronosHandlerError';\n }\n}\n\n/**\n * Thrown by {@link Webhook.verify} when signature verification fails.\n * Covers missing or malformed headers, expired timestamps, and signature\n * mismatches.\n *\n * @example\n * ```ts\n * import { Webhook, ChronosWebhookVerificationError } from '@chronos.sh/sdk';\n *\n * const wh = new Webhook(process.env.CHRONOS_SIGNING_SECRET!);\n * try {\n * const payload = await wh.verify(rawBody, headers);\n * } catch (err) {\n * if (err instanceof ChronosWebhookVerificationError) {\n * console.error('Webhook verification failed:', err.message);\n * }\n * }\n * ```\n */\nexport class ChronosWebhookVerificationError extends ChronosError {\n constructor(message: string) {\n super(message);\n this.name = 'ChronosWebhookVerificationError';\n }\n}\n","import type { ChronosLogger } from '../types';\n\nexport const defaultLogger: ChronosLogger = {\n debug: (message, meta) => logToConsole(console.debug, message, meta),\n info: (message, meta) => logToConsole(console.info, message, meta),\n warn: (message, meta) => logToConsole(console.warn, message, meta),\n error: (message, meta) => logToConsole(console.error, message, meta),\n};\n\nfunction logToConsole(\n method: (message?: unknown, ...optionalParams: unknown[]) => void,\n message: string,\n meta?: Record<string, unknown>,\n): void {\n if (meta) {\n method(message, meta);\n } else {\n method(message);\n }\n}\n","import { ChronosConfigError, ChronosError } from '../errors';\n\nexport const MAX_HANDLER_NAME_LENGTH = 255;\nexport const MAX_POLL_WAIT_TIME_SECONDS = 20;\n\nexport function validateApiKey(apiKey: string | undefined): string {\n const trimmed = apiKey?.trim();\n if (!trimmed) {\n throw new ChronosConfigError('Chronos apiKey is required');\n }\n return trimmed;\n}\n\nexport function validatePollWaitTime(seconds: number): void {\n if (!Number.isInteger(seconds) || seconds < 0 || seconds > MAX_POLL_WAIT_TIME_SECONDS) {\n throw new ChronosConfigError(\n `pollWaitTimeSeconds must be an integer between 0 and ${MAX_POLL_WAIT_TIME_SECONDS}`,\n );\n }\n}\n\nexport function validateRetryDelayMs(ms: number): void {\n if (!Number.isFinite(ms) || ms < 0) {\n throw new ChronosConfigError('retryDelayMs must be a non-negative number');\n }\n}\n\n// setTimeout silently clamps delays above 2^31-1 to 1ms.\nexport const MAX_TIMEOUT_MS = 2_147_483_647;\n\nexport function validateTimeoutMs(ms: number): void {\n if (!Number.isInteger(ms) || ms <= 0 || ms > MAX_TIMEOUT_MS) {\n throw new ChronosConfigError(\n `timeoutMs must be a positive integer no greater than ${MAX_TIMEOUT_MS}`,\n );\n }\n}\n\nexport function validateWorkerId(id: string): string {\n const trimmed = id.trim();\n if (trimmed.length === 0 || trimmed.length > 255) {\n throw new ChronosConfigError('workerId must be 1-255 characters');\n }\n return trimmed;\n}\n\nexport function normalizeHandlerName(name: string): string {\n const normalized = name.trim();\n\n if (!normalized) {\n throw new ChronosError('Handler name is required');\n }\n\n if (normalized.length > MAX_HANDLER_NAME_LENGTH) {\n throw new ChronosError(`Handler name must be ${MAX_HANDLER_NAME_LENGTH} characters or fewer`);\n }\n\n return normalized;\n}\n","import {\n ChronosApiError,\n ChronosConfigError,\n ChronosError,\n ChronosNetworkError,\n ChronosRateLimitError,\n ChronosTimeoutError,\n type RateLimitInfo,\n} from './errors';\nimport { defaultLogger } from './internal/logger';\nimport { validateApiKey, validateTimeoutMs } from './internal/validate';\nimport type { ChronosLogger, ChronosOptions, FetchLike } from './types';\n\n/** Default Chronos API base URL. */\nexport const DEFAULT_BASE_URL = 'https://api.chronos.sh';\n\n/** Default per-request transport timeout in milliseconds. */\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\ntype ApiResponse<T> = {\n success: boolean;\n message?: string;\n code?: string;\n data: T;\n};\n\ntype RequestOptions = {\n signal?: AbortSignal;\n timeoutMs?: number;\n};\n\nexport class BaseClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly fetch: FetchLike;\n readonly logger: ChronosLogger;\n readonly timeoutMs: number;\n private readonly headers: Record<string, string>;\n\n constructor(options: ChronosOptions) {\n this.apiKey = validateApiKey(options.apiKey);\n this.baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL);\n this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.logger = options.logger ?? defaultLogger;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateTimeoutMs(this.timeoutMs);\n this.headers = {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.apiKey}`,\n };\n }\n\n async request<T>(\n path: string,\n body: Record<string, unknown>,\n options: RequestOptions = {},\n ): Promise<T> {\n const { signal } = options;\n const timeoutMs = options.timeoutMs ?? this.timeoutMs;\n\n // Not AbortSignal.any: Node pins each composite onto long-lived source\n // signals (like the poll signal) forever, leaking per claim.\n const controller = new AbortController();\n let timedOut = false;\n const timer = setTimeout(() => {\n if (controller.signal.aborted) {\n return;\n }\n timedOut = true;\n controller.abort(\n new DOMException(`Chronos API request timed out after ${timeoutMs}ms`, 'TimeoutError'),\n );\n }, timeoutMs);\n const onCallerAbort = () => controller.abort(signal?.reason);\n if (signal?.aborted) {\n onCallerAbort();\n } else {\n signal?.addEventListener('abort', onCallerAbort, { once: true });\n }\n\n try {\n let response: Response;\n try {\n response = await this.fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n if (signal?.aborted && !timedOut) {\n throw err;\n }\n if (timedOut) {\n throw timeoutError(timeoutMs, err);\n }\n const message = err instanceof Error ? err.message : String(err);\n throw new ChronosNetworkError(`Chronos API request failed: ${message}`, { cause: err });\n }\n\n // A half-open connection can stall after headers arrive, so the\n // timeout must cover the body read too.\n let payload: ApiResponse<T> | null;\n try {\n payload = (await response.json()) as ApiResponse<T>;\n } catch (err) {\n // Aborted-state check, not reason identity: some runtimes wrap the\n // abort reason during body reads.\n if (signal?.aborted && !timedOut) {\n throw err;\n }\n if (timedOut) {\n throw timeoutError(timeoutMs, err);\n }\n if (err instanceof SyntaxError) {\n payload = null;\n } else {\n const message = err instanceof Error ? err.message : String(err);\n throw new ChronosNetworkError(`Chronos API response failed: ${message}`, { cause: err });\n }\n }\n\n const envelope = isEnvelope(payload) ? (payload as ApiResponse<T>) : undefined;\n\n if (!response.ok || (envelope && !envelope.success)) {\n const is429 = response.status === 429;\n const retryAfterApplies = is429 || response.status >= 500;\n const ErrorClass = is429 ? ChronosRateLimitError : ChronosApiError;\n throw new ErrorClass(apiErrorMessage(response, envelope), {\n status: response.status,\n code: typeof envelope?.code === 'string' ? envelope.code : undefined,\n body: payload,\n requestId: response.headers.get('x-request-id') ?? undefined,\n retryAfterSeconds: retryAfterApplies\n ? parseIntHeader(response.headers, 'retry-after')\n : undefined,\n rateLimit: is429 ? undefined : parseRateLimitHeaders(response.headers),\n });\n }\n\n if (!envelope) {\n // Plain ChronosError, not ChronosApiError — a malformed 200 body is\n // an infrastructure anomaly that should be retried, not a definitive\n // API rejection.\n throw new ChronosError('Chronos API returned an invalid response');\n }\n\n return envelope.data;\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener('abort', onCallerAbort);\n }\n }\n}\n\nfunction timeoutError(timeoutMs: number, cause: unknown): ChronosTimeoutError {\n return new ChronosTimeoutError(`Chronos API request timed out after ${timeoutMs}ms`, { cause });\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n const normalized = baseUrl.trim().replace(/\\/+$/, '');\n if (!normalized) {\n throw new ChronosConfigError('Chronos baseUrl is required');\n }\n return normalized;\n}\n\nfunction apiErrorMessage(\n response: Response,\n envelope: Record<string, unknown> | undefined,\n): string {\n if (typeof envelope?.message === 'string' && envelope.message.trim()) {\n return envelope.message;\n }\n\n return response.ok\n ? 'Chronos API returned an invalid response'\n : `Chronos API request failed with status ${response.status}`;\n}\n\nfunction parseIntHeader(headers: Headers, name: string): number | undefined {\n const raw = headers.get(name);\n if (raw === null || !/^\\d+$/.test(raw)) {\n return undefined;\n }\n return Number.parseInt(raw, 10);\n}\n\nfunction parseRateLimitHeaders(headers: Headers): RateLimitInfo | undefined {\n const limit = parseIntHeader(headers, 'x-ratelimit-limit');\n const remaining = parseIntHeader(headers, 'x-ratelimit-remaining');\n const reset = parseIntHeader(headers, 'x-ratelimit-reset');\n\n if (limit === undefined || remaining === undefined || reset === undefined) {\n return undefined;\n }\n return { limit, remaining, reset };\n}\n\n// Malformed bodies (arrays, primitives, missing `success`) are routed to the\n// invalid-response path, not classified as API errors.\nfunction isEnvelope(value: unknown): value is Record<string, unknown> & { success: boolean } {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n return typeof (value as Record<string, unknown>).success === 'boolean';\n}\n","export function generateWorkerId(): string {\n const bytes = crypto.getRandomValues(new Uint8Array(8));\n let hex = '';\n for (const b of bytes) {\n hex += b.toString(16).padStart(2, '0');\n }\n return `w_${hex}`;\n}\n","export function detectRuntime(): string {\n const g = globalThis as unknown as Record<string, Record<string, unknown> | undefined>;\n\n if (g.Bun != null) {\n return `bun/${(g.Bun.version as string | undefined) ?? 'unknown'}`;\n }\n\n if (g.Deno != null) {\n const version = g.Deno.version as Record<string, string> | undefined;\n return `deno/${version?.deno ?? 'unknown'}`;\n }\n\n if (typeof process !== 'undefined' && process.versions?.node) {\n return `node/${process.versions.node}`;\n }\n\n return 'unknown';\n}\n","declare const __SDK_VERSION__: string;\n\nexport const SDK_VERSION: string = __SDK_VERSION__;\n","import type { BaseClient } from './client';\nimport { ChronosApiError, ChronosError, ChronosHandlerError, ChronosNetworkError } from './errors';\nimport { generateWorkerId } from './internal/id';\nimport { detectRuntime } from './internal/runtime';\nimport {\n MAX_TIMEOUT_MS,\n normalizeHandlerName,\n validatePollWaitTime,\n validateRetryDelayMs,\n validateWorkerId,\n} from './internal/validate';\nimport { SDK_VERSION } from './internal/version';\nimport type {\n ChronosContext,\n ChronosHandler,\n ChronosHandlerResult,\n ChronosOptions,\n ChronosSchedule,\n} from './types';\n\n/** Default worker long-poll wait time in seconds. Equal to the API maximum. */\nexport const DEFAULT_POLL_WAIT_TIME_SECONDS = 20;\nconst DEFAULT_RETRY_DELAY_MS = 1_000;\n// Retry-After on 5xx often comes from proxies/CDNs with browser-oriented\n// values (e.g. 3600); uncapped it would park the worker for hours.\nconst MAX_RETRY_AFTER_MS = 60_000;\nconst RESULT_REPORT_MAX_ATTEMPTS = 3;\nconst MAX_REPORTED_ERROR_LENGTH = 4_096;\nconst DEFAULT_HANDLER_ERROR = 'Chronos handler failed';\n\ntype ResultStatus = 'completed' | 'failed' | 'timeout';\n\ntype HandlerOutcome = { timedOut: false; result: ChronosHandlerResult } | { timedOut: true };\n\ntype ClaimedJob = {\n job_id: string;\n execution_id: string;\n handler: string;\n scheduled_for: string;\n attempt: number;\n timeout: number;\n payload: unknown;\n schedule: ChronosSchedule | null;\n};\n\n/**\n * Long-poll worker. Claims jobs from the Chronos API, dispatches them to\n * registered handlers, and reports results.\n *\n * Construct via `new Chronos({ apiKey }).worker` rather than directly.\n */\nexport class Worker {\n private readonly client: BaseClient;\n private readonly pollWaitTimeSeconds: number;\n private readonly retryDelayMs: number;\n private readonly workerId: string;\n private readonly runtime: string;\n private readonly handlers = new Map<string, ChronosHandler<unknown>>();\n private handlerNames: string[] = [];\n private startPromise?: Promise<void>;\n private pollController?: AbortController;\n private startedAt = 0;\n\n constructor(client: BaseClient, options: ChronosOptions) {\n this.client = client;\n this.pollWaitTimeSeconds = options.pollWaitTimeSeconds ?? DEFAULT_POLL_WAIT_TIME_SECONDS;\n this.retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n this.workerId =\n options.workerId !== undefined ? validateWorkerId(options.workerId) : generateWorkerId();\n this.runtime = detectRuntime();\n\n validatePollWaitTime(this.pollWaitTimeSeconds);\n validateRetryDelayMs(this.retryDelayMs);\n }\n\n /**\n * Register a handler for a named job type. Invoked when the Chronos API\n * claims a job whose `handler` field matches `name`. Names are trimmed and\n * must be 1–255 characters.\n *\n * @param name - Handler name. Must match the schedule's `handler` on the API side.\n * @param handler - Async function invoked with the job context. Return a\n * plain object to record a result, or `undefined` for none.\n * @returns The Worker, for chaining.\n * @throws {ChronosError} If the name is invalid, already registered, or `handler` is not a function.\n *\n * @example\n * ```ts\n * chronos.worker\n * .handle('send-email', async (ctx) => ({ sent: true }))\n * .handle('cleanup', async () => undefined);\n * ```\n */\n handle<TPayload = unknown>(name: string, handler: ChronosHandler<TPayload>): this {\n const normalizedName = normalizeHandlerName(name);\n\n if (this.handlers.has(normalizedName)) {\n throw new ChronosError(`Handler \"${normalizedName}\" is already registered`);\n }\n\n if (typeof handler !== 'function') {\n throw new ChronosError(`Handler \"${normalizedName}\" must be a function`);\n }\n\n this.handlers.set(normalizedName, handler as ChronosHandler<unknown>);\n this.handlerNames.push(normalizedName);\n return this;\n }\n\n /**\n * Begin long-polling for jobs. The returned promise resolves when\n * {@link Worker.stop} is called and any in-flight job completes, and\n * rejects if the API rejects the worker's credentials (a 401 with the\n * `unauthorized` error code) — a misconfigured key is not recoverable by\n * retrying.\n *\n * @throws {ChronosError} Synchronously, if no handlers are registered or the worker is already running.\n * @throws {ChronosApiError} Via the returned promise, when the API rejects the worker's credentials.\n */\n start(): Promise<void> {\n if (this.startPromise) {\n throw new ChronosError('Chronos worker is already started');\n }\n\n if (this.handlers.size === 0) {\n throw new ChronosError('Register at least one handler before starting Chronos');\n }\n\n this.startedAt = performance.now();\n this.pollController = new AbortController();\n this.startPromise = this.runLoop().finally(() => {\n this.startPromise = undefined;\n this.pollController = undefined;\n });\n\n return this.startPromise;\n }\n\n /**\n * Request graceful shutdown: abort the poll, let an in-flight handler\n * finish (up to its timeout) and report its result, then resolve. Bounded\n * by that timeout plus `timeoutMs` per report attempt. Never rejects; a\n * credential rejection surfaces on {@link Worker.start} instead.\n */\n stop(): Promise<void> {\n this.pollController?.abort();\n return this.startPromise ?? Promise.resolve();\n }\n\n private get isStopped(): boolean {\n return this.pollController?.signal.aborted ?? true;\n }\n\n private async runLoop(): Promise<void> {\n while (!this.isStopped) {\n try {\n const job = await this.claimJob();\n if (job) {\n await this.processJob(job);\n }\n } catch (err) {\n if (this.isStopped) {\n break;\n }\n\n if (err instanceof ChronosApiError && isCredentialRejection(err)) {\n this.client.logger.error('Chronos worker stopped; API rejected credentials', {\n err: errorToLogValue(err),\n });\n throw err;\n }\n\n this.client.logger.error('Chronos poll loop error', { err: errorToLogValue(err) });\n await sleep(retryDelayFor(err, this.retryDelayMs), this.pollController?.signal);\n }\n }\n }\n\n private async claimJob(): Promise<ClaimedJob | null> {\n if (this.handlerNames.length === 0) {\n throw new ChronosError('Cannot claim jobs without registered handlers');\n }\n\n return this.client.request<ClaimedJob | null>(\n '/v1/workers/jobs/claim',\n {\n wait_time_seconds: this.pollWaitTimeSeconds,\n handlers: this.handlerNames,\n worker: {\n id: this.workerId,\n sdk_version: SDK_VERSION,\n runtime: this.runtime,\n uptime_ms: Math.round(performance.now() - this.startedAt),\n },\n },\n {\n signal: this.pollController?.signal,\n // The intentional long-poll wait must not count against the\n // transport bound.\n timeoutMs: Math.min(\n this.pollWaitTimeSeconds * 1_000 + this.client.timeoutMs,\n MAX_TIMEOUT_MS,\n ),\n },\n );\n }\n\n private async processJob(job: ClaimedJob): Promise<void> {\n const handler = this.handlers.get(job.handler);\n if (!handler) {\n return this.handleUnregisteredJob(job);\n }\n\n const controller = new AbortController();\n let outcome: HandlerOutcome;\n try {\n outcome = await this.runHandlerWithTimeout(\n handler,\n createContext(job, controller.signal),\n job.timeout * 1_000,\n controller,\n );\n } catch (err) {\n const message = errorMessage(err);\n const handlerErr = new ChronosHandlerError(message, { cause: err });\n this.client.logger.error('Chronos handler failed', {\n ...jobLogMeta(job),\n err: errorToLogValue(handlerErr),\n });\n await this.safeReportFailed(job, message);\n return;\n }\n\n if (outcome.timedOut) {\n this.client.logger.error('Chronos handler timed out', {\n ...jobLogMeta(job),\n timeout: job.timeout,\n });\n try {\n await this.reportTimeout(job.execution_id);\n } catch (err) {\n this.logResultReportFailure(err, job, 'timeout');\n }\n return;\n }\n\n let result: Record<string, unknown> | undefined;\n try {\n result = normalizeHandlerResult(outcome.result);\n } catch (err) {\n this.client.logger.error('Chronos handler returned invalid result', {\n ...jobLogMeta(job),\n err: errorToLogValue(err),\n });\n await this.safeReportFailed(job, errorMessage(err));\n return;\n }\n\n try {\n await this.reportCompleted(job.execution_id, result);\n } catch (err) {\n this.logResultReportFailure(err, job, 'completed');\n }\n }\n\n private runHandlerWithTimeout(\n handler: ChronosHandler<unknown>,\n ctx: ChronosContext<unknown>,\n timeoutMs: number,\n controller: AbortController,\n ): Promise<HandlerOutcome> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const handlerPromise = Promise.resolve(handler(ctx)).then(\n (result): HandlerOutcome => ({ timedOut: false, result }),\n );\n handlerPromise.catch(() => {});\n\n const timeoutPromise = new Promise<HandlerOutcome>((resolve) => {\n timer = setTimeout(() => {\n controller.abort();\n resolve({ timedOut: true });\n }, timeoutMs);\n });\n\n return Promise.race([handlerPromise, timeoutPromise]).finally(() => {\n clearTimeout(timer);\n });\n }\n\n private async handleUnregisteredJob(job: ClaimedJob): Promise<void> {\n const message = `Chronos SDK received job for unregistered handler \"${job.handler}\"`;\n this.client.logger.error(message, jobLogMeta(job));\n await this.safeReportFailed(job, message);\n }\n\n private async safeReportFailed(job: ClaimedJob, message: string): Promise<void> {\n try {\n await this.reportFailed(job.execution_id, message);\n } catch (err) {\n this.logResultReportFailure(err, job, 'failed');\n }\n }\n\n private async reportCompleted(\n executionId: string,\n result: Record<string, unknown> | undefined,\n ): Promise<void> {\n await this.reportResultWithRetry(executionId, {\n status: 'completed',\n ...(result === undefined ? {} : { result }),\n });\n }\n\n private async reportTimeout(executionId: string): Promise<void> {\n await this.reportResultWithRetry(executionId, { status: 'timeout' });\n }\n\n private async reportFailed(executionId: string, error: string): Promise<void> {\n await this.reportResultWithRetry(executionId, {\n status: 'failed',\n error: truncate(error, MAX_REPORTED_ERROR_LENGTH),\n });\n }\n\n private async reportResultWithRetry(\n executionId: string,\n body: Record<string, unknown>,\n ): Promise<void> {\n let lastErr: unknown;\n\n for (let attempt = 1; attempt <= RESULT_REPORT_MAX_ATTEMPTS; attempt++) {\n try {\n await this.client.request(\n `/v1/workers/executions/${encodeURIComponent(executionId)}/result`,\n body,\n );\n return;\n } catch (err) {\n const apiErr = err instanceof ChronosApiError ? err : undefined;\n\n if (apiErr?.status === 409) {\n this.client.logger.warn('Chronos result discarded; execution already terminal', {\n executionId,\n status: body.status,\n code: apiErr.code,\n });\n return;\n }\n\n if (apiErr && isTerminalReportError(apiErr.status)) {\n throw apiErr;\n }\n\n lastErr = err;\n if (attempt === RESULT_REPORT_MAX_ATTEMPTS) {\n break;\n }\n\n this.client.logger.warn('Chronos result report failed; retrying', {\n err: errorToLogValue(err),\n executionId,\n status: body.status,\n attempt,\n maxAttempts: RESULT_REPORT_MAX_ATTEMPTS,\n });\n // The signal skips the wait after stop(), never the retry itself:\n // the report is still allowed to complete.\n await sleep(retryDelayFor(err, this.retryDelayMs), this.pollController?.signal);\n }\n }\n\n throw lastErr;\n }\n\n private logResultReportFailure(err: unknown, job: ClaimedJob, status: ResultStatus): void {\n const isTerminal = err instanceof ChronosApiError && isTerminalReportError(err.status);\n this.client.logger.error(\n isTerminal\n ? 'Chronos result report rejected by API'\n : 'Chronos result report failed after retries',\n { ...jobLogMeta(job), err: errorToLogValue(err), status },\n );\n }\n}\n\nfunction createContext(job: ClaimedJob, signal: AbortSignal): ChronosContext<unknown> {\n return {\n jobId: job.job_id,\n executionId: job.execution_id,\n handler: job.handler,\n payload: job.payload,\n scheduledFor: new Date(job.scheduled_for),\n attempt: job.attempt,\n timeout: job.timeout,\n signal,\n schedule: job.schedule,\n };\n}\n\nfunction jobLogMeta(job: ClaimedJob): Record<string, unknown> {\n return {\n jobId: job.job_id,\n executionId: job.execution_id,\n handler: job.handler,\n };\n}\n\nfunction normalizeHandlerResult(result: ChronosHandlerResult): Record<string, unknown> | undefined {\n if (result === undefined) {\n return undefined;\n }\n\n if (!isPlainObject(result)) {\n throw new ChronosError('Chronos handler result must be a plain object or undefined');\n }\n\n try {\n JSON.stringify(result);\n } catch (err) {\n const reason = err instanceof Error ? err.message : 'value is not JSON-encodable';\n throw new ChronosError(`Chronos handler result is not JSON-encodable: ${reason}`);\n }\n\n return result;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction errorMessage(err: unknown): string {\n const message = err instanceof Error ? err.message : String(err);\n return message.trim() || DEFAULT_HANDLER_ERROR;\n}\n\nfunction errorToLogValue(err: unknown): unknown {\n if (!(err instanceof Error)) {\n return err;\n }\n\n const base = { name: err.name, message: err.message, stack: err.stack };\n\n if (err instanceof ChronosApiError) {\n return {\n ...base,\n status: err.status,\n code: err.code,\n requestId: err.requestId,\n ...(err.retryAfterSeconds !== undefined && { retryAfterSeconds: err.retryAfterSeconds }),\n ...(err.rateLimit !== undefined && { rateLimit: err.rateLimit }),\n };\n }\n if (err instanceof ChronosNetworkError || err instanceof ChronosHandlerError) {\n return { ...base, cause: errorToLogValue(err.cause) };\n }\n return base;\n}\n\nfunction truncate(value: string, maxLength: number): string {\n return value.length <= maxLength ? value : value.slice(0, maxLength);\n}\n\n// Floored at fallbackMs: a proxy's Retry-After: 0 would otherwise hot-loop\n// against a down origin.\nfunction retryDelayFor(err: unknown, fallbackMs: number): number {\n if (err instanceof ChronosApiError && err.retryAfterSeconds !== undefined) {\n return Math.max(Math.min(err.retryAfterSeconds * 1_000, MAX_RETRY_AFTER_MS), fallbackMs);\n }\n return fallbackMs;\n}\n\nfunction isCredentialRejection(err: ChronosApiError): boolean {\n return err.status === 401 && err.code === 'unauthorized';\n}\n\n// 409 is handled by the caller before reaching here; 408/429 are transient.\nconst NON_TERMINAL_4XX = new Set([408, 409, 429]);\n\n// 200 reaches here only via an explicit `{ success: false }` envelope from BaseClient.\nfunction isTerminalReportError(status: number): boolean {\n if (status === 200) {\n return true;\n }\n if (NON_TERMINAL_4XX.has(status)) {\n return false;\n }\n return status >= 400 && status < 500;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n const timeout: ReturnType<typeof setTimeout> = setTimeout(done, ms);\n\n function done() {\n clearTimeout(timeout);\n signal?.removeEventListener('abort', done);\n resolve();\n }\n\n signal?.addEventListener('abort', done, { once: true });\n });\n}\n","import { ChronosWebhookVerificationError } from './errors';\nimport type { WebhookOptions } from './types';\n\nexport const DEFAULT_TIMESTAMP_TOLERANCE_SECONDS = 300;\n\nconst SIGNATURE_PREFIX = 'sha256=';\nconst REQUIRED_HEADERS = [\n 'x-chronos-signature',\n 'x-chronos-timestamp',\n 'x-chronos-delivery-id',\n] as const;\n\n/**\n * Verifies webhook signatures on Chronos push deliveries.\n *\n * @example\n * ```ts\n * import { Webhook } from '@chronos.sh/sdk';\n *\n * const wh = new Webhook(process.env.CHRONOS_SIGNING_SECRET!);\n *\n * // In your request handler:\n * const payload = await wh.verify(rawBody, {\n * 'x-chronos-signature': req.headers['x-chronos-signature'],\n * 'x-chronos-timestamp': req.headers['x-chronos-timestamp'],\n * 'x-chronos-delivery-id': req.headers['x-chronos-delivery-id'],\n * });\n * ```\n */\nexport class Webhook {\n private readonly secrets: string[];\n private readonly toleranceSeconds: number;\n private keysPromise?: Promise<CryptoKey[]>;\n\n /**\n * @param secret - Signing secret or array of secrets (for key rotation).\n * @param options - Optional configuration.\n * @throws {ChronosWebhookVerificationError} If no valid secret is provided.\n */\n constructor(secret: string | string[], options?: WebhookOptions) {\n const secrets = Array.isArray(secret) ? secret : [secret];\n this.secrets = secrets\n .filter((s) => typeof s === 'string' && s.trim().length > 0)\n .map((s) => s.trim());\n\n if (this.secrets.length === 0) {\n throw new ChronosWebhookVerificationError(\n 'At least one non-empty signing secret is required',\n );\n }\n\n const tolerance = options?.toleranceSeconds ?? DEFAULT_TIMESTAMP_TOLERANCE_SECONDS;\n if (!Number.isFinite(tolerance) || tolerance < 0) {\n throw new ChronosWebhookVerificationError(\n 'toleranceSeconds must be a finite non-negative number',\n );\n }\n this.toleranceSeconds = tolerance;\n }\n\n /**\n * Verifies the webhook signature and returns the parsed request body.\n *\n * @param body - Raw request body as a string. Must be the exact bytes received — not re-serialized.\n * @param headers - Request headers. Keys are matched case-insensitively.\n * @returns The parsed JSON body on successful verification.\n * @throws {ChronosWebhookVerificationError} If any verification step fails.\n */\n async verify(\n body: string,\n headers: Record<string, string | undefined> | Headers,\n ): Promise<unknown> {\n const normalized = normalizeHeaders(headers);\n\n for (const name of REQUIRED_HEADERS) {\n const value = normalized[name];\n if (!value || typeof value !== 'string') {\n throw new ChronosWebhookVerificationError(`Missing required header: ${name}`);\n }\n }\n\n const signature = normalized['x-chronos-signature'] as string;\n const timestamp = normalized['x-chronos-timestamp'] as string;\n const deliveryId = normalized['x-chronos-delivery-id'] as string;\n\n if (!/^[0-9]+$/.test(timestamp)) {\n throw new ChronosWebhookVerificationError('Invalid timestamp');\n }\n\n const ts = Number(timestamp);\n if (ts <= 0) {\n throw new ChronosWebhookVerificationError('Invalid timestamp');\n }\n\n const now = Math.floor(Date.now() / 1000);\n const isStale = Math.abs(now - ts) > this.toleranceSeconds;\n if (this.toleranceSeconds > 0 && isStale) {\n throw new ChronosWebhookVerificationError('Timestamp outside tolerance');\n }\n\n if (!signature.startsWith(SIGNATURE_PREFIX)) {\n throw new ChronosWebhookVerificationError(\n `Invalid signature format: expected ${SIGNATURE_PREFIX}<hex>`,\n );\n }\n\n const expectedHex = signature.slice(SIGNATURE_PREFIX.length);\n if (expectedHex.length === 0) {\n throw new ChronosWebhookVerificationError(\n 'Invalid signature: expected 32-byte SHA-256 digest',\n );\n }\n\n let expectedBytes: ArrayBuffer;\n try {\n expectedBytes = hexDecode(expectedHex);\n } catch {\n throw new ChronosWebhookVerificationError('Invalid signature: malformed hex');\n }\n\n if (expectedBytes.byteLength !== 32) {\n throw new ChronosWebhookVerificationError(\n 'Invalid signature: expected 32-byte SHA-256 digest',\n );\n }\n\n const signedPayload = `${deliveryId}.${timestamp}.${body}`;\n const data = new TextEncoder().encode(signedPayload);\n\n try {\n const keys = await this.ensureKeys();\n for (const key of keys) {\n const valid = await globalThis.crypto.subtle.verify('HMAC', key, expectedBytes, data);\n if (valid) {\n try {\n return JSON.parse(body);\n } catch {\n throw new ChronosWebhookVerificationError('Verified payload is not valid JSON');\n }\n }\n }\n } catch (err) {\n if (err instanceof ChronosWebhookVerificationError) {\n throw err;\n }\n throw new ChronosWebhookVerificationError('Signature verification failed');\n }\n\n throw new ChronosWebhookVerificationError('Signature verification failed');\n }\n\n private ensureKeys(): Promise<CryptoKey[]> {\n if (!this.keysPromise) {\n const encoder = new TextEncoder();\n this.keysPromise = Promise.all(\n this.secrets.map((s) =>\n globalThis.crypto.subtle.importKey(\n 'raw',\n encoder.encode(s),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['verify'],\n ),\n ),\n );\n }\n return this.keysPromise;\n }\n}\n\nfunction normalizeHeaders(\n headers: Record<string, string | undefined> | Headers,\n): Record<string, string | undefined> {\n const result: Record<string, string | undefined> = {};\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n result[key.toLowerCase()] = value;\n });\n } else {\n for (const key of Object.keys(headers)) {\n result[key.toLowerCase()] = headers[key];\n }\n }\n return result;\n}\n\nfunction hexDecode(hex: string): ArrayBuffer {\n if (hex.length % 2 !== 0 || !/^[0-9a-f]+$/i.test(hex)) {\n throw new Error('Invalid hex string');\n }\n const length = hex.length / 2;\n const buffer = new ArrayBuffer(length);\n const view = new DataView(buffer);\n for (let i = 0; i < length; i++) {\n view.setUint8(i, Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16));\n }\n return buffer;\n}\n","import { BaseClient, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS } from './client';\nimport type { ChronosOptions } from './types';\nimport { DEFAULT_POLL_WAIT_TIME_SECONDS, Worker } from './worker';\n\n/**\n * The Chronos SDK client. Composes worker and (future) REST resource\n * subclients from a single instance.\n *\n * @example\n * ```ts\n * import { Chronos } from '@chronos.sh/sdk';\n *\n * const chronos = new Chronos({ apiKey: process.env.CHRONOS_API_KEY! });\n *\n * chronos.worker.handle<{ to: string }>('send-email', async (ctx) => {\n * await sendEmail(ctx.payload.to);\n * return { sent: true };\n * });\n *\n * await chronos.worker.start();\n * ```\n */\nexport class Chronos {\n /** Long-poll worker for executing pull-mode jobs. */\n readonly worker: Worker;\n\n /**\n * @param options - Client configuration. Only `apiKey` is required.\n * @throws {ChronosConfigError} If `apiKey` is missing or any option fails validation.\n */\n constructor(options: ChronosOptions) {\n const client = new BaseClient(options);\n this.worker = new Worker(client, options);\n }\n}\n\nexport {\n ChronosApiError,\n type ChronosApiErrorOptions,\n ChronosConfigError,\n ChronosError,\n ChronosHandlerError,\n ChronosNetworkError,\n ChronosRateLimitError,\n ChronosTimeoutError,\n ChronosWebhookVerificationError,\n type RateLimitInfo,\n} from './errors';\nexport { SDK_VERSION } from './internal/version';\nexport type {\n ChronosContext,\n ChronosHandler,\n ChronosHandlerResult,\n ChronosLogger,\n ChronosOptions,\n ChronosSchedule,\n FetchLike,\n WebhookOptions,\n} from './types';\nexport { DEFAULT_TIMESTAMP_TOLERANCE_SECONDS, Webhook } from './webhook';\nexport { DEFAULT_BASE_URL, DEFAULT_POLL_WAIT_TIME_SECONDS, DEFAULT_TIMEOUT_MS };\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chronos.sh/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.2-canary.2deb3ad",
4
4
  "description": "Chronos JavaScript/TypeScript SDK",
5
5
  "license": "MIT",
6
6
  "keywords": [