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