alchemy 0.83.1 → 0.83.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.
Files changed (129) hide show
  1. package/bin/alchemy.js +18 -10
  2. package/bin/commands/deploy.ts +2 -0
  3. package/bin/commands/destroy.ts +1 -1
  4. package/bin/services/execute-alchemy.ts +11 -0
  5. package/bin/services/package-manager.ts +5 -1
  6. package/lib/alchemy.d.ts +8 -0
  7. package/lib/alchemy.d.ts.map +1 -1
  8. package/lib/alchemy.js +4 -0
  9. package/lib/alchemy.js.map +1 -1
  10. package/lib/aws/ec2/internet-gateway-attachment.d.ts.map +1 -1
  11. package/lib/aws/ec2/internet-gateway-attachment.js.map +1 -1
  12. package/lib/aws/function.js.map +1 -1
  13. package/lib/aws/oidc/github-oidc-provider.d.ts.map +1 -1
  14. package/lib/aws/oidc/github-oidc-provider.js.map +1 -1
  15. package/lib/cloudflare/api-response.d.ts.map +1 -1
  16. package/lib/cloudflare/api-response.js.map +1 -1
  17. package/lib/cloudflare/api-schema.d.ts.map +1 -1
  18. package/lib/cloudflare/api-schema.js.map +1 -1
  19. package/lib/cloudflare/api-shield.d.ts.map +1 -1
  20. package/lib/cloudflare/api-shield.js.map +1 -1
  21. package/lib/cloudflare/astro/astro.d.ts.map +1 -1
  22. package/lib/cloudflare/astro/astro.js.map +1 -1
  23. package/lib/cloudflare/astro/plugin.d.ts.map +1 -1
  24. package/lib/cloudflare/astro/plugin.js +15 -1
  25. package/lib/cloudflare/astro/plugin.js.map +1 -1
  26. package/lib/cloudflare/bucket-custom-domain.d.ts.map +1 -1
  27. package/lib/cloudflare/bucket-custom-domain.js.map +1 -1
  28. package/lib/cloudflare/bucket.d.ts +1 -1
  29. package/lib/cloudflare/bucket.d.ts.map +1 -1
  30. package/lib/cloudflare/bucket.js +1 -1
  31. package/lib/cloudflare/bucket.js.map +1 -1
  32. package/lib/cloudflare/bundle/plugin-wasm.d.ts.map +1 -1
  33. package/lib/cloudflare/bundle/plugin-wasm.js +4 -2
  34. package/lib/cloudflare/bundle/plugin-wasm.js.map +1 -1
  35. package/lib/cloudflare/container.d.ts.map +1 -1
  36. package/lib/cloudflare/container.js.map +1 -1
  37. package/lib/cloudflare/dispatch-namespace.d.ts.map +1 -1
  38. package/lib/cloudflare/dispatch-namespace.js.map +1 -1
  39. package/lib/cloudflare/logpush-job.d.ts.map +1 -1
  40. package/lib/cloudflare/logpush-job.js +12 -7
  41. package/lib/cloudflare/logpush-job.js.map +1 -1
  42. package/lib/cloudflare/miniflare/miniflare-worker-proxy.js +1 -1
  43. package/lib/cloudflare/miniflare/miniflare-worker-proxy.js.map +1 -1
  44. package/lib/cloudflare/queue-consumer.d.ts +2 -2
  45. package/lib/cloudflare/ruleset.d.ts.map +1 -1
  46. package/lib/cloudflare/ruleset.js.map +1 -1
  47. package/lib/cloudflare/tunnel-route.d.ts.map +1 -1
  48. package/lib/cloudflare/tunnel-route.js.map +1 -1
  49. package/lib/cloudflare/website.d.ts.map +1 -1
  50. package/lib/cloudflare/website.js.map +1 -1
  51. package/lib/cloudflare/worker-assets.d.ts +1 -1
  52. package/lib/cloudflare/worker-assets.d.ts.map +1 -1
  53. package/lib/cloudflare/worker-assets.js +1 -1
  54. package/lib/cloudflare/worker-assets.js.map +1 -1
  55. package/lib/cloudflare/worker-bundle.d.ts.map +1 -1
  56. package/lib/cloudflare/worker-bundle.js.map +1 -1
  57. package/lib/cloudflare/worker-metadata.d.ts +3 -7
  58. package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
  59. package/lib/cloudflare/worker-metadata.js.map +1 -1
  60. package/lib/cloudflare/worker.d.ts +130 -17
  61. package/lib/cloudflare/worker.d.ts.map +1 -1
  62. package/lib/cloudflare/worker.js.map +1 -1
  63. package/lib/cloudflare/zone-settings.d.ts.map +1 -1
  64. package/lib/coinbase/evm-smart-account.d.ts.map +1 -1
  65. package/lib/coinbase/evm-smart-account.js.map +1 -1
  66. package/lib/coinbase/faucet.js.map +1 -1
  67. package/lib/context.d.ts.map +1 -1
  68. package/lib/context.js.map +1 -1
  69. package/lib/esbuild/bundle.d.ts.map +1 -1
  70. package/lib/esbuild/bundle.js.map +1 -1
  71. package/lib/scope.d.ts +9 -0
  72. package/lib/scope.d.ts.map +1 -1
  73. package/lib/scope.js +5 -3
  74. package/lib/scope.js.map +1 -1
  75. package/lib/sentry/client-key.js +1 -1
  76. package/lib/sentry/client-key.js.map +1 -1
  77. package/lib/serde.d.ts.map +1 -1
  78. package/lib/serde.js +4 -0
  79. package/lib/serde.js.map +1 -1
  80. package/lib/state/d1-state-store.js.map +1 -1
  81. package/lib/state/instrumented-state-store.d.ts.map +1 -1
  82. package/lib/util/api/client/types.gen.d.ts.map +1 -1
  83. package/lib/util/api/core/pathSerializer.gen.d.ts.map +1 -1
  84. package/lib/util/api/core/pathSerializer.gen.js.map +1 -1
  85. package/lib/util/idempotent-spawn.d.ts.map +1 -1
  86. package/lib/util/idempotent-spawn.js +1 -1
  87. package/lib/util/idempotent-spawn.js.map +1 -1
  88. package/package.json +10 -10
  89. package/src/alchemy.ts +13 -0
  90. package/src/aws/ec2/internet-gateway-attachment.ts +1 -2
  91. package/src/aws/function.ts +2 -3
  92. package/src/aws/oidc/github-oidc-provider.ts +4 -2
  93. package/src/cloudflare/api-response.ts +3 -2
  94. package/src/cloudflare/api-schema.ts +3 -2
  95. package/src/cloudflare/api-shield.ts +3 -2
  96. package/src/cloudflare/astro/astro.ts +4 -2
  97. package/src/cloudflare/astro/plugin.ts +15 -1
  98. package/src/cloudflare/bucket-custom-domain.ts +1 -2
  99. package/src/cloudflare/bucket.ts +9 -2
  100. package/src/cloudflare/bundle/plugin-wasm.ts +4 -5
  101. package/src/cloudflare/container.ts +2 -1
  102. package/src/cloudflare/dispatch-namespace.ts +4 -2
  103. package/src/cloudflare/logpush-job.ts +16 -13
  104. package/src/cloudflare/miniflare/miniflare-worker-proxy.ts +1 -1
  105. package/src/cloudflare/queue-consumer.ts +2 -2
  106. package/src/cloudflare/ruleset.ts +3 -2
  107. package/src/cloudflare/tunnel-route.ts +4 -2
  108. package/src/cloudflare/website.ts +4 -2
  109. package/src/cloudflare/worker-assets.ts +6 -1
  110. package/src/cloudflare/worker-bundle.ts +2 -1
  111. package/src/cloudflare/worker-metadata.ts +3 -6
  112. package/src/cloudflare/worker.ts +139 -17
  113. package/src/cloudflare/zone-settings.ts +1 -2
  114. package/src/coinbase/evm-smart-account.ts +1 -2
  115. package/src/coinbase/faucet.ts +3 -1
  116. package/src/context.ts +3 -2
  117. package/src/esbuild/bundle.ts +3 -2
  118. package/src/scope.ts +13 -2
  119. package/src/sentry/client-key.ts +5 -1
  120. package/src/serde.ts +4 -0
  121. package/src/state/d1-state-store.ts +2 -3
  122. package/src/state/instrumented-state-store.ts +3 -3
  123. package/src/util/api/client/types.gen.ts +4 -3
  124. package/src/util/api/core/pathSerializer.gen.ts +1 -2
  125. package/src/util/idempotent-spawn.ts +5 -1
  126. package/templates/astro/wrangler.jsonc +1 -1
  127. package/workers/cloudflare-state-store.js +57 -57
  128. package/workers/remote-binding-proxy.js +42 -15
  129. package/workers/tunnel-proxy.js +1 -1
