alchemy 2.0.0-beta.50 → 2.0.0-beta.52

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 (254) hide show
  1. package/bin/exec.js +133 -135
  2. package/bin/exec.js.map +1 -1
  3. package/lib/AWS/Lambda/BucketEventSource.d.ts.map +1 -1
  4. package/lib/AWS/Lambda/BucketEventSource.js +13 -2
  5. package/lib/AWS/Lambda/BucketEventSource.js.map +1 -1
  6. package/lib/AWS/S3/Bucket.d.ts.map +1 -1
  7. package/lib/AWS/S3/Bucket.js +49 -0
  8. package/lib/AWS/S3/Bucket.js.map +1 -1
  9. package/lib/AWS/S3/BucketNotifications.d.ts +10 -0
  10. package/lib/AWS/S3/BucketNotifications.d.ts.map +1 -1
  11. package/lib/AWS/S3/BucketNotifications.js.map +1 -1
  12. package/lib/Apply.js +15 -3
  13. package/lib/Apply.js.map +1 -1
  14. package/lib/Auth/AuthProvider.js +1 -1
  15. package/lib/Auth/AuthProvider.js.map +1 -1
  16. package/lib/Binding.d.ts.map +1 -1
  17. package/lib/Binding.js +12 -8
  18. package/lib/Binding.js.map +1 -1
  19. package/lib/Build/DevServer.d.ts +113 -0
  20. package/lib/Build/DevServer.d.ts.map +1 -0
  21. package/lib/Build/DevServer.js +212 -0
  22. package/lib/Build/DevServer.js.map +1 -0
  23. package/lib/Build/Local.d.ts +2 -0
  24. package/lib/Build/Local.d.ts.map +1 -0
  25. package/lib/Build/Local.js +4 -0
  26. package/lib/Build/Local.js.map +1 -0
  27. package/lib/Bundle/Bundle.js +1 -1
  28. package/lib/Bundle/Bundle.js.map +1 -1
  29. package/lib/Cli/commands/cloudflare.d.ts +1 -1
  30. package/lib/Cloudflare/Access.js +1 -1
  31. package/lib/Cloudflare/Access.js.map +1 -1
  32. package/lib/Cloudflare/AiGateway/AiGateway.d.ts +1 -1
  33. package/lib/Cloudflare/AiGateway/AiGateway.js +1 -1
  34. package/lib/Cloudflare/AiGateway/AiGatewayBinding.d.ts +1 -1
  35. package/lib/Cloudflare/AiGateway/AiGatewayBinding.d.ts.map +1 -1
  36. package/lib/Cloudflare/AiGateway/AiGatewayBinding.js +6 -2
  37. package/lib/Cloudflare/AiGateway/AiGatewayBinding.js.map +1 -1
  38. package/lib/Cloudflare/Browser/Browser.d.ts +84 -12
  39. package/lib/Cloudflare/Browser/Browser.d.ts.map +1 -1
  40. package/lib/Cloudflare/Browser/Browser.js +80 -9
  41. package/lib/Cloudflare/Browser/Browser.js.map +1 -1
  42. package/lib/Cloudflare/Browser/BrowserBinding.d.ts +90 -16
  43. package/lib/Cloudflare/Browser/BrowserBinding.d.ts.map +1 -1
  44. package/lib/Cloudflare/Browser/BrowserBinding.js +41 -6
  45. package/lib/Cloudflare/Browser/BrowserBinding.js.map +1 -1
  46. package/lib/Cloudflare/Browser/index.d.ts +1 -1
  47. package/lib/Cloudflare/Browser/index.d.ts.map +1 -1
  48. package/lib/Cloudflare/Browser/index.js.map +1 -1
  49. package/lib/Cloudflare/Container/ContainerBinding.d.ts.map +1 -1
  50. package/lib/Cloudflare/Container/ContainerBinding.js +2 -4
  51. package/lib/Cloudflare/Container/ContainerBinding.js.map +1 -1
  52. package/lib/Cloudflare/Images/Images.d.ts +4 -3
  53. package/lib/Cloudflare/Images/Images.d.ts.map +1 -1
  54. package/lib/Cloudflare/Images/Images.js.map +1 -1
  55. package/lib/Cloudflare/Providers.d.ts +1 -1
  56. package/lib/Cloudflare/Providers.d.ts.map +1 -1
  57. package/lib/Cloudflare/Providers.js +6 -1
  58. package/lib/Cloudflare/Providers.js.map +1 -1
  59. package/lib/Cloudflare/RateLimit/RateLimit.d.ts +4 -3
  60. package/lib/Cloudflare/RateLimit/RateLimit.d.ts.map +1 -1
  61. package/lib/Cloudflare/RateLimit/RateLimit.js.map +1 -1
  62. package/lib/Cloudflare/Ruleset/Ruleset.d.ts +82 -0
  63. package/lib/Cloudflare/Ruleset/Ruleset.d.ts.map +1 -0
  64. package/lib/Cloudflare/Ruleset/Ruleset.js +126 -0
  65. package/lib/Cloudflare/Ruleset/Ruleset.js.map +1 -0
  66. package/lib/Cloudflare/Ruleset/index.d.ts +2 -0
  67. package/lib/Cloudflare/Ruleset/index.d.ts.map +1 -0
  68. package/lib/Cloudflare/Ruleset/index.js +2 -0
  69. package/lib/Cloudflare/Ruleset/index.js.map +1 -0
  70. package/lib/Cloudflare/SecretsStore/Secret.d.ts +1 -0
  71. package/lib/Cloudflare/SecretsStore/Secret.d.ts.map +1 -1
  72. package/lib/Cloudflare/SecretsStore/Secret.js +2 -0
  73. package/lib/Cloudflare/SecretsStore/Secret.js.map +1 -1
  74. package/lib/Cloudflare/StateStore/State.d.ts +1 -1
  75. package/lib/Cloudflare/StateStore/State.d.ts.map +1 -1
  76. package/lib/Cloudflare/Website/StaticSite.d.ts +64 -12
  77. package/lib/Cloudflare/Website/StaticSite.d.ts.map +1 -1
  78. package/lib/Cloudflare/Website/StaticSite.js +80 -30
  79. package/lib/Cloudflare/Website/StaticSite.js.map +1 -1
  80. package/lib/Cloudflare/Website/Vite.d.ts +36 -7
  81. package/lib/Cloudflare/Website/Vite.d.ts.map +1 -1
  82. package/lib/Cloudflare/Website/Vite.js +26 -8
  83. package/lib/Cloudflare/Website/Vite.js.map +1 -1
  84. package/lib/Cloudflare/Workers/Assets.d.ts +10 -4
  85. package/lib/Cloudflare/Workers/Assets.d.ts.map +1 -1
  86. package/lib/Cloudflare/Workers/Assets.js +6 -6
  87. package/lib/Cloudflare/Workers/Assets.js.map +1 -1
  88. package/lib/Cloudflare/Workers/DurableObjectChatPersistence.d.ts +69 -0
  89. package/lib/Cloudflare/Workers/DurableObjectChatPersistence.d.ts.map +1 -0
  90. package/lib/Cloudflare/Workers/DurableObjectChatPersistence.js +104 -0
  91. package/lib/Cloudflare/Workers/DurableObjectChatPersistence.js.map +1 -0
  92. package/lib/Cloudflare/Workers/DynamicWorkerLoader.d.ts +4 -4
  93. package/lib/Cloudflare/Workers/InferEnv.d.ts +1 -1
  94. package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
  95. package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
  96. package/lib/Cloudflare/Workers/LocalWorkerProvider.js +45 -11
  97. package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
  98. package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.d.ts +5 -4
  99. package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.d.ts.map +1 -1
  100. package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.js +4 -2
  101. package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.js.map +1 -1
  102. package/lib/Cloudflare/Workers/RpcWorker.d.ts +3 -2
  103. package/lib/Cloudflare/Workers/RpcWorker.d.ts.map +1 -1
  104. package/lib/Cloudflare/Workers/RpcWorker.js +5 -3
  105. package/lib/Cloudflare/Workers/RpcWorker.js.map +1 -1
  106. package/lib/Cloudflare/Workers/VersionMetadata.d.ts +99 -0
  107. package/lib/Cloudflare/Workers/VersionMetadata.d.ts.map +1 -0
  108. package/lib/Cloudflare/Workers/VersionMetadata.js +65 -0
  109. package/lib/Cloudflare/Workers/VersionMetadata.js.map +1 -0
  110. package/lib/Cloudflare/Workers/VersionMetadataBinding.d.ts +35 -0
  111. package/lib/Cloudflare/Workers/VersionMetadataBinding.d.ts.map +1 -0
  112. package/lib/Cloudflare/Workers/VersionMetadataBinding.js +31 -0
  113. package/lib/Cloudflare/Workers/VersionMetadataBinding.js.map +1 -0
  114. package/lib/Cloudflare/Workers/Worker.d.ts +20 -19
  115. package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
  116. package/lib/Cloudflare/Workers/Worker.js +23 -37
  117. package/lib/Cloudflare/Workers/Worker.js.map +1 -1
  118. package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts.map +1 -1
  119. package/lib/Cloudflare/Workers/WorkerAsyncBindings.js +16 -0
  120. package/lib/Cloudflare/Workers/WorkerAsyncBindings.js.map +1 -1
  121. package/lib/Cloudflare/Workers/WorkerBinding.d.ts +3 -1
  122. package/lib/Cloudflare/Workers/WorkerBinding.d.ts.map +1 -1
  123. package/lib/Cloudflare/Workers/WorkerBinding.js.map +1 -1
  124. package/lib/Cloudflare/Workers/Workflow.d.ts +8 -1
  125. package/lib/Cloudflare/Workers/Workflow.d.ts.map +1 -1
  126. package/lib/Cloudflare/Workers/Workflow.js +1 -0
  127. package/lib/Cloudflare/Workers/Workflow.js.map +1 -1
  128. package/lib/Cloudflare/Workers/WorkflowBridge.d.ts.map +1 -1
  129. package/lib/Cloudflare/Workers/WorkflowBridge.js +31 -2
  130. package/lib/Cloudflare/Workers/WorkflowBridge.js.map +1 -1
  131. package/lib/Cloudflare/Workers/index.d.ts +3 -0
  132. package/lib/Cloudflare/Workers/index.d.ts.map +1 -1
  133. package/lib/Cloudflare/Workers/index.js +3 -0
  134. package/lib/Cloudflare/Workers/index.js.map +1 -1
  135. package/lib/Cloudflare/Zaraz/ZarazConfig.d.ts.map +1 -1
  136. package/lib/Cloudflare/index.d.ts +1 -0
  137. package/lib/Cloudflare/index.d.ts.map +1 -1
  138. package/lib/Cloudflare/index.js +1 -0
  139. package/lib/Cloudflare/index.js.map +1 -1
  140. package/lib/Deploy.d.ts +3 -2
  141. package/lib/Deploy.d.ts.map +1 -1
  142. package/lib/Deploy.js.map +1 -1
  143. package/lib/Destroy.d.ts +3 -2
  144. package/lib/Destroy.d.ts.map +1 -1
  145. package/lib/Destroy.js.map +1 -1
  146. package/lib/Diff.d.ts.map +1 -1
  147. package/lib/Diff.js +7 -0
  148. package/lib/Diff.js.map +1 -1
  149. package/lib/Drizzle/Postgres.d.ts +13 -12
  150. package/lib/Drizzle/Postgres.d.ts.map +1 -1
  151. package/lib/Drizzle/Postgres.js +13 -12
  152. package/lib/Drizzle/Postgres.js.map +1 -1
  153. package/lib/Drizzle/Schema.d.ts +1 -1
  154. package/lib/Drizzle/Schema.d.ts.map +1 -1
  155. package/lib/Drizzle/Schema.js +20 -9
  156. package/lib/Drizzle/Schema.js.map +1 -1
  157. package/lib/Local/RpcSerialization.js +5 -2
  158. package/lib/Local/RpcSerialization.js.map +1 -1
  159. package/lib/Output.d.ts.map +1 -1
  160. package/lib/Output.js +11 -10
  161. package/lib/Output.js.map +1 -1
  162. package/lib/Plan.d.ts.map +1 -1
  163. package/lib/Plan.js +5 -1
  164. package/lib/Plan.js.map +1 -1
  165. package/lib/Planetscale/MySQL/MySQLDatabase.d.ts +0 -2
  166. package/lib/Planetscale/MySQL/MySQLDatabase.d.ts.map +1 -1
  167. package/lib/Planetscale/MySQL/MySQLDatabase.js +1 -3
  168. package/lib/Planetscale/MySQL/MySQLDatabase.js.map +1 -1
  169. package/lib/Planetscale/Postgres/PostgresDatabase.d.ts +0 -2
  170. package/lib/Planetscale/Postgres/PostgresDatabase.d.ts.map +1 -1
  171. package/lib/Planetscale/Postgres/PostgresDatabase.js +1 -3
  172. package/lib/Planetscale/Postgres/PostgresDatabase.js.map +1 -1
  173. package/lib/Platform.d.ts +4 -4
  174. package/lib/Platform.d.ts.map +1 -1
  175. package/lib/Platform.js +27 -25
  176. package/lib/Platform.js.map +1 -1
  177. package/lib/Resource.d.ts +7 -1
  178. package/lib/Resource.d.ts.map +1 -1
  179. package/lib/Resource.js +11 -12
  180. package/lib/Resource.js.map +1 -1
  181. package/lib/Runtime.d.ts +1 -1
  182. package/lib/Runtime.d.ts.map +1 -1
  183. package/lib/Runtime.js +3 -4
  184. package/lib/Runtime.js.map +1 -1
  185. package/lib/Stack.d.ts +5 -4
  186. package/lib/Stack.d.ts.map +1 -1
  187. package/lib/Stack.js.map +1 -1
  188. package/lib/Test/Core.d.ts +2 -2
  189. package/lib/Test/Core.d.ts.map +1 -1
  190. package/lib/Util/effect.d.ts.map +1 -1
  191. package/lib/Util/effect.js +13 -15
  192. package/lib/Util/effect.js.map +1 -1
  193. package/lib/Util/poll.d.ts +0 -1
  194. package/lib/Util/poll.d.ts.map +1 -1
  195. package/lib/Util/poll.js +2 -2
  196. package/lib/Util/poll.js.map +1 -1
  197. package/lib/tsconfig.test.tsbuildinfo +1 -1
  198. package/package.json +20 -20
  199. package/src/AWS/Lambda/BucketEventSource.ts +16 -1
  200. package/src/AWS/S3/Bucket.ts +78 -0
  201. package/src/AWS/S3/BucketNotifications.ts +10 -0
  202. package/src/Apply.ts +22 -3
  203. package/src/Auth/AuthProvider.ts +1 -1
  204. package/src/Binding.ts +45 -38
  205. package/src/Build/DevServer.ts +330 -0
  206. package/src/Build/Local.ts +4 -0
  207. package/src/Bundle/Bundle.ts +1 -1
  208. package/src/Cloudflare/Access.ts +1 -1
  209. package/src/Cloudflare/AiGateway/AiGateway.ts +1 -1
  210. package/src/Cloudflare/AiGateway/AiGatewayBinding.ts +8 -3
  211. package/src/Cloudflare/Browser/Browser.ts +84 -12
  212. package/src/Cloudflare/Browser/BrowserBinding.ts +205 -33
  213. package/src/Cloudflare/Browser/index.ts +15 -2
  214. package/src/Cloudflare/Container/ContainerBinding.ts +5 -10
  215. package/src/Cloudflare/Images/Images.ts +4 -3
  216. package/src/Cloudflare/Providers.ts +8 -0
  217. package/src/Cloudflare/RateLimit/RateLimit.ts +4 -3
  218. package/src/Cloudflare/Ruleset/Ruleset.ts +223 -0
  219. package/src/Cloudflare/Ruleset/index.ts +1 -0
  220. package/src/Cloudflare/SecretsStore/Secret.ts +4 -0
  221. package/src/Cloudflare/Website/StaticSite.ts +154 -41
  222. package/src/Cloudflare/Website/Vite.ts +73 -25
  223. package/src/Cloudflare/Workers/Assets.ts +10 -8
  224. package/src/Cloudflare/Workers/DurableObjectChatPersistence.ts +131 -0
  225. package/src/Cloudflare/Workers/DynamicWorkerLoader.ts +4 -4
  226. package/src/Cloudflare/Workers/InferEnv.ts +14 -12
  227. package/src/Cloudflare/Workers/LocalWorkerProvider.ts +54 -13
  228. package/src/Cloudflare/Workers/RpcDurableObjectNamespace.ts +11 -8
  229. package/src/Cloudflare/Workers/RpcWorker.ts +8 -7
  230. package/src/Cloudflare/Workers/VersionMetadata.ts +129 -0
  231. package/src/Cloudflare/Workers/VersionMetadataBinding.ts +82 -0
  232. package/src/Cloudflare/Workers/Worker.ts +66 -82
  233. package/src/Cloudflare/Workers/WorkerAsyncBindings.ts +14 -0
  234. package/src/Cloudflare/Workers/WorkerBinding.ts +4 -0
  235. package/src/Cloudflare/Workers/Workflow.ts +12 -1
  236. package/src/Cloudflare/Workers/WorkflowBridge.ts +47 -6
  237. package/src/Cloudflare/Workers/index.ts +3 -0
  238. package/src/Cloudflare/index.ts +1 -0
  239. package/src/Deploy.ts +2 -1
  240. package/src/Destroy.ts +2 -1
  241. package/src/Diff.ts +7 -0
  242. package/src/Drizzle/Postgres.ts +13 -12
  243. package/src/Drizzle/Schema.ts +27 -9
  244. package/src/Local/RpcSerialization.ts +5 -2
  245. package/src/Output.ts +12 -10
  246. package/src/Plan.ts +5 -1
  247. package/src/Planetscale/MySQL/MySQLDatabase.ts +1 -6
  248. package/src/Planetscale/Postgres/PostgresDatabase.ts +1 -5
  249. package/src/Platform.ts +48 -36
  250. package/src/Resource.ts +22 -13
  251. package/src/Runtime.ts +3 -7
  252. package/src/Stack.ts +11 -10
  253. package/src/Util/effect.ts +13 -17
  254. package/src/Util/poll.ts +3 -3
