@lunora/cli 1.0.0-alpha.8 → 1.0.0-alpha.80

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.
Files changed (59) hide show
  1. package/LICENSE.md +6 -0
  2. package/__assets__/package-og.svg +1 -1
  3. package/dist/bin.mjs +1 -1
  4. package/dist/index.d.mts +290 -117
  5. package/dist/index.d.ts +290 -117
  6. package/dist/index.mjs +8 -8
  7. package/dist/packem_chunks/handler.mjs +87 -6
  8. package/dist/packem_chunks/handler10.mjs +8 -14
  9. package/dist/packem_chunks/handler11.mjs +19 -189
  10. package/dist/packem_chunks/handler12.mjs +176 -115
  11. package/dist/packem_chunks/handler13.mjs +118 -52
  12. package/dist/packem_chunks/handler14.mjs +50 -43
  13. package/dist/packem_chunks/handler15.mjs +48 -67
  14. package/dist/packem_chunks/handler16.mjs +85 -37
  15. package/dist/packem_chunks/handler17.mjs +39 -100
  16. package/dist/packem_chunks/handler18.mjs +87 -152
  17. package/dist/packem_chunks/handler19.mjs +148 -67
  18. package/dist/packem_chunks/handler2.mjs +6 -4
  19. package/dist/packem_chunks/handler20.mjs +77 -75
  20. package/dist/packem_chunks/handler21.mjs +71 -288
  21. package/dist/packem_chunks/handler3.mjs +6 -3
  22. package/dist/packem_chunks/handler4.mjs +2 -2
  23. package/dist/packem_chunks/handler5.mjs +7 -4
  24. package/dist/packem_chunks/handler6.mjs +10 -7
  25. package/dist/packem_chunks/handler7.mjs +2 -2
  26. package/dist/packem_chunks/handler8.mjs +1 -1
  27. package/dist/packem_chunks/handler9.mjs +315 -12
  28. package/dist/packem_chunks/planDevCommand.mjs +758 -81
  29. package/dist/packem_chunks/runCodegenCommand.mjs +5 -4
  30. package/dist/packem_chunks/runDeployCommand.mjs +126 -20
  31. package/dist/packem_chunks/runInitCommand.mjs +1661 -179
  32. package/dist/packem_chunks/runMigrateGenerateCommand.mjs +5 -4
  33. package/dist/packem_chunks/runResetCommand.mjs +2 -2
  34. package/dist/packem_chunks/runRpcCommand.mjs +3 -2
  35. package/dist/packem_shared/{COMMANDS-Bn8luojF.mjs → COMMANDS-DW8lQmuW.mjs} +85 -23
  36. package/dist/packem_shared/{DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs → DEFAULT_IMPORT_BATCH_SIZE-CRQmmBZM.mjs} +3 -2
  37. package/dist/packem_shared/{api-spec-CtA6ilu4.mjs → api-spec-Bx0iKbxA.mjs} +3 -1
  38. package/dist/packem_shared/{buildRegistryIndex-BcYe607_.mjs → buildRegistryIndex-BS5ig822.mjs} +1 -1
  39. package/dist/packem_shared/codegen-error-DJG-ghs_.mjs +31 -0
  40. package/dist/packem_shared/{command-BDXcJCCJ.mjs → command-lYnl4QyF.mjs} +6 -1
  41. package/dist/packem_shared/{commands-DqsEzojt.mjs → commands-ClEvcz3V.mjs} +224 -18
  42. package/dist/packem_shared/{createLogger-CHPNjFw2.mjs → createLogger-CIWSHrTL.mjs} +40 -8
  43. package/dist/packem_shared/{createRecordingSpawner-DxI3mebw.mjs → createRecordingSpawner-Cw5Iu73G.mjs} +12 -2
  44. package/dist/packem_shared/{detect-package-manager-DYp7n3mJ.mjs → detect-package-manager-DvEthdCw.mjs} +26 -30
  45. package/dist/packem_shared/{insertSchemaExtension-BuzF6-t2.mjs → insertSchemaExtension-DAqbfr9Z.mjs} +15 -10
  46. package/dist/packem_shared/{open-url-Dfq6fAyT.mjs → open-url-4PBLY9X0.mjs} +3 -2
  47. package/dist/packem_shared/{output-format-7gyGR3h8.mjs → output-format-B4642rjE.mjs} +1 -1
  48. package/dist/packem_shared/{parseManifest--vZf2FY1.mjs → parseManifest-Dbp-Q2q3.mjs} +36 -9
  49. package/dist/packem_shared/prompt-cancelled-APzX1Im-.mjs +9 -0
  50. package/dist/packem_shared/runAddCommand-DGjFXGqa.mjs +4 -0
  51. package/dist/packem_shared/storage-DEXpJkXh.mjs +84 -0
  52. package/dist/packem_shared/tui-prompts-BjEN8XgP.mjs +658 -0
  53. package/dist/packem_shared/wrangler-secrets-Dq_Fkbm-.mjs +49 -0
  54. package/package.json +16 -13
  55. package/skills/lunora-quickstart/SKILL.md +25 -5
  56. package/skills/lunora-setup-storage/SKILL.md +7 -3
  57. package/dist/packem_shared/features-ocSSpZtS.mjs +0 -24
  58. package/dist/packem_shared/runAddCommand-G544_v6e.mjs +0 -4
  59. package/dist/packem_shared/tui-prompts-XHFxlOg5.mjs +0 -269
