@lunora/cli 1.0.0-alpha.100 → 1.0.0-alpha.102

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 (83) hide show
  1. package/dist/bin.mjs +2 -10
  2. package/dist/index.mjs +1 -18
  3. package/dist/packem_chunks/handler.mjs +1 -160
  4. package/dist/packem_chunks/handler10.mjs +1 -16
  5. package/dist/packem_chunks/handler11.mjs +1 -23
  6. package/dist/packem_chunks/handler12.mjs +2 -192
  7. package/dist/packem_chunks/handler13.mjs +2 -131
  8. package/dist/packem_chunks/handler14.mjs +1 -65
  9. package/dist/packem_chunks/handler15.mjs +1 -100
  10. package/dist/packem_chunks/handler16.mjs +1 -44
  11. package/dist/packem_chunks/handler17.mjs +1 -105
  12. package/dist/packem_chunks/handler18.mjs +3 -170
  13. package/dist/packem_chunks/handler19.mjs +1 -128
  14. package/dist/packem_chunks/handler2.mjs +2 -116
  15. package/dist/packem_chunks/handler20.mjs +1 -94
  16. package/dist/packem_chunks/handler21.mjs +2 -202
  17. package/dist/packem_chunks/handler3.mjs +2 -208
  18. package/dist/packem_chunks/handler4.mjs +1 -33
  19. package/dist/packem_chunks/handler5.mjs +1 -52
  20. package/dist/packem_chunks/handler6.mjs +1 -94
  21. package/dist/packem_chunks/handler7.mjs +1 -42
  22. package/dist/packem_chunks/handler8.mjs +1 -174
  23. package/dist/packem_chunks/handler9.mjs +8 -334
  24. package/dist/packem_chunks/planDevCommand.mjs +7 -1181
  25. package/dist/packem_chunks/runCodegenCommand.mjs +4 -53
  26. package/dist/packem_chunks/runDeployCommand.mjs +1 -619
  27. package/dist/packem_chunks/runInitCommand.mjs +51 -1411
  28. package/dist/packem_chunks/runMigrateGenerateCommand.mjs +9 -442
  29. package/dist/packem_chunks/runResetCommand.mjs +1 -41
  30. package/dist/packem_chunks/runRpcCommand.mjs +1 -69
  31. package/dist/packem_shared/COMMANDS-DRqlsGT2.mjs +3 -0
  32. package/dist/packem_shared/DEFAULT_IMPORT_BATCH_SIZE-DL87PIEl.mjs +8 -0
  33. package/dist/packem_shared/admin-url-DfVehV3e.mjs +1 -0
  34. package/dist/packem_shared/api-spec-BENwiyUa.mjs +1 -0
  35. package/dist/packem_shared/buildRegistryIndex-DwySASBu.mjs +1 -0
  36. package/dist/packem_shared/codegen-error-DJN6pTH5.mjs +3 -0
  37. package/dist/packem_shared/command-Bjv4VmYA.mjs +1 -0
  38. package/dist/packem_shared/commands-BhX2Bo9B.mjs +19 -0
  39. package/dist/packem_shared/createLogger--C3x1FNE.mjs +2 -0
  40. package/dist/packem_shared/createRecordingSpawner-C8_7nffs.mjs +1 -0
  41. package/dist/packem_shared/detect-package-manager-B2eIuAiP.mjs +1 -0
  42. package/dist/packem_shared/diffSnapshots-9bDd9nOK.mjs +5 -0
  43. package/dist/packem_shared/docker-CKvYE9YF.mjs +1 -0
  44. package/dist/packem_shared/insertSchemaExtension-DZReBZ4_.mjs +8 -0
  45. package/dist/packem_shared/open-url-CTU_g9gr.mjs +1 -0
  46. package/dist/packem_shared/output-format-D7cKB-O5.mjs +2 -0
  47. package/dist/packem_shared/parseManifest-x3WsxKHz.mjs +1 -0
  48. package/dist/packem_shared/prompt-cancelled-C8Sj7OqI.mjs +1 -0
  49. package/dist/packem_shared/resolve-target-vxaXHmvg.mjs +1 -0
  50. package/dist/packem_shared/runAddCommand--TBYJQYi.mjs +1 -0
  51. package/dist/packem_shared/schema-drift-gate-CpqG-xP4.mjs +1 -0
  52. package/dist/packem_shared/schemaIrToSnapshot-Clwd2A8e.mjs +1 -0
  53. package/dist/packem_shared/storage-DOvAKGi4.mjs +1 -0
  54. package/dist/packem_shared/tui-prompts-CCt3jm1k.mjs +4 -0
  55. package/dist/packem_shared/wrangler-name-HIl0Z6yx.mjs +1 -0
  56. package/dist/packem_shared/wrangler-secrets-BMRJwKQU.mjs +1 -0
  57. package/package.json +6 -6
  58. package/dist/packem_shared/COMMANDS-BOJIDoVY.mjs +0 -1031
  59. package/dist/packem_shared/DEFAULT_IMPORT_BATCH_SIZE-D0VOTerB.mjs +0 -249
  60. package/dist/packem_shared/admin-url-4UzT-CI4.mjs +0 -19
  61. package/dist/packem_shared/api-spec-Bx0iKbxA.mjs +0 -15
  62. package/dist/packem_shared/buildRegistryIndex-BS5ig822.mjs +0 -38
  63. package/dist/packem_shared/codegen-error-DJG-ghs_.mjs +0 -31
  64. package/dist/packem_shared/command-lYnl4QyF.mjs +0 -19
  65. package/dist/packem_shared/commands-D5Yxt9VY.mjs +0 -991
  66. package/dist/packem_shared/createLogger-CIWSHrTL.mjs +0 -105
  67. package/dist/packem_shared/createRecordingSpawner-WuSn20kb.mjs +0 -64
  68. package/dist/packem_shared/detect-package-manager-v4hHpQd0.mjs +0 -62
  69. package/dist/packem_shared/diffSnapshots-BeDvvNiF.mjs +0 -161
  70. package/dist/packem_shared/docker-hMQ97KSQ.mjs +0 -21
  71. package/dist/packem_shared/insertSchemaExtension-DAqbfr9Z.mjs +0 -64
  72. package/dist/packem_shared/open-url-4PBLY9X0.mjs +0 -42
  73. package/dist/packem_shared/output-format-B4642rjE.mjs +0 -17
  74. package/dist/packem_shared/parseManifest-Dbp-Q2q3.mjs +0 -121
  75. package/dist/packem_shared/prompt-cancelled-APzX1Im-.mjs +0 -9
  76. package/dist/packem_shared/resolve-target-qbsJ_5sF.mjs +0 -16
  77. package/dist/packem_shared/runAddCommand-D1hgfqFQ.mjs +0 -4
  78. package/dist/packem_shared/schema-drift-gate-BtBt0as0.mjs +0 -79
  79. package/dist/packem_shared/schemaIrToSnapshot-DdsljJT-.mjs +0 -43
  80. package/dist/packem_shared/storage-BXU4ax4O.mjs +0 -84
  81. package/dist/packem_shared/tui-prompts-BjEN8XgP.mjs +0 -658
  82. package/dist/packem_shared/wrangler-name-cy4yhm9j.mjs +0 -12
  83. package/dist/packem_shared/wrangler-secrets-Coni-mER.mjs +0 -49
