alchemy 2.0.0-beta.43 → 2.0.0-beta.44

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 (207) hide show
  1. package/bin/cli.js +18 -5
  2. package/bin/exec.js +315 -233
  3. package/bin/exec.js.map +1 -1
  4. package/lib/Auth/Lock.js +2 -2
  5. package/lib/Auth/Lock.js.map +1 -1
  6. package/lib/Bundle/Bundle.d.ts +11 -0
  7. package/lib/Bundle/Bundle.d.ts.map +1 -1
  8. package/lib/Bundle/Bundle.js +19 -12
  9. package/lib/Bundle/Bundle.js.map +1 -1
  10. package/lib/Bundle/BundleAnalyzerPlugin.d.ts +25 -0
  11. package/lib/Bundle/BundleAnalyzerPlugin.d.ts.map +1 -0
  12. package/lib/Bundle/BundleAnalyzerPlugin.js +16 -0
  13. package/lib/Bundle/BundleAnalyzerPlugin.js.map +1 -0
  14. package/lib/Bundle/RawPlugin.d.ts +36 -0
  15. package/lib/Bundle/RawPlugin.d.ts.map +1 -0
  16. package/lib/Bundle/RawPlugin.js +80 -0
  17. package/lib/Bundle/RawPlugin.js.map +1 -0
  18. package/lib/Bundle/index.d.ts +2 -0
  19. package/lib/Bundle/index.d.ts.map +1 -1
  20. package/lib/Bundle/index.js +2 -0
  21. package/lib/Bundle/index.js.map +1 -1
  22. package/lib/Cli/commands/dev.d.ts +3 -2
  23. package/lib/Cli/commands/dev.d.ts.map +1 -1
  24. package/lib/Cli/commands/dev.js +9 -1
  25. package/lib/Cli/commands/dev.js.map +1 -1
  26. package/lib/Cli/exec.d.ts.map +1 -1
  27. package/lib/Cli/exec.js +2 -1
  28. package/lib/Cli/exec.js.map +1 -1
  29. package/lib/Cloudflare/Local.d.ts +2 -0
  30. package/lib/Cloudflare/Local.d.ts.map +1 -0
  31. package/lib/Cloudflare/Local.js +9 -0
  32. package/lib/Cloudflare/Local.js.map +1 -0
  33. package/lib/Cloudflare/Providers.d.ts.map +1 -1
  34. package/lib/Cloudflare/Providers.js +3 -1
  35. package/lib/Cloudflare/Providers.js.map +1 -1
  36. package/lib/Cloudflare/Workers/DurableObjectBridge.d.ts.map +1 -1
  37. package/lib/Cloudflare/Workers/DurableObjectBridge.js +0 -1
  38. package/lib/Cloudflare/Workers/DurableObjectBridge.js.map +1 -1
  39. package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts +22 -3
  40. package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
  41. package/lib/Cloudflare/Workers/LocalWorkerProvider.js +413 -21
  42. package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
  43. package/lib/Cloudflare/Workers/Worker.d.ts +6 -19
  44. package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
  45. package/lib/Cloudflare/Workers/Worker.js +3 -4
  46. package/lib/Cloudflare/Workers/Worker.js.map +1 -1
  47. package/lib/Cloudflare/Workers/WorkerBridge.d.ts.map +1 -1
  48. package/lib/Cloudflare/Workers/WorkerBridge.js +3 -5
  49. package/lib/Cloudflare/Workers/WorkerBridge.js.map +1 -1
  50. package/lib/Cloudflare/Workers/WorkerBundle.d.ts +1 -2
  51. package/lib/Cloudflare/Workers/WorkerBundle.d.ts.map +1 -1
  52. package/lib/Cloudflare/Workers/WorkerBundle.js +3 -6
  53. package/lib/Cloudflare/Workers/WorkerBundle.js.map +1 -1
  54. package/lib/Cloudflare/Zaraz/ZarazConfig.d.ts +184 -0
  55. package/lib/Cloudflare/Zaraz/ZarazConfig.d.ts.map +1 -0
  56. package/lib/Cloudflare/Zaraz/ZarazConfig.js +216 -0
  57. package/lib/Cloudflare/Zaraz/ZarazConfig.js.map +1 -0
  58. package/lib/Cloudflare/Zaraz/ZarazEventTypes.d.ts +188 -0
  59. package/lib/Cloudflare/Zaraz/ZarazEventTypes.d.ts.map +1 -0
  60. package/lib/Cloudflare/Zaraz/ZarazEventTypes.js +4 -0
  61. package/lib/Cloudflare/Zaraz/ZarazEventTypes.js.map +1 -0
  62. package/lib/Cloudflare/Zaraz/index.d.ts +3 -0
  63. package/lib/Cloudflare/Zaraz/index.d.ts.map +1 -0
  64. package/lib/Cloudflare/Zaraz/index.js +2 -0
  65. package/lib/Cloudflare/Zaraz/index.js.map +1 -0
  66. package/lib/Cloudflare/index.d.ts +1 -0
  67. package/lib/Cloudflare/index.d.ts.map +1 -1
  68. package/lib/Cloudflare/index.js +1 -0
  69. package/lib/Cloudflare/index.js.map +1 -1
  70. package/lib/Local/RpcProvider.d.ts +54 -0
  71. package/lib/Local/RpcProvider.d.ts.map +1 -0
  72. package/lib/Local/RpcProvider.js +57 -0
  73. package/lib/Local/RpcProvider.js.map +1 -0
  74. package/lib/Local/RpcProviderProxy.d.ts +19 -0
  75. package/lib/Local/RpcProviderProxy.d.ts.map +1 -0
  76. package/lib/Local/RpcProviderProxy.js +48 -0
  77. package/lib/Local/RpcProviderProxy.js.map +1 -0
  78. package/lib/Local/RpcSerialization.d.ts +34 -0
  79. package/lib/Local/RpcSerialization.d.ts.map +1 -0
  80. package/lib/Local/RpcSerialization.js +120 -0
  81. package/lib/Local/RpcSerialization.js.map +1 -0
  82. package/lib/Local/RpcServer.d.ts +63 -0
  83. package/lib/Local/RpcServer.d.ts.map +1 -0
  84. package/lib/Local/RpcServer.js +72 -0
  85. package/lib/Local/RpcServer.js.map +1 -0
  86. package/lib/Local/RpcServerBun.d.ts +3 -0
  87. package/lib/Local/RpcServerBun.d.ts.map +1 -0
  88. package/lib/Local/RpcServerBun.js +47 -0
  89. package/lib/Local/RpcServerBun.js.map +1 -0
  90. package/lib/Local/RpcServerEnvironment.d.ts +20 -0
  91. package/lib/Local/RpcServerEnvironment.d.ts.map +1 -0
  92. package/lib/Local/RpcServerEnvironment.js +22 -0
  93. package/lib/Local/RpcServerEnvironment.js.map +1 -0
  94. package/lib/Local/RpcServerNode.d.ts +3 -0
  95. package/lib/Local/RpcServerNode.d.ts.map +1 -0
  96. package/lib/Local/RpcServerNode.js +43 -0
  97. package/lib/Local/RpcServerNode.js.map +1 -0
  98. package/lib/Local/RpcServerSession.d.ts +27 -0
  99. package/lib/Local/RpcServerSession.d.ts.map +1 -0
  100. package/lib/Local/RpcServerSession.js +68 -0
  101. package/lib/Local/RpcServerSession.js.map +1 -0
  102. package/lib/Local/RpcSpawner.d.ts +21 -0
  103. package/lib/Local/RpcSpawner.d.ts.map +1 -0
  104. package/lib/Local/RpcSpawner.js +132 -0
  105. package/lib/Local/RpcSpawner.js.map +1 -0
  106. package/lib/Util/PlatformServices.d.ts +7 -0
  107. package/lib/Util/PlatformServices.d.ts.map +1 -1
  108. package/lib/Util/PlatformServices.js +22 -11
  109. package/lib/Util/PlatformServices.js.map +1 -1
  110. package/lib/Util/camel.d.ts.map +1 -1
  111. package/lib/Util/camel.js +2 -3
  112. package/lib/Util/camel.js.map +1 -1
  113. package/lib/Util/data.d.ts +5 -0
  114. package/lib/Util/data.d.ts.map +1 -1
  115. package/lib/Util/data.js +29 -0
  116. package/lib/Util/data.js.map +1 -1
  117. package/lib/Util/stable.d.ts.map +1 -1
  118. package/lib/Util/stable.js +3 -6
  119. package/lib/Util/stable.js.map +1 -1
  120. package/lib/tsconfig.test.tsbuildinfo +1 -1
  121. package/package.json +12 -14
  122. package/src/Auth/Lock.ts +2 -2
  123. package/src/Bundle/Bundle.ts +35 -13
  124. package/src/Bundle/BundleAnalyzerPlugin.ts +33 -0
  125. package/src/Bundle/RawPlugin.ts +82 -0
  126. package/src/Bundle/index.ts +2 -0
  127. package/src/Cli/commands/dev.ts +51 -37
  128. package/src/Cli/exec.ts +12 -7
  129. package/src/Cloudflare/Local.ts +23 -0
  130. package/src/Cloudflare/Providers.ts +3 -0
  131. package/src/Cloudflare/Workers/DurableObjectBridge.ts +0 -1
  132. package/src/Cloudflare/Workers/LocalWorkerProvider.ts +547 -21
  133. package/src/Cloudflare/Workers/Worker.ts +11 -22
  134. package/src/Cloudflare/Workers/WorkerBridge.ts +3 -5
  135. package/src/Cloudflare/Workers/WorkerBundle.ts +4 -8
  136. package/src/Cloudflare/Zaraz/ZarazConfig.ts +403 -0
  137. package/src/Cloudflare/Zaraz/ZarazEventTypes.ts +257 -0
  138. package/src/Cloudflare/Zaraz/index.ts +25 -0
  139. package/src/Cloudflare/index.ts +1 -0
  140. package/src/Local/RpcProvider.ts +102 -0
  141. package/src/Local/RpcProviderProxy.ts +86 -0
  142. package/src/Local/RpcSerialization.ts +225 -0
  143. package/src/Local/RpcServer.ts +138 -0
  144. package/src/Local/RpcServerBun.ts +59 -0
  145. package/src/Local/RpcServerEnvironment.ts +55 -0
  146. package/src/Local/RpcServerNode.ts +58 -0
  147. package/src/Local/RpcServerSession.ts +87 -0
  148. package/src/Local/RpcSpawner.ts +196 -0
  149. package/src/Util/PlatformServices.ts +41 -27
  150. package/src/Util/camel.ts +3 -5
  151. package/src/Util/data.ts +38 -0
  152. package/src/Util/stable.ts +4 -10
  153. package/lib/Cloudflare/Local/Sidecar.d.ts +0 -63
  154. package/lib/Cloudflare/Local/Sidecar.d.ts.map +0 -1
  155. package/lib/Cloudflare/Local/Sidecar.js +0 -50
  156. package/lib/Cloudflare/Local/Sidecar.js.map +0 -1
  157. package/lib/Cloudflare/Local/SidecarHandlers.d.ts +0 -8
  158. package/lib/Cloudflare/Local/SidecarHandlers.d.ts.map +0 -1
  159. package/lib/Cloudflare/Local/SidecarHandlers.js +0 -381
  160. package/lib/Cloudflare/Local/SidecarHandlers.js.map +0 -1
  161. package/lib/Cloudflare/Local/SidecarServer.d.ts +0 -2
  162. package/lib/Cloudflare/Local/SidecarServer.d.ts.map +0 -1
  163. package/lib/Cloudflare/Local/SidecarServer.js +0 -34
  164. package/lib/Cloudflare/Local/SidecarServer.js.map +0 -1
  165. package/lib/Sidecar/Lock.d.ts +0 -23
  166. package/lib/Sidecar/Lock.d.ts.map +0 -1
  167. package/lib/Sidecar/Lock.js +0 -39
  168. package/lib/Sidecar/Lock.js.map +0 -1
  169. package/lib/Sidecar/RpcClient.d.ts +0 -15
  170. package/lib/Sidecar/RpcClient.d.ts.map +0 -1
  171. package/lib/Sidecar/RpcClient.js +0 -78
  172. package/lib/Sidecar/RpcClient.js.map +0 -1
  173. package/lib/Sidecar/RpcHandler.d.ts +0 -51
  174. package/lib/Sidecar/RpcHandler.d.ts.map +0 -1
  175. package/lib/Sidecar/RpcHandler.js +0 -87
  176. package/lib/Sidecar/RpcHandler.js.map +0 -1
  177. package/lib/Sidecar/RpcPaths.d.ts +0 -19
  178. package/lib/Sidecar/RpcPaths.d.ts.map +0 -1
  179. package/lib/Sidecar/RpcPaths.js +0 -31
  180. package/lib/Sidecar/RpcPaths.js.map +0 -1
  181. package/lib/Sidecar/RpcServer.d.ts +0 -30
  182. package/lib/Sidecar/RpcServer.d.ts.map +0 -1
  183. package/lib/Sidecar/RpcServer.js +0 -105
  184. package/lib/Sidecar/RpcServer.js.map +0 -1
  185. package/lib/Sidecar/RpcServerBun.d.ts +0 -4
  186. package/lib/Sidecar/RpcServerBun.d.ts.map +0 -1
  187. package/lib/Sidecar/RpcServerBun.js +0 -28
  188. package/lib/Sidecar/RpcServerBun.js.map +0 -1
  189. package/lib/Sidecar/RpcServerNode.d.ts +0 -4
  190. package/lib/Sidecar/RpcServerNode.d.ts.map +0 -1
  191. package/lib/Sidecar/RpcServerNode.js +0 -39
  192. package/lib/Sidecar/RpcServerNode.js.map +0 -1
  193. package/lib/Sidecar/RpcServices.d.ts +0 -6
  194. package/lib/Sidecar/RpcServices.d.ts.map +0 -1
  195. package/lib/Sidecar/RpcServices.js +0 -29
  196. package/lib/Sidecar/RpcServices.js.map +0 -1
  197. package/src/Cloudflare/Local/Sidecar.ts +0 -81
  198. package/src/Cloudflare/Local/SidecarHandlers.ts +0 -491
  199. package/src/Cloudflare/Local/SidecarServer.ts +0 -70
  200. package/src/Sidecar/Lock.ts +0 -66
  201. package/src/Sidecar/RpcClient.ts +0 -142
  202. package/src/Sidecar/RpcHandler.ts +0 -205
  203. package/src/Sidecar/RpcPaths.ts +0 -39
  204. package/src/Sidecar/RpcServer.ts +0 -153
  205. package/src/Sidecar/RpcServerBun.ts +0 -41
  206. package/src/Sidecar/RpcServerNode.ts +0 -51
  207. package/src/Sidecar/RpcServices.ts +0 -48
