@rendobar/sdk 3.1.0 → 3.3.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/dist/index.cjs CHANGED
@@ -18,6 +18,32 @@ var ApiError = class extends Error {
18
18
  function isApiError(error) {
19
19
  return error instanceof ApiError;
20
20
  }
21
+ /** Thrown by jobs.wait() when the deadline passes before the job reaches a terminal state. */
22
+ var WaitTimeoutError = class extends Error {
23
+ jobId;
24
+ lastStatus;
25
+ timeoutMs;
26
+ constructor(jobId, lastStatus, timeoutMs) {
27
+ super(`Job ${jobId} did not complete within ${timeoutMs}ms (last status: ${lastStatus}). It may still be queued — check the dashboard or retry.`);
28
+ this.name = "WaitTimeoutError";
29
+ this.jobId = jobId;
30
+ this.lastStatus = lastStatus;
31
+ this.timeoutMs = timeoutMs;
32
+ }
33
+ };
34
+ /** Thrown by jobs.wait({ throwOnFailure: true }) when the job ends failed/cancelled. */
35
+ var JobFailedError = class extends Error {
36
+ jobId;
37
+ status;
38
+ job;
39
+ constructor(jobId, status, job, detail) {
40
+ super(`Job ${jobId} ended with status "${status}"${detail ? `: ${detail}` : ""}.`);
41
+ this.name = "JobFailedError";
42
+ this.jobId = jobId;
43
+ this.status = status;
44
+ this.job = job;
45
+ }
46
+ };
21
47
  //#endregion
22
48
  //#region src/lib/request.ts
23
49
  /**
@@ -35,10 +61,10 @@ const RETRYABLE_STATUS_CODES = new Set([
35
61
  504
36
62
  ]);
37
63
  function createRequestFn(config) {
38
- const { baseUrl = "https://api.rendobar.com", apiKey, accessToken, credentials, orgId, timeout = DEFAULT_TIMEOUT, maxRetries = DEFAULT_MAX_RETRIES, debug = false, fetch: fetchFn = globalThis.fetch } = config;
64
+ const { baseUrl = "https://api.rendobar.com", apiKey, accessToken, credentials, orgId, client = "sdk", timeout = DEFAULT_TIMEOUT, maxRetries = DEFAULT_MAX_RETRIES, debug = false, fetch: fetchFn = globalThis.fetch } = config;
39
65
  return async function request(path, options = {}) {
40
66
  const url = buildUrl(baseUrl, path, options.query);
41
- const init = buildInit(options, apiKey, accessToken, credentials, orgId);
67
+ const init = buildInit(options, apiKey, accessToken, credentials, orgId, client);
42
68
  const combinedSignal = combineSignals(options.signal, timeout);
43
69
  let lastError;
44
70
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
@@ -83,11 +109,12 @@ function buildUrl(baseUrl, path, query) {
83
109
  }
84
110
  return url;
85
111
  }
86
- function buildInit(options, apiKey, accessToken, credentials, orgId) {
112
+ function buildInit(options, apiKey, accessToken, credentials, orgId, client) {
87
113
  const headers = { "Content-Type": "application/json" };
88
114
  if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
89
115
  else if (accessToken) headers["Authorization"] = `Bearer ${accessToken}`;
90
116
  if (orgId) headers["X-Org-Id"] = orgId;
117
+ if (client) headers["X-Rendobar-Client"] = client;
91
118
  const init = {
92
119
  method: options.method ?? "GET",
93
120
  headers
@@ -183,21 +210,24 @@ function createJobsResource(request) {
183
210
  }
184
211
  },
185
212
  async wait(id, options = {}) {
186
- const { timeout = 3e5, interval = 2e3, onProgress, signal } = options;
213
+ const { timeout = 3e5, interval = 2e3, maxInterval = 1e4, onProgress, signal, throwOnFailure = false } = options;
187
214
  const deadline = Date.now() + timeout;
215
+ let currentInterval = interval;
188
216
  while (Date.now() < deadline) {
189
217
  if (signal?.aborted) throw new DOMException("Wait aborted", "AbortError");
190
218
  const job = await request(`/jobs/${id}`, { signal });
191
219
  onProgress?.(job);
192
- if (TERMINAL_STATUSES$1.has(job.status)) return job;
220
+ if (TERMINAL_STATUSES$1.has(job.status)) return resolveTerminal(id, job, throwOnFailure);
193
221
  const remaining = deadline - Date.now();
194
- const delay = Math.min(interval, remaining);
222
+ const delay = Math.min(currentInterval, remaining);
195
223
  if (delay <= 0) break;
196
224
  await sleep(delay, signal);
225
+ currentInterval = Math.min(currentInterval * 1.5, maxInterval);
197
226
  }
198
227
  const job = await request(`/jobs/${id}`, { signal });
199
- if (TERMINAL_STATUSES$1.has(job.status)) return job;
200
- throw new Error(`Job ${id} did not complete within ${timeout}ms (status: ${job.status})`);
228
+ onProgress?.(job);
229
+ if (TERMINAL_STATUSES$1.has(job.status)) return resolveTerminal(id, job, throwOnFailure);
230
+ throw new WaitTimeoutError(id, job.status, timeout);
201
231
  },
202
232
  async cancel(id, options) {
203
233
  return request(`/jobs/${id}/cancel`, {
@@ -222,6 +252,21 @@ function createJobsResource(request) {
222
252
  }
223
253
  };
224
254
  }
255
+ /**
256
+ * Handle a terminal job result: throw JobFailedError when throwOnFailure is
257
+ * set and the status is failed/cancelled; otherwise return the job.
258
+ *
259
+ * Narrowing on `status === "failed"` before reading `job.error` is required
260
+ * because `error` is only present on the "failed" variant of the discriminated
261
+ * union — the compiler won't allow access without narrowing first.
262
+ */
263
+ function resolveTerminal(id, job, throwOnFailure) {
264
+ if (throwOnFailure && (job.status === "failed" || job.status === "cancelled")) {
265
+ const detail = job.status === "failed" ? job.error.message : void 0;
266
+ throw new JobFailedError(id, job.status, job, detail);
267
+ }
268
+ return job;
269
+ }
225
270
  function sleep(ms, signal) {
226
271
  return new Promise((resolve, reject) => {
227
272
  if (signal?.aborted) {
@@ -248,6 +293,12 @@ function createBillingResource(request) {
248
293
  signal: options?.signal
249
294
  });
250
295
  },
296
+ async usageByClient(params, options) {
297
+ return request("/billing/usage-by-client", {
298
+ query: params,
299
+ signal: options?.signal
300
+ });
301
+ },
251
302
  async transactions(params, options) {
252
303
  return request("/billing/transactions", {
253
304
  query: params,
@@ -575,6 +626,16 @@ function createOrgsResource(request) {
575
626
  method: "DELETE",
576
627
  signal: options?.signal
577
628
  });
629
+ },
630
+ async getSettings(options) {
631
+ return request("/orgs/current/settings", { signal: options?.signal });
632
+ },
633
+ async updateSettings(body, options) {
634
+ return request("/orgs/current/settings", {
635
+ method: "PATCH",
636
+ body,
637
+ signal: options?.signal
638
+ });
578
639
  }
579
640
  };
580
641
  }
@@ -859,6 +920,8 @@ function jobData(job) {
859
920
  }
860
921
  //#endregion
861
922
  exports.ApiError = ApiError;
923
+ exports.JobFailedError = JobFailedError;
924
+ exports.WaitTimeoutError = WaitTimeoutError;
862
925
  exports.createClient = createClient;
863
926
  exports.isApiError = isApiError;
864
927
  exports.jobData = jobData;
package/dist/index.d.cts CHANGED
@@ -2270,6 +2270,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2270
2270
  }, $strip>>;
2271
2271
  logsAvailable: ZodBoolean;
2272
2272
  metricsAvailable: ZodBoolean;
2273
+ region: ZodOptional<ZodNullable<ZodString>>;
2273
2274
  createdAt: ZodNumber;
2274
2275
  dispatchedAt: ZodNullable<ZodNumber>;
2275
2276
  startedAt: ZodNullable<ZodNumber>;
@@ -2307,6 +2308,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2307
2308
  }, $strip>>;
