@michaelrwalker/stagehand 0.1.0 → 0.3.0
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 +221 -71
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +14 -2
- package/dist/context.js.map +1 -1
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +29 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/script.d.ts +44 -8
- package/dist/script.d.ts.map +1 -1
- package/dist/script.js +91 -4
- package/dist/script.js.map +1 -1
- package/dist/state.d.ts +11 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js.map +1 -1
- package/dist/types.d.ts +76 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/frame.d.ts +1 -6
- package/dist/ui/frame.d.ts.map +1 -1
- package/dist/ui/frame.js +27 -9
- package/dist/ui/frame.js.map +1 -1
- package/dist/ui/renderer.d.ts +8 -4
- package/dist/ui/renderer.d.ts.map +1 -1
- package/dist/ui/renderer.js +28 -5
- package/dist/ui/renderer.js.map +1 -1
- package/package.json +29 -5
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@ A fully typesafe, saga-style script framework for TypeScript, with a live termin
|
|
|
6
6
|
- **Phases** are a collection of **steps**.
|
|
7
7
|
- **Steps** have a `handler` and an optional `rollback` that fires when a *later* step fails.
|
|
8
8
|
- Whatever a handler returns is merged into a **typed context** that every later step can read.
|
|
9
|
+
- A step can `clean` keys it is done with, and a `rollback` declares the keys it needs.
|
|
9
10
|
- Zero runtime dependencies. Live rendering on a TTY, plain line output in CI.
|
|
10
11
|
|
|
11
12
|
```ts
|
|
@@ -22,12 +23,14 @@ const result = await new Script<{ service: string }>({ name: "deploy" })
|
|
|
22
23
|
.addStep({
|
|
23
24
|
name: "upload artifact",
|
|
24
25
|
handler: async ({ ctx, progress }) => {
|
|
26
|
+
// ^ ctx.sha is typed here
|
|
25
27
|
const bar = progress({ total: 100, label: "uploading" });
|
|
26
|
-
|
|
28
|
+
|
|
27
29
|
return { uploadId: await upload(ctx.sha, bar) };
|
|
28
30
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
rollbackKeys: ["sha"],
|
|
32
|
+
rollback: async ({ ctx, output }) => cdn.delete(output.uploadId, ctx.sha),
|
|
33
|
+
// ^ { sha: string } ^ typed as { uploadId: string }
|
|
31
34
|
})
|
|
32
35
|
.run({ service: "api" });
|
|
33
36
|
|
|
@@ -45,7 +48,7 @@ if (result.ok) result.ctx.uploadId; // string
|
|
|
45
48
|
✔ check permissions 517ms
|
|
46
49
|
|
|
47
50
|
⠸ Build 17.7s
|
|
48
|
-
✔ install dependencies
|
|
51
|
+
✔ install dependencies (428 packages) 14.4s
|
|
49
52
|
⠸ compile bundle › transform 3.3s
|
|
50
53
|
▕██████████████░░░░░░░░░░▏ 58% 412/710 src/router.ts
|
|
51
54
|
✔ typecheck
|
|
@@ -85,6 +88,68 @@ Reaching for a key a previous step did not produce is a compile error, as is
|
|
|
85
88
|
reading the wrong shape in a `rollback`. A handler that returns nothing leaves
|
|
86
89
|
the context unchanged.
|
|
87
90
|
|
|
91
|
+
## Cleaning the context
|
|
92
|
+
|
|
93
|
+
If a step produces — or receives — data that later steps do not need, listing
|
|
94
|
+
those keys in `clean` deletes them from the context at runtime **and** removes
|
|
95
|
+
them from the type that flows on:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
new Script<{ password: string; email: string }>({ name: "signup" })
|
|
99
|
+
.addStep({
|
|
100
|
+
name: "read input",
|
|
101
|
+
handler: ({ input }) => ({ ...input }),
|
|
102
|
+
})
|
|
103
|
+
.addStep({
|
|
104
|
+
name: "hash",
|
|
105
|
+
handler: async ({ ctx }) => ({ hash: await hashIt(ctx.password) }),
|
|
106
|
+
clean: ["password"], // not needed past this point
|
|
107
|
+
})
|
|
108
|
+
.addStep({
|
|
109
|
+
name: "persist",
|
|
110
|
+
handler: ({ ctx }) => {
|
|
111
|
+
ctx.hash; // string
|
|
112
|
+
ctx.email; // string
|
|
113
|
+
ctx.password; // compile error — cleaned away
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Rules:
|
|
119
|
+
|
|
120
|
+
- Keys are checked against the context as it stands *entering* that step — an
|
|
121
|
+
unknown key is a compile error, and the editor autocompletes the valid ones.
|
|
122
|
+
A step cannot clean a key it produces itself; that key does not exist yet
|
|
123
|
+
when `clean` is read.
|
|
124
|
+
- A key reserved by any step's `rollbackKeys` can never be cleaned, by that
|
|
125
|
+
step or any later one. Trying to throws `StepDefinitionError` from `addStep`,
|
|
126
|
+
while the script is being built, before anything runs.
|
|
127
|
+
- `clean` is part of the declared shape, not of the work, so it applies even
|
|
128
|
+
when the step is skipped by `when` — runtime and types never disagree.
|
|
129
|
+
- A step's own `output` is kept separately and is never cleaned, so its
|
|
130
|
+
`rollback` still sees everything the handler returned.
|
|
131
|
+
|
|
132
|
+
## Input from a schema
|
|
133
|
+
|
|
134
|
+
`In` doesn't have to be written by hand either. `defineInput` takes any
|
|
135
|
+
[Standard Schema](https://standardschema.dev)-compliant validator — Zod,
|
|
136
|
+
Valibot, ArkType, Effect Schema, or a hand-rolled one — infers `In` from its
|
|
137
|
+
output type, and validates whatever is passed to `run()` before any phase
|
|
138
|
+
executes, throwing `SchemaValidationError` on failure:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
const deploy = new Script({ name: "deploy" })
|
|
142
|
+
.defineInput(z.object({ service: z.string() }))
|
|
143
|
+
.addStep({
|
|
144
|
+
name: "resolve commit",
|
|
145
|
+
handler: async ({ input }) => ({ sha: await git.head(input.service) }),
|
|
146
|
+
// ^ input.service: string
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Call it first, right after construction — any `addStep`/`addPhase` added
|
|
151
|
+
before it still sees the previous `In`.
|
|
152
|
+
|
|
88
153
|
## Rollback semantics
|
|
89
154
|
|
|
90
155
|
When a step fails, every step that already **succeeded** is compensated in
|
|
@@ -100,6 +165,45 @@ A rollback that throws is recorded in `result.rollbacks` and surfaced in the
|
|
|
100
165
|
summary; it never masks the original error, and the remaining rollbacks still
|
|
101
166
|
run.
|
|
102
167
|
|
|
168
|
+
### What a rollback can see
|
|
169
|
+
|
|
170
|
+
A rollback always gets its own step's `output` in full. It gets **no context at
|
|
171
|
+
all** by default — it has to ask, via `rollbackKeys`. Asking does two things: it
|
|
172
|
+
narrows `ctx` inside the rollback to exactly those keys, and it reserves them,
|
|
173
|
+
so neither that step nor any later one can `clean` them away. Whatever the
|
|
174
|
+
rollback declared is therefore guaranteed to still be there if it ever runs.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
new Script<{ accountId: string; amount: number }>({ name: "charge" })
|
|
178
|
+
.addStep({ name: "read input", handler: ({ input }) => ({ ...input }) })
|
|
179
|
+
.addStep({
|
|
180
|
+
name: "reserve funds",
|
|
181
|
+
handler: async ({ ctx }) => ({ reservationId: await reserve(ctx.accountId, ctx.amount) }),
|
|
182
|
+
rollbackKeys: ["accountId", "reservationId"],
|
|
183
|
+
rollback: async ({ ctx }) => {
|
|
184
|
+
// ctx is { accountId: string; reservationId: string } — and nothing else
|
|
185
|
+
await release(ctx.accountId, ctx.reservationId);
|
|
186
|
+
},
|
|
187
|
+
})
|
|
188
|
+
.addStep({
|
|
189
|
+
name: "charge card",
|
|
190
|
+
handler: () => {
|
|
191
|
+
throw new Error("payment gateway timeout");
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`rollbackKeys` accepts the step's incoming context keys and its own output keys;
|
|
197
|
+
anything else is a compile error. Cleaning a reserved key is a compile error
|
|
198
|
+
too, and throws `StepDefinitionError` at build time:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
script
|
|
202
|
+
.addStep({ name: "one", handler: () => {}, rollbackKeys: ["a"], rollback: async () => {} })
|
|
203
|
+
.addStep({ name: "two", handler: () => {}, clean: ["a"] });
|
|
204
|
+
// ^ StepDefinitionError: reserved by rollbackKeys
|
|
205
|
+
```
|
|
206
|
+
|
|
103
207
|
## The handler surface
|
|
104
208
|
|
|
105
209
|
Every handler receives one object:
|
|
@@ -110,14 +214,75 @@ Every handler receives one object:
|
|
|
110
214
|
| `ctx` | everything earlier steps produced, fully typed |
|
|
111
215
|
| `signal` | aborts on timeout, Ctrl-C, or an external signal |
|
|
112
216
|
| `attempt` | 1-based, useful with `retry` |
|
|
113
|
-
| `log` / `info` / `warn` / `error` / `success` | permanent
|
|
114
|
-
| `status(text)` | transient one-liner beside the step |
|
|
217
|
+
| `log` / `info` / `warn` / `error` / `success` | a line, placed per `logPlacement` (default: permanent, above the live frame) |
|
|
218
|
+
| `status(text)` | transient one-liner beside the step, cleared when it settles |
|
|
219
|
+
| `note(text)` | annotates the step title — `(400 rows found)` — and stays |
|
|
115
220
|
| `progress({ total, label })` | a progress bar → `update` / `increment` / `setTotal` / `done` |
|
|
116
221
|
| `task(label)` | one nested checklist item → `succeed` / `fail` / `skip` |
|
|
117
222
|
| `tasks([...] as const)` | a whole checklist, keyed for typed lookup |
|
|
118
223
|
|
|
119
|
-
`rollback` receives
|
|
120
|
-
`
|
|
224
|
+
`rollback` receives `input`, `signal`, `phase`, `step`, `log`, `status`, `note`
|
|
225
|
+
and `progress`, plus `output` (that step's own return value) and `error` (what
|
|
226
|
+
triggered the unwind). Its `ctx` holds only the keys named in `rollbackKeys`.
|
|
227
|
+
|
|
228
|
+
### `status` vs `note`
|
|
229
|
+
|
|
230
|
+
Both write next to the step name, and they differ in lifetime. `status` is
|
|
231
|
+
scratch space for a step in flight — it is wiped the moment the step settles.
|
|
232
|
+
`note` is part of the title: it is written once and stays on the finished line,
|
|
233
|
+
which is where a count, a size, or an id belongs.
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
.addStep({
|
|
237
|
+
name: "query database",
|
|
238
|
+
handler: async ({ status, note }) => {
|
|
239
|
+
status("scanning"); // ⠸ query database › scanning
|
|
240
|
+
const rows = await db.all(sql);
|
|
241
|
+
note(`${rows.length} rows found`);
|
|
242
|
+
return { rows };
|
|
243
|
+
},
|
|
244
|
+
})
|
|
245
|
+
// ✔ query database (400 rows found) 1.2s
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Calling `note` again replaces the text; `note("")` removes it. Both renderers
|
|
249
|
+
show it — the live frame in the title, the CI renderer on the step's line.
|
|
250
|
+
|
|
251
|
+
## Log placement
|
|
252
|
+
|
|
253
|
+
By default, `log`/`info`/`warn`/`error`/`success` write a permanent line above
|
|
254
|
+
the whole frame — the complete record for the run, in order. `logPlacement`
|
|
255
|
+
moves them somewhere more local instead:
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
new Script({ name: "checkout", logPlacement: "step" })
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
| `logPlacement` | where it lands |
|
|
262
|
+
| --- | --- |
|
|
263
|
+
| `"scrollback"` (default) | a permanent line above the frame — the full run, in order |
|
|
264
|
+
| `"step"` | nested under the step that logged it, beside its tasks and progress bar |
|
|
265
|
+
| `"bottom"` | a rolling tail of the most recent lines, below the whole phase tree |
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
✖ Main 320ms
|
|
269
|
+
✔ reserve inventory 320ms
|
|
270
|
+
• checked warehouse A ← "step": nested where it happened
|
|
271
|
+
• checked warehouse B
|
|
272
|
+
✖ boom 0ms
|
|
273
|
+
boom
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
`"step"` and `"bottom"` both keep only the most recent few lines — they trade
|
|
277
|
+
completeness for locality, which is exactly what makes a rollback's `log()`
|
|
278
|
+
land next to the step it is undoing instead of scrolling past at the top.
|
|
279
|
+
Reach for `"scrollback"` when the log is the thing you need to still have once
|
|
280
|
+
the run is over. Only the live renderer honours this: the plain/CI renderer is
|
|
281
|
+
already sequential, so every placement just prints each line immediately, in
|
|
282
|
+
order, which is already both complete and in place.
|
|
283
|
+
|
|
284
|
+
Run `npm run example:log-placement` to see the same script three times, once
|
|
285
|
+
per placement.
|
|
121
286
|
|
|
122
287
|
## Step options
|
|
123
288
|
|
|
@@ -128,6 +293,8 @@ Every handler receives one object:
|
|
|
128
293
|
when: ({ input, ctx }) => input.env === "production",
|
|
129
294
|
retry: { attempts: 3, delayMs: (attempt) => attempt * 250, retryIf: isTransient },
|
|
130
295
|
timeoutMs: 30_000,
|
|
296
|
+
clean: ["draftId"], // drop from the context once this step settles
|
|
297
|
+
rollbackKeys: ["tagName"], // the context keys `rollback` needs, and reserves
|
|
131
298
|
handler,
|
|
132
299
|
rollback,
|
|
133
300
|
})
|
|
@@ -147,6 +314,7 @@ new Script<Input>({
|
|
|
147
314
|
plain: undefined, // force the CI renderer; default auto-detects a TTY
|
|
148
315
|
silent: false,
|
|
149
316
|
handleSignals: true, // Ctrl-C aborts and compensates; a second one gives up
|
|
317
|
+
logPlacement: "scrollback", // "scrollback" | "step" | "bottom"
|
|
150
318
|
})
|
|
151
319
|
```
|
|
152
320
|
|
|
@@ -169,18 +337,51 @@ type RunResult<Ctx> =
|
|
|
169
337
|
export const verifyId = stepFor<Input, { user: User }>()({
|
|
170
338
|
name: "verify id",
|
|
171
339
|
handler: async ({ ctx }) => ({ verified: ctx.user.id }),
|
|
340
|
+
rollbackKeys: ["verified"],
|
|
341
|
+
rollback: async ({ ctx }) => unverify(ctx.verified),
|
|
172
342
|
});
|
|
173
343
|
```
|
|
174
344
|
|
|
175
|
-
|
|
345
|
+
`rollbackKeys` narrows the rollback here exactly as it does inline, and the keys
|
|
346
|
+
stay reserved once the step is handed to `addStep`.
|
|
347
|
+
|
|
348
|
+
`addStep` is where the requirement is enforced: TypeScript checks that the
|
|
349
|
+
script has actually produced `Ctx` by that point. Dropping a step that needs
|
|
350
|
+
`{ user: User }` into a script that has not loaded a user yet is a compile
|
|
351
|
+
error, not a runtime `undefined`.
|
|
352
|
+
|
|
353
|
+
## Examples
|
|
354
|
+
|
|
355
|
+
Seven runnable scripts, each aimed at a different part of the API. Most take a
|
|
356
|
+
flag to switch between the happy path and the interesting one.
|
|
357
|
+
|
|
358
|
+
| | |
|
|
359
|
+
| --- | --- |
|
|
360
|
+
| [`deploy.ts`](examples/deploy.ts) | The tour: phases, progress bars, checklists, retry, `note`, `clean`, rollback. `npm run example`, `npm run example:fail` |
|
|
361
|
+
| [`checkout.ts`](examples/checkout.ts) | Saga semantics end to end — three mutations, three compensations, a secret dropped with `clean`, and `logPlacement: "step"` nesting each rollback's log under the step it undoes. `-- --ok` for the happy path |
|
|
362
|
+
| [`resilience.ts`](examples/resilience.ts) | `retry` with backoff, `retryIf` refusing to retry a 401, `timeoutMs` on a hung step, and an external `AbortSignal`. `-- --timeout`, `-- --fatal`, `-- --cancel` |
|
|
363
|
+
| [`intake.ts`](examples/intake.ts) | `defineInput` with a hand-rolled Standard Schema, plus the full handler UI surface. `-- --bad` to watch validation reject the run, `-- --dirty` for a failing checklist item |
|
|
364
|
+
| [`modular.ts`](examples/modular.ts) | `stepFor` steps living in [`steps/tenancy.ts`](examples/steps/tenancy.ts), shared by two unrelated scripts — the imported rollback compensates in both. `-- --fail` |
|
|
365
|
+
| [`log-placement.ts`](examples/log-placement.ts) | The same script run three times, once per `logPlacement` value, so the difference is visible directly |
|
|
366
|
+
| [`validate.ts`](examples/validate.ts) | The smallest thing that runs: two steps, `rollback: "none"` |
|
|
367
|
+
|
|
368
|
+
```
|
|
369
|
+
npm run example:checkout -- --ok
|
|
370
|
+
npm run example:resilience -- --cancel
|
|
371
|
+
npm run example:intake -- --bad
|
|
372
|
+
npm run example:modular -- --fail
|
|
373
|
+
npm run example:log-placement
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## npm scripts
|
|
176
377
|
|
|
177
378
|
```
|
|
178
379
|
npm run build # emit dist/
|
|
179
380
|
npm test # node:test suite
|
|
180
|
-
npm run typecheck # library + examples + tests
|
|
381
|
+
npm run typecheck # library + examples + tests
|
|
181
382
|
npm run example # the happy path, live
|
|
182
383
|
npm run example:fail
|
|
183
|
-
npm run release #
|
|
384
|
+
npm run release # release-it: version, tag, publish
|
|
184
385
|
```
|
|
185
386
|
|
|
186
387
|
## TypeScript layout
|
|
@@ -193,66 +394,15 @@ is invisible to them, so the IDE and the CLI disagree.
|
|
|
193
394
|
| --- | --- | --- |
|
|
194
395
|
| `tsconfig.json` | `src` | The library. `noEmit`, strict. |
|
|
195
396
|
| `tsconfig.build.json` | `src` | The only config that emits `dist/`. |
|
|
196
|
-
| `examples/tsconfig.json` | `examples` | Imports the built `dist
|
|
197
|
-
| `test/tsconfig.json` | `test` | Same. |
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
import
|
|
202
|
-
|
|
203
|
-
`
|
|
204
|
-
|
|
205
|
-
is set (TS5096).
|
|
206
|
-
|
|
207
|
-
## The release pipeline
|
|
208
|
-
|
|
209
|
-
`scripts/release.ts` builds and publishes this package, and is itself written
|
|
210
|
-
with this framework — the pipeline is the integration test.
|
|
211
|
-
|
|
212
|
-
```
|
|
213
|
-
npm run release # dry run; mutates nothing
|
|
214
|
-
npm run release -- --simulate-failure # rehearse the rollback path
|
|
215
|
-
npm run release -- --publish # for real
|
|
216
|
-
npm run release -- --publish --bump minor
|
|
217
|
-
npm run release -- --publish --version 1.0.0 --tag next
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
| Phase | Steps |
|
|
221
|
-
| --- | --- |
|
|
222
|
-
| Preflight | read manifest · authenticate npm · inspect git · resolve version · check registry |
|
|
223
|
-
| Verify | typecheck · run tests |
|
|
224
|
-
| Package | write version · clean dist · build · verify artifacts · audit tarball |
|
|
225
|
-
| Publish | tag release · push tag · publish to npm |
|
|
226
|
-
|
|
227
|
-
Three steps compensate, and the ordering is deliberate — `publish to npm` is
|
|
228
|
-
last, so a failure anywhere *before* it unwinds everything and nothing reaches
|
|
229
|
-
the registry:
|
|
230
|
-
|
|
231
|
-
| Step | Rollback |
|
|
232
|
-
| --- | --- |
|
|
233
|
-
| `write version` | restore the previous version in package.json |
|
|
234
|
-
| `clean dist` | rebuild from source |
|
|
235
|
-
| `tag release` | delete the local tag |
|
|
236
|
-
| `push tag` | delete the remote tag |
|
|
237
|
-
| `publish to npm` | `npm deprecate` — a published version cannot be recalled |
|
|
238
|
-
|
|
239
|
-
`--simulate-failure` performs the local mutations and then fails at the publish
|
|
240
|
-
step. Nothing leaves the machine, and you get to watch the unwind:
|
|
241
|
-
|
|
242
|
-
```
|
|
243
|
-
✖ publish to npm 0ms simulated publish failure (--simulate-failure)
|
|
244
|
-
▲ deleted local tag v0.2.0
|
|
245
|
-
▲ dist rebuilt from source
|
|
246
|
-
▲ package.json version restored to 0.1.0
|
|
247
|
-
|
|
248
|
-
✖ Failed at Publish › publish to npm after 8.1s
|
|
249
|
-
↺ Rolled back 3 steps
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
Other things it checks: a scoped package without `publishConfig.access`
|
|
253
|
-
(`"public"`) would be published as restricted, so preflight refuses; the tarball
|
|
254
|
-
is audited path-by-path against an allowlist so `src/` can never leak; and the
|
|
255
|
-
version is checked against the registry before any work is done.
|
|
397
|
+
| `examples/tsconfig.json` | `examples` | Imports the built `dist/`; adds `allowImportingTsExtensions`. |
|
|
398
|
+
| `test/tsconfig.json` | `test` | Same, without the flag. |
|
|
399
|
+
|
|
400
|
+
Only `examples/` needs that flag, and only because `modular.ts` imports a
|
|
401
|
+
sibling: Node's type stripping does not rewrite import extensions, so the
|
|
402
|
+
import has to say `./steps/tenancy.ts` rather than `./steps/tenancy.js`. The
|
|
403
|
+
flag cannot go in the root config — `tsconfig.build.json` extends it and sets
|
|
404
|
+
`noEmit: false`, and TypeScript rejects `allowImportingTsExtensions` unless
|
|
405
|
+
`noEmit` or `emitDeclarationOnly` is set (TS5096).
|
|
256
406
|
|
|
257
407
|
## Rendering notes
|
|
258
408
|
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA2B,SAAS,EAAa,MAAM,YAAY,CAAC;AAChF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAEV,eAAe,EACf,WAAW,EAGZ,MAAM,YAAY,CAAC;AA6FpB,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AASD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,GAAG,EACvC,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,EAAE,EACT,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,GACd,WAAW,CAAC,EAAE,EAAE,GAAG,CAAC,CA2BtB;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAChD,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,EAAE,EACT,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,GAAG,EACX,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,WAAW,GAClB,eAAe,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAkB/B"}
|
package/dist/context.js
CHANGED
|
@@ -78,9 +78,19 @@ function createTaskList(step, renderer, labels) {
|
|
|
78
78
|
get: (key) => map[key],
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
|
+
/** Set (or, given "", clear) the step's persistent title annotation. */
|
|
82
|
+
function annotate(step, renderer, message) {
|
|
83
|
+
if (message === "")
|
|
84
|
+
delete step.note;
|
|
85
|
+
else
|
|
86
|
+
step.note = message;
|
|
87
|
+
renderer.refresh();
|
|
88
|
+
}
|
|
81
89
|
export function createStepContext(deps, input, ctx, signal, attempt) {
|
|
82
90
|
const { renderer, step, phaseName } = deps;
|
|
83
|
-
|
|
91
|
+
// `step` is a routing hint: renderers that place logs on the step itself
|
|
92
|
+
// (rather than the scrollback) need to know which one.
|
|
93
|
+
const emit = (level) => (message) => renderer.log({ level, message }, step);
|
|
84
94
|
return {
|
|
85
95
|
input,
|
|
86
96
|
ctx,
|
|
@@ -97,6 +107,7 @@ export function createStepContext(deps, input, ctx, signal, attempt) {
|
|
|
97
107
|
step.statusText = message;
|
|
98
108
|
renderer.refresh();
|
|
99
109
|
},
|
|
110
|
+
note: (message) => annotate(step, renderer, message),
|
|
100
111
|
progress: (options) => createProgress(step, renderer, options),
|
|
101
112
|
task: (label) => createTask(step, renderer, label),
|
|
102
113
|
tasks: (labels) => createTaskList(step, renderer, labels),
|
|
@@ -112,11 +123,12 @@ export function createRollbackContext(deps, input, ctx, output, error, signal) {
|
|
|
112
123
|
signal,
|
|
113
124
|
phase: phaseName,
|
|
114
125
|
step: step.name,
|
|
115
|
-
log: (message) => renderer.log({ level: "warn", message }),
|
|
126
|
+
log: (message) => renderer.log({ level: "warn", message }, step),
|
|
116
127
|
status(message) {
|
|
117
128
|
step.statusText = message;
|
|
118
129
|
renderer.refresh();
|
|
119
130
|
},
|
|
131
|
+
note: (message) => annotate(step, renderer, message),
|
|
120
132
|
progress: (options) => createProgress(step, renderer, options),
|
|
121
133
|
};
|
|
122
134
|
}
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
/** The value passed to `run()` failed validation against `defineInput`'s schema. */
|
|
3
|
+
export declare class SchemaValidationError extends Error {
|
|
4
|
+
readonly issues: ReadonlyArray<StandardSchemaV1.Issue>;
|
|
5
|
+
constructor(issues: ReadonlyArray<StandardSchemaV1.Issue>);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A step was declared in a way the script cannot honour — today, a `clean`
|
|
9
|
+
* naming a key some step reserved through `rollbackKeys`. Thrown by `addStep`,
|
|
10
|
+
* while the script is being built, long before anything runs.
|
|
11
|
+
*/
|
|
12
|
+
export declare class StepDefinitionError extends Error {
|
|
13
|
+
readonly step: string;
|
|
14
|
+
constructor(step: string, message: string);
|
|
15
|
+
}
|
|
1
16
|
/** A step's handler threw. `cause` holds whatever it actually threw. */
|
|
2
17
|
export declare class StepFailedError extends Error {
|
|
3
18
|
readonly phase: string;
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAO1E;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAM5C;AAED,4EAA4E;AAC5E,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM;CAK3B;AAED,+EAA+E;AAC/E,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;gBAEpB,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO;CAOhF;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAK/C"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,oFAAoF;AACpF,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;gBAE3C,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,KAAK,CAAC;CAgB1D;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK1C;AAED,wEAAwE;AACxE,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAO1E;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAM5C;AAED,4EAA4E;AAC5E,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM;CAK3B;AAED,+EAA+E;AAC/E,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;gBAEpB,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO;CAOhF;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAK/C"}
|
package/dist/errors.js
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
/** The value passed to `run()` failed validation against `defineInput`'s schema. */
|
|
2
|
+
export class SchemaValidationError extends Error {
|
|
3
|
+
issues;
|
|
4
|
+
constructor(issues) {
|
|
5
|
+
super(issues
|
|
6
|
+
.map((issue) => {
|
|
7
|
+
const path = issue.path
|
|
8
|
+
?.map((segment) => String(typeof segment === "object" && segment !== null ? segment.key : segment))
|
|
9
|
+
.join(".");
|
|
10
|
+
return path ? `${path}: ${issue.message}` : issue.message;
|
|
11
|
+
})
|
|
12
|
+
.join("; "));
|
|
13
|
+
this.name = "SchemaValidationError";
|
|
14
|
+
this.issues = issues;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A step was declared in a way the script cannot honour — today, a `clean`
|
|
19
|
+
* naming a key some step reserved through `rollbackKeys`. Thrown by `addStep`,
|
|
20
|
+
* while the script is being built, long before anything runs.
|
|
21
|
+
*/
|
|
22
|
+
export class StepDefinitionError extends Error {
|
|
23
|
+
step;
|
|
24
|
+
constructor(step, message) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.name = "StepDefinitionError";
|
|
27
|
+
this.step = step;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
1
30
|
/** A step's handler threw. `cause` holds whatever it actually threw. */
|
|
2
31
|
export class StepFailedError extends Error {
|
|
3
32
|
phase;
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IACrC,MAAM,CAAwC;IAEvD,YAAY,MAA6C;QACvD,KAAK,CACH,MAAM;aACH,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACb,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI;gBACrB,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAChB,MAAM,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAChF;iBACA,IAAI,CAAC,GAAG,CAAC,CAAC;YACb,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;QAC5D,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CACd,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,IAAI,CAAS;IAEtB,YAAY,IAAY,EAAE,OAAe;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,wEAAwE;AACxE,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,KAAK,CAAS;IACd,IAAI,CAAS;IACb,QAAQ,CAAS;IAE1B,YAAY,KAAa,EAAE,IAAY,EAAE,QAAgB,EAAE,KAAc;QACvE,KAAK,CAAC,SAAS,IAAI,eAAe,KAAK,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,CAAS;IACb,SAAS,CAAS;IAE3B,YAAY,IAAY,EAAE,SAAiB;QACzC,KAAK,CAAC,SAAS,IAAI,qBAAqB,SAAS,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED,4EAA4E;AAC5E,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,MAAM,CAAS;IAExB,YAAY,MAAc;QACxB,KAAK,CAAC,mBAAmB,MAAM,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,+EAA+E;AAC/E,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,KAAK,CAAS;IACd,IAAI,CAAS;IACb,aAAa,CAAU;IAEhC,YAAY,KAAa,EAAE,IAAY,EAAE,aAAsB,EAAE,KAAc;QAC7E,KAAK,CAAC,iBAAiB,IAAI,eAAe,KAAK,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;CACF;AAED,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,CACL,KAAK,YAAY,kBAAkB;QACnC,CAAC,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CACxD,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { Script, script, stepFor, type RunOptions } from "./script.js";
|
|
2
|
-
export { RollbackFailedError, ScriptAbortedError, StepFailedError, StepTimeoutError, isAbort, } from "./errors.js";
|
|
3
|
-
export type { Awaitable, Merge, PhaseOptions, PhaseStatus, Prettify, ProgressHandle, RetryPolicy, RollbackContext, RollbackReport, RunResult, RunStatus, ScriptOptions, StepContext, StepDef, StepReport, StepStatus, TaskHandle, TaskListHandle, } from "./types.js";
|
|
2
|
+
export { RollbackFailedError, SchemaValidationError, ScriptAbortedError, StepDefinitionError, StepFailedError, StepTimeoutError, isAbort, } from "./errors.js";
|
|
3
|
+
export type { Awaitable, CleanField, Cleaned, LogPlacement, Merge, PhaseOptions, PhaseStatus, Prettify, ProgressHandle, RetryPolicy, RollbackContext, RollbackData, RollbackReport, RunResult, RunStatus, ScriptOptions, StepContext, StepDef, StepReport, StepStatus, TaskHandle, TaskListHandle, } from "./types.js";
|
|
4
4
|
export { formatDuration } from "./state.js";
|
|
5
5
|
export { setColorEnabled, isColorEnabled } from "./ui/ansi.js";
|
|
6
6
|
export { palette, symbols } from "./ui/theme.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvE,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,OAAO,GACR,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,SAAS,EACT,KAAK,EACL,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,cAAc,EACd,WAAW,EACX,eAAe,EACf,cAAc,EACd,SAAS,EACT,SAAS,EACT,aAAa,EACb,WAAW,EACX,OAAO,EACP,UAAU,EACV,UAAU,EACV,UAAU,EACV,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,OAAO,GACR,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,SAAS,EACT,UAAU,EACV,OAAO,EACP,YAAY,EACZ,KAAK,EACL,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,cAAc,EACd,WAAW,EACX,eAAe,EACf,YAAY,EACZ,cAAc,EACd,SAAS,EACT,SAAS,EACT,aAAa,EACb,WAAW,EACX,OAAO,EACP,UAAU,EACV,UAAU,EACV,UAAU,EACV,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Script, script, stepFor } from "./script.js";
|
|
2
|
-
export { RollbackFailedError, ScriptAbortedError, StepFailedError, StepTimeoutError, isAbort, } from "./errors.js";
|
|
2
|
+
export { RollbackFailedError, SchemaValidationError, ScriptAbortedError, StepDefinitionError, StepFailedError, StepTimeoutError, isAbort, } from "./errors.js";
|
|
3
3
|
export { formatDuration } from "./state.js";
|
|
4
4
|
export { setColorEnabled, isColorEnabled } from "./ui/ansi.js";
|
|
5
5
|
export { palette, symbols } from "./ui/theme.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAmB,MAAM,aAAa,CAAC;AAEvE,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,OAAO,GACR,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAmB,MAAM,aAAa,CAAC;AAEvE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,OAAO,GACR,MAAM,aAAa,CAAC;AA2BrB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/script.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
import type { CleanField, Cleaned, Merge, PhaseOptions, RunResult, ScriptOptions, StepDef } from "./types.js";
|
|
2
3
|
export interface RunOptions {
|
|
3
4
|
/** Cancel the run from the outside. */
|
|
4
5
|
signal?: AbortSignal;
|
|
@@ -26,21 +27,53 @@ export interface RunOptions {
|
|
|
26
27
|
* })
|
|
27
28
|
* .run({ userId: "u_1" });
|
|
28
29
|
* ```
|
|
30
|
+
*
|
|
31
|
+
* The third parameter is inferred too: it collects the keys steps reserved
|
|
32
|
+
* through `rollbackKeys`, which is how `clean` knows what it may not remove.
|
|
29
33
|
*/
|
|
30
|
-
export declare class Script<In = void, Ctx extends object = {}> {
|
|
34
|
+
export declare class Script<In = void, Ctx extends object = {}, Reserved extends PropertyKey = never> {
|
|
31
35
|
private readonly options;
|
|
32
36
|
private readonly definition;
|
|
37
|
+
private readonly reserved;
|
|
38
|
+
private _schema;
|
|
33
39
|
constructor(options?: ScriptOptions | string);
|
|
40
|
+
/**
|
|
41
|
+
* Provide a [Standard Schema](https://standardschema.dev) describing the run
|
|
42
|
+
* input instead of writing `In` by hand — any compliant library works (Zod,
|
|
43
|
+
* Valibot, ArkType, Effect Schema, ...). `In` is inferred from the schema's
|
|
44
|
+
* output type, and the value passed to `run()` is validated against it
|
|
45
|
+
* before any phase executes, throwing {@link SchemaValidationError} on
|
|
46
|
+
* failure.
|
|
47
|
+
*
|
|
48
|
+
* Call this first, right after construction — every `addStep`/`addPhase`
|
|
49
|
+
* called before it still sees the old `In`.
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* const deploy = new Script({ name: "deploy" })
|
|
53
|
+
* .defineInput(z.object({ service: z.string() }))
|
|
54
|
+
* .addStep({
|
|
55
|
+
* name: "resolve commit",
|
|
56
|
+
* handler: async ({ input }) => ({ sha: await git.head(input.service) }),
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
defineInput<TSchema>(schema: StandardSchemaV1<unknown, TSchema>): Script<TSchema, Ctx, Reserved>;
|
|
61
|
+
/** Validate `input` against the schema from `defineInput`, if any. */
|
|
62
|
+
private validateInput;
|
|
34
63
|
/** Open a new phase. Subsequent `addStep` calls land in it. */
|
|
35
|
-
addPhase(name: string, options?: PhaseOptions<In, Ctx>): Script<In, Ctx>;
|
|
64
|
+
addPhase(name: string, options?: PhaseOptions<In, Ctx>): Script<In, Ctx, Reserved>;
|
|
36
65
|
/** Open a phase and populate it inside a callback, keeping the type flow. */
|
|
37
|
-
addPhase<Next extends object>(name: string, build: (script: Script<In, Ctx>) => Script<In, Next>): Script<In, Next>;
|
|
38
|
-
addPhase<Next extends object>(name: string, options: PhaseOptions<In, Ctx>, build: (script: Script<In, Ctx>) => Script<In, Next>): Script<In, Next>;
|
|
66
|
+
addPhase<Next extends object, NextReserved extends PropertyKey>(name: string, build: (script: Script<In, Ctx, Reserved>) => Script<In, Next, NextReserved>): Script<In, Next, NextReserved>;
|
|
67
|
+
addPhase<Next extends object, NextReserved extends PropertyKey>(name: string, options: PhaseOptions<In, Ctx>, build: (script: Script<In, Ctx, Reserved>) => Script<In, Next, NextReserved>): Script<In, Next, NextReserved>;
|
|
39
68
|
/**
|
|
40
69
|
* Append a step to the current phase. Whatever the handler resolves to is
|
|
41
|
-
* merged into the context and becomes visible to every later step
|
|
70
|
+
* merged into the context and becomes visible to every later step; whatever
|
|
71
|
+
* it lists in `clean` is dropped from both.
|
|
72
|
+
*
|
|
73
|
+
* @throws {StepDefinitionError} if `clean` names a key reserved by some
|
|
74
|
+
* step's `rollbackKeys`.
|
|
42
75
|
*/
|
|
43
|
-
addStep<Out extends object | void>(def: StepDef<In, Ctx, Out>): Script<In, Merge<Ctx, Out
|
|
76
|
+
addStep<Out extends object | void, const RollbackKeys extends readonly PropertyKey[] = readonly [], const CleanKeys extends readonly PropertyKey[] = readonly []>(def: StepDef<In, Ctx, Out, RollbackKeys> & CleanField<Ctx, Reserved, CleanKeys>): Script<In, Cleaned<Merge<Ctx, Out>, CleanKeys[number]>, Reserved | RollbackKeys[number]>;
|
|
44
77
|
/** Every step name, in execution order — handy for tests and docs. */
|
|
45
78
|
outline(): Array<{
|
|
46
79
|
phase: string;
|
|
@@ -68,8 +101,11 @@ export declare class Script<In = void, Ctx extends object = {}> {
|
|
|
68
101
|
* handler: async ({ ctx }) => ({ verified: ctx.user.id }),
|
|
69
102
|
* });
|
|
70
103
|
* ```
|
|
104
|
+
*
|
|
105
|
+
* `rollbackKeys` works the same here, and the keys it names stay reserved once
|
|
106
|
+
* the step is handed to `addStep`.
|
|
71
107
|
*/
|
|
72
|
-
export declare function stepFor<In, Ctx extends object = {}>(): <Out extends object | void>(def: StepDef<In, Ctx, Out>) => StepDef<In, Ctx, Out>;
|
|
108
|
+
export declare function stepFor<In, Ctx extends object = {}>(): <Out extends object | void, const RollbackKeys extends readonly PropertyKey[] = readonly []>(def: StepDef<In, Ctx, Out, RollbackKeys>) => StepDef<In, Ctx, Out, RollbackKeys>;
|
|
73
109
|
/** Convenience factory so callers can skip `new`. */
|
|
74
110
|
export declare function script<In = void>(options?: ScriptOptions | string): Script<In, {}>;
|
|
75
111
|
//# sourceMappingURL=script.d.ts.map
|
package/dist/script.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../src/script.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../src/script.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAU9D,OAAO,KAAK,EACV,UAAU,EACV,OAAO,EACP,KAAK,EACL,YAAY,EAIZ,SAAS,EACT,aAAa,EACb,OAAO,EAER,MAAM,YAAY,CAAC;AA+BpB,MAAM,WAAW,UAAU;IACzB,uCAAuC;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,SAAS,MAAM,GAAG,EAAE,EAAE,QAAQ,SAAS,WAAW,GAAG,KAAK;IAC1F,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,OAAO,CAA+B;gBAElC,OAAO,GAAE,aAAa,GAAG,MAAW;IAIhD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC;IAKhG,sEAAsE;YACxD,aAAa;IAO3B,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC;IAClF,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,SAAS,MAAM,EAAE,YAAY,SAAS,WAAW,EAC5D,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,CAAC,GAC3E,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,IAAI,SAAS,MAAM,EAAE,YAAY,SAAS,WAAW,EAC5D,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,EAC9B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,CAAC,GAC3E,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,CAAC;IAqBjC;;;;;;;OAOG;IACH,OAAO,CACL,GAAG,SAAS,MAAM,GAAG,IAAI,EACzB,KAAK,CAAC,YAAY,SAAS,SAAS,WAAW,EAAE,GAAG,SAAS,EAAE,EAC/D,KAAK,CAAC,SAAS,SAAS,SAAS,WAAW,EAAE,GAAG,SAAS,EAAE,EAE5D,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,CAAC,GAC9E,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IA0B3F,sEAAsE;IACtE,OAAO,IAAI,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAOpD,OAAO,CAAC,YAAY;IAYd,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,UAAU,GAAE,UAAe,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IA6L1E,kEAAkE;YACpD,WAAW;IA8DzB,mDAAmD;YACrC,MAAM;IAwDpB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;CA+B3B;AA6DD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,GAAG,SAAS,MAAM,GAAG,EAAE,MACzC,GAAG,SAAS,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC,YAAY,SAAS,SAAS,WAAW,EAAE,GAAG,SAAS,EAAE,EAChG,KAAK,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,KACvC,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,CACvC;AAED,qDAAqD;AACrD,wBAAgB,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAElF"}
|