@renderinc/sdk 0.2.1 → 0.4.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/README.md +159 -42
- package/dist/experimental/experimental.d.ts +2 -2
- package/dist/experimental/experimental.d.ts.map +1 -1
- package/dist/experimental/experimental.js +4 -4
- package/dist/experimental/object/api.d.ts +2 -1
- package/dist/experimental/object/api.d.ts.map +1 -1
- package/dist/experimental/object/api.js +20 -3
- package/dist/experimental/object/client.d.ts +11 -5
- package/dist/experimental/object/client.d.ts.map +1 -1
- package/dist/experimental/object/client.js +78 -13
- package/dist/experimental/object/e2e-helpers.d.ts +3 -0
- package/dist/experimental/object/e2e-helpers.d.ts.map +1 -0
- package/dist/experimental/object/e2e-helpers.js +70 -0
- package/dist/experimental/object/index.d.ts +1 -1
- package/dist/experimental/object/index.d.ts.map +1 -1
- package/dist/experimental/object/types.d.ts +18 -0
- package/dist/experimental/object/types.d.ts.map +1 -1
- package/dist/generated/schema.d.ts +167 -28
- package/dist/generated/schema.d.ts.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +3 -1
- package/dist/workflows/client/client.d.ts +7 -3
- package/dist/workflows/client/client.d.ts.map +1 -1
- package/dist/workflows/client/client.js +96 -15
- package/dist/workflows/client/index.d.ts +2 -0
- package/dist/workflows/client/index.d.ts.map +1 -1
- package/dist/workflows/client/index.js +5 -1
- package/dist/workflows/client/sse.d.ts +0 -7
- package/dist/workflows/client/sse.d.ts.map +1 -1
- package/dist/workflows/client/sse.js +1 -71
- package/dist/workflows/client/task-run-promise.d.ts +12 -0
- package/dist/workflows/client/task-run-promise.d.ts.map +1 -0
- package/dist/workflows/client/task-run-promise.js +22 -0
- package/dist/workflows/client/task-run-result.d.ts +10 -0
- package/dist/workflows/client/task-run-result.d.ts.map +1 -0
- package/dist/workflows/client/task-run-result.js +18 -0
- package/dist/workflows/client/types.d.ts +2 -0
- package/dist/workflows/client/types.d.ts.map +1 -1
- package/dist/workflows/uds.d.ts +1 -0
- package/dist/workflows/uds.d.ts.map +1 -1
- package/dist/workflows/uds.js +30 -2
- package/dist/workflows/workflows.d.ts +19 -0
- package/dist/workflows/workflows.d.ts.map +1 -0
- package/dist/workflows/workflows.js +51 -0
- package/package.json +5 -1
- package/CHANGELOG.md +0 -33
- package/biome.json +0 -84
- package/examples/client/main.ts +0 -42
- package/examples/client/package-lock.json +0 -601
- package/examples/client/package.json +0 -16
- package/examples/client/tsconfig.json +0 -17
- package/examples/task/main.ts +0 -90
- package/examples/task/package-lock.json +0 -584
- package/examples/task/package.json +0 -16
- package/examples/task/tsconfig.json +0 -17
- package/src/errors.test.ts +0 -75
- package/src/errors.ts +0 -73
- package/src/experimental/experimental.ts +0 -56
- package/src/experimental/index.ts +0 -24
- package/src/experimental/object/api.ts +0 -91
- package/src/experimental/object/client.test.ts +0 -138
- package/src/experimental/object/client.ts +0 -317
- package/src/experimental/object/index.ts +0 -22
- package/src/experimental/object/types.test.ts +0 -87
- package/src/experimental/object/types.ts +0 -131
- package/src/generated/schema.ts +0 -12937
- package/src/index.ts +0 -7
- package/src/render.ts +0 -35
- package/src/utils/create-api-client.ts +0 -13
- package/src/utils/get-base-url.test.ts +0 -58
- package/src/utils/get-base-url.ts +0 -16
- package/src/version.ts +0 -37
- package/src/workflows/client/client.test.ts +0 -68
- package/src/workflows/client/client.ts +0 -142
- package/src/workflows/client/create-client.ts +0 -17
- package/src/workflows/client/index.ts +0 -3
- package/src/workflows/client/sse.ts +0 -95
- package/src/workflows/client/types.ts +0 -56
- package/src/workflows/executor.ts +0 -124
- package/src/workflows/index.ts +0 -7
- package/src/workflows/registry.test.ts +0 -76
- package/src/workflows/registry.ts +0 -88
- package/src/workflows/runner.ts +0 -38
- package/src/workflows/schema.ts +0 -348
- package/src/workflows/task.ts +0 -117
- package/src/workflows/types.test.ts +0 -52
- package/src/workflows/types.ts +0 -89
- package/src/workflows/uds.ts +0 -139
- package/test-types.ts +0 -14
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -23
- package/vitest.config.ts +0 -8
package/README.md
CHANGED
|
@@ -30,6 +30,12 @@ Or with pnpm:
|
|
|
30
30
|
pnpm add @renderinc/sdk
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
Or with Bun:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
bun add @renderinc/sdk
|
|
37
|
+
```
|
|
38
|
+
|
|
33
39
|
## Quick Start
|
|
34
40
|
|
|
35
41
|
### REST API Client
|
|
@@ -47,11 +53,13 @@ const result = await render.workflows.runTask('my-workflow/my-task', [42, 'hello
|
|
|
47
53
|
console.log('Status:', result.status);
|
|
48
54
|
console.log('Results:', result.results);
|
|
49
55
|
|
|
56
|
+
// Or start a task and decide when to await the result
|
|
57
|
+
const run = await render.workflows.startTask('my-workflow/my-task', [42, 'hello']);
|
|
58
|
+
console.log('Task run ID:', run.taskRunId);
|
|
59
|
+
const details = await run.get();
|
|
60
|
+
|
|
50
61
|
// List recent task runs
|
|
51
62
|
const taskRuns = await render.workflows.listTaskRuns({ limit: 10 });
|
|
52
|
-
|
|
53
|
-
// Get specific task run
|
|
54
|
-
const details = await render.workflows.getTaskRun(result.id);
|
|
55
63
|
```
|
|
56
64
|
|
|
57
65
|
Alternatively, you can create a workflows client directly:
|
|
@@ -125,9 +133,12 @@ Creates a new Render SDK instance with access to all Render products.
|
|
|
125
133
|
- `baseUrl?: string` - Base URL (defaults to `https://api.render.com`)
|
|
126
134
|
- `useLocalDev?: boolean` - Use local development mode
|
|
127
135
|
- `localDevUrl?: string` - Local development URL
|
|
136
|
+
- `ownerId?: string` - Default owner ID for object storage (falls back to `RENDER_WORKSPACE_ID` env var)
|
|
137
|
+
- `region?: string` - Default region for object storage (falls back to `RENDER_REGION` env var)
|
|
128
138
|
|
|
129
139
|
**Properties:**
|
|
130
140
|
- `workflows` - WorkflowsClient instance for managing workflow tasks
|
|
141
|
+
- `experimental` - ExperimentalClient instance for object storage and other experimental APIs
|
|
131
142
|
|
|
132
143
|
**Example:**
|
|
133
144
|
```typescript
|
|
@@ -175,6 +186,56 @@ const result = await render.workflows.runTask('my-workflow/square', [5]);
|
|
|
175
186
|
console.log('Results:', result.results);
|
|
176
187
|
```
|
|
177
188
|
|
|
189
|
+
#### `render.workflows.startTask(taskIdentifier, inputData, signal?)`
|
|
190
|
+
|
|
191
|
+
Starts a task run and returns a `TaskRunResult`. Results are not streamed until you call `.get()` on the returned result. Use this when you need the task run ID, want to defer awaiting, or want fire-and-forget.
|
|
192
|
+
|
|
193
|
+
**Parameters:**
|
|
194
|
+
- `taskIdentifier: string` - Task identifier in format "workflow-slug/task-name"
|
|
195
|
+
- `inputData: any[]` - Input data as array of parameters
|
|
196
|
+
- `signal?: AbortSignal` - Optional abort signal for cancellation
|
|
197
|
+
|
|
198
|
+
**Returns:** `Promise<TaskRunResult>`
|
|
199
|
+
|
|
200
|
+
**Example:**
|
|
201
|
+
```typescript
|
|
202
|
+
const render = new Render();
|
|
203
|
+
|
|
204
|
+
// Start a task and grab its ID
|
|
205
|
+
const run = await render.workflows.startTask('my-workflow/square', [5]);
|
|
206
|
+
console.log('Task run ID:', run.taskRunId);
|
|
207
|
+
|
|
208
|
+
// Await the result when you're ready
|
|
209
|
+
const result = await run.get();
|
|
210
|
+
console.log('Results:', result.results);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### `render.workflows.taskRunEvents(taskRunIds, signal?)`
|
|
214
|
+
|
|
215
|
+
Streams task run events as an async iterable. Yields a `TaskRunDetails` for each terminal event (completed or failed) received on the stream.
|
|
216
|
+
|
|
217
|
+
**Parameters:**
|
|
218
|
+
- `taskRunIds: string[]` - One or more task run IDs to subscribe to
|
|
219
|
+
- `signal?: AbortSignal` - Optional abort signal for cancellation
|
|
220
|
+
|
|
221
|
+
**Returns:** `AsyncGenerator<TaskRunDetails>`
|
|
222
|
+
|
|
223
|
+
**Example:**
|
|
224
|
+
```typescript
|
|
225
|
+
const render = new Render();
|
|
226
|
+
|
|
227
|
+
const run1 = await render.workflows.startTask('my-workflow/square', [3]);
|
|
228
|
+
const run2 = await render.workflows.startTask('my-workflow/square', [6]);
|
|
229
|
+
|
|
230
|
+
// The stream stays open until you break or abort.
|
|
231
|
+
const pending = new Set([run1.taskRunId, run2.taskRunId]);
|
|
232
|
+
for await (const event of render.workflows.taskRunEvents([...pending])) {
|
|
233
|
+
console.log('Event:', event.status, event.id, event.results);
|
|
234
|
+
pending.delete(event.id);
|
|
235
|
+
if (pending.size === 0) break;
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
178
239
|
#### `render.workflows.getTaskRun(taskRunId)`
|
|
179
240
|
|
|
180
241
|
Gets task run details by ID.
|
|
@@ -190,6 +251,22 @@ const render = new Render();
|
|
|
190
251
|
const details = await render.workflows.getTaskRun('task-run-id');
|
|
191
252
|
```
|
|
192
253
|
|
|
254
|
+
#### `render.workflows.cancelTaskRun(taskRunId)`
|
|
255
|
+
|
|
256
|
+
Cancels a running task.
|
|
257
|
+
|
|
258
|
+
**Parameters:**
|
|
259
|
+
- `taskRunId: string` - Task run ID to cancel
|
|
260
|
+
|
|
261
|
+
**Returns:** `Promise<void>`
|
|
262
|
+
|
|
263
|
+
**Example:**
|
|
264
|
+
```typescript
|
|
265
|
+
const render = new Render();
|
|
266
|
+
const run = await render.workflows.startTask('my-workflow/square', [5]);
|
|
267
|
+
await render.workflows.cancelTaskRun(run.taskRunId);
|
|
268
|
+
```
|
|
269
|
+
|
|
193
270
|
#### `render.workflows.listTaskRuns(params)`
|
|
194
271
|
|
|
195
272
|
Lists task runs with optional filters.
|
|
@@ -300,20 +377,36 @@ enum TaskRunStatus {
|
|
|
300
377
|
```typescript
|
|
301
378
|
interface TaskRun {
|
|
302
379
|
id: string;
|
|
380
|
+
taskId: string;
|
|
303
381
|
status: TaskRunStatus;
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
382
|
+
startedAt?: string;
|
|
383
|
+
completedAt?: string;
|
|
384
|
+
parentTaskRunId: string;
|
|
385
|
+
rootTaskRunId: string;
|
|
386
|
+
retries: number;
|
|
307
387
|
}
|
|
308
388
|
```
|
|
309
389
|
|
|
310
390
|
#### `TaskRunDetails`
|
|
311
391
|
|
|
312
392
|
```typescript
|
|
313
|
-
interface TaskRunDetails
|
|
314
|
-
|
|
315
|
-
|
|
393
|
+
interface TaskRunDetails {
|
|
394
|
+
id: string;
|
|
395
|
+
taskId: string;
|
|
396
|
+
status: TaskRunStatus;
|
|
397
|
+
results?: any;
|
|
316
398
|
error?: string;
|
|
399
|
+
startedAt?: string;
|
|
400
|
+
completedAt?: string;
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
#### `TaskRunResult`
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
class TaskRunResult {
|
|
408
|
+
readonly taskRunId: string;
|
|
409
|
+
get(): Promise<TaskRunDetails>;
|
|
317
410
|
}
|
|
318
411
|
```
|
|
319
412
|
|
|
@@ -340,6 +433,7 @@ The SDK provides several error classes:
|
|
|
340
433
|
import { Render } from '@renderinc/sdk';
|
|
341
434
|
import {
|
|
342
435
|
RenderError,
|
|
436
|
+
TaskRunError,
|
|
343
437
|
ClientError,
|
|
344
438
|
ServerError,
|
|
345
439
|
AbortError,
|
|
@@ -350,7 +444,9 @@ const render = new Render();
|
|
|
350
444
|
try {
|
|
351
445
|
const result = await render.workflows.runTask('my-workflow/task', [42]);
|
|
352
446
|
} catch (error) {
|
|
353
|
-
if (error instanceof
|
|
447
|
+
if (error instanceof TaskRunError) {
|
|
448
|
+
console.error('Task failed:', error.taskRunId, error.message);
|
|
449
|
+
} else if (error instanceof ClientError) {
|
|
354
450
|
console.error('Client error:', error.statusCode, error.cause);
|
|
355
451
|
} else if (error instanceof ServerError) {
|
|
356
452
|
console.error('Server error:', error.statusCode, error.cause);
|
|
@@ -365,11 +461,36 @@ try {
|
|
|
365
461
|
## Environment Variables
|
|
366
462
|
|
|
367
463
|
- `RENDER_API_KEY` - Your Render API key (required)
|
|
464
|
+
- `RENDER_WORKSPACE_ID` - Default owner ID for object storage (workspace team ID, e.g. `tea-xxxxx`)
|
|
465
|
+
- `RENDER_REGION` - Default region for object storage (e.g. `oregon`, `frankfurt`)
|
|
368
466
|
- `RENDER_USE_LOCAL_DEV` - Enable local development mode (`true`/`false`)
|
|
369
467
|
- `RENDER_LOCAL_DEV_URL` - Local development URL (default: `http://localhost:8120`)
|
|
370
468
|
- `RENDER_SDK_MODE` - Task execution mode (`run` or `register`)
|
|
371
469
|
- `RENDER_SDK_SOCKET_PATH` - Unix socket path for task communication
|
|
372
470
|
|
|
471
|
+
### Object Storage
|
|
472
|
+
|
|
473
|
+
When running on Render, `RENDER_WORKSPACE_ID` and `RENDER_REGION` are set automatically. You can also pass them as constructor options:
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
import { Render } from '@renderinc/sdk';
|
|
477
|
+
|
|
478
|
+
const render = new Render(); // Uses env vars for auth + object storage defaults
|
|
479
|
+
|
|
480
|
+
// Upload (no need to pass ownerId/region when env vars are set)
|
|
481
|
+
await render.experimental.storage.objects.put({
|
|
482
|
+
key: 'path/to/file.png',
|
|
483
|
+
data: Buffer.from('binary content'),
|
|
484
|
+
contentType: 'image/png',
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
// Download
|
|
488
|
+
const obj = await render.experimental.storage.objects.get({ key: 'path/to/file.png' });
|
|
489
|
+
|
|
490
|
+
// List
|
|
491
|
+
const response = await render.experimental.storage.objects.list();
|
|
492
|
+
```
|
|
493
|
+
|
|
373
494
|
## Examples
|
|
374
495
|
|
|
375
496
|
### Example 1: Running a Task
|
|
@@ -379,18 +500,14 @@ import { Render } from '@renderinc/sdk';
|
|
|
379
500
|
|
|
380
501
|
const render = new Render();
|
|
381
502
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
console.log('Square of 5 is:', result.results[0]); // 25
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
runSquareTask();
|
|
503
|
+
const result = await render.workflows.runTask('my-workflow/square', [5]);
|
|
504
|
+
console.log('Square of 5 is:', result.results[0]); // 25
|
|
388
505
|
```
|
|
389
506
|
|
|
390
507
|
### Example 2: Defining Tasks with Subtasks
|
|
391
508
|
|
|
392
509
|
```typescript
|
|
393
|
-
import { task
|
|
510
|
+
import { task } from '@renderinc/sdk/workflows';
|
|
394
511
|
|
|
395
512
|
const square = task(
|
|
396
513
|
{ name: 'square' },
|
|
@@ -407,8 +524,6 @@ task(
|
|
|
407
524
|
return Math.sqrt(aSquared + bSquared);
|
|
408
525
|
}
|
|
409
526
|
);
|
|
410
|
-
|
|
411
|
-
await startTaskServer();
|
|
412
527
|
```
|
|
413
528
|
|
|
414
529
|
### Example 3: Error Handling in Tasks
|
|
@@ -502,8 +617,7 @@ async function workflowExample() {
|
|
|
502
617
|
console.log(`\nRecent task runs: ${recentRuns.length}`);
|
|
503
618
|
|
|
504
619
|
for (const run of recentRuns) {
|
|
505
|
-
|
|
506
|
-
console.log(`- ${run.taskId}: ${details.status}`);
|
|
620
|
+
console.log(`- ${run.id}: ${run.status} (${run.taskId})`);
|
|
507
621
|
}
|
|
508
622
|
} catch (error) {
|
|
509
623
|
console.error('Error:', error);
|
|
@@ -544,30 +658,33 @@ npm run format
|
|
|
544
658
|
```
|
|
545
659
|
typescript/
|
|
546
660
|
├── src/
|
|
547
|
-
│ ├── render.ts
|
|
548
|
-
│ ├──
|
|
549
|
-
│
|
|
550
|
-
│
|
|
551
|
-
│
|
|
552
|
-
│
|
|
553
|
-
│
|
|
554
|
-
│
|
|
555
|
-
│
|
|
556
|
-
│
|
|
557
|
-
│
|
|
558
|
-
│
|
|
559
|
-
│
|
|
560
|
-
│
|
|
561
|
-
│
|
|
562
|
-
│
|
|
563
|
-
│
|
|
564
|
-
│
|
|
565
|
-
│
|
|
661
|
+
│ ├── render.ts # Main Render SDK class
|
|
662
|
+
│ ├── errors.ts # Error classes
|
|
663
|
+
│ ├── index.ts # Main exports
|
|
664
|
+
│ ├── version.ts # SDK version and user-agent
|
|
665
|
+
│ ├── workflows/ # Workflows functionality
|
|
666
|
+
│ │ ├── task.ts # task() function
|
|
667
|
+
│ │ ├── runner.ts # startTaskServer() and run()
|
|
668
|
+
│ │ ├── executor.ts # TaskExecutor
|
|
669
|
+
│ │ ├── registry.ts # TaskRegistry
|
|
670
|
+
│ │ ├── uds.ts # Unix socket client
|
|
671
|
+
│ │ ├── types.ts # Type definitions
|
|
672
|
+
│ │ ├── client/ # REST API client
|
|
673
|
+
│ │ │ ├── client.ts # WorkflowsClient class
|
|
674
|
+
│ │ │ ├── create-client.ts # createWorkflowsClient() factory
|
|
675
|
+
│ │ │ ├── task-run-result.ts # TaskRunResult class
|
|
676
|
+
│ │ │ ├── sse.ts # SSE event types
|
|
677
|
+
│ │ │ ├── types.ts # Client type definitions
|
|
678
|
+
│ │ │ └── index.ts # Exports
|
|
679
|
+
│ │ └── index.ts # Workflows exports
|
|
680
|
+
│ ├── experimental/ # Experimental features
|
|
681
|
+
│ │ └── object/ # Object storage API
|
|
682
|
+
│ └── utils/ # Shared utilities
|
|
566
683
|
├── examples/
|
|
567
|
-
│ ├── client/
|
|
684
|
+
│ ├── client/ # Client example
|
|
568
685
|
│ │ ├── main.ts
|
|
569
686
|
│ │ └── package.json
|
|
570
|
-
│ └── task/
|
|
687
|
+
│ └── task/ # Task example
|
|
571
688
|
│ ├── main.ts
|
|
572
689
|
│ └── package.json
|
|
573
690
|
├── package.json
|
|
@@ -3,10 +3,10 @@ import type { paths } from "../generated/schema.js";
|
|
|
3
3
|
import { ObjectClient } from "./object/client.js";
|
|
4
4
|
export declare class StorageClient {
|
|
5
5
|
readonly objects: ObjectClient;
|
|
6
|
-
constructor(apiClient: Client<paths
|
|
6
|
+
constructor(apiClient: Client<paths>, defaultOwnerId?: string, defaultRegion?: string);
|
|
7
7
|
}
|
|
8
8
|
export declare class ExperimentalClient {
|
|
9
9
|
readonly storage: StorageClient;
|
|
10
|
-
constructor(apiClient: Client<paths
|
|
10
|
+
constructor(apiClient: Client<paths>, defaultOwnerId?: string, defaultRegion?: string);
|
|
11
11
|
}
|
|
12
12
|
//# sourceMappingURL=experimental.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"experimental.d.ts","sourceRoot":"","sources":["../../src/experimental/experimental.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAgBlD,qBAAa,aAAa;IAExB,SAAgB,OAAO,EAAE,YAAY,CAAC;gBAE1B,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"experimental.d.ts","sourceRoot":"","sources":["../../src/experimental/experimental.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAgBlD,qBAAa,aAAa;IAExB,SAAgB,OAAO,EAAE,YAAY,CAAC;gBAE1B,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM;CAGtF;AAuBD,qBAAa,kBAAkB;IAE7B,SAAgB,OAAO,EAAE,aAAa,CAAC;gBAE3B,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM;CAGtF"}
|
|
@@ -3,14 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ExperimentalClient = exports.StorageClient = void 0;
|
|
4
4
|
const client_js_1 = require("./object/client.js");
|
|
5
5
|
class StorageClient {
|
|
6
|
-
constructor(apiClient) {
|
|
7
|
-
this.objects = new client_js_1.ObjectClient(apiClient);
|
|
6
|
+
constructor(apiClient, defaultOwnerId, defaultRegion) {
|
|
7
|
+
this.objects = new client_js_1.ObjectClient(apiClient, defaultOwnerId, defaultRegion);
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
exports.StorageClient = StorageClient;
|
|
11
11
|
class ExperimentalClient {
|
|
12
|
-
constructor(apiClient) {
|
|
13
|
-
this.storage = new StorageClient(apiClient);
|
|
12
|
+
constructor(apiClient, defaultOwnerId, defaultRegion) {
|
|
13
|
+
this.storage = new StorageClient(apiClient, defaultOwnerId, defaultRegion);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
exports.ExperimentalClient = ExperimentalClient;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { Client } from "openapi-fetch";
|
|
2
2
|
import type { paths } from "../../generated/schema.js";
|
|
3
|
-
import type { PresignedDownloadUrl, PresignedUploadUrl, Region } from "./types.js";
|
|
3
|
+
import type { ListObjectsResponse, PresignedDownloadUrl, PresignedUploadUrl, Region } from "./types.js";
|
|
4
4
|
export declare class ObjectApi {
|
|
5
5
|
private readonly apiClient;
|
|
6
6
|
constructor(apiClient: Client<paths>);
|
|
7
7
|
getUploadUrl(ownerId: string, region: Region | string, key: string, sizeBytes: number): Promise<PresignedUploadUrl>;
|
|
8
8
|
getDownloadUrl(ownerId: string, region: Region | string, key: string): Promise<PresignedDownloadUrl>;
|
|
9
9
|
delete(ownerId: string, region: Region | string, key: string): Promise<void>;
|
|
10
|
+
listObjects(ownerId: string, region: Region | string, cursor?: string, limit?: number): Promise<ListObjectsResponse>;
|
|
10
11
|
}
|
|
11
12
|
//# sourceMappingURL=api.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/experimental/object/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/experimental/object/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,KAAK,EACV,mBAAmB,EAEnB,oBAAoB,EACpB,kBAAkB,EAClB,MAAM,EACP,MAAM,YAAY,CAAC;AAUpB,qBAAa,SAAS;IACR,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC;IAW/C,YAAY,CAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,CAAC;IAyBxB,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,oBAAoB,CAAC;IAsB1B,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB5E,WAAW,CACf,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,mBAAmB,CAAC;CAoBhC"}
|
|
@@ -7,7 +7,7 @@ class ObjectApi {
|
|
|
7
7
|
this.apiClient = apiClient;
|
|
8
8
|
}
|
|
9
9
|
async getUploadUrl(ownerId, region, key, sizeBytes) {
|
|
10
|
-
const { data, error } = await this.apiClient.PUT("/
|
|
10
|
+
const { data, error } = await this.apiClient.PUT("/objects/{ownerId}/{region}/{key}", {
|
|
11
11
|
params: { path: { ownerId, region: region, key } },
|
|
12
12
|
body: { sizeBytes },
|
|
13
13
|
});
|
|
@@ -21,7 +21,7 @@ class ObjectApi {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
async getDownloadUrl(ownerId, region, key) {
|
|
24
|
-
const { data, error } = await this.apiClient.GET("/
|
|
24
|
+
const { data, error } = await this.apiClient.GET("/objects/{ownerId}/{region}/{key}", {
|
|
25
25
|
params: { path: { ownerId, region: region, key } },
|
|
26
26
|
});
|
|
27
27
|
if (error) {
|
|
@@ -33,12 +33,29 @@ class ObjectApi {
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
async delete(ownerId, region, key) {
|
|
36
|
-
const { error } = await this.apiClient.DELETE("/
|
|
36
|
+
const { error } = await this.apiClient.DELETE("/objects/{ownerId}/{region}/{key}", {
|
|
37
37
|
params: { path: { ownerId, region: region, key } },
|
|
38
38
|
});
|
|
39
39
|
if (error) {
|
|
40
40
|
throw new errors_js_1.RenderError(`Failed to delete object: ${error.message || "Unknown error"}`);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
+
async listObjects(ownerId, region, cursor, limit) {
|
|
44
|
+
const { data, error } = await this.apiClient.GET("/objects/{ownerId}/{region}", {
|
|
45
|
+
params: {
|
|
46
|
+
path: { ownerId, region: region },
|
|
47
|
+
query: { cursor, limit },
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
if (error) {
|
|
51
|
+
throw new errors_js_1.RenderError(`Failed to list objects: ${error.message || "Unknown error"}`);
|
|
52
|
+
}
|
|
53
|
+
const objects = data.items.map((item) => ({
|
|
54
|
+
key: item.object.key,
|
|
55
|
+
size: item.object.sizeBytes,
|
|
56
|
+
lastModified: new Date(item.object.lastModified),
|
|
57
|
+
}));
|
|
58
|
+
return { objects, hasNext: data.hasNext, nextCursor: data.nextCursor };
|
|
59
|
+
}
|
|
43
60
|
}
|
|
44
61
|
exports.ObjectApi = ObjectApi;
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import type { Client } from "openapi-fetch";
|
|
2
2
|
import type { paths } from "../../generated/schema.js";
|
|
3
|
-
import type { DeleteObjectInput, GetObjectInput, ObjectData, ObjectScope, PutObjectInput, PutObjectResult, ScopedDeleteObjectInput, ScopedGetObjectInput, ScopedPutObjectInput } from "./types.js";
|
|
3
|
+
import type { DeleteObjectInput, GetObjectInput, ListObjectsInput, ListObjectsResponse, ObjectData, ObjectScope, OptionalScope, PutObjectInput, PutObjectResult, ScopedDeleteObjectInput, ScopedGetObjectInput, ScopedListObjectsInput, ScopedPutObjectInput } from "./types.js";
|
|
4
4
|
export declare class ObjectClient {
|
|
5
5
|
private readonly apiClient;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
private readonly defaultOwnerId?;
|
|
7
|
+
private readonly defaultRegion?;
|
|
8
|
+
constructor(apiClient: Client<paths>, defaultOwnerId?: string, defaultRegion?: string);
|
|
9
|
+
private resolveOwnerId;
|
|
10
|
+
private resolveRegion;
|
|
11
|
+
put(input: OptionalScope<PutObjectInput>): Promise<PutObjectResult>;
|
|
12
|
+
get(input: OptionalScope<GetObjectInput>): Promise<ObjectData>;
|
|
13
|
+
delete(input: OptionalScope<DeleteObjectInput>): Promise<void>;
|
|
14
|
+
list(input: OptionalScope<ListObjectsInput>): Promise<ListObjectsResponse>;
|
|
10
15
|
scoped(scope: ObjectScope): ScopedObjectClient;
|
|
11
16
|
private resolveSize;
|
|
12
17
|
}
|
|
@@ -17,5 +22,6 @@ export declare class ScopedObjectClient {
|
|
|
17
22
|
put(input: ScopedPutObjectInput): Promise<PutObjectResult>;
|
|
18
23
|
get(input: ScopedGetObjectInput): Promise<ObjectData>;
|
|
19
24
|
delete(input: ScopedDeleteObjectInput): Promise<void>;
|
|
25
|
+
list(input?: ScopedListObjectsInput): Promise<ListObjectsResponse>;
|
|
20
26
|
}
|
|
21
27
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/experimental/object/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/experimental/object/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,UAAU,EAEV,WAAW,EACX,aAAa,EACb,cAAc,EACd,eAAe,EAEf,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AASpB,qBAAa,YAAY;IAKrB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAkB;gBAG9B,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,EACzC,cAAc,CAAC,EAAE,MAAM,EACvB,aAAa,CAAC,EAAE,MAAM;IAMxB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,aAAa;IA4Cf,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;IAwFnE,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IAkD9D,MAAM,CAAC,KAAK,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAgD9D,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAiDhF,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,kBAAkB;IAU9C,OAAO,CAAC,WAAW;CA0BpB;AAQD,qBAAa,kBAAkB;IAK3B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAJxB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;gBAG1C,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,EACP,KAAK,EAAE,WAAW;IAqB/B,GAAG,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,eAAe,CAAC;IAmB1D,GAAG,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC;IAkBrD,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBrD,IAAI,CAAC,KAAK,GAAE,sBAA2B,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAM7E"}
|
|
@@ -1,18 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ScopedObjectClient = exports.ObjectClient = void 0;
|
|
4
|
+
const node_stream_1 = require("node:stream");
|
|
4
5
|
const errors_js_1 = require("../../errors.js");
|
|
5
6
|
class ObjectClient {
|
|
6
|
-
constructor(apiClient) {
|
|
7
|
+
constructor(apiClient, defaultOwnerId, defaultRegion) {
|
|
7
8
|
this.apiClient = apiClient;
|
|
9
|
+
this.defaultOwnerId = defaultOwnerId;
|
|
10
|
+
this.defaultRegion = defaultRegion;
|
|
11
|
+
}
|
|
12
|
+
resolveOwnerId(ownerId) {
|
|
13
|
+
const resolved = ownerId || this.defaultOwnerId;
|
|
14
|
+
if (!resolved) {
|
|
15
|
+
throw new errors_js_1.RenderError("ownerId is required. Provide it as a parameter or set the RENDER_WORKSPACE_ID environment variable.");
|
|
16
|
+
}
|
|
17
|
+
return resolved;
|
|
18
|
+
}
|
|
19
|
+
resolveRegion(region) {
|
|
20
|
+
const resolved = region || this.defaultRegion;
|
|
21
|
+
if (!resolved) {
|
|
22
|
+
throw new errors_js_1.RenderError("region is required. Provide it as a parameter or set the RENDER_REGION environment variable.");
|
|
23
|
+
}
|
|
24
|
+
return resolved;
|
|
8
25
|
}
|
|
9
26
|
async put(input) {
|
|
27
|
+
const ownerId = this.resolveOwnerId(input.ownerId);
|
|
28
|
+
const region = this.resolveRegion(input.region);
|
|
10
29
|
const size = this.resolveSize(input);
|
|
11
|
-
const { data, error } = await this.apiClient.PUT("/
|
|
30
|
+
const { data, error } = await this.apiClient.PUT("/objects/{ownerId}/{region}/{key}", {
|
|
12
31
|
params: {
|
|
13
32
|
path: {
|
|
14
|
-
ownerId
|
|
15
|
-
region:
|
|
33
|
+
ownerId,
|
|
34
|
+
region: region,
|
|
16
35
|
key: input.key,
|
|
17
36
|
},
|
|
18
37
|
},
|
|
@@ -21,16 +40,27 @@ class ObjectClient {
|
|
|
21
40
|
if (error) {
|
|
22
41
|
throw new errors_js_1.RenderError(`Failed to get upload URL: ${error.message || "Unknown error"}`);
|
|
23
42
|
}
|
|
43
|
+
if (size !== data.maxSizeBytes) {
|
|
44
|
+
throw new errors_js_1.ClientError(`File size ${size} bytes does not match expected size of ${data.maxSizeBytes} bytes`, 400);
|
|
45
|
+
}
|
|
24
46
|
const headers = {
|
|
25
47
|
"Content-Length": size.toString(),
|
|
26
48
|
};
|
|
27
49
|
if (input.contentType) {
|
|
28
50
|
headers["Content-Type"] = input.contentType;
|
|
29
51
|
}
|
|
52
|
+
let body = input.data;
|
|
53
|
+
if (process.versions.bun && input.data instanceof node_stream_1.Readable) {
|
|
54
|
+
const chunks = [];
|
|
55
|
+
for await (const chunk of input.data) {
|
|
56
|
+
chunks.push(Buffer.from(chunk));
|
|
57
|
+
}
|
|
58
|
+
body = Buffer.concat(chunks);
|
|
59
|
+
}
|
|
30
60
|
const response = await fetch(data.url, {
|
|
31
61
|
method: "PUT",
|
|
32
62
|
headers,
|
|
33
|
-
body
|
|
63
|
+
body,
|
|
34
64
|
duplex: "half",
|
|
35
65
|
});
|
|
36
66
|
if (!response.ok) {
|
|
@@ -41,11 +71,13 @@ class ObjectClient {
|
|
|
41
71
|
};
|
|
42
72
|
}
|
|
43
73
|
async get(input) {
|
|
44
|
-
const
|
|
74
|
+
const ownerId = this.resolveOwnerId(input.ownerId);
|
|
75
|
+
const region = this.resolveRegion(input.region);
|
|
76
|
+
const { data, error } = await this.apiClient.GET("/objects/{ownerId}/{region}/{key}", {
|
|
45
77
|
params: {
|
|
46
78
|
path: {
|
|
47
|
-
ownerId
|
|
48
|
-
region:
|
|
79
|
+
ownerId,
|
|
80
|
+
region: region,
|
|
49
81
|
key: input.key,
|
|
50
82
|
},
|
|
51
83
|
},
|
|
@@ -66,11 +98,13 @@ class ObjectClient {
|
|
|
66
98
|
};
|
|
67
99
|
}
|
|
68
100
|
async delete(input) {
|
|
69
|
-
const
|
|
101
|
+
const ownerId = this.resolveOwnerId(input.ownerId);
|
|
102
|
+
const region = this.resolveRegion(input.region);
|
|
103
|
+
const { error } = await this.apiClient.DELETE("/objects/{ownerId}/{region}/{key}", {
|
|
70
104
|
params: {
|
|
71
105
|
path: {
|
|
72
|
-
ownerId
|
|
73
|
-
region:
|
|
106
|
+
ownerId,
|
|
107
|
+
region: region,
|
|
74
108
|
key: input.key,
|
|
75
109
|
},
|
|
76
110
|
},
|
|
@@ -79,6 +113,31 @@ class ObjectClient {
|
|
|
79
113
|
throw new errors_js_1.RenderError(`Failed to delete object: ${error.message || "Unknown error"}`);
|
|
80
114
|
}
|
|
81
115
|
}
|
|
116
|
+
async list(input) {
|
|
117
|
+
const ownerId = this.resolveOwnerId(input.ownerId);
|
|
118
|
+
const region = this.resolveRegion(input.region);
|
|
119
|
+
const { data, error } = await this.apiClient.GET("/objects/{ownerId}/{region}", {
|
|
120
|
+
params: {
|
|
121
|
+
path: {
|
|
122
|
+
ownerId,
|
|
123
|
+
region: region,
|
|
124
|
+
},
|
|
125
|
+
query: {
|
|
126
|
+
cursor: input.cursor,
|
|
127
|
+
limit: input.limit,
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
if (error) {
|
|
132
|
+
throw new errors_js_1.RenderError(`Failed to list objects: ${error.message || "Unknown error"}`);
|
|
133
|
+
}
|
|
134
|
+
const objects = data.items.map((item) => ({
|
|
135
|
+
key: item.object.key,
|
|
136
|
+
size: item.object.sizeBytes,
|
|
137
|
+
lastModified: new Date(item.object.lastModified),
|
|
138
|
+
}));
|
|
139
|
+
return { objects, hasNext: data.hasNext, nextCursor: data.nextCursor };
|
|
140
|
+
}
|
|
82
141
|
scoped(scope) {
|
|
83
142
|
return new ScopedObjectClient(this.apiClient, scope);
|
|
84
143
|
}
|
|
@@ -93,8 +152,8 @@ class ObjectClient {
|
|
|
93
152
|
if (input.size === undefined) {
|
|
94
153
|
throw new errors_js_1.RenderError("Size is required for stream and string inputs. Provide the size parameter.");
|
|
95
154
|
}
|
|
96
|
-
if (input.size
|
|
97
|
-
throw new errors_js_1.RenderError("Size must be a
|
|
155
|
+
if (input.size < 0) {
|
|
156
|
+
throw new errors_js_1.RenderError("Size must be a non-negative integer");
|
|
98
157
|
}
|
|
99
158
|
return input.size;
|
|
100
159
|
}
|
|
@@ -123,5 +182,11 @@ class ScopedObjectClient {
|
|
|
123
182
|
...input,
|
|
124
183
|
});
|
|
125
184
|
}
|
|
185
|
+
async list(input = {}) {
|
|
186
|
+
return this.objectClient.list({
|
|
187
|
+
...this.scope,
|
|
188
|
+
...input,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
126
191
|
}
|
|
127
192
|
exports.ScopedObjectClient = ScopedObjectClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2e-helpers.d.ts","sourceRoot":"","sources":["../../../src/experimental/object/e2e-helpers.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAchD,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,OAAO,MAAM,EAAE,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAsEjB"}
|