@renderinc/sdk 0.1.0 → 0.2.1

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.
Files changed (126) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +17 -7
  3. package/biome.json +84 -0
  4. package/dist/experimental/blob/api.d.ts +11 -0
  5. package/dist/experimental/blob/api.d.ts.map +1 -0
  6. package/dist/experimental/blob/api.js +44 -0
  7. package/dist/experimental/blob/client.d.ts +21 -0
  8. package/dist/experimental/blob/client.d.ts.map +1 -0
  9. package/dist/experimental/blob/client.js +127 -0
  10. package/dist/experimental/blob/index.d.ts +5 -0
  11. package/dist/experimental/blob/index.d.ts.map +1 -0
  12. package/dist/experimental/blob/index.js +8 -0
  13. package/dist/experimental/blob/types.d.ts +49 -0
  14. package/dist/experimental/blob/types.d.ts.map +1 -0
  15. package/dist/experimental/experimental.d.ts +12 -0
  16. package/dist/experimental/experimental.d.ts.map +1 -0
  17. package/dist/experimental/experimental.js +16 -0
  18. package/dist/experimental/index.d.ts +3 -0
  19. package/dist/experimental/index.d.ts.map +1 -0
  20. package/dist/experimental/index.js +10 -0
  21. package/dist/experimental/object/api.d.ts +11 -0
  22. package/dist/experimental/object/api.d.ts.map +1 -0
  23. package/dist/experimental/object/api.js +44 -0
  24. package/dist/experimental/object/client.d.ts +21 -0
  25. package/dist/experimental/object/client.d.ts.map +1 -0
  26. package/dist/experimental/object/client.js +127 -0
  27. package/dist/experimental/object/index.d.ts +5 -0
  28. package/dist/experimental/object/index.d.ts.map +1 -0
  29. package/dist/experimental/object/index.js +8 -0
  30. package/dist/experimental/object/types.d.ts +49 -0
  31. package/dist/experimental/object/types.d.ts.map +1 -0
  32. package/dist/experimental/object/types.js +2 -0
  33. package/dist/generated/schema.d.ts +9910 -0
  34. package/dist/generated/schema.d.ts.map +1 -0
  35. package/dist/generated/schema.js +2 -0
  36. package/dist/index.d.ts +3 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +5 -2
  39. package/dist/render.d.ts +2 -0
  40. package/dist/render.d.ts.map +1 -1
  41. package/dist/render.js +4 -2
  42. package/dist/utils/create-api-client.d.ts +1 -1
  43. package/dist/utils/create-api-client.d.ts.map +1 -1
  44. package/dist/utils/create-api-client.js +2 -0
  45. package/dist/version.d.ts +3 -0
  46. package/dist/version.d.ts.map +1 -0
  47. package/dist/version.js +23 -0
  48. package/dist/workflows/client/client.d.ts +1 -1
  49. package/dist/workflows/client/client.d.ts.map +1 -1
  50. package/dist/workflows/client/sse.d.ts +2 -2
  51. package/dist/workflows/client/sse.d.ts.map +1 -1
  52. package/dist/workflows/client/sse.js +2 -0
  53. package/dist/workflows/client/types.d.ts +1 -1
  54. package/dist/workflows/client/types.d.ts.map +1 -1
  55. package/dist/workflows/executor.d.ts +2 -2
  56. package/dist/workflows/executor.d.ts.map +1 -1
  57. package/dist/workflows/registry.d.ts +1 -1
  58. package/dist/workflows/registry.d.ts.map +1 -1
  59. package/dist/workflows/registry.js +13 -6
  60. package/dist/workflows/runner.d.ts.map +1 -1
  61. package/dist/workflows/runner.js +2 -0
  62. package/dist/workflows/schema.d.ts +9 -0
  63. package/dist/workflows/schema.d.ts.map +1 -1
  64. package/dist/workflows/task.d.ts +1 -0
  65. package/dist/workflows/task.d.ts.map +1 -1
  66. package/dist/workflows/task.js +34 -0
  67. package/dist/workflows/types.d.ts +3 -1
  68. package/dist/workflows/types.d.ts.map +1 -1
  69. package/dist/workflows/uds.d.ts +1 -1
  70. package/dist/workflows/uds.d.ts.map +1 -1
  71. package/dist/workflows/uds.js +27 -82
  72. package/examples/client/main.ts +42 -0
  73. package/examples/client/package-lock.json +601 -0
  74. package/examples/client/package.json +16 -0
  75. package/examples/client/tsconfig.json +17 -0
  76. package/examples/task/main.ts +90 -0
  77. package/examples/task/package-lock.json +584 -0
  78. package/examples/task/package.json +16 -0
  79. package/examples/task/tsconfig.json +17 -0
  80. package/package.json +19 -27
  81. package/src/errors.test.ts +75 -0
  82. package/src/errors.ts +73 -0
  83. package/src/experimental/experimental.ts +56 -0
  84. package/src/experimental/index.ts +24 -0
  85. package/src/experimental/object/api.ts +91 -0
  86. package/src/experimental/object/client.test.ts +138 -0
  87. package/src/experimental/object/client.ts +317 -0
  88. package/src/experimental/object/index.ts +22 -0
  89. package/src/experimental/object/types.test.ts +87 -0
  90. package/src/experimental/object/types.ts +131 -0
  91. package/src/generated/schema.ts +12937 -0
  92. package/src/index.ts +7 -0
  93. package/src/render.ts +35 -0
  94. package/src/utils/create-api-client.ts +13 -0
  95. package/src/utils/get-base-url.test.ts +58 -0
  96. package/src/utils/get-base-url.ts +16 -0
  97. package/src/version.ts +37 -0
  98. package/src/workflows/client/client.test.ts +68 -0
  99. package/src/workflows/client/client.ts +142 -0
  100. package/src/workflows/client/create-client.ts +17 -0
  101. package/src/workflows/client/index.ts +3 -0
  102. package/src/workflows/client/sse.ts +95 -0
  103. package/src/workflows/client/types.ts +56 -0
  104. package/src/workflows/executor.ts +124 -0
  105. package/src/workflows/index.ts +7 -0
  106. package/src/workflows/registry.test.ts +76 -0
  107. package/src/workflows/registry.ts +88 -0
  108. package/src/workflows/runner.ts +38 -0
  109. package/src/workflows/schema.ts +348 -0
  110. package/src/workflows/task.ts +117 -0
  111. package/src/workflows/types.test.ts +52 -0
  112. package/src/workflows/types.ts +89 -0
  113. package/src/workflows/uds.ts +139 -0
  114. package/test-types.ts +14 -0
  115. package/tsconfig.build.json +4 -0
  116. package/tsconfig.json +23 -0
  117. package/vitest.config.ts +8 -0
  118. package/dist/workflows/client/errors.d.ts +0 -25
  119. package/dist/workflows/client/errors.d.ts.map +0 -1
  120. package/dist/workflows/client/errors.js +0 -56
  121. package/dist/workflows/client/schema.d.ts +0 -9322
  122. package/dist/workflows/client/schema.d.ts.map +0 -1
  123. package/dist/workflows/client/workflows.d.ts +0 -15
  124. package/dist/workflows/client/workflows.d.ts.map +0 -1
  125. package/dist/workflows/client/workflows.js +0 -63
  126. /package/dist/{workflows/client/schema.js → experimental/blob/types.js} +0 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ All notable changes to the `@renderinc/sdk` TypeScript SDK will be documented in this file.
