alchemy 2.0.0-beta.50 → 2.0.0-beta.51
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.
- package/bin/exec.js +117 -113
- package/bin/exec.js.map +1 -1
- package/lib/AWS/Lambda/BucketEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/BucketEventSource.js +13 -2
- package/lib/AWS/Lambda/BucketEventSource.js.map +1 -1
- package/lib/AWS/S3/Bucket.d.ts.map +1 -1
- package/lib/AWS/S3/Bucket.js +49 -0
- package/lib/AWS/S3/Bucket.js.map +1 -1
- package/lib/AWS/S3/BucketNotifications.d.ts +10 -0
- package/lib/AWS/S3/BucketNotifications.d.ts.map +1 -1
- package/lib/AWS/S3/BucketNotifications.js.map +1 -1
- package/lib/Cli/commands/cloudflare.d.ts +1 -1
- package/lib/Cloudflare/AiGateway/AiGatewayBinding.d.ts +1 -1
- package/lib/Cloudflare/AiGateway/AiGatewayBinding.d.ts.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGatewayBinding.js +6 -2
- package/lib/Cloudflare/AiGateway/AiGatewayBinding.js.map +1 -1
- package/lib/Cloudflare/Providers.d.ts.map +1 -1
- package/lib/Cloudflare/Providers.js +3 -1
- package/lib/Cloudflare/Providers.js.map +1 -1
- package/lib/Cloudflare/Ruleset/Ruleset.d.ts +82 -0
- package/lib/Cloudflare/Ruleset/Ruleset.d.ts.map +1 -0
- package/lib/Cloudflare/Ruleset/Ruleset.js +126 -0
- package/lib/Cloudflare/Ruleset/Ruleset.js.map +1 -0
- package/lib/Cloudflare/Ruleset/index.d.ts +2 -0
- package/lib/Cloudflare/Ruleset/index.d.ts.map +1 -0
- package/lib/Cloudflare/Ruleset/index.js +2 -0
- package/lib/Cloudflare/Ruleset/index.js.map +1 -0
- package/lib/Cloudflare/SecretsStore/Secret.d.ts +1 -0
- package/lib/Cloudflare/SecretsStore/Secret.d.ts.map +1 -1
- package/lib/Cloudflare/SecretsStore/Secret.js +2 -0
- package/lib/Cloudflare/SecretsStore/Secret.js.map +1 -1
- package/lib/Cloudflare/StateStore/State.d.ts +1 -1
- package/lib/Cloudflare/StateStore/State.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/DurableObjectChatPersistence.d.ts +69 -0
- package/lib/Cloudflare/Workers/DurableObjectChatPersistence.d.ts.map +1 -0
- package/lib/Cloudflare/Workers/DurableObjectChatPersistence.js +104 -0
- package/lib/Cloudflare/Workers/DurableObjectChatPersistence.js.map +1 -0
- package/lib/Cloudflare/Workers/Worker.d.ts +3 -2
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js +9 -0
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts +2 -1
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.js.map +1 -1
- package/lib/Cloudflare/Workers/index.d.ts +1 -0
- package/lib/Cloudflare/Workers/index.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/index.js +1 -0
- package/lib/Cloudflare/Workers/index.js.map +1 -1
- package/lib/Cloudflare/Zaraz/ZarazConfig.d.ts.map +1 -1
- package/lib/Cloudflare/index.d.ts +1 -0
- package/lib/Cloudflare/index.d.ts.map +1 -1
- package/lib/Cloudflare/index.js +1 -0
- package/lib/Cloudflare/index.js.map +1 -1
- package/lib/Deploy.d.ts +3 -2
- package/lib/Deploy.d.ts.map +1 -1
- package/lib/Deploy.js.map +1 -1
- package/lib/Destroy.d.ts +3 -2
- package/lib/Destroy.d.ts.map +1 -1
- package/lib/Destroy.js.map +1 -1
- package/lib/Drizzle/Schema.d.ts.map +1 -1
- package/lib/Drizzle/Schema.js +6 -3
- package/lib/Drizzle/Schema.js.map +1 -1
- package/lib/Output.d.ts.map +1 -1
- package/lib/Output.js +11 -10
- package/lib/Output.js.map +1 -1
- package/lib/Plan.d.ts.map +1 -1
- package/lib/Plan.js +5 -1
- package/lib/Plan.js.map +1 -1
- package/lib/Planetscale/MySQL/MySQLDatabase.d.ts +0 -2
- package/lib/Planetscale/MySQL/MySQLDatabase.d.ts.map +1 -1
- package/lib/Planetscale/MySQL/MySQLDatabase.js +1 -3
- package/lib/Planetscale/MySQL/MySQLDatabase.js.map +1 -1
- package/lib/Planetscale/Postgres/PostgresDatabase.d.ts +0 -2
- package/lib/Planetscale/Postgres/PostgresDatabase.d.ts.map +1 -1
- package/lib/Planetscale/Postgres/PostgresDatabase.js +1 -3
- package/lib/Planetscale/Postgres/PostgresDatabase.js.map +1 -1
- package/lib/Platform.d.ts +4 -4
- package/lib/Platform.d.ts.map +1 -1
- package/lib/Platform.js.map +1 -1
- package/lib/Resource.d.ts +6 -0
- package/lib/Resource.d.ts.map +1 -1
- package/lib/Resource.js +2 -0
- package/lib/Resource.js.map +1 -1
- package/lib/Stack.d.ts +5 -4
- package/lib/Stack.d.ts.map +1 -1
- package/lib/Stack.js.map +1 -1
- package/lib/Test/Core.d.ts +2 -2
- package/lib/Test/Core.d.ts.map +1 -1
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/AWS/Lambda/BucketEventSource.ts +16 -1
- package/src/AWS/S3/Bucket.ts +78 -0
- package/src/AWS/S3/BucketNotifications.ts +10 -0
- package/src/Cloudflare/AiGateway/AiGatewayBinding.ts +8 -3
- package/src/Cloudflare/Providers.ts +3 -0
- package/src/Cloudflare/Ruleset/Ruleset.ts +223 -0
- package/src/Cloudflare/Ruleset/index.ts +1 -0
- package/src/Cloudflare/SecretsStore/Secret.ts +4 -0
- package/src/Cloudflare/Workers/DurableObjectChatPersistence.ts +131 -0
- package/src/Cloudflare/Workers/Worker.ts +6 -1
- package/src/Cloudflare/Workers/WorkerAsyncBindings.ts +8 -0
- package/src/Cloudflare/Workers/WorkerBinding.ts +2 -0
- package/src/Cloudflare/Workers/index.ts +1 -0
- package/src/Cloudflare/index.ts +1 -0
- package/src/Deploy.ts +2 -1
- package/src/Destroy.ts +2 -1
- package/src/Drizzle/Schema.ts +11 -3
- package/src/Output.ts +12 -10
- package/src/Plan.ts +5 -1
- package/src/Planetscale/MySQL/MySQLDatabase.ts +1 -6
- package/src/Planetscale/Postgres/PostgresDatabase.ts +1 -5
- package/src/Platform.ts +12 -4
- package/src/Resource.ts +10 -0
- package/src/Stack.ts +11 -10
package/bin/exec.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
*
|
|
@@ -865,108 +968,6 @@ const make$1 = Effect.fnUntraced(function* (spawnerUrl) {
|
|
|
865
968
|
});
|
|
866
969
|
const fromEnv = () => Layer.effect(RpcProviderProxy, Config.string(SPAWNER_URL_ENV_KEY).pipe(Effect.flatMap(make$1)));
|
|
867
970
|
|
|
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
971
|
//#endregion
|
|
971
972
|
//#region lib/Diff.js
|
|
972
973
|
const isResolved = (value) => !_hasUnresolved(value);
|
|
@@ -1372,7 +1373,9 @@ const make = (stack, options = {}) => Effect.gen(function* () {
|
|
|
1372
1373
|
output: void 0
|
|
1373
1374
|
}).pipe(providePlanScope(fqn, adoptInstanceId));
|
|
1374
1375
|
if (readResult !== void 0) {
|
|
1375
|
-
|
|
1376
|
+
const isUnowned = Unowned.is(readResult);
|
|
1377
|
+
const adoptThis = resource.Adopt ?? (yield* shouldAdopt);
|
|
1378
|
+
if (isUnowned && !adoptThis) return yield* new OwnedBySomeoneElse({
|
|
1376
1379
|
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
1380
|
resourceType: resource.Type,
|
|
1378
1381
|
logicalId: id
|
|
@@ -1667,6 +1670,7 @@ const make = (stack, options = {}) => Effect.gen(function* () {
|
|
|
1667
1670
|
Binding: void 0,
|
|
1668
1671
|
Provider: Provider(resourceType),
|
|
1669
1672
|
RemovalPolicy: oldState.removalPolicy,
|
|
1673
|
+
Adopt: void 0,
|
|
1670
1674
|
RuntimeContext: void 0,
|
|
1671
1675
|
Providers: void 0
|
|
1672
1676
|
},
|