@@ -365,22 +365,16 @@ export interface BaseWorkerProps<
365
365
  };
366
366
 
367
367
  /**
368
- * Smart placement configuration for the worker.
368
+ * Placement configuration for the worker.
369
369
  *
370
- * Controls how Cloudflare places the worker across its network for optimal performance.
370
+ * Controls where your Worker runs to reduce latency to back-end infrastructure.
371
+ * Only one placement option can be specified (mutually exclusive).
371
372
  *
372
- * When omitted, smart placement is disabled (default behavior).
373
+ * When omitted, the Worker runs in the data center closest to the incoming request.
374
+ *
375
+ * @see https://developers.cloudflare.com/workers/configuration/smart-placement/
373
376
  */
374
- placement?: {
375
- /**
376
- * The placement mode for the worker.
377
- *
378
- * - "smart": Automatically optimize placement based on performance metrics
379
- *
380
- * @default undefined (smart placement disabled)
381
- */
382
- mode: "smart";
383
- };
377
+ placement?: WorkerPlacement;
384
378
 
385
379
  limits?: {
386
380
  /**
@@ -477,6 +471,136 @@ export interface WorkerObservability {
477
471
  };
478
472
  }
479
473
 
474
+ /**
475
+ * Worker placement configuration for controlling where your Worker runs.
476
+ *
477
+ * Only one placement option can be specified at a time (mutually exclusive).
478
+ *
479
+ * @see https://developers.cloudflare.com/workers/configuration/smart-placement/
480
+ */
481
+ export type WorkerPlacement =
482
+ | WorkerPlacementSmart
483
+ | WorkerPlacementRegion
484
+ | WorkerPlacementHost
485
+ | WorkerPlacementHostname;
486
+
487
+ /**
488
+ * Smart placement mode - Cloudflare automatically places your Worker
489
+ * closest to the upstream with the most requests.
490
+ *
491
+ * Use when your Worker connects to multiple back-end services or you
492
+ * don't know the exact location of your infrastructure.
493
+ *
494
+ * @example
495
+ * ```ts
496
+ * const worker = await Worker("api", {
497
+ * entrypoint: "./src/worker.ts",
498
+ * placement: { mode: "smart" }
499
+ * });
500
+ * ```
501
+ */
502
+ export interface WorkerPlacementSmart {
503
+ /**
504
+ * Enable smart placement mode.
505
+ *
506
+ * Cloudflare automatically analyzes your Worker's traffic patterns and
507
+ * places it in an optimal location based on performance metrics.
508
+ */
509
+ mode: "smart";
510
+ }
511
+
512
+ /**
513
+ * Region-based placement - place your Worker closest to a specific
514
+ * cloud provider region.
515
+ *
516
+ * Use when your back-end infrastructure runs in a known AWS, GCP, or Azure region.
517
+ *
518
+ * @example
519
+ * ```ts
520
+ * const worker = await Worker("api", {
521
+ * entrypoint: "./src/worker.ts",
522
+ * placement: { region: "aws:us-east-1" }
523
+ * });
524
+ * ```
525
+ */
526
+ export interface WorkerPlacementRegion {
527
+ /**
528
+ * Cloud provider region to place your Worker closest to.
529
+ *
530
+ * Format: `{provider}:{region}`
531
+ *
532
+ * Supported providers:
533
+ * - AWS: `aws:us-east-1`, `aws:us-west-2`, `aws:eu-central-1`, etc.
534
+ * - GCP: `gcp:us-east4`, `gcp:europe-west1`, `gcp:asia-east1`, etc.
535
+ * - Azure: `azure:westeurope`, `azure:eastus`, `azure:southeastasia`, etc.
536
+ *
537
+ * @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html
538
+ * @see https://cloud.google.com/compute/docs/regions-zones
539
+ * @see https://learn.microsoft.com/en-us/azure/reliability/regions-list
540
+ *
541
+ * @example "aws:us-east-1"
542
+ * @example "gcp:us-east4"
543
+ * @example "azure:westeurope"
544
+ */
545
+ region: string;
546
+ }
547
+
548
+ /**
549
+ * Host-based placement (layer 4) - place your Worker closest to a specific
550
+ * TCP endpoint.
551
+ *
552
+ * Use when your infrastructure is not in a major cloud provider and you need
553
+ * to probe a TCP service (like a database) to determine optimal placement.
554
+ *
555
+ * @example
556
+ * ```ts
557
+ * const worker = await Worker("api", {
558
+ * entrypoint: "./src/worker.ts",
559
+ * placement: { host: "my-database.example.com:5432" }
560
+ * });
561
+ * ```
562
+ */
563
+ export interface WorkerPlacementHost {
564
+ /**
565
+ * Host endpoint to probe (TCP/layer 4) for placement.
566
+ *
567
+ * Cloudflare uses TCP CONNECT checks to measure latency and selects
568
+ * the best data center. Use this for database hosts or other TCP services.
569
+ *
570
+ * Format: `hostname:port`
571
+ *
572
+ * @example "my_database_host.com:5432"
573
+ */
574
+ host: string;
575
+ }
576
+
577
+ /**
578
+ * Hostname-based placement (layer 7) - place your Worker closest to a specific
579
+ * HTTP endpoint.
580
+ *
581
+ * Use when your infrastructure is not in a major cloud provider and you need
582
+ * to probe an HTTP service (like an API) to determine optimal placement.
583
+ *
584
+ * @example
585
+ * ```ts
586
+ * const worker = await Worker("api", {
587
+ * entrypoint: "./src/worker.ts",
588
+ * placement: { hostname: "my-api.example.com" }
589
+ * });
590
+ * ```
591
+ */
592
+ export interface WorkerPlacementHostname {
593
+ /**
594
+ * Hostname to probe (HTTP/layer 7) for placement.
595
+ *
596
+ * Cloudflare uses HTTP HEAD checks to measure latency and selects
597
+ * the best data center. Use this for API endpoints or other HTTP services.
598
+ *
599
+ * @example "my_api_server.com"
600
+ */
601
+ hostname: string;
602
+ }
603
+
480
604
  export interface InlineWorkerProps<
481
605
  B extends Bindings | undefined = Bindings,
482
606
  RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
@@ -630,11 +754,9 @@ export type Worker<
630
754
  version?: string;
631
755
 
632
756
  /**
633
- * Smart placement configuration for the worker
757
+ * Placement configuration for the worker
634
758
  */
635
- placement?: {
636
- mode: "smart";
637
- };
759
+ placement?: WorkerPlacement;
638
760
 
639
761
  /**
640
762
  * Whether the worker has a remote deployment
@@ -89,8 +89,7 @@ export interface AutomaticHTTPSRewritesSetting extends CloudflareSettingBase {
89
89
  /**
90
90
  * Automatic Platform Optimization setting
91
91
  */
92
- export interface AutomaticPlatformOptimizationSetting
93
- extends CloudflareSettingBase {
92
+ export interface AutomaticPlatformOptimizationSetting extends CloudflareSettingBase {
94
93
  id: "automatic_platform_optimization";
95
94
  value: {
96
95
  enabled: boolean;
@@ -48,8 +48,7 @@ export interface EvmSmartAccountProps extends CoinbaseClientOptions {
48
48
  faucet?: FaucetConfig;
49
49
  }
50
50
 
51
- export interface EvmSmartAccount
52
- extends Resource<"coinbase::evm-smart-account"> {
51
+ export interface EvmSmartAccount extends Resource<"coinbase::evm-smart-account"> {
53
52
  /**
54
53
  * The smart account name in CDP
55
54
  */
@@ -141,7 +141,9 @@ for (const account of accounts) {
141
141
 
142
142
  // Skip if already processed in this run
143
143
  if (funded.has(key)) {
144
- console.log(` ⏭️ Skipping ${token} on ${network} (already requested)`);
144
+ console.log(
145
+ ` ⏭️ Skipping ${token} on ${network} (already requested)`,
146
+ );
145
147
  continue;
146
148
  }
147
149
 
package/src/context.ts CHANGED
@@ -17,8 +17,9 @@ export type Context<
17
17
  Props extends ResourceProps = ResourceProps,
18
18
  > = CreateContext<Out> | UpdateContext<Out, Props> | DeleteContext<Out, Props>;
19
19
 
20
- export interface CreateContext<Out extends ResourceAttributes>
21
- extends BaseContext<Out> {
20
+ export interface CreateContext<
21
+ Out extends ResourceAttributes,
22
+ > extends BaseContext<Out> {
22
23
  phase: "create";
23
24
  output?: undefined;
24
25
  props?: undefined;
@@ -73,8 +73,9 @@ export interface BundleProps extends Partial<esbuild.BuildOptions> {
73
73
  /**
74
74
  * Output returned after bundle creation/update
75
75
  */
76
- export interface Bundle<P extends BundleProps = BundleProps>
77
- extends BundleProps {
76
+ export interface Bundle<
77
+ P extends BundleProps = BundleProps,
78
+ > extends BundleProps {
78
79
  /**
79
80
  * Path to the bundled file
80
81
  * Absolute or relative path to the generated bundle
package/src/scope.ts CHANGED
@@ -101,6 +101,14 @@ export interface ScopeOptions extends ProviderCredentials {
101
101
  * @default false
102
102
  */
103
103
  adopt?: boolean;
104
+ /**
105
+ * Skip decrypting secrets and treat them as undefined.
106
+ * Requires --force to be enabled.
107
+ * Useful for recovering from lost encryption passwords.
108
+ *
109
+ * @default false
110
+ */
111
+ eraseSecrets?: boolean;
104
112
  /**
105
113
  * The path to the root directory of the project.
106
114
  *
@@ -176,8 +184,8 @@ export class Scope {
176
184
 
177
185
  public static readonly KIND = "alchemy::Scope" as const;
178
186
 
179
- public static storage = globalThis.__ALCHEMY_STORAGE__ ??=
180
- new AsyncLocalStorage<Scope>();
187
+ public static storage = (globalThis.__ALCHEMY_STORAGE__ ??=
188
+ new AsyncLocalStorage<Scope>());
181
189
 
182
190
  public static getScope(): Scope | undefined {
183
191
  return Scope.storage.getStore();
@@ -209,6 +217,7 @@ export class Scope {
209
217
  public readonly tunnel: boolean;
210
218
  public readonly force: boolean;
211
219
  public readonly adopt: boolean;
220
+ public readonly eraseSecrets: boolean;
212
221
  public readonly destroyStrategy: DestroyStrategy;
213
222
  public readonly logger: LoggerApi;
214
223
  public readonly noTrack: boolean;
@@ -252,6 +261,7 @@ export class Scope {
252
261
  destroyStrategy,
253
262
  logger,
254
263
  adopt,
264
+ eraseSecrets,
255
265
  dotAlchemy,
256
266
  rootDir,
257
267
  isSelected,
@@ -310,6 +320,7 @@ export class Scope {
310
320
  this.tunnel = tunnel ?? this.parent?.tunnel ?? false;
311
321
  this.force = force ?? this.parent?.force ?? false;
312
322
  this.adopt = adopt ?? this.parent?.adopt ?? false;
323
+ this.eraseSecrets = eraseSecrets ?? this.parent?.eraseSecrets ?? false;
313
324
  this.destroyStrategy =
314
325
  destroyStrategy ?? this.parent?.destroyStrategy ?? "sequential";
315
326
  if (this.local) {
@@ -340,7 +340,11 @@ async function findClientKeyByName(
340
340
  */
341
341
  async function getClientKeyName(
342
342
  api: SentryApi,
343
- { organization, project, keyId }: {
343
+ {
344
+ organization,
345
+ project,
346
+ keyId,
347
+ }: {
344
348
  organization: string;
345
349
  project: string;
346
350
  keyId: string;
package/src/serde.ts CHANGED
@@ -177,6 +177,10 @@ export async function deserialize(
177
177
  }
178
178
  if (value && typeof value === "object") {
179
179
  if (value["@secret"]) {
180
+ // If eraseSecrets is enabled, return undefined instead of decrypting
181
+ if (scope.eraseSecrets) {
182
+ return undefined;
183
+ }
180
184
  if (!scope.password) {
181
185
  throw new Error(
182
186
  "Cannot deserialize secret without password, did you forget to set password when initializing your alchemy app?\n" +
@@ -75,9 +75,8 @@ const createDatabaseClient = memoize(async (options: D1StateStoreOptions) => {
75
75
  });
76
76
 
77
77
  const upsertDatabase = async (api: CloudflareApi, databaseName: string) => {
78
- const { listDatabases, createDatabase } = await import(
79
- "../cloudflare/d1-database.ts"
80
- );
78
+ const { listDatabases, createDatabase } =
79
+ await import("../cloudflare/d1-database.ts");
81
80
  const { listSqlFiles } = await import("../cloudflare/d1-sql-file.ts");
82
81
  const { applyMigrations } = await import("../cloudflare/d1-migrations.ts");
83
82
  const migrate = async (databaseId: string) => {
@@ -5,9 +5,9 @@ import {
5
5
  } from "../util/telemetry.ts";
6
6
 
7
7
  //todo(michael): we should also handle serde here
8
- export class InstrumentedStateStore<T extends StateStore>
9
- implements StateStore
10
- {
8
+ export class InstrumentedStateStore<
9
+ T extends StateStore,
10
+ > implements StateStore {
11
11
  /** @internal */
12
12
  __phantom?: T;
13
13
  private readonly stateStore: StateStore;
@@ -14,8 +14,7 @@ import type { Middleware } from "./utils.gen.ts";
14
14
  export type ResponseStyle = "data" | "fields";
15
15
 
16
16
  export interface Config<T extends ClientOptions = ClientOptions>
17
- extends Omit<RequestInit, "body" | "headers" | "method">,
18
- CoreConfig {
17
+ extends Omit<RequestInit, "body" | "headers" | "method">, CoreConfig {
19
18
  /**
20
19
  * Base URL for all requests made by this client.
21
20
  */
@@ -69,7 +68,9 @@ export interface RequestOptions<
69
68
  TResponseStyle extends ResponseStyle = "fields",
70
69
  ThrowOnError extends boolean = boolean,
71
70
  Url extends string = string,
72
- > extends Config<{
71
+ >
72
+ extends
73
+ Config<{
73
74
  responseStyle: TResponseStyle;
74
75
  throwOnError: ThrowOnError;
75
76
  }>,
@@ -1,8 +1,7 @@
1
1
  // This file is auto-generated by @hey-api/openapi-ts
2
2
 
3
3
  interface SerializeOptions<T>
4
- extends SerializePrimitiveOptions,
5
- SerializerOptions<T> {}
4
+ extends SerializePrimitiveOptions, SerializerOptions<T> {}
6
5
 
7
6
  interface SerializePrimitiveOptions {
8
7
  allowReserved?: boolean;
@@ -158,7 +158,11 @@ export async function idempotentSpawn({
158
158
  // Follow a file from persisted offset and mirror to a sink (stdout/stderr)
159
159
  async function followFilePersisted(
160
160
  logPath: string,
161
- { write, chunkSize = 64 * 1024, tickMs = 100 }: {
161
+ {
162
+ write,
163
+ chunkSize = 64 * 1024,
164
+ tickMs = 100,
165
+ }: {
162
166
  stateKey: string;
163
167
  write: (buf: Buffer) => boolean;
164
168
  chunkSize?: number;
@@ -2,5 +2,5 @@
2
2
  "name": "website",
3
3
  "main": "dist/_worker.js/index.js",
4
4
  "compatibility_date": "2025-04-20",
5
- "assets": { "binding": "ASSETS", "directory": "dist" }
5
+ "assets": { "binding": "ASSETS", "directory": "dist" },
6
6
  }