package/bin/exec.js CHANGED
@@ -24,7 +24,7 @@ import * as Data from "effect/Data";
24
24
  import * as Duration from "effect/Duration";
25
25
  import { flow, pipe } from "effect/Function";
26
26
  import { SingleShotGen } from "effect/Utils";
27
- import { pipeArguments } from "effect/Pipeable";
27
+ import * as Effectable from "effect/Effectable";
28
28
  import "effect/Predicate";
29
29
  import "effect/Record";
30
30
  import * as Cause from "effect/Cause";
@@ -232,6 +232,108 @@ const RefMetadata = Symbol.for("alchemy/RefMetadata");
232
232
  const isRef = (s) => s && s[RefMetadata] !== void 0;
233
233
  const getRefMetadata = (ref) => ref[RefMetadata];
234
234
 
235
+ //#endregion
236
+ //#region lib/AdoptPolicy.js
237
+ /**
238
+ * AdoptPolicy controls whether the engine should "adopt" pre-existing cloud
239
+ * resources that conflict with this stack instead of failing.
240
+ *
241
+ * The engine always calls a provider's `read` lifecycle operation when there
242
+ * is no prior state and `read` is implemented. The provider's job is to
243
+ * report two things:
244
+ *
245
+ * 1. Whether the resource exists (returns attributes vs. `undefined`).
246
+ * 2. Whether *we* own it (plain attributes vs. {@link Unowned}-branded).
247
+ *
248
+ * The engine then routes:
249
+ *
250
+ * | `read` outcome | `adopt: false` | `adopt: true` |
251
+ * | ------------------- | -------------- | ----------------- |
252
+ * | undefined | create | create |
253
+ * | owned (plain attrs) | silent adopt | silent adopt |
254
+ * | {@link Unowned} | fail | takeover (adopt) |
255
+ *
256
+ * "Owned" means a provider has affirmatively determined the resource was
257
+ * created by this stack/stage/logical-id (typically by inspecting tags or
258
+ * naming conventions). Resources without ownership semantics simply always
259
+ * return plain attrs — they are treated as owned by default, so silent
260
+ * adoption is the norm and `--adopt` is unnecessary.
261
+ *
262
+ * The policy can be overridden per-effect via {@link adopt} — most commonly
263
+ * applied at the resource or stack scope.
264
+ */
265
+ var AdoptPolicy = class extends EffectContext.Service()("AdoptPolicy") {};
266
+ /**
267
+ * Engine-raised failure produced when `read` reports an existing resource
268
+ * marked as {@link Unowned} and `adopt` is `false`. Surface this to the user
269
+ * to indicate they should either re-tag the cloud resource, pick a different
270
+ * physical name, or re-run with `--adopt` (or `adopt(true)`) to force a
271
+ * takeover.
272
+ */
273
+ var OwnedBySomeoneElse = class extends Data.TaggedError("OwnedBySomeoneElse") {};
274
+ /**
275
+ * Private symbol used to brand attribute objects returned by `read` as
276
+ * "exists in cloud, but not owned by this stack/stage/logical-id".
277
+ *
278
+ * Deliberately *not* registered via `Symbol.for` — the brand is an
279
+ * engine-internal routing hint and must not be observable or
280
+ * forgeable from outside this module. The engine strips it before any
281
+ * state persistence (see {@link stripUnowned}) so it never leaks into
282
+ * the state store, JSON serialization, or downstream `Output`s.
283
+ */
284
+ const UnownedTag = Symbol("alchemy/Unowned");
285
+ /**
286
+ * Brand a `read` return value as belonging to a different owner.
287
+ *
288
+ * Use this in a provider's `read` implementation when the resource exists in
289
+ * the cloud but a positive ownership check (e.g. tag inspection) shows it
290
+ * was *not* created by this stack/stage/logical-id:
291
+ *
292
+ * ```ts
293
+ * read: Effect.fnUntraced(function* ({ id, output, olds }) {
294
+ * const settings = yield* getScriptSettings({ ... }).pipe(
295
+ * Effect.catchTag("WorkerNotFound", () => Effect.succeed(undefined)),
296
+ * );
297
+ * if (!settings) return undefined;
298
+ *
299
+ * const attrs = { workerName, ...buildAttrs(settings) };
300
+ * return hasAlchemyWorkerTags(id, settings.tags) ? attrs : Unowned(attrs);
301
+ * }),
302
+ * ```
303
+ *
304
+ * The returned value is structurally still `T` — there is no wrapper to
305
+ * unwrap. The brand is a non-enumerable symbol that the engine inspects
306
+ * during planning to decide whether to take over (`adopt: true`) or fail
307
+ * loudly (`adopt: false`).
308
+ *
309
+ * Resources without ownership semantics should simply return plain attrs —
310
+ * the engine treats them as owned and silent adoption is the default.
311
+ */
312
+ const Unowned = Object.assign((attrs) => {
313
+ const cloned = { ...attrs };
314
+ Object.defineProperty(cloned, UnownedTag, {
315
+ value: true,
316
+ enumerable: false,
317
+ writable: false,
318
+ configurable: false
319
+ });
320
+ return cloned;
321
+ }, { is: (value) => typeof value === "object" && value !== null && value[UnownedTag] === true });
322
+ /**
323
+ * Strip the {@link Unowned} brand from an attributes object before persisting
324
+ * it — state should not carry per-deploy ownership-routing metadata.
325
+ *
326
+ * The brand is intentionally non-enumerable, so a plain spread already
327
+ * drops it; the additional `delete` is defense-in-depth in case a future
328
+ * change makes the descriptor enumerable. Always returns a fresh object
329
+ * (never mutates the input).
330
+ */
331
+ const stripUnowned = (attrs) => {
332
+ const out = { ...attrs };
333
+ if (UnownedTag in out) delete out[UnownedTag];
334
+ return out;
335
+ };
336
+
235
337
  //#endregion
