alchemy 0.26.0 → 0.26.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 (36) hide show
  1. package/lib/cloudflare/bindings.d.ts +2 -1
  2. package/lib/cloudflare/bindings.d.ts.map +1 -1
  3. package/lib/cloudflare/bindings.js.map +1 -1
  4. package/lib/cloudflare/bound.d.ts +4 -1
  5. package/lib/cloudflare/bound.d.ts.map +1 -1
  6. package/lib/cloudflare/dispatch-namespace.d.ts +94 -0
  7. package/lib/cloudflare/dispatch-namespace.d.ts.map +1 -0
  8. package/lib/cloudflare/dispatch-namespace.js +143 -0
  9. package/lib/cloudflare/dispatch-namespace.js.map +1 -0
  10. package/lib/cloudflare/index.d.ts +1 -0
  11. package/lib/cloudflare/index.d.ts.map +1 -1
  12. package/lib/cloudflare/index.js +1 -0
  13. package/lib/cloudflare/index.js.map +1 -1
  14. package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
  15. package/lib/cloudflare/worker-metadata.js +7 -0
  16. package/lib/cloudflare/worker-metadata.js.map +1 -1
  17. package/lib/cloudflare/worker.d.ts +12 -1
  18. package/lib/cloudflare/worker.d.ts.map +1 -1
  19. package/lib/cloudflare/worker.js +16 -3
  20. package/lib/cloudflare/worker.js.map +1 -1
  21. package/lib/cloudflare/wrangler.json.d.ts +7 -0
  22. package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
  23. package/lib/cloudflare/wrangler.json.js +10 -0
  24. package/lib/cloudflare/wrangler.json.js.map +1 -1
  25. package/lib/test/vitest.d.ts.map +1 -1
  26. package/lib/test/vitest.js +8 -3
  27. package/lib/test/vitest.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/cloudflare/bindings.ts +2 -0
  30. package/src/cloudflare/bound.ts +28 -25
  31. package/src/cloudflare/dispatch-namespace.ts +281 -0
  32. package/src/cloudflare/index.ts +1 -0
  33. package/src/cloudflare/worker-metadata.ts +6 -0
  34. package/src/cloudflare/worker.ts +40 -9
  35. package/src/cloudflare/wrangler.json.ts +21 -0
  36. package/src/test/vitest.ts +12 -3
@@ -478,6 +478,12 @@ export async function prepareWorkerMetadata<B extends Bindings>(
478
478
  type: "version_metadata",
479
479
  name: bindingName,
480
480
  });
481
+ } else if (binding.type === "dispatch_namespace") {
482
+ meta.bindings.push({
483
+ type: "dispatch_namespace",
484
+ name: bindingName,
485
+ namespace: binding.namespaceName,
486
+ });
481
487
  } else {
482
488
  // @ts-expect-error - we should never reach here
483
489
  throw new Error(`Unsupported binding type: ${binding.type}`);
@@ -34,6 +34,7 @@ import {
34
34
  bundleWorkerScript,
35
35
  } from "./bundle/bundle-worker.ts";
36
36
  import { isD1Database } from "./d1-database.ts";
37
+ import type { DispatchNamespaceResource } from "./dispatch-namespace.ts";
37
38
  import {
38
39
  DurableObjectNamespace,
39
40
  isDurableObjectNamespace,
@@ -250,6 +251,13 @@ export interface BaseWorkerProps<
250
251
  * This is only used when using the rpc property.
251
252
  */
252
253
  rpc?: (new (...args: any[]) => RPC) | type<RPC>;
254
+
255
+ /**
256
+ * Deploy this worker to a dispatch namespace
257
+ *
258
+ * This allows workers to be routed to via dispatch namespace routing rules
259
+ */
260
+ dispatchNamespace?: string | DispatchNamespaceResource;
253
261
  }
254
262
 
255
263
  export interface InlineWorkerProps<
@@ -416,6 +424,11 @@ export type Worker<
416
424
  * The compatibility flags for the worker
417
425
  */
418
426
  compatibilityFlags: string[];
427
+
428
+ /**
429
+ * The dispatch namespace this worker is deployed to
430
+ */
431
+ dispatchNamespace?: string | DispatchNamespaceResource;
419
432
  };
420
433
 