@@ -1,33 +1 @@
1
- import { p as parseApiSpec } from '../packem_shared/api-spec-Bx0iKbxA.mjs';
2
- import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
3
- import { runDeployCommand } from './runDeployCommand.mjs';
4
-
5
- const DEFAULT_OUT_DIR = ".lunora/build";
6
- const runBuildCommand = async (options) => {
7
- const outDirectory = options.outDir ?? DEFAULT_OUT_DIR;
8
- const result = await runDeployCommand({
9
- apiSpec: options.apiSpec,
10
- cwd: options.cwd,
11
- dryRun: true,
12
- format: options.format,
13
- logger: options.logger,
14
- outDir: outDirectory,
15
- spawner: options.spawner
16
- });
17
- if (result.code === 0) {
18
- options.logger.success(`build complete — bundle written to ${outDirectory}`);
19
- }
20
- return result;
21
- };
22
- const execute = defineHandler(async ({ cwd, logger, options }) => {
23
- const result = await runBuildCommand({
24
- apiSpec: parseApiSpec(options.apiSpec),
25
- cwd,
26
- format: options.format,
27
- logger,
28
- outDir: options.outDir
29
- });
30
- return { code: result.code };
31
- });
32
-
33
- export { execute, runBuildCommand };
1
+ import{r as t}from"../packem_shared/api-spec-BENwiyUa.mjs";import{i as a}from"../packem_shared/command-Bjv4VmYA.mjs";import{runDeployCommand as c}from"./runDeployCommand.mjs";const i=".lunora/build",n=async o=>{const r=o.outDir??i,e=await c({apiSpec:o.apiSpec,cwd:o.cwd,dryRun:!0,format:o.format,logger:o.logger,outDir:r,spawner:o.spawner});return e.code===0&&o.logger.success(`build complete — bundle written to ${r}`),e},d=a(async({cwd:o,logger:r,options:e})=>({code:(await n({apiSpec:t(e.apiSpec),cwd:o,format:e.format,logger:r,outDir:e.outDir})).code}));export{d as execute,n as runBuildCommand};
@@ -1,52 +1 @@
1
- import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
2
- import { e as execArgsFor, d as detectPackageManager } from '../packem_shared/detect-package-manager-v4hHpQd0.mjs';
3
- import { i as isDockerAvailable } from '../packem_shared/docker-hMQ97KSQ.mjs';
4
- import { defaultSpawner } from '../packem_shared/createRecordingSpawner-WuSn20kb.mjs';
5
-
6
- const SUBCOMMANDS = /* @__PURE__ */ new Set(["build", "delete", "images", "info", "list", "push"]);
7
- const NEEDS_DOCKER = /* @__PURE__ */ new Set(["build", "push"]);
8
- const runContainersCommand = async (options) => {
9
- const [subcommand, ...rest] = options.argument;
10
- if (subcommand === void 0 || !SUBCOMMANDS.has(subcommand)) {
11
- options.logger.error(
12
- `lunora containers requires a subcommand: ${[...SUBCOMMANDS].toSorted((a, b) => a.localeCompare(b)).join(" | ")}. Example: lunora containers build ./containers/app --tag app:v1 --push`
13
- );
14
- return { code: 1 };
15
- }
16
- if (NEEDS_DOCKER.has(subcommand) && !(options.dockerAvailable ?? isDockerAvailable)()) {
17
- options.logger.error(
18
- `containers ${subcommand} needs a running Docker-compatible engine (it builds/pushes images locally). Start Docker or Colima and retry. Note: container images must target linux/amd64.`
19
- );
20
- return { code: 1 };
21
- }
22
- const args = ["containers", subcommand, ...rest];
23
- if (options.tag !== void 0) {
24
- args.push("--tag", options.tag);
25
- }
26
- if (options.push === true) {
27
- args.push("--push");
28
- }
29
- if (options.env !== void 0) {
30
- args.push("--env", options.env);
31
- }
32
- const cwd = options.cwd ?? process.cwd();
33
- const exec = execArgsFor(detectPackageManager(cwd), "wrangler", args);
34
- const descriptor = { args: exec.args, command: exec.command, cwd };
35
- options.logger.info(`running ${descriptor.command} ${descriptor.args.join(" ")}`);
36
- const spawner = options.spawner ?? defaultSpawner;
37
- const result = await spawner(descriptor);
38
- return { code: result.code, descriptor };
39
- };
40
- const execute = defineHandler(async ({ argument, cwd, logger, options }) => {
41
- const result = await runContainersCommand({
42
- argument,
43
- cwd,
44
- env: options.env,
45
- logger,
46
- push: options.push === true,
47
- tag: options.tag
48
- });
49
- return { code: result.code };
50
- });
51
-
52
- export { execute, runContainersCommand };
1
+ import{i as d}from"../packem_shared/command-Bjv4VmYA.mjs";import{M as g,P as m}from"../packem_shared/detect-package-manager-B2eIuAiP.mjs";import{r as p}from"../packem_shared/docker-CKvYE9YF.mjs";import{defaultSpawner as l}from"../packem_shared/createRecordingSpawner-C8_7nffs.mjs";const i=new Set(["build","delete","images","info","list","push"]),h=new Set(["build","push"]),w=async r=>{const[a,...n]=r.argument;if(a===void 0||!i.has(a))return r.logger.error(`lunora containers requires a subcommand: ${[...i].toSorted((c,u)=>c.localeCompare(u)).join(" | ")}. Example: lunora containers build ./containers/app --tag app:v1 --push`),{code:1};if(h.has(a)&&!(r.dockerAvailable??p)())return r.logger.error(`containers ${a} needs a running Docker-compatible engine (it builds/pushes images locally). Start Docker or Colima and retry. Note: container images must target linux/amd64.`),{code:1};const o=["containers",a,...n];r.tag!==void 0&&o.push("--tag",r.tag),r.push===!0&&o.push("--push"),r.env!==void 0&&o.push("--env",r.env);const t=r.cwd??process.cwd(),s=g(m(t),"wrangler",o),e={args:s.args,command:s.command,cwd:t};return r.logger.info(`running ${e.command} ${e.args.join(" ")}`),{code:(await(r.spawner??l)(e)).code,descriptor:e}},C=d(async({argument:r,cwd:a,logger:n,options:o})=>({code:(await w({argument:r,cwd:a,env:o.env,logger:n,push:o.push===!0,tag:o.tag})).code}));export{C as execute,w as runContainersCommand};
@@ -1,94 +1 @@
1
- import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
2
- import { e as execArgsFor, d as detectPackageManager } from '../packem_shared/detect-package-manager-v4hHpQd0.mjs';
3
- import { defaultSpawner } from '../packem_shared/createRecordingSpawner-WuSn20kb.mjs';
4
-
5
- const withEnv = (args, env) => {
6
- if (env !== void 0) {
7
- args.push("--env", env);
8
- }
9
- return args;
10
- };
11
- const buildListArgs = (options) => {
12
- const args = withEnv(["deployments", "list"], options.env);
13
- if (options.json) {
14
- args.push("--json");
15
- }
16
- return args;
17
- };
18
- const buildArgs = (options) => {
19
- switch (options.subcommand) {
20
- case "inspect": {
21
- if (options.versionId === void 0) {
22
- return { error: "deployments inspect requires a version id. Usage: lunora deployments inspect <version-id>" };
23
- }
24
- return { args: withEnv(["versions", "view", options.versionId], options.env) };
25
- }
26
- case "list": {
27
- return { args: buildListArgs(options) };
28
- }
29
- case "promote": {
30
- if (options.versionId === void 0) {
31
- return { error: "deployments promote requires a version id. Usage: lunora deployments promote <version-id> --yes" };
32
- }
33
- if (!options.yes) {
34
- return { error: "deployments promote shifts 100% of live traffic. Re-run with --yes to confirm." };
35
- }
36
- const args = withEnv(["versions", "deploy", `${options.versionId}@100%`, "--yes"], options.env);
37
- if (options.message !== void 0) {
38
- args.push("--message", options.message);
39
- }
40
- return { args };
41
- }
42
- case "rollback": {
43
- if (!options.yes) {
44
- return { error: "deployments rollback changes the live version. Re-run with --yes to confirm." };
45
- }
46
- const args = withEnv(["rollback"], options.env);
47
- if (options.versionId !== void 0) {
48
- args.push(options.versionId);
49
- }
50
- args.push("--yes");
51
- if (options.message !== void 0) {
52
- args.push("--message", options.message);
53
- }
54
- return { args };
55
- }
56
- default: {
57
- return { error: `deployments: unknown subcommand "${options.subcommand}"` };
58
- }
59
- }
60
- };
61
- const runDeploymentsCommand = async (options) => {
62
- const { args, error } = buildArgs(options);
63
- if (error !== void 0 || args === void 0) {
64
- options.logger.error(error ?? "deployments: nothing to run");
65
- return { code: 1, descriptor: void 0, error };
66
- }
67
- const cwd = options.cwd ?? process.cwd();
68
- const exec = execArgsFor(detectPackageManager(cwd), "wrangler", args);
69
- const descriptor = { args: exec.args, command: exec.command, cwd };
70
- options.logger.info(`${descriptor.command} ${descriptor.args.join(" ")}`);
71
- const spawner = options.spawner ?? defaultSpawner;
72
- const result = await spawner(descriptor);
73
- return { code: result.code, descriptor };
74
- };
75
- const isDeploymentsSubcommand = (value) => value === "list" || value === "inspect" || value === "rollback" || value === "promote";
76
- const execute = defineHandler(({ argument, cwd, logger, options }) => {
77
- const sub = argument[0];
78
- if (!isDeploymentsSubcommand(sub)) {
79
- logger.error(`deployments: unknown subcommand "${sub ?? ""}" — expected list | inspect | rollback | promote`);
80
- return { code: 1 };
81
- }
82
- return runDeploymentsCommand({
83
- cwd,
84
- env: options.env,
85
- json: options.json === true,
86
- logger,
87
- message: options.message,
88
- subcommand: sub,
89
- versionId: argument[1],
90
- yes: options.yes === true
91
- });
92
- });
93
-
94
- export { execute, runDeploymentsCommand };
1
+ import{i as d}from"../packem_shared/command-Bjv4VmYA.mjs";import{M as a,P as m}from"../packem_shared/detect-package-manager-B2eIuAiP.mjs";import{defaultSpawner as c}from"../packem_shared/createRecordingSpawner-C8_7nffs.mjs";const i=(r,e)=>(e!==void 0&&r.push("--env",e),r),p=r=>{const e=i(["deployments","list"],r.env);return r.json&&e.push("--json"),e},u=r=>{switch(r.subcommand){case"inspect":return r.versionId===void 0?{error:"deployments inspect requires a version id. Usage: lunora deployments inspect <version-id>"}:{args:i(["versions","view",r.versionId],r.env)};case"list":return{args:p(r)};case"promote":{if(r.versionId===void 0)return{error:"deployments promote requires a version id. Usage: lunora deployments promote <version-id> --yes"};if(!r.yes)return{error:"deployments promote shifts 100% of live traffic. Re-run with --yes to confirm."};const e=i(["versions","deploy",`${r.versionId}@100%`,"--yes"],r.env);return r.message!==void 0&&e.push("--message",r.message),{args:e}}case"rollback":{if(!r.yes)return{error:"deployments rollback changes the live version. Re-run with --yes to confirm."};const e=i(["rollback"],r.env);return r.versionId!==void 0&&e.push(r.versionId),e.push("--yes"),r.message!==void 0&&e.push("--message",r.message),{args:e}}default:return{error:`deployments: unknown subcommand "${r.subcommand}"`}}},l=async r=>{const{args:e,error:s}=u(r);if(s!==void 0||e===void 0)return r.logger.error(s??"deployments: nothing to run"),{code:1,descriptor:void 0,error:s};const o=r.cwd??process.cwd(),n=a(m(o),"wrangler",e),t={args:n.args,command:n.command,cwd:o};return r.logger.info(`${t.command} ${t.args.join(" ")}`),{code:(await(r.spawner??c)(t)).code,descriptor:t}},v=r=>r==="list"||r==="inspect"||r==="rollback"||r==="promote",w=d(({argument:r,cwd:e,logger:s,options:o})=>{const n=r[0];return v(n)?l({cwd:e,env:o.env,json:o.json===!0,logger:s,message:o.message,subcommand:n,versionId:r[1],yes:o.yes===!0}):(s.error(`deployments: unknown subcommand "${n??""}" — expected list | inspect | rollback | promote`),{code:1})});export{w as execute,l as runDeploymentsCommand};
@@ -1,42 +1 @@
1
- import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
2
- import { o as openUrl } from '../packem_shared/open-url-4PBLY9X0.mjs';
3
-
4
- const DEFAULT_DOCS_URL = "https://lunora.anolilab.dev/docs";
5
- const trimSlashes = (value) => {
6
- let start = 0;
7
- let end = value.length;
8
- while (start < end && value[start] === "/") {
9
- start += 1;
10
- }
11
- while (end > start && value[end - 1] === "/") {
12
- end -= 1;
13
- }
14
- return value.slice(start, end);
15
- };
16
- const buildUrl = (section) => {
17
- if (!section || section.length === 0) {
18
- return DEFAULT_DOCS_URL;
19
- }
20
- const trimmed = trimSlashes(section);
21
- if (trimmed.length === 0) {
22
- return DEFAULT_DOCS_URL;
23
- }
24
- return `${DEFAULT_DOCS_URL}/${trimmed}`;
25
- };
26
- const runDocsCommand = async (options) => {
27
- const url = buildUrl(options.section);
28
- options.logger.info(`opening ${url}`);
29
- try {
30
- await openUrl(url, { opener: options.opener });
31
- } catch (error) {
32
- const message = error instanceof Error ? error.message : String(error);
33
- options.logger.error(`docs: failed to open URL: ${message}`);
34
- return { code: 1, url };
35
- }
36
- return { code: 0, url };
37
- };
38
- const execute = defineHandler(
39
- ({ argument, logger }) => runDocsCommand({ logger, section: argument[0] })
40
- );
41
-
42
- export { execute, runDocsCommand };
1
+ import{i as c}from"../packem_shared/command-Bjv4VmYA.mjs";import{f as s}from"../packem_shared/open-url-CTU_g9gr.mjs";const t="https://lunora.anolilab.dev/docs",l=r=>{let o=0,n=r.length;for(;o<n&&r[o]==="/";)o+=1;for(;n>o&&r[n-1]==="/";)n-=1;return r.slice(o,n)},g=r=>{if(!r||r.length===0)return t;const o=l(r);return o.length===0?t:`${t}/${o}`},a=async r=>{const o=g(r.section);r.logger.info(`opening ${o}`);try{await s(o,{opener:r.opener})}catch(n){const e=n instanceof Error?n.message:String(n);return r.logger.error(`docs: failed to open URL: ${e}`),{code:1,url:o}}return{code:0,url:o}},f=c(({argument:r,logger:o})=>a({logger:o,section:r[0]}));export{f as execute,a as runDocsCommand};
@@ -1,174 +1 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import { findWranglerFile, readWranglerJsonc, validateWranglerConfig, isPlaceholderValue, DEV_VARS_FILE, parseDevVariableEntries, inferLunoraBindings } from '@lunora/config';
4
- import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
5
-
6
- const SECRET_KEY_PATTERN = /(?:KEY|PASSWORD|SECRET|TOKEN)$/u;
7
- const isD1PlaceholderId = (databaseId) => {
8
- const value = databaseId.trim();
9
- if (value === "") {
10
- return true;
11
- }
12
- const lower = value.toLowerCase();
13
- return lower.includes("replace") || lower.startsWith("<") && lower.endsWith(">");
14
- };
15
- const readWrangler = (cwd) => {
16
- const path = findWranglerFile(cwd);
17
- if (path === void 0) {
18
- return { parsed: void 0, path: void 0 };
19
- }
20
- const { parsed } = readWranglerJsonc(path);
21
- return { parsed, path };
22
- };
23
- const checkWrangler = (parsed, path, findings) => {
24
- if (path === void 0) {
25
- findings.push({
26
- fix: "Run `lunora init` (or `lunora dev`) to scaffold and reconcile wrangler.jsonc.",
27
- level: "fail",
28
- message: "wrangler.jsonc not found."
29
- });
30
- return;
31
- }
32
- if (parsed === void 0) {
33
- findings.push({ fix: `Check ${path} is valid JSONC.`, level: "fail", message: `Could not parse ${path}.` });
34
- return;
35
- }
36
- const report = validateWranglerConfig(parsed);
37
- const shardError = report.errors.find((error) => error.includes("SHARD"));
38
- if (shardError === void 0) {
39
- findings.push({ level: "pass", message: "wrangler.jsonc present with a SHARD durable-object binding." });
40
- } else {
41
- findings.push({ fix: "Run `lunora dev` to auto-reconcile, or add the binding manually.", level: "fail", message: shardError });
42
- }
43
- };
44
- const checkD1Placeholders = (parsed, findings) => {
45
- if (parsed === void 0) {
46
- return;
47
- }
48
- const databases = (parsed.d1_databases ?? []).filter(Boolean);
49
- for (const database of databases) {
50
- const databaseId = typeof database.database_id === "string" ? database.database_id : "";
51
- if (isD1PlaceholderId(databaseId)) {
52
- const label = typeof database.binding === "string" && database.binding.length > 0 ? database.binding : "<unnamed>";
53
- findings.push({
54
- fix: "Run `wrangler d1 create <name>` and paste the returned database_id into wrangler.jsonc.",
55
- level: "fail",
56
- message: `D1 binding "${label}" has a placeholder database_id ("${databaseId || "<empty>"}").`
57
- });
58
- }
59
- }
60
- };
61
- const checkEmailDestination = (parsed, findings) => {
62
- if (parsed === void 0) {
63
- return;
64
- }
65
- const bindings = (parsed.send_email ?? []).filter(Boolean);
66
- for (const binding of bindings) {
67
- const destination = typeof binding.destination_address === "string" ? binding.destination_address : "";
68
- if (destination !== "" && isPlaceholderValue(destination)) {
69
- const label = typeof binding.name === "string" && binding.name.length > 0 ? binding.name : "send_email";
70
- findings.push({
71
- fix: "Set destination_address to a verified Cloudflare Email Routing address.",
72
- level: "warn",
73
- message: `send_email binding "${label}" has a placeholder destination_address ("${destination}").`
74
- });
75
- }
76
- }
77
- };
78
- const checkDevVariables = (cwd, findings) => {
79
- const devVariablesPath = join(cwd, DEV_VARS_FILE);
80
- if (!existsSync(devVariablesPath)) {
81
- return;
82
- }
83
- let content;
84
- try {
85
- content = readFileSync(devVariablesPath, "utf8");
86
- } catch {
87
- return;
88
- }
89
- const unfilled = parseDevVariableEntries(content).filter((entry) => SECRET_KEY_PATTERN.test(entry.key) && isPlaceholderValue(entry.value)).map((entry) => entry.key);
90
- if (unfilled.length > 0) {
91
- findings.push({
92
- fix: "Run `lunora dev` to auto-generate secrets, or fill them in by hand.",
93
- level: "warn",
94
- message: `${DEV_VARS_FILE} has unfilled secret value(s): ${unfilled.join(", ")}.`
95
- });
96
- }
97
- };
98
- const checkAdminToken = (findings) => {
99
- const token = process.env.LUNORA_ADMIN_TOKEN;
100
- if (token === void 0 || token.trim() === "") {
101
- findings.push({
102
- fix: "Set LUNORA_ADMIN_TOKEN (env or `.dev.vars`) to enable admin RPCs / studio.",
103
- level: "info",
104
- message: "LUNORA_ADMIN_TOKEN is not set."
105
- });
106
- } else {
107
- findings.push({ level: "pass", message: "LUNORA_ADMIN_TOKEN is set." });
108
- }
109
- };
110
- const checkContainers = async (cwd, findings) => {
111
- let containers;
112
- try {
113
- ({ containers } = await inferLunoraBindings({ projectRoot: cwd }));
114
- } catch {
115
- return;
116
- }
117
- for (const container of containers) {
118
- if (container.exported) {
119
- findings.push({ level: "pass", message: `container "${container.exportName}" is exported by the worker entry.` });
120
- } else {
121
- findings.push({
122
- fix: 'Add `export * from "./lunora/_generated/containers"` to your worker entry (or re-run `vis generate lunora-container`).',
123
- level: "fail",
124
- message: `container "${container.exportName}" is declared but ${container.className} is not exported by the worker entry.`
125
- });
126
- }
127
- }
128
- };
129
- const runDoctor = async (options) => {
130
- const cwd = options.cwd ?? process.cwd();
131
- const findings = [];
132
- const { parsed, path } = readWrangler(cwd);
133
- checkWrangler(parsed, path, findings);
134
- checkD1Placeholders(parsed, findings);
135
- checkEmailDestination(parsed, findings);
136
- checkDevVariables(cwd, findings);
137
- checkAdminToken(findings);
138
- await checkContainers(cwd, findings);
139
- const code = findings.some((finding) => finding.level === "fail") ? 1 : 0;
140
- return { code, findings };
141
- };
142
- const LEVEL_LABEL = { fail: "FAIL", info: "INFO", pass: "PASS", warn: "WARN" };
143
- const renderReport = (result, logger) => {
144
- logger.info("lunora doctor — project preflight");
145
- for (const finding of result.findings) {
146
- const line = `[${LEVEL_LABEL[finding.level]}] ${finding.message}`;
147
- if (finding.level === "fail") {
148
- logger.error(line);
149
- } else if (finding.level === "warn") {
150
- logger.warn(line);
151
- } else {
152
- logger.info(line);
153
- }
154
- if (finding.fix !== void 0 && finding.level !== "pass") {
155
- logger.info(` fix: ${finding.fix}`);
156
- }
157
- }
158
- const fails = result.findings.filter((finding) => finding.level === "fail").length;
159
- const warns = result.findings.filter((finding) => finding.level === "warn").length;
160
- if (fails > 0) {
161
- logger.error(`${String(fails)} failure(s), ${String(warns)} warning(s).`);
162
- } else if (warns > 0) {
163
- logger.warn(`0 failures, ${String(warns)} warning(s).`);
164
- } else {
165
- logger.success("all checks passed.");
166
- }
167
- };
168
- const execute = defineHandler(async ({ cwd, logger }) => {
169
- const result = await runDoctor({ cwd});
170
- renderReport(result, logger);
171
- return { code: result.code };
172
- });
173
-
174
- export { execute, runDoctor };
1
+ import{existsSync as g,readFileSync as h}from"node:fs";import{join as m}from"node:path";import{findWranglerFile as w,readWranglerJsonc as $,validateWranglerConfig as b,isPlaceholderValue as v,DEV_VARS_FILE as p,parseDevVariableEntries as x,inferLunoraBindings as y}from"@lunora/config";import{i as S}from"../packem_shared/command-Bjv4VmYA.mjs";const _=/(?:KEY|PASSWORD|SECRET|TOKEN)$/u,N=a=>{const e=a.trim();if(e==="")return!0;const n=e.toLowerCase();return n.includes("replace")||n.startsWith("<")&&n.endsWith(">")},R=a=>{const e=w(a);if(e===void 0)return{parsed:void 0,path:void 0};const{parsed:n}=$(e);return{parsed:n,path:e}},A=(a,e,n)=>{if(e===void 0){n.push({fix:"Run `lunora init` (or `lunora dev`) to scaffold and reconcile wrangler.jsonc.",level:"fail",message:"wrangler.jsonc not found."});return}if(a===void 0){n.push({fix:`Check ${e} is valid JSONC.`,level:"fail",message:`Could not parse ${e}.`});return}const r=b(a).errors.find(s=>s.includes("SHARD"));r===void 0?n.push({level:"pass",message:"wrangler.jsonc present with a SHARD durable-object binding."}):n.push({fix:"Run `lunora dev` to auto-reconcile, or add the binding manually.",level:"fail",message:r})},k=(a,e)=>{if(a===void 0)return;const n=(a.d1_databases??[]).filter(Boolean);for(const r of n){const s=typeof r.database_id=="string"?r.database_id:"";if(N(s)){const t=typeof r.binding=="string"&&r.binding.length>0?r.binding:"<unnamed>";e.push({fix:"Run `wrangler d1 create <name>` and paste the returned database_id into wrangler.jsonc.",level:"fail",message:`D1 binding "${t}" has a placeholder database_id ("${s||"<empty>"}").`})}}},O=(a,e)=>{if(a===void 0)return;const n=(a.send_email??[]).filter(Boolean);for(const r of n){const s=typeof r.destination_address=="string"?r.destination_address:"";if(s!==""&&v(s)){const t=typeof r.name=="string"&&r.name.length>0?r.name:"send_email";e.push({fix:"Set destination_address to a verified Cloudflare Email Routing address.",level:"warn",message:`send_email binding "${t}" has a placeholder destination_address ("${s}").`})}}},j=(a,e)=>{const n=m(a,p);if(!g(n))return;let r;try{r=h(n,"utf8")}catch{return}const s=x(r).filter(t=>_.test(t.key)&&v(t.value)).map(t=>t.key);s.length>0&&e.push({fix:"Run `lunora dev` to auto-generate secrets, or fill them in by hand.",level:"warn",message:`${p} has unfilled secret value(s): ${s.join(", ")}.`})},D=a=>{const e=process.env.LUNORA_ADMIN_TOKEN;e===void 0||e.trim()===""?a.push({fix:"Set LUNORA_ADMIN_TOKEN (env or `.dev.vars`) to enable admin RPCs / studio.",level:"info",message:"LUNORA_ADMIN_TOKEN is not set."}):a.push({level:"pass",message:"LUNORA_ADMIN_TOKEN is set."})},E=async(a,e)=>{let n;try{({containers:n}=await y({projectRoot:a}))}catch{return}for(const r of n)r.exported?e.push({level:"pass",message:`container "${r.exportName}" is exported by the worker entry.`}):e.push({fix:'Add `export * from "./lunora/_generated/containers"` to your worker entry (or re-run `vis generate lunora-container`).',level:"fail",message:`container "${r.exportName}" is declared but ${r.className} is not exported by the worker entry.`})},L=/^[\^~><= ]+/u,C=/^(?<core>\d+\.\d+\.\d+)(?:-(?<channel>[a-z]+)\.(?<counter>\d+))?$/u,I=a=>{const e=a.replace(L,"").trim(),n=C.exec(e);if(!n?.groups)return;const{channel:r,core:s,counter:t}=n.groups;return{channel:r??"",core:s??"",counter:t===void 0?void 0:Number.parseInt(t,10),raw:e}},W=(a,e)=>{const n=m(a,"package.json");if(!g(n))return;let r;try{r=JSON.parse(h(n,"utf8"))}catch{return}const s={...r.devDependencies,...r.dependencies},t=[];for(const[o,i]of Object.entries(s)){if(o!=="lunorash"&&!o.startsWith("@lunora/"))continue;const f=I(i);f&&t.push({name:o,version:f})}if(t.length<2)return;const d=o=>o.map(i=>`${i.name}@${i.version.raw}`).join(", "),u=new Set(t.map(o=>o.version.core)),c=new Set(t.map(o=>o.version.channel));if(u.size>1){e.push({fix:'Run `pnpm update "@lunora/*" lunorash` (or `npm`/`yarn` equivalent) so every Lunora package moves to the same release.',level:"warn",message:`Lunora packages span ${String(u.size)} different versions: ${d(t)}.`});return}if(c.size>1){e.push({fix:"Pick one channel (all stable, or all alpha/beta) and update the odd package out.",level:"warn",message:`Lunora packages mix release channels (${[...c].map(o=>o===""?"stable":o).join(" + ")}): ${d(t)}.`});return}const l=t.map(o=>o.version.counter).filter(o=>o!==void 0);if(l.length>1){const o=Math.min(...l),i=Math.max(...l);e.push({level:"info",message:l.length===t.length&&o===i?`Lunora packages are all at ${[...c][0]??""}.${String(i)}.`:`Lunora pre-release counters span ${String(o)}–${String(i)}: ${d(t)}.`})}},T=async a=>{const e=a.cwd??process.cwd(),n=[],{parsed:r,path:s}=R(e);return A(r,s,n),k(r,n),O(r,n),j(e,n),D(n),W(e,n),await E(e,n),{code:n.some(t=>t.level==="fail")?1:0,findings:n}},F={fail:"FAIL",info:"INFO",pass:"PASS",warn:"WARN"},K=(a,e)=>{e.info("lunora doctor — project preflight");for(const s of a.findings){const t=`[${F[s.level]}] ${s.message}`;s.level==="fail"?e.error(t):s.level==="warn"?e.warn(t):e.info(t),s.fix!==void 0&&s.level!=="pass"&&e.info(` fix: ${s.fix}`)}const n=a.findings.filter(s=>s.level==="fail").length,r=a.findings.filter(s=>s.level==="warn").length;n>0?e.error(`${String(n)} failure(s), ${String(r)} warning(s).`):r>0?e.warn(`0 failures, ${String(r)} warning(s).`):e.success("all checks passed.")},U=S(async({cwd:a,logger:e})=>{const n=await T({cwd:a});return K(n,e),{code:n.code}});export{U as execute,T as runDoctor};