@@ -1,7 +1,8 @@
1
1
  import { runCodegen } from '@lunora/codegen';
2
- import { p as parseApiSpec } from '../packem_shared/api-spec-CtA6ilu4.mjs';
3
- import { d as defineHandler } from '../packem_shared/command-BDXcJCCJ.mjs';
4
- import { v as validateOutputFormat, p as printJson, l as loggerForFormat, i as isJsonFormat } from '../packem_shared/output-format-7gyGR3h8.mjs';
2
+ import { collectWranglerSecretVariables } from '@lunora/config';
3
+ import { p as parseApiSpec } from '../packem_shared/api-spec-Bx0iKbxA.mjs';
4
+ import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
5
+ import { v as validateOutputFormat, p as printJson, l as loggerForFormat, i as isJsonFormat } from '../packem_shared/output-format-B4642rjE.mjs';
5
6
 
6
7
  const CRON_TRIGGER_LIMIT = 3;
7
8
  const runCodegenCommand = (options) => {
@@ -13,7 +14,7 @@ const runCodegenCommand = (options) => {
13
14
  options.logger.error(formatError);
14
15
  return { advisories: [], cronTriggers: [], error: formatError, outputDirectory: "" };
15
16
  }
16
- const result = runCodegen({ apiSpec: options.apiSpec, projectRoot });
17
+ const result = runCodegen({ apiSpec: options.apiSpec, projectRoot, wranglerVariables: collectWranglerSecretVariables(projectRoot) });
17
18
  const commandResult = {
18
19
  advisories: result.advisories.map((advisory) => {
19
20
  return {
@@ -1,18 +1,21 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { runCodegen, discoverMigrations } from '@lunora/codegen';
3
- import { readLinkedProject, writeLinkedProject, validateWranglerProject, inferLunoraBindings, reconcileWranglerBindings, DEV_VARS_FILE, parseDevVariableEntries, findWranglerFile, readWranglerJsonc, discoverContainerInfo } from '@lunora/config';
3
+ import { readLinkedProject, writeLinkedProject, validateWranglerProject, inferLunoraBindings, reconcileWranglerBindings, reconcileWranglerCompatibilityDate, DEV_VARS_FILE, parseDevVariableEntries, isMintableSecretKey, findWranglerFile, readWranglerJsonc, discoverContainerInfo, packageNamesFromBindings, requiredSecrets, generateSecretValue } from '@lunora/config';
4
4
  import { join } from '@visulima/path';
5
5
  import { Spinner } from '@visulima/spinner';
6
6
  import { Project } from 'ts-morph';
7
- import { p as parseApiSpec } from '../packem_shared/api-spec-CtA6ilu4.mjs';
7
+ import { p as parseApiSpec } from '../packem_shared/api-spec-Bx0iKbxA.mjs';
8
8
  import { r as readWranglerName } from '../packem_shared/wrangler-name-cy4yhm9j.mjs';
9
- import { d as defineHandler } from '../packem_shared/command-BDXcJCCJ.mjs';
9
+ import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
10
+ import { e as execArgsFor, d as detectPackageManager } from '../packem_shared/detect-package-manager-DvEthdCw.mjs';
10
11
  import { a as isRailpackAvailable, i as isDockerAvailable } from '../packem_shared/docker-hMQ97KSQ.mjs';
11
- import { v as validateOutputFormat, i as isJsonFormat, p as printJson, l as loggerForFormat } from '../packem_shared/output-format-7gyGR3h8.mjs';
12
+ import { v as validateOutputFormat, i as isJsonFormat, p as printJson, l as loggerForFormat } from '../packem_shared/output-format-B4642rjE.mjs';
12
13
  import { containerBuildTag } from '@lunora/container';
13
- import { defaultSpawner } from '../packem_shared/createRecordingSpawner-DxI3mebw.mjs';
14
+ import { defaultSpawner } from '../packem_shared/createRecordingSpawner-Cw5Iu73G.mjs';
14
15
  import { r as resolveWorkerUrl } from '../packem_shared/resolve-target-qbsJ_5sF.mjs';
15
16
  import { r as runSchemaDriftGate } from '../packem_shared/schema-drift-gate-BtBt0as0.mjs';
17
+ import { c as createTuiConfirm } from '../packem_shared/tui-prompts-BjEN8XgP.mjs';
18
+ import { l as listRemoteSecrets } from '../packem_shared/wrangler-secrets-Dq_Fkbm-.mjs';
16
19
  import { runMigrateDataCommand } from './runMigrateGenerateCommand.mjs';
17
20
 
18
21
  const WORKERS_DEV_URL = /https?:\/\/[^\s"'<>]+\.workers\.dev[^\s"'<>]*/u;
@@ -78,7 +81,8 @@ const buildRailpackImages = async (options) => {
78
81
  for (const target of options.targets) {
79
82
  const tag = containerBuildTag(target.exportName);
80
83
  const build = { args: ["build", target.buildDir, "--name", tag], command: "railpack", cwd: options.cwd };
81
- const push = { args: ["exec", "wrangler", "containers", "push", tag], command: "pnpm", cwd: options.cwd };
84
+ const pushExec = execArgsFor(detectPackageManager(options.cwd), "wrangler", ["containers", "push", tag]);
85
+ const push = { args: pushExec.args, command: pushExec.command, cwd: options.cwd };
82
86
  options.logger.info(`railpack: building "${target.exportName}" → ${tag} from ${target.buildDir}`);
83
87
  const buildResult = await spawner(build);
84
88
  if (buildResult.code !== 0) {
@@ -191,6 +195,17 @@ const provisionBindings = async (cwd, logger) => {
191
195
  const message = error instanceof Error ? error.message : String(error);
192
196
  logger.warn(`binding inference skipped: ${message}`);
193
197
  }
198
+ try {
199
+ const reconciled = reconcileWranglerCompatibilityDate(cwd);
200
+ if (reconciled.changed) {
201
+ logger.success(
202
+ `bumped compatibility_date to ${reconciled.date ?? "unknown"} (Workers Cache enabled) → ${reconciled.wranglerPath ?? "wrangler.jsonc"}`
203
+ );
204
+ }
205
+ } catch (error) {
206
+ const message = error instanceof Error ? error.message : String(error);
207
+ logger.warn(`compatibility date sync skipped: ${message}`);
208
+ }
194
209
  };
195
210
  const warnDevVariablesNotPushed = (cwd, logger) => {
196
211
  const devVariablesPath = join(cwd, DEV_VARS_FILE);
@@ -210,6 +225,90 @@ const warnDevVariablesNotPushed = (cwd, logger) => {
210
225
  `Note: \`lunora deploy\` does not push secrets. ${DEV_VARS_FILE} has ${String(keyCount)} key(s); if you changed them, run \`lunora env push --yes\` to update the deployed secrets.`
211
226
  );
212
227
  };
228
+ const SECRET_LIKE_KEY = /(?:KEY|PASSWORD|SECRET|TOKEN)$/u;
229
+ const resolveRequiredSecretKeys = async (cwd) => {
230
+ let packages = [];
231
+ try {
232
+ packages = packageNamesFromBindings(await inferLunoraBindings({ projectRoot: cwd }));
233
+ } catch {
234
+ }
235
+ const fromPackages = requiredSecrets(packages).map((entry) => entry.key);
236
+ let fromLocal = [];
237
+ try {
238
+ const devVariablesPath = join(cwd, DEV_VARS_FILE);
239
+ if (existsSync(devVariablesPath)) {
240
+ fromLocal = parseDevVariableEntries(readFileSync(devVariablesPath, "utf8")).map((entry) => entry.key).filter((key) => SECRET_LIKE_KEY.test(key));
241
+ }
242
+ } catch {
243
+ }
244
+ return [.../* @__PURE__ */ new Set([...fromPackages, ...fromLocal])];
245
+ };
246
+ const pushMintableSecrets = async (cwd, options, keys) => {
247
+ const { logger } = options;
248
+ const spawner = options.spawner ?? defaultSpawner;
249
+ const manager = detectPackageManager(cwd);
250
+ const environmentFlag = options.env === void 0 ? "" : ` --env ${options.env}`;
251
+ for (const key of keys) {
252
+ const args = ["secret", "put", key];
253
+ if (options.env !== void 0) {
254
+ args.push("--env", options.env);
255
+ }
256
+ if (options.temporary === true) {
257
+ args.push("--temporary");
258
+ }
259
+ const exec = execArgsFor(manager, "wrangler", args);
260
+ const pushResult = await spawner({ args: exec.args, command: exec.command, cwd, input: generateSecretValue() });
261
+ if (pushResult.code !== 0) {
262
+ logger.error(
263
+ `failed to push secret ${key} (exit ${String(pushResult.code)}); set it manually with \`wrangler secret put ${key}${environmentFlag}\`.`
264
+ );
265
+ return false;
266
+ }
267
+ logger.success(`generated + pushed ${key}`);
268
+ }
269
+ return true;
270
+ };
271
+ const offerMissingSecrets = async (cwd, options, interactive) => {
272
+ if (options.dryRun === true || options.preview === true) {
273
+ return void 0;
274
+ }
275
+ const { logger } = options;
276
+ const environmentFlag = options.env === void 0 ? "" : ` --env ${options.env}`;
277
+ let remote;
278
+ try {
279
+ remote = await (options.secretLister ?? listRemoteSecrets)({ cwd, env: options.env, temporary: options.temporary });
280
+ } catch {
281
+ return void 0;
282
+ }
283
+ if (!remote.ok) {
284
+ return void 0;
285
+ }
286
+ const remoteNames = new Set(remote.names);
287
+ const required = await resolveRequiredSecretKeys(cwd);
288
+ const missing = required.filter((key) => !remoteNames.has(key));
289
+ if (missing.length === 0) {
290
+ return void 0;
291
+ }
292
+ if (!interactive) {
293
+ return `missing required secret(s) on the deploy target: ${missing.join(", ")}. Set them with \`wrangler secret put <KEY>${environmentFlag}\` (or \`lunora env generate --set\` then \`lunora env push --yes${options.env === void 0 ? "" : " --prod"}\`), then re-deploy.`;
294
+ }
295
+ for (const key of missing.filter((name) => !isMintableSecretKey(name))) {
296
+ logger.warn(`required secret ${key} is not set on the target — set it with: wrangler secret put ${key}${environmentFlag}`);
297
+ }
298
+ const mintable = missing.filter((key) => isMintableSecretKey(key));
299
+ if (mintable.length === 0) {
300
+ return void 0;
301
+ }
302
+ const confirm = options.secretConfirm ?? createTuiConfirm();
303
+ if (await confirm(`${String(mintable.length)} required secret(s) not set on the target (${mintable.join(", ")}). Generate strong values and push them now?`)) {
304
+ await pushMintableSecrets(cwd, options, mintable);
305
+ return void 0;
306
+ }
307
+ logger.warn(
308
+ `${String(mintable.length)} required secret(s) not set on the target: ${mintable.join(", ")}. Generate + push with \`lunora env generate --set\` then \`lunora env push --yes${options.env === void 0 ? "" : " --prod"}\`.`
309
+ );
310
+ return void 0;
311
+ };
213
312
  const runPostDeployMigrations = async (options, cwd) => {
214
313
  const project = new Project({ skipAddingFilesFromTsConfig: true });
215
314
  const lunoraDirectory = join(cwd, "lunora");
@@ -352,7 +451,7 @@ const runPreDeployGates = async (cwd, options) => {
352
451
  return buildContainerImages(cwd, options);
353
452
  };
354
453
  const buildWranglerDeployArgs = (cwd, options) => {
355
- const args = options.preview ? ["exec", "wrangler", "versions", "upload"] : ["exec", "wrangler", "deploy"];
454
+ const args = options.preview ? ["versions", "upload"] : ["deploy"];
356
455
  const composedEntry = resolveComposedWorkerEntry(cwd);
357
456
  if (composedEntry !== void 0) {
358
457
  args.push(composedEntry);
@@ -375,6 +474,16 @@ const buildWranglerDeployArgs = (cwd, options) => {
375
474
  }
376
475
  return args;
377
476
  };
477
+ const reportWranglerProblems = (validation, logger) => {
478
+ if (validation.problems.length === 0) {
479
+ return false;
480
+ }
481
+ logger.error("wrangler.jsonc validation failed:");
482
+ for (const problem of validation.problems) {
483
+ logger.error(` - ${problem}`);
484
+ }
485
+ return true;
486
+ };
378
487
  const executeDeploy = async (options) => {
379
488
  const cwd = options.cwd ?? process.cwd();
380
489
  const interactive = isInteractive(options);
@@ -420,24 +529,21 @@ const executeDeploy = async (options) => {
420
529
  return { code: 1, descriptor: void 0, error: preflightError, validation: { problems: [], wranglerPath: void 0 } };
421
530
  }
422
531
  const validation = validateWranglerProject({ projectRoot: cwd });
423
- if (validation.problems.length > 0) {
424
- options.logger.error("wrangler.jsonc validation failed:");
425
- for (const problem of validation.problems) {
426
- options.logger.error(` - ${problem}`);
427
- }
428
- return {
429
- code: 1,
430
- descriptor: void 0,
431
- error: "wrangler validation failed",
432
- validation
433
- };
532
+ if (reportWranglerProblems(validation, options.logger)) {
533
+ return { code: 1, descriptor: void 0, error: "wrangler validation failed", validation };
434
534
  }
435
535
  warnDevVariablesNotPushed(cwd, options.logger);
536
+ const secretAbort = await offerMissingSecrets(cwd, options, interactive);
537
+ if (secretAbort !== void 0) {
538
+ options.logger.error(secretAbort);
539
+ return { code: 1, descriptor: void 0, error: secretAbort, validation };
540
+ }
436
541
  const shouldAutoLink = !isJsonFormat(options.format) && options.dryRun !== true && options.preview !== true && readLinkedProject(cwd) === void 0;
542
+ const exec = execArgsFor(detectPackageManager(cwd), "wrangler", buildWranglerDeployArgs(cwd, options));
437
543
  const descriptor = {
438
- args: buildWranglerDeployArgs(cwd, options),
544
+ args: exec.args,
439
545
  captureStdout: shouldAutoLink,
440
- command: "pnpm",
546
+ command: exec.command,
441
547
  cwd,
442
548
  // In `--format json` mode stdout is reserved for the single JSON document,
443
549
  // so route wrangler's progress + deployed-URL output to stderr instead.