@renderingvideo/sdk 1.0.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 ADDED
@@ -0,0 +1,612 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AlreadyRenderingError: () => AlreadyRenderingError,
24
+ AuthenticationError: () => AuthenticationError,
25
+ CreditsClient: () => CreditsClient,
26
+ FileClient: () => FileClient,
27
+ InsufficientCreditsError: () => InsufficientCreditsError,
28
+ InvalidApiKeyError: () => InvalidApiKeyError,
29
+ NotFoundError: () => NotFoundError,
30
+ PreviewClient: () => PreviewClient,
31
+ RateLimitError: () => RateLimitError,
32
+ RemoteError: () => RemoteError,
33
+ RenderingVideo: () => RenderingVideo,
34
+ RenderingVideoError: () => RenderingVideoError,
35
+ StorageLimitError: () => StorageLimitError,
36
+ UploadError: () => UploadError,
37
+ ValidationError: () => ValidationError,
38
+ VideoClient: () => VideoClient,
39
+ default: () => index_default
40
+ });
41
+ module.exports = __toCommonJS(index_exports);
42
+
43
+ // src/errors.ts
44
+ var RenderingVideoError = class extends Error {
45
+ code;
46
+ details;
47
+ constructor(message, code, details = {}) {
48
+ super(message);
49
+ this.name = "RenderingVideoError";
50
+ this.code = code;
51
+ this.details = details;
52
+ }
53
+ };
54
+ var AuthenticationError = class extends RenderingVideoError {
55
+ constructor(message, details = {}) {
56
+ super(message, "AUTHENTICATION_ERROR", details);
57
+ this.name = "AuthenticationError";
58
+ }
59
+ };
60
+ var InvalidApiKeyError = class extends RenderingVideoError {
61
+ constructor(message, details = {}) {
62
+ super(message, "INVALID_API_KEY", details);
63
+ this.name = "InvalidApiKeyError";
64
+ }
65
+ };
66
+ var InsufficientCreditsError = class extends RenderingVideoError {
67
+ constructor(message, details = {}) {
68
+ super(message, "INSUFFICIENT_CREDITS", details);
69
+ this.name = "InsufficientCreditsError";
70
+ }
71
+ };
72
+ var ValidationError = class extends RenderingVideoError {
73
+ constructor(message, details = {}) {
74
+ super(message, "VALIDATION_ERROR", details);
75
+ this.name = "ValidationError";
76
+ }
77
+ };
78
+ var NotFoundError = class extends RenderingVideoError {
79
+ constructor(message, details = {}) {
80
+ super(message, "NOT_FOUND", details);
81
+ this.name = "NotFoundError";
82
+ }
83
+ };
84
+ var RateLimitError = class extends RenderingVideoError {
85
+ constructor(message, details = {}) {
86
+ super(message, "RATE_LIMITED", details);
87
+ this.name = "RateLimitError";
88
+ }
89
+ };
90
+ var AlreadyRenderingError = class extends RenderingVideoError {
91
+ constructor(message, details = {}) {
92
+ super(message, "ALREADY_RENDERING", details);
93
+ this.name = "AlreadyRenderingError";
94
+ }
95
+ };
96
+ var UploadError = class extends RenderingVideoError {
97
+ constructor(message, details = {}) {
98
+ super(message, "UPLOAD_FAILED", details);
99
+ this.name = "UploadError";
100
+ }
101
+ };
102
+ var StorageLimitError = class extends RenderingVideoError {
103
+ constructor(message, details = {}) {
104
+ super(message, "STORAGE_LIMIT_EXCEEDED", details);
105
+ this.name = "StorageLimitError";
106
+ }
107
+ };
108
+ var RemoteError = class extends RenderingVideoError {
109
+ constructor(message, details = {}) {
110
+ super(message, "REMOTE_ERROR", details);
111
+ this.name = "RemoteError";
112
+ }
113
+ };
114
+ function handleApiError(statusCode, message, code, details = {}) {
115
+ switch (code) {
116
+ case "MISSING_API_KEY":
117
+ case "INVALID_API_KEY":
118
+ case "INVALID_API_KEY_FORMAT":
119
+ case "API_KEY_INACTIVE":
120
+ case "USER_NOT_FOUND":
121
+ return new AuthenticationError(message, { ...details, code, statusCode });
122
+ case "INSUFFICIENT_CREDITS":
123
+ return new InsufficientCreditsError(message, { ...details, code, statusCode });
124
+ case "INVALID_REQUEST":
125
+ case "INVALID_CONFIG":
126
+ case "NO_FILES":
127
+ case "UNSUPPORTED_FILE_TYPE":
128
+ return new ValidationError(message, { ...details, code, statusCode });
129
+ case "NOT_FOUND":
130
+ return new NotFoundError(message, { ...details, code, statusCode });
131
+ case "ALREADY_RENDERING":
132
+ return new AlreadyRenderingError(message, { ...details, code, statusCode });
133
+ case "STORAGE_LIMIT_EXCEEDED":
134
+ return new StorageLimitError(message, { ...details, code, statusCode });
135
+ case "UPLOAD_FAILED":
136
+ return new UploadError(message, { ...details, code, statusCode });
137
+ case "REMOTE_ERROR":
138
+ case "RENDER_TRIGGER_FAILED":
139
+ return new RemoteError(message, { ...details, code, statusCode });
140
+ }
141
+ switch (statusCode) {
142
+ case 401:
143
+ return new AuthenticationError(message, { ...details, code, statusCode });
144
+ case 402:
145
+ return new InsufficientCreditsError(message, { ...details, code, statusCode });
146
+ case 400:
147
+ return new ValidationError(message, { ...details, code, statusCode });
148
+ case 404:
149
+ return new NotFoundError(message, { ...details, code, statusCode });
150
+ case 429:
151
+ return new RateLimitError(message, { ...details, code, statusCode });
152
+ default:
153
+ return new RenderingVideoError(message, code, { ...details, statusCode });
154
+ }
155
+ }
156
+
157
+ // src/client.ts
158
+ var DEFAULT_BASE_URL = "https://renderingvideo.com";
159
+ var DEFAULT_TIMEOUT = 3e4;
160
+ async function request(baseUrl, apiKey, timeout, method, endpoint, body, params) {
161
+ const url = new URL(`${baseUrl}${endpoint}`);
162
+ if (params) {
163
+ Object.entries(params).forEach(([key, value]) => {
164
+ if (value !== void 0) {
165
+ url.searchParams.append(key, String(value));
166
+ }
167
+ });
168
+ }
169
+ const controller = new AbortController();
170
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
171
+ try {
172
+ const response = await fetch(url.toString(), {
173
+ method,
174
+ headers: {
175
+ Authorization: `Bearer ${apiKey}`,
176
+ "Content-Type": "application/json"
177
+ },
178
+ body: body ? JSON.stringify(body) : void 0,
179
+ signal: controller.signal
180
+ });
181
+ const data = await response.json();
182
+ if (!response.ok) {
183
+ throw handleApiError(
184
+ response.status,
185
+ data.error || "Unknown error",
186
+ data.code || "UNKNOWN_ERROR",
187
+ data.details || data
188
+ );
189
+ }
190
+ return data;
191
+ } catch (error) {
192
+ if (error instanceof RenderingVideoError) {
193
+ throw error;
194
+ }
195
+ if (error instanceof Error && error.name === "AbortError") {
196
+ throw new Error(`Request timed out after ${timeout}ms`);
197
+ }
198
+ throw error;
199
+ } finally {
200
+ clearTimeout(timeoutId);
201
+ }
202
+ }
203
+ var VideoClient = class {
204
+ constructor(baseUrl, apiKey, timeout) {
205
+ this.baseUrl = baseUrl;
206
+ this.apiKey = apiKey;
207
+ this.timeout = timeout;
208
+ }
209
+ async request(method, endpoint, body, params) {
210
+ return request(this.baseUrl, this.apiKey, this.timeout, method, endpoint, body, params);
211
+ }
212
+ /**
213
+ * Create a new video task (does not start rendering)
214
+ * @example
215
+ * ```typescript
216
+ * const task = await client.video.create({
217
+ * config: {
218
+ * meta: { version: '2.0.0', width: 1920, height: 1080, fps: 30 },
219
+ * tracks: [{ clips: [{ type: 'text', text: 'Hello World', start: 0, duration: 5 }] }]
220
+ * },
221
+ * metadata: { projectId: 'proj_123' }
222
+ * });
223
+ * ```
224
+ */
225
+ async create(options) {
226
+ const body = { config: options.config };
227
+ if (options.metadata) body.metadata = options.metadata;
228
+ return this.request("POST", "/api/v1/video", body);
229
+ }
230
+ /**
231
+ * List video tasks
232
+ * @example
233
+ * ```typescript
234
+ * const { tasks, pagination } = await client.video.list({ page: 1, limit: 20, status: 'completed' });
235
+ * ```
236
+ */
237
+ async list(options) {
238
+ return this.request("GET", "/api/v1/video", void 0, {
239
+ page: options?.page,
240
+ limit: options?.limit,
241
+ status: options?.status
242
+ });
243
+ }
244
+ /**
245
+ * Get task details by ID
246
+ * @example
247
+ * ```typescript
248
+ * const task = await client.video.get('abc123def456');
249
+ * console.log(task.status, task.videoUrl);
250
+ * ```
251
+ */
252
+ async get(taskId) {
253
+ return this.request("GET", `/api/v1/video/${taskId}`);
254
+ }
255
+ /**
256
+ * Delete a video task permanently
257
+ * @example
258
+ * ```typescript
259
+ * const result = await client.video.delete('abc123def456');
260
+ * console.log(result.deleted, result.remoteDeleted);
261
+ * ```
262
+ */
263
+ async delete(taskId) {
264
+ return this.request("DELETE", `/api/v1/video/${taskId}`);
265
+ }
266
+ /**
267
+ * Trigger rendering for a task
268
+ * @example
269
+ * ```typescript
270
+ * const result = await client.video.render('abc123def456', {
271
+ * webhookUrl: 'https://example.com/webhook',
272
+ * numWorkers: 5
273
+ * });
274
+ * ```
275
+ */
276
+ async render(taskId, options) {
277
+ const body = {};
278
+ if (options?.webhookUrl) body.webhook_url = options.webhookUrl;
279
+ if (options?.numWorkers) body.num_workers = options.numWorkers;
280
+ return this.request("POST", `/api/v1/video/${taskId}/render`, body);
281
+ }
282
+ /**
283
+ * Create task and immediately start rendering (convenience method)
284
+ * @example
285
+ * ```typescript
286
+ * const task = await client.video.createAndRender({
287
+ * config: { ... },
288
+ * webhookUrl: 'https://example.com/webhook'
289
+ * });
290
+ * ```
291
+ */
292
+ async createAndRender(options) {
293
+ const task = await this.create(options);
294
+ return this.render(task.taskId, { webhookUrl: options.webhookUrl, numWorkers: options.numWorkers });
295
+ }
296
+ };
297
+ var FileClient = class {
298
+ constructor(baseUrl, apiKey, timeout) {
299
+ this.baseUrl = baseUrl;
300
+ this.apiKey = apiKey;
301
+ this.timeout = timeout;
302
+ }
303
+ async request(method, endpoint, body, params) {
304
+ return request(this.baseUrl, this.apiKey, this.timeout, method, endpoint, body, params);
305
+ }
306
+ /**
307
+ * Upload files (images, videos, audio)
308
+ * @example
309
+ * ```typescript
310
+ * // In Node.js with FormData
311
+ * const formData = new FormData();
312
+ * formData.append('file', fileBlob, 'image.png');
313
+ * const result = await client.files.upload(formData);
314
+ *
315
+ * // Multiple files
316
+ * formData.append('files', file1Blob, 'video.mp4');
317
+ * formData.append('files', file2Blob, 'audio.mp3');
318
+ * const result = await client.files.upload(formData);
319
+ * ```
320
+ */
321
+ async upload(formData) {
322
+ const controller = new AbortController();
323
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
324
+ try {
325
+ const response = await fetch(`${this.baseUrl}/api/v1/upload`, {
326
+ method: "POST",
327
+ headers: {
328
+ Authorization: `Bearer ${this.apiKey}`
329
+ },
330
+ body: formData,
331
+ signal: controller.signal
332
+ });
333
+ const data = await response.json();
334
+ if (!response.ok) {
335
+ throw handleApiError(
336
+ response.status,
337
+ data.error || "Unknown error",
338
+ data.code || "UNKNOWN_ERROR",
339
+ data.details || data
340
+ );
341
+ }
342
+ return data;
343
+ } catch (error) {
344
+ if (error instanceof RenderingVideoError) {
345
+ throw error;
346
+ }
347
+ if (error instanceof Error && error.name === "AbortError") {
348
+ throw new Error(`Upload timed out after ${this.timeout}ms`);
349
+ }
350
+ throw error;
351
+ } finally {
352
+ clearTimeout(timeoutId);
353
+ }
354
+ }
355
+ /**
356
+ * Upload a single file from buffer (Node.js)
357
+ * @example
358
+ * ```typescript
359
+ * const buffer = fs.readFileSync('./image.png');
360
+ * const result = await client.files.uploadBuffer(buffer, 'image.png', 'image/png');
361
+ * ```
362
+ */
363
+ async uploadBuffer(buffer, filename, mimeType) {
364
+ const formData = new FormData();
365
+ const blob = new Blob([buffer], { type: mimeType });
366
+ formData.append("file", blob, filename);
367
+ return this.upload(formData);
368
+ }
369
+ /**
370
+ * Upload a single file from Blob/File
371
+ * @example
372
+ * ```typescript
373
+ * const blob = new Blob([data], { type: 'image/png' });
374
+ * const result = await client.files.uploadFile(blob, 'image.png');
375
+ * ```
376
+ */
377
+ async uploadFile(file, filename) {
378
+ const formData = new FormData();
379
+ formData.append("file", file, filename || (file instanceof File ? file.name : "file"));
380
+ return this.upload(formData);
381
+ }
382
+ /**
383
+ * List uploaded files
384
+ * @example
385
+ * ```typescript
386
+ * const { files, pagination } = await client.files.list({ type: 'image', limit: 50 });
387
+ * ```
388
+ */
389
+ async list(options) {
390
+ return this.request("GET", "/api/v1/files", void 0, {
391
+ page: options?.page,
392
+ limit: options?.limit,
393
+ type: options?.type
394
+ });
395
+ }
396
+ /**
397
+ * Delete a file
398
+ * @example
399
+ * ```typescript
400
+ * const result = await client.files.delete('asset_001');
401
+ * ```
402
+ */
403
+ async delete(fileId) {
404
+ return this.request("DELETE", `/api/v1/files/${fileId}`);
405
+ }
406
+ /**
407
+ * Get file by ID (convenience method - searches through list)
408
+ * @example
409
+ * ```typescript
410
+ * const file = await client.files.get('asset_001');
411
+ * ```
412
+ */
413
+ async get(fileId) {
414
+ const { files } = await this.list({ limit: 100 });
415
+ return files.find((f) => f.id === fileId) || null;
416
+ }
417
+ };
418
+ var PreviewClient = class {
419
+ constructor(baseUrl, apiKey, timeout) {
420
+ this.baseUrl = baseUrl;
421
+ this.apiKey = apiKey;
422
+ this.timeout = timeout;
423
+ }
424
+ async request(method, endpoint, body, params) {
425
+ return request(this.baseUrl, this.apiKey, this.timeout, method, endpoint, body, params);
426
+ }
427
+ /**
428
+ * Create a temporary preview link (7 days validity, no credits consumed)
429
+ * @example
430
+ * ```typescript
431
+ * const preview = await client.preview.create({
432
+ * meta: { version: '2.0.0', width: 1920, height: 1080 },
433
+ * tracks: [{ clips: [{ type: 'text', text: 'Preview', start: 0, duration: 5 }] }]
434
+ * });
435
+ * console.log(preview.previewUrl, preview.tempId);
436
+ * ```
437
+ */
438
+ async create(config) {
439
+ return this.request("POST", "/api/v1/preview", { config });
440
+ }
441
+ /**
442
+ * Get preview configuration
443
+ * @example
444
+ * ```typescript
445
+ * const { config } = await client.preview.get('temp_abc123');
446
+ * ```
447
+ */
448
+ async get(tempId) {
449
+ return this.request("GET", `/api/v1/preview/${tempId}`);
450
+ }
451
+ /**
452
+ * Delete a preview link
453
+ * @example
454
+ * ```typescript
455
+ * const result = await client.preview.delete('temp_abc123');
456
+ * ```
457
+ */
458
+ async delete(tempId) {
459
+ return this.request("DELETE", `/api/v1/preview/${tempId}`);
460
+ }
461
+ /**
462
+ * Convert preview to permanent task (does not start rendering)
463
+ * @example
464
+ * ```typescript
465
+ * const result = await client.preview.convert('temp_abc123', { category: 'marketing' });
466
+ * console.log(result.taskId);
467
+ * ```
468
+ */
469
+ async convert(tempId, options) {
470
+ const body = {};
471
+ if (options?.category) body.category = options.category;
472
+ return this.request("POST", `/api/v1/preview/${tempId}/convert`, body);
473
+ }
474
+ /**
475
+ * Convert preview to permanent task and immediately start rendering
476
+ * @example
477
+ * ```typescript
478
+ * const result = await client.preview.render('temp_abc123', {
479
+ * webhookUrl: 'https://example.com/webhook'
480
+ * });
481
+ * console.log(result.taskId, result.status);
482
+ * ```
483
+ */
484
+ async render(tempId, options) {
485
+ const body = {};
486
+ if (options?.category) body.category = options.category;
487
+ if (options?.webhookUrl) body.webhook_url = options.webhookUrl;
488
+ if (options?.numWorkers) body.num_workers = options.numWorkers;
489
+ return this.request("POST", `/api/v1/preview/${tempId}/render`, body);
490
+ }
491
+ };
492
+ var RenderingVideo = class {
493
+ apiKey;
494
+ baseUrl;
495
+ timeout;
496
+ _video = null;
497
+ _files = null;
498
+ _preview = null;
499
+ constructor(apiKeyOrOptions, options) {
500
+ if (typeof apiKeyOrOptions === "string") {
501
+ this.apiKey = apiKeyOrOptions;
502
+ this.baseUrl = options?.baseUrl ?? DEFAULT_BASE_URL;
503
+ this.timeout = options?.timeout ?? DEFAULT_TIMEOUT;
504
+ } else {
505
+ this.apiKey = apiKeyOrOptions.apiKey;
506
+ this.baseUrl = apiKeyOrOptions.baseUrl ?? DEFAULT_BASE_URL;
507
+ this.timeout = apiKeyOrOptions.timeout ?? DEFAULT_TIMEOUT;
508
+ }
509
+ if (!this.apiKey) {
510
+ throw new Error("API key is required");
511
+ }
512
+ if (!this.apiKey.startsWith("sk-")) {
513
+ throw new Error('Invalid API key. API key should start with "sk-"');
514
+ }
515
+ }
516
+ /**
517
+ * Video API operations
518
+ */
519
+ get video() {
520
+ if (!this._video) {
521
+ this._video = new VideoClient(this.baseUrl, this.apiKey, this.timeout);
522
+ }
523
+ return this._video;
524
+ }
525
+ /**
526
+ * File API operations (upload, list, delete)
527
+ */
528
+ get files() {
529
+ if (!this._files) {
530
+ this._files = new FileClient(this.baseUrl, this.apiKey, this.timeout);
531
+ }
532
+ return this._files;
533
+ }
534
+ /**
535
+ * Preview API operations
536
+ */
537
+ get preview() {
538
+ if (!this._preview) {
539
+ this._preview = new PreviewClient(this.baseUrl, this.apiKey, this.timeout);
540
+ }
541
+ return this._preview;
542
+ }
543
+ /**
544
+ * Credits API operations
545
+ */
546
+ get credits() {
547
+ return new CreditsClient(this.baseUrl, this.apiKey, this.timeout);
548
+ }
549
+ /**
550
+ * Get masked API key for logging
551
+ */
552
+ get apiKeyPreview() {
553
+ return this.apiKey.length > 12 ? `${this.apiKey.slice(0, 8)}...${this.apiKey.slice(-4)}` : "***";
554
+ }
555
+ /**
556
+ * Get the base URL being used
557
+ */
558
+ get baseURL() {
559
+ return this.baseUrl;
560
+ }
561
+ };
562
+ var CreditsClient = class {
563
+ constructor(baseUrl, apiKey, timeout) {
564
+ this.baseUrl = baseUrl;
565
+ this.apiKey = apiKey;
566
+ this.timeout = timeout;
567
+ }
568
+ /**
569
+ * Get current credit balance
570
+ * @example
571
+ * ```typescript
572
+ * const { credits } = await client.credits.get();
573
+ * console.log(`You have ${credits} credits remaining`);
574
+ * ```
575
+ */
576
+ async get() {
577
+ return request(this.baseUrl, this.apiKey, this.timeout, "GET", "/api/v1/credits");
578
+ }
579
+ /**
580
+ * Check if user has enough credits for a render
581
+ * @example
582
+ * ```typescript
583
+ * const hasCredits = await client.credits.hasEnough(100);
584
+ * ```
585
+ */
586
+ async hasEnough(required) {
587
+ const { credits } = await this.get();
588
+ return credits >= required;
589
+ }
590
+ };
591
+
592
+ // src/index.ts
593
+ var index_default = RenderingVideo;
594
+ // Annotate the CommonJS export names for ESM import in node:
595
+ 0 && (module.exports = {
596
+ AlreadyRenderingError,
597
+ AuthenticationError,
598
+ CreditsClient,
599
+ FileClient,
600
+ InsufficientCreditsError,
601
+ InvalidApiKeyError,
602
+ NotFoundError,
603
+ PreviewClient,
604
+ RateLimitError,
605
+ RemoteError,
606
+ RenderingVideo,
607
+ RenderingVideoError,
608
+ StorageLimitError,
609
+ UploadError,
610
+ ValidationError,
611
+ VideoClient
612
+ });