4
+
5
+ This project follows [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [0.2.1] - 2026-01-29
8
+
9
+ ### Changed
10
+ - Updated package name in README from @render/sdk to @renderinc/sdk
11
+ - Renamed experimental blob storage API to object storage (Blob* -> Object*)
12
+ - Switched internal workflows task communication from SSE to HTTP requests
13
+
14
+ ## [0.2.0] - 2026-01-26
15
+
16
+ ### Added
17
+ - Add experimental blob storage API with `BlobClient` and `ScopedBlobClient`
18
+ - Add plan support for task execution
19
+ - Add per-task timeout override via `timeoutSeconds` option
20
+
21
+ ### Changed
22
+ - Auto-start task server on task registration (no need to call `startTaskServer()` manually)
23
+ - Rename `wait_duration` to `wait_duration_ms` for cross-SDK consistency
24
+ - Move generated API schema to `generated/` directory
25
+
26
+ ## [0.1.0] - 2025-12-15
27
+
28
+ ### Added
29
+ - Add initial TypeScript SDK for Render Workflows
30
+ - Add task registration and execution via `@renderinc/sdk/workflows`
31
+ - Add `TaskContext` for task metadata and subtask execution
32
+ - Add configurable retry policies with exponential backoff
33
+ - Add generated OpenAPI types for full type safety
package/README.md CHANGED
@@ -95,8 +95,10 @@ task(
95
95
  retry: {
96
96
  maxRetries: 3,
97
97
  waitDurationMs: 1000,
98
- factor: 1.5,
98
+ backoffScaling: 1.5,
99
99
  },
100
+ timeoutSeconds: 86400, // 24h
101
+ plan: 'starter',
100
102
  },
101
103
  async function retryableTask(input: string): Promise<string> {
102
104
  // Task implementation
@@ -104,8 +106,10 @@ task(
104
106
  }
105
107
  );
106
108
 
107
- // Start the task server
108
- await startTaskServer();
109
+ // The task server starts automatically when running in a workflow environment
110
+ // (when RENDER_SDK_SOCKET_PATH is set). No need to call startTaskServer() explicitly.
111
+ //
112
+ // To disable auto-start, set RENDER_SDK_AUTO_START=false in your environment.
109
113
  ```
110
114
 
111
115
  ## API Reference
@@ -215,7 +219,9 @@ Registers a function as a task.
215
219
  - `retry?: RetryOptions` - Optional retry configuration
216
220
  - `maxRetries: number` - Maximum number of retries
217
221
  - `waitDurationMs: number` - Wait duration between retries in milliseconds
218
- - `factor?: number` - Backoff factor (default: 1.5)
222
+ - `backoffScaling?: number` - Backoff multiplier (default: 1.5)
223
+ - `timeoutSeconds?: number` - Maximum execution time in seconds
224
+ - `plan?: string` - Resource plan for task execution (e.g., `"starter"`, `"standard"`, `"pro"`)
219
225
  - `func: TaskFunction` - The task function to register
220
226
 
221
227
  **Returns:** The registered function with the same signature
@@ -230,15 +236,17 @@ const myTask = task(
230
236
  }
231
237
  );
232
238
 
233
- // With retry options
239
+ // With retry, timeout, and plan options
234
240
  task(
235
241
  {
236
242
  name: 'retryableTask',
237
243
  retry: {
238
244
  maxRetries: 3,
239
245
  waitDurationMs: 1000,
240
- factor: 1.5,
246
+ backoffScaling: 1.5,
241
247
  },
248
+ timeoutSeconds: 300,
249
+ plan: 'starter',
242
250
  },
243
251
  function retryableTask(arg: string): string {
244
252
  return arg.toUpperCase();
@@ -317,8 +325,10 @@ interface RegisterTaskOptions {
317
325
  retry?: {
318
326
  maxRetries: number;
319
327
  waitDurationMs: number;
320
- factor?: number; // default 1.5
328
+ backoffScaling?: number; // default 1.5
321
329
  };
330
+ timeoutSeconds?: number;
331
+ plan?: string; // e.g., "starter", "standard", "pro"
322
332
  }
323
333
  ```
324
334
 
package/biome.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
3
+ "vcs": {
4
+ "enabled": true,
5
+ "clientKind": "git",
6
+ "useIgnoreFile": true
7
+ },
8
+ "files": {
9
+ "ignoreUnknown": false,
10
+ "includes": ["**", "!!**/src/generated/**/*"]
11
+ },
12
+ "formatter": {
13
+ "enabled": true,
14
+ "indentStyle": "space",
15
+ "indentWidth": 2,
16
+ "lineWidth": 100
17
+ },
18
+ "linter": {
19
+ "enabled": true,
20
+ "rules": {
21
+ "recommended": true,
22
+ "performance": {
23
+ "noAccumulatingSpread": "error",
24
+ "noDelete": "error",
25
+ "noDynamicNamespaceImportAccess": "error",
26
+ "noNamespaceImport": "error",
27
+ "useTopLevelRegex": "error"
28
+ },
29
+ "complexity": {
30
+ "noCommaOperator": "error",
31
+ "noForEach": "error",
32
+ "noUselessConstructor": "error",
33
+ "noUselessEmptyExport": "error",
34
+ "noUselessFragments": "error",
35
+ "noUselessLabel": "error",
36
+ "noUselessLoneBlockStatements": "error",
37
+ "noUselessRename": "error",
38
+ "noUselessSwitchCase": "error",
39
+ "noUselessTypeConstraint": "error",
40
+ "useArrowFunction": "error",
41
+ "useLiteralKeys": "error"
42
+ },
43
+ "suspicious": {
44
+ "noExplicitAny": "off"
45
+ },
46
+ "style": {
47
+ "noImplicitBoolean": "error",
48
+ "noNegationElse": "error",
49
+ "noParameterAssign": "warn",
50
+ "noRestrictedGlobals": "error",
51
+ "noRestrictedImports": {
52
+ "level": "error",
53
+ "options": {
54
+ "paths": {
55
+ "vitest": {
56
+ "message": "Vitest functions are automatically imported.",
57
+ "allowImportNames": ["Mock"]
58
+ }
59
+ }
60
+ }
61
+ },
62
+ "useDefaultParameterLast": "error",
63
+ "useExponentiationOperator": "error",
64
+ "useNodejsImportProtocol": "error",
65
+ "useNumberNamespace": "error",
66
+ "useSingleVarDeclarator": "error",
67
+ "noCommonJs": "error",
68
+ "useNumericSeparators": "error",
69
+ "useReadonlyClassProperties": "error",
70
+ "useUnifiedTypeSignatures": "error"
71
+ }
72
+ }
73
+ },
74
+ "javascript": {
75
+ "formatter": {
76
+ "quoteStyle": "double",
77
+ "trailingCommas": "all",
78
+ "semicolons": "always",
79
+ "quoteProperties": "asNeeded",
80
+ "bracketSpacing": true,
81
+ "arrowParentheses": "always"
82
+ }
83
+ }
84
+ }
@@ -0,0 +1,11 @@
1
+ import type { Client } from "openapi-fetch";
2
+ import type { paths } from "../../generated/schema.js";
3
+ import type { PresignedDownloadUrl, PresignedUploadUrl, Region } from "./types.js";
4
+ export declare class BlobApi {
5
+ private readonly apiClient;
6
+ constructor(apiClient: Client<paths>);
7
+ getUploadUrl(ownerId: string, region: Region | string, key: string, sizeBytes: number): Promise<PresignedUploadUrl>;
8
+ getDownloadUrl(ownerId: string, region: Region | string, key: string): Promise<PresignedDownloadUrl>;
9
+ delete(ownerId: string, region: Region | string, key: string): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/experimental/blob/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,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAUnF,qBAAa,OAAO;IACN,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;CASnF"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BlobApi = void 0;
4
+ const errors_js_1 = require("../../errors.js");
5
+ class BlobApi {
6
+ constructor(apiClient) {
7
+ this.apiClient = apiClient;
8
+ }
9
+ async getUploadUrl(ownerId, region, key, sizeBytes) {
10
+ const { data, error } = await this.apiClient.PUT("/blobs/{ownerId}/{region}/{key}", {
11
+ params: { path: { ownerId, region: region, key } },
12
+ body: { sizeBytes },
13
+ });
14
+ if (error) {
15
+ throw new errors_js_1.RenderError(`Failed to get upload URL: ${error.message || "Unknown error"}`);
16
+ }
17
+ return {
18
+ url: data.url,
19
+ expiresAt: new Date(data.expiresAt),
20
+ maxSizeBytes: data.maxSizeBytes,
21
+ };
22
+ }
23
+ async getDownloadUrl(ownerId, region, key) {
24
+ const { data, error } = await this.apiClient.GET("/blobs/{ownerId}/{region}/{key}", {
25
+ params: { path: { ownerId, region: region, key } },
26
+ });
27
+ if (error) {
28
+ throw new errors_js_1.RenderError(`Failed to get download URL: ${error.message || "Unknown error"}`);
29
+ }
30
+ return {
31
+ url: data.url,
32
+ expiresAt: new Date(data.expiresAt),
33
+ };
34
+ }
35
+ async delete(ownerId, region, key) {
36
+ const { error } = await this.apiClient.DELETE("/blobs/{ownerId}/{region}/{key}", {
37
+ params: { path: { ownerId, region: region, key } },
38
+ });
39
+ if (error) {
40
+ throw new errors_js_1.RenderError(`Failed to delete blob: ${error.message || "Unknown error"}`);
41
+ }
42
+ }
43
+ }
44
+ exports.BlobApi = BlobApi;
@@ -0,0 +1,21 @@
1
+ import type { Client } from "openapi-fetch";
2
+ import type { paths } from "../../generated/schema.js";
3
+ import type { BlobData, BlobScope, DeleteBlobInput, GetBlobInput, PutBlobInput, PutBlobResult, ScopedDeleteBlobInput, ScopedGetBlobInput, ScopedPutBlobInput } from "./types.js";
4
+ export declare class BlobClient {
5
+ private readonly apiClient;
6
+ constructor(apiClient: Client<paths>);
7
+ put(input: PutBlobInput): Promise<PutBlobResult>;
8
+ get(input: GetBlobInput): Promise<BlobData>;
9
+ delete(input: DeleteBlobInput): Promise<void>;
10
+ scoped(scope: BlobScope): ScopedBlobClient;
11
+ private resolveSize;
12
+ }
13
+ export declare class ScopedBlobClient {
14
+ private readonly scope;
15
+ private readonly blobClient;
16
+ constructor(apiClient: Client<paths>, scope: BlobScope);
17
+ put(input: ScopedPutBlobInput): Promise<PutBlobResult>;
18
+ get(input: ScopedGetBlobInput): Promise<BlobData>;
19
+ delete(input: ScopedDeleteBlobInput): Promise<void>;
20
+ }
21
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/experimental/blob/client.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,QAAQ,EACR,SAAS,EACT,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,EAEb,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AASpB,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC;IAgC/C,GAAG,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAgEhD,GAAG,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC;IA+C3C,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCnD,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,gBAAgB;IAU1C,OAAO,CAAC,WAAW;CA0BpB;AAQD,qBAAa,gBAAgB;IAKzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAJxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;gBAGtC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,EACP,KAAK,EAAE,SAAS;IAqB7B,GAAG,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;IAmBtD,GAAG,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAkBjD,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CAM1D"}
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScopedBlobClient = exports.BlobClient = void 0;
4
+ const errors_js_1 = require("../../errors.js");
5
+ class BlobClient {
6
+ constructor(apiClient) {
7
+ this.apiClient = apiClient;
8
+ }
9
+ async put(input) {
10
+ const size = this.resolveSize(input);
11
+ const { data, error } = await this.apiClient.PUT("/blobs/{ownerId}/{region}/{key}", {
12
+ params: {
13
+ path: {
14
+ ownerId: input.ownerId,
15
+ region: input.region,
16
+ key: input.key,
17
+ },
18
+ },
19
+ body: { sizeBytes: size },
20
+ });
21
+ if (error) {
22
+ throw new errors_js_1.RenderError(`Failed to get upload URL: ${error.message || "Unknown error"}`);
23
+ }
24
+ const headers = {
25
+ "Content-Length": size.toString(),
26
+ };
27
+ if (input.contentType) {
28
+ headers["Content-Type"] = input.contentType;
29
+ }
30
+ const response = await fetch(data.url, {
31
+ method: "PUT",
32
+ headers,
33
+ body: input.data,
34
+ duplex: "half",
35
+ });
36
+ if (!response.ok) {
37
+ throw new errors_js_1.RenderError(`Upload failed: ${response.status} ${response.statusText}`);
38
+ }
39
+ return {
40
+ etag: response.headers.get("ETag") ?? undefined,
41
+ };
42
+ }
43
+ async get(input) {
44
+ const { data, error } = await this.apiClient.GET("/blobs/{ownerId}/{region}/{key}", {
45
+ params: {
46
+ path: {
47
+ ownerId: input.ownerId,
48
+ region: input.region,
49
+ key: input.key,
50
+ },
51
+ },
52
+ });
53
+ if (error) {
54
+ throw new errors_js_1.RenderError(`Failed to get download URL: ${error.message || "Unknown error"}`);
55
+ }
56
+ const response = await fetch(data.url);
57
+ if (!response.ok) {
58
+ throw new errors_js_1.RenderError(`Download failed: ${response.status} ${response.statusText}`);
59
+ }
60
+ const arrayBuffer = await response.arrayBuffer();
61
+ const buffer = Buffer.from(arrayBuffer);
62
+ return {
63
+ data: buffer,
64
+ size: buffer.byteLength,
65
+ contentType: response.headers.get("Content-Type") ?? undefined,
66
+ };
67
+ }
68
+ async delete(input) {
69
+ const { error } = await this.apiClient.DELETE("/blobs/{ownerId}/{region}/{key}", {
70
+ params: {
71
+ path: {
72
+ ownerId: input.ownerId,
73
+ region: input.region,
74
+ key: input.key,
75
+ },
76
+ },
77
+ });
78
+ if (error) {
79
+ throw new errors_js_1.RenderError(`Failed to delete blob: ${error.message || "Unknown error"}`);
80
+ }
81
+ }
82
+ scoped(scope) {
83
+ return new ScopedBlobClient(this.apiClient, scope);
84
+ }
85
+ resolveSize(input) {
86
+ if (Buffer.isBuffer(input.data) || input.data instanceof Uint8Array) {
87
+ const actualSize = input.data.byteLength;
88
+ if (input.size !== undefined && input.size !== actualSize) {
89
+ throw new errors_js_1.RenderError(`Size mismatch: provided size ${input.size} does not match actual size ${actualSize}`);
90
+ }
91
+ return actualSize;
92
+ }
93
+ if (input.size === undefined) {
94
+ throw new errors_js_1.RenderError("Size is required for stream and string inputs. Provide the size parameter.");
95
+ }
96
+ if (input.size <= 0) {
97
+ throw new errors_js_1.RenderError("Size must be a positive integer");
98
+ }
99
+ return input.size;
100
+ }
101
+ }
102
+ exports.BlobClient = BlobClient;
103
+ class ScopedBlobClient {
104
+ constructor(apiClient, scope) {
105
+ this.scope = scope;
106
+ this.blobClient = new BlobClient(apiClient);
107
+ }
108
+ async put(input) {
109
+ return this.blobClient.put({
110
+ ...this.scope,
111
+ ...input,
112
+ });
113
+ }
114
+ async get(input) {
115
+ return this.blobClient.get({
116
+ ...this.scope,
117
+ ...input,
118
+ });
119
+ }
120
+ async delete(input) {
121
+ return this.blobClient.delete({
122
+ ...this.scope,
123
+ ...input,
124
+ });
125
+ }
126
+ }
127
+ exports.ScopedBlobClient = ScopedBlobClient;
@@ -0,0 +1,5 @@
1
+ export { BlobApi } from "./api.js";
2
+ export { BlobClient, ScopedBlobClient } from "./client.js";
3
+ export type { BlobData, BlobIdentifier, BlobScope, DeleteBlobInput, GetBlobInput, PresignedDownloadUrl, PresignedUploadUrl, PutBlobInput, PutBlobInputBuffer, PutBlobInputStream, PutBlobResult, ScopedDeleteBlobInput, ScopedGetBlobInput, ScopedPutBlobInput, } from "./types.js";
4
+ export { Region } from "./types.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/experimental/blob/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE3D,YAAY,EACV,QAAQ,EACR,cAAc,EACd,SAAS,EACT,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScopedBlobClient = exports.BlobClient = exports.BlobApi = void 0;
4
+ var api_js_1 = require("./api.js");
5
+ Object.defineProperty(exports, "BlobApi", { enumerable: true, get: function () { return api_js_1.BlobApi; } });
6
+ var client_js_1 = require("./client.js");
7
+ Object.defineProperty(exports, "BlobClient", { enumerable: true, get: function () { return client_js_1.BlobClient; } });
8
+ Object.defineProperty(exports, "ScopedBlobClient", { enumerable: true, get: function () { return client_js_1.ScopedBlobClient; } });
@@ -0,0 +1,49 @@
1
+ import type { Readable } from "node:stream";
2
+ export type Region = "frankfurt" | "oregon" | "ohio" | "singapore" | "virginia";
3
+ export interface BlobIdentifier {
4
+ ownerId: `tea-${string}`;
5
+ region: Region | string;
6
+ key: string;
7
+ }
8
+ interface PutBlobInputBase extends BlobIdentifier {
9
+ contentType?: string;
10
+ }
11
+ export interface PutBlobInputBuffer extends PutBlobInputBase {
12
+ data: Buffer | Uint8Array | string;
13
+ size?: number;
14
+ }
15
+ export interface PutBlobInputStream extends PutBlobInputBase {
16
+ data: Readable;
17
+ size: number;
18
+ }
19
+ export type PutBlobInput = PutBlobInputBuffer | PutBlobInputStream;
20
+ export interface GetBlobInput extends BlobIdentifier {
21
+ }
22
+ export interface DeleteBlobInput extends BlobIdentifier {
23
+ }
24
+ export interface PresignedUploadUrl {
25
+ url: string;
26
+ expiresAt: Date;
27
+ maxSizeBytes: number;
28
+ }
29
+ export interface PresignedDownloadUrl {
30
+ url: string;
31
+ expiresAt: Date;
32
+ }
33
+ export interface BlobData {
34
+ data: Buffer;
35
+ contentType?: string;
36
+ size: number;
37
+ }
38
+ export interface PutBlobResult {
39
+ etag?: string;
40
+ }
41
+ export interface BlobScope {
42
+ ownerId: `tea-${string}`;
43
+ region: Region | string;
44
+ }
45
+ export type ScopedPutBlobInput = Omit<PutBlobInput, keyof BlobScope>;
46
+ export type ScopedGetBlobInput = Omit<GetBlobInput, keyof BlobScope>;
47
+ export type ScopedDeleteBlobInput = Omit<DeleteBlobInput, keyof BlobScope>;
48
+ export {};
49
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/experimental/blob/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAK5C,MAAM,MAAM,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;AAKhF,MAAM,WAAW,cAAc;IAE7B,OAAO,EAAE,OAAO,MAAM,EAAE,CAAC;IAEzB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAExB,GAAG,EAAE,MAAM,CAAC;CACb;AAKD,UAAU,gBAAiB,SAAQ,cAAc;IAE/C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAE1D,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IAEnC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAE1D,IAAI,EAAE,QAAQ,CAAC;IAEf,IAAI,EAAE,MAAM,CAAC;CACd;AAMD,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAKnE,MAAM,WAAW,YAAa,SAAQ,cAAc;CAAG;AAKvD,MAAM,WAAW,eAAgB,SAAQ,cAAc;CAAG;AAK1D,MAAM,WAAW,kBAAkB;IAEjC,GAAG,EAAE,MAAM,CAAC;IAEZ,SAAS,EAAE,IAAI,CAAC;IAEhB,YAAY,EAAE,MAAM,CAAC;CACtB;AAKD,MAAM,WAAW,oBAAoB;IAEnC,GAAG,EAAE,MAAM,CAAC;IAEZ,SAAS,EAAE,IAAI,CAAC;CACjB;AAKD,MAAM,WAAW,QAAQ;IAEvB,IAAI,EAAE,MAAM,CAAC;IAEb,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,IAAI,EAAE,MAAM,CAAC;CACd;AAKD,MAAM,WAAW,aAAa;IAE5B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAKD,MAAM,WAAW,SAAS;IAExB,OAAO,EAAE,OAAO,MAAM,EAAE,CAAC;IAEzB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAKD,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,SAAS,CAAC,CAAC;AAKrE,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,SAAS,CAAC,CAAC;AAKrE,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,eAAe,EAAE,MAAM,SAAS,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Client } from "openapi-fetch";
2
+ import type { paths } from "../generated/schema.js";
3
+ import { ObjectClient } from "./object/client.js";
4
+ export declare class StorageClient {
5
+ readonly objects: ObjectClient;
6
+ constructor(apiClient: Client<paths>);
7
+ }
8
+ export declare class ExperimentalClient {
9
+ readonly storage: StorageClient;
10
+ constructor(apiClient: Client<paths>);
11
+ }
12
+ //# sourceMappingURL=experimental.d.ts.map
@@ -0,0 +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;CAGrC;AAuBD,qBAAa,kBAAkB;IAE7B,SAAgB,OAAO,EAAE,aAAa,CAAC;gBAE3B,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC;CAGrC"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExperimentalClient = exports.StorageClient = void 0;
4
+ const client_js_1 = require("./object/client.js");
5
+ class StorageClient {
6
+ constructor(apiClient) {
7
+ this.objects = new client_js_1.ObjectClient(apiClient);
8
+ }
9
+ }
10
+ exports.StorageClient = StorageClient;
11
+ class ExperimentalClient {
12
+ constructor(apiClient) {
13
+ this.storage = new StorageClient(apiClient);
14
+ }
15
+ }
16
+ exports.ExperimentalClient = ExperimentalClient;
@@ -0,0 +1,3 @@
1
+ export { ExperimentalClient, StorageClient } from "./experimental.js";
2
+ export { type DeleteObjectInput, type GetObjectInput, ObjectApi, ObjectClient, type ObjectData, type ObjectIdentifier, type ObjectScope, type PresignedDownloadUrl, type PresignedUploadUrl, type PutObjectInput, type PutObjectInputBuffer, type PutObjectInputStream, type PutObjectResult, Region, type ScopedDeleteObjectInput, type ScopedGetObjectInput, ScopedObjectClient, type ScopedPutObjectInput, } from "./object/index.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/experimental/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEtE,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,SAAS,EACT,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,MAAM,EACN,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,kBAAkB,EAClB,KAAK,oBAAoB,GAC1B,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScopedObjectClient = exports.ObjectClient = exports.ObjectApi = exports.StorageClient = exports.ExperimentalClient = void 0;
4
+ var experimental_js_1 = require("./experimental.js");
5
+ Object.defineProperty(exports, "ExperimentalClient", { enumerable: true, get: function () { return experimental_js_1.ExperimentalClient; } });
6
+ Object.defineProperty(exports, "StorageClient", { enumerable: true, get: function () { return experimental_js_1.StorageClient; } });
7
+ var index_js_1 = require("./object/index.js");
8
+ Object.defineProperty(exports, "ObjectApi", { enumerable: true, get: function () { return index_js_1.ObjectApi; } });
9
+ Object.defineProperty(exports, "ObjectClient", { enumerable: true, get: function () { return index_js_1.ObjectClient; } });
10
+ Object.defineProperty(exports, "ScopedObjectClient", { enumerable: true, get: function () { return index_js_1.ScopedObjectClient; } });
@@ -0,0 +1,11 @@
1
+ import type { Client } from "openapi-fetch";
2
+ import type { paths } from "../../generated/schema.js";
3
+ import type { PresignedDownloadUrl, PresignedUploadUrl, Region } from "./types.js";
4
+ export declare class ObjectApi {
5
+ private readonly apiClient;
6
+ constructor(apiClient: Client<paths>);
7
+ getUploadUrl(ownerId: string, region: Region | string, key: string, sizeBytes: number): Promise<PresignedUploadUrl>;
8
+ getDownloadUrl(ownerId: string, region: Region | string, key: string): Promise<PresignedDownloadUrl>;
9
+ delete(ownerId: string, region: Region | string, key: string): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +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,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAUnF,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;CASnF"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ObjectApi = void 0;
4
+ const errors_js_1 = require("../../errors.js");
5
+ class ObjectApi {
6
+ constructor(apiClient) {
7
+ this.apiClient = apiClient;
8
+ }
9
+ async getUploadUrl(ownerId, region, key, sizeBytes) {
10
+ const { data, error } = await this.apiClient.PUT("/blobs/{ownerId}/{region}/{key}", {
11
+ params: { path: { ownerId, region: region, key } },
12
+ body: { sizeBytes },
13
+ });
14
+ if (error) {
15
+ throw new errors_js_1.RenderError(`Failed to get upload URL: ${error.message || "Unknown error"}`);
16
+ }
17
+ return {
18
+ url: data.url,
19
+ expiresAt: new Date(data.expiresAt),
20
+ maxSizeBytes: data.maxSizeBytes,
21
+ };
22
+ }
23
+ async getDownloadUrl(ownerId, region, key) {
24
+ const { data, error } = await this.apiClient.GET("/blobs/{ownerId}/{region}/{key}", {
25
+ params: { path: { ownerId, region: region, key } },
26
+ });
27
+ if (error) {
28
+ throw new errors_js_1.RenderError(`Failed to get download URL: ${error.message || "Unknown error"}`);
29
+ }
30
+ return {
31
+ url: data.url,
32
+ expiresAt: new Date(data.expiresAt),
33
+ };
34
+ }
35
+ async delete(ownerId, region, key) {
36
+ const { error } = await this.apiClient.DELETE("/blobs/{ownerId}/{region}/{key}", {
37
+ params: { path: { ownerId, region: region, key } },
38
+ });
39
+ if (error) {
40
+ throw new errors_js_1.RenderError(`Failed to delete object: ${error.message || "Unknown error"}`);
41
+ }
42
+ }
43
+ }
44
+ exports.ObjectApi = ObjectApi;
@@ -0,0 +1,21 @@
1
+ import type { Client } from "openapi-fetch";
2
+ import type { paths } from "../../generated/schema.js";
3
+ import type { DeleteObjectInput, GetObjectInput, ObjectData, ObjectScope, PutObjectInput, PutObjectResult, ScopedDeleteObjectInput, ScopedGetObjectInput, ScopedPutObjectInput } from "./types.js";
4
+ export declare class ObjectClient {
5
+ private readonly apiClient;
6
+ constructor(apiClient: Client<paths>);
7
+ put(input: PutObjectInput): Promise<PutObjectResult>;
8
+ get(input: GetObjectInput): Promise<ObjectData>;
9
+ delete(input: DeleteObjectInput): Promise<void>;
10
+ scoped(scope: ObjectScope): ScopedObjectClient;
11
+ private resolveSize;
12
+ }
13
+ export declare class ScopedObjectClient {
14
+ private readonly scope;
15
+ private readonly objectClient;
16
+ constructor(apiClient: Client<paths>, scope: ObjectScope);
17
+ put(input: ScopedPutObjectInput): Promise<PutObjectResult>;
18
+ get(input: ScopedGetObjectInput): Promise<ObjectData>;
19
+ delete(input: ScopedDeleteObjectInput): Promise<void>;
20
+ }
21
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/experimental/object/client.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,iBAAiB,EACjB,cAAc,EACd,UAAU,EACV,WAAW,EACX,cAAc,EACd,eAAe,EAEf,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AASpB,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC;IAgC/C,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAgEpD,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IA+C/C,MAAM,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCrD,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;CAM5D"}