236
338
  //#region lib/FQN.js
237
339
  /**
@@ -366,6 +468,7 @@ const of = (resource) => {
366
468
  const asOutput = (t) => isOutput(t) ? t : Effect.isEffect(t) ? new EffectExpr(VoidExpr, () => t) : new LiteralExpr(t);
367
469
  const isOutput = (value) => value && (typeof value === "object" || typeof value === "function") && ExprSymbol in value;
368
470
  const ExprSymbol = Symbol.for("alchemy/Expr");
471
+ const exprKind = (node) => node?.[ExprSymbol]?.kind ?? node?.kind;
369
472
  const isExpr = (value) => value && (typeof value === "object" || typeof value === "function") && ExprSymbol in value;
370
473
  var BaseExpr = class {
371
474
  constructor() {}
@@ -389,7 +492,7 @@ var BaseExpr = class {
389
492
  return this[inspect]();
390
493
  }
391
494
  };
392
- const isResourceExpr = (node) => node?.kind === "ResourceExpr";
495
+ const isResourceExpr = (node) => exprKind(node) === "ResourceExpr";
393
496
  var ResourceExpr = class extends BaseExpr {
394
497
  src;
395
498
  stables;
@@ -404,7 +507,7 @@ var ResourceExpr = class extends BaseExpr {
404
507
  return this.src.LogicalId;
405
508
  }
406
509
  };
407
- const isPropExpr = (node) => node?.kind === "PropExpr";
510
+ const isPropExpr = (node) => exprKind(node) === "PropExpr";
408
511
  var PropExpr = class extends BaseExpr {
409
512
  expr;
410
513
  identifier;
@@ -419,7 +522,7 @@ var PropExpr = class extends BaseExpr {
419
522
  return `${this.expr[inspect]()}.${this.identifier.toString()}`;
420
523
  }
421
524
  };
422
- const isLiteralExpr = (node) => node?.kind === "LiteralExpr";
525
+ const isLiteralExpr = (node) => exprKind(node) === "LiteralExpr";
423
526
  var LiteralExpr = class extends BaseExpr {
424
527
  value;
425
528
  kind = "LiteralExpr";
@@ -433,7 +536,7 @@ var LiteralExpr = class extends BaseExpr {
433
536
  }
434
537
  };
435
538
  const VoidExpr = new LiteralExpr(void 0);
436
- const isApplyExpr = (node) => node?.kind === "ApplyExpr";
539
+ const isApplyExpr = (node) => exprKind(node) === "ApplyExpr";
437
540
  var ApplyExpr = class extends BaseExpr {
438
541
  expr;
439
542
  f;
@@ -448,7 +551,7 @@ var ApplyExpr = class extends BaseExpr {
448
551
  return `${this.expr[inspect]()}.map(${this.f.toString()})`;
449
552
  }
450
553
  };
451
- const isFlatMapExpr = (node) => node?.kind === "FlatMapExpr";
554
+ const isFlatMapExpr = (node) => exprKind(node) === "FlatMapExpr";
452
555
  var FlatMapExpr = class extends BaseExpr {
453
556
  expr;
454
557
  f;
@@ -463,7 +566,7 @@ var FlatMapExpr = class extends BaseExpr {
463
566
  return `${this.expr[inspect]()}.flatMap(${this.f.toString()})`;
464
567
  }
465
568
  };
466
- const isEffectExpr = (node) => node?.kind === "EffectExpr";
569
+ const isEffectExpr = (node) => exprKind(node) === "EffectExpr";
467
570
  var EffectExpr = class extends BaseExpr {
468
571
  expr;
469
572
  f;
@@ -478,7 +581,7 @@ var EffectExpr = class extends BaseExpr {
478
581
  return `${this.expr[inspect]()}.mapEffect(${this.f.toString()})`;
479
582
  }
480
583
  };
481
- const isNamedExpr = (node) => node?.kind === "NamedExpr";
584
+ const isNamedExpr = (node) => exprKind(node) === "NamedExpr";
482
585
  /**
483
586
  * Wraps another `Expr` and overrides its `toString()` / inspect output.
484
587
  *
@@ -500,7 +603,7 @@ var NamedExpr = class extends BaseExpr {
500
603
  return this.bindingName;
501
604
  }
502
605
  };
503
- const isAllExpr = (node) => node?.kind === "AllExpr";
606
+ const isAllExpr = (node) => exprKind(node) === "AllExpr";
504
607
  var AllExpr = class extends BaseExpr {
505
608
  outs;
506
609
  kind = "AllExpr";
@@ -513,7 +616,7 @@ var AllExpr = class extends BaseExpr {
513
616
  return `all(${this.outs.map((out) => out[inspect]()).join(", ")})`;
514
617
  }
515
618
  };
516
- const isRefExpr = (node) => node?.kind === "RefExpr";
619
+ const isRefExpr = (node) => exprKind(node) === "RefExpr";
517
620
  var RefExpr = class extends BaseExpr {
518
621
  stack;
519
622
  stage;
@@ -530,7 +633,7 @@ var RefExpr = class extends BaseExpr {
530
633
  return `ref(${this.resourceId}, { stack: ${this.stack}, stage: ${this.stage} })`;
531
634
  }
532
635
  };
533
- const isStackRefExpr = (node) => node?.kind === "StackRefExpr";
636
+ const isStackRefExpr = (node) => exprKind(node) === "StackRefExpr";
534
637
  /**
535
638
  * A reference to the persisted output of a Stack at `(stack, stage)`.
536
639
  *
@@ -695,24 +798,12 @@ const loadConfigProvider = (envFile$1) => {
695
798
 
696
799
  //#endregion
697
800
  //#region lib/Util/effect.js
698
- const effectClass = ((impl) => impl === void 0 ? (innerImpl) => effectClass(innerImpl) : Object.assign(class {
699
- static asEffect() {
700
- return impl;
701
- }
702
- static [Symbol.iterator]() {
703
- return new SingleShotGen(this.asEffect());
704
- }
705
- static pipe(...fns) {
706
- return pipeArguments(this, fns);
707
- }
708
- }, impl));
801
+ const effectClass = ((impl) => impl === void 0 ? (innerImpl) => effectClass(innerImpl) : Object.assign(class {}, Effectable.Prototype({
802
+ label: "alchemy/EffectClass",
803
+ evaluate: () => impl
804
+ })));
709
805
  const taggedFunction = (tag$1, fn) => {
710
- const overrides = {
711
- asEffect: () => tag$1,
712
- [Symbol.iterator]: () => tag$1[Symbol.iterator](),
713
- pipe: (...fns) => pipeArguments(tag$1, fns),
714
- toString: () => `${tag$1.toString()}.${fn.name}`
715
- };
806
+ const overrides = { toString: () => `${tag$1.toString()}.${fn.name}` };
716
807
  return new Proxy(fn, {
717
808
  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),
718
809
  has: (target, prop) => Reflect.has(overrides, prop) || Reflect.has(target, prop) || Reflect.has(tag$1, prop)
@@ -804,7 +895,7 @@ const platform = Layer.mergeAll(PlatformServices, FetchHttpClient.layer, Logger.
804
895
  const unwrapRpcHandlers = (handlers, streamKeys) => {
805
896
  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]));
806
897
  };
807
- const serializeError = Schema.encodeSync(Schema.Defect);
898
+ const serializeError = Schema.encodeSync(Schema.Defect());
808
899
  const unwrapRpcEffectHandler = (handler) => flow((...args) => serializeRpcArgs(args), (args) => Effect.promise(() => handler(args)), Effect.flatMap((exit) => {
809
900
  if (exit._tag === "Success") return Exit.succeed(exit.value);
810
901
  return Exit.failCause(Cause.fromReasons(exit.cause.map((reason) => {
@@ -865,108 +956,6 @@ const make$1 = Effect.fnUntraced(function* (spawnerUrl) {
865
956
  });
866
957
  const fromEnv = () => Layer.effect(RpcProviderProxy, Config.string(SPAWNER_URL_ENV_KEY).pipe(Effect.flatMap(make$1)));
867
958
 
868
- //#endregion
869
- //#region lib/AdoptPolicy.js
870
- /**
871
- * AdoptPolicy controls whether the engine should "adopt" pre-existing cloud
872
- * resources that conflict with this stack instead of failing.
873
- *
874
- * The engine always calls a provider's `read` lifecycle operation when there
875
- * is no prior state and `read` is implemented. The provider's job is to
876
- * report two things:
877
- *
878
- * 1. Whether the resource exists (returns attributes vs. `undefined`).
879
- * 2. Whether *we* own it (plain attributes vs. {@link Unowned}-branded).
880
- *
881
- * The engine then routes:
882
- *
883
- * | `read` outcome | `adopt: false` | `adopt: true` |
884
- * | ------------------- | -------------- | ----------------- |
885
- * | undefined | create | create |
886
- * | owned (plain attrs) | silent adopt | silent adopt |
887
- * | {@link Unowned} | fail | takeover (adopt) |
888
- *
889
- * "Owned" means a provider has affirmatively determined the resource was
890
- * created by this stack/stage/logical-id (typically by inspecting tags or
891
- * naming conventions). Resources without ownership semantics simply always
892
- * return plain attrs — they are treated as owned by default, so silent
893
- * adoption is the norm and `--adopt` is unnecessary.
894
- *
895
- * The policy can be overridden per-effect via {@link adopt} — most commonly
896
- * applied at the resource or stack scope.
897
- */
898
- var AdoptPolicy = class extends EffectContext.Service()("AdoptPolicy") {};
899
- /**
900
- * Engine-raised failure produced when `read` reports an existing resource
901
- * marked as {@link Unowned} and `adopt` is `false`. Surface this to the user
902
- * to indicate they should either re-tag the cloud resource, pick a different
903
- * physical name, or re-run with `--adopt` (or `adopt(true)`) to force a
904
- * takeover.
905
- */
906
- var OwnedBySomeoneElse = class extends Data.TaggedError("OwnedBySomeoneElse") {};
907
- /**
908
- * Private symbol used to brand attribute objects returned by `read` as
909
- * "exists in cloud, but not owned by this stack/stage/logical-id".
910
- *
911
- * Deliberately *not* registered via `Symbol.for` — the brand is an
912
- * engine-internal routing hint and must not be observable or
913
- * forgeable from outside this module. The engine strips it before any
914
- * state persistence (see {@link stripUnowned}) so it never leaks into
915
- * the state store, JSON serialization, or downstream `Output`s.
916
- */
917
- const UnownedTag = Symbol("alchemy/Unowned");
918
- /**
919
- * Brand a `read` return value as belonging to a different owner.
920
- *
921
- * Use this in a provider's `read` implementation when the resource exists in
922
- * the cloud but a positive ownership check (e.g. tag inspection) shows it
923
- * was *not* created by this stack/stage/logical-id:
924
- *
925
- * ```ts
926
- * read: Effect.fnUntraced(function* ({ id, output, olds }) {
927
- * const settings = yield* getScriptSettings({ ... }).pipe(
928
- * Effect.catchTag("WorkerNotFound", () => Effect.succeed(undefined)),
929
- * );
930
- * if (!settings) return undefined;
931
- *
932
- * const attrs = { workerName, ...buildAttrs(settings) };
933
- * return hasAlchemyWorkerTags(id, settings.tags) ? attrs : Unowned(attrs);
934
- * }),
935
- * ```
936
- *
937
- * The returned value is structurally still `T` — there is no wrapper to
938
- * unwrap. The brand is a non-enumerable symbol that the engine inspects
939
- * during planning to decide whether to take over (`adopt: true`) or fail
940
- * loudly (`adopt: false`).
941
- *
942
- * Resources without ownership semantics should simply return plain attrs —
943
- * the engine treats them as owned and silent adoption is the default.
944
- */
945
- const Unowned = Object.assign((attrs) => {
946
- const cloned = { ...attrs };
947
- Object.defineProperty(cloned, UnownedTag, {
948
- value: true,
949
- enumerable: false,
950
- writable: false,
951
- configurable: false
952
- });
953
- return cloned;
954
- }, { is: (value) => typeof value === "object" && value !== null && value[UnownedTag] === true });
955
- /**
956
- * Strip the {@link Unowned} brand from an attributes object before persisting
957
- * it — state should not carry per-deploy ownership-routing metadata.
958
- *
959
- * The brand is intentionally non-enumerable, so a plain spread already
960
- * drops it; the additional `delete` is defense-in-depth in case a future
961
- * change makes the descriptor enumerable. Always returns a fresh object
962
- * (never mutates the input).
963
- */
964
- const stripUnowned = (attrs) => {
965
- const out = { ...attrs };
966
- if (UnownedTag in out) delete out[UnownedTag];
967
- return out;
968
- };
969
-
970
959
  //#endregion
