@moku-labs/worker 0.8.1 → 0.9.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/dist/{cli-l-AOWzhR.cjs → cli-CfgYgnzW.cjs} +298 -42
- package/dist/{cli-DNW8_355.mjs → cli-Cs3R3Jhr.mjs} +298 -42
- package/dist/cli.cjs +1 -1
- package/dist/cli.d.cts +1 -1
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/{index-BDkgen4r.d.cts → index-Cb3vzZte.d.cts} +75 -11
- package/dist/{index-BDkgen4r.d.mts → index-Cb3vzZte.d.mts} +75 -11
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
|
@@ -1608,6 +1608,76 @@ const runWranglerInherit = (args) => {
|
|
|
1608
1608
|
});
|
|
1609
1609
|
};
|
|
1610
1610
|
//#endregion
|
|
1611
|
+
//#region src/plugins/deploy/seed.ts
|
|
1612
|
+
/**
|
|
1613
|
+
* @file deploy plugin — shared D1 seed helpers (resolve the target db, run a configured seed).
|
|
1614
|
+
*
|
|
1615
|
+
* Pure orchestration over an INJECTED wrangler runner, so the post-deploy REMOTE seed (api.ts) and
|
|
1616
|
+
* the dev-session LOCAL seed (dev/runner.ts) stay in lockstep — same file, same KV-reset semantics,
|
|
1617
|
+
* differing only in the `--remote` / `--local` scope. Migrations are NOT applied here: each caller
|
|
1618
|
+
* applies the schema first (the deploy's migration step / dev's local-migrate step), then seeds.
|
|
1619
|
+
* Node-only; never imported by the runtime Worker bundle.
|
|
1620
|
+
*/
|
|
1621
|
+
/**
|
|
1622
|
+
* Resolve the single configured d1 database (or the one bound to `binding` when several exist) from
|
|
1623
|
+
* the d1 plugin's manifest. The shared resolver behind `seed()`, the post-deploy seed, and the dev
|
|
1624
|
+
* seed; throws a branded error when the choice is ambiguous (none/several, no binding) or unknown.
|
|
1625
|
+
*
|
|
1626
|
+
* @param ctx - The deploy plugin context.
|
|
1627
|
+
* @param binding - The d1 binding to target when more than one is configured; the sole one otherwise.
|
|
1628
|
+
* @returns The resolved d1 resource descriptor (its binding + optional migrations dir).
|
|
1629
|
+
* @throws {Error} When no single database resolves (none/several without a binding, or unknown binding).
|
|
1630
|
+
* @example
|
|
1631
|
+
* ```ts
|
|
1632
|
+
* const db = resolveD1(ctx, "DB");
|
|
1633
|
+
* ```
|
|
1634
|
+
*/
|
|
1635
|
+
const resolveD1 = (ctx, binding) => {
|
|
1636
|
+
const databases = ctx.require(d1Plugin).deployManifest();
|
|
1637
|
+
const matched = binding === void 0 ? databases : databases.filter((db) => db.binding === binding);
|
|
1638
|
+
const target = matched.length === 1 ? matched[0] : void 0;
|
|
1639
|
+
if (target === void 0) throw new Error(binding === void 0 ? `[moku-worker] seed: ${String(databases.length)} d1 databases configured — pass { binding } to choose one.` : `[moku-worker] seed: no d1 database is bound to "${binding}".`);
|
|
1640
|
+
return target;
|
|
1641
|
+
};
|
|
1642
|
+
/**
|
|
1643
|
+
* Run a configured seed against one scope: execute the seed SQL against the d1 database, then delete
|
|
1644
|
+
* each configured cached KV key so the next read rebuilds it from the freshly-seeded rows. The
|
|
1645
|
+
* schema is assumed to exist (the caller applies migrations first), so this never migrates. The
|
|
1646
|
+
* wrangler runner is injected so the same orchestration serves the streamed deploy path and the
|
|
1647
|
+
* injectable dev path.
|
|
1648
|
+
*
|
|
1649
|
+
* @param ctx - The deploy plugin context.
|
|
1650
|
+
* @param run - The wrangler runner to execute each command through.
|
|
1651
|
+
* @param seed - The resolved seed config (SQL file, optional binding, KV keys to reset).
|
|
1652
|
+
* @param scope - The wrangler scope: `--remote` (deploy) or `--local` (dev).
|
|
1653
|
+
* @returns Resolves once the seed file has executed and every cached KV key is cleared.
|
|
1654
|
+
* @throws {Error} When no d1 database is configured, or the seed's binding cannot be resolved.
|
|
1655
|
+
* @example
|
|
1656
|
+
* ```ts
|
|
1657
|
+
* await runConfiguredSeed(ctx, runWranglerInherit, ctx.config.seed, "--remote");
|
|
1658
|
+
* ```
|
|
1659
|
+
*/
|
|
1660
|
+
const runConfiguredSeed = async (ctx, run, seed, scope) => {
|
|
1661
|
+
if (!ctx.has("d1")) throw new Error("[moku-worker] seed: no d1 database is configured.");
|
|
1662
|
+
await run([
|
|
1663
|
+
"d1",
|
|
1664
|
+
"execute",
|
|
1665
|
+
resolveD1(ctx, seed.binding).binding,
|
|
1666
|
+
scope,
|
|
1667
|
+
"--file",
|
|
1668
|
+
seed.file
|
|
1669
|
+
]);
|
|
1670
|
+
for (const entry of seed.resetKv ?? []) await run([
|
|
1671
|
+
"kv",
|
|
1672
|
+
"key",
|
|
1673
|
+
"delete",
|
|
1674
|
+
entry.key,
|
|
1675
|
+
"--binding",
|
|
1676
|
+
entry.binding,
|
|
1677
|
+
scope
|
|
1678
|
+
]);
|
|
1679
|
+
};
|
|
1680
|
+
//#endregion
|
|
1611
1681
|
//#region src/plugins/deploy/dev/build.ts
|
|
1612
1682
|
/**
|
|
1613
1683
|
* @file deploy plugin — dev site-rebuild resolution.
|
|
@@ -1930,8 +2000,32 @@ const rebuild = async (ctx, deps, changedPaths, hooks) => {
|
|
|
1930
2000
|
}
|
|
1931
2001
|
};
|
|
1932
2002
|
/**
|
|
1933
|
-
*
|
|
1934
|
-
*
|
|
2003
|
+
* Load the configured seed into the LOCAL D1 for a `dev --seed` session: execute the SQL file, then
|
|
2004
|
+
* clear the configured cached KV keys so the app rebuilds them from the freshly-seeded rows. The
|
|
2005
|
+
* schema already exists (the migrate step above runs first), so this never migrates — the local
|
|
2006
|
+
* analogue of the deploy's remote seed, over the same `pluginConfigs.deploy.seed` config.
|
|
2007
|
+
*
|
|
2008
|
+
* @param ctx - The deploy plugin context.
|
|
2009
|
+
* @param deps - The injected dev deps (for the wrangler runner).
|
|
2010
|
+
* @returns Resolves once the seed file has executed and every cached KV key is cleared.
|
|
2011
|
+
* @throws {Error} When `--seed` is set but no seed is configured under `pluginConfigs.deploy.seed`.
|
|
2012
|
+
* @example
|
|
2013
|
+
* ```ts
|
|
2014
|
+
* await seedLocal(ctx, realDevDeps());
|
|
2015
|
+
* ```
|
|
2016
|
+
*/
|
|
2017
|
+
const seedLocal = async (ctx, deps) => {
|
|
2018
|
+
const config = ctx.config.seed;
|
|
2019
|
+
if (config === void 0) throw new Error("[moku-worker] dev({ seed: true }) but no seed is configured — set pluginConfigs.deploy.seed.");
|
|
2020
|
+
ctx.emit("dev:phase", {
|
|
2021
|
+
phase: "seed",
|
|
2022
|
+
detail: config.file
|
|
2023
|
+
});
|
|
2024
|
+
await runConfiguredSeed(ctx, deps.runWrangler, config, "--local");
|
|
2025
|
+
};
|
|
2026
|
+
/**
|
|
2027
|
+
* Run a long-lived dev session: cold build → (local d1 migrate) → (local seed) → spawn `wrangler
|
|
2028
|
+
* dev` → watch + rebuild on change → teardown on signal.
|
|
1935
2029
|
*
|
|
1936
2030
|
* @param ctx - The deploy plugin context (config + emit + require/has).
|
|
1937
2031
|
* @param opts - Optional options.
|
|
@@ -1939,23 +2033,25 @@ const rebuild = async (ctx, deps, changedPaths, hooks) => {
|
|
|
1939
2033
|
* @param opts.webBuild - Cold-build hook (also the per-change rebuild when `onChange` is omitted).
|
|
1940
2034
|
* @param opts.onChange - Incremental per-change rebuild hook (e.g. `c => web.cli.update(c)`); when
|
|
1941
2035
|
* set, each debounced change rebuilds only the changed paths instead of a full `webBuild()`.
|
|
2036
|
+
* @param opts.seed - Load the configured seed into the LOCAL D1 (+ reset its KV keys) before serving.
|
|
1942
2037
|
* @param deps - Injected side effects (real ones from realDevDeps in production).
|
|
1943
2038
|
* @returns Resolves when the session ends (SIGINT).
|
|
1944
2039
|
* @example
|
|
1945
2040
|
* ```ts
|
|
1946
|
-
* await runDev(ctx, { port: 8787, webBuild: () => web.cli.build()
|
|
2041
|
+
* await runDev(ctx, { port: 8787, seed: true, webBuild: () => web.cli.build() }, realDevDeps());
|
|
1947
2042
|
* ```
|
|
1948
2043
|
*/
|
|
1949
2044
|
const runDev = async (ctx, opts, deps) => {
|
|
1950
2045
|
const port = opts?.port ?? 8787;
|
|
1951
2046
|
const webBuild = opts?.webBuild;
|
|
1952
2047
|
const onChange = opts?.onChange;
|
|
2048
|
+
const seed = opts?.seed === true;
|
|
1953
2049
|
ctx.emit("dev:phase", {
|
|
1954
2050
|
phase: "build",
|
|
1955
2051
|
detail: "site"
|
|
1956
2052
|
});
|
|
1957
2053
|
await deps.build(ctx, webBuild);
|
|
1958
|
-
const migrationBindings = ctx.config.migrateLocal ? d1MigrationBindings(ctx) : [];
|
|
2054
|
+
const migrationBindings = ctx.config.migrateLocal || seed ? d1MigrationBindings(ctx) : [];
|
|
1959
2055
|
if (migrationBindings.length > 0) {
|
|
1960
2056
|
ctx.emit("dev:phase", {
|
|
1961
2057
|
phase: "migrate",
|
|
@@ -1969,6 +2065,7 @@ const runDev = async (ctx, opts, deps) => {
|
|
|
1969
2065
|
"--local"
|
|
1970
2066
|
]);
|
|
1971
2067
|
}
|
|
2068
|
+
if (seed) await seedLocal(ctx, deps);
|
|
1972
2069
|
ctx.emit("dev:phase", {
|
|
1973
2070
|
phase: "serve",
|
|
1974
2071
|
detail: `http://localhost:${String(port)}`
|
|
@@ -2951,17 +3048,33 @@ const HINTS = {
|
|
|
2951
3048
|
deploy: "wrangler deploy failed — review the output above, then retry."
|
|
2952
3049
|
};
|
|
2953
3050
|
/**
|
|
2954
|
-
* Emit the terminal `aborted` phase
|
|
2955
|
-
* the user stops the deploy
|
|
3051
|
+
* Emit the terminal `aborted` phase AND build the matching {@link DeployReport} — the single exit
|
|
3052
|
+
* every guided gate/retry funnels through when the user stops the deploy (or auth was never set up).
|
|
3053
|
+
* Centralizing it keeps every abort path emitting one consistent line and returning the same shaped
|
|
3054
|
+
* report: `status: "aborted"`, both post-steps `"skipped"`, no errors — so a calling script sees a
|
|
3055
|
+
* clean stop, never a half-filled success, and the remote-DB migration/seed are guaranteed unrun.
|
|
2956
3056
|
*
|
|
2957
3057
|
* @param ctx - The deploy plugin context.
|
|
2958
|
-
* @
|
|
3058
|
+
* @param stage - The resolved deploy stage (echoed into the report).
|
|
3059
|
+
* @param startedAt - The run's start timestamp, for the elapsed field.
|
|
3060
|
+
* @returns The aborted deploy report.
|
|
2959
3061
|
* @example
|
|
2960
3062
|
* ```ts
|
|
2961
|
-
* if (declined) return
|
|
3063
|
+
* if (declined) return aborted(ctx, stage, startedAt);
|
|
2962
3064
|
* ```
|
|
2963
3065
|
*/
|
|
2964
|
-
const
|
|
3066
|
+
const aborted = (ctx, stage, startedAt) => {
|
|
3067
|
+
ctx.emit("deploy:phase", { phase: "aborted" });
|
|
3068
|
+
return {
|
|
3069
|
+
ok: false,
|
|
3070
|
+
status: "aborted",
|
|
3071
|
+
stage,
|
|
3072
|
+
migration: "skipped",
|
|
3073
|
+
seed: "skipped",
|
|
3074
|
+
elapsedMs: Date.now() - startedAt,
|
|
3075
|
+
errors: []
|
|
3076
|
+
};
|
|
3077
|
+
};
|
|
2965
3078
|
/**
|
|
2966
3079
|
* The full guided token setup shown after an auth failure on a TTY. Offers to walk the user through
|
|
2967
3080
|
* it, and when accepted: prints WHERE to create the Cloudflare token (dashboard URL, which template,
|
|
@@ -3181,6 +3294,104 @@ const guidedDeployStep = async (ctx, manifest, stage, deps) => {
|
|
|
3181
3294
|
return url;
|
|
3182
3295
|
};
|
|
3183
3296
|
/**
|
|
3297
|
+
* Apply pending D1 migrations to the REMOTE database for every configured d1 instance that ships a
|
|
3298
|
+
* migrations dir — the generic, deploy-owned analogue of `wrangler d1 migrations apply <binding>
|
|
3299
|
+
* --remote`. The wrangler config was written earlier in the pipeline, so each binding resolves. The
|
|
3300
|
+
* caller runs this only AFTER a successful deploy, so a deploy that never happened never migrates a
|
|
3301
|
+
* remote DB. Streams wrangler's output; throws on the first non-zero exit (the caller folds it into
|
|
3302
|
+
* the report).
|
|
3303
|
+
*
|
|
3304
|
+
* @param ctx - The deploy plugin context.
|
|
3305
|
+
* @returns Resolves once every configured database's remote migrations have been applied.
|
|
3306
|
+
* @example
|
|
3307
|
+
* ```ts
|
|
3308
|
+
* await applyRemoteMigrations(ctx);
|
|
3309
|
+
* ```
|
|
3310
|
+
*/
|
|
3311
|
+
const applyRemoteMigrations = async (ctx) => {
|
|
3312
|
+
if (!ctx.has("d1")) return;
|
|
3313
|
+
for (const database of ctx.require(d1Plugin).deployManifest()) if (database.migrations !== void 0) await runWranglerInherit([
|
|
3314
|
+
"d1",
|
|
3315
|
+
"migrations",
|
|
3316
|
+
"apply",
|
|
3317
|
+
database.binding,
|
|
3318
|
+
"--remote"
|
|
3319
|
+
]);
|
|
3320
|
+
};
|
|
3321
|
+
/**
|
|
3322
|
+
* Render a post-deploy step's failure as a branded line and capture its message into `errors` —
|
|
3323
|
+
* folding the failure into the report instead of throwing, so a deploy that already went live still
|
|
3324
|
+
* yields a complete, honest report when a later remote step (migration/seed) fails.
|
|
3325
|
+
*
|
|
3326
|
+
* @param ui - The branded console to render the error through.
|
|
3327
|
+
* @param errors - The accumulator the captured message is pushed into.
|
|
3328
|
+
* @param error - The thrown error (or value) to brand and capture.
|
|
3329
|
+
* @returns The captured (branded) message.
|
|
3330
|
+
* @example
|
|
3331
|
+
* ```ts
|
|
3332
|
+
* captureFailure(ui, errors, new Error("[moku-worker] seed failed"));
|
|
3333
|
+
* ```
|
|
3334
|
+
*/
|
|
3335
|
+
const captureFailure = (ui, errors, error) => {
|
|
3336
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3337
|
+
ui.error(message);
|
|
3338
|
+
errors.push(message);
|
|
3339
|
+
return message;
|
|
3340
|
+
};
|
|
3341
|
+
/**
|
|
3342
|
+
* Run the post-deploy remote steps — REACHED ONLY ON A SUCCESSFUL DEPLOY (every gate in `run` returns
|
|
3343
|
+
* early before here), so a deploy that never happened never touches a remote DB. Applies remote D1
|
|
3344
|
+
* migrations (when requested), then loads the configured seed (when requested) — but skips the seed
|
|
3345
|
+
* if the migration it depends on failed. Each step's failure is RENDERED inline and CAPTURED in
|
|
3346
|
+
* `errors` (never thrown), so one failed step still yields a complete, honest report.
|
|
3347
|
+
*
|
|
3348
|
+
* @param ctx - The deploy plugin context.
|
|
3349
|
+
* @param want - Which post-steps the caller requested.
|
|
3350
|
+
* @param want.migration - Whether to apply pending remote D1 migrations.
|
|
3351
|
+
* @param want.seed - Whether to load the configured remote seed (and reset its KV keys).
|
|
3352
|
+
* @returns The migration + seed outcomes and any captured branded errors.
|
|
3353
|
+
* @example
|
|
3354
|
+
* ```ts
|
|
3355
|
+
* const post = await runPostDeploy(ctx, { migration: true, seed: true });
|
|
3356
|
+
* ```
|
|
3357
|
+
*/
|
|
3358
|
+
const runPostDeploy = async (ctx, want) => {
|
|
3359
|
+
const ui = createBrandConsole();
|
|
3360
|
+
const errors = [];
|
|
3361
|
+
let migration = "skipped";
|
|
3362
|
+
if (want.migration) try {
|
|
3363
|
+
await applyRemoteMigrations(ctx);
|
|
3364
|
+
migration = "applied";
|
|
3365
|
+
ui.check(true, "migrated", "remote D1");
|
|
3366
|
+
} catch (error) {
|
|
3367
|
+
migration = "failed";
|
|
3368
|
+
captureFailure(ui, errors, error);
|
|
3369
|
+
}
|
|
3370
|
+
let seed = "skipped";
|
|
3371
|
+
if (want.seed && migration === "failed") {
|
|
3372
|
+
seed = "failed";
|
|
3373
|
+
captureFailure(ui, errors, /* @__PURE__ */ new Error("[moku-worker] seed skipped — the remote migration it depends on failed."));
|
|
3374
|
+
} else if (want.seed) {
|
|
3375
|
+
const config = ctx.config.seed;
|
|
3376
|
+
if (config === void 0) {
|
|
3377
|
+
seed = "failed";
|
|
3378
|
+
captureFailure(ui, errors, /* @__PURE__ */ new Error("[moku-worker] deploy({ seed: true }) but no seed is configured — set pluginConfigs.deploy.seed."));
|
|
3379
|
+
} else try {
|
|
3380
|
+
await runConfiguredSeed(ctx, runWranglerInherit, config, "--remote");
|
|
3381
|
+
seed = "applied";
|
|
3382
|
+
ui.check(true, "seeded", config.file);
|
|
3383
|
+
} catch (error) {
|
|
3384
|
+
seed = "failed";
|
|
3385
|
+
captureFailure(ui, errors, error);
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3388
|
+
return {
|
|
3389
|
+
migration,
|
|
3390
|
+
seed,
|
|
3391
|
+
errors
|
|
3392
|
+
};
|
|
3393
|
+
};
|
|
3394
|
+
/**
|
|
3184
3395
|
* Create the deploy api. Assembles the manifest from each resource plugin's own deployManifest(),
|
|
3185
3396
|
* runs an infra preflight (check-before-create + id capture), generates config, uploads, and runs
|
|
3186
3397
|
* `wrangler deploy`, emitting global deploy events along the way.
|
|
@@ -3196,13 +3407,19 @@ const guidedDeployStep = async (ctx, manifest, stage, deps) => {
|
|
|
3196
3407
|
const createDeployApi = (ctx) => ({
|
|
3197
3408
|
/**
|
|
3198
3409
|
* Run the full deploy pipeline: detect → preflight (check-before-create) → provision (only the
|
|
3199
|
-
* missing) → wrangler-config (with real ids) → upload → deploy
|
|
3200
|
-
*
|
|
3410
|
+
* missing) → wrangler-config (with real ids) → upload → deploy, then — ONLY on a successful
|
|
3411
|
+
* deploy — the requested post-deploy remote steps (migration, seed). When opts.manifest is
|
|
3412
|
+
* supplied it is used verbatim (universal path).
|
|
3201
3413
|
*
|
|
3202
3414
|
* On a TTY the run is GUIDED end to end: each gate is confirmed, and every failure is recovered
|
|
3203
|
-
* interactively rather than thrown — a missing/invalid token offers `
|
|
3204
|
-
* infra, upload, and `wrangler deploy` steps offer a retry. In CI/pipes it fails fast
|
|
3205
|
-
* the first error propagates to the branded CLI handler).
|
|
3415
|
+
* interactively rather than thrown — a missing/invalid token offers a `.env.local` scaffold, and
|
|
3416
|
+
* the build, infra, upload, and `wrangler deploy` steps offer a retry. In CI/pipes it fails fast
|
|
3417
|
+
* (no prompt, the first error propagates to the branded CLI handler).
|
|
3418
|
+
*
|
|
3419
|
+
* Resolves to a {@link DeployReport}. Every abort path (a declined gate, or auth never set up)
|
|
3420
|
+
* returns `status: "aborted"` BEFORE the post-deploy steps, so `migration`/`seed` run only when
|
|
3421
|
+
* the worker actually went live — a first `deploy --seed` with no token aborts cleanly instead of
|
|
3422
|
+
* falling through to a raw `wrangler … --remote` auth error.
|
|
3206
3423
|
*
|
|
3207
3424
|
* @param opts - Optional run options.
|
|
3208
3425
|
* @param opts.ci - CI/automated mode: never prompts, auto-confirms every gate, fails fast. When
|
|
@@ -3211,11 +3428,15 @@ const createDeployApi = (ctx) => ({
|
|
|
3211
3428
|
* @param opts.stage - Target stage; suffixes resource names (`production` = bare). Falls back to the app stage.
|
|
3212
3429
|
* @param opts.webBuild - Build the web site first (e.g. `() => webApp.cli.build()`), before deploy.
|
|
3213
3430
|
* @param opts.manifest - Caller-supplied manifest (bypasses deployManifest() assembly).
|
|
3214
|
-
* @
|
|
3431
|
+
* @param opts.migration - After a successful deploy, apply pending remote D1 migrations for every
|
|
3432
|
+
* configured d1 instance that ships migrations. Skipped (not attempted) on an aborted deploy.
|
|
3433
|
+
* @param opts.seed - After a successful deploy (+ migration), load the seed configured under
|
|
3434
|
+
* `pluginConfigs.deploy.seed` into the remote D1 and reset its cached KV keys. Skipped on abort.
|
|
3435
|
+
* @returns The deploy report (status, url, resource tally, migration/seed outcome, errors).
|
|
3215
3436
|
* @example
|
|
3216
3437
|
* ```ts
|
|
3217
|
-
* await api.run({ webBuild: () => web.cli.build()
|
|
3218
|
-
*
|
|
3438
|
+
* const report = await api.run({ webBuild: () => web.cli.build(), migration: true, seed: true });
|
|
3439
|
+
* if (!report.ok) process.exitCode = 1; // aborted or a post-step failed
|
|
3219
3440
|
* ```
|
|
3220
3441
|
*/
|
|
3221
3442
|
async run(opts) {
|
|
@@ -3228,26 +3449,44 @@ const createDeployApi = (ctx) => ({
|
|
|
3228
3449
|
};
|
|
3229
3450
|
const startedAt = Date.now();
|
|
3230
3451
|
ctx.emit("deploy:phase", { phase: "auth" });
|
|
3231
|
-
if (!await guidedAuth(ctx, deps)) return
|
|
3232
|
-
if (!await guidedWebBuild(ctx, opts?.webBuild ?? ctx.config.webBuild, deps)) return
|
|
3452
|
+
if (!await guidedAuth(ctx, deps)) return aborted(ctx, stage, startedAt);
|
|
3453
|
+
if (!await guidedWebBuild(ctx, opts?.webBuild ?? ctx.config.webBuild, deps)) return aborted(ctx, stage, startedAt);
|
|
3233
3454
|
ctx.emit("deploy:phase", { phase: "detect" });
|
|
3234
3455
|
const manifest = opts?.manifest ?? assembleManifest(ctx, stage);
|
|
3235
3456
|
ctx.emit("deploy:phase", { phase: "provision" });
|
|
3236
3457
|
const provisioned = await guidedProvision(ctx, manifest, ci, deps);
|
|
3237
|
-
if (provisioned === ABORTED) return
|
|
3458
|
+
if (provisioned === ABORTED) return aborted(ctx, stage, startedAt);
|
|
3238
3459
|
ctx.emit("deploy:phase", { phase: "wrangler-config" });
|
|
3239
3460
|
await writeWranglerConfig(ctx.config.configFile, manifest, provisioned.ids, wranglerExtra(ctx.config));
|
|
3240
|
-
if (!await guidedUpload(ctx, manifest, deps)) return
|
|
3461
|
+
if (!await guidedUpload(ctx, manifest, deps)) return aborted(ctx, stage, startedAt);
|
|
3241
3462
|
const url = await guidedDeployStep(ctx, manifest, stage, deps);
|
|
3242
|
-
if (url === void 0) return
|
|
3463
|
+
if (url === void 0) return aborted(ctx, stage, startedAt);
|
|
3464
|
+
const resources = {
|
|
3465
|
+
created: provisioned.created.length,
|
|
3466
|
+
exists: provisioned.skipped.length,
|
|
3467
|
+
failed: provisioned.failed.length
|
|
3468
|
+
};
|
|
3243
3469
|
renderDeploySummary(createBrandConsole(), {
|
|
3244
3470
|
url,
|
|
3245
3471
|
stage,
|
|
3246
|
-
|
|
3247
|
-
exists: provisioned.skipped.length,
|
|
3248
|
-
failed: provisioned.failed.length,
|
|
3472
|
+
...resources,
|
|
3249
3473
|
elapsedMs: Date.now() - startedAt
|
|
3250
3474
|
});
|
|
3475
|
+
const post = await runPostDeploy(ctx, {
|
|
3476
|
+
migration: opts?.migration === true,
|
|
3477
|
+
seed: opts?.seed === true
|
|
3478
|
+
});
|
|
3479
|
+
return {
|
|
3480
|
+
ok: post.errors.length === 0,
|
|
3481
|
+
status: post.errors.length === 0 ? "deployed" : "failed",
|
|
3482
|
+
stage,
|
|
3483
|
+
url,
|
|
3484
|
+
resources,
|
|
3485
|
+
migration: post.migration,
|
|
3486
|
+
seed: post.seed,
|
|
3487
|
+
elapsedMs: Date.now() - startedAt,
|
|
3488
|
+
errors: post.errors
|
|
3489
|
+
};
|
|
3251
3490
|
},
|
|
3252
3491
|
/**
|
|
3253
3492
|
* Start a long-lived local dev session: cold-build the Moku site, spawn `wrangler dev
|
|
@@ -3260,10 +3499,12 @@ const createDeployApi = (ctx) => ({
|
|
|
3260
3499
|
* @param opts.webBuild - Cold-build the web site (e.g. `() => webApp.cli.build()`); also the
|
|
3261
3500
|
* per-change rebuild when `onChange` is omitted.
|
|
3262
3501
|
* @param opts.onChange - Incremental per-change rebuild (e.g. `changes => webApp.cli.update(changes)`).
|
|
3502
|
+
* @param opts.seed - Load the configured seed (`pluginConfigs.deploy.seed`) into the LOCAL D1 and
|
|
3503
|
+
* reset its cached KV keys before serving — the local analogue of `deploy({ seed: true })`.
|
|
3263
3504
|
* @returns Resolves when the dev session ends.
|
|
3264
3505
|
* @example
|
|
3265
3506
|
* ```ts
|
|
3266
|
-
* await api.dev({ port: 8787, webBuild: () => web.cli.build(), onChange: c => web.cli.update(c) });
|
|
3507
|
+
* await api.dev({ port: 8787, seed: true, webBuild: () => web.cli.build(), onChange: c => web.cli.update(c) });
|
|
3267
3508
|
* ```
|
|
3268
3509
|
*/
|
|
3269
3510
|
async dev(opts) {
|
|
@@ -3293,11 +3534,7 @@ const createDeployApi = (ctx) => ({
|
|
|
3293
3534
|
if (!ctx.has("d1")) throw new Error("[moku-worker] seed: no d1 database is configured.");
|
|
3294
3535
|
const stage = opts?.stage ?? ctx.global.stage;
|
|
3295
3536
|
await writeWranglerConfig(ctx.config.configFile, assembleManifest(ctx, stage), {}, wranglerExtra(ctx.config));
|
|
3296
|
-
const
|
|
3297
|
-
const wanted = opts?.binding;
|
|
3298
|
-
const matched = wanted === void 0 ? databases : databases.filter((database) => database.binding === wanted);
|
|
3299
|
-
const target = matched.length === 1 ? matched[0] : void 0;
|
|
3300
|
-
if (target === void 0) throw new Error(wanted === void 0 ? `[moku-worker] seed: ${String(databases.length)} d1 databases configured — pass { binding } to choose one.` : `[moku-worker] seed: no d1 database is bound to "${wanted}".`);
|
|
3537
|
+
const target = resolveD1(ctx, opts?.binding);
|
|
3301
3538
|
const scope = opts?.remote === true ? "--remote" : "--local";
|
|
3302
3539
|
if (scope === "--local" && target.migrations !== void 0) await runWranglerInherit([
|
|
3303
3540
|
"d1",
|
|
@@ -3520,10 +3757,12 @@ const createCliApi = (ctx) => ({
|
|
|
3520
3757
|
* per-change rebuild when `onChange` is omitted.
|
|
3521
3758
|
* @param opts.onChange - Incremental per-change rebuild (e.g. `changes => webApp.cli.update(changes)`),
|
|
3522
3759
|
* so each change rebuilds only the changed paths instead of a full `webBuild()`.
|
|
3760
|
+
* @param opts.seed - Load the configured seed (`pluginConfigs.deploy.seed`) into the LOCAL D1 and
|
|
3761
|
+
* reset its cached KV keys before serving — the local analogue of `deploy({ seed: true })`.
|
|
3523
3762
|
* @returns Resolves when the dev session ends.
|
|
3524
3763
|
* @example
|
|
3525
3764
|
* ```ts
|
|
3526
|
-
* await api.dev({ port: 7878, webBuild: () => web.cli.build(), onChange: c => web.cli.update(c) });
|
|
3765
|
+
* await api.dev({ port: 7878, seed: true, webBuild: () => web.cli.build(), onChange: c => web.cli.update(c) });
|
|
3527
3766
|
* ```
|
|
3528
3767
|
*/
|
|
3529
3768
|
async dev(opts) {
|
|
@@ -3538,7 +3777,8 @@ const createCliApi = (ctx) => ({
|
|
|
3538
3777
|
...opts?.port === void 0 ? {} : { port: opts.port },
|
|
3539
3778
|
...stage === void 0 ? {} : { stage },
|
|
3540
3779
|
...opts?.webBuild ? { webBuild: opts.webBuild } : {},
|
|
3541
|
-
...opts?.onChange ? { onChange: opts.onChange } : {}
|
|
3780
|
+
...opts?.onChange ? { onChange: opts.onChange } : {},
|
|
3781
|
+
...opts?.seed ? { seed: opts.seed } : {}
|
|
3542
3782
|
});
|
|
3543
3783
|
ui.check(true, "dev session stopped cleanly");
|
|
3544
3784
|
} catch (error) {
|
|
@@ -3547,32 +3787,48 @@ const createCliApi = (ctx) => ({
|
|
|
3547
3787
|
}
|
|
3548
3788
|
},
|
|
3549
3789
|
/**
|
|
3550
|
-
* One-command Cloudflare deploy; forwards opts verbatim to deploy.run
|
|
3551
|
-
*
|
|
3552
|
-
*
|
|
3553
|
-
*
|
|
3790
|
+
* One-command Cloudflare deploy; forwards opts verbatim to deploy.run, then — only on a successful
|
|
3791
|
+
* deploy — the requested post-deploy migration/seed. Guided/interactive by default; `{ ci: true }`
|
|
3792
|
+
* runs the automated path (CI). A `webBuild` hook builds the web site first (before `wrangler
|
|
3793
|
+
* deploy`). RETURNS the structured {@link DeployReport}; on a failure it also renders a branded `✗`
|
|
3794
|
+
* line + sets a non-zero exit code (matching cli.auth/doctor), never a raw stack trace.
|
|
3554
3795
|
*
|
|
3555
3796
|
* @param opts - Optional deploy options.
|
|
3556
3797
|
* @param opts.ci - Automated mode: never prompts, auto-confirms. Omit/false → guided on a TTY.
|
|
3557
3798
|
* @param opts.stage - Target stage (resource-name suffix); falls back to `--stage` then the app stage.
|
|
3558
3799
|
* @param opts.webBuild - Build the web site first (e.g. `() => webApp.cli.build()`), before deploy.
|
|
3559
|
-
* @
|
|
3800
|
+
* @param opts.migration - Apply pending remote D1 migrations after a successful deploy (skipped on abort).
|
|
3801
|
+
* @param opts.seed - Load the configured remote seed (`pluginConfigs.deploy.seed`) after a
|
|
3802
|
+
* successful deploy (+ migration); skipped on an aborted deploy.
|
|
3803
|
+
* @returns The deploy report (status, url, resource tally, migration/seed outcome, errors).
|
|
3560
3804
|
* @example
|
|
3561
3805
|
* ```ts
|
|
3562
|
-
* await api.deploy({ webBuild: () => web.cli.build()
|
|
3563
|
-
*
|
|
3806
|
+
* const report = await api.deploy({ webBuild: () => web.cli.build(), migration: true, seed: true });
|
|
3807
|
+
* if (report.status === "aborted") return; // creds not set up yet — nothing shipped
|
|
3564
3808
|
* ```
|
|
3565
3809
|
*/
|
|
3566
3810
|
async deploy(opts) {
|
|
3567
3811
|
const stage = opts?.stage ?? parseStageArg(process.argv);
|
|
3568
3812
|
try {
|
|
3569
|
-
await ctx.require(deployPlugin).run({
|
|
3813
|
+
const report = await ctx.require(deployPlugin).run({
|
|
3570
3814
|
...opts,
|
|
3571
3815
|
...stage === void 0 ? {} : { stage }
|
|
3572
3816
|
});
|
|
3817
|
+
if (report.status === "failed") process.exitCode = 1;
|
|
3818
|
+
return report;
|
|
3573
3819
|
} catch (error) {
|
|
3574
|
-
|
|
3820
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3821
|
+
createBrandConsole().error(message);
|
|
3575
3822
|
process.exitCode = 1;
|
|
3823
|
+
return {
|
|
3824
|
+
ok: false,
|
|
3825
|
+
status: "failed",
|
|
3826
|
+
stage: stage ?? "production",
|
|
3827
|
+
migration: "skipped",
|
|
3828
|
+
seed: "skipped",
|
|
3829
|
+
elapsedMs: 0,
|
|
3830
|
+
errors: [message]
|
|
3831
|
+
};
|
|
3576
3832
|
}
|
|
3577
3833
|
},
|
|
3578
3834
|
/**
|
package/dist/cli.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_cli = require("./cli-
|
|
2
|
+
const require_cli = require("./cli-CfgYgnzW.cjs");
|
|
3
3
|
exports.cliPlugin = require_cli.cliPlugin;
|
|
4
4
|
exports.deployPlugin = require_cli.deployPlugin;
|
package/dist/cli.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as ResourceManifest, i as ExternalManifest, n as cliPlugin, t as deployPlugin } from "./index-Cb3vzZte.cjs";
|
|
2
2
|
export { type ExternalManifest, type ResourceManifest, cliPlugin, deployPlugin };
|
package/dist/cli.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as ResourceManifest, i as ExternalManifest, n as cliPlugin, t as deployPlugin } from "./index-Cb3vzZte.mjs";
|
|
2
2
|
export { type ExternalManifest, type ResourceManifest, cliPlugin, deployPlugin };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as deployPlugin, t as cliPlugin } from "./cli-
|
|
1
|
+
import { n as deployPlugin, t as cliPlugin } from "./cli-Cs3R3Jhr.mjs";
|
|
2
2
|
export { cliPlugin, deployPlugin };
|