alchemy 0.7.1 → 0.7.3
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/lib/cloudflare/bindings.d.ts +14 -2
- package/lib/cloudflare/bound.d.ts +3 -1
- package/lib/cloudflare/bucket.js +1 -0
- package/lib/cloudflare/d1-database.d.ts +18 -1
- package/lib/cloudflare/d1-database.js +42 -3
- package/lib/cloudflare/index.d.ts +1 -0
- package/lib/cloudflare/index.js +1 -0
- package/lib/cloudflare/pipeline.d.ts +335 -0
- package/lib/cloudflare/pipeline.js +250 -0
- package/lib/cloudflare/r2-rest-state-store.js +20 -32
- package/lib/cloudflare/worker.d.ts +9 -0
- package/lib/cloudflare/worker.js +13 -0
- package/package.json +1 -1
- package/src/cloudflare/bindings.ts +15 -0
- package/src/cloudflare/bound.ts +5 -1
- package/src/cloudflare/bucket.ts +1 -0
- package/src/cloudflare/d1-database.ts +61 -3
- package/src/cloudflare/index.ts +1 -0
- package/src/cloudflare/pipeline.ts +642 -0
- package/src/cloudflare/r2-rest-state-store.ts +23 -45
- package/src/cloudflare/worker.ts +25 -0
- package/src/esbuild/bundle.ts +3 -3
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type CloudflareApiOptions,
|
|
8
8
|
createCloudflareApi,
|
|
9
9
|
} from "./api";
|
|
10
|
+
import { CloudflareApiError, handleApiError } from "./api-error";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Options for CloudflareR2StateStore
|
|
@@ -106,21 +107,13 @@ export class R2RestStateStore implements StateStore {
|
|
|
106
107
|
const response = await this.api.get(listPath);
|
|
107
108
|
|
|
108
109
|
if (!response.ok) {
|
|
109
|
-
|
|
110
|
-
errors: [{ message: response.statusText }],
|
|
111
|
-
}));
|
|
112
|
-
throw new Error(
|
|
113
|
-
`Error listing R2 objects: ${errorData.errors?.[0]?.message || response.statusText}`
|
|
114
|
-
);
|
|
110
|
+
await handleApiError(response, "list", "bucket", this.bucketName);
|
|
115
111
|
}
|
|
116
112
|
|
|
117
113
|
return response;
|
|
118
114
|
},
|
|
119
115
|
// Retry on transient errors
|
|
120
|
-
|
|
121
|
-
error.message?.includes("502") ||
|
|
122
|
-
error.message?.includes("503") ||
|
|
123
|
-
error.message?.includes("timeout"),
|
|
116
|
+
isRetryableError,
|
|
124
117
|
5, // 5 retry attempts
|
|
125
118
|
1000 // Start with 1 second delay
|
|
126
119
|
);
|
|
@@ -173,26 +166,14 @@ export class R2RestStateStore implements StateStore {
|
|
|
173
166
|
`/accounts/${this.api.accountId}/r2/buckets/${this.bucketName}/objects/${this.getObjectKey(key)}`
|
|
174
167
|
);
|
|
175
168
|
|
|
176
|
-
if (!response.ok) {
|
|
177
|
-
|
|
178
|
-
return response;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const errorData: any = await response.json().catch(() => ({
|
|
182
|
-
errors: [{ message: response.statusText }],
|
|
183
|
-
}));
|
|
184
|
-
throw new Error(
|
|
185
|
-
`Error getting R2 object: ${errorData.errors?.[0]?.message || response.statusText}`
|
|
186
|
-
);
|
|
169
|
+
if (!response.ok && response.status !== 404) {
|
|
170
|
+
await handleApiError(response, "get", "object", key);
|
|
187
171
|
}
|
|
188
172
|
|
|
189
173
|
return response;
|
|
190
174
|
},
|
|
191
175
|
// Retry on transient errors
|
|
192
|
-
|
|
193
|
-
error.message?.includes("502") ||
|
|
194
|
-
error.message?.includes("503") ||
|
|
195
|
-
error.message?.includes("timeout"),
|
|
176
|
+
isRetryableError,
|
|
196
177
|
5, // 5 retry attempts
|
|
197
178
|
1000 // Start with 1 second delay
|
|
198
179
|
);
|
|
@@ -280,19 +261,12 @@ export class R2RestStateStore implements StateStore {
|
|
|
280
261
|
);
|
|
281
262
|
|
|
282
263
|
if (!response.ok) {
|
|
283
|
-
|
|
284
|
-
errors: [{ message: response.statusText }],
|
|
285
|
-
}));
|
|
286
|
-
throw new Error(
|
|
287
|
-
`Error writing to R2: ${errorData.errors?.[0]?.message || response.statusText}`
|
|
288
|
-
);
|
|
264
|
+
await handleApiError(response, "put", "object", objectKey);
|
|
289
265
|
}
|
|
290
|
-
|
|
291
266
|
return response;
|
|
292
267
|
},
|
|
293
268
|
// Retry on transient errors
|
|
294
|
-
|
|
295
|
-
error.message?.includes("503") || error.message?.includes("timeout"),
|
|
269
|
+
isRetryableError,
|
|
296
270
|
5, // 5 retry attempts
|
|
297
271
|
1000 // Start with 1 second delay
|
|
298
272
|
);
|
|
@@ -313,21 +287,12 @@ export class R2RestStateStore implements StateStore {
|
|
|
313
287
|
);
|
|
314
288
|
|
|
315
289
|
if (!response.ok && response.status !== 404) {
|
|
316
|
-
|
|
317
|
-
errors: [{ message: response.statusText }],
|
|
318
|
-
}));
|
|
319
|
-
throw new Error(
|
|
320
|
-
`Error deleting from R2: ${errorData.errors?.[0]?.message || response.statusText}`
|
|
321
|
-
);
|
|
290
|
+
await handleApiError(response, "delete", "object", key);
|
|
322
291
|
}
|
|
323
292
|
|
|
324
293
|
return response;
|
|
325
294
|
},
|
|
326
|
-
|
|
327
|
-
(error) =>
|
|
328
|
-
error.message?.includes("502") ||
|
|
329
|
-
error.message?.includes("503") ||
|
|
330
|
-
error.message?.includes("timeout"),
|
|
295
|
+
isRetryableError,
|
|
331
296
|
5, // 5 retry attempts
|
|
332
297
|
1000 // Start with 1 second delay
|
|
333
298
|
);
|
|
@@ -373,3 +338,16 @@ export class R2RestStateStore implements StateStore {
|
|
|
373
338
|
}
|
|
374
339
|
}
|
|
375
340
|
}
|
|
341
|
+
|
|
342
|
+
function isRetryableError(error: any): boolean {
|
|
343
|
+
if (error instanceof CloudflareApiError) {
|
|
344
|
+
return (
|
|
345
|
+
error.status === 500 ||
|
|
346
|
+
error.status === 502 ||
|
|
347
|
+
error.status === 503 ||
|
|
348
|
+
error.message.includes("timeout") ||
|
|
349
|
+
error.message.includes("internal error")
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
return false;
|
|
353
|
+
}
|
package/src/cloudflare/worker.ts
CHANGED
|
@@ -99,6 +99,17 @@ export interface WorkerProps<B extends Bindings = Bindings>
|
|
|
99
99
|
* Whether to adopt the Worker if it already exists when creating
|
|
100
100
|
*/
|
|
101
101
|
adopt?: boolean;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The compatibility date for the worker
|
|
105
|
+
* @default "2024-09-09"
|
|
106
|
+
*/
|
|
107
|
+
compatibilityDate?: string;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The compatibility flags for the worker
|
|
111
|
+
*/
|
|
112
|
+
compatibilityFlags?: string[];
|
|
102
113
|
}
|
|
103
114
|
|
|
104
115
|
/**
|
|
@@ -456,6 +467,8 @@ class NotFoundError extends Error {
|
|
|
456
467
|
}
|
|
457
468
|
|
|
458
469
|
interface WorkerMetadata {
|
|
470
|
+
compatibility_date: string;
|
|
471
|
+
compatibility_flags?: string[];
|
|
459
472
|
bindings: WorkerBindingSpec[];
|
|
460
473
|
observability: {
|
|
461
474
|
enabled: boolean;
|
|
@@ -490,6 +503,8 @@ async function prepareWorkerMetadata<B extends Bindings>(
|
|
|
490
503
|
): Promise<WorkerMetadata> {
|
|
491
504
|
// Prepare metadata with bindings
|
|
492
505
|
const meta: WorkerMetadata = {
|
|
506
|
+
compatibility_date: props.compatibilityDate ?? "2024-09-09",
|
|
507
|
+
compatibility_flags: props.compatibilityFlags,
|
|
493
508
|
bindings: [],
|
|
494
509
|
observability: {
|
|
495
510
|
enabled: props.observability?.enabled !== false,
|
|
@@ -590,6 +605,12 @@ async function prepareWorkerMetadata<B extends Bindings>(
|
|
|
590
605
|
name: bindingName,
|
|
591
606
|
queue_name: binding.name,
|
|
592
607
|
});
|
|
608
|
+
} else if (binding.type === "pipeline") {
|
|
609
|
+
meta.bindings.push({
|
|
610
|
+
type: "pipelines",
|
|
611
|
+
name: bindingName,
|
|
612
|
+
pipeline: binding.name,
|
|
613
|
+
});
|
|
593
614
|
} else {
|
|
594
615
|
// @ts-expect-error - we should never reach here
|
|
595
616
|
throw new Error(`Unsupported binding type: ${binding.type}`);
|
|
@@ -699,6 +720,10 @@ async function bundleWorkerScript<B extends Bindings>(props: WorkerProps) {
|
|
|
699
720
|
minify: true,
|
|
700
721
|
options: {
|
|
701
722
|
keepNames: true, // Important for Durable Object classes
|
|
723
|
+
loader: {
|
|
724
|
+
".sql": "text",
|
|
725
|
+
".json": "json",
|
|
726
|
+
},
|
|
702
727
|
},
|
|
703
728
|
};
|
|
704
729
|
|
package/src/esbuild/bundle.ts
CHANGED
|
@@ -116,7 +116,7 @@ export const Bundle = Resource(
|
|
|
116
116
|
async function (
|
|
117
117
|
this: Context<Bundle>,
|
|
118
118
|
id: string,
|
|
119
|
-
props: BundleProps
|
|
119
|
+
props: BundleProps
|
|
120
120
|
): Promise<Bundle> {
|
|
121
121
|
// Determine output path
|
|
122
122
|
const outputPath = getOutputPath(props);
|
|
@@ -145,7 +145,7 @@ export const Bundle = Resource(
|
|
|
145
145
|
path: outputPath,
|
|
146
146
|
hash,
|
|
147
147
|
});
|
|
148
|
-
}
|
|
148
|
+
}
|
|
149
149
|
);
|
|
150
150
|
|
|
151
151
|
export async function bundle(props: BundleProps) {
|
|
@@ -172,7 +172,7 @@ function getOutputPath(props: BundleProps) {
|
|
|
172
172
|
props.outfile ||
|
|
173
173
|
path.join(
|
|
174
174
|
props.outdir || "dist",
|
|
175
|
-
path.basename(props.entryPoint, path.extname(props.entryPoint)) + ".js"
|
|
175
|
+
path.basename(props.entryPoint, path.extname(props.entryPoint)) + ".js"
|
|
176
176
|
)
|
|
177
177
|
);
|
|
178
178
|
}
|