971
960
  //#region lib/Diff.js
972
961
  const isResolved = (value) => !_hasUnresolved(value);
@@ -980,6 +969,10 @@ const _hasUnresolved = (value) => {
980
969
  const havePropsChanged = (oldProps, newProps) => hasOutputs(newProps) || JSON.stringify(canonicalize(oldProps ?? {}, false)) !== JSON.stringify(canonicalize(newProps ?? {}, false));
981
970
  const canonicalize = (value, stripNullish) => {
982
971
  if (stripNullish && value == null) return void 0;
972
+ if (Redacted.isRedacted(value)) return {
973
+ _tag: "Redacted",
974
+ value: Redacted.value(value)
975
+ };
983
976
  if (Array.isArray(value)) return value.map((v) => canonicalize(v, stripNullish));
984
977
  if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).filter(([, nested]) => !stripNullish || nested != null).sort(([a], [b]) => a.localeCompare(b)).map(([key, nested]) => [key, canonicalize(nested, stripNullish)]));
985
978
  return value;
@@ -1372,7 +1365,9 @@ const make = (stack, options = {}) => Effect.gen(function* () {
1372
1365
  output: void 0
1373
1366
  }).pipe(providePlanScope(fqn, adoptInstanceId));
1374
1367
  if (readResult !== void 0) {
1375
- if (Unowned.is(readResult) && !(yield* shouldAdopt)) return yield* new OwnedBySomeoneElse({
1368
+ const isUnowned = Unowned.is(readResult);
1369
+ const adoptThis = resource.Adopt ?? (yield* shouldAdopt);
1370
+ if (isUnowned && !adoptThis) return yield* new OwnedBySomeoneElse({
1376
1371
  message: `Cannot adopt resource '${fqn}' (${resource.Type}): it exists in the cloud but is not owned by this stack/stage/logical-id. Re-run with \`--adopt\` (or wrap the effect in \`adopt(true)\`) to take it over.`,
1377
1372
  resourceType: resource.Type,
1378
1373
  logicalId: id
@@ -1667,6 +1662,7 @@ const make = (stack, options = {}) => Effect.gen(function* () {
1667
1662
  Binding: void 0,
1668
1663
  Provider: Provider(resourceType),
1669
1664
  RemovalPolicy: oldState.removalPolicy,
1665
+ Adopt: void 0,
1670
1666
  RuntimeContext: void 0,
1671
1667
  Providers: void 0
1672
1668
  },
@@ -2483,7 +2479,9 @@ const collectGarbage = Effect.fnUntraced(function* (plan, session) {
2483
2479
  removalPolicy: node.resource.RemovalPolicy
2484
2480
  });
2485
2481
  }
2486
- if (attr !== void 0) yield* provider.delete({
2482
+ const retainOldGeneration = !isDeleteNode(node) && node.removalPolicy === "retain";
2483
+ if (retainOldGeneration) yield* scopedSession.note("Retaining replaced resource (removal policy: retain)...");
2484
+ if (attr !== void 0 && !retainOldGeneration) yield* provider.delete({
2487
2485
  id: logicalId,
2488
2486
  instanceId,
2489
2487
  olds: props,
@@ -2499,7 +2497,7 @@ const collectGarbage = Effect.fnUntraced(function* (plan, session) {
2499
2497
  });
2500
2498
  yield* report("deleted");
2501
2499
  } else {
2502
- yield* scopedSession.note("Cleaning up replaced resource...");
2500
+ if (!retainOldGeneration) yield* scopedSession.note("Cleaning up replaced resource...");
2503
2501
  if (node.old.status === "replacing" || node.old.status === "replaced") yield* commit({
2504
2502
  status: "replaced",
2505
2503
  fqn,
@@ -2528,7 +2526,7 @@ const collectGarbage = Effect.fnUntraced(function* (plan, session) {
2528
2526
  bindings: excludeDeletedBindings(node.bindings),
2529
2527
  removalPolicy: node.removalPolicy
2530
2528
  });
2531
- yield* scopedSession.note("Replaced resource cleanup complete.");
2529
+ yield* scopedSession.note(retainOldGeneration ? "Replaced resource retained." : "Replaced resource cleanup complete.");
2532
2530
  }
2533
2531
  }));
2534
2532
  });