package/bin/cli.js CHANGED
@@ -19,11 +19,16 @@
19
19
  // exports point at .ts source), but consumers install into `node_modules/`,
20
20
  // so the path check sends them to the bundled `alchemy.js` regardless.
21
21
  //
22
- // foreground-child forwards stdio + signals and exits with the child's code,
23
- // so the launcher is transparent to the invoking shell / npm script.
24
- import { foregroundChild } from "foreground-child";
22
+ // We use @alchemy.run/node-utils' foreground-child so we can pipe the
23
+ // child's stderr through a filter upstream hardcodes stdio = [0, 1, 2],
24
+ // so the only way to drop bun's hard-coded watcher warning ("warn: File
25
+ // <path> is not in the project directory and will not be watched", which is
26
+ // noise in our monorepo and has no bun flag to silence) is to own the spawn
27
+ // call. Everything else — signal proxying, watchdog, IPC bridging, exit-code
28
+ // forwarding — matches upstream.
25
29
  import { fileURLToPath } from "node:url";
26
30
  import path from "pathe";
31
+ import { foregroundChild } from "@alchemy.run/node-utils";
27
32
 
28
33
  const execpath = (process.env.npm_execpath ?? "").toLowerCase();
29
34
  const userAgent = (process.env.npm_config_user_agent ?? "").toLowerCase();
