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.
@@ -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
- const errorData: any = await response.json().catch(() => ({
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
- (error) =>
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
- if (response.status === 404) {
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
- (error) =>
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
- const errorData: any = await response.json().catch(() => ({
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
- (error) =>
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
- const errorData: any = await response.json().catch(() => ({
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
- // Retry on transient errors
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
+ }
@@ -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
 
@@ -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
  }