@moku-labs/worker 0.9.0 → 0.9.1

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.
@@ -2090,12 +2090,12 @@ const runDev = async (ctx, opts, deps) => {
2090
2090
  //#endregion
2091
2091
  //#region src/plugins/deploy/infra/plan.ts
2092
2092
  /**
2093
- * Decide whether a single declared resource already exists in the account, recovering its id
2094
- * (kv/d1) when it does. Durable Objects are config-only — they ship with the Worker (`wrangler
2095
- * deploy` + the auto-derived DO migration create the namespace), never provisioned via the API — so
2096
- * they are treated as already EXISTING, and the plan never re-offers to "create" them each deploy.
2093
+ * Decide whether a single API-provisioned resource already exists in the account, recovering its id
2094
+ * (kv/d1) when it does. Durable Objects are NOT handled here — they ship with the Worker (`wrangler
2095
+ * deploy` + the auto-derived DO migration create the namespace), are never provisioned via the API,
2096
+ * and are partitioned into the plan's `ships` bucket by {@link planInfra} before this is ever called.
2097
2097
  *
2098
- * @param resource - The declared resource descriptor.
2098
+ * @param resource - The declared (provisionable) resource descriptor.
2099
2099
  * @param existing - The indexed set of resources already in the account.
2100
2100
  * @returns Whether it exists, plus the captured id for kv/d1.
2101
2101
  * @example
@@ -2121,7 +2121,6 @@ const checkExisting = (resource, existing) => {
2121
2121
  }
2122
2122
  case "r2": return { exists: existing.r2.has(resource.name) };
2123
2123
  case "queue": return { exists: existing.queue.has(resource.name) };
2124
- case "do": return { exists: true };
2125
2124
  }
2126
2125
  };
2127
2126
  /**
@@ -2130,7 +2129,7 @@ const checkExisting = (resource, existing) => {
2130
2129
  *
2131
2130
  * @param ctx - The deploy plugin context (env + emit).
2132
2131
  * @param manifest - The assembled (or caller-supplied) deploy manifest.
2133
- * @returns The infra plan: existing (with ids) vs missing resources.
2132
+ * @returns The infra plan: existing (with ids) vs missing vs ships-with-Worker (Durable Objects).
2134
2133
  * @throws {Error} When the token is absent/invalid or a Cloudflare listing fails.
2135
2134
  * @example
2136
2135
  * ```ts
@@ -2149,7 +2148,12 @@ const planInfra = async (ctx, manifest) => {
2149
2148
  const existing = await listExisting(token, account.id, kinds);
2150
2149
  const exists = [];
2151
2150
  const missing = [];
2151
+ const ships = [];
2152
2152
  for (const resource of manifest.resources) {
2153
+ if (resource.kind === "do") {
2154
+ ships.push(resource);
2155
+ continue;
2156
+ }
2153
2157
  const check = checkExisting(resource, existing);
2154
2158
  if (check.exists) exists.push(check.id === void 0 ? { resource } : {
2155
2159
  resource,
@@ -2160,13 +2164,15 @@ const planInfra = async (ctx, manifest) => {
2160
2164
  ctx.emit("provision:plan", {
2161
2165
  exists: exists.length,
2162
2166
  missing: missing.length,
2167
+ ships: ships.length,
2163
2168
  account: account.name
2164
2169
  });
2165
2170
  return {
2166
2171
  account: account.name,
2167
2172
  accountId: account.id,
2168
2173
  exists,
2169
- missing
2174
+ missing,
2175
+ ships
2170
2176
  };
2171
2177
  };
2172
2178
  //#endregion
@@ -2197,6 +2203,12 @@ const resourceName = (resource) => resource.kind === "do" ? resource.className :
2197
2203
  */
2198
2204
  const cell = (kind, name) => `${kind.padEnd(6)}${name}`;
2199
2205
  /**
2206
+ * Row tag for a Durable Object — it ships with the Worker (`wrangler deploy` creates the namespace),
2207
+ * so it is NEVER labelled `(exists)` (the planner never queried the account for it). Shared by the
2208
+ * plan and provision-result panels so the two always read the same.
2209
+ */
2210
+ const SHIPS_WITH_WORKER = "(ships with worker)";
2211
+ /**
2200
2212
  * ANSI SGR matcher — built from `String.fromCharCode(27)` (the ESC byte) so no control character
2201
2213
  * appears in a regex literal (which both linters reject).
2202
2214
  */
@@ -2257,10 +2269,11 @@ const wrapText = (text, width) => {
2257
2269
  /**
2258
2270
  * Render the infra preflight plan as a branded panel: a dim summary line (counts + account) then one
2259
2271
  * row per declared resource — a pink `+` for those to create, a dim `~ (exists)` for those already
2260
- * present. When nothing needs creating it still renders, so the user sees the full picture.
2272
+ * present, and a dim `~ (ships with worker)` for Durable Objects (created by `wrangler deploy`, never
2273
+ * pre-provisioned). When nothing needs creating it still renders, so the user sees the full picture.
2261
2274
  *
2262
2275
  * @param ui - The branded console to render through.
2263
- * @param plan - The infra plan (existing vs missing) from checkInfra()/planInfra().
2276
+ * @param plan - The infra plan (existing vs missing vs ships-with-Worker) from checkInfra()/planInfra().
2264
2277
  * @example
2265
2278
  * ```ts
2266
2279
  * renderPlan(ui, await planInfra(ctx, manifest));
@@ -2268,22 +2281,27 @@ const wrapText = (text, width) => {
2268
2281
  */
2269
2282
  const renderPlan = (ui, plan) => {
2270
2283
  const { palette } = ui;
2271
- const summary = palette.dim(`${String(plan.missing.length)} to create · ${String(plan.exists.length)} exist · ${plan.account}`);
2272
- const existsRows = plan.exists.map((ref) => `${palette.dim("~")} ${cell(ref.resource.kind, resourceName(ref.resource))} ${palette.dim("(exists)")}`);
2284
+ const counts = [`${String(plan.missing.length)} to create`, `${String(plan.exists.length)} exist`];
2285
+ if (plan.ships.length > 0) counts.push(`${String(plan.ships.length)} with worker`);
2286
+ const summary = palette.dim(`${counts.join(" · ")} · ${plan.account}`);
2273
2287
  const createRows = plan.missing.map((resource) => `${palette.pink("+")} ${cell(resource.kind, resourceName(resource))}`);
2288
+ const existsRows = plan.exists.map((ref) => `${palette.dim("~")} ${cell(ref.resource.kind, resourceName(ref.resource))} ${palette.dim("(exists)")}`);
2289
+ const shipsRows = plan.ships.map((resource) => `${palette.dim("~")} ${cell(resource.kind, resourceName(resource))} ${palette.dim(SHIPS_WITH_WORKER)}`);
2274
2290
  ui.heading("Infra plan");
2275
2291
  ui.box([
2276
2292
  summary,
2277
2293
  "",
2278
2294
  ...createRows,
2279
- ...existsRows
2295
+ ...existsRows,
2296
+ ...shipsRows
2280
2297
  ]);
2281
2298
  };
2282
2299
  /**
2283
2300
  * Render the provision result as a branded panel — a green `✓` per created resource, a dim `~` per
2284
- * skipped, a red `✗` per failure, then a summary line (failed count red when non-zero) — followed,
2285
- * when anything failed, by a detail block printing each failure's FULL reason (ANSI-stripped and
2286
- * word-wrapped) so it is actually readable instead of truncated inside the box.
2301
+ * skipped, a dim `~ (ships with worker)` per Durable Object, a red `✗` per failure, then a summary
2302
+ * line (failed count red when non-zero) — followed, when anything failed, by a detail block printing
2303
+ * each failure's FULL reason (ANSI-stripped and word-wrapped) so it is actually readable instead of
2304
+ * truncated inside the box.
2287
2305
  *
2288
2306
  * @param ui - The branded console to render through.
2289
2307
  * @param result - The provision result from provisionInfra()/the deploy pipeline.
@@ -2296,13 +2314,17 @@ const renderProvisionResult = (ui, result) => {
2296
2314
  const { palette } = ui;
2297
2315
  const createdRows = result.created.map((ref) => `${palette.green("✓")} ${cell(ref.resource.kind, resourceName(ref.resource))}`);
2298
2316
  const skippedRows = result.skipped.map((ref) => `${palette.dim("~")} ${cell(ref.resource.kind, resourceName(ref.resource))} ${palette.dim("(exists)")}`);
2317
+ const bundledRows = result.bundled.map((resource) => `${palette.dim("~")} ${cell(resource.kind, resourceName(resource))} ${palette.dim(SHIPS_WITH_WORKER)}`);
2299
2318
  const failedRows = result.failed.map((failure) => `${palette.red("✗")} ${cell(failure.resource.kind, resourceName(failure.resource))}`);
2300
2319
  const failedCount = result.failed.length > 0 ? palette.red(`${String(result.failed.length)} failed`) : "0 failed";
2301
- const summary = `${String(result.created.length)} created · ${String(result.skipped.length)} exist · ${failedCount}`;
2320
+ const counts = [`${String(result.created.length)} created`, `${String(result.skipped.length)} exist`];
2321
+ if (result.bundled.length > 0) counts.push(`${String(result.bundled.length)} with worker`);
2322
+ const summary = `${counts.join(" · ")} · ${failedCount}`;
2302
2323
  ui.heading("Provisioned");
2303
2324
  ui.box([
2304
2325
  ...createdRows,
2305
2326
  ...skippedRows,
2327
+ ...bundledRows,
2306
2328
  ...failedRows,
2307
2329
  "",
2308
2330
  summary
@@ -2345,16 +2367,19 @@ const formatDuration = (ms) => {
2345
2367
  * @param summary.stage - The target stage the worker deployed to.
2346
2368
  * @param summary.created - How many resources were created this run.
2347
2369
  * @param summary.exists - How many resources already existed (skipped).
2370
+ * @param summary.bundled - How many Durable Objects shipped with the Worker.
2348
2371
  * @param summary.failed - How many resources failed to provision.
2349
2372
  * @param summary.elapsedMs - The wall-clock deploy duration in milliseconds.
2350
2373
  * @example
2351
2374
  * ```ts
2352
- * renderDeploySummary(ui, { url, stage: "production", created: 0, exists: 5, failed: 0, elapsedMs: 4234 });
2375
+ * renderDeploySummary(ui, { url, stage: "production", created: 0, exists: 5, bundled: 1, failed: 0, elapsedMs: 4234 });
2353
2376
  * ```
2354
2377
  */
2355
2378
  const renderDeploySummary = (ui, summary) => {
2356
2379
  const { palette } = ui;
2357
- const tally = `${String(summary.exists)} exist · ${String(summary.created)} created`;
2380
+ const parts = [`${String(summary.exists)} exist`, `${String(summary.created)} created`];
2381
+ if (summary.bundled > 0) parts.push(`${String(summary.bundled)} with worker`);
2382
+ const tally = parts.join(" · ");
2358
2383
  const failedLabel = palette.red(`${String(summary.failed)} failed`);
2359
2384
  const resources = summary.failed > 0 ? `${tally} · ${failedLabel}` : tally;
2360
2385
  ui.heading("Deployed");
@@ -2986,32 +3011,25 @@ const assembleManifest = (ctx, stage) => {
2986
3011
  };
2987
3012
  };
2988
3013
  /**
2989
- * Act on an infra plan: skip the resources that already exist (reusing their ids), create the
2990
- * missing ones (capturing each new id), and announce each via provision:skip / :resource. Resilient
2991
- * — a single resource that fails to create is CAPTURED in `failed` (not thrown), so one bad resource
2992
- * (e.g. an invalid bucket name) never aborts the whole run and the caller can report a clear result.
3014
+ * Create the still-missing resources one at a time: provision each, fold its captured id (kv/d1) into
3015
+ * the shared `ids` map, and announce it via provision:resource. Resilient — a single failure is
3016
+ * CAPTURED (not thrown), so one bad resource never aborts the rest. Extracted from {@link applyPlan}
3017
+ * so that orchestrator stays flat (skip existing, skip DOs, create missing).
2993
3018
  *
2994
3019
  * @param ctx - The deploy plugin context.
2995
- * @param plan - The infra plan from planInfra (existing vs missing).
3020
+ * @param missing - The resources the plan flagged as not-yet-existing.
2996
3021
  * @param ci - Whether provisioning runs non-interactively (forwarded to each provider).
2997
- * @returns The provisioning result: created, skipped, failed, and the merged binding id map.
3022
+ * @param ids - The binding Cloudflare id map, mutated in place with each created kv/d1 id.
3023
+ * @returns The created refs and any captured per-resource failures.
2998
3024
  * @example
2999
3025
  * ```ts
3000
- * const { created, failed } = await applyPlan(ctx, plan, false);
3026
+ * const { created, failed } = await provisionMissing(ctx, plan.missing, false, ids);
3001
3027
  * ```
3002
3028
  */
3003
- const applyPlan = async (ctx, plan, ci) => {
3004
- const ids = {};
3005
- for (const ref of plan.exists) {
3006
- if (ref.id !== void 0 && (ref.resource.kind === "kv" || ref.resource.kind === "d1")) ids[ref.resource.binding] = ref.id;
3007
- ctx.emit("provision:skip", {
3008
- kind: ref.resource.kind,
3009
- name: resourceName(ref.resource)
3010
- });
3011
- }
3029
+ const provisionMissing = async (ctx, missing, ci, ids) => {
3012
3030
  const created = [];
3013
3031
  const failed = [];
3014
- for (const resource of plan.missing) try {
3032
+ for (const resource of missing) try {
3015
3033
  const { id } = await provisionResource(resource, ci);
3016
3034
  if (id !== void 0 && (resource.kind === "kv" || resource.kind === "d1")) ids[resource.binding] = id;
3017
3035
  created.push(id === void 0 ? { resource } : {
@@ -3028,9 +3046,45 @@ const applyPlan = async (ctx, plan, ci) => {
3028
3046
  error: error instanceof Error ? error.message : String(error)
3029
3047
  });
3030
3048
  }
3049
+ return {
3050
+ created,
3051
+ failed
3052
+ };
3053
+ };
3054
+ /**
3055
+ * Act on an infra plan: skip the resources that already exist (reusing their ids), skip the Durable
3056
+ * Objects that ship with the Worker, create the missing ones (capturing each new id), and announce
3057
+ * each via provision:skip / :resource. Resilient — a single resource that fails to create is CAPTURED
3058
+ * in `failed` (not thrown), so one bad resource (e.g. an invalid bucket name) never aborts the whole
3059
+ * run and the caller can report a clear result.
3060
+ *
3061
+ * @param ctx - The deploy plugin context.
3062
+ * @param plan - The infra plan from planInfra (existing vs missing vs ships-with-Worker).
3063
+ * @param ci - Whether provisioning runs non-interactively (forwarded to each provider).
3064
+ * @returns The provisioning result: created, skipped, bundled, failed, and the merged binding → id map.
3065
+ * @example
3066
+ * ```ts
3067
+ * const { created, failed } = await applyPlan(ctx, plan, false);
3068
+ * ```
3069
+ */
3070
+ const applyPlan = async (ctx, plan, ci) => {
3071
+ const ids = {};
3072
+ for (const ref of plan.exists) {
3073
+ if (ref.id !== void 0 && (ref.resource.kind === "kv" || ref.resource.kind === "d1")) ids[ref.resource.binding] = ref.id;
3074
+ ctx.emit("provision:skip", {
3075
+ kind: ref.resource.kind,
3076
+ name: resourceName(ref.resource)
3077
+ });
3078
+ }
3079
+ for (const resource of plan.ships) ctx.emit("provision:skip", {
3080
+ kind: resource.kind,
3081
+ name: resourceName(resource)
3082
+ });
3083
+ const { created, failed } = await provisionMissing(ctx, plan.missing, ci, ids);
3031
3084
  return {
3032
3085
  created,
3033
3086
  skipped: plan.exists,
3087
+ bundled: plan.ships,
3034
3088
  failed,
3035
3089
  ids
3036
3090
  };
@@ -3464,6 +3518,7 @@ const createDeployApi = (ctx) => ({
3464
3518
  const resources = {
3465
3519
  created: provisioned.created.length,
3466
3520
  exists: provisioned.skipped.length,
3521
+ bundled: provisioned.bundled.length,
3467
3522
  failed: provisioned.failed.length
3468
3523
  };
3469
3524
  renderDeploySummary(createBrandConsole(), {
@@ -2113,12 +2113,12 @@ const runDev = async (ctx, opts, deps) => {
2113
2113
  //#endregion
2114
2114
  //#region src/plugins/deploy/infra/plan.ts
2115
2115
  /**
2116
- * Decide whether a single declared resource already exists in the account, recovering its id
2117
- * (kv/d1) when it does. Durable Objects are config-only — they ship with the Worker (`wrangler
2118
- * deploy` + the auto-derived DO migration create the namespace), never provisioned via the API — so
2119
- * they are treated as already EXISTING, and the plan never re-offers to "create" them each deploy.
2116
+ * Decide whether a single API-provisioned resource already exists in the account, recovering its id
2117
+ * (kv/d1) when it does. Durable Objects are NOT handled here — they ship with the Worker (`wrangler
2118
+ * deploy` + the auto-derived DO migration create the namespace), are never provisioned via the API,
2119
+ * and are partitioned into the plan's `ships` bucket by {@link planInfra} before this is ever called.
2120
2120
  *
2121
- * @param resource - The declared resource descriptor.
2121
+ * @param resource - The declared (provisionable) resource descriptor.
2122
2122
  * @param existing - The indexed set of resources already in the account.
2123
2123
  * @returns Whether it exists, plus the captured id for kv/d1.
2124
2124
  * @example
@@ -2144,7 +2144,6 @@ const checkExisting = (resource, existing) => {
2144
2144
  }
2145
2145
  case "r2": return { exists: existing.r2.has(resource.name) };
2146
2146
  case "queue": return { exists: existing.queue.has(resource.name) };
2147
- case "do": return { exists: true };
2148
2147
  }
2149
2148
  };
2150
2149
  /**
@@ -2153,7 +2152,7 @@ const checkExisting = (resource, existing) => {
2153
2152
  *
2154
2153
  * @param ctx - The deploy plugin context (env + emit).
2155
2154
  * @param manifest - The assembled (or caller-supplied) deploy manifest.
2156
- * @returns The infra plan: existing (with ids) vs missing resources.
2155
+ * @returns The infra plan: existing (with ids) vs missing vs ships-with-Worker (Durable Objects).
2157
2156
  * @throws {Error} When the token is absent/invalid or a Cloudflare listing fails.
2158
2157
  * @example
2159
2158
  * ```ts
@@ -2172,7 +2171,12 @@ const planInfra = async (ctx, manifest) => {
2172
2171
  const existing = await listExisting(token, account.id, kinds);
2173
2172
  const exists = [];
2174
2173
  const missing = [];
2174
+ const ships = [];
2175
2175
  for (const resource of manifest.resources) {
2176
+ if (resource.kind === "do") {
2177
+ ships.push(resource);
2178
+ continue;
2179
+ }
2176
2180
  const check = checkExisting(resource, existing);
2177
2181
  if (check.exists) exists.push(check.id === void 0 ? { resource } : {
2178
2182
  resource,
@@ -2183,13 +2187,15 @@ const planInfra = async (ctx, manifest) => {
2183
2187
  ctx.emit("provision:plan", {
2184
2188
  exists: exists.length,
2185
2189
  missing: missing.length,
2190
+ ships: ships.length,
2186
2191
  account: account.name
2187
2192
  });
2188
2193
  return {
2189
2194
  account: account.name,
2190
2195
  accountId: account.id,
2191
2196
  exists,
2192
- missing
2197
+ missing,
2198
+ ships
2193
2199
  };
2194
2200
  };
2195
2201
  //#endregion
@@ -2220,6 +2226,12 @@ const resourceName = (resource) => resource.kind === "do" ? resource.className :
2220
2226
  */
2221
2227
  const cell = (kind, name) => `${kind.padEnd(6)}${name}`;
2222
2228
  /**
2229
+ * Row tag for a Durable Object — it ships with the Worker (`wrangler deploy` creates the namespace),
2230
+ * so it is NEVER labelled `(exists)` (the planner never queried the account for it). Shared by the
2231
+ * plan and provision-result panels so the two always read the same.
2232
+ */
2233
+ const SHIPS_WITH_WORKER = "(ships with worker)";
2234
+ /**
2223
2235
  * ANSI SGR matcher — built from `String.fromCharCode(27)` (the ESC byte) so no control character
2224
2236
  * appears in a regex literal (which both linters reject).
2225
2237
  */
@@ -2280,10 +2292,11 @@ const wrapText = (text, width) => {
2280
2292
  /**
2281
2293
  * Render the infra preflight plan as a branded panel: a dim summary line (counts + account) then one
2282
2294
  * row per declared resource — a pink `+` for those to create, a dim `~ (exists)` for those already
2283
- * present. When nothing needs creating it still renders, so the user sees the full picture.
2295
+ * present, and a dim `~ (ships with worker)` for Durable Objects (created by `wrangler deploy`, never
2296
+ * pre-provisioned). When nothing needs creating it still renders, so the user sees the full picture.
2284
2297
  *
2285
2298
  * @param ui - The branded console to render through.
2286
- * @param plan - The infra plan (existing vs missing) from checkInfra()/planInfra().
2299
+ * @param plan - The infra plan (existing vs missing vs ships-with-Worker) from checkInfra()/planInfra().
2287
2300
  * @example
2288
2301
  * ```ts
2289
2302
  * renderPlan(ui, await planInfra(ctx, manifest));
@@ -2291,22 +2304,27 @@ const wrapText = (text, width) => {
2291
2304
  */
2292
2305
  const renderPlan = (ui, plan) => {
2293
2306
  const { palette } = ui;
2294
- const summary = palette.dim(`${String(plan.missing.length)} to create · ${String(plan.exists.length)} exist · ${plan.account}`);
2295
- const existsRows = plan.exists.map((ref) => `${palette.dim("~")} ${cell(ref.resource.kind, resourceName(ref.resource))} ${palette.dim("(exists)")}`);
2307
+ const counts = [`${String(plan.missing.length)} to create`, `${String(plan.exists.length)} exist`];
2308
+ if (plan.ships.length > 0) counts.push(`${String(plan.ships.length)} with worker`);
2309
+ const summary = palette.dim(`${counts.join(" · ")} · ${plan.account}`);
2296
2310
  const createRows = plan.missing.map((resource) => `${palette.pink("+")} ${cell(resource.kind, resourceName(resource))}`);
2311
+ const existsRows = plan.exists.map((ref) => `${palette.dim("~")} ${cell(ref.resource.kind, resourceName(ref.resource))} ${palette.dim("(exists)")}`);
2312
+ const shipsRows = plan.ships.map((resource) => `${palette.dim("~")} ${cell(resource.kind, resourceName(resource))} ${palette.dim(SHIPS_WITH_WORKER)}`);
2297
2313
  ui.heading("Infra plan");
2298
2314
  ui.box([
2299
2315
  summary,
2300
2316
  "",
2301
2317
  ...createRows,
2302
- ...existsRows
2318
+ ...existsRows,
2319
+ ...shipsRows
2303
2320
  ]);
2304
2321
  };
2305
2322
  /**
2306
2323
  * Render the provision result as a branded panel — a green `✓` per created resource, a dim `~` per
2307
- * skipped, a red `✗` per failure, then a summary line (failed count red when non-zero) — followed,
2308
- * when anything failed, by a detail block printing each failure's FULL reason (ANSI-stripped and
2309
- * word-wrapped) so it is actually readable instead of truncated inside the box.
2324
+ * skipped, a dim `~ (ships with worker)` per Durable Object, a red `✗` per failure, then a summary
2325
+ * line (failed count red when non-zero) — followed, when anything failed, by a detail block printing
2326
+ * each failure's FULL reason (ANSI-stripped and word-wrapped) so it is actually readable instead of
2327
+ * truncated inside the box.
2310
2328
  *
2311
2329
  * @param ui - The branded console to render through.
2312
2330
  * @param result - The provision result from provisionInfra()/the deploy pipeline.
@@ -2319,13 +2337,17 @@ const renderProvisionResult = (ui, result) => {
2319
2337
  const { palette } = ui;
2320
2338
  const createdRows = result.created.map((ref) => `${palette.green("✓")} ${cell(ref.resource.kind, resourceName(ref.resource))}`);
2321
2339
  const skippedRows = result.skipped.map((ref) => `${palette.dim("~")} ${cell(ref.resource.kind, resourceName(ref.resource))} ${palette.dim("(exists)")}`);
2340
+ const bundledRows = result.bundled.map((resource) => `${palette.dim("~")} ${cell(resource.kind, resourceName(resource))} ${palette.dim(SHIPS_WITH_WORKER)}`);
2322
2341
  const failedRows = result.failed.map((failure) => `${palette.red("✗")} ${cell(failure.resource.kind, resourceName(failure.resource))}`);
2323
2342
  const failedCount = result.failed.length > 0 ? palette.red(`${String(result.failed.length)} failed`) : "0 failed";
2324
- const summary = `${String(result.created.length)} created · ${String(result.skipped.length)} exist · ${failedCount}`;
2343
+ const counts = [`${String(result.created.length)} created`, `${String(result.skipped.length)} exist`];
2344
+ if (result.bundled.length > 0) counts.push(`${String(result.bundled.length)} with worker`);
2345
+ const summary = `${counts.join(" · ")} · ${failedCount}`;
2325
2346
  ui.heading("Provisioned");
2326
2347
  ui.box([
2327
2348
  ...createdRows,
2328
2349
  ...skippedRows,
2350
+ ...bundledRows,
2329
2351
  ...failedRows,
2330
2352
  "",
2331
2353
  summary
@@ -2368,16 +2390,19 @@ const formatDuration = (ms) => {
2368
2390
  * @param summary.stage - The target stage the worker deployed to.
2369
2391
  * @param summary.created - How many resources were created this run.
2370
2392
  * @param summary.exists - How many resources already existed (skipped).
2393
+ * @param summary.bundled - How many Durable Objects shipped with the Worker.
2371
2394
  * @param summary.failed - How many resources failed to provision.
2372
2395
  * @param summary.elapsedMs - The wall-clock deploy duration in milliseconds.
2373
2396
  * @example
2374
2397
  * ```ts
2375
- * renderDeploySummary(ui, { url, stage: "production", created: 0, exists: 5, failed: 0, elapsedMs: 4234 });
2398
+ * renderDeploySummary(ui, { url, stage: "production", created: 0, exists: 5, bundled: 1, failed: 0, elapsedMs: 4234 });
2376
2399
  * ```
2377
2400
  */
2378
2401
  const renderDeploySummary = (ui, summary) => {
2379
2402
  const { palette } = ui;
2380
- const tally = `${String(summary.exists)} exist · ${String(summary.created)} created`;
2403
+ const parts = [`${String(summary.exists)} exist`, `${String(summary.created)} created`];
2404
+ if (summary.bundled > 0) parts.push(`${String(summary.bundled)} with worker`);
2405
+ const tally = parts.join(" · ");
2381
2406
  const failedLabel = palette.red(`${String(summary.failed)} failed`);
2382
2407
  const resources = summary.failed > 0 ? `${tally} · ${failedLabel}` : tally;
2383
2408
  ui.heading("Deployed");
@@ -3009,32 +3034,25 @@ const assembleManifest = (ctx, stage) => {
3009
3034
  };
3010
3035
  };
3011
3036
  /**
3012
- * Act on an infra plan: skip the resources that already exist (reusing their ids), create the
3013
- * missing ones (capturing each new id), and announce each via provision:skip / :resource. Resilient
3014
- * — a single resource that fails to create is CAPTURED in `failed` (not thrown), so one bad resource
3015
- * (e.g. an invalid bucket name) never aborts the whole run and the caller can report a clear result.
3037
+ * Create the still-missing resources one at a time: provision each, fold its captured id (kv/d1) into
3038
+ * the shared `ids` map, and announce it via provision:resource. Resilient — a single failure is
3039
+ * CAPTURED (not thrown), so one bad resource never aborts the rest. Extracted from {@link applyPlan}
3040
+ * so that orchestrator stays flat (skip existing, skip DOs, create missing).
3016
3041
  *
3017
3042
  * @param ctx - The deploy plugin context.
3018
- * @param plan - The infra plan from planInfra (existing vs missing).
3043
+ * @param missing - The resources the plan flagged as not-yet-existing.
3019
3044
  * @param ci - Whether provisioning runs non-interactively (forwarded to each provider).
3020
- * @returns The provisioning result: created, skipped, failed, and the merged binding id map.
3045
+ * @param ids - The binding Cloudflare id map, mutated in place with each created kv/d1 id.
3046
+ * @returns The created refs and any captured per-resource failures.
3021
3047
  * @example
3022
3048
  * ```ts
3023
- * const { created, failed } = await applyPlan(ctx, plan, false);
3049
+ * const { created, failed } = await provisionMissing(ctx, plan.missing, false, ids);
3024
3050
  * ```
3025
3051
  */
3026
- const applyPlan = async (ctx, plan, ci) => {
3027
- const ids = {};
3028
- for (const ref of plan.exists) {
3029
- if (ref.id !== void 0 && (ref.resource.kind === "kv" || ref.resource.kind === "d1")) ids[ref.resource.binding] = ref.id;
3030
- ctx.emit("provision:skip", {
3031
- kind: ref.resource.kind,
3032
- name: resourceName(ref.resource)
3033
- });
3034
- }
3052
+ const provisionMissing = async (ctx, missing, ci, ids) => {
3035
3053
  const created = [];
3036
3054
  const failed = [];
3037
- for (const resource of plan.missing) try {
3055
+ for (const resource of missing) try {
3038
3056
  const { id } = await provisionResource(resource, ci);
3039
3057
  if (id !== void 0 && (resource.kind === "kv" || resource.kind === "d1")) ids[resource.binding] = id;
3040
3058
  created.push(id === void 0 ? { resource } : {
@@ -3051,9 +3069,45 @@ const applyPlan = async (ctx, plan, ci) => {
3051
3069
  error: error instanceof Error ? error.message : String(error)
3052
3070
  });
3053
3071
  }
3072
+ return {
3073
+ created,
3074
+ failed
3075
+ };
3076
+ };
3077
+ /**
3078
+ * Act on an infra plan: skip the resources that already exist (reusing their ids), skip the Durable
3079
+ * Objects that ship with the Worker, create the missing ones (capturing each new id), and announce
3080
+ * each via provision:skip / :resource. Resilient — a single resource that fails to create is CAPTURED
3081
+ * in `failed` (not thrown), so one bad resource (e.g. an invalid bucket name) never aborts the whole
3082
+ * run and the caller can report a clear result.
3083
+ *
3084
+ * @param ctx - The deploy plugin context.
3085
+ * @param plan - The infra plan from planInfra (existing vs missing vs ships-with-Worker).
3086
+ * @param ci - Whether provisioning runs non-interactively (forwarded to each provider).
3087
+ * @returns The provisioning result: created, skipped, bundled, failed, and the merged binding → id map.
3088
+ * @example
3089
+ * ```ts
3090
+ * const { created, failed } = await applyPlan(ctx, plan, false);
3091
+ * ```
3092
+ */
3093
+ const applyPlan = async (ctx, plan, ci) => {
3094
+ const ids = {};
3095
+ for (const ref of plan.exists) {
3096
+ if (ref.id !== void 0 && (ref.resource.kind === "kv" || ref.resource.kind === "d1")) ids[ref.resource.binding] = ref.id;
3097
+ ctx.emit("provision:skip", {
3098
+ kind: ref.resource.kind,
3099
+ name: resourceName(ref.resource)
3100
+ });
3101
+ }
3102
+ for (const resource of plan.ships) ctx.emit("provision:skip", {
3103
+ kind: resource.kind,
3104
+ name: resourceName(resource)
3105
+ });
3106
+ const { created, failed } = await provisionMissing(ctx, plan.missing, ci, ids);
3054
3107
  return {
3055
3108
  created,
3056
3109
  skipped: plan.exists,
3110
+ bundled: plan.ships,
3057
3111
  failed,
3058
3112
  ids
3059
3113
  };
@@ -3487,6 +3541,7 @@ const createDeployApi = (ctx) => ({
3487
3541
  const resources = {
3488
3542
  created: provisioned.created.length,
3489
3543
  exists: provisioned.skipped.length,
3544
+ bundled: provisioned.bundled.length,
3490
3545
  failed: provisioned.failed.length
3491
3546
  };
3492
3547
  renderDeploySummary((0, _moku_labs_common_cli.createBrandConsole)(), {
package/dist/cli.cjs CHANGED
@@ -1,4 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_cli = require("./cli-CfgYgnzW.cjs");
2
+ const require_cli = require("./cli-imQGo0tc.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 { a as ResourceManifest, i as ExternalManifest, n as cliPlugin, t as deployPlugin } from "./index-Cb3vzZte.cjs";
1
+ import { a as ResourceManifest, i as ExternalManifest, n as cliPlugin, t as deployPlugin } from "./index-CWxQr2Q3.cjs";
2
2
  export { type ExternalManifest, type ResourceManifest, cliPlugin, deployPlugin };
package/dist/cli.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as ResourceManifest, i as ExternalManifest, n as cliPlugin, t as deployPlugin } from "./index-Cb3vzZte.mjs";
1
+ import { a as ResourceManifest, i as ExternalManifest, n as cliPlugin, t as deployPlugin } from "./index-CWxQr2Q3.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-Cs3R3Jhr.mjs";
1
+ import { n as deployPlugin, t as cliPlugin } from "./cli--EPl98vG.mjs";
2
2
  export { cliPlugin, deployPlugin };
@@ -36,6 +36,7 @@ type WorkerEvents = {
36
36
  "provision:plan": {
37
37
  exists: number;
38
38
  missing: number;
39
+ ships: number;
39
40
  account: string;
40
41
  };
41
42
  "provision:skip": {
@@ -246,13 +247,18 @@ type ProvisionedRef = {
246
247
  };
247
248
  /**
248
249
  * Read-only infra preflight result: which declared resources already exist in the Cloudflare
249
- * account versus which are still missing and must be created. Produced by `checkInfra()`.
250
+ * account, which are still missing and must be created, and which ship with the Worker. Produced by
251
+ * `checkInfra()`. Durable Objects are neither "exists" nor "missing" — the planner never queries the
252
+ * account for them and never API-provisions them; they are created by `wrangler deploy` (the
253
+ * auto-derived DO migration), so they get their own `ships` bucket instead of masquerading as
254
+ * already-existing.
250
255
  */
251
256
  type InfraPlan = {
252
257
  /** Resolved account display name (or id when the name is unknown). */account: string; /** Resolved Cloudflare account id used for the existence checks. */
253
- accountId: string; /** Declared resources that already exist (with their captured ids where applicable). */
258
+ accountId: string; /** Declared resources the account listing confirmed already exist (with captured ids where applicable). */
254
259
  exists: ProvisionedRef[]; /** Declared resources that do not yet exist and must be created. */
255
- missing: ResourceManifest[];
260
+ missing: ResourceManifest[]; /** Durable Objects that ship with the Worker — created by `wrangler deploy`, never API-provisioned. */
261
+ ships: ResourceManifest[];
256
262
  };
257
263
  /**
258
264
  * A resource that failed to provision, with the (branded) error message captured so the guided flow
@@ -264,13 +270,15 @@ type ProvisionFailure = {
264
270
  };
265
271
  /**
266
272
  * Outcome of acting on an {@link InfraPlan}: the resources just created, those skipped because they
267
- * already existed, those that FAILED to create, and the merged id map (binding Cloudflare id) for
268
- * the config writer. Provisioning is resilient a single resource failure is captured here, not
269
- * thrown, so the guided flow can report a clear per-resource result.
273
+ * already existed, those that ship with the Worker (Durable Objects not created here), those that
274
+ * FAILED to create, and the merged id map (binding Cloudflare id) for the config writer.
275
+ * Provisioning is resilient a single resource failure is captured here, not thrown, so the guided
276
+ * flow can report a clear per-resource result.
270
277
  */
271
278
  type ProvisionResult = {
272
279
  /** Resources created during this run. */created: ProvisionedRef[]; /** Resources skipped because they already existed. */
273
- skipped: ProvisionedRef[]; /** Resources that failed to create (captured, not thrown). */
280
+ skipped: ProvisionedRef[]; /** Durable Objects that ship with the Worker not created at the provision step (`wrangler deploy` does). */
281
+ bundled: ResourceManifest[]; /** Resources that failed to create (captured, not thrown). */
274
282
  failed: ProvisionFailure[]; /** Merged binding → Cloudflare id map (existing + created) for writeWranglerConfig. */
275
283
  ids: Record<string, string>;
276
284
  };
@@ -289,10 +297,11 @@ type DeployReport = {
289
297
  /** True only when the worker is live and every requested post-step (migration, seed) succeeded. */ok: boolean; /** Coarse outcome: "deployed" (live + post-steps ok), "aborted" (a gate declined / auth not set up), "failed" (a step errored). */
290
298
  status: "deployed" | "aborted" | "failed"; /** The resolved deploy stage (resource-name suffix; "production" is bare). */
291
299
  stage: string; /** The live worker URL once `wrangler deploy` succeeded — set even if a later migration/seed failed. */
292
- url?: string; /** Provisioning tally: resources created, already-existing, and failed to create. */
300
+ url?: string; /** Provisioning tally: resources created, already-existing, shipped-with-the-Worker (DOs), and failed to create. */
293
301
  resources?: {
294
302
  created: number;
295
303
  exists: number;
304
+ bundled: number;
296
305
  failed: number;
297
306
  }; /** Remote D1 migration outcome — "skipped" (not requested), "applied", or "failed". */
298
307
  migration: "skipped" | "applied" | "failed"; /** Remote seed outcome — "skipped" (not requested), "applied", or "failed". */
@@ -36,6 +36,7 @@ type WorkerEvents = {
36
36
  "provision:plan": {
37
37
  exists: number;
38
38
  missing: number;
39
+ ships: number;
39
40
  account: string;
40
41
  };
41
42
  "provision:skip": {
@@ -246,13 +247,18 @@ type ProvisionedRef = {
246
247
  };
247
248
  /**
248
249
  * Read-only infra preflight result: which declared resources already exist in the Cloudflare
249
- * account versus which are still missing and must be created. Produced by `checkInfra()`.
250
+ * account, which are still missing and must be created, and which ship with the Worker. Produced by
251
+ * `checkInfra()`. Durable Objects are neither "exists" nor "missing" — the planner never queries the
252
+ * account for them and never API-provisions them; they are created by `wrangler deploy` (the
253
+ * auto-derived DO migration), so they get their own `ships` bucket instead of masquerading as
254
+ * already-existing.
250
255
  */
251
256
  type InfraPlan = {
252
257
  /** Resolved account display name (or id when the name is unknown). */account: string; /** Resolved Cloudflare account id used for the existence checks. */
253
- accountId: string; /** Declared resources that already exist (with their captured ids where applicable). */
258
+ accountId: string; /** Declared resources the account listing confirmed already exist (with captured ids where applicable). */
254
259
  exists: ProvisionedRef[]; /** Declared resources that do not yet exist and must be created. */
255
- missing: ResourceManifest[];
260
+ missing: ResourceManifest[]; /** Durable Objects that ship with the Worker — created by `wrangler deploy`, never API-provisioned. */
261
+ ships: ResourceManifest[];
256
262
  };
257
263
  /**
258
264
  * A resource that failed to provision, with the (branded) error message captured so the guided flow
@@ -264,13 +270,15 @@ type ProvisionFailure = {
264
270
  };
265
271
  /**
266
272
  * Outcome of acting on an {@link InfraPlan}: the resources just created, those skipped because they
267
- * already existed, those that FAILED to create, and the merged id map (binding Cloudflare id) for
268
- * the config writer. Provisioning is resilient a single resource failure is captured here, not
269
- * thrown, so the guided flow can report a clear per-resource result.
273
+ * already existed, those that ship with the Worker (Durable Objects not created here), those that
274
+ * FAILED to create, and the merged id map (binding Cloudflare id) for the config writer.
275
+ * Provisioning is resilient a single resource failure is captured here, not thrown, so the guided
276
+ * flow can report a clear per-resource result.
270
277
  */
271
278
  type ProvisionResult = {
272
279
  /** Resources created during this run. */created: ProvisionedRef[]; /** Resources skipped because they already existed. */
273
- skipped: ProvisionedRef[]; /** Resources that failed to create (captured, not thrown). */
280
+ skipped: ProvisionedRef[]; /** Durable Objects that ship with the Worker not created at the provision step (`wrangler deploy` does). */
281
+ bundled: ResourceManifest[]; /** Resources that failed to create (captured, not thrown). */
274
282
  failed: ProvisionFailure[]; /** Merged binding → Cloudflare id map (existing + created) for writeWranglerConfig. */
275
283
  ids: Record<string, string>;
276
284
  };
@@ -289,10 +297,11 @@ type DeployReport = {
289
297
  /** True only when the worker is live and every requested post-step (migration, seed) succeeded. */ok: boolean; /** Coarse outcome: "deployed" (live + post-steps ok), "aborted" (a gate declined / auth not set up), "failed" (a step errored). */
290
298
  status: "deployed" | "aborted" | "failed"; /** The resolved deploy stage (resource-name suffix; "production" is bare). */
291
299
  stage: string; /** The live worker URL once `wrangler deploy` succeeded — set even if a later migration/seed failed. */
292
- url?: string; /** Provisioning tally: resources created, already-existing, and failed to create. */
300
+ url?: string; /** Provisioning tally: resources created, already-existing, shipped-with-the-Worker (DOs), and failed to create. */
293
301
  resources?: {
294
302
  created: number;
295
303
  exists: number;
304
+ bundled: number;
296
305
  failed: number;
297
306
  }; /** Remote D1 migration outcome — "skipped" (not requested), "applied", or "failed". */
298
307
  migration: "skipped" | "applied" | "failed"; /** Remote seed outcome — "skipped" (not requested), "applied", or "failed". */
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_cli = require("./cli-CfgYgnzW.cjs");
2
+ const require_cli = require("./cli-imQGo0tc.cjs");
3
3
  let _moku_labs_common = require("@moku-labs/common");
4
4
  //#region src/env-provider.ts
5
5
  /**
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as ResourceManifest, c as WorkerEnv, i as ExternalManifest, l as WorkerEvents, n as cliPlugin, o as SeedConfig, r as DeployReport, s as WorkerConfig, t as deployPlugin, u as WorkerPluginCtx } from "./index-Cb3vzZte.cjs";
1
+ import { a as ResourceManifest, c as WorkerEnv, i as ExternalManifest, l as WorkerEvents, n as cliPlugin, o as SeedConfig, r as DeployReport, s as WorkerConfig, t as deployPlugin, u as WorkerPluginCtx } from "./index-CWxQr2Q3.cjs";
2
2
  import { envPlugin, logPlugin } from "@moku-labs/common";
3
3
  import { PluginCtx, PluginCtx as PluginCtx$1, PluginInstance } from "@moku-labs/core";
4
4
 
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as ResourceManifest, c as WorkerEnv, i as ExternalManifest, l as WorkerEvents, n as cliPlugin, o as SeedConfig, r as DeployReport, s as WorkerConfig, t as deployPlugin, u as WorkerPluginCtx } from "./index-Cb3vzZte.mjs";
1
+ import { a as ResourceManifest, c as WorkerEnv, i as ExternalManifest, l as WorkerEvents, n as cliPlugin, o as SeedConfig, r as DeployReport, s as WorkerConfig, t as deployPlugin, u as WorkerPluginCtx } from "./index-CWxQr2Q3.mjs";
2
2
  import { envPlugin, logPlugin } from "@moku-labs/common";
3
3
  import { PluginCtx, PluginCtx as PluginCtx$1, PluginInstance } from "@moku-labs/core";
4
4
 
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as kvPlugin, c as d1Plugin, d as createCore, f as createPlugin$1, i as queuesPlugin, l as bindingsPlugin, n as deployPlugin, o as durableObjectsPlugin, p as stagePlugin, r as storagePlugin, s as defineDurableObject, t as cliPlugin, u as coreConfig } from "./cli-Cs3R3Jhr.mjs";
1
+ import { a as kvPlugin, c as d1Plugin, d as createCore, f as createPlugin$1, i as queuesPlugin, l as bindingsPlugin, n as deployPlugin, o as durableObjectsPlugin, p as stagePlugin, r as storagePlugin, s as defineDurableObject, t as cliPlugin, u as coreConfig } from "./cli--EPl98vG.mjs";
2
2
  import { envPlugin, logPlugin } from "@moku-labs/common";
3
3
  //#region src/env-provider.ts
4
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moku-labs/worker",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Cloudflare Worker framework for Moku — Durable Objects, Queues, R2, D1, and KV plugins that compose with Moku Web.",
5
5
  "repository": {
6
6
  "type": "git",