diffusr 0.0.0-stage → 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 diffusr
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,129 @@
1
- # Temporary Holding Version
1
+ # diffusr
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The diffusr API client for Node 18+. Make videos, images and music from code.
4
+ No dependencies. Bodies and answers are the API's own snake_case JSON.
5
+
6
+ ```sh
7
+ npm install diffusr
8
+ ```
9
+
10
+ ## Quickstart
11
+
12
+ Use a **test key** (`dfsr_test_…`) while you build: prices are quoted exactly,
13
+ nothing is charged, no model runs, and the result is a placeholder file a few
14
+ seconds later. Swap in a live key (`dfsr_live_…`) when you are ready to spend.
15
+ Mint keys on the Developers page in the app.
16
+
17
+ ```ts
18
+ import { Diffusr } from "diffusr";
19
+
20
+ const diffusr = new Diffusr(); // reads DIFFUSR_KEY
21
+
22
+ // 1. Ask the price. Free: nothing is made, nothing is spent.
23
+ const quote = await diffusr.makeVideo({
24
+ prompt: "A can of sparkling water on a wet street, slow push-in, rain",
25
+ duration_sec: 5,
26
+ dry_run: true,
27
+ });
28
+ console.log(quote.price); // { credits: 63, usd: "0.6300", ... }
29
+
30
+ // 2. Make it. An Idempotency-Key is added for you and reused on retries,
31
+ // so a dropped connection never pays twice.
32
+ const job = await diffusr.makeVideo({
33
+ prompt: "A can of sparkling water on a wet street, slow push-in, rain",
34
+ duration_sec: 5,
35
+ });
36
+
37
+ // 3. Wait for it (polls with backoff; throws WAIT_TIMEOUT if it takes too long).
38
+ const result = await diffusr.waitFor(job.id, { timeoutMs: 10 * 60_000 });
39
+ if (result.status === "SUCCEEDED") console.log(result.output?.url);
40
+ else console.error(result.status, result.error);
41
+ console.log(result.charge); // { quoted_credits, charged_credits, final }
42
+ ```
43
+
44
+ ### Callbacks instead of polling
45
+
46
+ Pass `callback_url` (https, public) and we POST one signed event when the job
47
+ ends. Verify it with your signing secret (`await diffusr.getCallbackSecret()`):
48
+
49
+ ```ts
50
+ import { Diffusr } from "diffusr";
51
+
52
+ // Express: use the RAW body, not the parsed one.
53
+ app.post("/diffusr", express.text({ type: "*/*" }), (req, res) => {
54
+ if (!Diffusr.verifyCallback(req.body, req.headers, process.env.DIFFUSR_WHSEC!)) {
55
+ return res.sendStatus(400);
56
+ }
57
+ const event = JSON.parse(req.body); // { id, type: "result.finished", data: <result> }
58
+ res.sendStatus(200); // any 2xx; drop repeats of event.id
59
+ });
60
+ ```
61
+
62
+ `verifyCallback` implements [Standard Webhooks](https://www.standardwebhooks.com):
63
+ constant-time compare, two signatures after a secret rotation, a 5-minute
64
+ timestamp window, `whsec_` prefix handled.
65
+
66
+ ## Methods
67
+
68
+ | Method | REST |
69
+ |---|---|
70
+ | `makeVideo`, `makeImage`, `editImage`, `recast`, `makeMusic`, `creatorVideo`, `runTemplate` `(body, { idempotencyKey? })` | `POST /{tool}` |
71
+ | `getResult(id)`, `listResults({ limit? })`, `cancel(id)` (stops queued work; a step already generating may finish and be charged: check `result.charge`) | `GET /results/{id}`, `GET /results`, `POST /results/{id}/cancel` |
72
+ | `waitFor(id, { timeoutMs?, intervalMs?, onPoll? })` | polls `GET /results/{id}` |
73
+ | `uploadFile(pathOrBytesOrBlob, { contentType? })`, `uploadFromUrl(url)` | `POST /uploads` + signed `PUT` |
74
+ | `listModels({ kind? })`, `listTemplates()` | `GET /models`, `GET /templates` |
75
+ | `listCallbacks({ limit?, cursor? })`, `retryCallback(eventId)`, `getCallbackSecret()`, `rotateCallbackSecret()` | `/callbacks…` |
76
+ | `Diffusr.verifyCallback(rawBody, headers, secret)` | |
77
+
78
+ `dry_run: true` on any make call answers with the price only.
79
+
80
+ `runTemplate` takes one flat body: `{ template: "<id from listTemplates()>", mode?, prompt?,
81
+ pictures?, image_urls?, product_image_url?, script?, place?, people?, setup?, resolution?, dry_run? }`.
82
+ `listTemplates()` says which fields each template takes.
83
+
84
+ ```ts
85
+ await diffusr.runTemplate({ template: "tpl-ugc-talking-head", script: "Hi!", people: [{ name: "Mia", image_url: "https://…" }], dry_run: true });
86
+ ```
87
+
88
+ ## Retries and errors
89
+
90
+ - Every request times out after 60 s (`new Diffusr(key, { timeoutMs })`, or
91
+ `{ timeoutMs, signal }` per call) with a `TIMEOUT` error. Your own `signal`
92
+ aborts without a retry.
93
+ - `GET`s (and so `waitFor`) retry on 429, 500, 502, 503, 504, network errors
94
+ and timeouts with backoff, honouring `Retry-After` (waits over 30 s are not
95
+ slept: the error is thrown).
96
+ - Make calls retry on 429, 503, network errors and timeouts only, **with the
97
+ same Idempotency-Key**.
98
+ Pass your own with `{ idempotencyKey }` to make a retry safe across restarts.
99
+ - Every failure is a `DiffusrError`:
100
+
101
+ ```ts
102
+ try {
103
+ await diffusr.makeVideo({ prompt: "…" });
104
+ } catch (e) {
105
+ if (e instanceof DiffusrError) {
106
+ console.log(e.status, e.code, e.message, e.requestId, e.retryAfter);
107
+ // e.body has the extras: issues, field, budget…
108
+ }
109
+ }
110
+ ```
111
+
112
+ Codes are the API's (`RATE_LIMITED`, `BUDGET_EXCEEDED`, `INSUFFICIENT_CREDITS`…).
113
+ The SDK adds `NETWORK_ERROR`, `TIMEOUT`, `WAIT_TIMEOUT`, `UPLOAD_FAILED`,
114
+ `CONTENT_TYPE_REQUIRED` and `MISSING_API_KEY` (status 0 or the PUT's status).
115
+ Handle codes you don't know.
116
+
117
+ ## Publishing
118
+
119
+ ESM only (Node 18+). In the monorepo `package.json` points at `src` so the
120
+ workspace can use it untouched; `publishConfig` swaps in `dist` with types.
121
+ Publish with **`pnpm publish` from `packages/sdk`** (it applies `publishConfig`
122
+ and builds first); `npm publish` would ship the `src` entry points. Check a
123
+ pack first with `pnpm pack:check`.
124
+
125
+ ## Docs
126
+
127
+ Full API reference, prices and agent guides: https://diffusr.ai/docs
128
+
129
+ MIT licensed.
@@ -0,0 +1,98 @@
1
+ import type { HeaderBag } from "./verify.js";
2
+ import type { CallbackDelivery, CallbackDeliveryList, CallbackSecret, CallOptions, CreatorVideoBody, RequestOptions, EditImageBody, MakeAnswer, MakeImageBody, MakeMusicBody, MakeVideoBody, ModelList, RecastBody, Result, ResultList, RunTemplateBody, TemplateList, UploadedFile } from "./types.js";
3
+ export declare const DEFAULT_BASE_URL = "https://app.diffusr.ai/api/v2";
4
+ export interface DiffusrOptions {
5
+ /** Default `https://app.diffusr.ai/api/v2`. */
6
+ baseUrl?: string;
7
+ /** Your own fetch (tests, proxies). Default: the global one (Node 18+). */
8
+ fetch?: typeof fetch;
9
+ /** Automatic retries on 429 / 503 / network errors / timeouts (GETs also on 500, 502, 504). Default 3. */
10
+ maxRetries?: number;
11
+ /** First retry delay when the API sends no Retry-After; doubles each try. Default 500. */
12
+ retryBaseMs?: number;
13
+ /** Per-request timeout in ms (each attempt). Default 60 000. */
14
+ timeoutMs?: number;
15
+ }
16
+ export interface WaitOptions {
17
+ /** Give up after this long. Default 15 minutes. */
18
+ timeoutMs?: number;
19
+ /** First pause between checks. Default 3000; it grows ×1.5 up to 15 s. */
20
+ intervalMs?: number;
21
+ /** Called with every answer while waiting. */
22
+ onPoll?: (result: Result) => void;
23
+ }
24
+ export declare class Diffusr {
25
+ private readonly apiKey;
26
+ private readonly baseUrl;
27
+ private readonly fetchImpl;
28
+ private readonly maxRetries;
29
+ private readonly retryBaseMs;
30
+ private readonly timeoutMs;
31
+ /** @param apiKey `dfsr_live_…` or `dfsr_test_…` (free). Default: `process.env.DIFFUSR_KEY`. */
32
+ constructor(apiKey?: string, opts?: DiffusrOptions);
33
+ makeVideo<B extends MakeVideoBody>(body: B, opts?: CallOptions): Promise<MakeAnswer<B>>;
34
+ makeImage<B extends MakeImageBody>(body: B, opts?: CallOptions): Promise<MakeAnswer<B>>;
35
+ editImage<B extends EditImageBody>(body: B, opts?: CallOptions): Promise<MakeAnswer<B>>;
36
+ recast<B extends RecastBody>(body: B, opts?: CallOptions): Promise<MakeAnswer<B>>;
37
+ makeMusic<B extends MakeMusicBody>(body: B, opts?: CallOptions): Promise<MakeAnswer<B>>;
38
+ creatorVideo<B extends CreatorVideoBody>(body: B, opts?: CallOptions): Promise<MakeAnswer<B>>;
39
+ runTemplate<B extends RunTemplateBody>(body: B, opts?: CallOptions): Promise<MakeAnswer<B>>;
40
+ /** POST /{tool}. One Idempotency-Key per call, reused by every automatic retry. */
41
+ private make;
42
+ getResult(id: string, opts?: RequestOptions): Promise<Result>;
43
+ listResults(q?: {
44
+ limit?: number;
45
+ }): Promise<ResultList>;
46
+ /**
47
+ * Stop queued work before it generates (that part is never charged). A step
48
+ * that is already generating may still finish and be charged: check
49
+ * `result.charge` on the answer. A finished job comes back unchanged.
50
+ */
51
+ cancel(id: string): Promise<Result>;
52
+ /**
53
+ * Poll until the job is over and return the result. A job that ends FAILED
54
+ * or CANCELED is returned too: check `result.status`. Throws a
55
+ * `DiffusrError` with code `WAIT_TIMEOUT` if it is still running at the
56
+ * deadline (the job itself keeps going).
57
+ */
58
+ waitFor(id: string, opts?: WaitOptions): Promise<Result>;
59
+ /**
60
+ * Upload a local file and get a `file_url` to pass to a tool. Takes a path
61
+ * (Node), a Buffer / Uint8Array, or a Blob. Two steps: ask for a signed
62
+ * URL, PUT the exact bytes to it.
63
+ */
64
+ uploadFile(file: string | Uint8Array | Blob, opts?: {
65
+ contentType?: string;
66
+ }): Promise<{
67
+ file_url: string;
68
+ kind: string;
69
+ }>;
70
+ /** Have us copy a public link in (images and short clips; use `uploadFile` for big videos). */
71
+ uploadFromUrl(sourceUrl: string): Promise<UploadedFile>;
72
+ listModels(q?: {
73
+ kind?: "video" | "image";
74
+ }): Promise<ModelList>;
75
+ listTemplates(): Promise<TemplateList>;
76
+ listCallbacks(q?: {
77
+ limit?: number;
78
+ cursor?: string;
79
+ }): Promise<CallbackDeliveryList>;
80
+ /** One more try for a FAILED event (up to 3 by hand). */
81
+ retryCallback(eventId: string): Promise<CallbackDelivery>;
82
+ /** Your signing secret (`whsec_…`) for `Diffusr.verifyCallback`. */
83
+ getCallbackSecret(): Promise<CallbackSecret>;
84
+ rotateCallbackSecret(): Promise<CallbackSecret>;
85
+ /**
86
+ * Check a callback's signature (Standard Webhooks). Pass the raw request
87
+ * body text, the request headers and your `whsec_…` secret. Rejects a
88
+ * timestamp more than 5 minutes off; accepts a rotation's two signatures.
89
+ */
90
+ static verifyCallback(rawBody: string, headers: HeaderBag, secret: string, opts?: {
91
+ toleranceSec?: number;
92
+ nowSec?: number;
93
+ }): boolean;
94
+ private request;
95
+ /** 0.5 s, 1 s, 2 s… with a little jitter. */
96
+ private backoff;
97
+ private toError;
98
+ }
package/dist/client.js ADDED
@@ -0,0 +1,263 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { DiffusrError } from "./errors.js";
3
+ import { verifyCallback } from "./verify.js";
4
+ import { TERMINAL_STATUSES } from "./types.js";
5
+ export const DEFAULT_BASE_URL = "https://app.diffusr.ai/api/v2";
6
+ const SDK_VERSION = "0.1.0";
7
+ /** Never wait longer than this on a single automatic retry; throw instead. */
8
+ const MAX_AUTO_RETRY_WAIT_SEC = 30;
9
+ const DEFAULT_TIMEOUT_MS = 60_000;
10
+ const CONTENT_TYPES = {
11
+ jpg: "image/jpeg",
12
+ jpeg: "image/jpeg",
13
+ png: "image/png",
14
+ webp: "image/webp",
15
+ gif: "image/gif",
16
+ mp4: "video/mp4",
17
+ mov: "video/quicktime",
18
+ webm: "video/webm",
19
+ mp3: "audio/mpeg",
20
+ wav: "audio/wav",
21
+ m4a: "audio/mp4",
22
+ };
23
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
24
+ function toQuery(q) {
25
+ const p = new URLSearchParams();
26
+ for (const [k, v] of Object.entries(q ?? {}))
27
+ if (v !== undefined)
28
+ p.set(k, String(v));
29
+ const s = p.toString();
30
+ return s ? `?${s}` : "";
31
+ }
32
+ export class Diffusr {
33
+ apiKey;
34
+ baseUrl;
35
+ fetchImpl;
36
+ maxRetries;
37
+ retryBaseMs;
38
+ timeoutMs;
39
+ /** @param apiKey `dfsr_live_…` or `dfsr_test_…` (free). Default: `process.env.DIFFUSR_KEY`. */
40
+ constructor(apiKey, opts = {}) {
41
+ const key = apiKey ?? (typeof process !== "undefined" ? process.env.DIFFUSR_KEY : undefined);
42
+ if (!key)
43
+ throw new DiffusrError({ status: 0, code: "MISSING_API_KEY", message: "Pass an API key or set DIFFUSR_KEY." });
44
+ this.apiKey = key;
45
+ this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
46
+ this.fetchImpl = opts.fetch ?? ((...a) => fetch(...a));
47
+ this.maxRetries = opts.maxRetries ?? 3;
48
+ this.retryBaseMs = opts.retryBaseMs ?? 500;
49
+ this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
50
+ }
51
+ // ——— make calls (paid; `dry_run: true` is free) ———
52
+ makeVideo(body, opts) {
53
+ return this.make("make_video", body, opts);
54
+ }
55
+ makeImage(body, opts) {
56
+ return this.make("make_image", body, opts);
57
+ }
58
+ editImage(body, opts) {
59
+ return this.make("edit_image", body, opts);
60
+ }
61
+ recast(body, opts) {
62
+ return this.make("recast", body, opts);
63
+ }
64
+ makeMusic(body, opts) {
65
+ return this.make("make_music", body, opts);
66
+ }
67
+ creatorVideo(body, opts) {
68
+ return this.make("creator_video", body, opts);
69
+ }
70
+ runTemplate(body, opts) {
71
+ return this.make("run_template", body, opts);
72
+ }
73
+ /** POST /{tool}. One Idempotency-Key per call, reused by every automatic retry. */
74
+ async make(tool, body, opts = {}) {
75
+ const key = opts.idempotencyKey ?? body.idempotency_key ?? randomUUID();
76
+ const { idempotency_key: _drop, ...rest } = body;
77
+ void _drop;
78
+ return this.request("POST", `/${tool}`, { body: rest, headers: { "Idempotency-Key": key }, signal: opts.signal, timeoutMs: opts.timeoutMs });
79
+ }
80
+ // ——— results ———
81
+ getResult(id, opts) {
82
+ return this.request("GET", `/results/${encodeURIComponent(id)}`, opts);
83
+ }
84
+ listResults(q) {
85
+ return this.request("GET", `/results${toQuery(q)}`);
86
+ }
87
+ /**
88
+ * Stop queued work before it generates (that part is never charged). A step
89
+ * that is already generating may still finish and be charged: check
90
+ * `result.charge` on the answer. A finished job comes back unchanged.
91
+ */
92
+ cancel(id) {
93
+ return this.request("POST", `/results/${encodeURIComponent(id)}/cancel`, { body: {} });
94
+ }
95
+ /**
96
+ * Poll until the job is over and return the result. A job that ends FAILED
97
+ * or CANCELED is returned too: check `result.status`. Throws a
98
+ * `DiffusrError` with code `WAIT_TIMEOUT` if it is still running at the
99
+ * deadline (the job itself keeps going).
100
+ */
101
+ async waitFor(id, opts = {}) {
102
+ const deadline = Date.now() + (opts.timeoutMs ?? 15 * 60_000);
103
+ let interval = opts.intervalMs ?? 3000;
104
+ for (;;) {
105
+ const result = await this.getResult(id);
106
+ opts.onPoll?.(result);
107
+ if (TERMINAL_STATUSES.includes(result.status))
108
+ return result;
109
+ const left = deadline - Date.now();
110
+ if (left <= 0)
111
+ break;
112
+ await sleep(Math.min(interval, left));
113
+ interval = Math.min(Math.round(interval * 1.5), Math.max(15_000, opts.intervalMs ?? 0));
114
+ if (Date.now() >= deadline)
115
+ break;
116
+ }
117
+ throw new DiffusrError({
118
+ status: 0,
119
+ code: "WAIT_TIMEOUT",
120
+ message: `Result ${id} was still not finished after ${Math.round((opts.timeoutMs ?? 15 * 60_000) / 1000)} s. It keeps running: call waitFor or getResult again.`,
121
+ });
122
+ }
123
+ // ——— files ———
124
+ /**
125
+ * Upload a local file and get a `file_url` to pass to a tool. Takes a path
126
+ * (Node), a Buffer / Uint8Array, or a Blob. Two steps: ask for a signed
127
+ * URL, PUT the exact bytes to it.
128
+ */
129
+ async uploadFile(file, opts = {}) {
130
+ let bytes;
131
+ let contentType = opts.contentType;
132
+ if (typeof file === "string") {
133
+ const { readFile } = await import("node:fs/promises");
134
+ bytes = await readFile(file);
135
+ contentType ??= CONTENT_TYPES[file.split(".").pop()?.toLowerCase() ?? ""];
136
+ }
137
+ else if (typeof Blob !== "undefined" && file instanceof Blob) {
138
+ bytes = new Uint8Array(await file.arrayBuffer());
139
+ contentType ??= file.type || undefined;
140
+ }
141
+ else {
142
+ bytes = file;
143
+ }
144
+ if (!contentType) {
145
+ throw new DiffusrError({ status: 0, code: "CONTENT_TYPE_REQUIRED", message: "Pass { contentType } (e.g. \"video/mp4\"): it could not be worked out." });
146
+ }
147
+ const ticket = await this.request("POST", "/uploads", { body: { content_type: contentType, size_bytes: bytes.byteLength } });
148
+ const res = await this.fetchImpl(ticket.upload_url, { method: ticket.method, headers: ticket.headers, body: bytes });
149
+ if (!res.ok) {
150
+ throw new DiffusrError({ status: res.status, code: "UPLOAD_FAILED", message: `The upload PUT failed with HTTP ${res.status}.` });
151
+ }
152
+ return { file_url: ticket.file_url, kind: ticket.kind };
153
+ }
154
+ /** Have us copy a public link in (images and short clips; use `uploadFile` for big videos). */
155
+ uploadFromUrl(sourceUrl) {
156
+ return this.request("POST", "/uploads", { body: { source_url: sourceUrl } });
157
+ }
158
+ // ——— catalog ———
159
+ listModels(q) {
160
+ return this.request("GET", `/models${toQuery(q)}`);
161
+ }
162
+ listTemplates() {
163
+ return this.request("GET", "/templates");
164
+ }
165
+ // ——— callbacks ———
166
+ listCallbacks(q) {
167
+ return this.request("GET", `/callbacks${toQuery(q)}`);
168
+ }
169
+ /** One more try for a FAILED event (up to 3 by hand). */
170
+ retryCallback(eventId) {
171
+ return this.request("POST", `/callbacks/${encodeURIComponent(eventId)}/retry`, { body: {} });
172
+ }
173
+ /** Your signing secret (`whsec_…`) for `Diffusr.verifyCallback`. */
174
+ getCallbackSecret() {
175
+ return this.request("GET", "/callbacks/secret");
176
+ }
177
+ rotateCallbackSecret() {
178
+ return this.request("POST", "/callbacks/secret/rotate", { body: {} });
179
+ }
180
+ /**
181
+ * Check a callback's signature (Standard Webhooks). Pass the raw request
182
+ * body text, the request headers and your `whsec_…` secret. Rejects a
183
+ * timestamp more than 5 minutes off; accepts a rotation's two signatures.
184
+ */
185
+ static verifyCallback(rawBody, headers, secret, opts) {
186
+ return verifyCallback(rawBody, headers, secret, opts);
187
+ }
188
+ // ——— plumbing ———
189
+ async request(method, path, init = {}) {
190
+ const headers = {
191
+ Authorization: `Bearer ${this.apiKey}`,
192
+ Accept: "application/json",
193
+ "User-Agent": `diffusr-node/${SDK_VERSION}`,
194
+ ...init.headers,
195
+ };
196
+ if (init.body !== undefined)
197
+ headers["Content-Type"] = "application/json";
198
+ const payload = init.body === undefined ? undefined : JSON.stringify(init.body);
199
+ const timeoutMs = init.timeoutMs ?? this.timeoutMs;
200
+ for (let attempt = 0;; attempt++) {
201
+ let res;
202
+ const timeoutSignal = AbortSignal.timeout(timeoutMs);
203
+ const signal = init.signal ? AbortSignal.any([init.signal, timeoutSignal]) : timeoutSignal;
204
+ try {
205
+ res = await this.fetchImpl(this.baseUrl + path, { method, headers, signal, ...(payload !== undefined ? { body: payload } : {}) });
206
+ }
207
+ catch (cause) {
208
+ // The caller's own abort is theirs: never retry or rewrap it.
209
+ if (init.signal?.aborted)
210
+ throw cause;
211
+ const timedOut = timeoutSignal.aborted;
212
+ if (attempt < this.maxRetries) {
213
+ await sleep(this.backoff(attempt));
214
+ continue;
215
+ }
216
+ throw timedOut
217
+ ? new DiffusrError({ status: 0, code: "TIMEOUT", message: `diffusr did not answer within ${Math.round(timeoutMs / 1000)} s.` })
218
+ : new DiffusrError({ status: 0, code: "NETWORK_ERROR", message: `Could not reach diffusr: ${cause.message}` });
219
+ }
220
+ if (res.ok) {
221
+ const text = await res.text();
222
+ return (text ? JSON.parse(text) : {});
223
+ }
224
+ const err = await this.toError(res);
225
+ const retryable = res.status === 429 || res.status === 503 || (method === "GET" && (res.status === 500 || res.status === 502 || res.status === 504));
226
+ const wait = err.retryAfter ?? this.backoff(attempt) / 1000;
227
+ if (retryable && attempt < this.maxRetries && wait <= MAX_AUTO_RETRY_WAIT_SEC) {
228
+ await sleep(Math.round(wait * 1000));
229
+ continue;
230
+ }
231
+ throw err;
232
+ }
233
+ }
234
+ /** 0.5 s, 1 s, 2 s… with a little jitter. */
235
+ backoff(attempt) {
236
+ return this.retryBaseMs * 2 ** attempt * (1 + Math.random() * 0.2);
237
+ }
238
+ async toError(res) {
239
+ const text = await res.text().catch(() => "");
240
+ let body;
241
+ try {
242
+ const parsed = JSON.parse(text);
243
+ if (parsed && typeof parsed === "object")
244
+ body = parsed;
245
+ }
246
+ catch {
247
+ /* not JSON */
248
+ }
249
+ const header = Number(res.headers.get("retry-after"));
250
+ const fromBody = typeof body?.retry_after_seconds === "number" ? body.retry_after_seconds : undefined;
251
+ const retryAfter = Number.isFinite(header) && res.headers.get("retry-after") !== null ? header : fromBody;
252
+ const message = typeof body?.error === "string" ? body.error : text.slice(0, 300) || `HTTP ${res.status}`;
253
+ return new DiffusrError({
254
+ status: res.status,
255
+ code: typeof body?.code === "string" ? body.code : `HTTP_${res.status}`,
256
+ message,
257
+ requestId: (typeof body?.request_id === "string" ? body.request_id : undefined) ?? res.headers.get("x-request-id") ?? undefined,
258
+ retryAfter,
259
+ body,
260
+ });
261
+ }
262
+ }
263
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /** Every non-2xx answer (and a few client-side failures) throws this. */
2
+ export declare class DiffusrError extends Error {
3
+ /** HTTP status; 0 when no answer came (network error, wait timeout). */
4
+ readonly status: number;
5
+ /** The API's machine code, e.g. `RATE_LIMITED`. Unknown codes are passed through. */
6
+ readonly code: string;
7
+ /** The `request_id` of the call: quote it to support. */
8
+ readonly requestId: string | undefined;
9
+ /** Seconds to wait before trying again, when the API said so. */
10
+ readonly retryAfter: number | undefined;
11
+ /** The whole JSON error body (extra fields such as `field`, `issues`, `budget`). */
12
+ readonly body: Record<string, unknown> | undefined;
13
+ constructor(init: {
14
+ status: number;
15
+ code: string;
16
+ message: string;
17
+ requestId?: string | undefined;
18
+ retryAfter?: number | undefined;
19
+ body?: Record<string, unknown> | undefined;
20
+ });
21
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,23 @@
1
+ /** Every non-2xx answer (and a few client-side failures) throws this. */
2
+ export class DiffusrError extends Error {
3
+ /** HTTP status; 0 when no answer came (network error, wait timeout). */
4
+ status;
5
+ /** The API's machine code, e.g. `RATE_LIMITED`. Unknown codes are passed through. */
6
+ code;
7
+ /** The `request_id` of the call: quote it to support. */
8
+ requestId;
9
+ /** Seconds to wait before trying again, when the API said so. */
10
+ retryAfter;
11
+ /** The whole JSON error body (extra fields such as `field`, `issues`, `budget`). */
12
+ body;
13
+ constructor(init) {
14
+ super(init.message);
15
+ this.name = "DiffusrError";
16
+ this.status = init.status;
17
+ this.code = init.code;
18
+ this.requestId = init.requestId;
19
+ this.retryAfter = init.retryAfter;
20
+ this.body = init.body;
21
+ }
22
+ }
23
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,wEAAwE;IAC/D,MAAM,CAAS;IACxB,qFAAqF;IAC5E,IAAI,CAAS;IACtB,yDAAyD;IAChD,SAAS,CAAqB;IACvC,iEAAiE;IACxD,UAAU,CAAqB;IACxC,oFAAoF;IAC3E,IAAI,CAAsC;IAEnD,YAAY,IAOX;QACC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ export { Diffusr, DEFAULT_BASE_URL } from "./client.js";
2
+ export type { DiffusrOptions, WaitOptions } from "./client.js";
3
+ export { DiffusrError } from "./errors.js";
4
+ export { verifyCallback, SIGNATURE_TOLERANCE_SEC } from "./verify.js";
5
+ export { TERMINAL_STATUSES } from "./types.js";
6
+ export type * from "./types.js";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { Diffusr, DEFAULT_BASE_URL } from "./client.js";
2
+ export { DiffusrError } from "./errors.js";
3
+ export { verifyCallback, SIGNATURE_TOLERANCE_SEC } from "./verify.js";
4
+ export { TERMINAL_STATUSES } from "./types.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,208 @@
1
+ export type ResultStatus = "PENDING" | "RUNNING" | "SUCCEEDED" | "FAILED" | "CANCELED";
2
+ export declare const TERMINAL_STATUSES: readonly ResultStatus[];
3
+ export interface Price {
4
+ credits: number;
5
+ usd: string;
6
+ tariff: "direct" | "outcome";
7
+ tariff_version: string;
8
+ expires_at: string;
9
+ }
10
+ export interface Started {
11
+ id: string;
12
+ status: string;
13
+ credits_estimated: number;
14
+ idempotent_replay?: true;
15
+ test?: true;
16
+ price?: Price;
17
+ duration_sec?: number;
18
+ warnings?: string[];
19
+ next: string;
20
+ }
21
+ export interface DryRun {
22
+ dry_run: true;
23
+ test?: true;
24
+ credits_estimated: number;
25
+ price?: Price;
26
+ duration_sec?: number;
27
+ warnings?: string[];
28
+ note: string;
29
+ }
30
+ export interface Charge {
31
+ quoted_credits: number | null;
32
+ charged_credits: number;
33
+ final: boolean;
34
+ }
35
+ export interface ResultOutput {
36
+ kind: "IMAGE" | "VIDEO" | "AUDIO";
37
+ url: string;
38
+ thumbnail_url?: string;
39
+ width?: number;
40
+ height?: number;
41
+ duration_sec?: number;
42
+ }
43
+ export interface Result {
44
+ id: string;
45
+ status: ResultStatus;
46
+ model: string;
47
+ credits_estimated?: number;
48
+ created_at: string;
49
+ finished_at?: string;
50
+ output?: ResultOutput;
51
+ error?: {
52
+ code: string;
53
+ message: string;
54
+ };
55
+ request_id?: string;
56
+ test?: true;
57
+ charge: Charge;
58
+ price?: Price;
59
+ next?: string;
60
+ }
61
+ export interface ResultList {
62
+ results: Result[];
63
+ }
64
+ export interface UploadTicket {
65
+ upload_url: string;
66
+ method: "PUT";
67
+ headers: {
68
+ "Content-Type": string;
69
+ };
70
+ file_url: string;
71
+ kind: string;
72
+ expires_in_sec: number;
73
+ curl: string;
74
+ next: string;
75
+ }
76
+ export interface UploadedFile {
77
+ file_url: string;
78
+ kind: string;
79
+ next: string;
80
+ }
81
+ export interface CallbackDelivery {
82
+ event_id: string;
83
+ type: string;
84
+ result_id: string;
85
+ url: string;
86
+ /** PENDING = will be tried (again), DELIVERED, FAILED. */
87
+ status: "PENDING" | "DELIVERED" | "FAILED";
88
+ attempts: number;
89
+ last_status_code?: number;
90
+ last_error?: string;
91
+ last_attempt_at?: string;
92
+ next_attempt_at?: string;
93
+ delivered_at?: string;
94
+ created_at: string;
95
+ test?: true;
96
+ }
97
+ export interface CallbackDeliveryList {
98
+ deliveries: CallbackDelivery[];
99
+ next_cursor?: string;
100
+ }
101
+ export interface CallbackSecret {
102
+ /** Starts with "whsec_". */
103
+ secret: string;
104
+ previous_valid_until?: string;
105
+ }
106
+ export interface ModelList {
107
+ models: Array<{
108
+ id: string;
109
+ [key: string]: unknown;
110
+ }>;
111
+ [key: string]: unknown;
112
+ }
113
+ export interface TemplateList {
114
+ templates: Array<{
115
+ id: string;
116
+ name: string;
117
+ kind: string;
118
+ about: string;
119
+ inputs: unknown[];
120
+ [key: string]: unknown;
121
+ }>;
122
+ [key: string]: unknown;
123
+ }
124
+ /** Fields every make call takes. Anything else the API documents passes through. */
125
+ export interface MakeBase {
126
+ dry_run?: boolean;
127
+ /** Also sent as the `Idempotency-Key` header. Leave out and the SDK makes one. */
128
+ idempotency_key?: string;
129
+ callback_url?: string;
130
+ [key: string]: unknown;
131
+ }
132
+ export interface MakeVideoBody extends MakeBase {
133
+ prompt: string;
134
+ image_urls?: string[];
135
+ audio_urls?: string[];
136
+ duration_sec?: number;
137
+ aspect_ratio?: string;
138
+ resolution?: string;
139
+ model?: string;
140
+ }
141
+ export interface MakeImageBody extends MakeBase {
142
+ prompt: string;
143
+ image_urls?: string[];
144
+ aspect_ratio?: string;
145
+ resolution?: string;
146
+ model?: string;
147
+ }
148
+ export interface EditImageBody extends MakeBase {
149
+ prompt: string;
150
+ image_urls: string[];
151
+ aspect_ratio?: string;
152
+ resolution?: string;
153
+ model?: string;
154
+ }
155
+ export interface RecastBody extends MakeBase {
156
+ video_url: string;
157
+ image_urls?: string[];
158
+ mode?: "world" | "swap";
159
+ prompt?: string;
160
+ aspect_ratio?: string;
161
+ resolution?: string;
162
+ model?: string;
163
+ }
164
+ export interface MakeMusicBody extends MakeBase {
165
+ prompt: string;
166
+ }
167
+ export interface CreatorVideoBody extends MakeBase {
168
+ creator_id: string;
169
+ script: string;
170
+ resolution?: string;
171
+ }
172
+ /** One flat body for every template kind; `listTemplates()` says which fields
173
+ each template takes. A field a template doesn't take is refused. */
174
+ export interface RunTemplateBody extends MakeBase {
175
+ /** The template's id, from `listTemplates()`. */
176
+ template: string;
177
+ /** Video templates: "remix" (default) or "recast". */
178
+ mode?: "remix" | "recast";
179
+ prompt?: string;
180
+ /** Video template remix: one picture per slot name. */
181
+ pictures?: Record<string, string>;
182
+ /** Video template recast: photos of who should appear. */
183
+ image_urls?: string[];
184
+ product_image_url?: string;
185
+ script?: string;
186
+ place?: string;
187
+ people?: Array<{
188
+ name: string;
189
+ image_url: string;
190
+ look?: string;
191
+ }>;
192
+ setup?: "selfie" | "propped" | "friend";
193
+ resolution?: "480p" | "720p";
194
+ }
195
+ /** A body with `dry_run: true` answers with the price; any other starts a job. */
196
+ export type MakeAnswer<B> = B extends {
197
+ dry_run: true;
198
+ } ? DryRun : Started;
199
+ export interface RequestOptions {
200
+ /** Abort the call (not retried). Combined with the timeout. */
201
+ signal?: AbortSignal;
202
+ /** Per-request timeout in ms for this call. Default: the client's (60 000). */
203
+ timeoutMs?: number;
204
+ }
205
+ export interface CallOptions extends RequestOptions {
206
+ /** Retry the same call with this key. Default: a fresh random one. */
207
+ idempotencyKey?: string;
208
+ }
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ // Response shapes of the diffusr REST API (v2). Hand-written so the package
2
+ // ships with no dependencies; the contract is packages/schema/src/api-v2*.ts.
3
+ // Bodies and answers are the API's own snake_case JSON.
4
+ export const TERMINAL_STATUSES = ["SUCCEEDED", "FAILED", "CANCELED"];
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,8EAA8E;AAC9E,wDAAwD;AAGxD,MAAM,CAAC,MAAM,iBAAiB,GAA4B,CAAC,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare const SIGNATURE_TOLERANCE_SEC = 300;
2
+ export type HeaderBag = Headers | Record<string, string | string[] | undefined>;
3
+ /**
4
+ * Check a diffusr callback (Standard Webhooks). `rawBody` must be the text
5
+ * exactly as received, before any JSON parsing. Returns false for a missing
6
+ * header, a bad or stale signature; never throws.
7
+ */
8
+ export declare function verifyCallback(rawBody: string, headers: HeaderBag, secret: string, opts?: {
9
+ toleranceSec?: number;
10
+ nowSec?: number;
11
+ }): boolean;
package/dist/verify.js ADDED
@@ -0,0 +1,43 @@
1
+ import { createHmac, timingSafeEqual } from "node:crypto";
2
+ export const SIGNATURE_TOLERANCE_SEC = 300;
3
+ function headerOf(headers, name) {
4
+ if (typeof Headers !== "undefined" && headers instanceof Headers)
5
+ return headers.get(name) ?? undefined;
6
+ for (const [k, v] of Object.entries(headers)) {
7
+ if (k.toLowerCase() === name)
8
+ return Array.isArray(v) ? v.join(" ") : v;
9
+ }
10
+ return undefined;
11
+ }
12
+ /**
13
+ * Check a diffusr callback (Standard Webhooks). `rawBody` must be the text
14
+ * exactly as received, before any JSON parsing. Returns false for a missing
15
+ * header, a bad or stale signature; never throws.
16
+ */
17
+ export function verifyCallback(rawBody, headers, secret, opts = {}) {
18
+ try {
19
+ const id = headerOf(headers, "webhook-id");
20
+ const timestamp = headerOf(headers, "webhook-timestamp");
21
+ const signature = headerOf(headers, "webhook-signature");
22
+ if (!id || !timestamp || !signature || !/^\d+$/.test(timestamp))
23
+ return false;
24
+ const nowSec = opts.nowSec ?? Math.floor(Date.now() / 1000);
25
+ if (Math.abs(nowSec - Number(timestamp)) > (opts.toleranceSec ?? SIGNATURE_TOLERANCE_SEC))
26
+ return false;
27
+ const key = Buffer.from(secret.startsWith("whsec_") ? secret.slice(6) : secret, "base64");
28
+ const expected = createHmac("sha256", key).update(`${id}.${timestamp}.${rawBody}`).digest();
29
+ let ok = false;
30
+ for (const part of signature.split(" ")) {
31
+ if (!part.startsWith("v1,"))
32
+ continue;
33
+ const given = Buffer.from(part.slice(3), "base64");
34
+ if (given.length === expected.length && timingSafeEqual(given, expected))
35
+ ok = true;
36
+ }
37
+ return ok;
38
+ }
39
+ catch {
40
+ return false;
41
+ }
42
+ }
43
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAI3C,SAAS,QAAQ,CAAC,OAAkB,EAAE,IAAY;IAChD,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,YAAY,OAAO;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;IACxG,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAwD,CAAC,EAAE,CAAC;QAC9F,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,OAAkB,EAClB,MAAc,EACd,OAAmD,EAAE;IAErD,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACzD,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACzD,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,OAAO,KAAK,CAAC;QAC9E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC5D,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,uBAAuB,CAAC;YAAE,OAAO,KAAK,CAAC;QACxG,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC1F,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,SAAS,IAAI,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;QAC5F,IAAI,EAAE,GAAG,KAAK,CAAC;QACf,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;gBAAE,SAAS;YACtC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;YACnD,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC;gBAAE,EAAE,GAAG,IAAI,CAAC;QACtF,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,54 @@
1
1
  {
2
2
  "name": "diffusr",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "The diffusr API client: make videos, images and music from code. Free price checks, idempotent starts, waitFor, signed callbacks.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "devDependencies": {
20
+ "@types/node": "^26",
21
+ "typescript": "^5",
22
+ "vitest": "^3.2.7",
23
+ "@diffusr/schema": "0.1.0"
24
+ },
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "engines": {
28
+ "node": ">=18"
29
+ },
30
+ "sideEffects": false,
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/jkrperson/diffusr.git",
34
+ "directory": "packages/sdk"
35
+ },
36
+ "homepage": "https://diffusr.ai/docs",
37
+ "keywords": [
38
+ "diffusr",
39
+ "video",
40
+ "image",
41
+ "ai",
42
+ "api",
43
+ "sdk"
44
+ ],
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "scripts": {
49
+ "build": "rm -rf dist && tsc -p tsconfig.build.json",
50
+ "typecheck": "tsc --noEmit",
51
+ "test": "vitest run",
52
+ "pack:check": "pnpm run build && d=$(mktemp -d) && pnpm pack --pack-destination \"$d\" >/dev/null && tar -xzf \"$d\"/*.tgz -C \"$d\" && node -e \"import(process.argv[1]).then(m=>{if(typeof m.Diffusr!=='function')process.exit(1);console.log('pack ok: '+Object.keys(m).join(', '))})\" \"$d/package/dist/index.js\" && node -e \"const p=require(process.argv[1]);console.log(JSON.stringify(p.exports))\" \"$d/package/package.json\"; r=$?; rm -rf \"$d\"; exit $r"
53
+ }
6
54
  }