2308
2309
  logsAvailable: ZodBoolean;
2309
2310
  metricsAvailable: ZodBoolean;
2311
+ region: ZodOptional<ZodNullable<ZodString>>;
2310
2312
  createdAt: ZodNumber;
2311
2313
  dispatchedAt: ZodNullable<ZodNumber>;
2312
2314
  startedAt: ZodNullable<ZodNumber>;
@@ -2346,6 +2348,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2346
2348
  }, $strip>>;
2347
2349
  logsAvailable: ZodBoolean;
2348
2350
  metricsAvailable: ZodBoolean;
2351
+ region: ZodOptional<ZodNullable<ZodString>>;
2349
2352
  createdAt: ZodNumber;
2350
2353
  dispatchedAt: ZodNullable<ZodNumber>;
2351
2354
  startedAt: ZodNullable<ZodNumber>;
@@ -2385,6 +2388,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2385
2388
  }, $strip>>;
2386
2389
  logsAvailable: ZodBoolean;
2387
2390
  metricsAvailable: ZodBoolean;
2391
+ region: ZodOptional<ZodNullable<ZodString>>;
2388
2392
  createdAt: ZodNumber;
2389
2393
  dispatchedAt: ZodNullable<ZodNumber>;
2390
2394
  startedAt: ZodNullable<ZodNumber>;
@@ -2466,6 +2470,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2466
2470
  }, $strip>>;
2467
2471
  logsAvailable: ZodBoolean;
2468
2472
  metricsAvailable: ZodBoolean;
2473
+ region: ZodOptional<ZodNullable<ZodString>>;
2469
2474
  createdAt: ZodNumber;
2470
2475
  dispatchedAt: ZodNullable<ZodNumber>;
2471
2476
  startedAt: ZodNullable<ZodNumber>;
@@ -2509,6 +2514,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2509
2514
  }, $strip>>;
2510
2515
  logsAvailable: ZodBoolean;