@@ -62,6 +67,9 @@ if (runtime === "bun" && isDev) {
62
67
  args.push(runtime === "bun" ? tsEntry : jsEntry, ...process.argv.slice(2));
63
68
 
64
69
  process.on("uncaughtException", (error) => {
70
+ // STATUS_CONTROL_C_EXIT on Windows — the watchdog inherits Ctrl-C from the
71
+ // console and exits with this code instead of a SIGINT signal.
72
+ const WIN_CTRL_C = 3221225786;
65
73
  if (
66
74
  error.message.includes(
67
75
  "foreground-child watchdog process died unexpectedly!",
@@ -71,7 +79,7 @@ process.on("uncaughtException", (error) => {
71
79
  "watchedProcess" in error.cause &&
72
80
  error.cause.watchedProcess !== null &&
73
81
  "cmd" in error.cause.watchedProcess &&
74
- error.cause.signal === "SIGINT"
82
+ (error.cause.signal === "SIGINT" || error.cause.code === WIN_CTRL_C)
75
83
  ) {
76
84
  console.log("Interrupted.");
77
85
  process.exit(0);
@@ -79,4 +87,9 @@ process.on("uncaughtException", (error) => {
79
87
  console.error(error);
80
88
  });
81
89
 
82
- foregroundChild(runtime, args);
90
+ // Substring match (not regex) — bun may wrap the line in ANSI color codes
91
+ // when stderr is piped to a TTY-aware parent, so anchored regex is fragile.
92
+ foregroundChild(runtime, args, {
93
+ stderrFilter: (line) =>
94
+ !line.includes("is not in the project directory and will not be watched"),
95
+ });
package/bin/exec.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as ConfigProvider from "effect/ConfigProvider";
2
2
  import * as Effect from "effect/Effect";
3
3
  import * as Layer from "effect/Layer";
4
- import * as S from "effect/Schema";
4
+ import * as Schema from "effect/Schema";
5
5
  import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
6
6
  import * as EffectContext from "effect/Context";
7
7
  import * as FileSystem from "effect/FileSystem";
@@ -11,20 +11,28 @@ import * as Redacted from "effect/Redacted";
11
11
  import path from "pathe";
12
12
  import * as Config from "effect/Config";
13
13
  import os from "node:os";
14
- import * as Console from "effect/Console";
14
+ import { newWebSocketRpcSession } from "capnweb";
15
+ import * as Cache from "effect/Cache";
16
+ import * as HttpBody from "effect/unstable/http/HttpBody";
17
+ import * as HttpClient from "effect/unstable/http/HttpClient";
15
18
  import * as Logger from "effect/Logger";
16
19
  import * as Option from "effect/Option";
17
- import * as Command from "effect/unstable/cli/Command";
18
- import * as Flag from "effect/unstable/cli/Flag";
19
- import * as Data from "effect/Data";
20
- import * as Cause from "effect/Cause";
20
+ import "effect/Scope";
21
21
  import * as Deferred from "effect/Deferred";
22
- import { pipe } from "effect/Function";
22
+ import * as Data from "effect/Data";
23
+ import { flow, pipe } from "effect/Function";
23
24
  import { SingleShotGen } from "effect/Utils";
24
25
  import { pipeArguments } from "effect/Pipeable";
25
- import "effect/Scope";
26
- import * as Duration from "effect/Duration";
26
+ import "effect/Predicate";
27
+ import "effect/Record";
28
+ import * as Cause from "effect/Cause";
27
29
  import * as Exit from "effect/Exit";
30
+ import * as Stream from "effect/Stream";
31
+ import * as NodeUtil from "node:util";
32
+ import * as Console from "effect/Console";
33
+ import * as Command from "effect/unstable/cli/Command";
34
+ import * as Flag from "effect/unstable/cli/Flag";
35
+ import * as Duration from "effect/Duration";
28
36
  import * as Metric from "effect/Metric";
29
37
  import { createHash } from "node:crypto";
30
38
  import * as Argument from "effect/unstable/cli/Argument";
@@ -146,125 +154,6 @@ const CredentialsStoreLive = Layer.effect(CredentialsStore, Effect.gen(function*
146
154
  };
147
155
  }));
148
156
 
149
- //#endregion
150
- //#region lib/Util/PlatformServices.js
151
- const isBun = typeof Bun !== "undefined";
152
- const PlatformServices = Effect.promise(async () => {
153
- if (isBun) {
154
- const [BunServices, BunSocket] = await Promise.all([import("@effect/platform-bun/BunServices"), import("@effect/platform-bun/BunSocket")]);
155
- return Layer.merge(BunServices.layer, BunSocket.layerWebSocketConstructor);
156
- } else {
157
- const [NodeServices, NodeSocket] = await Promise.all([import("@effect/platform-node/NodeServices"), import("@effect/platform-node/NodeSocket")]);
158
- return Layer.merge(NodeServices.layer, NodeSocket.layerWebSocketConstructor);
159
- }
160
- }).pipe(Layer.unwrap);
161
- const runMain = (effect, options) => {
162
- if (isBun) import("@effect/platform-bun/BunRuntime").then((BunRuntime) => BunRuntime.runMain(effect, options));
163
- else import("@effect/platform-node/NodeRuntime").then((NodeRuntime) => NodeRuntime.runMain(effect, options));
164
- };
165
-
166
- //#endregion
167
- //#region lib/AdoptPolicy.js
168
- /**
169
- * AdoptPolicy controls whether the engine should "adopt" pre-existing cloud
170
- * resources that conflict with this stack instead of failing.
171
- *
172
- * The engine always calls a provider's `read` lifecycle operation when there
173
- * is no prior state and `read` is implemented. The provider's job is to
174
- * report two things:
175
- *
176
- * 1. Whether the resource exists (returns attributes vs. `undefined`).
177
- * 2. Whether *we* own it (plain attributes vs. {@link Unowned}-branded).
178
- *
179
- * The engine then routes:
180
- *
181
- * | `read` outcome | `adopt: false` | `adopt: true` |
182
- * | ------------------- | -------------- | ----------------- |
183
- * | undefined | create | create |
184
- * | owned (plain attrs) | silent adopt | silent adopt |
185
- * | {@link Unowned} | fail | takeover (adopt) |
186
- *
187
- * "Owned" means a provider has affirmatively determined the resource was
188
- * created by this stack/stage/logical-id (typically by inspecting tags or
189
- * naming conventions). Resources without ownership semantics simply always
190
- * return plain attrs — they are treated as owned by default, so silent
191
- * adoption is the norm and `--adopt` is unnecessary.
192
- *
193
- * The policy can be overridden per-effect via {@link adopt} — most commonly
194
- * applied at the resource or stack scope.
195
- */
196
- var AdoptPolicy = class extends EffectContext.Service()("AdoptPolicy") {};
197
- /**
198
- * Engine-raised failure produced when `read` reports an existing resource
199
- * marked as {@link Unowned} and `adopt` is `false`. Surface this to the user
200
- * to indicate they should either re-tag the cloud resource, pick a different
201
- * physical name, or re-run with `--adopt` (or `adopt(true)`) to force a
202
- * takeover.
203
- */
204
- var OwnedBySomeoneElse = class extends Data.TaggedError("OwnedBySomeoneElse") {};
205
- /**
206
- * Private symbol used to brand attribute objects returned by `read` as
207
- * "exists in cloud, but not owned by this stack/stage/logical-id".
208
- *
209
- * Deliberately *not* registered via `Symbol.for` — the brand is an
210
- * engine-internal routing hint and must not be observable or
211
- * forgeable from outside this module. The engine strips it before any
212
- * state persistence (see {@link stripUnowned}) so it never leaks into
213
- * the state store, JSON serialization, or downstream `Output`s.
214
- */
215
- const UnownedTag = Symbol("alchemy/Unowned");
216
- /**
217
- * Brand a `read` return value as belonging to a different owner.
218
- *
219
- * Use this in a provider's `read` implementation when the resource exists in
220
- * the cloud but a positive ownership check (e.g. tag inspection) shows it
221
- * was *not* created by this stack/stage/logical-id:
222
- *
223
- * ```ts
224
- * read: Effect.fnUntraced(function* ({ id, output, olds }) {
225
- * const settings = yield* getScriptSettings({ ... }).pipe(
226
- * Effect.catchTag("WorkerNotFound", () => Effect.succeed(undefined)),
227
- * );
228
- * if (!settings) return undefined;
229
- *
230
- * const attrs = { workerName, ...buildAttrs(settings) };
231
- * return hasAlchemyWorkerTags(id, settings.tags) ? attrs : Unowned(attrs);
232
- * }),
233
- * ```
234
- *
235
- * The returned value is structurally still `T` — there is no wrapper to
236
- * unwrap. The brand is a non-enumerable symbol that the engine inspects
237
- * during planning to decide whether to take over (`adopt: true`) or fail
238
- * loudly (`adopt: false`).
239
- *
240
- * Resources without ownership semantics should simply return plain attrs —
241
- * the engine treats them as owned and silent adoption is the default.
242
- */
243
- const Unowned = Object.assign((attrs) => {
244
- const cloned = { ...attrs };
245
- Object.defineProperty(cloned, UnownedTag, {
246
- value: true,
247
- enumerable: false,
248
- writable: false,
249
- configurable: false
250
- });
251
- return cloned;
252
- }, { is: (value) => typeof value === "object" && value !== null && value[UnownedTag] === true });
253
- /**
254
- * Strip the {@link Unowned} brand from an attributes object before persisting
255
- * it — state should not carry per-deploy ownership-routing metadata.
256
- *
257
- * The brand is intentionally non-enumerable, so a plain spread already
258
- * drops it; the additional `delete` is defense-in-depth in case a future
259
- * change makes the descriptor enumerable. Always returns a fresh object
260
- * (never mutates the input).
261
- */
262
- const stripUnowned = (attrs) => {
263
- const out = { ...attrs };
264
- if (UnownedTag in out) delete out[UnownedTag];
265
- return out;
266
- };
267
-
268
157
  //#endregion
269
158
  //#region lib/Artifacts.js
270
159
  /**
@@ -325,6 +214,10 @@ const makeScopedArtifacts = (store, fqn) => {
325
214
  */
326
215
  const ensureArtifactStore = (effect) => Effect.serviceOption(ArtifactStore).pipe(Effect.map(Option.getOrUndefined), Effect.flatMap((existing) => effect.pipe(Effect.provideService(ArtifactStore, existing ?? createArtifactStore()))));
327
216
 
217
+ //#endregion
218
+ //#region lib/Auth/AuthProvider.js
219
+ var AuthProviders = class extends EffectContext.Service()("AuthProviders") {};
220
+
328
221
  //#endregion
329
222
  //#region lib/Cli/Cli.js
330
223
  var Cli = class extends EffectContext.Service()("CLI") {};
@@ -415,97 +308,6 @@ const tryFindProviderByType = Effect.fnUntraced(function* (resourceType) {
415
308
  return Option.none();
416
309
  });
417
310
 
418
- //#endregion
419
- //#region lib/Auth/AuthProvider.js
420
- var AuthProviders = class extends EffectContext.Service()("AuthProviders") {};
421
-
422
- //#endregion
423
- //#region lib/Stage.js
424
- var Stage = class extends EffectContext.Service()("Stage") {};
425
-
426
- //#endregion
427
- //#region lib/Util/ConfigProvider.js
428
- const loadConfigProvider = (envFile$1) => {
429
- if (Option.isSome(envFile$1)) return ConfigProvider.fromDotEnv({ path: envFile$1.value }).pipe(Effect.map((dotEnv) => ConfigProvider.orElse(dotEnv, ConfigProvider.fromEnv())));
430
- return Effect.gen(function* () {
431
- if (!(yield* (yield* FileSystem.FileSystem).exists(".env"))) return ConfigProvider.fromEnv();
432
- return ConfigProvider.orElse(yield* ConfigProvider.fromDotEnv({ path: ".env" }), ConfigProvider.fromEnv());
433
- });
434
- };
435
-
436
- //#endregion
437
- //#region lib/Util/effect.js
438
- const effectClass = ((impl) => impl === void 0 ? (innerImpl) => effectClass(innerImpl) : Object.assign(class {
439
- static asEffect() {
440
- return impl;
441
- }
442
- static [Symbol.iterator]() {
443
- return new SingleShotGen(this.asEffect());
444
- }
445
- static pipe(...fns) {
446
- return pipeArguments(this, fns);
447
- }
448
- }, impl));
449
- const taggedFunction = (tag$1, fn) => {
450
- const overrides = {
451
- asEffect: () => tag$1,
452
- [Symbol.iterator]: () => tag$1[Symbol.iterator](),
453
- pipe: (...fns) => pipeArguments(tag$1, fns),
454
- toString: () => `${tag$1.toString()}.${fn.name}`
455
- };
456
- return new Proxy(fn, {
457
- get: (target, prop, receiver) => Reflect.has(overrides, prop) ? Reflect.get(overrides, prop, receiver) : Reflect.has(target, prop) ? Reflect.get(target, prop, receiver) : Reflect.get(tag$1, prop, tag$1),
458
- has: (target, prop) => Reflect.has(overrides, prop) || Reflect.has(target, prop) || Reflect.has(tag$1, prop)
459
- });
460
- };
461
-
462
- //#endregion
463
- //#region lib/Util/FileLogger.js
464
- const fileLogger = Effect.fnUntraced(function* (...segments) {
465
- const { dotAlchemy } = yield* AlchemyContext;
466
- const fs = yield* FileSystem.FileSystem;
467
- const path$1 = yield* Path;
468
- const logFile = path$1.join(dotAlchemy, "log", ...segments);
469
- yield* fs.makeDirectory(path$1.dirname(logFile), { recursive: true });
470
- return yield* Logger.formatLogFmt.pipe(Logger.toFile(logFile, { flag: "a" }));
471
- });
472
-
473
- //#endregion
474
- //#region lib/Stack.js
475
- const Stack = Object.assign(taggedFunction(EffectContext.Service()("Stack"), (stackName, options, eff) => {
476
- if (!stackName) return (stackName$1) => Object.assign(stackRef(stackName$1).pipe(effectClass), {
477
- stage: createStageProxy(stackName$1),
478
- make: (options$1, eff$1) => Stack(stackName$1, options$1, eff$1)
479
- });
480
- return eff.pipe(make$1({
481
- name: stackName,
482
- ...options
483
- }), (eff$1) => Object.assign(eff$1, { stage: createStageProxy(stackName) }));
484
- }));
485
- const createStageProxy = (stackName) => new Proxy({}, { get: (_, stage$1) => stackRef(stackName, { stage: stage$1 }) });
486
- const StackName = Stack.use((stack) => Effect.succeed(stack.name));
487
- const make$1 = (options) => (effect) => Effect.scope.pipe(Effect.flatMap((scope) => {
488
- if (options.state == null) return Effect.die(/* @__PURE__ */ new Error(`Stack "${options.name}" is missing a state store. Add a \`state\` layer to the stack options, e.g.:\n Alchemy.Stack("${options.name}", {\n providers: Cloudflare.providers(),\n state: Cloudflare.state(), // <-- required\n }, ...)\nSee https://v2.alchemy.run/concepts/state-store for available state stores.`));
489
- if (options.providers == null) return Effect.die(/* @__PURE__ */ new Error(`Stack "${options.name}" is missing a providers layer. Add a \`providers\` layer to the stack options, e.g.:\n Alchemy.Stack("${options.name}", {\n providers: Cloudflare.providers(), // <-- required\n state: Cloudflare.state(),\n }, ...)`));
490
- return options.providers.pipe(Layer.provideMerge(options.state), Layer.provideMerge(Layer.effect(Stack, Stage.pipe(Effect.map((stage$1) => options.stack ?? {
491
- name: options.name,
492
- stage: stage$1,
493
- resources: {},
494
- bindings: {},
495
- actions: {}
496
- })))), Layer.buildWithScope(scope));
497
- }), Effect.flatMap((context) => Effect.all([
498
- effect,
499
- Stack,
500
- Effect.context()
501
- ]).pipe(Effect.map(([output, stack, services$1]) => ({
502
- ...stack,
503
- output,
504
- services: EffectContext.merge(services$1, context)
505
- })), Effect.provideContext(context))));
506
- const CurrentStack = Effect.serviceOption(Stack).pipe(Effect.map(Option.getOrUndefined));
507
- const platform = Layer.mergeAll(PlatformServices, FetchHttpClient.layer, Logger.layer([fileLogger("out")], { mergeWithExisting: true }), Layer.provide(ProfileLive, PlatformServices), Layer.provide(CredentialsStoreLive, PlatformServices));
508
-
509
311
  //#endregion
510
312
  //#region lib/Resource.js
511
313
  const isResource = (value) => {
@@ -522,6 +324,10 @@ const isResource = (value) => {
522
324
  var RuntimeContext = class extends EffectContext.Service()("RuntimeContext") {};
523
325
  const CurrentRuntimeContext = Effect.serviceOption(RuntimeContext).pipe(Effect.map(Option.getOrUndefined));
524
326
 
327
+ //#endregion
328
+ //#region lib/Stage.js
329
+ var Stage = class extends EffectContext.Service()("Stage") {};
330
+
525
331
  //#endregion
526
332
  //#region lib/State/State.js
527
333
  const isActionState = (s) => !!s && s.kind === "action";
@@ -839,6 +645,282 @@ const toObject = (acc, v) => ({
839
645
  ...v
840
646
  });
841
647
 
648
+ //#endregion
649
+ //#region lib/Util/ConfigProvider.js
650
+ const loadConfigProvider = (envFile$1) => {
651
+ if (Option.isSome(envFile$1)) return ConfigProvider.fromDotEnv({ path: envFile$1.value }).pipe(Effect.map((dotEnv) => ConfigProvider.orElse(dotEnv, ConfigProvider.fromEnv())));
652
+ return Effect.gen(function* () {
653
+ if (!(yield* (yield* FileSystem.FileSystem).exists(".env"))) return ConfigProvider.fromEnv();
654
+ return ConfigProvider.orElse(yield* ConfigProvider.fromDotEnv({ path: ".env" }), ConfigProvider.fromEnv());
655
+ });
656
+ };
657
+
658
+ //#endregion
659
+ //#region lib/Util/effect.js
660
+ const effectClass = ((impl) => impl === void 0 ? (innerImpl) => effectClass(innerImpl) : Object.assign(class {
661
+ static asEffect() {
662
+ return impl;
663
+ }
664
+ static [Symbol.iterator]() {
665
+ return new SingleShotGen(this.asEffect());
666
+ }
667
+ static pipe(...fns) {
668
+ return pipeArguments(this, fns);
669
+ }
670
+ }, impl));
671
+ const taggedFunction = (tag$1, fn) => {
672
+ const overrides = {
673
+ asEffect: () => tag$1,
674
+ [Symbol.iterator]: () => tag$1[Symbol.iterator](),
675
+ pipe: (...fns) => pipeArguments(tag$1, fns),
676
+ toString: () => `${tag$1.toString()}.${fn.name}`
677
+ };
678
+ return new Proxy(fn, {
679
+ get: (target, prop, receiver) => Reflect.has(overrides, prop) ? Reflect.get(overrides, prop, receiver) : Reflect.has(target, prop) ? Reflect.get(target, prop, receiver) : Reflect.get(tag$1, prop, tag$1),
680
+ has: (target, prop) => Reflect.has(overrides, prop) || Reflect.has(target, prop) || Reflect.has(tag$1, prop)
681
+ });
682
+ };
683
+
684
+ //#endregion
685
+ //#region lib/Util/FileLogger.js
686
+ const fileLogger = Effect.fnUntraced(function* (...segments) {
687
+ const { dotAlchemy } = yield* AlchemyContext;
688
+ const fs = yield* FileSystem.FileSystem;
689
+ const path$1 = yield* Path;
690
+ const logFile = path$1.join(dotAlchemy, "log", ...segments);
691
+ yield* fs.makeDirectory(path$1.dirname(logFile), { recursive: true });
692
+ return yield* Logger.formatLogFmt.pipe(Logger.toFile(logFile, { flag: "a" }));
693
+ });
694
+
695
+ //#endregion
696
+ //#region lib/Util/PlatformServices.js
697
+ const isBun = typeof Bun !== "undefined";
698
+ /**
699
+ * Constructs a layer with different implementations for Bun and Node.
700
+ */
701
+ const platformLayer = (constructors) => Layer.unwrap(Effect.promise(async () => {
702
+ if (isBun) return await constructors.bun();
703
+ else return await constructors.node();
704
+ }));
705
+ const PlatformServices = platformLayer({
706
+ bun: async () => {
707
+ const [BunServices, BunSocket] = await Promise.all([import("@effect/platform-bun/BunServices"), import("@effect/platform-bun/BunSocket")]);
708
+ return Layer.merge(BunServices.layer, BunSocket.layerWebSocketConstructor);
709
+ },
710
+ node: async () => {
711
+ const [NodeServices, NodeSocket] = await Promise.all([import("@effect/platform-node/NodeServices"), import("@effect/platform-node/NodeSocket")]);
712
+ return Layer.merge(NodeServices.layer, NodeSocket.layerWebSocketConstructor);
713
+ }
714
+ });
715
+ const runMain = (effect, options) => {
716
+ if (isBun) import("@effect/platform-bun/BunRuntime").then((BunRuntime) => BunRuntime.runMain(effect, options));
717
+ else import("@effect/platform-node/NodeRuntime").then((NodeRuntime) => NodeRuntime.runMain(effect, options));
718
+ };
719
+
720
+ //#endregion
721
+ //#region lib/Stack.js
722
+ const Stack = Object.assign(taggedFunction(EffectContext.Service()("Stack"), (stackName, options, eff) => {
723
+ if (!stackName) return (stackName$1) => Object.assign(stackRef(stackName$1).pipe(effectClass), {
724
+ stage: createStageProxy(stackName$1),
725
+ make: (options$1, eff$1) => Stack(stackName$1, options$1, eff$1)
726
+ });
727
+ return eff.pipe(make$2({
728
+ name: stackName,
729
+ ...options
730
+ }), (eff$1) => Object.assign(eff$1, { stage: createStageProxy(stackName) }));
731
+ }));
732
+ const createStageProxy = (stackName) => new Proxy({}, { get: (_, stage$1) => stackRef(stackName, { stage: stage$1 }) });
733
+ const StackName = Stack.use((stack) => Effect.succeed(stack.name));
734
+ const make$2 = (options) => (effect) => Effect.scope.pipe(Effect.flatMap((scope) => {
735
+ if (options.state == null) return Effect.die(/* @__PURE__ */ new Error(`Stack "${options.name}" is missing a state store. Add a \`state\` layer to the stack options, e.g.:\n Alchemy.Stack("${options.name}", {\n providers: Cloudflare.providers(),\n state: Cloudflare.state(), // <-- required\n }, ...)\nSee https://v2.alchemy.run/concepts/state-store for available state stores.`));
736
+ if (options.providers == null) return Effect.die(/* @__PURE__ */ new Error(`Stack "${options.name}" is missing a providers layer. Add a \`providers\` layer to the stack options, e.g.:\n Alchemy.Stack("${options.name}", {\n providers: Cloudflare.providers(), // <-- required\n state: Cloudflare.state(),\n }, ...)`));
737
+ return options.providers.pipe(Layer.provideMerge(options.state), Layer.provideMerge(Layer.effect(Stack, Stage.pipe(Effect.map((stage$1) => options.stack ?? {
738
+ name: options.name,
739
+ stage: stage$1,
740
+ resources: {},
741
+ bindings: {},
742
+ actions: {}
743
+ })))), Layer.buildWithScope(scope));
744
+ }), Effect.flatMap((context) => Effect.all([
745
+ effect,
746
+ Stack,
747
+ Effect.context()
748
+ ]).pipe(Effect.map(([output, stack, services$1]) => ({
749
+ ...stack,
750
+ output,
751
+ services: EffectContext.merge(services$1, context)
752
+ })), Effect.provideContext(context))));
753
+ const CurrentStack = Effect.serviceOption(Stack).pipe(Effect.map(Option.getOrUndefined));
754
+ const platform = Layer.mergeAll(PlatformServices, FetchHttpClient.layer, Logger.layer([fileLogger("out")], { mergeWithExisting: true }), Layer.provide(ProfileLive, PlatformServices), Layer.provide(CredentialsStoreLive, PlatformServices));
755
+
756
+ //#endregion
757
+ //#region lib/Local/RpcSerialization.js
758
+ const unwrapRpcHandlers = (handlers, streamKeys) => {
759
+ return Object.fromEntries(Object.entries(handlers).map(([key, value]) => [key, typeof value === "function" ? streamKeys?.includes(key) ? unwrapRpcStreamHandler(value) : unwrapRpcEffectHandler(value) : typeof value === "object" && value !== null ? unwrapRpcHandlers(value) : value]));
760
+ };
761
+ const serializeError = Schema.encodeSync(Schema.Defect);
762
+ const unwrapRpcEffectHandler = (handler) => flow((...args) => serializeRpcArgs(args), (args) => Effect.promise(() => handler(args)), Effect.flatMap((exit) => {
763
+ if (exit._tag === "Success") return Exit.succeed(exit.value);
764
+ return Exit.failCause(Cause.fromReasons(exit.cause.map((reason) => {
765
+ switch (reason._tag) {
766
+ case "Fail": return Cause.makeFailReason(reason.error);
767
+ case "Die": return Cause.makeDieReason(reason.defect);
768
+ case "Interrupt": return Cause.makeInterruptReason(reason.fiberId);
769
+ }
770
+ })));
771
+ }));
772
+ const unwrapRpcStreamHandler = (handler) => flow((...args) => serializeRpcArgs(args), (args) => handler(args), (stream) => Stream.fromReadableStream({
773
+ evaluate: () => stream,
774
+ onError: (error) => error
775
+ }));
776
+ const serializeRpcArgs = (value) => {
777
+ if (Redacted.isRedacted(value)) return {
778
+ _tag: "Redacted",
779
+ value: Redacted.value(value)
780
+ };
781
+ if (isOutput(value)) return {
782
+ _tag: "Output",
783
+ description: NodeUtil.inspect(value)
784
+ };
785
+ if (typeof value === "function") return null;
786
+ if (Array.isArray(value)) return value.map(serializeRpcArgs);
787
+ if (value && typeof value === "object" && !("toJSON" in value)) return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, serializeRpcArgs(child)]));
788
+ return value;
789
+ };
790
+
791
+ //#endregion
792
+ //#region lib/Local/RpcProviderProxy.js
793
+ var RpcProviderProxy = class extends EffectContext.Service()("alchemy/Local/RpcProviderProxy") {};
794
+ const SPAWNER_URL_ENV_KEY = "ALCHEMY_RPC_SPAWNER_URL";
795
+ const make$1 = Effect.fnUntraced(function* (spawnerUrl) {
796
+ const client = yield* HttpClient.HttpClient;
797
+ const getSession = Effect.fnUntraced(function* (serverEntryUrl) {
798
+ const alchemyContext = yield* AlchemyContext;
799
+ const stack = yield* Stack;
800
+ const payload = {
801
+ serverEntryUrl,
802
+ alchemyContext,
803
+ stack: {
804
+ name: stack.name,
805
+ stage: stack.stage
806
+ }
807
+ };
808
+ return newWebSocketRpcSession(yield* (yield* client.post(spawnerUrl, { body: yield* HttpBody.json(payload) })).text);
809
+ }, (effect, serverEntryUrl) => Effect.catch(effect, (error) => Effect.die(new Error(`Failed to create provider RPC session for "${serverEntryUrl}"`, { cause: error }))));
810
+ const cache = yield* Cache.make({
811
+ lookup: getSession,
812
+ capacity: Infinity,
813
+ requireServicesAt: "lookup"
814
+ });
815
+ return RpcProviderProxy.of({ get: Effect.fnUntraced(function* (mainUrl, providerName) {
816
+ const session = yield* cache.lookup(mainUrl);
817
+ return unwrapRpcHandlers(yield* Effect.promise(() => session.getProvider(providerName)), ["tail"]);
818
+ }) });
819
+ });
820
+ const fromEnv = () => Layer.effect(RpcProviderProxy, Config.string(SPAWNER_URL_ENV_KEY).pipe(Effect.flatMap(make$1)));
821
+
822
+ //#endregion
823
+ //#region lib/AdoptPolicy.js
824
+ /**
825
+ * AdoptPolicy controls whether the engine should "adopt" pre-existing cloud
826
+ * resources that conflict with this stack instead of failing.
827
+ *
828
+ * The engine always calls a provider's `read` lifecycle operation when there
829
+ * is no prior state and `read` is implemented. The provider's job is to
830
+ * report two things:
831
+ *
832
+ * 1. Whether the resource exists (returns attributes vs. `undefined`).
833
+ * 2. Whether *we* own it (plain attributes vs. {@link Unowned}-branded).
834
+ *
835
+ * The engine then routes:
836
+ *
837
+ * | `read` outcome | `adopt: false` | `adopt: true` |
838
+ * | ------------------- | -------------- | ----------------- |
839
+ * | undefined | create | create |
840
+ * | owned (plain attrs) | silent adopt | silent adopt |
841
+ * | {@link Unowned} | fail | takeover (adopt) |
842
+ *
843
+ * "Owned" means a provider has affirmatively determined the resource was
844
+ * created by this stack/stage/logical-id (typically by inspecting tags or
845
+ * naming conventions). Resources without ownership semantics simply always
846
+ * return plain attrs — they are treated as owned by default, so silent
847
+ * adoption is the norm and `--adopt` is unnecessary.
848
+ *
849
+ * The policy can be overridden per-effect via {@link adopt} — most commonly
850
+ * applied at the resource or stack scope.
851
+ */
852
+ var AdoptPolicy = class extends EffectContext.Service()("AdoptPolicy") {};
853
+ /**
854
+ * Engine-raised failure produced when `read` reports an existing resource
855
+ * marked as {@link Unowned} and `adopt` is `false`. Surface this to the user
856
+ * to indicate they should either re-tag the cloud resource, pick a different
857
+ * physical name, or re-run with `--adopt` (or `adopt(true)`) to force a
858
+ * takeover.
859
+ */
860
+ var OwnedBySomeoneElse = class extends Data.TaggedError("OwnedBySomeoneElse") {};
861
+ /**
862
+ * Private symbol used to brand attribute objects returned by `read` as
863
+ * "exists in cloud, but not owned by this stack/stage/logical-id".
864
+ *
865
+ * Deliberately *not* registered via `Symbol.for` — the brand is an
866
+ * engine-internal routing hint and must not be observable or
867
+ * forgeable from outside this module. The engine strips it before any
868
+ * state persistence (see {@link stripUnowned}) so it never leaks into
869
+ * the state store, JSON serialization, or downstream `Output`s.
870
+ */
871
+ const UnownedTag = Symbol("alchemy/Unowned");
872
+ /**
873
+ * Brand a `read` return value as belonging to a different owner.
874
+ *
875
+ * Use this in a provider's `read` implementation when the resource exists in
876
+ * the cloud but a positive ownership check (e.g. tag inspection) shows it
877
+ * was *not* created by this stack/stage/logical-id:
878
+ *
879
+ * ```ts
880
+ * read: Effect.fnUntraced(function* ({ id, output, olds }) {
881
+ * const settings = yield* getScriptSettings({ ... }).pipe(
882
+ * Effect.catchTag("WorkerNotFound", () => Effect.succeed(undefined)),
883
+ * );
884
+ * if (!settings) return undefined;
885
+ *
886
+ * const attrs = { workerName, ...buildAttrs(settings) };
887
+ * return hasAlchemyWorkerTags(id, settings.tags) ? attrs : Unowned(attrs);
888
+ * }),
889
+ * ```
890
+ *
891
+ * The returned value is structurally still `T` — there is no wrapper to
892
+ * unwrap. The brand is a non-enumerable symbol that the engine inspects
893
+ * during planning to decide whether to take over (`adopt: true`) or fail
894
+ * loudly (`adopt: false`).
895
+ *
896
+ * Resources without ownership semantics should simply return plain attrs —
897
+ * the engine treats them as owned and silent adoption is the default.
898
+ */
899
+ const Unowned = Object.assign((attrs) => {
900
+ const cloned = { ...attrs };
901
+ Object.defineProperty(cloned, UnownedTag, {
902
+ value: true,
903
+ enumerable: false,
904
+ writable: false,
905
+ configurable: false
906
+ });
907
+ return cloned;
908
+ }, { is: (value) => typeof value === "object" && value !== null && value[UnownedTag] === true });
909
+ /**
910
+ * Strip the {@link Unowned} brand from an attributes object before persisting
911
+ * it — state should not carry per-deploy ownership-routing metadata.
912
+ *
913
+ * The brand is intentionally non-enumerable, so a plain spread already
914
+ * drops it; the additional `delete` is defense-in-depth in case a future
915
+ * change makes the descriptor enumerable. Always returns a fresh object
916
+ * (never mutates the input).
917
+ */
918
+ const stripUnowned = (attrs) => {
919
+ const out = { ...attrs };
920
+ if (UnownedTag in out) delete out[UnownedTag];
921
+ return out;
922
+ };
923
+
842
924
  //#endregion
843
925
  //#region lib/Diff.js
844
926
  const isResolved = (value) => !_hasUnresolved(value);
@@ -2420,7 +2502,7 @@ var __rewriteRelativeImportExtension = void 0 && (void 0).__rewriteRelativeImpor
2420
2502
  };
2421
2503
  const USER = Config.string("USER").pipe(Config.orElse(() => Config.string("USERNAME")), Config.withDefault("unknown"));
2422
2504
  const STAGE = Config.string("stage").pipe(Config.option, (a) => a, Effect.map(Option.getOrUndefined));
2423
- const stage = Flag.string("stage").pipe(Flag.withSchema(S.String.check(S.isPattern(/^[a-z0-9]+([-_a-z0-9]+)*$/gi))), Flag.withDescription("Stage to deploy to, defaults to dev_${USER}"), Flag.optional, Flag.map(Option.getOrUndefined), Flag.mapEffect(Effect.fn(function* (stage$1) {
2505
+ const stage = Flag.string("stage").pipe(Flag.withSchema(Schema.String.check(Schema.isPattern(/^[a-z0-9]+([-_a-z0-9]+)*$/gi))), Flag.withDescription("Stage to deploy to, defaults to dev_${USER}"), Flag.optional, Flag.map(Option.getOrUndefined), Flag.mapEffect(Effect.fn(function* (stage$1) {
2424
2506
  if (stage$1) return stage$1;
2425
2507
  return yield* STAGE.pipe(Effect.catch(() => Effect.fail(new CliError.MissingOption({ option: "stage" }))), Effect.flatMap((s) => s === void 0 ? USER.pipe(Effect.map((user) => `dev_${user}`), Effect.catch(() => Effect.succeed("unknown"))) : Effect.succeed(s)));
2426
2508
  })));
@@ -2460,17 +2542,17 @@ const importStack = Effect.fn(function* (main) {
2460
2542
 
2461
2543
  //#endregion
2462
2544
  //#region lib/Cli/commands/deploy.js
2463
- const ExecStackOptions = S.Struct({
2464
- main: S.String,
2465
- stage: S.String,
2466
- envFile: S.OptionFromOptional(S.String),
2467
- profile: S.optional(S.String),
2468
- dryRun: S.optional(S.Boolean),
2469
- force: S.optional(S.Boolean),
2470
- yes: S.optional(S.Boolean),
2471
- destroy: S.optional(S.Boolean),
2472
- dev: S.optional(S.Boolean),
2473
- adopt: S.optional(S.Boolean)
2545
+ const ExecStackOptions = Schema.Struct({
2546
+ main: Schema.String,
2547
+ stage: Schema.String,
2548
+ envFile: Schema.OptionFromOptional(Schema.String),
2549
+ profile: Schema.optional(Schema.String),
2550
+ dryRun: Schema.optional(Schema.Boolean),
2551
+ force: Schema.optional(Schema.Boolean),
2552
+ yes: Schema.optional(Schema.Boolean),
2553
+ destroy: Schema.optional(Schema.Boolean),
2554
+ dev: Schema.optional(Schema.Boolean),
2555
+ adopt: Schema.optional(Schema.Boolean)
2474
2556
  });
2475
2557
  const stackSpanAttrs = (args) => ({
2476
2558
  "alchemy.stage": args.stage,
@@ -3341,8 +3423,8 @@ const selectCli = () => isNonInteractive() ? LoggingCli : inkCLI();
3341
3423
 
3342
3424
  //#endregion
3343
3425
  //#region lib/Cli/exec.js
3344
- const services = Layer.mergeAll(Layer.provideMerge(AlchemyContextLive, PlatformServices), Layer.provide(ProfileLive, PlatformServices), Layer.provide(CredentialsStoreLive, PlatformServices), FetchHttpClient.layer, ConfigProvider.layer(ConfigProvider.fromEnv()), selectCli());
3345
- const exec = () => execStack(S.decodeSync(ExecStackOptions)(JSON.parse(process.env.ALCHEMY_EXEC_OPTIONS))).pipe(Effect.provide(services), Effect.scoped);
3426
+ const services = Layer.merge(selectCli(), fromEnv()).pipe(Layer.provideMerge(Layer.mergeAll(AlchemyContextLive, ProfileLive, CredentialsStoreLive)), Layer.provideMerge(Layer.mergeAll(PlatformServices, FetchHttpClient.layer, ConfigProvider.layer(ConfigProvider.fromEnv()))));
3427
+ const exec = () => execStack(Schema.decodeSync(ExecStackOptions)(JSON.parse(process.env.ALCHEMY_EXEC_OPTIONS))).pipe(Effect.provide(services), Effect.scoped);
3346
3428
 
3347
3429
  //#endregion
3348
3430
  //#region bin/exec.ts