effect-pulumi 0.1.0 → 0.1.2
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/README.md +48 -180
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -26
- package/dist/index.d.ts +26 -26
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/pierskarsenbarg/effect-pulumi/actions/workflows/ci.yml)
|
|
4
4
|
|
|
5
|
-
Gives Pulumi programs Effect's composability
|
|
6
|
-
dependent resources, and structured result inspection
|
|
5
|
+
Gives Pulumi programs Effect's composability - typed errors, sequenced
|
|
6
|
+
dependent resources, and structured result inspection - without hand-wrapping
|
|
7
7
|
every resource constructor.
|
|
8
8
|
|
|
9
9
|
## Why
|
|
@@ -12,6 +12,7 @@ Mixing Effect and Pulumi by hand means wrapping every constructor and every
|
|
|
12
12
|
data-source call yourself:
|
|
13
13
|
|
|
14
14
|
```ts
|
|
15
|
+
// InfraError here is a tagged error you have to define yourself
|
|
15
16
|
const bucket = yield* Effect.try({
|
|
16
17
|
try: () => new aws.s3.Bucket("assets", { forceDestroy: true }),
|
|
17
18
|
catch: (cause) => new InfraError({ cause }),
|
|
@@ -39,10 +40,9 @@ npm install effect-pulumi
|
|
|
39
40
|
```
|
|
40
41
|
|
|
41
42
|
Requires Node.js ≥ 22 (the floor `@pulumi/pulumi` itself sets). The peer
|
|
42
|
-
ranges are `@pulumi/pulumi ^3.0.0` and `effect ^3.0.0
|
|
43
|
-
against `@pulumi/pulumi` 3.255 and `effect` 3.22.
|
|
43
|
+
ranges are `@pulumi/pulumi ^3.0.0` and `effect ^3.0.0`.
|
|
44
44
|
|
|
45
|
-
`@pulumi/pulumi` and `effect` are peer dependencies
|
|
45
|
+
`@pulumi/pulumi` and `effect` are peer dependencies - this library extends
|
|
46
46
|
your Pulumi and Effect runtimes, so it must use the same copies you do rather
|
|
47
47
|
than bundle its own. npm 7+ installs peers automatically; on pnpm or Yarn you
|
|
48
48
|
may need them explicitly:
|
|
@@ -52,12 +52,7 @@ npm install @pulumi/pulumi effect
|
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
Ships as dual ESM + CommonJS, so it works from a conventional CJS Pulumi
|
|
55
|
-
program as well as an ESM one
|
|
56
|
-
|
|
57
|
-
```ts
|
|
58
|
-
import { effectify } from "effect-pulumi"; // ESM
|
|
59
|
-
const { effectify } = require("effect-pulumi"); // CJS
|
|
60
|
-
```
|
|
55
|
+
program as well as an ESM one - both are shown below.
|
|
61
56
|
|
|
62
57
|
## Quick start
|
|
63
58
|
|
|
@@ -70,7 +65,7 @@ const eaws = effectify(aws); // wrap the provider package once
|
|
|
70
65
|
|
|
71
66
|
const program = Effect.gen(function* () {
|
|
72
67
|
const bucket = yield* eaws.s3.Bucket("assets", { forceDestroy: true });
|
|
73
|
-
// ^ Effect<aws.s3.Bucket, PulumiError>
|
|
68
|
+
// ^ Effect<aws.s3.Bucket, PulumiError> - no Effect.sync / Effect.try
|
|
74
69
|
|
|
75
70
|
const object = yield* eaws.s3.BucketObject("readme", {
|
|
76
71
|
bucket: fromOutput(bucket.id), // an Effect in an args slot, auto-resolved
|
|
@@ -86,101 +81,34 @@ const program = Effect.gen(function* () {
|
|
|
86
81
|
export const { id, key } = await Effect.runPromise(program);
|
|
87
82
|
```
|
|
88
83
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
For examples you can actually deploy, see [`examples/`](examples/) — those use
|
|
99
|
-
`@pulumi/random`, whose resources take no inputs from one another, so they
|
|
100
|
-
don't show `fromOutput` or an Effect in an args slot. For that, see
|
|
101
|
-
[`test/random-password-file-program.ts`](test/random-password-file-program.ts):
|
|
102
|
-
a `RandomPassword`'s Output flows into a `local.File`'s args, and it's
|
|
103
|
-
deployed for real by `npm run test:live` — no cloud credentials needed, since
|
|
104
|
-
`@pulumi/local` only touches the local filesystem.
|
|
105
|
-
|
|
106
|
-
## What `effectify` does
|
|
107
|
-
|
|
108
|
-
`effectify(mod)` returns a lazy, memoized proxy over a provider package:
|
|
109
|
-
|
|
110
|
-
| Export kind | Result |
|
|
111
|
-
| --- | --- |
|
|
112
|
-
| `CustomResource` subclass | `(name, args, opts?) => Effect<R, PulumiError>`, and any **top-level** args field may additionally be an `Effect` (several resolve concurrently) |
|
|
113
|
-
| `ComponentResource` subclass | `(name, args, opts?) => Effect<R, PulumiError>`, args passed through verbatim — never auto-lifted |
|
|
114
|
-
| Namespace object (`aws.s3`) | Recursively proxied, lazily |
|
|
115
|
-
| Invoke function (`aws.s3.getBucket`) | Returns `Effect<R, PulumiError>` instead of `Promise<R>` |
|
|
116
|
-
| `*Output` invoke variant (`getBucketOutput`) | Passed through untouched (returns an `Output`, as upstream) |
|
|
117
|
-
| Enums, plain values, sync functions | Passed through untouched |
|
|
118
|
-
|
|
119
|
-
Semantics worth knowing:
|
|
120
|
-
|
|
121
|
-
- **Outputs still work exactly as in vanilla Pulumi.** `effectify` only
|
|
122
|
-
*additionally* accepts `Effect`s; passing a bare `Output<T>` or `Input<T>`
|
|
123
|
-
needs no unwrapping or rewrapping.
|
|
124
|
-
- **Statics survive the wrapping.** `eaws.s3.Bucket.get(name, id)` (adopt an
|
|
125
|
-
existing resource), `isInstance`, and any other codegen'd static forward to
|
|
126
|
-
the original class — `instanceof` works too — so the wrapped package can be
|
|
127
|
-
the only import a program needs.
|
|
128
|
-
- **Component args are never lifted.** Component args aren't guaranteed to be
|
|
129
|
-
`Input<T>`-shaped the way codegen'd `CustomResource` args are — a component
|
|
130
|
-
may do synchronous work on a bare primitive in its constructor — so passing
|
|
131
|
-
an `Effect` where a component expects a primitive is a type error. See
|
|
132
|
-
[Component resources](#component-resources) for the patterns this implies.
|
|
133
|
-
- **Invokes start when you call them.** Whether a function is async is only
|
|
134
|
-
knowable by calling it, so `eaws.getAmi(args)` fires the invoke immediately
|
|
135
|
-
and hands back an Effect that resolves the already-in-flight call — the
|
|
136
|
-
failure still lands in the typed error channel, but `Effect.retry` re-awaits
|
|
137
|
-
the same call rather than re-invoking. To re-invoke per attempt, defer the
|
|
138
|
-
call site: `Effect.suspend(() => eaws.getAmi(args))`.
|
|
139
|
-
|
|
140
|
-
Resource registration stays synchronous under the hood; `Effect.try` runs its
|
|
141
|
-
thunk immediately. This removes wrapper boilerplate, not Pulumi's execution
|
|
142
|
-
model.
|
|
143
|
-
|
|
144
|
-
## Component resources
|
|
145
|
-
|
|
146
|
-
Component resources are fully supported as *consumers*: `effectify` detects
|
|
147
|
-
any class extending `pulumi.ComponentResource` — your own, or those in a
|
|
148
|
-
component-based package like `@pulumi/awsx` — and wraps its constructor into
|
|
149
|
-
an Effect factory, exactly like a custom resource. Construction errors land
|
|
150
|
-
in the typed error channel, and the component sequences with `yield*` like
|
|
151
|
-
everything else.
|
|
152
|
-
|
|
153
|
-
What differs is the args object. Custom resource args can carry `Effect`
|
|
154
|
-
fields because codegen guarantees they are all `Input<T>`-shaped, so
|
|
155
|
-
substituting a resolved value is always legal. Component args are
|
|
156
|
-
hand-authored: a component may take a bare `replicas: number` and do
|
|
157
|
-
synchronous arithmetic on it inside its constructor, and an `Effect` silently
|
|
158
|
-
swapped in there would break it. So for components, `effectify` refuses at
|
|
159
|
-
the type level instead of guessing — resolve your Effects first, then
|
|
160
|
-
construct with plain values:
|
|
84
|
+
Pulumi's TypeScript programs default to CommonJS (no `"type": "module"` in
|
|
85
|
+
`package.json`), where top-level `await` isn't available. `fromOutput` and
|
|
86
|
+
`fromOutputs` resolve an Output's real value, which is genuinely
|
|
87
|
+
asynchronous, so `Effect.runSync` isn't an option here either - it throws on
|
|
88
|
+
any effect that suspends on real async work. Export the Promise itself
|
|
89
|
+
instead; Pulumi's engine awaits an exported Promise the same way it would an
|
|
90
|
+
awaited value. The `program` itself is unchanged - only the first and last
|
|
91
|
+
lines differ:
|
|
161
92
|
|
|
162
93
|
```ts
|
|
163
|
-
const
|
|
94
|
+
const aws = require("@pulumi/aws");
|
|
95
|
+
const { Effect } = require("effect");
|
|
96
|
+
const { effectify, fromOutput, fromOutputs } = require("effect-pulumi");
|
|
164
97
|
|
|
165
|
-
|
|
166
|
-
// ✗ type error — component args are never auto-lifted:
|
|
167
|
-
// eawsx.ecs.Cluster("app", { vpcId: fromOutput(vpc.id) })
|
|
98
|
+
// ... same program ...
|
|
168
99
|
|
|
169
|
-
|
|
170
|
-
// Input<T>-typed component args accept those as in vanilla Pulumi):
|
|
171
|
-
const vpcId = yield* fromOutput(vpc.id);
|
|
172
|
-
const cluster = yield* eawsx.ecs.Cluster("app", { vpcId });
|
|
173
|
-
});
|
|
100
|
+
module.exports = Effect.runPromise(program);
|
|
174
101
|
```
|
|
175
102
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
`
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
103
|
+
`Effect.runSync` does work for programs that never resolve an Output's value
|
|
104
|
+
- e.g. [`examples/random-pet`](examples/random-pet), which exports raw
|
|
105
|
+
`Output`s from resource properties directly rather than reading through them
|
|
106
|
+
with `fromOutput`.
|
|
107
|
+
|
|
108
|
+
Alternatively, hand `program` to the [Automation API](#automation-api) as an
|
|
109
|
+
inline program and deploy it from the same process.
|
|
110
|
+
|
|
111
|
+
For projects you can deploy as-is, see [`examples/`](examples/).
|
|
184
112
|
|
|
185
113
|
## Automation API
|
|
186
114
|
|
|
@@ -191,93 +119,33 @@ re-selecting.
|
|
|
191
119
|
```ts
|
|
192
120
|
const exit = await Effect.runPromiseExit(
|
|
193
121
|
deploy({
|
|
194
|
-
stackName,
|
|
195
|
-
projectName,
|
|
196
|
-
|
|
122
|
+
stackName: "dev",
|
|
123
|
+
projectName: "my-infra",
|
|
124
|
+
// a PulumiFn - run the Effect, return its result as the stack outputs
|
|
125
|
+
program: async () => Effect.runPromise(program),
|
|
197
126
|
up: { onOutput: (out) => process.stdout.write(out) },
|
|
198
127
|
})
|
|
199
128
|
);
|
|
200
129
|
// Exit/Cause instead of a thrown, stringified error
|
|
201
130
|
```
|
|
202
131
|
|
|
203
|
-
|
|
204
|
-
|
|
132
|
+
Stacks are either inline programs (`projectName` + `program`, above) or an
|
|
133
|
+
existing project on disk (`workDir`), and every operation forwards the
|
|
134
|
+
matching Pulumi options type - `UpOptions`, `DestroyOptions`, and so on. Pass
|
|
205
135
|
`onOutput` to stream the CLI's progress; without it a multi-minute deploy
|
|
206
|
-
prints nothing until it finishes.
|
|
207
|
-
(`projectName` + `program`) or an existing project on disk (`workDir`).
|
|
208
|
-
|
|
209
|
-
Previewing is opt-in via `preview: true` (or a `PreviewOptions` object), and
|
|
210
|
-
its result comes back on `DeployResult.preview`. It is off by default because
|
|
211
|
-
a preview is a full engine run against the provider, so previewing and then
|
|
212
|
-
immediately upping does the work twice — and `up` surfaces the same failures.
|
|
213
|
-
|
|
214
|
-
Teardown is two steps. `destroyStack` removes the resources but leaves the
|
|
215
|
-
stack registered with the backend; `teardownStack` destroys and then deletes
|
|
216
|
-
it, which is what you want for per-run stacks. `RemoveOptions.force` deletes a
|
|
217
|
-
stack while leaving its resources alive and billing — it is reachable, but it
|
|
218
|
-
orphans them.
|
|
136
|
+
prints nothing until it finishes.
|
|
219
137
|
|
|
220
|
-
|
|
138
|
+
Preview is opt-in via `preview: true` and comes back on
|
|
139
|
+
`DeployResult.preview`. It is off by default because a preview is a full
|
|
140
|
+
engine run, so previewing and then immediately upping does the work twice -
|
|
141
|
+
and `up` surfaces the same failures anyway.
|
|
221
142
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
143
|
+
Teardown is two steps: `destroyStack` removes the resources but leaves the
|
|
144
|
+
stack registered, while `teardownStack` destroys and then deletes it - the
|
|
145
|
+
latter is what per-run stacks want. Avoid `RemoveOptions.force`, which drops
|
|
146
|
+
a stack while leaving its resources alive and billing with nothing tracking
|
|
147
|
+
them.
|
|
226
148
|
|
|
227
|
-
|
|
228
|
-
import { Effect } from "effect";
|
|
229
|
-
import { deploy } from "effect-pulumi";
|
|
230
|
-
|
|
231
|
-
const guarded = deploy({ stackName, projectName, program }).pipe(
|
|
232
|
-
// Transient engine failures during `up` are worth another attempt; a
|
|
233
|
-
// failure creating the stack or setting config is not.
|
|
234
|
-
Effect.retry({ times: 2, while: (error) => error.stage === "up" }),
|
|
235
|
-
Effect.catchTag("AutomationError", (error) =>
|
|
236
|
-
Effect.fail(new Error(`deploy failed at ${error.stage}: ${error.message}`))
|
|
237
|
-
)
|
|
238
|
-
);
|
|
239
|
-
```
|
|
149
|
+
## License
|
|
240
150
|
|
|
241
|
-
|
|
242
|
-
resource, or `Effect.exit` / `runPromiseExit` at the edge to inspect the full
|
|
243
|
-
`Cause`.
|
|
244
|
-
|
|
245
|
-
## API
|
|
246
|
-
|
|
247
|
-
| Export | What it does |
|
|
248
|
-
| --- | --- |
|
|
249
|
-
| `effectify(mod)` | Wrap a provider package (or any namespace) once; see the table above |
|
|
250
|
-
| `fromOutput(output)` | `Output<T>` → `Effect<T, PulumiError>`; resolves to the unknown sentinel during `preview` instead of throwing |
|
|
251
|
-
| `fromOutputs(record)` | Record of Outputs → `Effect` of the resolved record |
|
|
252
|
-
| `deploy(opts)` | Select/create stack → apply config → optional preview → `up`; returns `{ stack, result, preview? }` |
|
|
253
|
-
| `createOrSelectStack(opts)` | Inline (`projectName` + `program`) or local (`workDir`) stack |
|
|
254
|
-
| `setStackConfig(stack, config)` | Apply a whole config map in one `setAllConfig` round-trip |
|
|
255
|
-
| `previewStack(stack, opts?)` | `pulumi preview`, returning the `PreviewResult` |
|
|
256
|
-
| `upStack(stack, opts?)` | `pulumi up`, returning the `UpResult` |
|
|
257
|
-
| `refreshStack(stack, opts?)` | Re-sync state from the actual cloud resources |
|
|
258
|
-
| `stackOutputs(stack)` | Read current outputs without running an update |
|
|
259
|
-
| `destroyStack(stack, opts?)` | Destroy resources; the stack stays registered |
|
|
260
|
-
| `removeStack(stack, opts?)` | Delete the stack from the backend |
|
|
261
|
-
| `teardownStack(stack, opts?)` | Destroy then remove — skips the remove if the destroy failed |
|
|
262
|
-
| `PulumiError` | Construction / Output-resolution failure; carries `cause` |
|
|
263
|
-
| `AutomationError` | Lifecycle failure; carries `stage` and `cause` |
|
|
264
|
-
|
|
265
|
-
## Scripts
|
|
266
|
-
|
|
267
|
-
| Command | What it does |
|
|
268
|
-
| --- | --- |
|
|
269
|
-
| `npm run build` | Build dual ESM + CJS (`tsup`) with declarations to `dist/` |
|
|
270
|
-
| `npm run typecheck` | Type-check everything, including tests and examples |
|
|
271
|
-
| `npm run lint` | Lint with `oxlint` (`npm run lint:fix` applies safe fixes) |
|
|
272
|
-
| `npm run format` | Format with `oxfmt` (`npm run format:check` asserts instead) |
|
|
273
|
-
| `npm run check` | `typecheck` + `lint` + `format:check`, the pre-commit sweep |
|
|
274
|
-
| `npm test` | Unit + mocked-provider tests. No credentials needed |
|
|
275
|
-
| `npm run test:package` | Builds, packs a tarball and consumes it from ESM and CJS projects |
|
|
276
|
-
| `npm run test:live` | Deploys `test/s3-bucket-program.ts` against real AWS, then destroys it |
|
|
277
|
-
|
|
278
|
-
`npm test` never runs the live harness: it's excluded in `vitest.config.ts`
|
|
279
|
-
and additionally gated on `EFFECT_PULUMI_RUN_LIVE_TESTS=1`. The live harness
|
|
280
|
-
picks up credentials from the environment the normal way each provider expects
|
|
281
|
-
(e.g. `AWS_PROFILE` / `AWS_ACCESS_KEY_ID`), and uses
|
|
282
|
-
`Effect.acquireRelease` + `Effect.scoped` so the stack is destroyed even when
|
|
283
|
-
an assertion fails.
|
|
151
|
+
MIT - see [LICENSE](LICENSE).
|
package/dist/index.cjs
CHANGED
|
@@ -27,15 +27,15 @@ var pulumi2__namespace = /*#__PURE__*/_interopNamespace(pulumi2);
|
|
|
27
27
|
// src/errors.ts
|
|
28
28
|
var describeCause = (cause) => cause instanceof Error ? cause.message : String(cause);
|
|
29
29
|
var PulumiError = class extends effect.Data.TaggedError("PulumiError") {
|
|
30
|
-
/** Derived so anything reading `.message`
|
|
31
|
-
* output, non-Effect error handling
|
|
30
|
+
/** Derived so anything reading `.message` - plain logging, test failure
|
|
31
|
+
* output, non-Effect error handling - sees the underlying failure instead
|
|
32
32
|
* of an empty string. */
|
|
33
33
|
get message() {
|
|
34
34
|
return describeCause(this.cause);
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
37
|
var AutomationError = class extends effect.Data.TaggedError("AutomationError") {
|
|
38
|
-
/** `"<stage> failed: <cause>"`
|
|
38
|
+
/** `"<stage> failed: <cause>"` - the stage is included because the cause
|
|
39
39
|
* alone rarely says which operation produced it. */
|
|
40
40
|
get message() {
|
|
41
41
|
return `${this.stage} failed: ${describeCause(this.cause)}`;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/output-bridge.ts","../src/effectify.ts","../src/automation.ts"],"names":["Data","Effect","pulumi","pulumi2","LocalWorkspace"],"mappings":"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","file":"index.cjs","sourcesContent":["import { Data } from \"effect\";\n\nconst describeCause = (cause: unknown): string =>\n cause instanceof Error ? cause.message : String(cause);\n\n/**\n * Any synchronous failure constructing a resource (bad args, provider\n * validation, etc.), or a failure resolving an Output's promise.\n *\n * Tagged `\"PulumiError\"`, so it can be matched by tag rather than by\n * `instanceof`:\n *\n * @example\n * ```ts\n * program.pipe(\n * Effect.catchTag(\"PulumiError\", (e) => Effect.logError(e.message))\n * );\n * ```\n */\nexport class PulumiError extends Data.TaggedError(\"PulumiError\")<{\n /** The original thrown value or rejection reason, unwrapped and unmodified.\n * Not necessarily an `Error`. */\n readonly cause: unknown;\n}> {\n /** Derived so anything reading `.message` — plain logging, test failure\n * output, non-Effect error handling — sees the underlying failure instead\n * of an empty string. */\n get message(): string {\n return describeCause(this.cause);\n }\n}\n\n/**\n * Failure from an Automation API lifecycle call (up/preview/destroy/select).\n *\n * `stage` says which call failed, which matters most in the composite\n * operations: a failed `deploy` could have died selecting the stack, applying\n * config, or running the update, and the three want different responses.\n *\n * @example\n * ```ts\n * deploy(opts).pipe(\n * Effect.catchTag(\"AutomationError\", (e) =>\n * e.stage === \"createOrSelectStack\"\n * ? Effect.fail(new BackendUnreachable())\n * : Effect.logError(e.message)\n * )\n * );\n * ```\n */\nexport class AutomationError extends Data.TaggedError(\"AutomationError\")<{\n /** Which Automation API call failed. Named for the wrapper that raised it,\n * so `deploy`'s failures still report the underlying stage. */\n readonly stage:\n | \"createOrSelectStack\"\n | \"setConfig\"\n | \"up\"\n | \"preview\"\n | \"refresh\"\n | \"outputs\"\n | \"destroy\"\n | \"removeStack\";\n /** The rejection reason from the Automation API. For a failed update this is\n * usually a `CommandError` carrying the CLI's stdout and stderr. */\n readonly cause: unknown;\n}> {\n /** `\"<stage> failed: <cause>\"` — the stage is included because the cause\n * alone rarely says which operation produced it. */\n get message(): string {\n return `${this.stage} failed: ${describeCause(this.cause)}`;\n }\n}\n","import * as pulumi from \"@pulumi/pulumi\";\nimport { Effect } from \"effect\";\nimport { PulumiError } from \"./errors.js\";\n\n/** `Output.promise()` is how the Pulumi runtime itself gets a settled value out\n * of an Output, but it is not part of the public `Output<T>` surface. */\ninterface PromisableOutput<T> {\n promise(withUnknowns?: boolean): Promise<T>;\n}\n\n/**\n * Lift a single Output into an Effect.\n *\n * `withUnknowns: true` matters during `pulumi preview`, where a not-yet-created\n * resource's outputs have no value: it resolves to Pulumi's unknown sentinel\n * instead of throwing, so a program that reads outputs still previews cleanly.\n *\n * @param output - The Output to resolve.\n * @returns An Effect yielding the settled value, failing with\n * {@link PulumiError} if the underlying promise rejects.\n *\n * @example\n * ```ts\n * const bucket = yield* eaws.s3.Bucket(\"assets\", {});\n * const id = yield* fromOutput(bucket.id); // string\n * ```\n *\n * @remarks Reading an Output only makes sense inside a running Pulumi program.\n * During `preview` the value may be the unknown sentinel rather than real data,\n * so don't branch on it to decide what to create.\n */\nexport const fromOutput = <T>(\n output: pulumi.Output<T>\n): Effect.Effect<T, PulumiError> =>\n Effect.tryPromise({\n try: () => (output as unknown as PromisableOutput<T>).promise(true),\n catch: (cause) => new PulumiError({ cause }),\n });\n\n/**\n * Lift a record of Outputs into a single Effect of the resolved record — use\n * this right after constructing a resource to grab several fields at once.\n *\n * Resolves them together via `pulumi.all`, so it costs one await rather than\n * one per field.\n *\n * @param outputs - A record whose values are all Outputs. Interfaces work as\n * well as object literals; the constraint is self-referential rather than\n * `Record<string, Output<any>>` precisely so interface-typed bags are accepted.\n * @returns An Effect yielding the same record with each value unwrapped.\n *\n * @example\n * ```ts\n * const bucket = yield* eaws.s3.Bucket(\"assets\", {});\n * const { id, arn } = yield* fromOutputs({ id: bucket.id, arn: bucket.arn });\n * ```\n */\nexport const fromOutputs = <T extends { [K in keyof T]: pulumi.Output<any> }>(\n outputs: T\n): Effect.Effect<{ [K in keyof T]: pulumi.Unwrap<T[K]> }, PulumiError> =>\n fromOutput(pulumi.all(outputs) as pulumi.Output<any>);\n","/**\n * effectify — auto-wrap a Pulumi provider package (e.g. @pulumi/aws,\n * @pulumi/cloudflare) so every resource constructor becomes an\n * Effect-returning factory, without the caller ever writing `Effect.sync`.\n *\n * Usage:\n *\n * import * as aws from \"@pulumi/aws\";\n * const eaws = effectify(aws);\n *\n * const program = Effect.gen(function* () {\n * const bucket = yield* eaws.s3.Bucket(\"my-bucket\", { forceDestroy: true });\n * // ^ Effect<aws.s3.Bucket, PulumiError> — no manual wrapping\n * });\n *\n * How it works:\n * - Every Pulumi resource class extends `pulumi.Resource` under the hood\n * (via CustomResource / ComponentResource). That's the runtime marker\n * used to tell \"this export is a resource constructor\" apart from \"this\n * export is a namespace object\" (e.g. `aws.s3`) or \"this export is an\n * invoke function\" (e.g. `aws.s3.getBucket`).\n * - Namespace objects get recursively proxied (lazily, memoized).\n * - CustomResource constructors get wrapped so any field in their args\n * object may *additionally* be an Effect — resolved (concurrently, they\n * are independent by construction) before construction. This is safe\n * because codegen guarantees CustomResource args are always\n * Record<string, Input<T>>.\n * - Wrapped constructors keep their static members: `Bucket.get(...)`,\n * `Bucket.isInstance(...)` and friends forward to the original class, so\n * the wrapped package can be the only import a program needs.\n * - ComponentResource constructors get wrapped with no arg-lifting — args\n * pass through exactly as declared, since component args aren't\n * guaranteed to be Input<T>-shaped (hand-authored, may do synchronous\n * work on a bare primitive inside the constructor).\n * - Invoke functions (`aws.s3.getBucket`) return an Effect instead of a\n * Promise. There is no runtime marker for \"this function is async\", so\n * the wrapper calls the function and inspects the result: a thenable\n * becomes an Effect, anything else is returned as-is. That means the\n * invoke *starts* at the call site (see the caveat on `wrapInvokeLike`);\n * `*Output` invoke variants return an Output, which is not thenable, so\n * they pass through untouched — matching the type-level mapping, which\n * only rewrites Promise-returning signatures.\n * - Everything else (enums, plain values, non-resource classes) passes\n * through untouched.\n *\n * Resource registration remains synchronous under the hood — Effect.try\n * runs its thunk immediately. This only removes hand-written wrapper\n * boilerplate, not Pulumi's execution model.\n */\n\nimport * as pulumi from \"@pulumi/pulumi\";\nimport { Effect } from \"effect\";\nimport { PulumiError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Runtime type guards\n// ---------------------------------------------------------------------------\n\nconst isResourceConstructor = (\n value: unknown\n): value is new (...args: any[]) => pulumi.Resource =>\n typeof value === \"function\" &&\n (value === (pulumi.Resource as unknown) ||\n value.prototype instanceof pulumi.Resource);\n\nconst isComponentResourceConstructor = (\n Ctor: Function\n): Ctor is new (...args: any[]) => pulumi.ComponentResource =>\n Ctor === (pulumi.ComponentResource as unknown) ||\n Ctor.prototype instanceof pulumi.ComponentResource;\n\n/** An object whose string-keyed properties we only ever *read*. Distinct from\n * `Record<string, unknown>`, which additionally claims the properties are\n * writable and that the object declares an index signature — neither is true\n * of a codegen'd `BucketArgs`, and neither is something this module relies on. */\ntype UnknownProps = { readonly [key: string]: unknown };\n\n/** Is this a namespace to recurse into? The narrowed type is only ever handed\n * to `effectifyInner`, which takes `object` — so claim exactly that and no\n * more. */\nconst isNamespace = (value: unknown): value is object =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** Is this an args object whose entries we can scan for Effects? Same runtime\n * check as `isNamespace`, but a different question, so it gets the narrowing\n * that question needs: `object` would make `Object.entries` infer `any` values\n * and silently drop the `isEffect` filter's type safety. */\nconst isArgsObject = (value: unknown): value is UnknownProps =>\n isNamespace(value);\n\n/** Note: `pulumi.Output` is deliberately not thenable, so `*Output` invoke\n * variants fail this check and pass through unwrapped — keeping the runtime\n * behaviour aligned with the type mapping, which only rewrites\n * Promise-returning signatures. */\nconst isPromiseLike = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\";\n\n// ---------------------------------------------------------------------------\n// Type-level mapping\n// ---------------------------------------------------------------------------\n\n/** Allow any field of a CustomResource args object to *additionally* be an\n * Effect. Homomorphic, so optional fields stay optional and plain\n * `Input<T>`/`Output<T>` values keep working untouched. */\ntype LiftedArgs<A> = A extends object\n ? { [K in keyof A]: A[K] | Effect.Effect<A[K], PulumiError> }\n : A;\n\n/** Apply `LiftedArgs` to the second constructor parameter (the args object),\n * leaving `name` and `opts` alone. Mapping over the parameter tuple\n * homomorphically preserves labels and optionality, so constructors whose\n * args are optional stay callable as `Bucket(\"name\")`. */\ntype LiftArgsParam<P extends readonly unknown[]> = {\n [K in keyof P]: K extends \"1\" ? LiftedArgs<P[K]> : P[K];\n};\n\n/** The class's static side, minus `prototype`: `keyof` on a constructor type\n * yields exactly the statics (own and inherited, e.g. codegen'd `get` and\n * `isInstance`), which the runtime wrapper forwards to the original class. */\ntype StaticMembers<T> = Omit<T, \"prototype\">;\n\n/**\n * The type of {@link effectify}'s result: `T` with every resource constructor\n * and every `Promise`-returning invoke rewritten, and everything else left\n * alone.\n *\n * The cases, in the order they are tried:\n *\n * | Input | Becomes |\n * | --------------------------- | ---------------------------------------------- |\n * | `ComponentResource` class | factory returning `Effect`, args **not** lifted |\n * | `CustomResource` class | factory returning `Effect`, args lifted |\n * | other class | unchanged |\n * | `(...) => Promise<R>` | `(...) => Effect<R, PulumiError>` |\n * | other function | unchanged (includes `*Output` invokes) |\n * | object | mapped recursively |\n * | anything else | unchanged |\n *\n * Statics survive on the wrapped constructors, so `Bucket.get` and\n * `Bucket.isInstance` remain callable.\n */\nexport type Effectify<T> = T extends abstract new (\n ...params: infer P\n) => infer R\n ? R extends pulumi.ComponentResource\n ? ((...params: P) => Effect.Effect<R, PulumiError>) & StaticMembers<T>\n : R extends pulumi.CustomResource\n ? ((...params: LiftArgsParam<P>) => Effect.Effect<R, PulumiError>) &\n StaticMembers<T>\n : T\n : T extends (...args: infer A) => Promise<infer R>\n ? (...args: A) => Effect.Effect<R, PulumiError>\n : T extends (...args: any[]) => any\n ? T\n : T extends object\n ? { [K in keyof T]: Effectify<T[K]> }\n : T;\n\n// ---------------------------------------------------------------------------\n// Runtime implementation\n// ---------------------------------------------------------------------------\n\nconst proxyCache = new WeakMap<object, unknown>();\n\nconst isEffect = (value: unknown): value is Effect.Effect<unknown, unknown> =>\n Effect.isEffect(value);\n\nfunction resolveLiftedArgs(args: unknown): Effect.Effect<unknown, PulumiError> {\n if (!isArgsObject(args)) {\n return Effect.succeed(args);\n }\n\n const effectEntries = Object.entries(args).filter(([, v]) => isEffect(v));\n\n if (effectEntries.length === 0) {\n return Effect.succeed(args);\n }\n\n // The arg Effects are independent of one another, so resolve them\n // concurrently — it matters when several of them await slow Outputs.\n return Effect.map(\n Effect.all(\n effectEntries.map(([key, effectValue]) =>\n Effect.map(\n effectValue as Effect.Effect<unknown, PulumiError>,\n (resolved) => [key, resolved] as const\n )\n ),\n { concurrency: \"unbounded\" }\n ),\n (resolved) => ({ ...args, ...Object.fromEntries(resolved) })\n );\n}\n\nfunction wrapCustomResourceCtor(\n Ctor: new (...args: any[]) => pulumi.CustomResource\n) {\n return (name: string, args?: unknown, opts?: unknown) =>\n Effect.gen(function* () {\n const resolvedArgs = yield* resolveLiftedArgs(args);\n return yield* Effect.try({\n try: () => new Ctor(name, resolvedArgs, opts),\n catch: (cause) => new PulumiError({ cause }),\n });\n });\n}\n\nfunction wrapComponentResourceCtor(\n Ctor: new (...args: any[]) => pulumi.ComponentResource\n) {\n return (name: string, args?: unknown, opts?: unknown) =>\n Effect.try({\n try: () => new Ctor(name, args, opts),\n catch: (cause) => new PulumiError({ cause }),\n });\n}\n\n/** Forward static members (codegen'd `get`, `isInstance`, …) from the class\n * onto the factory. The factory's own and inherited properties (`name`,\n * `length`, `call`, …) win; anything else falls through to the class, so new\n * statics keep working without being enumerated here. A bonus of forwarding\n * `prototype` is that `x instanceof wrapped` still works. */\nconst withStatics = <F extends object>(factory: F, Ctor: Function): F =>\n new Proxy(factory, {\n get: (target, prop, receiver) =>\n Reflect.has(target, prop)\n ? Reflect.get(target, prop, receiver)\n : Reflect.get(Ctor, prop),\n has: (target, prop) => Reflect.has(target, prop) || Reflect.has(Ctor, prop),\n });\n\nfunction wrapResourceCtor(Ctor: new (...args: any[]) => pulumi.Resource) {\n const factory = isComponentResourceConstructor(Ctor)\n ? wrapComponentResourceCtor(Ctor)\n : wrapCustomResourceCtor(\n Ctor as new (...args: any[]) => pulumi.CustomResource\n );\n return withStatics(factory, Ctor);\n}\n\n/** Turn a Promise-returning invoke into an Effect-returning one, leaving\n * synchronous functions' behaviour untouched.\n *\n * A Proxy over the original function (rather than a new function) so `name`,\n * `length`, own properties and prototype all survive; only the call itself is\n * intercepted.\n *\n * Caveat, stated openly: whether a function is async is only knowable by\n * calling it, so the invoke *starts* when the factory is called — the Effect\n * resolves an already-in-flight Promise rather than deferring the call. Two\n * consequences:\n * - `Effect.retry` re-awaits the same call instead of re-invoking. To\n * re-invoke per attempt, wrap the call site: `Effect.suspend(() =>\n * eaws.getAmi(args))`.\n * - A discarded Effect must not surface as an unhandled rejection, so the\n * rejection is pre-observed on a side branch before the Effect awaits it.\n */\nfunction wrapInvokeLike(fn: Function): Function {\n return new Proxy(fn, {\n apply(target, thisArg, args) {\n const result = Reflect.apply(target, thisArg, args);\n if (!isPromiseLike(result)) {\n return result;\n }\n result.then(undefined, () => {});\n return Effect.tryPromise({\n try: () => result as Promise<unknown>,\n catch: (cause) => new PulumiError({ cause }),\n });\n },\n });\n}\n\n/** Wrapped constructors are cached so repeated reads of the same property\n * hand back the same function — identity checks like\n * `eaws.s3.Bucket === eaws.s3.Bucket` hold, and the `get` and\n * `getOwnPropertyDescriptor` traps agree on a property's value. */\nconst wrapperCache = new WeakMap<object, unknown>();\n\nfunction effectifyValue(value: unknown): unknown {\n if (isResourceConstructor(value)) {\n const cached = wrapperCache.get(value);\n if (cached) return cached;\n const wrapped = wrapResourceCtor(value);\n wrapperCache.set(value, wrapped);\n return wrapped;\n }\n\n if (typeof value === \"function\") {\n const cached = wrapperCache.get(value);\n if (cached) return cached;\n const wrapped = wrapInvokeLike(value);\n wrapperCache.set(value, wrapped);\n return wrapped;\n }\n\n if (isNamespace(value)) {\n return effectifyInner(value);\n }\n\n return value; // plain value, enum member, type-only export\n}\n\nfunction effectifyInner<T extends object>(mod: T): Effectify<T> {\n const cached = proxyCache.get(mod);\n if (cached) return cached as Effectify<T>;\n\n // The proxy target is a fresh plain object rather than `mod` itself: ES\n // module namespace objects (and @pulumi/aws's lazily-defined namespace\n // getters) expose non-configurable own properties, and a `get` trap that\n // returns a wrapper instead of the real value would violate the proxy\n // invariants for those. Forwarding to `mod` from a closure sidesteps that\n // entirely while keeping the lazy-loading behaviour intact.\n const proxy = new Proxy(Object.create(null) as T, {\n get(_target, prop) {\n return effectifyValue(Reflect.get(mod, prop));\n },\n has(_target, prop) {\n return Reflect.has(mod, prop);\n },\n ownKeys() {\n return Reflect.ownKeys(mod);\n },\n getOwnPropertyDescriptor(_target, prop) {\n const descriptor = Reflect.getOwnPropertyDescriptor(mod, prop);\n if (!descriptor) return undefined;\n // Must be reported as configurable — the target does not actually have\n // the property, so claiming otherwise breaks the proxy invariants.\n return {\n value: effectifyValue(Reflect.get(mod, prop)),\n enumerable: descriptor.enumerable,\n configurable: true,\n writable: true,\n };\n },\n set() {\n return false; // the wrapper is read-only\n },\n }) as Effectify<T>;\n\n proxyCache.set(mod, proxy);\n return proxy;\n}\n\n/**\n * Wrap a provider package (or any namespace) once, turning every resource\n * constructor into an `Effect`-returning factory and every `Promise`-returning\n * invoke into an `Effect`-returning function.\n *\n * Call this once per package at module scope and export the result — the\n * wrapper is cached, so repeated calls and repeated property reads hand back\n * the same objects, but there is no reason to re-wrap.\n *\n * @param mod - The provider package, or any namespace within one. Not mutated;\n * the result is a read-only proxy that forwards to it.\n * @returns A same-shaped view of `mod`, typed by {@link Effectify}.\n *\n * @example Constructing a resource\n * ```ts\n * import * as aws from \"@pulumi/aws\";\n * const eaws = effectify(aws);\n *\n * const program = Effect.gen(function* () {\n * const bucket = yield* eaws.s3.Bucket(\"assets\", { forceDestroy: true });\n * return bucket.id;\n * });\n * ```\n *\n * @example Passing an Effect as an argument\n * A `CustomResource`'s args may hold Effects, which are resolved concurrently\n * before the resource is constructed:\n * ```ts\n * yield* eaws.s3.BucketObject(\"readme\", {\n * bucket: bucketIdEffect,\n * content: \"hello\",\n * });\n * ```\n *\n * @throws Nothing. Failures surface in the returned Effect's error channel as\n * {@link PulumiError} — including synchronous throws from the constructor.\n *\n * @see {@link Effectify} for the type-level mapping.\n */\nexport function effectify<T extends object>(mod: T): Effectify<T> {\n return effectifyInner(mod);\n}\n","import type {\n ConfigMap,\n DestroyOptions,\n DestroyResult,\n LocalWorkspaceOptions,\n OutputMap,\n PreviewOptions,\n PreviewResult,\n PulumiFn,\n RefreshOptions,\n RefreshResult,\n RemoveOptions,\n Stack,\n UpOptions,\n UpResult,\n} from \"@pulumi/pulumi/automation/index.js\";\nimport { LocalWorkspace } from \"@pulumi/pulumi/automation/index.js\";\nimport { Effect } from \"effect\";\nimport { AutomationError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Primitives\n//\n// Each wraps one Automation API call, tagging failures with the stage they\n// came from. They are exported individually so callers can assemble their own\n// lifecycle — `deploy` below is only the common path.\n//\n// Every operation takes the matching Pulumi options type. That includes\n// `onOutput`: pass it to stream the CLI's progress as it happens. Without it\n// nothing is printed during what may be a multi-minute operation (the text is\n// still captured on the result's `stdout`, and on the error when one is\n// thrown, but only once the operation has finished).\n// ---------------------------------------------------------------------------\n\n/** Arguments for an inline program — the Pulumi program is a function in this\n * process, with no `Pulumi.yaml` on disk. */\nexport interface InlineStackOptions {\n /** Stack to select, created if absent. */\n readonly stackName: string;\n /** Project name to register the stack under. Chosen freely here, since\n * there is no `Pulumi.yaml` to take it from — but it is part of the stack's\n * identity in the backend, so changing it later points at a different\n * stack. */\n readonly projectName: string;\n /** The program itself. Runs in this process, so it needs no separate Node\n * runtime and can close over values from the caller. */\n readonly program: PulumiFn;\n readonly workspaceOptions?: LocalWorkspaceOptions;\n}\n\n/** Arguments for a local program — an existing Pulumi project on disk. */\nexport interface LocalStackOptions {\n /** Stack to select, created if absent. */\n readonly stackName: string;\n /** Directory holding the project's `Pulumi.yaml`. Its `name:` supplies the\n * project name, which is why there is no `projectName` here. */\n readonly workDir: string;\n readonly workspaceOptions?: LocalWorkspaceOptions;\n}\n\n/** Either flavour of stack. Discriminated at runtime by the presence of\n * `workDir`, so the two are not interchangeable: an inline program needs\n * `projectName`, a local one takes it from `Pulumi.yaml`. */\nexport type StackOptions = InlineStackOptions | LocalStackOptions;\n\nconst isLocal = (opts: StackOptions): opts is LocalStackOptions =>\n \"workDir\" in opts;\n\n/** Select the stack, creating it if it does not exist, and return the handle\n * every other operation here takes.\n *\n * Creating the workspace is itself work — it may write files and shell out to\n * the CLI — so hold on to the returned `Stack` rather than re-selecting before\n * each operation. */\nexport const createOrSelectStack = (\n opts: StackOptions\n): Effect.Effect<Stack, AutomationError> =>\n Effect.tryPromise({\n try: () =>\n isLocal(opts)\n ? LocalWorkspace.createOrSelectStack(\n { stackName: opts.stackName, workDir: opts.workDir },\n opts.workspaceOptions\n )\n : LocalWorkspace.createOrSelectStack(\n {\n stackName: opts.stackName,\n projectName: opts.projectName,\n program: opts.program,\n },\n opts.workspaceOptions\n ),\n catch: (cause) =>\n new AutomationError({ stage: \"createOrSelectStack\", cause }),\n });\n\n/** Apply the whole config map in one `setAllConfig` call — a single CLI\n * round-trip, where per-key `setConfig` costs one `pulumi config set`\n * invocation each. */\nexport const setStackConfig = (\n stack: Stack,\n config: ConfigMap | undefined\n): Effect.Effect<void, AutomationError> =>\n !config || Object.keys(config).length === 0\n ? Effect.void\n : Effect.tryPromise({\n try: () => stack.setAllConfig(config),\n catch: (cause) => new AutomationError({ stage: \"setConfig\", cause }),\n });\n\n/** Compute the plan without applying it.\n *\n * A preview is a full engine run against the provider, not a cheap check — see\n * {@link DeployOptions.preview} before pairing one with an `up`. */\nexport const previewStack = (\n stack: Stack,\n opts?: PreviewOptions\n): Effect.Effect<PreviewResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.preview(opts),\n catch: (cause) => new AutomationError({ stage: \"preview\", cause }),\n });\n\n/** Apply the program: create, update and delete resources to match it.\n *\n * The result carries the stack's outputs and a summary; pass `onOutput` to\n * watch progress while it runs. */\nexport const upStack = (\n stack: Stack,\n opts?: UpOptions\n): Effect.Effect<UpResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.up(opts),\n catch: (cause) => new AutomationError({ stage: \"up\", cause }),\n });\n\n/** Refresh the stack's state from the actual cloud resources, without\n * changing them — what to run when state may have drifted (manual console\n * edits, a crashed update) before deciding what to do about it. */\nexport const refreshStack = (\n stack: Stack,\n opts?: RefreshOptions\n): Effect.Effect<RefreshResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.refresh(opts),\n catch: (cause) => new AutomationError({ stage: \"refresh\", cause }),\n });\n\n/** Read the stack's current outputs without running an update. */\nexport const stackOutputs = (\n stack: Stack\n): Effect.Effect<OutputMap, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.outputs(),\n catch: (cause) => new AutomationError({ stage: \"outputs\", cause }),\n });\n\n/** Destroy the stack's resources. The stack itself remains registered with\n * the backend — see `removeStack` / `teardownStack` to delete it too. */\nexport const destroyStack = (\n stack: Stack,\n opts?: DestroyOptions\n): Effect.Effect<DestroyResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.destroy(opts),\n catch: (cause) => new AutomationError({ stage: \"destroy\", cause }),\n });\n\n/** Delete the stack and its configuration and history from the backend.\n *\n * This does not destroy resources — run `destroyStack` first, or use\n * `teardownStack`. Pulumi refuses to remove a stack that still has resources\n * unless `RemoveOptions.force` is set, and forcing it orphans them: they keep\n * existing and billing with nothing tracking them. */\nexport const removeStack = (\n stack: Stack,\n opts?: RemoveOptions\n): Effect.Effect<void, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.workspace.removeStack(stack.name, opts),\n catch: (cause) => new AutomationError({ stage: \"removeStack\", cause }),\n });\n\n/** Full teardown: destroy the resources, then delete the stack.\n *\n * `destroyStack` alone leaves an empty stack behind, so anything creating\n * stacks per-run (ephemeral environments, tests naming stacks by timestamp)\n * accumulates them in the backend. */\nexport const teardownStack = (\n stack: Stack,\n opts?: { readonly destroy?: DestroyOptions; readonly remove?: RemoveOptions }\n): Effect.Effect<DestroyResult, AutomationError> =>\n Effect.gen(function* () {\n const result = yield* destroyStack(stack, opts?.destroy);\n yield* removeStack(stack, opts?.remove);\n return result;\n });\n\n// ---------------------------------------------------------------------------\n// Convenience lifecycle\n// ---------------------------------------------------------------------------\n\n/** {@link deploy}'s arguments: the stack to target, plus what to do with it. */\nexport type DeployOptions = StackOptions & {\n /** Config to apply before the update, in one `setAllConfig` call. Keys are\n * fully qualified (`\"my-project:myKey\"`). */\n readonly config?: ConfigMap;\n /** Options forwarded to the update — `onOutput` to stream progress,\n * `parallel`, `target`, and so on. */\n readonly up?: UpOptions;\n /** Run `preview` before `up`, returning its result.\n *\n * Off by default: a preview is a full engine run against the provider, so\n * previewing and then immediately upping does the work twice. `up` reports\n * the same failures, so this earns its cost only when you want the plan\n * itself. */\n readonly preview?: PreviewOptions | boolean;\n};\n\n/** What {@link deploy} hands back. */\nexport interface DeployResult {\n /** The selected stack, so teardown needs no second `createOrSelectStack`. */\n readonly stack: Stack;\n /** The update's result — `outputs` and `summary` live here. */\n readonly result: UpResult;\n /** Present only when `preview` was requested. */\n readonly preview?: PreviewResult;\n}\n\n/**\n * Select or create the stack, apply config, optionally preview, then up.\n *\n * The common path, assembled from the primitives above. Anything more\n * involved — refreshing first, inspecting the plan before deciding, retrying a\n * stage — should compose those directly rather than grow options here.\n *\n * @param opts - Which stack, and what to do with it.\n * @returns The stack handle alongside the results, so callers can tear down\n * afterwards without re-selecting.\n *\n * @example Deploy, use the outputs, then always tear down\n * ```ts\n * Effect.scoped(\n * Effect.gen(function* () {\n * const { result } = yield* Effect.acquireRelease(\n * deploy({ stackName, projectName, program, up: { onOutput } }),\n * ({ stack }) => teardownStack(stack).pipe(Effect.ignore)\n * );\n * return result.outputs.bucketId?.value;\n * })\n * );\n * ```\n */\nexport const deploy = (\n opts: DeployOptions\n): Effect.Effect<DeployResult, AutomationError> =>\n Effect.gen(function* () {\n const stack = yield* createOrSelectStack(opts);\n yield* setStackConfig(stack, opts.config);\n\n const preview = opts.preview\n ? yield* previewStack(\n stack,\n typeof opts.preview === \"boolean\" ? undefined : opts.preview\n )\n : undefined;\n\n const result = yield* upStack(stack, opts.up);\n return { stack, result, preview };\n });\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/output-bridge.ts","../src/effectify.ts","../src/automation.ts"],"names":["Data","Effect","pulumi","pulumi2","LocalWorkspace"],"mappings":"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","file":"index.cjs","sourcesContent":["import { Data } from \"effect\";\n\nconst describeCause = (cause: unknown): string =>\n cause instanceof Error ? cause.message : String(cause);\n\n/**\n * Any synchronous failure constructing a resource (bad args, provider\n * validation, etc.), or a failure resolving an Output's promise.\n *\n * Tagged `\"PulumiError\"`, so it can be matched by tag rather than by\n * `instanceof`:\n *\n * @example\n * ```ts\n * program.pipe(\n * Effect.catchTag(\"PulumiError\", (e) => Effect.logError(e.message))\n * );\n * ```\n */\nexport class PulumiError extends Data.TaggedError(\"PulumiError\")<{\n /** The original thrown value or rejection reason, unwrapped and unmodified.\n * Not necessarily an `Error`. */\n readonly cause: unknown;\n}> {\n /** Derived so anything reading `.message` - plain logging, test failure\n * output, non-Effect error handling - sees the underlying failure instead\n * of an empty string. */\n get message(): string {\n return describeCause(this.cause);\n }\n}\n\n/**\n * Failure from an Automation API lifecycle call (up/preview/destroy/select).\n *\n * `stage` says which call failed, which matters most in the composite\n * operations: a failed `deploy` could have died selecting the stack, applying\n * config, or running the update, and the three want different responses.\n *\n * @example\n * ```ts\n * deploy(opts).pipe(\n * Effect.catchTag(\"AutomationError\", (e) =>\n * e.stage === \"createOrSelectStack\"\n * ? Effect.fail(new BackendUnreachable())\n * : Effect.logError(e.message)\n * )\n * );\n * ```\n */\nexport class AutomationError extends Data.TaggedError(\"AutomationError\")<{\n /** Which Automation API call failed. Named for the wrapper that raised it,\n * so `deploy`'s failures still report the underlying stage. */\n readonly stage:\n | \"createOrSelectStack\"\n | \"setConfig\"\n | \"up\"\n | \"preview\"\n | \"refresh\"\n | \"outputs\"\n | \"destroy\"\n | \"removeStack\";\n /** The rejection reason from the Automation API. For a failed update this is\n * usually a `CommandError` carrying the CLI's stdout and stderr. */\n readonly cause: unknown;\n}> {\n /** `\"<stage> failed: <cause>\"` - the stage is included because the cause\n * alone rarely says which operation produced it. */\n get message(): string {\n return `${this.stage} failed: ${describeCause(this.cause)}`;\n }\n}\n","import * as pulumi from \"@pulumi/pulumi\";\nimport { Effect } from \"effect\";\nimport { PulumiError } from \"./errors.js\";\n\n/** `Output.promise()` is how the Pulumi runtime itself gets a settled value out\n * of an Output, but it is not part of the public `Output<T>` surface. */\ninterface PromisableOutput<T> {\n promise(withUnknowns?: boolean): Promise<T>;\n}\n\n/**\n * Lift a single Output into an Effect.\n *\n * `withUnknowns: true` matters during `pulumi preview`, where a not-yet-created\n * resource's outputs have no value: it resolves to Pulumi's unknown sentinel\n * instead of throwing, so a program that reads outputs still previews cleanly.\n *\n * @param output - The Output to resolve.\n * @returns An Effect yielding the settled value, failing with\n * {@link PulumiError} if the underlying promise rejects.\n *\n * @example\n * ```ts\n * const bucket = yield* eaws.s3.Bucket(\"assets\", {});\n * const id = yield* fromOutput(bucket.id); // string\n * ```\n *\n * @remarks Reading an Output only makes sense inside a running Pulumi program.\n * During `preview` the value may be the unknown sentinel rather than real data,\n * so don't branch on it to decide what to create.\n */\nexport const fromOutput = <T>(\n output: pulumi.Output<T>\n): Effect.Effect<T, PulumiError> =>\n Effect.tryPromise({\n try: () => (output as unknown as PromisableOutput<T>).promise(true),\n catch: (cause) => new PulumiError({ cause }),\n });\n\n/**\n * Lift a record of Outputs into a single Effect of the resolved record - use\n * this right after constructing a resource to grab several fields at once.\n *\n * Resolves them together via `pulumi.all`, so it costs one await rather than\n * one per field.\n *\n * @param outputs - A record whose values are all Outputs. Interfaces work as\n * well as object literals; the constraint is self-referential rather than\n * `Record<string, Output<any>>` precisely so interface-typed bags are accepted.\n * @returns An Effect yielding the same record with each value unwrapped.\n *\n * @example\n * ```ts\n * const bucket = yield* eaws.s3.Bucket(\"assets\", {});\n * const { id, arn } = yield* fromOutputs({ id: bucket.id, arn: bucket.arn });\n * ```\n */\nexport const fromOutputs = <T extends { [K in keyof T]: pulumi.Output<any> }>(\n outputs: T\n): Effect.Effect<{ [K in keyof T]: pulumi.Unwrap<T[K]> }, PulumiError> =>\n fromOutput(pulumi.all(outputs) as pulumi.Output<any>);\n","/**\n * effectify - auto-wrap a Pulumi provider package (e.g. @pulumi/aws,\n * @pulumi/cloudflare) so every resource constructor becomes an\n * Effect-returning factory, without the caller ever writing `Effect.sync`.\n *\n * Usage:\n *\n * import * as aws from \"@pulumi/aws\";\n * const eaws = effectify(aws);\n *\n * const program = Effect.gen(function* () {\n * const bucket = yield* eaws.s3.Bucket(\"my-bucket\", { forceDestroy: true });\n * // ^ Effect<aws.s3.Bucket, PulumiError> - no manual wrapping\n * });\n *\n * How it works:\n * - Every Pulumi resource class extends `pulumi.Resource` under the hood\n * (via CustomResource / ComponentResource). That's the runtime marker\n * used to tell \"this export is a resource constructor\" apart from \"this\n * export is a namespace object\" (e.g. `aws.s3`) or \"this export is an\n * invoke function\" (e.g. `aws.s3.getBucket`).\n * - Namespace objects get recursively proxied (lazily, memoized).\n * - CustomResource constructors get wrapped so any field in their args\n * object may *additionally* be an Effect - resolved (concurrently, they\n * are independent by construction) before construction. This is safe\n * because codegen guarantees CustomResource args are always\n * Record<string, Input<T>>.\n * - Wrapped constructors keep their static members: `Bucket.get(...)`,\n * `Bucket.isInstance(...)` and friends forward to the original class, so\n * the wrapped package can be the only import a program needs.\n * - ComponentResource constructors get wrapped with no arg-lifting - args\n * pass through exactly as declared, since component args aren't\n * guaranteed to be Input<T>-shaped (hand-authored, may do synchronous\n * work on a bare primitive inside the constructor).\n * - Invoke functions (`aws.s3.getBucket`) return an Effect instead of a\n * Promise. There is no runtime marker for \"this function is async\", so\n * the wrapper calls the function and inspects the result: a thenable\n * becomes an Effect, anything else is returned as-is. That means the\n * invoke *starts* at the call site (see the caveat on `wrapInvokeLike`);\n * `*Output` invoke variants return an Output, which is not thenable, so\n * they pass through untouched - matching the type-level mapping, which\n * only rewrites Promise-returning signatures.\n * - Everything else (enums, plain values, non-resource classes) passes\n * through untouched.\n *\n * Resource registration remains synchronous under the hood - Effect.try\n * runs its thunk immediately. This only removes hand-written wrapper\n * boilerplate, not Pulumi's execution model.\n */\n\nimport * as pulumi from \"@pulumi/pulumi\";\nimport { Effect } from \"effect\";\nimport { PulumiError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Runtime type guards\n// ---------------------------------------------------------------------------\n\nconst isResourceConstructor = (\n value: unknown\n): value is new (...args: any[]) => pulumi.Resource =>\n typeof value === \"function\" &&\n (value === (pulumi.Resource as unknown) ||\n value.prototype instanceof pulumi.Resource);\n\nconst isComponentResourceConstructor = (\n Ctor: Function\n): Ctor is new (...args: any[]) => pulumi.ComponentResource =>\n Ctor === (pulumi.ComponentResource as unknown) ||\n Ctor.prototype instanceof pulumi.ComponentResource;\n\n/** An object whose string-keyed properties we only ever *read*. Distinct from\n * `Record<string, unknown>`, which additionally claims the properties are\n * writable and that the object declares an index signature - neither is true\n * of a codegen'd `BucketArgs`, and neither is something this module relies on. */\ntype UnknownProps = { readonly [key: string]: unknown };\n\n/** Is this a namespace to recurse into? The narrowed type is only ever handed\n * to `effectifyInner`, which takes `object` - so claim exactly that and no\n * more. */\nconst isNamespace = (value: unknown): value is object =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** Is this an args object whose entries we can scan for Effects? Same runtime\n * check as `isNamespace`, but a different question, so it gets the narrowing\n * that question needs: `object` would make `Object.entries` infer `any` values\n * and silently drop the `isEffect` filter's type safety. */\nconst isArgsObject = (value: unknown): value is UnknownProps =>\n isNamespace(value);\n\n/** Note: `pulumi.Output` is deliberately not thenable, so `*Output` invoke\n * variants fail this check and pass through unwrapped - keeping the runtime\n * behaviour aligned with the type mapping, which only rewrites\n * Promise-returning signatures. */\nconst isPromiseLike = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\";\n\n// ---------------------------------------------------------------------------\n// Type-level mapping\n// ---------------------------------------------------------------------------\n\n/** Allow any field of a CustomResource args object to *additionally* be an\n * Effect. Homomorphic, so optional fields stay optional and plain\n * `Input<T>`/`Output<T>` values keep working untouched. */\ntype LiftedArgs<A> = A extends object\n ? { [K in keyof A]: A[K] | Effect.Effect<A[K], PulumiError> }\n : A;\n\n/** Apply `LiftedArgs` to the second constructor parameter (the args object),\n * leaving `name` and `opts` alone. Mapping over the parameter tuple\n * homomorphically preserves labels and optionality, so constructors whose\n * args are optional stay callable as `Bucket(\"name\")`. */\ntype LiftArgsParam<P extends readonly unknown[]> = {\n [K in keyof P]: K extends \"1\" ? LiftedArgs<P[K]> : P[K];\n};\n\n/** The class's static side, minus `prototype`: `keyof` on a constructor type\n * yields exactly the statics (own and inherited, e.g. codegen'd `get` and\n * `isInstance`), which the runtime wrapper forwards to the original class. */\ntype StaticMembers<T> = Omit<T, \"prototype\">;\n\n/**\n * The type of {@link effectify}'s result: `T` with every resource constructor\n * and every `Promise`-returning invoke rewritten, and everything else left\n * alone.\n *\n * The cases, in the order they are tried:\n *\n * | Input | Becomes |\n * | --------------------------- | ---------------------------------------------- |\n * | `ComponentResource` class | factory returning `Effect`, args **not** lifted |\n * | `CustomResource` class | factory returning `Effect`, args lifted |\n * | other class | unchanged |\n * | `(...) => Promise<R>` | `(...) => Effect<R, PulumiError>` |\n * | other function | unchanged (includes `*Output` invokes) |\n * | object | mapped recursively |\n * | anything else | unchanged |\n *\n * Statics survive on the wrapped constructors, so `Bucket.get` and\n * `Bucket.isInstance` remain callable.\n */\nexport type Effectify<T> = T extends abstract new (\n ...params: infer P\n) => infer R\n ? R extends pulumi.ComponentResource\n ? ((...params: P) => Effect.Effect<R, PulumiError>) & StaticMembers<T>\n : R extends pulumi.CustomResource\n ? ((...params: LiftArgsParam<P>) => Effect.Effect<R, PulumiError>) &\n StaticMembers<T>\n : T\n : T extends (...args: infer A) => Promise<infer R>\n ? (...args: A) => Effect.Effect<R, PulumiError>\n : T extends (...args: any[]) => any\n ? T\n : T extends object\n ? { [K in keyof T]: Effectify<T[K]> }\n : T;\n\n// ---------------------------------------------------------------------------\n// Runtime implementation\n// ---------------------------------------------------------------------------\n\nconst proxyCache = new WeakMap<object, unknown>();\n\nconst isEffect = (value: unknown): value is Effect.Effect<unknown, unknown> =>\n Effect.isEffect(value);\n\nfunction resolveLiftedArgs(args: unknown): Effect.Effect<unknown, PulumiError> {\n if (!isArgsObject(args)) {\n return Effect.succeed(args);\n }\n\n const effectEntries = Object.entries(args).filter(([, v]) => isEffect(v));\n\n if (effectEntries.length === 0) {\n return Effect.succeed(args);\n }\n\n // The arg Effects are independent of one another, so resolve them\n // concurrently - it matters when several of them await slow Outputs.\n return Effect.map(\n Effect.all(\n effectEntries.map(([key, effectValue]) =>\n Effect.map(\n effectValue as Effect.Effect<unknown, PulumiError>,\n (resolved) => [key, resolved] as const\n )\n ),\n { concurrency: \"unbounded\" }\n ),\n (resolved) => ({ ...args, ...Object.fromEntries(resolved) })\n );\n}\n\nfunction wrapCustomResourceCtor(\n Ctor: new (...args: any[]) => pulumi.CustomResource\n) {\n return (name: string, args?: unknown, opts?: unknown) =>\n Effect.gen(function* () {\n const resolvedArgs = yield* resolveLiftedArgs(args);\n return yield* Effect.try({\n try: () => new Ctor(name, resolvedArgs, opts),\n catch: (cause) => new PulumiError({ cause }),\n });\n });\n}\n\nfunction wrapComponentResourceCtor(\n Ctor: new (...args: any[]) => pulumi.ComponentResource\n) {\n return (name: string, args?: unknown, opts?: unknown) =>\n Effect.try({\n try: () => new Ctor(name, args, opts),\n catch: (cause) => new PulumiError({ cause }),\n });\n}\n\n/** Forward static members (codegen'd `get`, `isInstance`, …) from the class\n * onto the factory. The factory's own and inherited properties (`name`,\n * `length`, `call`, …) win; anything else falls through to the class, so new\n * statics keep working without being enumerated here. A bonus of forwarding\n * `prototype` is that `x instanceof wrapped` still works. */\nconst withStatics = <F extends object>(factory: F, Ctor: Function): F =>\n new Proxy(factory, {\n get: (target, prop, receiver) =>\n Reflect.has(target, prop)\n ? Reflect.get(target, prop, receiver)\n : Reflect.get(Ctor, prop),\n has: (target, prop) => Reflect.has(target, prop) || Reflect.has(Ctor, prop),\n });\n\nfunction wrapResourceCtor(Ctor: new (...args: any[]) => pulumi.Resource) {\n const factory = isComponentResourceConstructor(Ctor)\n ? wrapComponentResourceCtor(Ctor)\n : wrapCustomResourceCtor(\n Ctor as new (...args: any[]) => pulumi.CustomResource\n );\n return withStatics(factory, Ctor);\n}\n\n/** Turn a Promise-returning invoke into an Effect-returning one, leaving\n * synchronous functions' behaviour untouched.\n *\n * A Proxy over the original function (rather than a new function) so `name`,\n * `length`, own properties and prototype all survive; only the call itself is\n * intercepted.\n *\n * Caveat, stated openly: whether a function is async is only knowable by\n * calling it, so the invoke *starts* when the factory is called - the Effect\n * resolves an already-in-flight Promise rather than deferring the call. Two\n * consequences:\n * - `Effect.retry` re-awaits the same call instead of re-invoking. To\n * re-invoke per attempt, wrap the call site: `Effect.suspend(() =>\n * eaws.getAmi(args))`.\n * - A discarded Effect must not surface as an unhandled rejection, so the\n * rejection is pre-observed on a side branch before the Effect awaits it.\n */\nfunction wrapInvokeLike(fn: Function): Function {\n return new Proxy(fn, {\n apply(target, thisArg, args) {\n const result = Reflect.apply(target, thisArg, args);\n if (!isPromiseLike(result)) {\n return result;\n }\n result.then(undefined, () => {});\n return Effect.tryPromise({\n try: () => result as Promise<unknown>,\n catch: (cause) => new PulumiError({ cause }),\n });\n },\n });\n}\n\n/** Wrapped constructors are cached so repeated reads of the same property\n * hand back the same function - identity checks like\n * `eaws.s3.Bucket === eaws.s3.Bucket` hold, and the `get` and\n * `getOwnPropertyDescriptor` traps agree on a property's value. */\nconst wrapperCache = new WeakMap<object, unknown>();\n\nfunction effectifyValue(value: unknown): unknown {\n if (isResourceConstructor(value)) {\n const cached = wrapperCache.get(value);\n if (cached) return cached;\n const wrapped = wrapResourceCtor(value);\n wrapperCache.set(value, wrapped);\n return wrapped;\n }\n\n if (typeof value === \"function\") {\n const cached = wrapperCache.get(value);\n if (cached) return cached;\n const wrapped = wrapInvokeLike(value);\n wrapperCache.set(value, wrapped);\n return wrapped;\n }\n\n if (isNamespace(value)) {\n return effectifyInner(value);\n }\n\n return value; // plain value, enum member, type-only export\n}\n\nfunction effectifyInner<T extends object>(mod: T): Effectify<T> {\n const cached = proxyCache.get(mod);\n if (cached) return cached as Effectify<T>;\n\n // The proxy target is a fresh plain object rather than `mod` itself: ES\n // module namespace objects (and @pulumi/aws's lazily-defined namespace\n // getters) expose non-configurable own properties, and a `get` trap that\n // returns a wrapper instead of the real value would violate the proxy\n // invariants for those. Forwarding to `mod` from a closure sidesteps that\n // entirely while keeping the lazy-loading behaviour intact.\n const proxy = new Proxy(Object.create(null) as T, {\n get(_target, prop) {\n return effectifyValue(Reflect.get(mod, prop));\n },\n has(_target, prop) {\n return Reflect.has(mod, prop);\n },\n ownKeys() {\n return Reflect.ownKeys(mod);\n },\n getOwnPropertyDescriptor(_target, prop) {\n const descriptor = Reflect.getOwnPropertyDescriptor(mod, prop);\n if (!descriptor) return undefined;\n // Must be reported as configurable - the target does not actually have\n // the property, so claiming otherwise breaks the proxy invariants.\n return {\n value: effectifyValue(Reflect.get(mod, prop)),\n enumerable: descriptor.enumerable,\n configurable: true,\n writable: true,\n };\n },\n set() {\n return false; // the wrapper is read-only\n },\n }) as Effectify<T>;\n\n proxyCache.set(mod, proxy);\n return proxy;\n}\n\n/**\n * Wrap a provider package (or any namespace) once, turning every resource\n * constructor into an `Effect`-returning factory and every `Promise`-returning\n * invoke into an `Effect`-returning function.\n *\n * Call this once per package at module scope and export the result - the\n * wrapper is cached, so repeated calls and repeated property reads hand back\n * the same objects, but there is no reason to re-wrap.\n *\n * @param mod - The provider package, or any namespace within one. Not mutated;\n * the result is a read-only proxy that forwards to it.\n * @returns A same-shaped view of `mod`, typed by {@link Effectify}.\n *\n * @example Constructing a resource\n * ```ts\n * import * as aws from \"@pulumi/aws\";\n * const eaws = effectify(aws);\n *\n * const program = Effect.gen(function* () {\n * const bucket = yield* eaws.s3.Bucket(\"assets\", { forceDestroy: true });\n * return bucket.id;\n * });\n * ```\n *\n * @example Passing an Effect as an argument\n * A `CustomResource`'s args may hold Effects, which are resolved concurrently\n * before the resource is constructed:\n * ```ts\n * yield* eaws.s3.BucketObject(\"readme\", {\n * bucket: bucketIdEffect,\n * content: \"hello\",\n * });\n * ```\n *\n * @throws Nothing. Failures surface in the returned Effect's error channel as\n * {@link PulumiError} - including synchronous throws from the constructor.\n *\n * @see {@link Effectify} for the type-level mapping.\n */\nexport function effectify<T extends object>(mod: T): Effectify<T> {\n return effectifyInner(mod);\n}\n","import type {\n ConfigMap,\n DestroyOptions,\n DestroyResult,\n LocalWorkspaceOptions,\n OutputMap,\n PreviewOptions,\n PreviewResult,\n PulumiFn,\n RefreshOptions,\n RefreshResult,\n RemoveOptions,\n Stack,\n UpOptions,\n UpResult,\n} from \"@pulumi/pulumi/automation/index.js\";\nimport { LocalWorkspace } from \"@pulumi/pulumi/automation/index.js\";\nimport { Effect } from \"effect\";\nimport { AutomationError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Primitives\n//\n// Each wraps one Automation API call, tagging failures with the stage they\n// came from. They are exported individually so callers can assemble their own\n// lifecycle - `deploy` below is only the common path.\n//\n// Every operation takes the matching Pulumi options type. That includes\n// `onOutput`: pass it to stream the CLI's progress as it happens. Without it\n// nothing is printed during what may be a multi-minute operation (the text is\n// still captured on the result's `stdout`, and on the error when one is\n// thrown, but only once the operation has finished).\n// ---------------------------------------------------------------------------\n\n/** Arguments for an inline program - the Pulumi program is a function in this\n * process, with no `Pulumi.yaml` on disk. */\nexport interface InlineStackOptions {\n /** Stack to select, created if absent. */\n readonly stackName: string;\n /** Project name to register the stack under. Chosen freely here, since\n * there is no `Pulumi.yaml` to take it from - but it is part of the stack's\n * identity in the backend, so changing it later points at a different\n * stack. */\n readonly projectName: string;\n /** The program itself. Runs in this process, so it needs no separate Node\n * runtime and can close over values from the caller. */\n readonly program: PulumiFn;\n readonly workspaceOptions?: LocalWorkspaceOptions;\n}\n\n/** Arguments for a local program - an existing Pulumi project on disk. */\nexport interface LocalStackOptions {\n /** Stack to select, created if absent. */\n readonly stackName: string;\n /** Directory holding the project's `Pulumi.yaml`. Its `name:` supplies the\n * project name, which is why there is no `projectName` here. */\n readonly workDir: string;\n readonly workspaceOptions?: LocalWorkspaceOptions;\n}\n\n/** Either flavour of stack. Discriminated at runtime by the presence of\n * `workDir`, so the two are not interchangeable: an inline program needs\n * `projectName`, a local one takes it from `Pulumi.yaml`. */\nexport type StackOptions = InlineStackOptions | LocalStackOptions;\n\nconst isLocal = (opts: StackOptions): opts is LocalStackOptions =>\n \"workDir\" in opts;\n\n/** Select the stack, creating it if it does not exist, and return the handle\n * every other operation here takes.\n *\n * Creating the workspace is itself work - it may write files and shell out to\n * the CLI - so hold on to the returned `Stack` rather than re-selecting before\n * each operation. */\nexport const createOrSelectStack = (\n opts: StackOptions\n): Effect.Effect<Stack, AutomationError> =>\n Effect.tryPromise({\n try: () =>\n isLocal(opts)\n ? LocalWorkspace.createOrSelectStack(\n { stackName: opts.stackName, workDir: opts.workDir },\n opts.workspaceOptions\n )\n : LocalWorkspace.createOrSelectStack(\n {\n stackName: opts.stackName,\n projectName: opts.projectName,\n program: opts.program,\n },\n opts.workspaceOptions\n ),\n catch: (cause) =>\n new AutomationError({ stage: \"createOrSelectStack\", cause }),\n });\n\n/** Apply the whole config map in one `setAllConfig` call - a single CLI\n * round-trip, where per-key `setConfig` costs one `pulumi config set`\n * invocation each. */\nexport const setStackConfig = (\n stack: Stack,\n config: ConfigMap | undefined\n): Effect.Effect<void, AutomationError> =>\n !config || Object.keys(config).length === 0\n ? Effect.void\n : Effect.tryPromise({\n try: () => stack.setAllConfig(config),\n catch: (cause) => new AutomationError({ stage: \"setConfig\", cause }),\n });\n\n/** Compute the plan without applying it.\n *\n * A preview is a full engine run against the provider, not a cheap check - see\n * {@link DeployOptions.preview} before pairing one with an `up`. */\nexport const previewStack = (\n stack: Stack,\n opts?: PreviewOptions\n): Effect.Effect<PreviewResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.preview(opts),\n catch: (cause) => new AutomationError({ stage: \"preview\", cause }),\n });\n\n/** Apply the program: create, update and delete resources to match it.\n *\n * The result carries the stack's outputs and a summary; pass `onOutput` to\n * watch progress while it runs. */\nexport const upStack = (\n stack: Stack,\n opts?: UpOptions\n): Effect.Effect<UpResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.up(opts),\n catch: (cause) => new AutomationError({ stage: \"up\", cause }),\n });\n\n/** Refresh the stack's state from the actual cloud resources, without\n * changing them - what to run when state may have drifted (manual console\n * edits, a crashed update) before deciding what to do about it. */\nexport const refreshStack = (\n stack: Stack,\n opts?: RefreshOptions\n): Effect.Effect<RefreshResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.refresh(opts),\n catch: (cause) => new AutomationError({ stage: \"refresh\", cause }),\n });\n\n/** Read the stack's current outputs without running an update. */\nexport const stackOutputs = (\n stack: Stack\n): Effect.Effect<OutputMap, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.outputs(),\n catch: (cause) => new AutomationError({ stage: \"outputs\", cause }),\n });\n\n/** Destroy the stack's resources. The stack itself remains registered with\n * the backend - see `removeStack` / `teardownStack` to delete it too. */\nexport const destroyStack = (\n stack: Stack,\n opts?: DestroyOptions\n): Effect.Effect<DestroyResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.destroy(opts),\n catch: (cause) => new AutomationError({ stage: \"destroy\", cause }),\n });\n\n/** Delete the stack and its configuration and history from the backend.\n *\n * This does not destroy resources - run `destroyStack` first, or use\n * `teardownStack`. Pulumi refuses to remove a stack that still has resources\n * unless `RemoveOptions.force` is set, and forcing it orphans them: they keep\n * existing and billing with nothing tracking them. */\nexport const removeStack = (\n stack: Stack,\n opts?: RemoveOptions\n): Effect.Effect<void, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.workspace.removeStack(stack.name, opts),\n catch: (cause) => new AutomationError({ stage: \"removeStack\", cause }),\n });\n\n/** Full teardown: destroy the resources, then delete the stack.\n *\n * `destroyStack` alone leaves an empty stack behind, so anything creating\n * stacks per-run (ephemeral environments, tests naming stacks by timestamp)\n * accumulates them in the backend. */\nexport const teardownStack = (\n stack: Stack,\n opts?: { readonly destroy?: DestroyOptions; readonly remove?: RemoveOptions }\n): Effect.Effect<DestroyResult, AutomationError> =>\n Effect.gen(function* () {\n const result = yield* destroyStack(stack, opts?.destroy);\n yield* removeStack(stack, opts?.remove);\n return result;\n });\n\n// ---------------------------------------------------------------------------\n// Convenience lifecycle\n// ---------------------------------------------------------------------------\n\n/** {@link deploy}'s arguments: the stack to target, plus what to do with it. */\nexport type DeployOptions = StackOptions & {\n /** Config to apply before the update, in one `setAllConfig` call. Keys are\n * fully qualified (`\"my-project:myKey\"`). */\n readonly config?: ConfigMap;\n /** Options forwarded to the update - `onOutput` to stream progress,\n * `parallel`, `target`, and so on. */\n readonly up?: UpOptions;\n /** Run `preview` before `up`, returning its result.\n *\n * Off by default: a preview is a full engine run against the provider, so\n * previewing and then immediately upping does the work twice. `up` reports\n * the same failures, so this earns its cost only when you want the plan\n * itself. */\n readonly preview?: PreviewOptions | boolean;\n};\n\n/** What {@link deploy} hands back. */\nexport interface DeployResult {\n /** The selected stack, so teardown needs no second `createOrSelectStack`. */\n readonly stack: Stack;\n /** The update's result - `outputs` and `summary` live here. */\n readonly result: UpResult;\n /** Present only when `preview` was requested. */\n readonly preview?: PreviewResult;\n}\n\n/**\n * Select or create the stack, apply config, optionally preview, then up.\n *\n * The common path, assembled from the primitives above. Anything more\n * involved - refreshing first, inspecting the plan before deciding, retrying a\n * stage - should compose those directly rather than grow options here.\n *\n * @param opts - Which stack, and what to do with it.\n * @returns The stack handle alongside the results, so callers can tear down\n * afterwards without re-selecting.\n *\n * @example Deploy, use the outputs, then always tear down\n * ```ts\n * Effect.scoped(\n * Effect.gen(function* () {\n * const { result } = yield* Effect.acquireRelease(\n * deploy({ stackName, projectName, program, up: { onOutput } }),\n * ({ stack }) => teardownStack(stack).pipe(Effect.ignore)\n * );\n * return result.outputs.bucketId?.value;\n * })\n * );\n * ```\n */\nexport const deploy = (\n opts: DeployOptions\n): Effect.Effect<DeployResult, AutomationError> =>\n Effect.gen(function* () {\n const stack = yield* createOrSelectStack(opts);\n yield* setStackConfig(stack, opts.config);\n\n const preview = opts.preview\n ? yield* previewStack(\n stack,\n typeof opts.preview === \"boolean\" ? undefined : opts.preview\n )\n : undefined;\n\n const result = yield* upStack(stack, opts.up);\n return { stack, result, preview };\n });\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -26,8 +26,8 @@ declare class PulumiError extends PulumiError_base<{
|
|
|
26
26
|
* Not necessarily an `Error`. */
|
|
27
27
|
readonly cause: unknown;
|
|
28
28
|
}> {
|
|
29
|
-
/** Derived so anything reading `.message`
|
|
30
|
-
* output, non-Effect error handling
|
|
29
|
+
/** Derived so anything reading `.message` - plain logging, test failure
|
|
30
|
+
* output, non-Effect error handling - sees the underlying failure instead
|
|
31
31
|
* of an empty string. */
|
|
32
32
|
get message(): string;
|
|
33
33
|
}
|
|
@@ -60,7 +60,7 @@ declare class AutomationError extends AutomationError_base<{
|
|
|
60
60
|
* usually a `CommandError` carrying the CLI's stdout and stderr. */
|
|
61
61
|
readonly cause: unknown;
|
|
62
62
|
}> {
|
|
63
|
-
/** `"<stage> failed: <cause>"`
|
|
63
|
+
/** `"<stage> failed: <cause>"` - the stage is included because the cause
|
|
64
64
|
* alone rarely says which operation produced it. */
|
|
65
65
|
get message(): string;
|
|
66
66
|
}
|
|
@@ -88,7 +88,7 @@ declare class AutomationError extends AutomationError_base<{
|
|
|
88
88
|
*/
|
|
89
89
|
declare const fromOutput: <T>(output: pulumi.Output<T>) => Effect.Effect<T, PulumiError>;
|
|
90
90
|
/**
|
|
91
|
-
* Lift a record of Outputs into a single Effect of the resolved record
|
|
91
|
+
* Lift a record of Outputs into a single Effect of the resolved record - use
|
|
92
92
|
* this right after constructing a resource to grab several fields at once.
|
|
93
93
|
*
|
|
94
94
|
* Resolves them together via `pulumi.all`, so it costs one await rather than
|
|
@@ -108,7 +108,7 @@ declare const fromOutput: <T>(output: pulumi.Output<T>) => Effect.Effect<T, Pulu
|
|
|
108
108
|
declare const fromOutputs: <T extends { [K in keyof T]: pulumi.Output<any>; }>(outputs: T) => Effect.Effect<{ [K in keyof T]: pulumi.Unwrap<T[K]>; }, PulumiError>;
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
|
-
* effectify
|
|
111
|
+
* effectify - auto-wrap a Pulumi provider package (e.g. @pulumi/aws,
|
|
112
112
|
* @pulumi/cloudflare) so every resource constructor becomes an
|
|
113
113
|
* Effect-returning factory, without the caller ever writing `Effect.sync`.
|
|
114
114
|
*
|
|
@@ -119,7 +119,7 @@ declare const fromOutputs: <T extends { [K in keyof T]: pulumi.Output<any>; }>(o
|
|
|
119
119
|
*
|
|
120
120
|
* const program = Effect.gen(function* () {
|
|
121
121
|
* const bucket = yield* eaws.s3.Bucket("my-bucket", { forceDestroy: true });
|
|
122
|
-
* // ^ Effect<aws.s3.Bucket, PulumiError>
|
|
122
|
+
* // ^ Effect<aws.s3.Bucket, PulumiError> - no manual wrapping
|
|
123
123
|
* });
|
|
124
124
|
*
|
|
125
125
|
* How it works:
|
|
@@ -130,14 +130,14 @@ declare const fromOutputs: <T extends { [K in keyof T]: pulumi.Output<any>; }>(o
|
|
|
130
130
|
* invoke function" (e.g. `aws.s3.getBucket`).
|
|
131
131
|
* - Namespace objects get recursively proxied (lazily, memoized).
|
|
132
132
|
* - CustomResource constructors get wrapped so any field in their args
|
|
133
|
-
* object may *additionally* be an Effect
|
|
133
|
+
* object may *additionally* be an Effect - resolved (concurrently, they
|
|
134
134
|
* are independent by construction) before construction. This is safe
|
|
135
135
|
* because codegen guarantees CustomResource args are always
|
|
136
136
|
* Record<string, Input<T>>.
|
|
137
137
|
* - Wrapped constructors keep their static members: `Bucket.get(...)`,
|
|
138
138
|
* `Bucket.isInstance(...)` and friends forward to the original class, so
|
|
139
139
|
* the wrapped package can be the only import a program needs.
|
|
140
|
-
* - ComponentResource constructors get wrapped with no arg-lifting
|
|
140
|
+
* - ComponentResource constructors get wrapped with no arg-lifting - args
|
|
141
141
|
* pass through exactly as declared, since component args aren't
|
|
142
142
|
* guaranteed to be Input<T>-shaped (hand-authored, may do synchronous
|
|
143
143
|
* work on a bare primitive inside the constructor).
|
|
@@ -147,12 +147,12 @@ declare const fromOutputs: <T extends { [K in keyof T]: pulumi.Output<any>; }>(o
|
|
|
147
147
|
* becomes an Effect, anything else is returned as-is. That means the
|
|
148
148
|
* invoke *starts* at the call site (see the caveat on `wrapInvokeLike`);
|
|
149
149
|
* `*Output` invoke variants return an Output, which is not thenable, so
|
|
150
|
-
* they pass through untouched
|
|
150
|
+
* they pass through untouched - matching the type-level mapping, which
|
|
151
151
|
* only rewrites Promise-returning signatures.
|
|
152
152
|
* - Everything else (enums, plain values, non-resource classes) passes
|
|
153
153
|
* through untouched.
|
|
154
154
|
*
|
|
155
|
-
* Resource registration remains synchronous under the hood
|
|
155
|
+
* Resource registration remains synchronous under the hood - Effect.try
|
|
156
156
|
* runs its thunk immediately. This only removes hand-written wrapper
|
|
157
157
|
* boilerplate, not Pulumi's execution model.
|
|
158
158
|
*/
|
|
@@ -202,7 +202,7 @@ type Effectify<T> = T extends abstract new (...params: infer P) => infer R ? R e
|
|
|
202
202
|
* constructor into an `Effect`-returning factory and every `Promise`-returning
|
|
203
203
|
* invoke into an `Effect`-returning function.
|
|
204
204
|
*
|
|
205
|
-
* Call this once per package at module scope and export the result
|
|
205
|
+
* Call this once per package at module scope and export the result - the
|
|
206
206
|
* wrapper is cached, so repeated calls and repeated property reads hand back
|
|
207
207
|
* the same objects, but there is no reason to re-wrap.
|
|
208
208
|
*
|
|
@@ -232,19 +232,19 @@ type Effectify<T> = T extends abstract new (...params: infer P) => infer R ? R e
|
|
|
232
232
|
* ```
|
|
233
233
|
*
|
|
234
234
|
* @throws Nothing. Failures surface in the returned Effect's error channel as
|
|
235
|
-
* {@link PulumiError}
|
|
235
|
+
* {@link PulumiError} - including synchronous throws from the constructor.
|
|
236
236
|
*
|
|
237
237
|
* @see {@link Effectify} for the type-level mapping.
|
|
238
238
|
*/
|
|
239
239
|
declare function effectify<T extends object>(mod: T): Effectify<T>;
|
|
240
240
|
|
|
241
|
-
/** Arguments for an inline program
|
|
241
|
+
/** Arguments for an inline program - the Pulumi program is a function in this
|
|
242
242
|
* process, with no `Pulumi.yaml` on disk. */
|
|
243
243
|
interface InlineStackOptions {
|
|
244
244
|
/** Stack to select, created if absent. */
|
|
245
245
|
readonly stackName: string;
|
|
246
246
|
/** Project name to register the stack under. Chosen freely here, since
|
|
247
|
-
* there is no `Pulumi.yaml` to take it from
|
|
247
|
+
* there is no `Pulumi.yaml` to take it from - but it is part of the stack's
|
|
248
248
|
* identity in the backend, so changing it later points at a different
|
|
249
249
|
* stack. */
|
|
250
250
|
readonly projectName: string;
|
|
@@ -253,7 +253,7 @@ interface InlineStackOptions {
|
|
|
253
253
|
readonly program: PulumiFn;
|
|
254
254
|
readonly workspaceOptions?: LocalWorkspaceOptions;
|
|
255
255
|
}
|
|
256
|
-
/** Arguments for a local program
|
|
256
|
+
/** Arguments for a local program - an existing Pulumi project on disk. */
|
|
257
257
|
interface LocalStackOptions {
|
|
258
258
|
/** Stack to select, created if absent. */
|
|
259
259
|
readonly stackName: string;
|
|
@@ -269,17 +269,17 @@ type StackOptions = InlineStackOptions | LocalStackOptions;
|
|
|
269
269
|
/** Select the stack, creating it if it does not exist, and return the handle
|
|
270
270
|
* every other operation here takes.
|
|
271
271
|
*
|
|
272
|
-
* Creating the workspace is itself work
|
|
273
|
-
* the CLI
|
|
272
|
+
* Creating the workspace is itself work - it may write files and shell out to
|
|
273
|
+
* the CLI - so hold on to the returned `Stack` rather than re-selecting before
|
|
274
274
|
* each operation. */
|
|
275
275
|
declare const createOrSelectStack: (opts: StackOptions) => Effect.Effect<Stack, AutomationError>;
|
|
276
|
-
/** Apply the whole config map in one `setAllConfig` call
|
|
276
|
+
/** Apply the whole config map in one `setAllConfig` call - a single CLI
|
|
277
277
|
* round-trip, where per-key `setConfig` costs one `pulumi config set`
|
|
278
278
|
* invocation each. */
|
|
279
279
|
declare const setStackConfig: (stack: Stack, config: ConfigMap | undefined) => Effect.Effect<void, AutomationError>;
|
|
280
280
|
/** Compute the plan without applying it.
|
|
281
281
|
*
|
|
282
|
-
* A preview is a full engine run against the provider, not a cheap check
|
|
282
|
+
* A preview is a full engine run against the provider, not a cheap check - see
|
|
283
283
|
* {@link DeployOptions.preview} before pairing one with an `up`. */
|
|
284
284
|
declare const previewStack: (stack: Stack, opts?: PreviewOptions) => Effect.Effect<PreviewResult, AutomationError>;
|
|
285
285
|
/** Apply the program: create, update and delete resources to match it.
|
|
@@ -288,17 +288,17 @@ declare const previewStack: (stack: Stack, opts?: PreviewOptions) => Effect.Effe
|
|
|
288
288
|
* watch progress while it runs. */
|
|
289
289
|
declare const upStack: (stack: Stack, opts?: UpOptions) => Effect.Effect<UpResult, AutomationError>;
|
|
290
290
|
/** Refresh the stack's state from the actual cloud resources, without
|
|
291
|
-
* changing them
|
|
291
|
+
* changing them - what to run when state may have drifted (manual console
|
|
292
292
|
* edits, a crashed update) before deciding what to do about it. */
|
|
293
293
|
declare const refreshStack: (stack: Stack, opts?: RefreshOptions) => Effect.Effect<RefreshResult, AutomationError>;
|
|
294
294
|
/** Read the stack's current outputs without running an update. */
|
|
295
295
|
declare const stackOutputs: (stack: Stack) => Effect.Effect<OutputMap, AutomationError>;
|
|
296
296
|
/** Destroy the stack's resources. The stack itself remains registered with
|
|
297
|
-
* the backend
|
|
297
|
+
* the backend - see `removeStack` / `teardownStack` to delete it too. */
|
|
298
298
|
declare const destroyStack: (stack: Stack, opts?: DestroyOptions) => Effect.Effect<DestroyResult, AutomationError>;
|
|
299
299
|
/** Delete the stack and its configuration and history from the backend.
|
|
300
300
|
*
|
|
301
|
-
* This does not destroy resources
|
|
301
|
+
* This does not destroy resources - run `destroyStack` first, or use
|
|
302
302
|
* `teardownStack`. Pulumi refuses to remove a stack that still has resources
|
|
303
303
|
* unless `RemoveOptions.force` is set, and forcing it orphans them: they keep
|
|
304
304
|
* existing and billing with nothing tracking them. */
|
|
@@ -317,7 +317,7 @@ type DeployOptions = StackOptions & {
|
|
|
317
317
|
/** Config to apply before the update, in one `setAllConfig` call. Keys are
|
|
318
318
|
* fully qualified (`"my-project:myKey"`). */
|
|
319
319
|
readonly config?: ConfigMap;
|
|
320
|
-
/** Options forwarded to the update
|
|
320
|
+
/** Options forwarded to the update - `onOutput` to stream progress,
|
|
321
321
|
* `parallel`, `target`, and so on. */
|
|
322
322
|
readonly up?: UpOptions;
|
|
323
323
|
/** Run `preview` before `up`, returning its result.
|
|
@@ -332,7 +332,7 @@ type DeployOptions = StackOptions & {
|
|
|
332
332
|
interface DeployResult {
|
|
333
333
|
/** The selected stack, so teardown needs no second `createOrSelectStack`. */
|
|
334
334
|
readonly stack: Stack;
|
|
335
|
-
/** The update's result
|
|
335
|
+
/** The update's result - `outputs` and `summary` live here. */
|
|
336
336
|
readonly result: UpResult;
|
|
337
337
|
/** Present only when `preview` was requested. */
|
|
338
338
|
readonly preview?: PreviewResult;
|
|
@@ -341,8 +341,8 @@ interface DeployResult {
|
|
|
341
341
|
* Select or create the stack, apply config, optionally preview, then up.
|
|
342
342
|
*
|
|
343
343
|
* The common path, assembled from the primitives above. Anything more
|
|
344
|
-
* involved
|
|
345
|
-
* stage
|
|
344
|
+
* involved - refreshing first, inspecting the plan before deciding, retrying a
|
|
345
|
+
* stage - should compose those directly rather than grow options here.
|
|
346
346
|
*
|
|
347
347
|
* @param opts - Which stack, and what to do with it.
|
|
348
348
|
* @returns The stack handle alongside the results, so callers can tear down
|
package/dist/index.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ declare class PulumiError extends PulumiError_base<{
|
|
|
26
26
|
* Not necessarily an `Error`. */
|
|
27
27
|
readonly cause: unknown;
|
|
28
28
|
}> {
|
|
29
|
-
/** Derived so anything reading `.message`
|
|
30
|
-
* output, non-Effect error handling
|
|
29
|
+
/** Derived so anything reading `.message` - plain logging, test failure
|
|
30
|
+
* output, non-Effect error handling - sees the underlying failure instead
|
|
31
31
|
* of an empty string. */
|
|
32
32
|
get message(): string;
|
|
33
33
|
}
|
|
@@ -60,7 +60,7 @@ declare class AutomationError extends AutomationError_base<{
|
|
|
60
60
|
* usually a `CommandError` carrying the CLI's stdout and stderr. */
|
|
61
61
|
readonly cause: unknown;
|
|
62
62
|
}> {
|
|
63
|
-
/** `"<stage> failed: <cause>"`
|
|
63
|
+
/** `"<stage> failed: <cause>"` - the stage is included because the cause
|
|
64
64
|
* alone rarely says which operation produced it. */
|
|
65
65
|
get message(): string;
|
|
66
66
|
}
|
|
@@ -88,7 +88,7 @@ declare class AutomationError extends AutomationError_base<{
|
|
|
88
88
|
*/
|
|
89
89
|
declare const fromOutput: <T>(output: pulumi.Output<T>) => Effect.Effect<T, PulumiError>;
|
|
90
90
|
/**
|
|
91
|
-
* Lift a record of Outputs into a single Effect of the resolved record
|
|
91
|
+
* Lift a record of Outputs into a single Effect of the resolved record - use
|
|
92
92
|
* this right after constructing a resource to grab several fields at once.
|
|
93
93
|
*
|
|
94
94
|
* Resolves them together via `pulumi.all`, so it costs one await rather than
|
|
@@ -108,7 +108,7 @@ declare const fromOutput: <T>(output: pulumi.Output<T>) => Effect.Effect<T, Pulu
|
|
|
108
108
|
declare const fromOutputs: <T extends { [K in keyof T]: pulumi.Output<any>; }>(outputs: T) => Effect.Effect<{ [K in keyof T]: pulumi.Unwrap<T[K]>; }, PulumiError>;
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
|
-
* effectify
|
|
111
|
+
* effectify - auto-wrap a Pulumi provider package (e.g. @pulumi/aws,
|
|
112
112
|
* @pulumi/cloudflare) so every resource constructor becomes an
|
|
113
113
|
* Effect-returning factory, without the caller ever writing `Effect.sync`.
|
|
114
114
|
*
|
|
@@ -119,7 +119,7 @@ declare const fromOutputs: <T extends { [K in keyof T]: pulumi.Output<any>; }>(o
|
|
|
119
119
|
*
|
|
120
120
|
* const program = Effect.gen(function* () {
|
|
121
121
|
* const bucket = yield* eaws.s3.Bucket("my-bucket", { forceDestroy: true });
|
|
122
|
-
* // ^ Effect<aws.s3.Bucket, PulumiError>
|
|
122
|
+
* // ^ Effect<aws.s3.Bucket, PulumiError> - no manual wrapping
|
|
123
123
|
* });
|
|
124
124
|
*
|
|
125
125
|
* How it works:
|
|
@@ -130,14 +130,14 @@ declare const fromOutputs: <T extends { [K in keyof T]: pulumi.Output<any>; }>(o
|
|
|
130
130
|
* invoke function" (e.g. `aws.s3.getBucket`).
|
|
131
131
|
* - Namespace objects get recursively proxied (lazily, memoized).
|
|
132
132
|
* - CustomResource constructors get wrapped so any field in their args
|
|
133
|
-
* object may *additionally* be an Effect
|
|
133
|
+
* object may *additionally* be an Effect - resolved (concurrently, they
|
|
134
134
|
* are independent by construction) before construction. This is safe
|
|
135
135
|
* because codegen guarantees CustomResource args are always
|
|
136
136
|
* Record<string, Input<T>>.
|
|
137
137
|
* - Wrapped constructors keep their static members: `Bucket.get(...)`,
|
|
138
138
|
* `Bucket.isInstance(...)` and friends forward to the original class, so
|
|
139
139
|
* the wrapped package can be the only import a program needs.
|
|
140
|
-
* - ComponentResource constructors get wrapped with no arg-lifting
|
|
140
|
+
* - ComponentResource constructors get wrapped with no arg-lifting - args
|
|
141
141
|
* pass through exactly as declared, since component args aren't
|
|
142
142
|
* guaranteed to be Input<T>-shaped (hand-authored, may do synchronous
|
|
143
143
|
* work on a bare primitive inside the constructor).
|
|
@@ -147,12 +147,12 @@ declare const fromOutputs: <T extends { [K in keyof T]: pulumi.Output<any>; }>(o
|
|
|
147
147
|
* becomes an Effect, anything else is returned as-is. That means the
|
|
148
148
|
* invoke *starts* at the call site (see the caveat on `wrapInvokeLike`);
|
|
149
149
|
* `*Output` invoke variants return an Output, which is not thenable, so
|
|
150
|
-
* they pass through untouched
|
|
150
|
+
* they pass through untouched - matching the type-level mapping, which
|
|
151
151
|
* only rewrites Promise-returning signatures.
|
|
152
152
|
* - Everything else (enums, plain values, non-resource classes) passes
|
|
153
153
|
* through untouched.
|
|
154
154
|
*
|
|
155
|
-
* Resource registration remains synchronous under the hood
|
|
155
|
+
* Resource registration remains synchronous under the hood - Effect.try
|
|
156
156
|
* runs its thunk immediately. This only removes hand-written wrapper
|
|
157
157
|
* boilerplate, not Pulumi's execution model.
|
|
158
158
|
*/
|
|
@@ -202,7 +202,7 @@ type Effectify<T> = T extends abstract new (...params: infer P) => infer R ? R e
|
|
|
202
202
|
* constructor into an `Effect`-returning factory and every `Promise`-returning
|
|
203
203
|
* invoke into an `Effect`-returning function.
|
|
204
204
|
*
|
|
205
|
-
* Call this once per package at module scope and export the result
|
|
205
|
+
* Call this once per package at module scope and export the result - the
|
|
206
206
|
* wrapper is cached, so repeated calls and repeated property reads hand back
|
|
207
207
|
* the same objects, but there is no reason to re-wrap.
|
|
208
208
|
*
|
|
@@ -232,19 +232,19 @@ type Effectify<T> = T extends abstract new (...params: infer P) => infer R ? R e
|
|
|
232
232
|
* ```
|
|
233
233
|
*
|
|
234
234
|
* @throws Nothing. Failures surface in the returned Effect's error channel as
|
|
235
|
-
* {@link PulumiError}
|
|
235
|
+
* {@link PulumiError} - including synchronous throws from the constructor.
|
|
236
236
|
*
|
|
237
237
|
* @see {@link Effectify} for the type-level mapping.
|
|
238
238
|
*/
|
|
239
239
|
declare function effectify<T extends object>(mod: T): Effectify<T>;
|
|
240
240
|
|
|
241
|
-
/** Arguments for an inline program
|
|
241
|
+
/** Arguments for an inline program - the Pulumi program is a function in this
|
|
242
242
|
* process, with no `Pulumi.yaml` on disk. */
|
|
243
243
|
interface InlineStackOptions {
|
|
244
244
|
/** Stack to select, created if absent. */
|
|
245
245
|
readonly stackName: string;
|
|
246
246
|
/** Project name to register the stack under. Chosen freely here, since
|
|
247
|
-
* there is no `Pulumi.yaml` to take it from
|
|
247
|
+
* there is no `Pulumi.yaml` to take it from - but it is part of the stack's
|
|
248
248
|
* identity in the backend, so changing it later points at a different
|
|
249
249
|
* stack. */
|
|
250
250
|
readonly projectName: string;
|
|
@@ -253,7 +253,7 @@ interface InlineStackOptions {
|
|
|
253
253
|
readonly program: PulumiFn;
|
|
254
254
|
readonly workspaceOptions?: LocalWorkspaceOptions;
|
|
255
255
|
}
|
|
256
|
-
/** Arguments for a local program
|
|
256
|
+
/** Arguments for a local program - an existing Pulumi project on disk. */
|
|
257
257
|
interface LocalStackOptions {
|
|
258
258
|
/** Stack to select, created if absent. */
|
|
259
259
|
readonly stackName: string;
|
|
@@ -269,17 +269,17 @@ type StackOptions = InlineStackOptions | LocalStackOptions;
|
|
|
269
269
|
/** Select the stack, creating it if it does not exist, and return the handle
|
|
270
270
|
* every other operation here takes.
|
|
271
271
|
*
|
|
272
|
-
* Creating the workspace is itself work
|
|
273
|
-
* the CLI
|
|
272
|
+
* Creating the workspace is itself work - it may write files and shell out to
|
|
273
|
+
* the CLI - so hold on to the returned `Stack` rather than re-selecting before
|
|
274
274
|
* each operation. */
|
|
275
275
|
declare const createOrSelectStack: (opts: StackOptions) => Effect.Effect<Stack, AutomationError>;
|
|
276
|
-
/** Apply the whole config map in one `setAllConfig` call
|
|
276
|
+
/** Apply the whole config map in one `setAllConfig` call - a single CLI
|
|
277
277
|
* round-trip, where per-key `setConfig` costs one `pulumi config set`
|
|
278
278
|
* invocation each. */
|
|
279
279
|
declare const setStackConfig: (stack: Stack, config: ConfigMap | undefined) => Effect.Effect<void, AutomationError>;
|
|
280
280
|
/** Compute the plan without applying it.
|
|
281
281
|
*
|
|
282
|
-
* A preview is a full engine run against the provider, not a cheap check
|
|
282
|
+
* A preview is a full engine run against the provider, not a cheap check - see
|
|
283
283
|
* {@link DeployOptions.preview} before pairing one with an `up`. */
|
|
284
284
|
declare const previewStack: (stack: Stack, opts?: PreviewOptions) => Effect.Effect<PreviewResult, AutomationError>;
|
|
285
285
|
/** Apply the program: create, update and delete resources to match it.
|
|
@@ -288,17 +288,17 @@ declare const previewStack: (stack: Stack, opts?: PreviewOptions) => Effect.Effe
|
|
|
288
288
|
* watch progress while it runs. */
|
|
289
289
|
declare const upStack: (stack: Stack, opts?: UpOptions) => Effect.Effect<UpResult, AutomationError>;
|
|
290
290
|
/** Refresh the stack's state from the actual cloud resources, without
|
|
291
|
-
* changing them
|
|
291
|
+
* changing them - what to run when state may have drifted (manual console
|
|
292
292
|
* edits, a crashed update) before deciding what to do about it. */
|
|
293
293
|
declare const refreshStack: (stack: Stack, opts?: RefreshOptions) => Effect.Effect<RefreshResult, AutomationError>;
|
|
294
294
|
/** Read the stack's current outputs without running an update. */
|
|
295
295
|
declare const stackOutputs: (stack: Stack) => Effect.Effect<OutputMap, AutomationError>;
|
|
296
296
|
/** Destroy the stack's resources. The stack itself remains registered with
|
|
297
|
-
* the backend
|
|
297
|
+
* the backend - see `removeStack` / `teardownStack` to delete it too. */
|
|
298
298
|
declare const destroyStack: (stack: Stack, opts?: DestroyOptions) => Effect.Effect<DestroyResult, AutomationError>;
|
|
299
299
|
/** Delete the stack and its configuration and history from the backend.
|
|
300
300
|
*
|
|
301
|
-
* This does not destroy resources
|
|
301
|
+
* This does not destroy resources - run `destroyStack` first, or use
|
|
302
302
|
* `teardownStack`. Pulumi refuses to remove a stack that still has resources
|
|
303
303
|
* unless `RemoveOptions.force` is set, and forcing it orphans them: they keep
|
|
304
304
|
* existing and billing with nothing tracking them. */
|
|
@@ -317,7 +317,7 @@ type DeployOptions = StackOptions & {
|
|
|
317
317
|
/** Config to apply before the update, in one `setAllConfig` call. Keys are
|
|
318
318
|
* fully qualified (`"my-project:myKey"`). */
|
|
319
319
|
readonly config?: ConfigMap;
|
|
320
|
-
/** Options forwarded to the update
|
|
320
|
+
/** Options forwarded to the update - `onOutput` to stream progress,
|
|
321
321
|
* `parallel`, `target`, and so on. */
|
|
322
322
|
readonly up?: UpOptions;
|
|
323
323
|
/** Run `preview` before `up`, returning its result.
|
|
@@ -332,7 +332,7 @@ type DeployOptions = StackOptions & {
|
|
|
332
332
|
interface DeployResult {
|
|
333
333
|
/** The selected stack, so teardown needs no second `createOrSelectStack`. */
|
|
334
334
|
readonly stack: Stack;
|
|
335
|
-
/** The update's result
|
|
335
|
+
/** The update's result - `outputs` and `summary` live here. */
|
|
336
336
|
readonly result: UpResult;
|
|
337
337
|
/** Present only when `preview` was requested. */
|
|
338
338
|
readonly preview?: PreviewResult;
|
|
@@ -341,8 +341,8 @@ interface DeployResult {
|
|
|
341
341
|
* Select or create the stack, apply config, optionally preview, then up.
|
|
342
342
|
*
|
|
343
343
|
* The common path, assembled from the primitives above. Anything more
|
|
344
|
-
* involved
|
|
345
|
-
* stage
|
|
344
|
+
* involved - refreshing first, inspecting the plan before deciding, retrying a
|
|
345
|
+
* stage - should compose those directly rather than grow options here.
|
|
346
346
|
*
|
|
347
347
|
* @param opts - Which stack, and what to do with it.
|
|
348
348
|
* @returns The stack handle alongside the results, so callers can tear down
|
package/dist/index.js
CHANGED
|
@@ -5,15 +5,15 @@ import { LocalWorkspace } from '@pulumi/pulumi/automation/index.js';
|
|
|
5
5
|
// src/errors.ts
|
|
6
6
|
var describeCause = (cause) => cause instanceof Error ? cause.message : String(cause);
|
|
7
7
|
var PulumiError = class extends Data.TaggedError("PulumiError") {
|
|
8
|
-
/** Derived so anything reading `.message`
|
|
9
|
-
* output, non-Effect error handling
|
|
8
|
+
/** Derived so anything reading `.message` - plain logging, test failure
|
|
9
|
+
* output, non-Effect error handling - sees the underlying failure instead
|
|
10
10
|
* of an empty string. */
|
|
11
11
|
get message() {
|
|
12
12
|
return describeCause(this.cause);
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
var AutomationError = class extends Data.TaggedError("AutomationError") {
|
|
16
|
-
/** `"<stage> failed: <cause>"`
|
|
16
|
+
/** `"<stage> failed: <cause>"` - the stage is included because the cause
|
|
17
17
|
* alone rarely says which operation produced it. */
|
|
18
18
|
get message() {
|
|
19
19
|
return `${this.stage} failed: ${describeCause(this.cause)}`;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/output-bridge.ts","../src/effectify.ts","../src/automation.ts"],"names":["pulumi","Effect"],"mappings":";;;;;AAEA,IAAM,aAAA,GAAgB,CAAC,KAAA,KACrB,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAgBhD,IAAM,WAAA,GAAN,cAA0B,IAAA,CAAK,WAAA,CAAY,aAAa,CAAA,CAI5D;AAAA;AAAA;AAAA;AAAA,EAID,IAAI,OAAA,GAAkB;AACpB,IAAA,OAAO,aAAA,CAAc,KAAK,KAAK,CAAA;AAAA,EACjC;AACF;AAoBO,IAAM,eAAA,GAAN,cAA8B,IAAA,CAAK,WAAA,CAAY,iBAAiB,CAAA,CAepE;AAAA;AAAA;AAAA,EAGD,IAAI,OAAA,GAAkB;AACpB,IAAA,OAAO,GAAG,IAAA,CAAK,KAAK,YAAY,aAAA,CAAc,IAAA,CAAK,KAAK,CAAC,CAAA,CAAA;AAAA,EAC3D;AACF;ACxCO,IAAM,UAAA,GAAa,CACxB,MAAA,KAEA,MAAA,CAAO,UAAA,CAAW;AAAA,EAChB,GAAA,EAAK,MAAO,MAAA,CAA0C,OAAA,CAAQ,IAAI,CAAA;AAAA,EAClE,OAAO,CAAC,KAAA,KAAU,IAAI,WAAA,CAAY,EAAE,OAAO;AAC7C,CAAC;AAoBI,IAAM,cAAc,CACzB,OAAA,KAEA,UAAA,CAAkBA,OAAA,CAAA,GAAA,CAAI,OAAO,CAAuB;ACFtD,IAAM,qBAAA,GAAwB,CAC5B,KAAA,KAEA,OAAO,UAAU,UAAA,KAChB,KAAA,KAAkB,OAAA,CAAA,QAAA,IACjB,KAAA,CAAM,SAAA,YAA4B,OAAA,CAAA,QAAA,CAAA;AAEtC,IAAM,iCAAiC,CACrC,IAAA,KAEA,IAAA,KAAiB,OAAA,CAAA,iBAAA,IACjB,KAAK,SAAA,YAA4B,OAAA,CAAA,iBAAA;AAWnC,IAAM,WAAA,GAAc,CAAC,KAAA,KACnB,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,IAAQ,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA;AAMrE,IAAM,YAAA,GAAe,CAAC,KAAA,KACpB,WAAA,CAAY,KAAK,CAAA;AAMnB,IAAM,aAAA,GAAgB,CAAC,KAAA,KACrB,OAAO,KAAA,KAAU,YACjB,KAAA,KAAU,IAAA,IACV,OAAQ,KAAA,CAA6B,IAAA,KAAS,UAAA;AAmEhD,IAAM,UAAA,uBAAiB,OAAA,EAAyB;AAEhD,IAAM,QAAA,GAAW,CAAC,KAAA,KAChBC,MAAAA,CAAO,SAAS,KAAK,CAAA;AAEvB,SAAS,kBAAkB,IAAA,EAAoD;AAC7E,EAAA,IAAI,CAAC,YAAA,CAAa,IAAI,CAAA,EAAG;AACvB,IAAA,OAAOA,MAAAA,CAAO,QAAQ,IAAI,CAAA;AAAA,EAC5B;AAEA,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,CAAC,CAAA,KAAM,QAAA,CAAS,CAAC,CAAC,CAAA;AAExE,EAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAC9B,IAAA,OAAOA,MAAAA,CAAO,QAAQ,IAAI,CAAA;AAAA,EAC5B;AAIA,EAAA,OAAOA,MAAAA,CAAO,GAAA;AAAA,IACZA,MAAAA,CAAO,GAAA;AAAA,MACL,aAAA,CAAc,GAAA;AAAA,QAAI,CAAC,CAAC,GAAA,EAAK,WAAW,MAClCA,MAAAA,CAAO,GAAA;AAAA,UACL,WAAA;AAAA,UACA,CAAC,QAAA,KAAa,CAAC,GAAA,EAAK,QAAQ;AAAA;AAC9B,OACF;AAAA,MACA,EAAE,aAAa,WAAA;AAAY,KAC7B;AAAA,IACA,CAAC,cAAc,EAAE,GAAG,MAAM,GAAG,MAAA,CAAO,WAAA,CAAY,QAAQ,CAAA,EAAE;AAAA,GAC5D;AACF;AAEA,SAAS,uBACP,IAAA,EACA;AACA,EAAA,OAAO,CAAC,IAAA,EAAc,IAAA,EAAgB,IAAA,KACpCA,MAAAA,CAAO,IAAI,aAAa;AACtB,IAAA,MAAM,YAAA,GAAe,OAAO,iBAAA,CAAkB,IAAI,CAAA;AAClD,IAAA,OAAO,OAAOA,OAAO,GAAA,CAAI;AAAA,MACvB,KAAK,MAAM,IAAI,IAAA,CAAK,IAAA,EAAM,cAAc,IAAI,CAAA;AAAA,MAC5C,OAAO,CAAC,KAAA,KAAU,IAAI,WAAA,CAAY,EAAE,OAAO;AAAA,KAC5C,CAAA;AAAA,EACH,CAAC,CAAA;AACL;AAEA,SAAS,0BACP,IAAA,EACA;AACA,EAAA,OAAO,CAAC,IAAA,EAAc,IAAA,EAAgB,IAAA,KACpCA,OAAO,GAAA,CAAI;AAAA,IACT,KAAK,MAAM,IAAI,IAAA,CAAK,IAAA,EAAM,MAAM,IAAI,CAAA;AAAA,IACpC,OAAO,CAAC,KAAA,KAAU,IAAI,WAAA,CAAY,EAAE,OAAO;AAAA,GAC5C,CAAA;AACL;AAOA,IAAM,cAAc,CAAmB,OAAA,EAAY,IAAA,KACjD,IAAI,MAAM,OAAA,EAAS;AAAA,EACjB,KAAK,CAAC,MAAA,EAAQ,MAAM,QAAA,KAClB,OAAA,CAAQ,IAAI,MAAA,EAAQ,IAAI,IACpB,OAAA,CAAQ,GAAA,CAAI,QAAQ,IAAA,EAAM,QAAQ,IAClC,OAAA,CAAQ,GAAA,CAAI,MAAM,IAAI,CAAA;AAAA,EAC5B,GAAA,EAAK,CAAC,MAAA,EAAQ,IAAA,KAAS,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,IAAI,CAAA,IAAK,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,IAAI;AAC5E,CAAC,CAAA;AAEH,SAAS,iBAAiB,IAAA,EAA+C;AACvE,EAAA,MAAM,UAAU,8BAAA,CAA+B,IAAI,CAAA,GAC/C,yBAAA,CAA0B,IAAI,CAAA,GAC9B,sBAAA;AAAA,IACE;AAAA,GACF;AACJ,EAAA,OAAO,WAAA,CAAY,SAAS,IAAI,CAAA;AAClC;AAmBA,SAAS,eAAe,EAAA,EAAwB;AAC9C,EAAA,OAAO,IAAI,MAAM,EAAA,EAAI;AAAA,IACnB,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM;AAC3B,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,SAAS,IAAI,CAAA;AAClD,MAAA,IAAI,CAAC,aAAA,CAAc,MAAM,CAAA,EAAG;AAC1B,QAAA,OAAO,MAAA;AAAA,MACT;AACA,MAAA,MAAA,CAAO,IAAA,CAAK,QAAW,MAAM;AAAA,MAAC,CAAC,CAAA;AAC/B,MAAA,OAAOA,OAAO,UAAA,CAAW;AAAA,QACvB,KAAK,MAAM,MAAA;AAAA,QACX,OAAO,CAAC,KAAA,KAAU,IAAI,WAAA,CAAY,EAAE,OAAO;AAAA,OAC5C,CAAA;AAAA,IACH;AAAA,GACD,CAAA;AACH;AAMA,IAAM,YAAA,uBAAmB,OAAA,EAAyB;AAElD,SAAS,eAAe,KAAA,EAAyB;AAC/C,EAAA,IAAI,qBAAA,CAAsB,KAAK,CAAA,EAAG;AAChC,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,GAAA,CAAI,KAAK,CAAA;AACrC,IAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,IAAA,MAAM,OAAA,GAAU,iBAAiB,KAAK,CAAA;AACtC,IAAA,YAAA,CAAa,GAAA,CAAI,OAAO,OAAO,CAAA;AAC/B,IAAA,OAAO,OAAA;AAAA,EACT;AAEA,EAAA,IAAI,OAAO,UAAU,UAAA,EAAY;AAC/B,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,GAAA,CAAI,KAAK,CAAA;AACrC,IAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,IAAA,MAAM,OAAA,GAAU,eAAe,KAAK,CAAA;AACpC,IAAA,YAAA,CAAa,GAAA,CAAI,OAAO,OAAO,CAAA;AAC/B,IAAA,OAAO,OAAA;AAAA,EACT;AAEA,EAAA,IAAI,WAAA,CAAY,KAAK,CAAA,EAAG;AACtB,IAAA,OAAO,eAAe,KAAK,CAAA;AAAA,EAC7B;AAEA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,eAAiC,GAAA,EAAsB;AAC9D,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA;AACjC,EAAA,IAAI,QAAQ,OAAO,MAAA;AAQnB,EAAA,MAAM,QAAQ,IAAI,KAAA,iBAAM,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA,EAAQ;AAAA,IAChD,GAAA,CAAI,SAAS,IAAA,EAAM;AACjB,MAAA,OAAO,cAAA,CAAe,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,IAAI,CAAC,CAAA;AAAA,IAC9C,CAAA;AAAA,IACA,GAAA,CAAI,SAAS,IAAA,EAAM;AACjB,MAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA;AAAA,IAC9B,CAAA;AAAA,IACA,OAAA,GAAU;AACR,MAAA,OAAO,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,IAC5B,CAAA;AAAA,IACA,wBAAA,CAAyB,SAAS,IAAA,EAAM;AACtC,MAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,wBAAA,CAAyB,GAAA,EAAK,IAAI,CAAA;AAC7D,MAAA,IAAI,CAAC,YAAY,OAAO,MAAA;AAGxB,MAAA,OAAO;AAAA,QACL,OAAO,cAAA,CAAe,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,IAAI,CAAC,CAAA;AAAA,QAC5C,YAAY,UAAA,CAAW,UAAA;AAAA,QACvB,YAAA,EAAc,IAAA;AAAA,QACd,QAAA,EAAU;AAAA,OACZ;AAAA,IACF,CAAA;AAAA,IACA,GAAA,GAAM;AACJ,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,GACD,CAAA;AAED,EAAA,UAAA,CAAW,GAAA,CAAI,KAAK,KAAK,CAAA;AACzB,EAAA,OAAO,KAAA;AACT;AAyCO,SAAS,UAA4B,GAAA,EAAsB;AAChE,EAAA,OAAO,eAAe,GAAG,CAAA;AAC3B;AClUA,IAAM,OAAA,GAAU,CAAC,IAAA,KACf,SAAA,IAAa,IAAA;AAQR,IAAM,mBAAA,GAAsB,CACjC,IAAA,KAEAA,MAAAA,CAAO,UAAA,CAAW;AAAA,EAChB,GAAA,EAAK,MACH,OAAA,CAAQ,IAAI,IACR,cAAA,CAAe,mBAAA;AAAA,IACb,EAAE,SAAA,EAAW,IAAA,CAAK,SAAA,EAAW,OAAA,EAAS,KAAK,OAAA,EAAQ;AAAA,IACnD,IAAA,CAAK;AAAA,MAEP,cAAA,CAAe,mBAAA;AAAA,IACb;AAAA,MACE,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,IACA,IAAA,CAAK;AAAA,GACP;AAAA,EACN,KAAA,EAAO,CAAC,KAAA,KACN,IAAI,gBAAgB,EAAE,KAAA,EAAO,qBAAA,EAAuB,KAAA,EAAO;AAC/D,CAAC;AAKI,IAAM,cAAA,GAAiB,CAC5B,KAAA,EACA,MAAA,KAEA,CAAC,MAAA,IAAU,MAAA,CAAO,IAAA,CAAK,MAAM,EAAE,MAAA,KAAW,CAAA,GACtCA,MAAAA,CAAO,IAAA,GACPA,OAAO,UAAA,CAAW;AAAA,EAChB,GAAA,EAAK,MAAM,KAAA,CAAM,YAAA,CAAa,MAAM,CAAA;AAAA,EACpC,KAAA,EAAO,CAAC,KAAA,KAAU,IAAI,gBAAgB,EAAE,KAAA,EAAO,WAAA,EAAa,KAAA,EAAO;AACrE,CAAC;AAMA,IAAM,YAAA,GAAe,CAC1B,KAAA,EACA,IAAA,KAEAA,OAAO,UAAA,CAAW;AAAA,EAChB,GAAA,EAAK,MAAM,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,EAC7B,KAAA,EAAO,CAAC,KAAA,KAAU,IAAI,gBAAgB,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO;AACnE,CAAC;AAMI,IAAM,OAAA,GAAU,CACrB,KAAA,EACA,IAAA,KAEAA,OAAO,UAAA,CAAW;AAAA,EAChB,GAAA,EAAK,MAAM,KAAA,CAAM,EAAA,CAAG,IAAI,CAAA;AAAA,EACxB,KAAA,EAAO,CAAC,KAAA,KAAU,IAAI,gBAAgB,EAAE,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO;AAC9D,CAAC;AAKI,IAAM,YAAA,GAAe,CAC1B,KAAA,EACA,IAAA,KAEAA,OAAO,UAAA,CAAW;AAAA,EAChB,GAAA,EAAK,MAAM,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,EAC7B,KAAA,EAAO,CAAC,KAAA,KAAU,IAAI,gBAAgB,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO;AACnE,CAAC;AAGI,IAAM,YAAA,GAAe,CAC1B,KAAA,KAEAA,MAAAA,CAAO,UAAA,CAAW;AAAA,EAChB,GAAA,EAAK,MAAM,KAAA,CAAM,OAAA,EAAQ;AAAA,EACzB,KAAA,EAAO,CAAC,KAAA,KAAU,IAAI,gBAAgB,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO;AACnE,CAAC;AAII,IAAM,YAAA,GAAe,CAC1B,KAAA,EACA,IAAA,KAEAA,OAAO,UAAA,CAAW;AAAA,EAChB,GAAA,EAAK,MAAM,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,EAC7B,KAAA,EAAO,CAAC,KAAA,KAAU,IAAI,gBAAgB,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO;AACnE,CAAC;AAQI,IAAM,WAAA,GAAc,CACzB,KAAA,EACA,IAAA,KAEAA,OAAO,UAAA,CAAW;AAAA,EAChB,KAAK,MAAM,KAAA,CAAM,UAAU,WAAA,CAAY,KAAA,CAAM,MAAM,IAAI,CAAA;AAAA,EACvD,KAAA,EAAO,CAAC,KAAA,KAAU,IAAI,gBAAgB,EAAE,KAAA,EAAO,aAAA,EAAe,KAAA,EAAO;AACvE,CAAC;AAOI,IAAM,gBAAgB,CAC3B,KAAA,EACA,IAAA,KAEAA,MAAAA,CAAO,IAAI,aAAa;AACtB,EAAA,MAAM,MAAA,GAAS,OAAO,YAAA,CAAa,KAAA,EAAO,MAAM,OAAO,CAAA;AACvD,EAAA,OAAO,WAAA,CAAY,KAAA,EAAO,IAAA,EAAM,MAAM,CAAA;AACtC,EAAA,OAAO,MAAA;AACT,CAAC;AAyDI,IAAM,MAAA,GAAS,CACpB,IAAA,KAEAA,MAAAA,CAAO,IAAI,aAAa;AACtB,EAAA,MAAM,KAAA,GAAQ,OAAO,mBAAA,CAAoB,IAAI,CAAA;AAC7C,EAAA,OAAO,cAAA,CAAe,KAAA,EAAO,IAAA,CAAK,MAAM,CAAA;AAExC,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,GACjB,OAAO,YAAA;AAAA,IACL,KAAA;AAAA,IACA,OAAO,IAAA,CAAK,OAAA,KAAY,SAAA,GAAY,SAAY,IAAA,CAAK;AAAA,GACvD,GACA,MAAA;AAEJ,EAAA,MAAM,MAAA,GAAS,OAAO,OAAA,CAAQ,KAAA,EAAO,KAAK,EAAE,CAAA;AAC5C,EAAA,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,OAAA,EAAQ;AAClC,CAAC","file":"index.js","sourcesContent":["import { Data } from \"effect\";\n\nconst describeCause = (cause: unknown): string =>\n cause instanceof Error ? cause.message : String(cause);\n\n/**\n * Any synchronous failure constructing a resource (bad args, provider\n * validation, etc.), or a failure resolving an Output's promise.\n *\n * Tagged `\"PulumiError\"`, so it can be matched by tag rather than by\n * `instanceof`:\n *\n * @example\n * ```ts\n * program.pipe(\n * Effect.catchTag(\"PulumiError\", (e) => Effect.logError(e.message))\n * );\n * ```\n */\nexport class PulumiError extends Data.TaggedError(\"PulumiError\")<{\n /** The original thrown value or rejection reason, unwrapped and unmodified.\n * Not necessarily an `Error`. */\n readonly cause: unknown;\n}> {\n /** Derived so anything reading `.message` — plain logging, test failure\n * output, non-Effect error handling — sees the underlying failure instead\n * of an empty string. */\n get message(): string {\n return describeCause(this.cause);\n }\n}\n\n/**\n * Failure from an Automation API lifecycle call (up/preview/destroy/select).\n *\n * `stage` says which call failed, which matters most in the composite\n * operations: a failed `deploy` could have died selecting the stack, applying\n * config, or running the update, and the three want different responses.\n *\n * @example\n * ```ts\n * deploy(opts).pipe(\n * Effect.catchTag(\"AutomationError\", (e) =>\n * e.stage === \"createOrSelectStack\"\n * ? Effect.fail(new BackendUnreachable())\n * : Effect.logError(e.message)\n * )\n * );\n * ```\n */\nexport class AutomationError extends Data.TaggedError(\"AutomationError\")<{\n /** Which Automation API call failed. Named for the wrapper that raised it,\n * so `deploy`'s failures still report the underlying stage. */\n readonly stage:\n | \"createOrSelectStack\"\n | \"setConfig\"\n | \"up\"\n | \"preview\"\n | \"refresh\"\n | \"outputs\"\n | \"destroy\"\n | \"removeStack\";\n /** The rejection reason from the Automation API. For a failed update this is\n * usually a `CommandError` carrying the CLI's stdout and stderr. */\n readonly cause: unknown;\n}> {\n /** `\"<stage> failed: <cause>\"` — the stage is included because the cause\n * alone rarely says which operation produced it. */\n get message(): string {\n return `${this.stage} failed: ${describeCause(this.cause)}`;\n }\n}\n","import * as pulumi from \"@pulumi/pulumi\";\nimport { Effect } from \"effect\";\nimport { PulumiError } from \"./errors.js\";\n\n/** `Output.promise()` is how the Pulumi runtime itself gets a settled value out\n * of an Output, but it is not part of the public `Output<T>` surface. */\ninterface PromisableOutput<T> {\n promise(withUnknowns?: boolean): Promise<T>;\n}\n\n/**\n * Lift a single Output into an Effect.\n *\n * `withUnknowns: true` matters during `pulumi preview`, where a not-yet-created\n * resource's outputs have no value: it resolves to Pulumi's unknown sentinel\n * instead of throwing, so a program that reads outputs still previews cleanly.\n *\n * @param output - The Output to resolve.\n * @returns An Effect yielding the settled value, failing with\n * {@link PulumiError} if the underlying promise rejects.\n *\n * @example\n * ```ts\n * const bucket = yield* eaws.s3.Bucket(\"assets\", {});\n * const id = yield* fromOutput(bucket.id); // string\n * ```\n *\n * @remarks Reading an Output only makes sense inside a running Pulumi program.\n * During `preview` the value may be the unknown sentinel rather than real data,\n * so don't branch on it to decide what to create.\n */\nexport const fromOutput = <T>(\n output: pulumi.Output<T>\n): Effect.Effect<T, PulumiError> =>\n Effect.tryPromise({\n try: () => (output as unknown as PromisableOutput<T>).promise(true),\n catch: (cause) => new PulumiError({ cause }),\n });\n\n/**\n * Lift a record of Outputs into a single Effect of the resolved record — use\n * this right after constructing a resource to grab several fields at once.\n *\n * Resolves them together via `pulumi.all`, so it costs one await rather than\n * one per field.\n *\n * @param outputs - A record whose values are all Outputs. Interfaces work as\n * well as object literals; the constraint is self-referential rather than\n * `Record<string, Output<any>>` precisely so interface-typed bags are accepted.\n * @returns An Effect yielding the same record with each value unwrapped.\n *\n * @example\n * ```ts\n * const bucket = yield* eaws.s3.Bucket(\"assets\", {});\n * const { id, arn } = yield* fromOutputs({ id: bucket.id, arn: bucket.arn });\n * ```\n */\nexport const fromOutputs = <T extends { [K in keyof T]: pulumi.Output<any> }>(\n outputs: T\n): Effect.Effect<{ [K in keyof T]: pulumi.Unwrap<T[K]> }, PulumiError> =>\n fromOutput(pulumi.all(outputs) as pulumi.Output<any>);\n","/**\n * effectify — auto-wrap a Pulumi provider package (e.g. @pulumi/aws,\n * @pulumi/cloudflare) so every resource constructor becomes an\n * Effect-returning factory, without the caller ever writing `Effect.sync`.\n *\n * Usage:\n *\n * import * as aws from \"@pulumi/aws\";\n * const eaws = effectify(aws);\n *\n * const program = Effect.gen(function* () {\n * const bucket = yield* eaws.s3.Bucket(\"my-bucket\", { forceDestroy: true });\n * // ^ Effect<aws.s3.Bucket, PulumiError> — no manual wrapping\n * });\n *\n * How it works:\n * - Every Pulumi resource class extends `pulumi.Resource` under the hood\n * (via CustomResource / ComponentResource). That's the runtime marker\n * used to tell \"this export is a resource constructor\" apart from \"this\n * export is a namespace object\" (e.g. `aws.s3`) or \"this export is an\n * invoke function\" (e.g. `aws.s3.getBucket`).\n * - Namespace objects get recursively proxied (lazily, memoized).\n * - CustomResource constructors get wrapped so any field in their args\n * object may *additionally* be an Effect — resolved (concurrently, they\n * are independent by construction) before construction. This is safe\n * because codegen guarantees CustomResource args are always\n * Record<string, Input<T>>.\n * - Wrapped constructors keep their static members: `Bucket.get(...)`,\n * `Bucket.isInstance(...)` and friends forward to the original class, so\n * the wrapped package can be the only import a program needs.\n * - ComponentResource constructors get wrapped with no arg-lifting — args\n * pass through exactly as declared, since component args aren't\n * guaranteed to be Input<T>-shaped (hand-authored, may do synchronous\n * work on a bare primitive inside the constructor).\n * - Invoke functions (`aws.s3.getBucket`) return an Effect instead of a\n * Promise. There is no runtime marker for \"this function is async\", so\n * the wrapper calls the function and inspects the result: a thenable\n * becomes an Effect, anything else is returned as-is. That means the\n * invoke *starts* at the call site (see the caveat on `wrapInvokeLike`);\n * `*Output` invoke variants return an Output, which is not thenable, so\n * they pass through untouched — matching the type-level mapping, which\n * only rewrites Promise-returning signatures.\n * - Everything else (enums, plain values, non-resource classes) passes\n * through untouched.\n *\n * Resource registration remains synchronous under the hood — Effect.try\n * runs its thunk immediately. This only removes hand-written wrapper\n * boilerplate, not Pulumi's execution model.\n */\n\nimport * as pulumi from \"@pulumi/pulumi\";\nimport { Effect } from \"effect\";\nimport { PulumiError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Runtime type guards\n// ---------------------------------------------------------------------------\n\nconst isResourceConstructor = (\n value: unknown\n): value is new (...args: any[]) => pulumi.Resource =>\n typeof value === \"function\" &&\n (value === (pulumi.Resource as unknown) ||\n value.prototype instanceof pulumi.Resource);\n\nconst isComponentResourceConstructor = (\n Ctor: Function\n): Ctor is new (...args: any[]) => pulumi.ComponentResource =>\n Ctor === (pulumi.ComponentResource as unknown) ||\n Ctor.prototype instanceof pulumi.ComponentResource;\n\n/** An object whose string-keyed properties we only ever *read*. Distinct from\n * `Record<string, unknown>`, which additionally claims the properties are\n * writable and that the object declares an index signature — neither is true\n * of a codegen'd `BucketArgs`, and neither is something this module relies on. */\ntype UnknownProps = { readonly [key: string]: unknown };\n\n/** Is this a namespace to recurse into? The narrowed type is only ever handed\n * to `effectifyInner`, which takes `object` — so claim exactly that and no\n * more. */\nconst isNamespace = (value: unknown): value is object =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** Is this an args object whose entries we can scan for Effects? Same runtime\n * check as `isNamespace`, but a different question, so it gets the narrowing\n * that question needs: `object` would make `Object.entries` infer `any` values\n * and silently drop the `isEffect` filter's type safety. */\nconst isArgsObject = (value: unknown): value is UnknownProps =>\n isNamespace(value);\n\n/** Note: `pulumi.Output` is deliberately not thenable, so `*Output` invoke\n * variants fail this check and pass through unwrapped — keeping the runtime\n * behaviour aligned with the type mapping, which only rewrites\n * Promise-returning signatures. */\nconst isPromiseLike = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\";\n\n// ---------------------------------------------------------------------------\n// Type-level mapping\n// ---------------------------------------------------------------------------\n\n/** Allow any field of a CustomResource args object to *additionally* be an\n * Effect. Homomorphic, so optional fields stay optional and plain\n * `Input<T>`/`Output<T>` values keep working untouched. */\ntype LiftedArgs<A> = A extends object\n ? { [K in keyof A]: A[K] | Effect.Effect<A[K], PulumiError> }\n : A;\n\n/** Apply `LiftedArgs` to the second constructor parameter (the args object),\n * leaving `name` and `opts` alone. Mapping over the parameter tuple\n * homomorphically preserves labels and optionality, so constructors whose\n * args are optional stay callable as `Bucket(\"name\")`. */\ntype LiftArgsParam<P extends readonly unknown[]> = {\n [K in keyof P]: K extends \"1\" ? LiftedArgs<P[K]> : P[K];\n};\n\n/** The class's static side, minus `prototype`: `keyof` on a constructor type\n * yields exactly the statics (own and inherited, e.g. codegen'd `get` and\n * `isInstance`), which the runtime wrapper forwards to the original class. */\ntype StaticMembers<T> = Omit<T, \"prototype\">;\n\n/**\n * The type of {@link effectify}'s result: `T` with every resource constructor\n * and every `Promise`-returning invoke rewritten, and everything else left\n * alone.\n *\n * The cases, in the order they are tried:\n *\n * | Input | Becomes |\n * | --------------------------- | ---------------------------------------------- |\n * | `ComponentResource` class | factory returning `Effect`, args **not** lifted |\n * | `CustomResource` class | factory returning `Effect`, args lifted |\n * | other class | unchanged |\n * | `(...) => Promise<R>` | `(...) => Effect<R, PulumiError>` |\n * | other function | unchanged (includes `*Output` invokes) |\n * | object | mapped recursively |\n * | anything else | unchanged |\n *\n * Statics survive on the wrapped constructors, so `Bucket.get` and\n * `Bucket.isInstance` remain callable.\n */\nexport type Effectify<T> = T extends abstract new (\n ...params: infer P\n) => infer R\n ? R extends pulumi.ComponentResource\n ? ((...params: P) => Effect.Effect<R, PulumiError>) & StaticMembers<T>\n : R extends pulumi.CustomResource\n ? ((...params: LiftArgsParam<P>) => Effect.Effect<R, PulumiError>) &\n StaticMembers<T>\n : T\n : T extends (...args: infer A) => Promise<infer R>\n ? (...args: A) => Effect.Effect<R, PulumiError>\n : T extends (...args: any[]) => any\n ? T\n : T extends object\n ? { [K in keyof T]: Effectify<T[K]> }\n : T;\n\n// ---------------------------------------------------------------------------\n// Runtime implementation\n// ---------------------------------------------------------------------------\n\nconst proxyCache = new WeakMap<object, unknown>();\n\nconst isEffect = (value: unknown): value is Effect.Effect<unknown, unknown> =>\n Effect.isEffect(value);\n\nfunction resolveLiftedArgs(args: unknown): Effect.Effect<unknown, PulumiError> {\n if (!isArgsObject(args)) {\n return Effect.succeed(args);\n }\n\n const effectEntries = Object.entries(args).filter(([, v]) => isEffect(v));\n\n if (effectEntries.length === 0) {\n return Effect.succeed(args);\n }\n\n // The arg Effects are independent of one another, so resolve them\n // concurrently — it matters when several of them await slow Outputs.\n return Effect.map(\n Effect.all(\n effectEntries.map(([key, effectValue]) =>\n Effect.map(\n effectValue as Effect.Effect<unknown, PulumiError>,\n (resolved) => [key, resolved] as const\n )\n ),\n { concurrency: \"unbounded\" }\n ),\n (resolved) => ({ ...args, ...Object.fromEntries(resolved) })\n );\n}\n\nfunction wrapCustomResourceCtor(\n Ctor: new (...args: any[]) => pulumi.CustomResource\n) {\n return (name: string, args?: unknown, opts?: unknown) =>\n Effect.gen(function* () {\n const resolvedArgs = yield* resolveLiftedArgs(args);\n return yield* Effect.try({\n try: () => new Ctor(name, resolvedArgs, opts),\n catch: (cause) => new PulumiError({ cause }),\n });\n });\n}\n\nfunction wrapComponentResourceCtor(\n Ctor: new (...args: any[]) => pulumi.ComponentResource\n) {\n return (name: string, args?: unknown, opts?: unknown) =>\n Effect.try({\n try: () => new Ctor(name, args, opts),\n catch: (cause) => new PulumiError({ cause }),\n });\n}\n\n/** Forward static members (codegen'd `get`, `isInstance`, …) from the class\n * onto the factory. The factory's own and inherited properties (`name`,\n * `length`, `call`, …) win; anything else falls through to the class, so new\n * statics keep working without being enumerated here. A bonus of forwarding\n * `prototype` is that `x instanceof wrapped` still works. */\nconst withStatics = <F extends object>(factory: F, Ctor: Function): F =>\n new Proxy(factory, {\n get: (target, prop, receiver) =>\n Reflect.has(target, prop)\n ? Reflect.get(target, prop, receiver)\n : Reflect.get(Ctor, prop),\n has: (target, prop) => Reflect.has(target, prop) || Reflect.has(Ctor, prop),\n });\n\nfunction wrapResourceCtor(Ctor: new (...args: any[]) => pulumi.Resource) {\n const factory = isComponentResourceConstructor(Ctor)\n ? wrapComponentResourceCtor(Ctor)\n : wrapCustomResourceCtor(\n Ctor as new (...args: any[]) => pulumi.CustomResource\n );\n return withStatics(factory, Ctor);\n}\n\n/** Turn a Promise-returning invoke into an Effect-returning one, leaving\n * synchronous functions' behaviour untouched.\n *\n * A Proxy over the original function (rather than a new function) so `name`,\n * `length`, own properties and prototype all survive; only the call itself is\n * intercepted.\n *\n * Caveat, stated openly: whether a function is async is only knowable by\n * calling it, so the invoke *starts* when the factory is called — the Effect\n * resolves an already-in-flight Promise rather than deferring the call. Two\n * consequences:\n * - `Effect.retry` re-awaits the same call instead of re-invoking. To\n * re-invoke per attempt, wrap the call site: `Effect.suspend(() =>\n * eaws.getAmi(args))`.\n * - A discarded Effect must not surface as an unhandled rejection, so the\n * rejection is pre-observed on a side branch before the Effect awaits it.\n */\nfunction wrapInvokeLike(fn: Function): Function {\n return new Proxy(fn, {\n apply(target, thisArg, args) {\n const result = Reflect.apply(target, thisArg, args);\n if (!isPromiseLike(result)) {\n return result;\n }\n result.then(undefined, () => {});\n return Effect.tryPromise({\n try: () => result as Promise<unknown>,\n catch: (cause) => new PulumiError({ cause }),\n });\n },\n });\n}\n\n/** Wrapped constructors are cached so repeated reads of the same property\n * hand back the same function — identity checks like\n * `eaws.s3.Bucket === eaws.s3.Bucket` hold, and the `get` and\n * `getOwnPropertyDescriptor` traps agree on a property's value. */\nconst wrapperCache = new WeakMap<object, unknown>();\n\nfunction effectifyValue(value: unknown): unknown {\n if (isResourceConstructor(value)) {\n const cached = wrapperCache.get(value);\n if (cached) return cached;\n const wrapped = wrapResourceCtor(value);\n wrapperCache.set(value, wrapped);\n return wrapped;\n }\n\n if (typeof value === \"function\") {\n const cached = wrapperCache.get(value);\n if (cached) return cached;\n const wrapped = wrapInvokeLike(value);\n wrapperCache.set(value, wrapped);\n return wrapped;\n }\n\n if (isNamespace(value)) {\n return effectifyInner(value);\n }\n\n return value; // plain value, enum member, type-only export\n}\n\nfunction effectifyInner<T extends object>(mod: T): Effectify<T> {\n const cached = proxyCache.get(mod);\n if (cached) return cached as Effectify<T>;\n\n // The proxy target is a fresh plain object rather than `mod` itself: ES\n // module namespace objects (and @pulumi/aws's lazily-defined namespace\n // getters) expose non-configurable own properties, and a `get` trap that\n // returns a wrapper instead of the real value would violate the proxy\n // invariants for those. Forwarding to `mod` from a closure sidesteps that\n // entirely while keeping the lazy-loading behaviour intact.\n const proxy = new Proxy(Object.create(null) as T, {\n get(_target, prop) {\n return effectifyValue(Reflect.get(mod, prop));\n },\n has(_target, prop) {\n return Reflect.has(mod, prop);\n },\n ownKeys() {\n return Reflect.ownKeys(mod);\n },\n getOwnPropertyDescriptor(_target, prop) {\n const descriptor = Reflect.getOwnPropertyDescriptor(mod, prop);\n if (!descriptor) return undefined;\n // Must be reported as configurable — the target does not actually have\n // the property, so claiming otherwise breaks the proxy invariants.\n return {\n value: effectifyValue(Reflect.get(mod, prop)),\n enumerable: descriptor.enumerable,\n configurable: true,\n writable: true,\n };\n },\n set() {\n return false; // the wrapper is read-only\n },\n }) as Effectify<T>;\n\n proxyCache.set(mod, proxy);\n return proxy;\n}\n\n/**\n * Wrap a provider package (or any namespace) once, turning every resource\n * constructor into an `Effect`-returning factory and every `Promise`-returning\n * invoke into an `Effect`-returning function.\n *\n * Call this once per package at module scope and export the result — the\n * wrapper is cached, so repeated calls and repeated property reads hand back\n * the same objects, but there is no reason to re-wrap.\n *\n * @param mod - The provider package, or any namespace within one. Not mutated;\n * the result is a read-only proxy that forwards to it.\n * @returns A same-shaped view of `mod`, typed by {@link Effectify}.\n *\n * @example Constructing a resource\n * ```ts\n * import * as aws from \"@pulumi/aws\";\n * const eaws = effectify(aws);\n *\n * const program = Effect.gen(function* () {\n * const bucket = yield* eaws.s3.Bucket(\"assets\", { forceDestroy: true });\n * return bucket.id;\n * });\n * ```\n *\n * @example Passing an Effect as an argument\n * A `CustomResource`'s args may hold Effects, which are resolved concurrently\n * before the resource is constructed:\n * ```ts\n * yield* eaws.s3.BucketObject(\"readme\", {\n * bucket: bucketIdEffect,\n * content: \"hello\",\n * });\n * ```\n *\n * @throws Nothing. Failures surface in the returned Effect's error channel as\n * {@link PulumiError} — including synchronous throws from the constructor.\n *\n * @see {@link Effectify} for the type-level mapping.\n */\nexport function effectify<T extends object>(mod: T): Effectify<T> {\n return effectifyInner(mod);\n}\n","import type {\n ConfigMap,\n DestroyOptions,\n DestroyResult,\n LocalWorkspaceOptions,\n OutputMap,\n PreviewOptions,\n PreviewResult,\n PulumiFn,\n RefreshOptions,\n RefreshResult,\n RemoveOptions,\n Stack,\n UpOptions,\n UpResult,\n} from \"@pulumi/pulumi/automation/index.js\";\nimport { LocalWorkspace } from \"@pulumi/pulumi/automation/index.js\";\nimport { Effect } from \"effect\";\nimport { AutomationError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Primitives\n//\n// Each wraps one Automation API call, tagging failures with the stage they\n// came from. They are exported individually so callers can assemble their own\n// lifecycle — `deploy` below is only the common path.\n//\n// Every operation takes the matching Pulumi options type. That includes\n// `onOutput`: pass it to stream the CLI's progress as it happens. Without it\n// nothing is printed during what may be a multi-minute operation (the text is\n// still captured on the result's `stdout`, and on the error when one is\n// thrown, but only once the operation has finished).\n// ---------------------------------------------------------------------------\n\n/** Arguments for an inline program — the Pulumi program is a function in this\n * process, with no `Pulumi.yaml` on disk. */\nexport interface InlineStackOptions {\n /** Stack to select, created if absent. */\n readonly stackName: string;\n /** Project name to register the stack under. Chosen freely here, since\n * there is no `Pulumi.yaml` to take it from — but it is part of the stack's\n * identity in the backend, so changing it later points at a different\n * stack. */\n readonly projectName: string;\n /** The program itself. Runs in this process, so it needs no separate Node\n * runtime and can close over values from the caller. */\n readonly program: PulumiFn;\n readonly workspaceOptions?: LocalWorkspaceOptions;\n}\n\n/** Arguments for a local program — an existing Pulumi project on disk. */\nexport interface LocalStackOptions {\n /** Stack to select, created if absent. */\n readonly stackName: string;\n /** Directory holding the project's `Pulumi.yaml`. Its `name:` supplies the\n * project name, which is why there is no `projectName` here. */\n readonly workDir: string;\n readonly workspaceOptions?: LocalWorkspaceOptions;\n}\n\n/** Either flavour of stack. Discriminated at runtime by the presence of\n * `workDir`, so the two are not interchangeable: an inline program needs\n * `projectName`, a local one takes it from `Pulumi.yaml`. */\nexport type StackOptions = InlineStackOptions | LocalStackOptions;\n\nconst isLocal = (opts: StackOptions): opts is LocalStackOptions =>\n \"workDir\" in opts;\n\n/** Select the stack, creating it if it does not exist, and return the handle\n * every other operation here takes.\n *\n * Creating the workspace is itself work — it may write files and shell out to\n * the CLI — so hold on to the returned `Stack` rather than re-selecting before\n * each operation. */\nexport const createOrSelectStack = (\n opts: StackOptions\n): Effect.Effect<Stack, AutomationError> =>\n Effect.tryPromise({\n try: () =>\n isLocal(opts)\n ? LocalWorkspace.createOrSelectStack(\n { stackName: opts.stackName, workDir: opts.workDir },\n opts.workspaceOptions\n )\n : LocalWorkspace.createOrSelectStack(\n {\n stackName: opts.stackName,\n projectName: opts.projectName,\n program: opts.program,\n },\n opts.workspaceOptions\n ),\n catch: (cause) =>\n new AutomationError({ stage: \"createOrSelectStack\", cause }),\n });\n\n/** Apply the whole config map in one `setAllConfig` call — a single CLI\n * round-trip, where per-key `setConfig` costs one `pulumi config set`\n * invocation each. */\nexport const setStackConfig = (\n stack: Stack,\n config: ConfigMap | undefined\n): Effect.Effect<void, AutomationError> =>\n !config || Object.keys(config).length === 0\n ? Effect.void\n : Effect.tryPromise({\n try: () => stack.setAllConfig(config),\n catch: (cause) => new AutomationError({ stage: \"setConfig\", cause }),\n });\n\n/** Compute the plan without applying it.\n *\n * A preview is a full engine run against the provider, not a cheap check — see\n * {@link DeployOptions.preview} before pairing one with an `up`. */\nexport const previewStack = (\n stack: Stack,\n opts?: PreviewOptions\n): Effect.Effect<PreviewResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.preview(opts),\n catch: (cause) => new AutomationError({ stage: \"preview\", cause }),\n });\n\n/** Apply the program: create, update and delete resources to match it.\n *\n * The result carries the stack's outputs and a summary; pass `onOutput` to\n * watch progress while it runs. */\nexport const upStack = (\n stack: Stack,\n opts?: UpOptions\n): Effect.Effect<UpResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.up(opts),\n catch: (cause) => new AutomationError({ stage: \"up\", cause }),\n });\n\n/** Refresh the stack's state from the actual cloud resources, without\n * changing them — what to run when state may have drifted (manual console\n * edits, a crashed update) before deciding what to do about it. */\nexport const refreshStack = (\n stack: Stack,\n opts?: RefreshOptions\n): Effect.Effect<RefreshResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.refresh(opts),\n catch: (cause) => new AutomationError({ stage: \"refresh\", cause }),\n });\n\n/** Read the stack's current outputs without running an update. */\nexport const stackOutputs = (\n stack: Stack\n): Effect.Effect<OutputMap, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.outputs(),\n catch: (cause) => new AutomationError({ stage: \"outputs\", cause }),\n });\n\n/** Destroy the stack's resources. The stack itself remains registered with\n * the backend — see `removeStack` / `teardownStack` to delete it too. */\nexport const destroyStack = (\n stack: Stack,\n opts?: DestroyOptions\n): Effect.Effect<DestroyResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.destroy(opts),\n catch: (cause) => new AutomationError({ stage: \"destroy\", cause }),\n });\n\n/** Delete the stack and its configuration and history from the backend.\n *\n * This does not destroy resources — run `destroyStack` first, or use\n * `teardownStack`. Pulumi refuses to remove a stack that still has resources\n * unless `RemoveOptions.force` is set, and forcing it orphans them: they keep\n * existing and billing with nothing tracking them. */\nexport const removeStack = (\n stack: Stack,\n opts?: RemoveOptions\n): Effect.Effect<void, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.workspace.removeStack(stack.name, opts),\n catch: (cause) => new AutomationError({ stage: \"removeStack\", cause }),\n });\n\n/** Full teardown: destroy the resources, then delete the stack.\n *\n * `destroyStack` alone leaves an empty stack behind, so anything creating\n * stacks per-run (ephemeral environments, tests naming stacks by timestamp)\n * accumulates them in the backend. */\nexport const teardownStack = (\n stack: Stack,\n opts?: { readonly destroy?: DestroyOptions; readonly remove?: RemoveOptions }\n): Effect.Effect<DestroyResult, AutomationError> =>\n Effect.gen(function* () {\n const result = yield* destroyStack(stack, opts?.destroy);\n yield* removeStack(stack, opts?.remove);\n return result;\n });\n\n// ---------------------------------------------------------------------------\n// Convenience lifecycle\n// ---------------------------------------------------------------------------\n\n/** {@link deploy}'s arguments: the stack to target, plus what to do with it. */\nexport type DeployOptions = StackOptions & {\n /** Config to apply before the update, in one `setAllConfig` call. Keys are\n * fully qualified (`\"my-project:myKey\"`). */\n readonly config?: ConfigMap;\n /** Options forwarded to the update — `onOutput` to stream progress,\n * `parallel`, `target`, and so on. */\n readonly up?: UpOptions;\n /** Run `preview` before `up`, returning its result.\n *\n * Off by default: a preview is a full engine run against the provider, so\n * previewing and then immediately upping does the work twice. `up` reports\n * the same failures, so this earns its cost only when you want the plan\n * itself. */\n readonly preview?: PreviewOptions | boolean;\n};\n\n/** What {@link deploy} hands back. */\nexport interface DeployResult {\n /** The selected stack, so teardown needs no second `createOrSelectStack`. */\n readonly stack: Stack;\n /** The update's result — `outputs` and `summary` live here. */\n readonly result: UpResult;\n /** Present only when `preview` was requested. */\n readonly preview?: PreviewResult;\n}\n\n/**\n * Select or create the stack, apply config, optionally preview, then up.\n *\n * The common path, assembled from the primitives above. Anything more\n * involved — refreshing first, inspecting the plan before deciding, retrying a\n * stage — should compose those directly rather than grow options here.\n *\n * @param opts - Which stack, and what to do with it.\n * @returns The stack handle alongside the results, so callers can tear down\n * afterwards without re-selecting.\n *\n * @example Deploy, use the outputs, then always tear down\n * ```ts\n * Effect.scoped(\n * Effect.gen(function* () {\n * const { result } = yield* Effect.acquireRelease(\n * deploy({ stackName, projectName, program, up: { onOutput } }),\n * ({ stack }) => teardownStack(stack).pipe(Effect.ignore)\n * );\n * return result.outputs.bucketId?.value;\n * })\n * );\n * ```\n */\nexport const deploy = (\n opts: DeployOptions\n): Effect.Effect<DeployResult, AutomationError> =>\n Effect.gen(function* () {\n const stack = yield* createOrSelectStack(opts);\n yield* setStackConfig(stack, opts.config);\n\n const preview = opts.preview\n ? yield* previewStack(\n stack,\n typeof opts.preview === \"boolean\" ? undefined : opts.preview\n )\n : undefined;\n\n const result = yield* upStack(stack, opts.up);\n return { stack, result, preview };\n });\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/output-bridge.ts","../src/effectify.ts","../src/automation.ts"],"names":["pulumi","Effect"],"mappings":"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","file":"index.js","sourcesContent":["import { Data } from \"effect\";\n\nconst describeCause = (cause: unknown): string =>\n cause instanceof Error ? cause.message : String(cause);\n\n/**\n * Any synchronous failure constructing a resource (bad args, provider\n * validation, etc.), or a failure resolving an Output's promise.\n *\n * Tagged `\"PulumiError\"`, so it can be matched by tag rather than by\n * `instanceof`:\n *\n * @example\n * ```ts\n * program.pipe(\n * Effect.catchTag(\"PulumiError\", (e) => Effect.logError(e.message))\n * );\n * ```\n */\nexport class PulumiError extends Data.TaggedError(\"PulumiError\")<{\n /** The original thrown value or rejection reason, unwrapped and unmodified.\n * Not necessarily an `Error`. */\n readonly cause: unknown;\n}> {\n /** Derived so anything reading `.message` - plain logging, test failure\n * output, non-Effect error handling - sees the underlying failure instead\n * of an empty string. */\n get message(): string {\n return describeCause(this.cause);\n }\n}\n\n/**\n * Failure from an Automation API lifecycle call (up/preview/destroy/select).\n *\n * `stage` says which call failed, which matters most in the composite\n * operations: a failed `deploy` could have died selecting the stack, applying\n * config, or running the update, and the three want different responses.\n *\n * @example\n * ```ts\n * deploy(opts).pipe(\n * Effect.catchTag(\"AutomationError\", (e) =>\n * e.stage === \"createOrSelectStack\"\n * ? Effect.fail(new BackendUnreachable())\n * : Effect.logError(e.message)\n * )\n * );\n * ```\n */\nexport class AutomationError extends Data.TaggedError(\"AutomationError\")<{\n /** Which Automation API call failed. Named for the wrapper that raised it,\n * so `deploy`'s failures still report the underlying stage. */\n readonly stage:\n | \"createOrSelectStack\"\n | \"setConfig\"\n | \"up\"\n | \"preview\"\n | \"refresh\"\n | \"outputs\"\n | \"destroy\"\n | \"removeStack\";\n /** The rejection reason from the Automation API. For a failed update this is\n * usually a `CommandError` carrying the CLI's stdout and stderr. */\n readonly cause: unknown;\n}> {\n /** `\"<stage> failed: <cause>\"` - the stage is included because the cause\n * alone rarely says which operation produced it. */\n get message(): string {\n return `${this.stage} failed: ${describeCause(this.cause)}`;\n }\n}\n","import * as pulumi from \"@pulumi/pulumi\";\nimport { Effect } from \"effect\";\nimport { PulumiError } from \"./errors.js\";\n\n/** `Output.promise()` is how the Pulumi runtime itself gets a settled value out\n * of an Output, but it is not part of the public `Output<T>` surface. */\ninterface PromisableOutput<T> {\n promise(withUnknowns?: boolean): Promise<T>;\n}\n\n/**\n * Lift a single Output into an Effect.\n *\n * `withUnknowns: true` matters during `pulumi preview`, where a not-yet-created\n * resource's outputs have no value: it resolves to Pulumi's unknown sentinel\n * instead of throwing, so a program that reads outputs still previews cleanly.\n *\n * @param output - The Output to resolve.\n * @returns An Effect yielding the settled value, failing with\n * {@link PulumiError} if the underlying promise rejects.\n *\n * @example\n * ```ts\n * const bucket = yield* eaws.s3.Bucket(\"assets\", {});\n * const id = yield* fromOutput(bucket.id); // string\n * ```\n *\n * @remarks Reading an Output only makes sense inside a running Pulumi program.\n * During `preview` the value may be the unknown sentinel rather than real data,\n * so don't branch on it to decide what to create.\n */\nexport const fromOutput = <T>(\n output: pulumi.Output<T>\n): Effect.Effect<T, PulumiError> =>\n Effect.tryPromise({\n try: () => (output as unknown as PromisableOutput<T>).promise(true),\n catch: (cause) => new PulumiError({ cause }),\n });\n\n/**\n * Lift a record of Outputs into a single Effect of the resolved record - use\n * this right after constructing a resource to grab several fields at once.\n *\n * Resolves them together via `pulumi.all`, so it costs one await rather than\n * one per field.\n *\n * @param outputs - A record whose values are all Outputs. Interfaces work as\n * well as object literals; the constraint is self-referential rather than\n * `Record<string, Output<any>>` precisely so interface-typed bags are accepted.\n * @returns An Effect yielding the same record with each value unwrapped.\n *\n * @example\n * ```ts\n * const bucket = yield* eaws.s3.Bucket(\"assets\", {});\n * const { id, arn } = yield* fromOutputs({ id: bucket.id, arn: bucket.arn });\n * ```\n */\nexport const fromOutputs = <T extends { [K in keyof T]: pulumi.Output<any> }>(\n outputs: T\n): Effect.Effect<{ [K in keyof T]: pulumi.Unwrap<T[K]> }, PulumiError> =>\n fromOutput(pulumi.all(outputs) as pulumi.Output<any>);\n","/**\n * effectify - auto-wrap a Pulumi provider package (e.g. @pulumi/aws,\n * @pulumi/cloudflare) so every resource constructor becomes an\n * Effect-returning factory, without the caller ever writing `Effect.sync`.\n *\n * Usage:\n *\n * import * as aws from \"@pulumi/aws\";\n * const eaws = effectify(aws);\n *\n * const program = Effect.gen(function* () {\n * const bucket = yield* eaws.s3.Bucket(\"my-bucket\", { forceDestroy: true });\n * // ^ Effect<aws.s3.Bucket, PulumiError> - no manual wrapping\n * });\n *\n * How it works:\n * - Every Pulumi resource class extends `pulumi.Resource` under the hood\n * (via CustomResource / ComponentResource). That's the runtime marker\n * used to tell \"this export is a resource constructor\" apart from \"this\n * export is a namespace object\" (e.g. `aws.s3`) or \"this export is an\n * invoke function\" (e.g. `aws.s3.getBucket`).\n * - Namespace objects get recursively proxied (lazily, memoized).\n * - CustomResource constructors get wrapped so any field in their args\n * object may *additionally* be an Effect - resolved (concurrently, they\n * are independent by construction) before construction. This is safe\n * because codegen guarantees CustomResource args are always\n * Record<string, Input<T>>.\n * - Wrapped constructors keep their static members: `Bucket.get(...)`,\n * `Bucket.isInstance(...)` and friends forward to the original class, so\n * the wrapped package can be the only import a program needs.\n * - ComponentResource constructors get wrapped with no arg-lifting - args\n * pass through exactly as declared, since component args aren't\n * guaranteed to be Input<T>-shaped (hand-authored, may do synchronous\n * work on a bare primitive inside the constructor).\n * - Invoke functions (`aws.s3.getBucket`) return an Effect instead of a\n * Promise. There is no runtime marker for \"this function is async\", so\n * the wrapper calls the function and inspects the result: a thenable\n * becomes an Effect, anything else is returned as-is. That means the\n * invoke *starts* at the call site (see the caveat on `wrapInvokeLike`);\n * `*Output` invoke variants return an Output, which is not thenable, so\n * they pass through untouched - matching the type-level mapping, which\n * only rewrites Promise-returning signatures.\n * - Everything else (enums, plain values, non-resource classes) passes\n * through untouched.\n *\n * Resource registration remains synchronous under the hood - Effect.try\n * runs its thunk immediately. This only removes hand-written wrapper\n * boilerplate, not Pulumi's execution model.\n */\n\nimport * as pulumi from \"@pulumi/pulumi\";\nimport { Effect } from \"effect\";\nimport { PulumiError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Runtime type guards\n// ---------------------------------------------------------------------------\n\nconst isResourceConstructor = (\n value: unknown\n): value is new (...args: any[]) => pulumi.Resource =>\n typeof value === \"function\" &&\n (value === (pulumi.Resource as unknown) ||\n value.prototype instanceof pulumi.Resource);\n\nconst isComponentResourceConstructor = (\n Ctor: Function\n): Ctor is new (...args: any[]) => pulumi.ComponentResource =>\n Ctor === (pulumi.ComponentResource as unknown) ||\n Ctor.prototype instanceof pulumi.ComponentResource;\n\n/** An object whose string-keyed properties we only ever *read*. Distinct from\n * `Record<string, unknown>`, which additionally claims the properties are\n * writable and that the object declares an index signature - neither is true\n * of a codegen'd `BucketArgs`, and neither is something this module relies on. */\ntype UnknownProps = { readonly [key: string]: unknown };\n\n/** Is this a namespace to recurse into? The narrowed type is only ever handed\n * to `effectifyInner`, which takes `object` - so claim exactly that and no\n * more. */\nconst isNamespace = (value: unknown): value is object =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** Is this an args object whose entries we can scan for Effects? Same runtime\n * check as `isNamespace`, but a different question, so it gets the narrowing\n * that question needs: `object` would make `Object.entries` infer `any` values\n * and silently drop the `isEffect` filter's type safety. */\nconst isArgsObject = (value: unknown): value is UnknownProps =>\n isNamespace(value);\n\n/** Note: `pulumi.Output` is deliberately not thenable, so `*Output` invoke\n * variants fail this check and pass through unwrapped - keeping the runtime\n * behaviour aligned with the type mapping, which only rewrites\n * Promise-returning signatures. */\nconst isPromiseLike = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\";\n\n// ---------------------------------------------------------------------------\n// Type-level mapping\n// ---------------------------------------------------------------------------\n\n/** Allow any field of a CustomResource args object to *additionally* be an\n * Effect. Homomorphic, so optional fields stay optional and plain\n * `Input<T>`/`Output<T>` values keep working untouched. */\ntype LiftedArgs<A> = A extends object\n ? { [K in keyof A]: A[K] | Effect.Effect<A[K], PulumiError> }\n : A;\n\n/** Apply `LiftedArgs` to the second constructor parameter (the args object),\n * leaving `name` and `opts` alone. Mapping over the parameter tuple\n * homomorphically preserves labels and optionality, so constructors whose\n * args are optional stay callable as `Bucket(\"name\")`. */\ntype LiftArgsParam<P extends readonly unknown[]> = {\n [K in keyof P]: K extends \"1\" ? LiftedArgs<P[K]> : P[K];\n};\n\n/** The class's static side, minus `prototype`: `keyof` on a constructor type\n * yields exactly the statics (own and inherited, e.g. codegen'd `get` and\n * `isInstance`), which the runtime wrapper forwards to the original class. */\ntype StaticMembers<T> = Omit<T, \"prototype\">;\n\n/**\n * The type of {@link effectify}'s result: `T` with every resource constructor\n * and every `Promise`-returning invoke rewritten, and everything else left\n * alone.\n *\n * The cases, in the order they are tried:\n *\n * | Input | Becomes |\n * | --------------------------- | ---------------------------------------------- |\n * | `ComponentResource` class | factory returning `Effect`, args **not** lifted |\n * | `CustomResource` class | factory returning `Effect`, args lifted |\n * | other class | unchanged |\n * | `(...) => Promise<R>` | `(...) => Effect<R, PulumiError>` |\n * | other function | unchanged (includes `*Output` invokes) |\n * | object | mapped recursively |\n * | anything else | unchanged |\n *\n * Statics survive on the wrapped constructors, so `Bucket.get` and\n * `Bucket.isInstance` remain callable.\n */\nexport type Effectify<T> = T extends abstract new (\n ...params: infer P\n) => infer R\n ? R extends pulumi.ComponentResource\n ? ((...params: P) => Effect.Effect<R, PulumiError>) & StaticMembers<T>\n : R extends pulumi.CustomResource\n ? ((...params: LiftArgsParam<P>) => Effect.Effect<R, PulumiError>) &\n StaticMembers<T>\n : T\n : T extends (...args: infer A) => Promise<infer R>\n ? (...args: A) => Effect.Effect<R, PulumiError>\n : T extends (...args: any[]) => any\n ? T\n : T extends object\n ? { [K in keyof T]: Effectify<T[K]> }\n : T;\n\n// ---------------------------------------------------------------------------\n// Runtime implementation\n// ---------------------------------------------------------------------------\n\nconst proxyCache = new WeakMap<object, unknown>();\n\nconst isEffect = (value: unknown): value is Effect.Effect<unknown, unknown> =>\n Effect.isEffect(value);\n\nfunction resolveLiftedArgs(args: unknown): Effect.Effect<unknown, PulumiError> {\n if (!isArgsObject(args)) {\n return Effect.succeed(args);\n }\n\n const effectEntries = Object.entries(args).filter(([, v]) => isEffect(v));\n\n if (effectEntries.length === 0) {\n return Effect.succeed(args);\n }\n\n // The arg Effects are independent of one another, so resolve them\n // concurrently - it matters when several of them await slow Outputs.\n return Effect.map(\n Effect.all(\n effectEntries.map(([key, effectValue]) =>\n Effect.map(\n effectValue as Effect.Effect<unknown, PulumiError>,\n (resolved) => [key, resolved] as const\n )\n ),\n { concurrency: \"unbounded\" }\n ),\n (resolved) => ({ ...args, ...Object.fromEntries(resolved) })\n );\n}\n\nfunction wrapCustomResourceCtor(\n Ctor: new (...args: any[]) => pulumi.CustomResource\n) {\n return (name: string, args?: unknown, opts?: unknown) =>\n Effect.gen(function* () {\n const resolvedArgs = yield* resolveLiftedArgs(args);\n return yield* Effect.try({\n try: () => new Ctor(name, resolvedArgs, opts),\n catch: (cause) => new PulumiError({ cause }),\n });\n });\n}\n\nfunction wrapComponentResourceCtor(\n Ctor: new (...args: any[]) => pulumi.ComponentResource\n) {\n return (name: string, args?: unknown, opts?: unknown) =>\n Effect.try({\n try: () => new Ctor(name, args, opts),\n catch: (cause) => new PulumiError({ cause }),\n });\n}\n\n/** Forward static members (codegen'd `get`, `isInstance`, …) from the class\n * onto the factory. The factory's own and inherited properties (`name`,\n * `length`, `call`, …) win; anything else falls through to the class, so new\n * statics keep working without being enumerated here. A bonus of forwarding\n * `prototype` is that `x instanceof wrapped` still works. */\nconst withStatics = <F extends object>(factory: F, Ctor: Function): F =>\n new Proxy(factory, {\n get: (target, prop, receiver) =>\n Reflect.has(target, prop)\n ? Reflect.get(target, prop, receiver)\n : Reflect.get(Ctor, prop),\n has: (target, prop) => Reflect.has(target, prop) || Reflect.has(Ctor, prop),\n });\n\nfunction wrapResourceCtor(Ctor: new (...args: any[]) => pulumi.Resource) {\n const factory = isComponentResourceConstructor(Ctor)\n ? wrapComponentResourceCtor(Ctor)\n : wrapCustomResourceCtor(\n Ctor as new (...args: any[]) => pulumi.CustomResource\n );\n return withStatics(factory, Ctor);\n}\n\n/** Turn a Promise-returning invoke into an Effect-returning one, leaving\n * synchronous functions' behaviour untouched.\n *\n * A Proxy over the original function (rather than a new function) so `name`,\n * `length`, own properties and prototype all survive; only the call itself is\n * intercepted.\n *\n * Caveat, stated openly: whether a function is async is only knowable by\n * calling it, so the invoke *starts* when the factory is called - the Effect\n * resolves an already-in-flight Promise rather than deferring the call. Two\n * consequences:\n * - `Effect.retry` re-awaits the same call instead of re-invoking. To\n * re-invoke per attempt, wrap the call site: `Effect.suspend(() =>\n * eaws.getAmi(args))`.\n * - A discarded Effect must not surface as an unhandled rejection, so the\n * rejection is pre-observed on a side branch before the Effect awaits it.\n */\nfunction wrapInvokeLike(fn: Function): Function {\n return new Proxy(fn, {\n apply(target, thisArg, args) {\n const result = Reflect.apply(target, thisArg, args);\n if (!isPromiseLike(result)) {\n return result;\n }\n result.then(undefined, () => {});\n return Effect.tryPromise({\n try: () => result as Promise<unknown>,\n catch: (cause) => new PulumiError({ cause }),\n });\n },\n });\n}\n\n/** Wrapped constructors are cached so repeated reads of the same property\n * hand back the same function - identity checks like\n * `eaws.s3.Bucket === eaws.s3.Bucket` hold, and the `get` and\n * `getOwnPropertyDescriptor` traps agree on a property's value. */\nconst wrapperCache = new WeakMap<object, unknown>();\n\nfunction effectifyValue(value: unknown): unknown {\n if (isResourceConstructor(value)) {\n const cached = wrapperCache.get(value);\n if (cached) return cached;\n const wrapped = wrapResourceCtor(value);\n wrapperCache.set(value, wrapped);\n return wrapped;\n }\n\n if (typeof value === \"function\") {\n const cached = wrapperCache.get(value);\n if (cached) return cached;\n const wrapped = wrapInvokeLike(value);\n wrapperCache.set(value, wrapped);\n return wrapped;\n }\n\n if (isNamespace(value)) {\n return effectifyInner(value);\n }\n\n return value; // plain value, enum member, type-only export\n}\n\nfunction effectifyInner<T extends object>(mod: T): Effectify<T> {\n const cached = proxyCache.get(mod);\n if (cached) return cached as Effectify<T>;\n\n // The proxy target is a fresh plain object rather than `mod` itself: ES\n // module namespace objects (and @pulumi/aws's lazily-defined namespace\n // getters) expose non-configurable own properties, and a `get` trap that\n // returns a wrapper instead of the real value would violate the proxy\n // invariants for those. Forwarding to `mod` from a closure sidesteps that\n // entirely while keeping the lazy-loading behaviour intact.\n const proxy = new Proxy(Object.create(null) as T, {\n get(_target, prop) {\n return effectifyValue(Reflect.get(mod, prop));\n },\n has(_target, prop) {\n return Reflect.has(mod, prop);\n },\n ownKeys() {\n return Reflect.ownKeys(mod);\n },\n getOwnPropertyDescriptor(_target, prop) {\n const descriptor = Reflect.getOwnPropertyDescriptor(mod, prop);\n if (!descriptor) return undefined;\n // Must be reported as configurable - the target does not actually have\n // the property, so claiming otherwise breaks the proxy invariants.\n return {\n value: effectifyValue(Reflect.get(mod, prop)),\n enumerable: descriptor.enumerable,\n configurable: true,\n writable: true,\n };\n },\n set() {\n return false; // the wrapper is read-only\n },\n }) as Effectify<T>;\n\n proxyCache.set(mod, proxy);\n return proxy;\n}\n\n/**\n * Wrap a provider package (or any namespace) once, turning every resource\n * constructor into an `Effect`-returning factory and every `Promise`-returning\n * invoke into an `Effect`-returning function.\n *\n * Call this once per package at module scope and export the result - the\n * wrapper is cached, so repeated calls and repeated property reads hand back\n * the same objects, but there is no reason to re-wrap.\n *\n * @param mod - The provider package, or any namespace within one. Not mutated;\n * the result is a read-only proxy that forwards to it.\n * @returns A same-shaped view of `mod`, typed by {@link Effectify}.\n *\n * @example Constructing a resource\n * ```ts\n * import * as aws from \"@pulumi/aws\";\n * const eaws = effectify(aws);\n *\n * const program = Effect.gen(function* () {\n * const bucket = yield* eaws.s3.Bucket(\"assets\", { forceDestroy: true });\n * return bucket.id;\n * });\n * ```\n *\n * @example Passing an Effect as an argument\n * A `CustomResource`'s args may hold Effects, which are resolved concurrently\n * before the resource is constructed:\n * ```ts\n * yield* eaws.s3.BucketObject(\"readme\", {\n * bucket: bucketIdEffect,\n * content: \"hello\",\n * });\n * ```\n *\n * @throws Nothing. Failures surface in the returned Effect's error channel as\n * {@link PulumiError} - including synchronous throws from the constructor.\n *\n * @see {@link Effectify} for the type-level mapping.\n */\nexport function effectify<T extends object>(mod: T): Effectify<T> {\n return effectifyInner(mod);\n}\n","import type {\n ConfigMap,\n DestroyOptions,\n DestroyResult,\n LocalWorkspaceOptions,\n OutputMap,\n PreviewOptions,\n PreviewResult,\n PulumiFn,\n RefreshOptions,\n RefreshResult,\n RemoveOptions,\n Stack,\n UpOptions,\n UpResult,\n} from \"@pulumi/pulumi/automation/index.js\";\nimport { LocalWorkspace } from \"@pulumi/pulumi/automation/index.js\";\nimport { Effect } from \"effect\";\nimport { AutomationError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Primitives\n//\n// Each wraps one Automation API call, tagging failures with the stage they\n// came from. They are exported individually so callers can assemble their own\n// lifecycle - `deploy` below is only the common path.\n//\n// Every operation takes the matching Pulumi options type. That includes\n// `onOutput`: pass it to stream the CLI's progress as it happens. Without it\n// nothing is printed during what may be a multi-minute operation (the text is\n// still captured on the result's `stdout`, and on the error when one is\n// thrown, but only once the operation has finished).\n// ---------------------------------------------------------------------------\n\n/** Arguments for an inline program - the Pulumi program is a function in this\n * process, with no `Pulumi.yaml` on disk. */\nexport interface InlineStackOptions {\n /** Stack to select, created if absent. */\n readonly stackName: string;\n /** Project name to register the stack under. Chosen freely here, since\n * there is no `Pulumi.yaml` to take it from - but it is part of the stack's\n * identity in the backend, so changing it later points at a different\n * stack. */\n readonly projectName: string;\n /** The program itself. Runs in this process, so it needs no separate Node\n * runtime and can close over values from the caller. */\n readonly program: PulumiFn;\n readonly workspaceOptions?: LocalWorkspaceOptions;\n}\n\n/** Arguments for a local program - an existing Pulumi project on disk. */\nexport interface LocalStackOptions {\n /** Stack to select, created if absent. */\n readonly stackName: string;\n /** Directory holding the project's `Pulumi.yaml`. Its `name:` supplies the\n * project name, which is why there is no `projectName` here. */\n readonly workDir: string;\n readonly workspaceOptions?: LocalWorkspaceOptions;\n}\n\n/** Either flavour of stack. Discriminated at runtime by the presence of\n * `workDir`, so the two are not interchangeable: an inline program needs\n * `projectName`, a local one takes it from `Pulumi.yaml`. */\nexport type StackOptions = InlineStackOptions | LocalStackOptions;\n\nconst isLocal = (opts: StackOptions): opts is LocalStackOptions =>\n \"workDir\" in opts;\n\n/** Select the stack, creating it if it does not exist, and return the handle\n * every other operation here takes.\n *\n * Creating the workspace is itself work - it may write files and shell out to\n * the CLI - so hold on to the returned `Stack` rather than re-selecting before\n * each operation. */\nexport const createOrSelectStack = (\n opts: StackOptions\n): Effect.Effect<Stack, AutomationError> =>\n Effect.tryPromise({\n try: () =>\n isLocal(opts)\n ? LocalWorkspace.createOrSelectStack(\n { stackName: opts.stackName, workDir: opts.workDir },\n opts.workspaceOptions\n )\n : LocalWorkspace.createOrSelectStack(\n {\n stackName: opts.stackName,\n projectName: opts.projectName,\n program: opts.program,\n },\n opts.workspaceOptions\n ),\n catch: (cause) =>\n new AutomationError({ stage: \"createOrSelectStack\", cause }),\n });\n\n/** Apply the whole config map in one `setAllConfig` call - a single CLI\n * round-trip, where per-key `setConfig` costs one `pulumi config set`\n * invocation each. */\nexport const setStackConfig = (\n stack: Stack,\n config: ConfigMap | undefined\n): Effect.Effect<void, AutomationError> =>\n !config || Object.keys(config).length === 0\n ? Effect.void\n : Effect.tryPromise({\n try: () => stack.setAllConfig(config),\n catch: (cause) => new AutomationError({ stage: \"setConfig\", cause }),\n });\n\n/** Compute the plan without applying it.\n *\n * A preview is a full engine run against the provider, not a cheap check - see\n * {@link DeployOptions.preview} before pairing one with an `up`. */\nexport const previewStack = (\n stack: Stack,\n opts?: PreviewOptions\n): Effect.Effect<PreviewResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.preview(opts),\n catch: (cause) => new AutomationError({ stage: \"preview\", cause }),\n });\n\n/** Apply the program: create, update and delete resources to match it.\n *\n * The result carries the stack's outputs and a summary; pass `onOutput` to\n * watch progress while it runs. */\nexport const upStack = (\n stack: Stack,\n opts?: UpOptions\n): Effect.Effect<UpResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.up(opts),\n catch: (cause) => new AutomationError({ stage: \"up\", cause }),\n });\n\n/** Refresh the stack's state from the actual cloud resources, without\n * changing them - what to run when state may have drifted (manual console\n * edits, a crashed update) before deciding what to do about it. */\nexport const refreshStack = (\n stack: Stack,\n opts?: RefreshOptions\n): Effect.Effect<RefreshResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.refresh(opts),\n catch: (cause) => new AutomationError({ stage: \"refresh\", cause }),\n });\n\n/** Read the stack's current outputs without running an update. */\nexport const stackOutputs = (\n stack: Stack\n): Effect.Effect<OutputMap, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.outputs(),\n catch: (cause) => new AutomationError({ stage: \"outputs\", cause }),\n });\n\n/** Destroy the stack's resources. The stack itself remains registered with\n * the backend - see `removeStack` / `teardownStack` to delete it too. */\nexport const destroyStack = (\n stack: Stack,\n opts?: DestroyOptions\n): Effect.Effect<DestroyResult, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.destroy(opts),\n catch: (cause) => new AutomationError({ stage: \"destroy\", cause }),\n });\n\n/** Delete the stack and its configuration and history from the backend.\n *\n * This does not destroy resources - run `destroyStack` first, or use\n * `teardownStack`. Pulumi refuses to remove a stack that still has resources\n * unless `RemoveOptions.force` is set, and forcing it orphans them: they keep\n * existing and billing with nothing tracking them. */\nexport const removeStack = (\n stack: Stack,\n opts?: RemoveOptions\n): Effect.Effect<void, AutomationError> =>\n Effect.tryPromise({\n try: () => stack.workspace.removeStack(stack.name, opts),\n catch: (cause) => new AutomationError({ stage: \"removeStack\", cause }),\n });\n\n/** Full teardown: destroy the resources, then delete the stack.\n *\n * `destroyStack` alone leaves an empty stack behind, so anything creating\n * stacks per-run (ephemeral environments, tests naming stacks by timestamp)\n * accumulates them in the backend. */\nexport const teardownStack = (\n stack: Stack,\n opts?: { readonly destroy?: DestroyOptions; readonly remove?: RemoveOptions }\n): Effect.Effect<DestroyResult, AutomationError> =>\n Effect.gen(function* () {\n const result = yield* destroyStack(stack, opts?.destroy);\n yield* removeStack(stack, opts?.remove);\n return result;\n });\n\n// ---------------------------------------------------------------------------\n// Convenience lifecycle\n// ---------------------------------------------------------------------------\n\n/** {@link deploy}'s arguments: the stack to target, plus what to do with it. */\nexport type DeployOptions = StackOptions & {\n /** Config to apply before the update, in one `setAllConfig` call. Keys are\n * fully qualified (`\"my-project:myKey\"`). */\n readonly config?: ConfigMap;\n /** Options forwarded to the update - `onOutput` to stream progress,\n * `parallel`, `target`, and so on. */\n readonly up?: UpOptions;\n /** Run `preview` before `up`, returning its result.\n *\n * Off by default: a preview is a full engine run against the provider, so\n * previewing and then immediately upping does the work twice. `up` reports\n * the same failures, so this earns its cost only when you want the plan\n * itself. */\n readonly preview?: PreviewOptions | boolean;\n};\n\n/** What {@link deploy} hands back. */\nexport interface DeployResult {\n /** The selected stack, so teardown needs no second `createOrSelectStack`. */\n readonly stack: Stack;\n /** The update's result - `outputs` and `summary` live here. */\n readonly result: UpResult;\n /** Present only when `preview` was requested. */\n readonly preview?: PreviewResult;\n}\n\n/**\n * Select or create the stack, apply config, optionally preview, then up.\n *\n * The common path, assembled from the primitives above. Anything more\n * involved - refreshing first, inspecting the plan before deciding, retrying a\n * stage - should compose those directly rather than grow options here.\n *\n * @param opts - Which stack, and what to do with it.\n * @returns The stack handle alongside the results, so callers can tear down\n * afterwards without re-selecting.\n *\n * @example Deploy, use the outputs, then always tear down\n * ```ts\n * Effect.scoped(\n * Effect.gen(function* () {\n * const { result } = yield* Effect.acquireRelease(\n * deploy({ stackName, projectName, program, up: { onOutput } }),\n * ({ stack }) => teardownStack(stack).pipe(Effect.ignore)\n * );\n * return result.outputs.bucketId?.value;\n * })\n * );\n * ```\n */\nexport const deploy = (\n opts: DeployOptions\n): Effect.Effect<DeployResult, AutomationError> =>\n Effect.gen(function* () {\n const stack = yield* createOrSelectStack(opts);\n yield* setStackConfig(stack, opts.config);\n\n const preview = opts.preview\n ? yield* previewStack(\n stack,\n typeof opts.preview === \"boolean\" ? undefined : opts.preview\n )\n : undefined;\n\n const result = yield* upStack(stack, opts.up);\n return { stack, result, preview };\n });\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effect-pulumi",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Effect bindings for Pulumi
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Effect bindings for Pulumi - wrap a provider package once and get Effect-returning resource factories, typed errors, and structured deploy results.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"effect",
|
|
7
7
|
"effect-ts",
|