@simpleq/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,91 @@
1
+ /** Lifecycle status of a job. */
2
+ type JobStatus = 'pending' | 'processing' | 'awaiting_ack' | 'completed' | 'failed' | 'dead';
3
+ /** Outcome of a single delivery attempt. */
4
+ type JobAttemptStatus = 'success' | 'failed' | 'nacked' | 'deferred';
5
+ /** The JSON envelope SimpleQ POSTs to your webhook. Your data is under `payload`. */
6
+ interface WebhookPayload {
7
+ id: string;
8
+ queue: string;
9
+ payload: Record<string, unknown>;
10
+ attempt: number;
11
+ maxAttempts: number;
12
+ createdAt: string;
13
+ }
14
+ /** Body of `POST /v1/queues/:queueName/jobs`. */
15
+ interface PublishJobRequest {
16
+ payload: Record<string, unknown>;
17
+ idempotencyKey?: string;
18
+ /** Seconds (0–86400). */
19
+ delay?: number;
20
+ }
21
+ /** Response of a publish: `201` created or `200` idempotent hit. */
22
+ interface PublishJobResponse {
23
+ id: string;
24
+ status: JobStatus;
25
+ createdAt: string;
26
+ }
27
+ /** A single delivery attempt, as returned by `getJob`. Timestamps are ISO-8601 strings. */
28
+ interface JobAttempt {
29
+ attempt: number;
30
+ status: JobAttemptStatus;
31
+ error: string | null;
32
+ webhookStatusCode: number | null;
33
+ timestamp: string;
34
+ }
35
+ /** A job as returned by `GET /v1/jobs/:id`. Timestamps are ISO-8601 strings. */
36
+ interface Job {
37
+ id: string;
38
+ /** The queue name. */
39
+ queue: string;
40
+ status: JobStatus;
41
+ attempts: number;
42
+ maxAttempts: number;
43
+ idempotencyKey: string | null;
44
+ payload: Record<string, unknown>;
45
+ scheduledFor: string;
46
+ lastError: string | null;
47
+ history: JobAttempt[];
48
+ createdAt: string;
49
+ completedAt: string | null;
50
+ }
51
+ /** Response of the ack / nack / defer callbacks. */
52
+ interface AckResponse {
53
+ id: string;
54
+ accepted: true;
55
+ }
56
+ interface SimpleQOptions {
57
+ /** API key. Defaults to `process.env.SIMPLEQ_API_KEY`. */
58
+ apiKey?: string;
59
+ /** Base URL of the SimpleQ API. Defaults to `https://api.simpleq.io`. */
60
+ baseUrl?: string;
61
+ /** Per-request timeout in seconds. Defaults to `30`. */
62
+ timeout?: number;
63
+ /** Max automatic retries for transient failures (network / 5xx / 429). Defaults to `2`. */
64
+ maxRetries?: number;
65
+ /** Custom fetch implementation (for testing or non-global environments). */
66
+ fetch?: typeof fetch;
67
+ }
68
+ interface PublishParams {
69
+ /** Arbitrary JSON delivered verbatim to the queue's webhook. */
70
+ payload: Record<string, unknown>;
71
+ /**
72
+ * Dedupe key (≤255 chars) for cross-call deduplication: publishing again with the same key
73
+ * returns the original job. Omit it and `publish` generates one per call and reuses it across
74
+ * the SDK's automatic retries, so a retried request can never create a duplicate job.
75
+ */
76
+ idempotencyKey?: string;
77
+ /** Delay first delivery by this many seconds (0–86400). */
78
+ delay?: number;
79
+ }
80
+ interface NackOptions {
81
+ /** `true` (default) re-queues with backoff; `false` dead-letters immediately. */
82
+ retryable?: boolean;
83
+ reason?: string;
84
+ }
85
+ interface DeferOptions {
86
+ /** Hold the job for this many seconds, then redeliver without burning an attempt (0–3600). */
87
+ retryAfter: number;
88
+ reason?: string;
89
+ }
90
+
91
+ export type { AckResponse as A, DeferOptions as D, Job as J, NackOptions as N, PublishParams as P, SimpleQOptions as S, WebhookPayload as W, PublishJobResponse as a, JobAttempt as b, JobAttemptStatus as c, JobStatus as d, PublishJobRequest as e };
@@ -0,0 +1,91 @@
1
+ /** Lifecycle status of a job. */
2
+ type JobStatus = 'pending' | 'processing' | 'awaiting_ack' | 'completed' | 'failed' | 'dead';
3
+ /** Outcome of a single delivery attempt. */
4
+ type JobAttemptStatus = 'success' | 'failed' | 'nacked' | 'deferred';
5
+ /** The JSON envelope SimpleQ POSTs to your webhook. Your data is under `payload`. */
6
+ interface WebhookPayload {
7
+ id: string;
8
+ queue: string;
9
+ payload: Record<string, unknown>;
10
+ attempt: number;
11
+ maxAttempts: number;
12
+ createdAt: string;
13
+ }
14
+ /** Body of `POST /v1/queues/:queueName/jobs`. */
15
+ interface PublishJobRequest {
16
+ payload: Record<string, unknown>;
17
+ idempotencyKey?: string;
18
+ /** Seconds (0–86400). */
19
+ delay?: number;
20
+ }
21
+ /** Response of a publish: `201` created or `200` idempotent hit. */
22
+ interface PublishJobResponse {
23
+ id: string;
24
+ status: JobStatus;
25
+ createdAt: string;
26
+ }
27
+ /** A single delivery attempt, as returned by `getJob`. Timestamps are ISO-8601 strings. */
28
+ interface JobAttempt {
29
+ attempt: number;
30
+ status: JobAttemptStatus;
31
+ error: string | null;
32
+ webhookStatusCode: number | null;
33
+ timestamp: string;
34
+ }
35
+ /** A job as returned by `GET /v1/jobs/:id`. Timestamps are ISO-8601 strings. */
36
+ interface Job {
37
+ id: string;
38
+ /** The queue name. */
39
+ queue: string;
40
+ status: JobStatus;
41
+ attempts: number;
42
+ maxAttempts: number;
43
+ idempotencyKey: string | null;
44
+ payload: Record<string, unknown>;
45
+ scheduledFor: string;
46
+ lastError: string | null;
47
+ history: JobAttempt[];
48
+ createdAt: string;
49
+ completedAt: string | null;
50
+ }
51
+ /** Response of the ack / nack / defer callbacks. */
52
+ interface AckResponse {
53
+ id: string;
54
+ accepted: true;
55
+ }
56
+ interface SimpleQOptions {
57
+ /** API key. Defaults to `process.env.SIMPLEQ_API_KEY`. */
58
+ apiKey?: string;
59
+ /** Base URL of the SimpleQ API. Defaults to `https://api.simpleq.io`. */
60
+ baseUrl?: string;
61
+ /** Per-request timeout in seconds. Defaults to `30`. */
62
+ timeout?: number;
63
+ /** Max automatic retries for transient failures (network / 5xx / 429). Defaults to `2`. */
64
+ maxRetries?: number;
65
+ /** Custom fetch implementation (for testing or non-global environments). */
66
+ fetch?: typeof fetch;
67
+ }
68
+ interface PublishParams {
69
+ /** Arbitrary JSON delivered verbatim to the queue's webhook. */
70
+ payload: Record<string, unknown>;
71
+ /**
72
+ * Dedupe key (≤255 chars) for cross-call deduplication: publishing again with the same key
73
+ * returns the original job. Omit it and `publish` generates one per call and reuses it across
74
+ * the SDK's automatic retries, so a retried request can never create a duplicate job.
75
+ */
76
+ idempotencyKey?: string;
77
+ /** Delay first delivery by this many seconds (0–86400). */
78
+ delay?: number;
79
+ }
80
+ interface NackOptions {
81
+ /** `true` (default) re-queues with backoff; `false` dead-letters immediately. */
82
+ retryable?: boolean;
83
+ reason?: string;
84
+ }
85
+ interface DeferOptions {
86
+ /** Hold the job for this many seconds, then redeliver without burning an attempt (0–3600). */
87
+ retryAfter: number;
88
+ reason?: string;
89
+ }
90
+
91
+ export type { AckResponse as A, DeferOptions as D, Job as J, NackOptions as N, PublishParams as P, SimpleQOptions as S, WebhookPayload as W, PublishJobResponse as a, JobAttempt as b, JobAttemptStatus as c, JobStatus as d, PublishJobRequest as e };
@@ -0,0 +1,46 @@
1
+ 'use strict';
2
+
3
+ var crypto = require('crypto');
4
+
5
+ // src/webhooks.ts
6
+
7
+ // src/errors.ts
8
+ var SimpleQError = class extends Error {
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = this.constructor.name;
12
+ }
13
+ };
14
+ var SignatureVerificationError = class extends SimpleQError {
15
+ };
16
+
17
+ // src/webhooks.ts
18
+ var SIGNATURE_HEADER = "x-simpleq-signature";
19
+ function toBuffer(rawBody) {
20
+ if (typeof rawBody === "string") return Buffer.from(rawBody, "utf8");
21
+ if (Buffer.isBuffer(rawBody)) return rawBody;
22
+ return Buffer.from(rawBody);
23
+ }
24
+ function expectedSignature(rawBody, signingSecret) {
25
+ return "sha256=" + crypto.createHmac("sha256", signingSecret).update(toBuffer(rawBody)).digest("hex");
26
+ }
27
+ function verifyWebhookSignature(rawBody, signatureHeader, signingSecret) {
28
+ if (!signatureHeader) return false;
29
+ const expected = Buffer.from(expectedSignature(rawBody, signingSecret));
30
+ const received = Buffer.from(signatureHeader);
31
+ if (expected.length !== received.length) return false;
32
+ return crypto.timingSafeEqual(expected, received);
33
+ }
34
+ function verifyWebhook(rawBody, signatureHeader, signingSecret) {
35
+ if (!verifyWebhookSignature(rawBody, signatureHeader, signingSecret)) {
36
+ throw new SignatureVerificationError("SimpleQ webhook signature verification failed");
37
+ }
38
+ const text = typeof rawBody === "string" ? rawBody : toBuffer(rawBody).toString("utf8");
39
+ return JSON.parse(text);
40
+ }
41
+
42
+ exports.SIGNATURE_HEADER = SIGNATURE_HEADER;
43
+ exports.verifyWebhook = verifyWebhook;
44
+ exports.verifyWebhookSignature = verifyWebhookSignature;
45
+ //# sourceMappingURL=webhooks.cjs.map
46
+ //# sourceMappingURL=webhooks.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/webhooks.ts"],"names":["createHmac","timingSafeEqual"],"mappings":";;;;;;;AAGO,IAAM,YAAA,GAAN,cAA2B,KAAA,CAAM;AAAA,EACtC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,KAAK,WAAA,CAAY,IAAA;AAAA,EAC/B;AACF,CAAA;AAMO,IAAM,0BAAA,GAAN,cAAyC,YAAA,CAAa;AAAC,CAAA;;;ACPvD,IAAM,gBAAA,GAAmB;AAEhC,SAAS,SAAS,OAAA,EAA+C;AAC/D,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,SAAiB,MAAA,CAAO,IAAA,CAAK,SAAS,MAAM,CAAA;AACnE,EAAA,IAAI,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA,EAAG,OAAO,OAAA;AACrC,EAAA,OAAO,MAAA,CAAO,KAAK,OAAO,CAAA;AAC5B;AAEA,SAAS,iBAAA,CAAkB,SAAuC,aAAA,EAA+B;AAC/F,EAAA,OAAO,SAAA,GAAYA,iBAAA,CAAW,QAAA,EAAU,aAAa,CAAA,CAAE,MAAA,CAAO,QAAA,CAAS,OAAO,CAAC,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AAC/F;AAQO,SAAS,sBAAA,CACd,OAAA,EACA,eAAA,EACA,aAAA,EACS;AACT,EAAA,IAAI,CAAC,iBAAiB,OAAO,KAAA;AAC7B,EAAA,MAAM,WAAW,MAAA,CAAO,IAAA,CAAK,iBAAA,CAAkB,OAAA,EAAS,aAAa,CAAC,CAAA;AACtE,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,IAAA,CAAK,eAAe,CAAA;AAE5C,EAAA,IAAI,QAAA,CAAS,MAAA,KAAW,QAAA,CAAS,MAAA,EAAQ,OAAO,KAAA;AAChD,EAAA,OAAOC,sBAAA,CAAgB,UAAU,QAAQ,CAAA;AAC3C;AAQO,SAAS,aAAA,CACd,OAAA,EACA,eAAA,EACA,aAAA,EACgB;AAChB,EAAA,IAAI,CAAC,sBAAA,CAAuB,OAAA,EAAS,eAAA,EAAiB,aAAa,CAAA,EAAG;AACpE,IAAA,MAAM,IAAI,2BAA2B,+CAA+C,CAAA;AAAA,EACtF;AACA,EAAA,MAAM,IAAA,GAAO,OAAO,OAAA,KAAY,QAAA,GAAW,UAAU,QAAA,CAAS,OAAO,CAAA,CAAE,QAAA,CAAS,MAAM,CAAA;AACtF,EAAA,OAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AACxB","file":"webhooks.cjs","sourcesContent":["// Error and signal types for @simpleq/sdk.\n\n/** Base class for everything thrown by the SDK. Catch this to handle any SimpleQ error. */\nexport class SimpleQError extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\n/** A network failure, timeout, or aborted request — retryable. */\nexport class SimpleQConnectionError extends SimpleQError {}\n\n/** Thrown by `verifyWebhook` when a webhook signature does not verify. */\nexport class SignatureVerificationError extends SimpleQError {}\n\nexport type BackpressureStatus = 429 | 503 | 529;\n\n/**\n * A backpressure signal — not a failure. Throw this from a standard-mode webhook handler to\n * tell the adapter to respond with `429`/`503`/`529` and a `Retry-After`. SimpleQ then holds\n * the job and redelivers it without burning a delivery attempt.\n */\nexport class SimpleQBackpressure extends SimpleQError {\n /** Seconds to hold the job before redelivery. Omit to let SimpleQ pick its fallback. */\n readonly retryAfter?: number;\n /** HTTP status the adapter responds with. Defaults to `503`. */\n readonly status: BackpressureStatus;\n\n constructor(retryAfter?: number, options?: { status?: BackpressureStatus; reason?: string }) {\n const detail = retryAfter != null ? ` (retry after ${retryAfter}s)` : '';\n super(options?.reason ?? `SimpleQ backpressure${detail}`);\n this.retryAfter = retryAfter;\n this.status = options?.status ?? 503;\n }\n\n /**\n * Build a backpressure signal directly from a provider error (Anthropic, OpenAI, any\n * HTTP-shaped error). Reads `err.status` (429/503/529 pass through; anything else maps\n * to 503) and the `Retry-After` header in seconds from `err.headers` or\n * `err.response.headers` (plain object or Headers). When no header is present,\n * `options.fallback` seconds is used; with neither, SimpleQ applies its own 60s hold.\n */\n static from(err: unknown, options?: { fallback?: number; reason?: string }): SimpleQBackpressure {\n const e = err as { status?: unknown; message?: unknown } | null | undefined;\n const status: BackpressureStatus =\n e?.status === 429 || e?.status === 503 || e?.status === 529 ? e.status : 503;\n const retryAfter = retryAfterSeconds(err) ?? options?.fallback;\n const reason =\n options?.reason ?? (typeof e?.message === 'string' && e.message ? e.message : undefined);\n return new SimpleQBackpressure(retryAfter, { status, reason });\n }\n}\n\nfunction readHeader(headers: unknown, name: string): string | undefined {\n if (!headers || typeof headers !== 'object') return undefined;\n if (typeof (headers as Headers).get === 'function') {\n return (headers as Headers).get(name) ?? undefined;\n }\n const record = headers as Record<string, unknown>;\n const value = record[name.toLowerCase()] ?? record['Retry-After'];\n return typeof value === 'string' ? value : undefined;\n}\n\n/**\n * Read the `Retry-After` value, in **seconds**, from a provider error (Anthropic, OpenAI, any\n * HTTP-shaped error). Looks at `err.headers` and `err.response.headers` (plain object or a\n * `Headers` instance). Returns `undefined` when the header is absent or non-numeric (e.g. an\n * HTTP-date). Pair with `simpleq.defer` in ack mode: `defer(id, { retryAfter: retryAfterSeconds(err) ?? 10 })`.\n */\nexport function retryAfterSeconds(err: unknown): number | undefined {\n const e = err as { headers?: unknown; response?: { headers?: unknown } } | null | undefined;\n const raw =\n readHeader(e?.headers, 'retry-after') ?? readHeader(e?.response?.headers, 'retry-after');\n if (raw === undefined) return undefined;\n const seconds = Number(raw);\n return Number.isFinite(seconds) && seconds >= 0 ? seconds : undefined;\n}\n\n/** Any non-2xx response from the SimpleQ API. */\nexport class ApiError extends SimpleQError {\n readonly status: number;\n readonly body: unknown;\n\n constructor(message: string, status: number, body: unknown) {\n super(message);\n this.status = status;\n this.body = body;\n }\n}\n\n/** `401`/`403` — the API key is missing, invalid, or revoked. */\nexport class AuthenticationError extends ApiError {}\n\n/** `400` — request validation failed. `body.error` carries the field-level details. */\nexport class ValidationError extends ApiError {}\n\n/** `404` — the queue or job was not found. */\nexport class NotFoundError extends ApiError {}\n\n/** `429` — rate limited. `retryAfter` is the `Retry-After` header in seconds, if present. */\nexport class RateLimitError extends ApiError {\n readonly retryAfter?: number;\n\n constructor(message: string, status: number, body: unknown, retryAfter?: number) {\n super(message, status, body);\n this.retryAfter = retryAfter;\n }\n}\n\nfunction extractMessage(status: number, body: unknown): string {\n if (body && typeof body === 'object' && 'error' in body) {\n const err = (body as { error: unknown }).error;\n if (typeof err === 'string') return err;\n if (err && typeof err === 'object') return `Validation failed: ${JSON.stringify(err)}`;\n }\n return `SimpleQ API error (HTTP ${status})`;\n}\n\n/** Map an HTTP status + parsed body to the right ApiError subclass. */\nexport function mapApiError(status: number, body: unknown, headers?: Headers): ApiError {\n const message = extractMessage(status, body);\n switch (status) {\n case 400:\n return new ValidationError(message, status, body);\n case 401:\n case 403:\n return new AuthenticationError(message, status, body);\n case 404:\n return new NotFoundError(message, status, body);\n case 429: {\n const raw = headers?.get('retry-after');\n const retryAfter = raw != null ? Number(raw) : NaN;\n return new RateLimitError(message, status, body, Number.isFinite(retryAfter) ? retryAfter : undefined);\n }\n default:\n return new ApiError(message, status, body);\n }\n}\n","// Standalone webhook verification — no API key or client required. Importable as\n// `@simpleq/sdk/webhooks` with only `node:crypto` pulled in.\nimport { createHmac, timingSafeEqual } from 'node:crypto';\nimport { SignatureVerificationError } from './errors.js';\nimport type { WebhookPayload } from './types.js';\n\n/** The header SimpleQ sends with every webhook delivery. */\nexport const SIGNATURE_HEADER = 'x-simpleq-signature';\n\nfunction toBuffer(rawBody: string | Buffer | Uint8Array): Buffer {\n if (typeof rawBody === 'string') return Buffer.from(rawBody, 'utf8');\n if (Buffer.isBuffer(rawBody)) return rawBody;\n return Buffer.from(rawBody);\n}\n\nfunction expectedSignature(rawBody: string | Buffer | Uint8Array, signingSecret: string): string {\n return 'sha256=' + createHmac('sha256', signingSecret).update(toBuffer(rawBody)).digest('hex');\n}\n\n/**\n * Verify the `x-simpleq-signature` header against the raw request body, in constant time.\n * Returns a boolean and never throws — a missing or malformed header simply returns `false`.\n *\n * Always pass the *raw* body bytes (a string or Buffer), never a re-serialized parsed object.\n */\nexport function verifyWebhookSignature(\n rawBody: string | Buffer | Uint8Array,\n signatureHeader: string | null | undefined,\n signingSecret: string,\n): boolean {\n if (!signatureHeader) return false;\n const expected = Buffer.from(expectedSignature(rawBody, signingSecret));\n const received = Buffer.from(signatureHeader);\n // timingSafeEqual throws on differing lengths — guard before the constant-time compare.\n if (expected.length !== received.length) return false;\n return timingSafeEqual(expected, received);\n}\n\n/**\n * Verify the signature and return the parsed, typed webhook envelope (the equivalent of\n * Stripe's `constructEvent`). Throws `SignatureVerificationError` if the signature does\n * not match — the body is only parsed after verification passes, so a tampered payload\n * never reaches `JSON.parse`.\n */\nexport function verifyWebhook(\n rawBody: string | Buffer | Uint8Array,\n signatureHeader: string | null | undefined,\n signingSecret: string,\n): WebhookPayload {\n if (!verifyWebhookSignature(rawBody, signatureHeader, signingSecret)) {\n throw new SignatureVerificationError('SimpleQ webhook signature verification failed');\n }\n const text = typeof rawBody === 'string' ? rawBody : toBuffer(rawBody).toString('utf8');\n return JSON.parse(text) as WebhookPayload;\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import { W as WebhookPayload } from './types-eDJHwexZ.cjs';
2
+
3
+ /** The header SimpleQ sends with every webhook delivery. */
4
+ declare const SIGNATURE_HEADER = "x-simpleq-signature";
5
+ /**
6
+ * Verify the `x-simpleq-signature` header against the raw request body, in constant time.
7
+ * Returns a boolean and never throws — a missing or malformed header simply returns `false`.
8
+ *
9
+ * Always pass the *raw* body bytes (a string or Buffer), never a re-serialized parsed object.
10
+ */
11
+ declare function verifyWebhookSignature(rawBody: string | Buffer | Uint8Array, signatureHeader: string | null | undefined, signingSecret: string): boolean;
12
+ /**
13
+ * Verify the signature and return the parsed, typed webhook envelope (the equivalent of
14
+ * Stripe's `constructEvent`). Throws `SignatureVerificationError` if the signature does
15
+ * not match — the body is only parsed after verification passes, so a tampered payload
16
+ * never reaches `JSON.parse`.
17
+ */
18
+ declare function verifyWebhook(rawBody: string | Buffer | Uint8Array, signatureHeader: string | null | undefined, signingSecret: string): WebhookPayload;
19
+
20
+ export { SIGNATURE_HEADER, verifyWebhook, verifyWebhookSignature };
@@ -0,0 +1,20 @@
1
+ import { W as WebhookPayload } from './types-eDJHwexZ.js';
2
+
3
+ /** The header SimpleQ sends with every webhook delivery. */
4
+ declare const SIGNATURE_HEADER = "x-simpleq-signature";
5
+ /**
6
+ * Verify the `x-simpleq-signature` header against the raw request body, in constant time.
7
+ * Returns a boolean and never throws — a missing or malformed header simply returns `false`.
8
+ *
9
+ * Always pass the *raw* body bytes (a string or Buffer), never a re-serialized parsed object.
10
+ */
11
+ declare function verifyWebhookSignature(rawBody: string | Buffer | Uint8Array, signatureHeader: string | null | undefined, signingSecret: string): boolean;
12
+ /**
13
+ * Verify the signature and return the parsed, typed webhook envelope (the equivalent of
14
+ * Stripe's `constructEvent`). Throws `SignatureVerificationError` if the signature does
15
+ * not match — the body is only parsed after verification passes, so a tampered payload
16
+ * never reaches `JSON.parse`.
17
+ */
18
+ declare function verifyWebhook(rawBody: string | Buffer | Uint8Array, signatureHeader: string | null | undefined, signingSecret: string): WebhookPayload;
19
+
20
+ export { SIGNATURE_HEADER, verifyWebhook, verifyWebhookSignature };
@@ -0,0 +1,3 @@
1
+ export { SIGNATURE_HEADER, verifyWebhook, verifyWebhookSignature } from './chunk-72DDDNF6.js';
2
+ //# sourceMappingURL=webhooks.js.map
3
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"webhooks.js"}
package/package.json ADDED
@@ -0,0 +1,112 @@
1
+ {
2
+ "name": "@simpleq/sdk",
3
+ "version": "0.1.0",
4
+ "description": "Official Node/TypeScript SDK for SimpleQ — publish jobs, verify webhook signatures, and ack/nack/defer deliveries.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "engines": {
9
+ "node": ">=22.0.0"
10
+ },
11
+ "homepage": "https://docs.simpleq.io",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/simpleqio/simpleq-sdk-typescript.git"
15
+ },
16
+ "bugs": "https://github.com/simpleqio/simpleq-sdk-typescript/issues",
17
+ "keywords": [
18
+ "simpleq",
19
+ "queue",
20
+ "jobs",
21
+ "webhook",
22
+ "transport",
23
+ "sdk"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "README.md"
31
+ ],
32
+ "main": "./dist/index.cjs",
33
+ "module": "./dist/index.js",
34
+ "types": "./dist/index.d.ts",
35
+ "exports": {
36
+ ".": {
37
+ "import": {
38
+ "types": "./dist/index.d.ts",
39
+ "default": "./dist/index.js"
40
+ },
41
+ "require": {
42
+ "types": "./dist/index.d.cts",
43
+ "default": "./dist/index.cjs"
44
+ }
45
+ },
46
+ "./webhooks": {
47
+ "import": {
48
+ "types": "./dist/webhooks.d.ts",
49
+ "default": "./dist/webhooks.js"
50
+ },
51
+ "require": {
52
+ "types": "./dist/webhooks.d.cts",
53
+ "default": "./dist/webhooks.cjs"
54
+ }
55
+ },
56
+ "./express": {
57
+ "import": {
58
+ "types": "./dist/express.d.ts",
59
+ "default": "./dist/express.js"
60
+ },
61
+ "require": {
62
+ "types": "./dist/express.d.cts",
63
+ "default": "./dist/express.cjs"
64
+ }
65
+ },
66
+ "./nest": {
67
+ "import": {
68
+ "types": "./dist/nest.d.ts",
69
+ "default": "./dist/nest.js"
70
+ },
71
+ "require": {
72
+ "types": "./dist/nest.d.cts",
73
+ "default": "./dist/nest.cjs"
74
+ }
75
+ },
76
+ "./package.json": "./package.json"
77
+ },
78
+ "peerDependencies": {
79
+ "@nestjs/common": "^10.0.0 || ^11.0.0",
80
+ "express": "^4.17.0 || ^5.0.0"
81
+ },
82
+ "peerDependenciesMeta": {
83
+ "@nestjs/common": {
84
+ "optional": true
85
+ },
86
+ "express": {
87
+ "optional": true
88
+ }
89
+ },
90
+ "devDependencies": {
91
+ "@nestjs/common": "^10.4.15",
92
+ "@types/express": "^4.17.21",
93
+ "@types/node": "^22.10.7",
94
+ "express": "^4.21.2",
95
+ "openapi-typescript": "^7.13.0",
96
+ "reflect-metadata": "^0.2.2",
97
+ "rxjs": "^7.8.1",
98
+ "tsup": "^8.3.5",
99
+ "typescript": "^5.7.3",
100
+ "vitest": "^3.0.5"
101
+ },
102
+ "scripts": {
103
+ "build": "tsup && node scripts/audit-dts.mjs",
104
+ "dev": "tsup --watch",
105
+ "type-check": "tsc --noEmit",
106
+ "audit:dts": "node scripts/audit-dts.mjs",
107
+ "test": "vitest run",
108
+ "test:watch": "vitest",
109
+ "clean": "rm -rf dist",
110
+ "check:contract": "node scripts/check-contract.mjs"
111
+ }
112
+ }