421
434
  /**
@@ -884,7 +897,20 @@ export const _Worker = Resource(
884
897
  assetUploadResult,
885
898
  );
886
899
 
887
- await putWorker(api, workerName, scriptBundle, scriptMetadata);
900
+ // Get dispatch namespace if specified
901
+ const dispatchNamespace = props.dispatchNamespace
902
+ ? typeof props.dispatchNamespace === "string"
903
+ ? props.dispatchNamespace
904
+ : props.dispatchNamespace.namespace
905
+ : undefined;
906
+
907
+ await putWorker(
908
+ api,
909
+ workerName,
910
+ scriptBundle,
911
+ scriptMetadata,
912
+ dispatchNamespace,
913
+ );
888
914
 
889
915
  for (const workflow of workflowsBindings) {
890
916
  if (
@@ -968,6 +994,8 @@ export const _Worker = Resource(
968
994
  // we are writing a stub worker (to remove binding/event source dependencies)
969
995
  // queue consumers will no longer exist by this point
970
996
  eventSources: undefined,
997
+ // stub worker doesn't need dispatch namespace
998
+ dispatchNamespace: undefined,
971
999
  });
972
1000
 
973
1001
  await withExponentialBackoff(
@@ -1081,6 +1109,8 @@ export const _Worker = Resource(
1081
1109
  crons: props.crons,
1082
1110
  // Include the created routes in the output
1083
1111
  routes: createdRoutes.length > 0 ? createdRoutes : undefined,
1112
+ // Include the dispatch namespace in the output
1113
+ dispatchNamespace: props.dispatchNamespace,
1084
1114
  // phantom property
1085
1115
  Env: undefined!,
1086
1116
  } as unknown as Worker<B>);
@@ -1128,6 +1158,7 @@ export async function putWorker(
1128
1158
  workerName: string,
1129
1159
  scriptBundle: string | NoBundleResult,
1130
1160
  scriptMetadata: WorkerMetadata,
1161
+ dispatchNamespace?: string,
1131
1162
  ) {
1132
1163
  return withExponentialBackoff(
1133
1164
  async () => {
@@ -1170,15 +1201,15 @@ export async function putWorker(
1170
1201
  );
1171
1202
 
1172
1203
  // Upload worker script with bindings
1173
- const uploadResponse = await api.put(
1174
- `/accounts/${api.accountId}/workers/scripts/${workerName}`,
1175
- formData,
1176
- {
1177
- headers: {
1178
- "Content-Type": "multipart/form-data",
1179
- },
1204
+ const endpoint = dispatchNamespace
1205
+ ? `/accounts/${api.accountId}/workers/dispatch/namespaces/${dispatchNamespace}/scripts/${workerName}`
1206
+ : `/accounts/${api.accountId}/workers/scripts/${workerName}`;
1207
+
1208
+ const uploadResponse = await api.put(endpoint, formData, {
1209
+ headers: {
1210
+ "Content-Type": "multipart/form-data",
1180
1211
  },
1181
- );
1212
+ });
1182
1213
 
1183
1214
  // Check if the upload was successful
1184
1215
  if (!uploadResponse.ok) {
@@ -363,6 +363,14 @@ export interface WranglerJsonSpec {
363
363
  version_metadata?: {
364
364
  binding: string;
365
365
  };
366
+
367
+ /**
368
+ * Dispatch namespace bindings
369
+ */
370
+ dispatch_namespaces?: {
371
+ binding: string;
372
+ namespace: string;
373
+ }[];
366
374
  }
367
375
 
368
376
  /**
@@ -429,6 +437,10 @@ function processBindings(
429
437
  store_id: string;
430
438
  secret_name: string;
431
439
  }[] = [];
440
+ const dispatchNamespaces: {
441
+ binding: string;
442
+ namespace: string;
443
+ }[] = [];
432
444
 
433
445
  for (const eventSource of eventSources ?? []) {
434
446
  if (isQueueEventSource(eventSource)) {
@@ -594,6 +606,11 @@ function processBindings(
594
606
  });
595
607
  }
596
608
  }
609
+ } else if (binding.type === "dispatch_namespace") {
610
+ dispatchNamespaces.push({
611
+ binding: bindingName,
612
+ namespace: binding.namespaceName,
613
+ });
597
614
  } else {
598
615
  // biome-ignore lint/correctness/noVoidTypeReturn: it returns never
599
616
  return assertNever(binding);
@@ -660,4 +677,8 @@ function processBindings(
660
677
  if (secretsStoreSecrets.length > 0) {
661
678
  spec.secrets_store_secrets = secretsStoreSecrets;
662
679
  }
680
+
681
+ if (dispatchNamespaces.length > 0) {
682
+ spec.dispatch_namespaces = dispatchNamespaces;
683
+ }
663
684
  }
@@ -114,8 +114,16 @@ type test = {
114
114
  * });
115
115
  * ```
116
116
  */
117
- export function test(meta: ImportMeta, defaultOptions?: TestOptions): test {
118
- defaultOptions = defaultOptions ?? {};
117
+ export function test(
118
+ meta: ImportMeta,
119
+ defaultOptions: TestOptions = {
120
+ quiet: true,
121
+ },
122
+ ): test {
123
+ if (!("quiet" in defaultOptions)) {
124
+ defaultOptions.quiet = true;
125
+ }
126
+
119
127
  if (
120
128
  defaultOptions.stateStore === undefined &&
121
129
  process.env.ALCHEMY_STATE_STORE === "cloudflare"
@@ -135,6 +143,7 @@ export function test(meta: ImportMeta, defaultOptions?: TestOptions): test {
135
143
  stateStore: defaultOptions?.stateStore,
136
144
  phase: "up",
137
145
  telemetryClient: new NoopTelemetryClient(),
146
+ quiet: defaultOptions.quiet,
138
147
  });
139
148
 
140
149
  test.beforeAll = (fn: (scope: Scope) => Promise<void>) => {
@@ -172,7 +181,7 @@ export function test(meta: ImportMeta, defaultOptions?: TestOptions): test {
172
181
  : {};
173
182
 
174
183
  const options: TestOptions = {
175
- quiet: false,
184
+ quiet: defaultOptions?.quiet ?? false,
176
185
  password: "test-password",
177
186
  ...spread(defaultOptions),
178
187
  ...spread(_options),