2511
2516
  metricsAvailable: ZodBoolean;
2517
+ region: ZodOptional<ZodNullable<ZodString>>;
2512
2518
  createdAt: ZodNumber;
2513
2519
  dispatchedAt: ZodNullable<ZodNumber>;
2514
2520
  startedAt: ZodNullable<ZodNumber>;
@@ -2604,6 +2610,12 @@ declare const usageSummarySchema: ZodObject<{
2604
2610
  computeSeconds: ZodNumber;
2605
2611
  }, $strip>>;
2606
2612
  }, $strip>;
2613
+ declare const usageByClientSchema: ZodArray<ZodObject<{
2614
+ client: ZodString;
2615
+ jobCount: ZodNumber;
2616
+ amountCharged: ZodNumber;
2617
+ amountFormatted: ZodString;
2618
+ }, $strip>>;
2607
2619
  declare const webhookEndpointSchema: ZodObject<{
2608
2620
  id: ZodString;
2609
2621
  name: ZodString;
@@ -2788,6 +2800,12 @@ declare const assetListMetaSchema: ZodObject<{
2788
2800
  limit: ZodNumber;
2789
2801
  offset: ZodNumber;
2790
2802
  }, $strip>;
2803
+ declare const orgSettingsResponseSchema: ZodObject<{
2804
+ billingEmailsEnabled: ZodBoolean;
2805
+ defaultRegion: ZodString;
2806
+ regionPinned: ZodBoolean;
2807
+ }, $strip>;
2808
+ type OrgSettings = output<typeof orgSettingsResponseSchema>;
2791
2809
  type JobResponse = output<typeof jobResponseSchema>;
2792
2810
  type JobStep = output<typeof jobStepSchema>;
2793
2811
  type Output = output<typeof jobOutputSchema>;
@@ -2800,6 +2818,7 @@ type JobType = output<typeof jobTypeSchema>;
2800
2818
  type BillingState = output<typeof billingStateSchema>;
2801
2819
  type Transaction = output<typeof transactionSchema>;
2802
2820
  type UsageSummary = output<typeof usageSummarySchema>;
2821
+ type UsageByClient = output<typeof usageByClientSchema>;
2803
2822
  type WebhookEndpoint = output<typeof webhookEndpointSchema>;
2804
2823
  type WebhookDelivery = output<typeof webhookDeliverySchema>;
2805
2824
  type Organization = output<typeof organizationSchema>;
@@ -2828,6 +2847,12 @@ declare const orgEventSchema: ZodDiscriminatedUnion<[ZodObject<{
2828
2847
  }, $strip>, ZodObject<{
2829
2848
  type: ZodLiteral<"job.result">;
2830
2849
  jobId: ZodString;
2850
+ }, $strip>, ZodObject<{
2851
+ type: ZodLiteral<"job.region_failover">;
2852
+ jobId: ZodString;
2853
+ fromRegion: ZodString;
2854
+ toRegion: ZodString;
2855
+ timestamp: ZodOptional<ZodNumber>;
2831
2856
  }, $strip>, ZodObject<{
2832
2857
  type: ZodLiteral<"balance.updated">;
2833
2858
  balance: ZodNumber;
@@ -2999,6 +3024,12 @@ interface ClientConfig {
2999
3024
  maxRetries?: number;
3000
3025
  /** Default org ID (sent as X-Org-Id header). */
3001
3026
  orgId?: string;
3027
+ /**
3028
+ * Client identifier sent as the X-Rendobar-Client header for usage
3029
+ * attribution. Defaults to "sdk". Wrappers built on this SDK should override
3030
+ * it (e.g. "cli", "n8n") so their traffic is attributed distinctly.
3031
+ */
3032
+ client?: string;
3002
3033
  /** Log request metadata to console.debug. Default: false */
3003
3034
  debug?: boolean;
3004
3035
  /** Custom fetch function for testing or special runtimes. */
@@ -3042,6 +3073,11 @@ declare function createClient(config?: ClientConfig): {
3042
3073
  usage(params?: UsageParams, options?: {
3043
3074
  signal?: AbortSignal;
3044
3075
  }): Promise<UsageSummary>;
3076
+ usageByClient(params?: {
3077
+ days?: number;
3078
+ }, options?: {
3079
+ signal?: AbortSignal;
3080
+ }): Promise<UsageByClient>;
3045
3081
  transactions(params?: TransactionListParams, options?: {
3046
3082
  signal?: AbortSignal;
3047
3083
  }): Promise<{
@@ -3178,6 +3214,12 @@ declare function createClient(config?: ClientConfig): {
3178
3214
  delete(options?: {
3179
3215
  signal?: AbortSignal;
3180
3216
  }): Promise<void>;
3217
+ getSettings(options?: {
3218
+ signal?: AbortSignal;
3219
+ }): Promise<OrgSettings>;
3220
+ updateSettings(body: Partial<Pick<OrgSettings, "billingEmailsEnabled" | "defaultRegion" | "regionPinned">>, options?: {
3221
+ signal?: AbortSignal;
3222
+ }): Promise<OrgSettings>;
3181
3223
  };
3182
3224
  batches: {
3183
3225
  create(params: {
@@ -3266,6 +3308,20 @@ declare class ApiError extends Error {
3266
3308
  constructor(code: string, statusCode: number, message: string, details?: Record<string, unknown> | undefined, retryAfter?: number | undefined);
3267
3309
  }
3268
3310
  declare function isApiError(error: unknown): error is ApiError;
3311
+ /** Thrown by jobs.wait() when the deadline passes before the job reaches a terminal state. */
3312
+ declare class WaitTimeoutError extends Error {
3313
+ readonly jobId: string;
3314
+ readonly lastStatus: string;
3315
+ readonly timeoutMs: number;
3316
+ constructor(jobId: string, lastStatus: string, timeoutMs: number);
3317
+ }
3318
+ /** Thrown by jobs.wait({ throwOnFailure: true }) when the job ends failed/cancelled. */
3319
+ declare class JobFailedError extends Error {
3320
+ readonly jobId: string;
3321
+ readonly status: string;
3322
+ readonly job: unknown;
3323
+ constructor(jobId: string, status: string, job: unknown, detail?: string);
3324
+ }
3269
3325
  //#endregion
3270
3326
  //#region src/realtime/client.d.ts
3271
3327
  interface RealtimeConnectOptions {
@@ -3348,10 +3404,16 @@ type ListJobsParams = {
3348
3404
  offset?: number;
3349
3405
  };
3350
3406
  type WaitOptions = {
3351
- /** Max wait time in ms. Default: 300_000 (5 minutes). */timeout?: number; /** Poll interval in ms. Default: 2_000. */
3352
- interval?: number; /** Called on each poll with the latest job state. */
3407
+ /** Max wait time in ms. Default: 300_000 (5 minutes). */timeout?: number; /** Initial poll interval in ms. Default: 2_000. Grows with exponential backoff. */
3408
+ interval?: number; /** Cap for the backoff poll interval in ms. Default: 10_000. */
3409
+ maxInterval?: number; /** Called on each poll with the latest job state. */
3353
3410
  onProgress?: (job: JobResponse) => void; /** Abort signal for cancellation. */
3354
3411
  signal?: AbortSignal;
3412
+ /**
3413
+ * When true, throw JobFailedError if the job ends with status "failed" or "cancelled".
3414
+ * Default: false (returns the terminal job, preserving existing behavior).
3415
+ */
3416
+ throwOnFailure?: boolean;
3355
3417
  };
3356
3418
  type JobListPage = {
3357
3419
  data: JobResponse[];
@@ -3451,4 +3513,4 @@ type AssetListPage = {
3451
3513
  meta: AssetListMeta;
3452
3514
  };
3453
3515
  //#endregion
3454
- export { ApiError, type ApiKey, type AssetResponse as Asset, type AssetDownloadResponse, type AssetInitResponse, type AssetListMeta, type AssetListPage, type BatchResult, type BillingInvoice, type BillingState, type ClientConfig, type Cost, type CreateJobParams, type CreateUploadOptions, type CreateWebhookParams, type FfmpegParams, type FileType, type JobResponse as Job, type JobCreatedResponse, type JobError, type JobListPage, type JobStep, type JobSubscribeOptions, type JobSubscription, type JobTimings, type JobType, type ListAssetsParams, type ListDeliveriesParams, type ListJobsParams, type LogEntryData, type OrgCurrentResponse, type OrgEvent, type Organization, type Output, type OutputFile, type PaginationMeta, type PaymentMethod, type RealtimeConnectOptions, type RealtimeConnection, type RendobarClient, type Transaction, type TransactionListParams, type UpdateWebhookParams, type UploadProgress, type UsageParams, type UsageSummary, type WaitOptions, type WebhookDelivery, type WebhookEndpoint, createClient, isApiError, jobData, outputUrl };
3516
+ export { ApiError, type ApiKey, type AssetResponse as Asset, type AssetDownloadResponse, type AssetInitResponse, type AssetListMeta, type AssetListPage, type BatchResult, type BillingInvoice, type BillingState, type ClientConfig, type Cost, type CreateJobParams, type CreateUploadOptions, type CreateWebhookParams, type FfmpegParams, type FileType, type JobResponse as Job, type JobCreatedResponse, type JobError, JobFailedError, type JobListPage, type JobStep, type JobSubscribeOptions, type JobSubscription, type JobTimings, type JobType, type ListAssetsParams, type ListDeliveriesParams, type ListJobsParams, type LogEntryData, type OrgCurrentResponse, type OrgEvent, type OrgSettings, type Organization, type Output, type OutputFile, type PaginationMeta, type PaymentMethod, type RealtimeConnectOptions, type RealtimeConnection, type RendobarClient, type Transaction, type TransactionListParams, type UpdateWebhookParams, type UploadProgress, type UsageParams, type UsageSummary, type WaitOptions, WaitTimeoutError, type WebhookDelivery, type WebhookEndpoint, createClient, isApiError, jobData, outputUrl };
package/dist/index.d.mts CHANGED
@@ -2270,6 +2270,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2270
2270
  }, $strip>>;
2271
2271
  logsAvailable: ZodBoolean;
2272
2272
  metricsAvailable: ZodBoolean;
2273
+ region: ZodOptional<ZodNullable<ZodString>>;
2273
2274
  createdAt: ZodNumber;
2274
2275
  dispatchedAt: ZodNullable<ZodNumber>;
2275
2276
  startedAt: ZodNullable<ZodNumber>;
@@ -2307,6 +2308,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2307
2308
  }, $strip>>;
2308
2309
  logsAvailable: ZodBoolean;
2309
2310
  metricsAvailable: ZodBoolean;
2311
+ region: ZodOptional<ZodNullable<ZodString>>;
2310
2312
  createdAt: ZodNumber;
2311
2313
  dispatchedAt: ZodNullable<ZodNumber>;
2312
2314
  startedAt: ZodNullable<ZodNumber>;
@@ -2346,6 +2348,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2346
2348
  }, $strip>>;
2347
2349
  logsAvailable: ZodBoolean;
2348
2350
  metricsAvailable: ZodBoolean;
2351
+ region: ZodOptional<ZodNullable<ZodString>>;
2349
2352
  createdAt: ZodNumber;
2350
2353
  dispatchedAt: ZodNullable<ZodNumber>;
2351
2354
  startedAt: ZodNullable<ZodNumber>;
@@ -2385,6 +2388,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2385
2388
  }, $strip>>;
2386
2389
  logsAvailable: ZodBoolean;
2387
2390
  metricsAvailable: ZodBoolean;
2391
+ region: ZodOptional<ZodNullable<ZodString>>;
2388
2392
  createdAt: ZodNumber;
2389
2393
  dispatchedAt: ZodNullable<ZodNumber>;
2390
2394
  startedAt: ZodNullable<ZodNumber>;
@@ -2466,6 +2470,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2466
2470
  }, $strip>>;
2467
2471
  logsAvailable: ZodBoolean;
2468
2472
  metricsAvailable: ZodBoolean;
2473
+ region: ZodOptional<ZodNullable<ZodString>>;
2469
2474
  createdAt: ZodNumber;
2470
2475
  dispatchedAt: ZodNullable<ZodNumber>;
2471
2476
  startedAt: ZodNullable<ZodNumber>;
@@ -2509,6 +2514,7 @@ declare const jobResponseSchema: ZodDiscriminatedUnion<[ZodObject<{
2509
2514
  }, $strip>>;
2510
2515
  logsAvailable: ZodBoolean;
2511
2516
  metricsAvailable: ZodBoolean;
2517
+ region: ZodOptional<ZodNullable<ZodString>>;
2512
2518
  createdAt: ZodNumber;
2513
2519
  dispatchedAt: ZodNullable<ZodNumber>;
2514
2520
  startedAt: ZodNullable<ZodNumber>;
@@ -2604,6 +2610,12 @@ declare const usageSummarySchema: ZodObject<{
2604
2610
  computeSeconds: ZodNumber;
2605
2611
  }, $strip>>;
2606
2612
  }, $strip>;
2613
+ declare const usageByClientSchema: ZodArray<ZodObject<{
2614
+ client: ZodString;
2615
+ jobCount: ZodNumber;
2616
+ amountCharged: ZodNumber;
2617
+ amountFormatted: ZodString;
2618
+ }, $strip>>;
2607
2619
  declare const webhookEndpointSchema: ZodObject<{
2608
2620
  id: ZodString;
2609
2621
  name: ZodString;
@@ -2788,6 +2800,12 @@ declare const assetListMetaSchema: ZodObject<{
2788
2800
  limit: ZodNumber;
2789
2801
  offset: ZodNumber;
2790
2802
  }, $strip>;
2803
+ declare const orgSettingsResponseSchema: ZodObject<{
2804
+ billingEmailsEnabled: ZodBoolean;
2805
+ defaultRegion: ZodString;
2806
+ regionPinned: ZodBoolean;
2807
+ }, $strip>;
2808
+ type OrgSettings = output<typeof orgSettingsResponseSchema>;
2791
2809
  type JobResponse = output<typeof jobResponseSchema>;
2792
2810
  type JobStep = output<typeof jobStepSchema>;
2793
2811
  type Output = output<typeof jobOutputSchema>;
@@ -2800,6 +2818,7 @@ type JobType = output<typeof jobTypeSchema>;
2800
2818
  type BillingState = output<typeof billingStateSchema>;
2801
2819
  type Transaction = output<typeof transactionSchema>;
2802
2820
  type UsageSummary = output<typeof usageSummarySchema>;
2821
+ type UsageByClient = output<typeof usageByClientSchema>;
2803
2822
  type WebhookEndpoint = output<typeof webhookEndpointSchema>;
2804
2823
  type WebhookDelivery = output<typeof webhookDeliverySchema>;
2805
2824
  type Organization = output<typeof organizationSchema>;
@@ -2828,6 +2847,12 @@ declare const orgEventSchema: ZodDiscriminatedUnion<[ZodObject<{
2828
2847
  }, $strip>, ZodObject<{
2829
2848
  type: ZodLiteral<"job.result">;
2830
2849
  jobId: ZodString;
2850
+ }, $strip>, ZodObject<{
2851
+ type: ZodLiteral<"job.region_failover">;
2852
+ jobId: ZodString;
2853
+ fromRegion: ZodString;
2854
+ toRegion: ZodString;
2855
+ timestamp: ZodOptional<ZodNumber>;
2831
2856
  }, $strip>, ZodObject<{
2832
2857
  type: ZodLiteral<"balance.updated">;
2833
2858
  balance: ZodNumber;
@@ -2999,6 +3024,12 @@ interface ClientConfig {
2999
3024
  maxRetries?: number;
3000
3025
  /** Default org ID (sent as X-Org-Id header). */
3001
3026
  orgId?: string;
3027
+ /**
3028
+ * Client identifier sent as the X-Rendobar-Client header for usage
3029
+ * attribution. Defaults to "sdk". Wrappers built on this SDK should override
3030
+ * it (e.g. "cli", "n8n") so their traffic is attributed distinctly.
3031
+ */
3032
+ client?: string;
3002
3033
  /** Log request metadata to console.debug. Default: false */
3003
3034
  debug?: boolean;
3004
3035
  /** Custom fetch function for testing or special runtimes. */
@@ -3042,6 +3073,11 @@ declare function createClient(config?: ClientConfig): {
3042
3073
  usage(params?: UsageParams, options?: {
3043
3074
  signal?: AbortSignal;
3044
3075
  }): Promise<UsageSummary>;
3076
+ usageByClient(params?: {
3077
+ days?: number;
3078
+ }, options?: {
3079
+ signal?: AbortSignal;
3080
+ }): Promise<UsageByClient>;
3045
3081
  transactions(params?: TransactionListParams, options?: {
3046
3082
  signal?: AbortSignal;
3047
3083
  }): Promise<{
@@ -3178,6 +3214,12 @@ declare function createClient(config?: ClientConfig): {
3178
3214
  delete(options?: {
3179
3215
  signal?: AbortSignal;
3180
3216
  }): Promise<void>;
3217
+ getSettings(options?: {
3218
+ signal?: AbortSignal;
3219
+ }): Promise<OrgSettings>;
3220
+ updateSettings(body: Partial<Pick<OrgSettings, "billingEmailsEnabled" | "defaultRegion" | "regionPinned">>, options?: {
3221
+ signal?: AbortSignal;
3222
+ }): Promise<OrgSettings>;
3181
3223
  };
3182
3224
  batches: {
3183
3225
  create(params: {
@@ -3266,6 +3308,20 @@ declare class ApiError extends Error {
3266
3308
  constructor(code: string, statusCode: number, message: string, details?: Record<string, unknown> | undefined, retryAfter?: number | undefined);
3267
3309
  }
3268
3310
  declare function isApiError(error: unknown): error is ApiError;
3311
+ /** Thrown by jobs.wait() when the deadline passes before the job reaches a terminal state. */
3312
+ declare class WaitTimeoutError extends Error {
3313
+ readonly jobId: string;
3314
+ readonly lastStatus: string;
3315
+ readonly timeoutMs: number;
3316
+ constructor(jobId: string, lastStatus: string, timeoutMs: number);
3317
+ }
3318
+ /** Thrown by jobs.wait({ throwOnFailure: true }) when the job ends failed/cancelled. */
3319
+ declare class JobFailedError extends Error {
3320
+ readonly jobId: string;
3321
+ readonly status: string;
3322
+ readonly job: unknown;
3323
+ constructor(jobId: string, status: string, job: unknown, detail?: string);
3324
+ }
3269
3325
  //#endregion
3270
3326
  //#region src/realtime/client.d.ts
3271
3327
  interface RealtimeConnectOptions {
@@ -3348,10 +3404,16 @@ type ListJobsParams = {
3348
3404
  offset?: number;
3349
3405
  };
3350
3406
  type WaitOptions = {
3351
- /** Max wait time in ms. Default: 300_000 (5 minutes). */timeout?: number; /** Poll interval in ms. Default: 2_000. */
3352
- interval?: number; /** Called on each poll with the latest job state. */
3407
+ /** Max wait time in ms. Default: 300_000 (5 minutes). */timeout?: number; /** Initial poll interval in ms. Default: 2_000. Grows with exponential backoff. */
3408
+ interval?: number; /** Cap for the backoff poll interval in ms. Default: 10_000. */
3409
+ maxInterval?: number; /** Called on each poll with the latest job state. */
3353
3410
  onProgress?: (job: JobResponse) => void; /** Abort signal for cancellation. */
3354
3411
  signal?: AbortSignal;
3412
+ /**
3413
+ * When true, throw JobFailedError if the job ends with status "failed" or "cancelled".
3414
+ * Default: false (returns the terminal job, preserving existing behavior).
3415
+ */
3416
+ throwOnFailure?: boolean;
3355
3417
  };
3356
3418
  type JobListPage = {
3357
3419
  data: JobResponse[];
@@ -3451,4 +3513,4 @@ type AssetListPage = {
3451
3513
  meta: AssetListMeta;
3452
3514
  };
3453
3515
  //#endregion
3454
- export { ApiError, type ApiKey, type AssetResponse as Asset, type AssetDownloadResponse, type AssetInitResponse, type AssetListMeta, type AssetListPage, type BatchResult, type BillingInvoice, type BillingState, type ClientConfig, type Cost, type CreateJobParams, type CreateUploadOptions, type CreateWebhookParams, type FfmpegParams, type FileType, type JobResponse as Job, type JobCreatedResponse, type JobError, type JobListPage, type JobStep, type JobSubscribeOptions, type JobSubscription, type JobTimings, type JobType, type ListAssetsParams, type ListDeliveriesParams, type ListJobsParams, type LogEntryData, type OrgCurrentResponse, type OrgEvent, type Organization, type Output, type OutputFile, type PaginationMeta, type PaymentMethod, type RealtimeConnectOptions, type RealtimeConnection, type RendobarClient, type Transaction, type TransactionListParams, type UpdateWebhookParams, type UploadProgress, type UsageParams, type UsageSummary, type WaitOptions, type WebhookDelivery, type WebhookEndpoint, createClient, isApiError, jobData, outputUrl };
3516
+ export { ApiError, type ApiKey, type AssetResponse as Asset, type AssetDownloadResponse, type AssetInitResponse, type AssetListMeta, type AssetListPage, type BatchResult, type BillingInvoice, type BillingState, type ClientConfig, type Cost, type CreateJobParams, type CreateUploadOptions, type CreateWebhookParams, type FfmpegParams, type FileType, type JobResponse as Job, type JobCreatedResponse, type JobError, JobFailedError, type JobListPage, type JobStep, type JobSubscribeOptions, type JobSubscription, type JobTimings, type JobType, type ListAssetsParams, type ListDeliveriesParams, type ListJobsParams, type LogEntryData, type OrgCurrentResponse, type OrgEvent, type OrgSettings, type Organization, type Output, type OutputFile, type PaginationMeta, type PaymentMethod, type RealtimeConnectOptions, type RealtimeConnection, type RendobarClient, type Transaction, type TransactionListParams, type UpdateWebhookParams, type UploadProgress, type UsageParams, type UsageSummary, type WaitOptions, WaitTimeoutError, type WebhookDelivery, type WebhookEndpoint, createClient, isApiError, jobData, outputUrl };
package/dist/index.mjs CHANGED
@@ -17,6 +17,32 @@ var ApiError = class extends Error {
17
17
  function isApiError(error) {
18
18
  return error instanceof ApiError;
19
19
  }
20
+ /** Thrown by jobs.wait() when the deadline passes before the job reaches a terminal state. */
21
+ var WaitTimeoutError = class extends Error {
22
+ jobId;
23
+ lastStatus;
24
+ timeoutMs;
25
+ constructor(jobId, lastStatus, timeoutMs) {
26
+ super(`Job ${jobId} did not complete within ${timeoutMs}ms (last status: ${lastStatus}). It may still be queued — check the dashboard or retry.`);
27
+ this.name = "WaitTimeoutError";
28
+ this.jobId = jobId;
29
+ this.lastStatus = lastStatus;
30
+ this.timeoutMs = timeoutMs;
31
+ }
32
+ };
33
+ /** Thrown by jobs.wait({ throwOnFailure: true }) when the job ends failed/cancelled. */
34
+ var JobFailedError = class extends Error {
35
+ jobId;
36
+ status;
37
+ job;
38
+ constructor(jobId, status, job, detail) {
39
+ super(`Job ${jobId} ended with status "${status}"${detail ? `: ${detail}` : ""}.`);
40
+ this.name = "JobFailedError";
41
+ this.jobId = jobId;
42
+ this.status = status;
43
+ this.job = job;
44
+ }
45
+ };
20
46
  //#endregion
21
47
  //#region src/lib/request.ts
22
48
  /**
@@ -34,10 +60,10 @@ const RETRYABLE_STATUS_CODES = new Set([
34
60
  504
35
61
  ]);
36
62
  function createRequestFn(config) {
37
- const { baseUrl = "https://api.rendobar.com", apiKey, accessToken, credentials, orgId, timeout = DEFAULT_TIMEOUT, maxRetries = DEFAULT_MAX_RETRIES, debug = false, fetch: fetchFn = globalThis.fetch } = config;
63
+ const { baseUrl = "https://api.rendobar.com", apiKey, accessToken, credentials, orgId, client = "sdk", timeout = DEFAULT_TIMEOUT, maxRetries = DEFAULT_MAX_RETRIES, debug = false, fetch: fetchFn = globalThis.fetch } = config;
38
64
  return async function request(path, options = {}) {
39
65
  const url = buildUrl(baseUrl, path, options.query);
40
- const init = buildInit(options, apiKey, accessToken, credentials, orgId);
66
+ const init = buildInit(options, apiKey, accessToken, credentials, orgId, client);
41
67
  const combinedSignal = combineSignals(options.signal, timeout);
42
68
  let lastError;
43
69
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
@@ -82,11 +108,12 @@ function buildUrl(baseUrl, path, query) {
82
108
  }
83
109
  return url;
84
110
  }
85
- function buildInit(options, apiKey, accessToken, credentials, orgId) {
111
+ function buildInit(options, apiKey, accessToken, credentials, orgId, client) {
86
112
  const headers = { "Content-Type": "application/json" };
87
113
  if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
88
114
  else if (accessToken) headers["Authorization"] = `Bearer ${accessToken}`;
89
115
  if (orgId) headers["X-Org-Id"] = orgId;
116
+ if (client) headers["X-Rendobar-Client"] = client;
90
117
  const init = {
91
118
  method: options.method ?? "GET",
92
119
  headers
@@ -182,21 +209,24 @@ function createJobsResource(request) {
182
209
  }
183
210
  },
184
211
  async wait(id, options = {}) {
185
- const { timeout = 3e5, interval = 2e3, onProgress, signal } = options;
212
+ const { timeout = 3e5, interval = 2e3, maxInterval = 1e4, onProgress, signal, throwOnFailure = false } = options;
186
213
  const deadline = Date.now() + timeout;
214
+ let currentInterval = interval;
187
215
  while (Date.now() < deadline) {
188
216
  if (signal?.aborted) throw new DOMException("Wait aborted", "AbortError");
189
217
  const job = await request(`/jobs/${id}`, { signal });
190
218
  onProgress?.(job);
191
- if (TERMINAL_STATUSES$1.has(job.status)) return job;
219
+ if (TERMINAL_STATUSES$1.has(job.status)) return resolveTerminal(id, job, throwOnFailure);
192
220
  const remaining = deadline - Date.now();
193
- const delay = Math.min(interval, remaining);
221
+ const delay = Math.min(currentInterval, remaining);
194
222
  if (delay <= 0) break;
195
223
  await sleep(delay, signal);
224
+ currentInterval = Math.min(currentInterval * 1.5, maxInterval);
196
225
  }
197
226
  const job = await request(`/jobs/${id}`, { signal });
198
- if (TERMINAL_STATUSES$1.has(job.status)) return job;
199
- throw new Error(`Job ${id} did not complete within ${timeout}ms (status: ${job.status})`);
227
+ onProgress?.(job);
228
+ if (TERMINAL_STATUSES$1.has(job.status)) return resolveTerminal(id, job, throwOnFailure);
229
+ throw new WaitTimeoutError(id, job.status, timeout);
200
230
  },
201
231
  async cancel(id, options) {
202
232
  return request(`/jobs/${id}/cancel`, {
@@ -221,6 +251,21 @@ function createJobsResource(request) {
221
251
  }
222
252
  };
223
253
  }
254
+ /**
255
+ * Handle a terminal job result: throw JobFailedError when throwOnFailure is
256
+ * set and the status is failed/cancelled; otherwise return the job.
257
+ *
258
+ * Narrowing on `status === "failed"` before reading `job.error` is required
259
+ * because `error` is only present on the "failed" variant of the discriminated
260
+ * union — the compiler won't allow access without narrowing first.
261
+ */
262
+ function resolveTerminal(id, job, throwOnFailure) {
263
+ if (throwOnFailure && (job.status === "failed" || job.status === "cancelled")) {
264
+ const detail = job.status === "failed" ? job.error.message : void 0;
265
+ throw new JobFailedError(id, job.status, job, detail);
266
+ }
267
+ return job;
268
+ }
224
269
  function sleep(ms, signal) {
225
270
  return new Promise((resolve, reject) => {
226
271
  if (signal?.aborted) {
@@ -247,6 +292,12 @@ function createBillingResource(request) {
247
292
  signal: options?.signal
248
293
  });
249
294
  },
295
+ async usageByClient(params, options) {
296
+ return request("/billing/usage-by-client", {
297
+ query: params,
298
+ signal: options?.signal
299
+ });
300
+ },
250
301
  async transactions(params, options) {
251
302
  return request("/billing/transactions", {
252
303
  query: params,
@@ -574,6 +625,16 @@ function createOrgsResource(request) {
574
625
  method: "DELETE",
575
626
  signal: options?.signal
576
627
  });
628
+ },
629
+ async getSettings(options) {
630
+ return request("/orgs/current/settings", { signal: options?.signal });
631
+ },
632
+ async updateSettings(body, options) {
633
+ return request("/orgs/current/settings", {
634
+ method: "PATCH",
635
+ body,
636
+ signal: options?.signal
637
+ });
577
638
  }
578
639
  };
579
640
  }
@@ -857,4 +918,4 @@ function jobData(job) {
857
918
  return job.output.data;
858
919
  }
859
920
  //#endregion
860
- export { ApiError, createClient, isApiError, jobData, outputUrl };
921
+ export { ApiError, JobFailedError, WaitTimeoutError, createClient, isApiError, jobData, outputUrl };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rendobar/sdk",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "type": "module",
5
5
  "description": "TypeScript client for the Rendobar media processing API",
6
6
  "main": "./dist/index.cjs",