@lunora/cli 1.0.0-alpha.90 → 1.0.0-alpha.92

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.
@@ -1,96 +1,94 @@
1
- import { existsSync } from 'node:fs';
1
+ import { readFileSync, existsSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
- import { runCodegen } from '@lunora/codegen';
4
- import { p as parseApiSpec } from '../packem_shared/api-spec-Bx0iKbxA.mjs';
5
- import { a as renderCodegenHint } from '../packem_shared/codegen-error-DJG-ghs_.mjs';
3
+ import { parse } from 'jsonc-parser';
6
4
  import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
7
- import { e as execArgsFor, d as detectPackageManager } from '../packem_shared/detect-package-manager-v4hHpQd0.mjs';
8
- import { v as validateOutputFormat, i as isJsonFormat, p as printJson, l as loggerForFormat } from '../packem_shared/output-format-B4642rjE.mjs';
9
- import { r as runSchemaDriftGate } from '../packem_shared/schema-drift-gate-BtBt0as0.mjs';
10
- import { defaultSpawner } from '../packem_shared/createRecordingSpawner-WuSn20kb.mjs';
11
- import { validateWranglerProject } from '@lunora/config';
5
+ import { o as openUrl } from '../packem_shared/open-url-4PBLY9X0.mjs';
12
6
 
13
- const runTypecheckStep = async (cwd, spawner) => {
14
- if (!existsSync(join(cwd, "tsconfig.json"))) {
15
- return { warning: "no tsconfig.json found — skipping TypeScript type-check" };
7
+ const DEFAULT_DEV_PORT = 8787;
8
+ const STUDIO_PATH = "/_lunora/studio";
9
+ const findWranglerFile = (projectRoot) => {
10
+ for (const candidate of ["wrangler.jsonc", "wrangler.json"]) {
11
+ const fullPath = join(projectRoot, candidate);
12
+ if (existsSync(fullPath)) {
13
+ return fullPath;
14
+ }
15
+ }
16
+ return void 0;
17
+ };
18
+ const readWrangler = (projectRoot) => {
19
+ const file = findWranglerFile(projectRoot);
20
+ if (!file) {
21
+ return void 0;
22
+ }
23
+ try {
24
+ const parsed = parse(readFileSync(file, "utf8"));
25
+ return parsed !== null && typeof parsed === "object" ? parsed : void 0;
26
+ } catch {
27
+ return void 0;
16
28
  }
17
- const exec = execArgsFor(detectPackageManager(cwd), "tsc", ["--noEmit", "-p", "tsconfig.json"]);
18
- const result = await spawner({ args: exec.args, command: exec.command, cwd });
19
- return result.code === 0 ? {} : { error: `type errors: tsc --noEmit exited ${String(result.code)}` };
20
29
  };
21
- const reportVerifyResult = (logger, errors, warnings, wranglerPath) => {
22
- if (errors.length === 0 && warnings.length === 0) {
23
- logger.success("verify: project is valid");
24
- return { code: 0, errors: [], warnings: [], wranglerPath };
30
+ const resolveDevPort = (wrangler) => {
31
+ if (!wrangler) {
32
+ return DEFAULT_DEV_PORT;
25
33
  }
26
- if (warnings.length > 0) {
27
- logger.warn("verify: warnings:");
28
- for (const warning of warnings) {
29
- logger.warn(` - ${warning}`);
34
+ const { dev } = wrangler;
35
+ if (dev !== null && typeof dev === "object") {
36
+ const { port } = dev;
37
+ if (typeof port === "number" && Number.isFinite(port)) {
38
+ return port;
30
39
  }
31
40
  }
32
- if (errors.length > 0) {
33
- logger.error("verify: errors:");
34
- for (const error of errors) {
35
- logger.error(` - ${error}`);
36
- const hint = renderCodegenHint(error);
37
- if (hint !== void 0) {
38
- logger.error(hint);
41
+ return DEFAULT_DEV_PORT;
42
+ };
43
+ const resolveRemoteUrl = (wrangler) => {
44
+ if (!wrangler) {
45
+ return void 0;
46
+ }
47
+ const { routes } = wrangler;
48
+ if (Array.isArray(routes) && routes.length > 0) {
49
+ const first = routes[0];
50
+ if (typeof first === "string") {
51
+ return `https://${first.split("/")[0] ?? first}${STUDIO_PATH}`;
52
+ }
53
+ if (first !== null && typeof first === "object") {
54
+ const { pattern } = first;
55
+ if (typeof pattern === "string" && pattern.length > 0) {
56
+ return `https://${pattern.split("/")[0] ?? pattern}${STUDIO_PATH}`;
39
57
  }
40
58
  }
41
- return { code: 1, errors, warnings, wranglerPath };
42
59
  }
43
- logger.success("verify: project is valid (with warnings)");
44
- return { code: 0, errors: [], warnings, wranglerPath };
60
+ const { name } = wrangler;
61
+ if (typeof name === "string" && name.length > 0) {
62
+ return `https://${name}.workers.dev${STUDIO_PATH}`;
63
+ }
64
+ return void 0;
45
65
  };
46
- const runVerifyCommand = async (options) => {
66
+ const runViewCommand = async (options) => {
47
67
  const cwd = options.cwd ?? process.cwd();
48
- const logger = loggerForFormat(options.format, options.logger);
49
- const formatError = validateOutputFormat("verify", options.format);
50
- if (formatError !== void 0) {
51
- options.logger.error(formatError);
52
- return { code: 1, error: formatError, errors: [], warnings: [], wranglerPath: void 0 };
68
+ const wrangler = readWrangler(cwd);
69
+ const { logger } = options;
70
+ let url;
71
+ if (options.remote) {
72
+ url = resolveRemoteUrl(wrangler);
73
+ if (!url) {
74
+ logger.error("view --remote: could not determine the remote URL from wrangler config (set `routes` or `name`).");
75
+ return { code: 1, url: void 0 };
76
+ }
77
+ } else {
78
+ url = `http://localhost:${String(resolveDevPort(wrangler))}${STUDIO_PATH}`;
53
79
  }
54
- const validation = validateWranglerProject({ projectRoot: cwd });
55
- const errors = [...validation.report.errors];
56
- const warnings = [...validation.report.warnings];
80
+ logger.info(`opening ${url}`);
57
81
  try {
58
- const codegen = runCodegen({ apiSpec: options.apiSpec, dryRun: true, projectRoot: cwd });
59
- const gate = runSchemaDriftGate({ allowDrift: options.allowSchemaDrift === true, codegen, logger, readOnly: true });
60
- if (gate.blocked) {
61
- errors.push(gate.reason);
62
- }
82
+ await openUrl(url, { opener: options.opener });
63
83
  } catch (error) {
64
84
  const message = error instanceof Error ? error.message : String(error);
65
- errors.push(`codegen failed: ${message}`);
66
- }
67
- if (options.typecheck !== false) {
68
- const typecheck = await runTypecheckStep(cwd, options.spawner ?? defaultSpawner);
69
- if (typecheck.error !== void 0) {
70
- errors.push(typecheck.error);
71
- }
72
- if (typecheck.warning !== void 0) {
73
- warnings.push(typecheck.warning);
74
- }
75
- }
76
- const result = reportVerifyResult(logger, errors, warnings, validation.wranglerPath);
77
- if (isJsonFormat(options.format)) {
78
- printJson(result);
85
+ logger.error(`view: failed to open URL: ${message}`);
86
+ return { code: 1, url };
79
87
  }
80
- return result;
88
+ return { code: 0, url };
81
89
  };
82
- const execute = defineHandler(async ({ cwd, logger, options }) => {
83
- const result = await runVerifyCommand({
84
- allowSchemaDrift: options.allowSchemaDrift === true,
85
- apiSpec: parseApiSpec(options.apiSpec),
86
- cwd,
87
- format: options.format,
88
- logger,
89
- // `--no-typecheck` is declared as a `no-*` option but cerebro exposes it
90
- // under the negated `typecheck` key (false when passed, true when absent).
91
- typecheck: options.typecheck === false ? false : void 0
92
- });
93
- return { code: result.code };
94
- });
90
+ const execute = defineHandler(
91
+ ({ cwd, logger, options }) => runViewCommand({ cwd, logger, remote: options.remote === true })
92
+ );
95
93
 
96
- export { execute, runVerifyCommand };
94
+ export { execute, runViewCommand };
@@ -1,94 +1,202 @@
1
- import { readFileSync, existsSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import { parse } from 'jsonc-parser';
1
+ import { readLinkedProject } from '@lunora/config';
4
2
  import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
5
- import { o as openUrl } from '../packem_shared/open-url-4PBLY9X0.mjs';
3
+ import { e as execArgsFor, d as detectPackageManager } from '../packem_shared/detect-package-manager-v4hHpQd0.mjs';
4
+ import { defaultSpawner } from '../packem_shared/createRecordingSpawner-WuSn20kb.mjs';
5
+ import { createR2Sql } from '@lunora/bindings/r2sql';
6
+ import { createPipelineLogReader } from '@lunora/runtime';
6
7
 
7
- const DEFAULT_DEV_PORT = 8787;
8
- const STUDIO_PATH = "/_lunora/studio";
9
- const findWranglerFile = (projectRoot) => {
10
- for (const candidate of ["wrangler.jsonc", "wrangler.json"]) {
11
- const fullPath = join(projectRoot, candidate);
12
- if (existsSync(fullPath)) {
13
- return fullPath;
14
- }
8
+ const LOG_LEVELS = /* @__PURE__ */ new Set(["debug", "error", "fatal", "info", "log", "trace", "warn"]);
9
+ const EPOCH_MILLIS_RE = /^\d+$/;
10
+ const parseTimestamp = (value, flag) => {
11
+ if (value === void 0) {
12
+ return void 0;
13
+ }
14
+ const trimmed = value.trim();
15
+ if (EPOCH_MILLIS_RE.test(trimmed)) {
16
+ return Number(trimmed);
15
17
  }
16
- return void 0;
18
+ const parsed = Date.parse(trimmed);
19
+ if (Number.isNaN(parsed)) {
20
+ throw new TypeError(`logs: invalid ${flag} "${value}" — pass epoch-millis or an ISO 8601 date`);
21
+ }
22
+ return parsed;
17
23
  };
18
- const readWrangler = (projectRoot) => {
19
- const file = findWranglerFile(projectRoot);
20
- if (!file) {
24
+ const parseLevel = (value, flag) => {
25
+ if (value === void 0) {
21
26
  return void 0;
22
27
  }
23
- try {
24
- const parsed = parse(readFileSync(file, "utf8"));
25
- return parsed !== null && typeof parsed === "object" ? parsed : void 0;
26
- } catch {
27
- return void 0;
28
+ if (!LOG_LEVELS.has(value)) {
29
+ throw new TypeError(`logs: invalid ${flag} "${value}" — expected one of trace, debug, log, info, warn, error, fatal`);
28
30
  }
31
+ return value;
29
32
  };
30
- const resolveDevPort = (wrangler) => {
31
- if (!wrangler) {
32
- return DEFAULT_DEV_PORT;
33
- }
34
- const { dev } = wrangler;
35
- if (dev !== null && typeof dev === "object") {
36
- const { port } = dev;
37
- if (typeof port === "number" && Number.isFinite(port)) {
38
- return port;
39
- }
33
+ const buildQuery = (options) => {
34
+ const query = {};
35
+ const sinceTs = parseTimestamp(options.since, "--since");
36
+ if (sinceTs !== void 0) {
37
+ query.sinceTs = sinceTs;
40
38
  }
41
- return DEFAULT_DEV_PORT;
42
- };
43
- const resolveRemoteUrl = (wrangler) => {
44
- if (!wrangler) {
45
- return void 0;
39
+ const untilTs = parseTimestamp(options.until, "--until");
40
+ if (untilTs !== void 0) {
41
+ query.untilTs = untilTs;
46
42
  }
47
- const { routes } = wrangler;
48
- if (Array.isArray(routes) && routes.length > 0) {
49
- const first = routes[0];
50
- if (typeof first === "string") {
51
- return `https://${first.split("/")[0] ?? first}${STUDIO_PATH}`;
52
- }
53
- if (first !== null && typeof first === "object") {
54
- const { pattern } = first;
55
- if (typeof pattern === "string" && pattern.length > 0) {
56
- return `https://${pattern.split("/")[0] ?? pattern}${STUDIO_PATH}`;
57
- }
43
+ const level = parseLevel(options.level, "--level");
44
+ if (level !== void 0) {
45
+ query.level = level;
46
+ }
47
+ const minLevel = parseLevel(options.minLevel, "--min-level");
48
+ if (minLevel !== void 0) {
49
+ query.minLevel = minLevel;
50
+ }
51
+ if (options.functionPrefix !== void 0) {
52
+ query.functionPathPrefix = options.functionPrefix;
53
+ }
54
+ if (options.traceId !== void 0) {
55
+ query.traceId = options.traceId;
56
+ }
57
+ if (options.shardKey !== void 0) {
58
+ query.shardKey = options.shardKey;
59
+ }
60
+ if (options.userId !== void 0) {
61
+ query.userId = options.userId;
62
+ }
63
+ if (options.limit !== void 0) {
64
+ const limit = Number(options.limit);
65
+ if (!Number.isFinite(limit)) {
66
+ throw new TypeError(`logs: invalid --limit "${options.limit}" — expected a number`);
58
67
  }
68
+ query.limit = limit;
59
69
  }
60
- const { name } = wrangler;
61
- if (typeof name === "string" && name.length > 0) {
62
- return `https://${name}.workers.dev${STUDIO_PATH}`;
70
+ if (options.cursor !== void 0) {
71
+ const cursorTs = Number(options.cursor);
72
+ if (!Number.isFinite(cursorTs)) {
73
+ throw new TypeError(`logs: invalid --cursor "${options.cursor}" — expected the epoch-millis ts from a prior page's nextCursor`);
74
+ }
75
+ query.cursor = { ts: cursorTs };
63
76
  }
64
- return void 0;
77
+ return query;
65
78
  };
66
- const runViewCommand = async (options) => {
67
- const cwd = options.cwd ?? process.cwd();
68
- const wrangler = readWrangler(cwd);
69
- const { logger } = options;
70
- let url;
71
- if (options.remote) {
72
- url = resolveRemoteUrl(wrangler);
73
- if (!url) {
74
- logger.error("view --remote: could not determine the remote URL from wrangler config (set `routes` or `name`).");
75
- return { code: 1, url: void 0 };
76
- }
77
- } else {
78
- url = `http://localhost:${String(resolveDevPort(wrangler))}${STUDIO_PATH}`;
79
+ const formatRow = (row) => {
80
+ const time = new Date(row.ts).toISOString();
81
+ const level = row.level.toUpperCase().padEnd(5);
82
+ return `${time} ${level} ${row.functionPath} ${row.message}`;
83
+ };
84
+ const runDurableLogsCommand = async (options) => {
85
+ const environment = options.environment ?? process.env;
86
+ const accountId = environment.R2_SQL_ACCOUNT_ID;
87
+ const apiToken = environment.R2_SQL_TOKEN;
88
+ const bucket = environment.R2_SQL_BUCKET;
89
+ const missing = [];
90
+ if (accountId === void 0 || accountId.length === 0) {
91
+ missing.push("R2_SQL_ACCOUNT_ID");
92
+ }
93
+ if (apiToken === void 0 || apiToken.length === 0) {
94
+ missing.push("R2_SQL_TOKEN");
95
+ }
96
+ if (bucket === void 0 || bucket.length === 0) {
97
+ missing.push("R2_SQL_BUCKET");
98
+ }
99
+ if (options.table === void 0 || options.table.length === 0) {
100
+ missing.push("--table");
101
+ }
102
+ if (missing.length > 0) {
103
+ options.logger.error(
104
+ `logs --durable: R2 SQL not configured (missing ${missing.join(", ")}). The Pipeline must write to an R2 Data Catalog (Iceberg) table, and you must supply R2_SQL_ACCOUNT_ID / R2_SQL_TOKEN / R2_SQL_BUCKET plus --table — see the observability docs.`
105
+ );
106
+ return { code: 1, error: "not configured" };
79
107
  }
80
- logger.info(`opening ${url}`);
108
+ let query;
81
109
  try {
82
- await openUrl(url, { opener: options.opener });
110
+ query = buildQuery(options);
83
111
  } catch (error) {
84
- const message = error instanceof Error ? error.message : String(error);
85
- logger.error(`view: failed to open URL: ${message}`);
86
- return { code: 1, url };
112
+ options.logger.error(error instanceof Error ? error.message : String(error));
113
+ return { code: 1, error: "invalid option" };
114
+ }
115
+ const client = createR2Sql({ accountId, apiToken, bucket, fetch: options.fetch });
116
+ const reader = createPipelineLogReader(client, { namespace: options.namespace, table: options.table });
117
+ const page = await reader.query(query);
118
+ for (const row of page.rows) {
119
+ process.stdout.write(`${options.ndjson === true ? JSON.stringify(row) : formatRow(row)}
120
+ `);
121
+ }
122
+ if (page.rows.length === 0) {
123
+ options.logger.info("logs --durable: no matching log records");
124
+ } else if (page.nextCursor !== void 0) {
125
+ options.logger.info(`logs --durable: more rows available — pass --cursor ${String(page.nextCursor.ts)} for the next page`);
126
+ }
127
+ return { code: 0, rows: page.rows };
128
+ };
129
+
130
+ const LOG_FORMATS = /* @__PURE__ */ new Set(["json", "pretty"]);
131
+ const runLogsCommand = async (options) => {
132
+ const cwd = options.cwd ?? process.cwd();
133
+ if (options.format !== void 0 && !LOG_FORMATS.has(options.format)) {
134
+ options.logger.error(`logs: unknown --format "${options.format}" — expected pretty | json`);
135
+ return { code: 1, descriptor: void 0, error: "invalid format" };
136
+ }
137
+ const args = ["tail"];
138
+ if (options.worker !== void 0) {
139
+ args.push(options.worker);
140
+ }
141
+ const env = options.env ?? readLinkedProject(cwd)?.env;
142
+ if (env !== void 0) {
143
+ args.push("--env", env);
144
+ }
145
+ if (options.format !== void 0) {
146
+ args.push("--format", options.format);
87
147
  }
88
- return { code: 0, url };
148
+ if (options.status !== void 0) {
149
+ args.push("--status", options.status);
150
+ }
151
+ if (options.search !== void 0) {
152
+ args.push("--search", options.search);
153
+ }
154
+ if (options.temporary) {
155
+ args.push("--temporary");
156
+ }
157
+ const exec = execArgsFor(detectPackageManager(cwd), "wrangler", args);
158
+ const descriptor = {
159
+ args: exec.args,
160
+ command: exec.command,
161
+ cwd
162
+ };
163
+ options.logger.info(`tailing logs via ${descriptor.command} ${descriptor.args.join(" ")}`);
164
+ const spawner = options.spawner ?? defaultSpawner;
165
+ const result = await spawner(descriptor);
166
+ return {
167
+ code: result.code,
168
+ descriptor
169
+ };
89
170
  };
90
- const execute = defineHandler(
91
- ({ cwd, logger, options }) => runViewCommand({ cwd, logger, remote: options.remote === true })
92
- );
171
+ const execute = defineHandler(({ argument, cwd, logger, options }) => {
172
+ if (options.durable === true) {
173
+ return runDurableLogsCommand({
174
+ cursor: options.cursor,
175
+ functionPrefix: options.functionPrefix,
176
+ level: options.level,
177
+ limit: options.limit,
178
+ logger,
179
+ minLevel: options.minLevel,
180
+ namespace: options.namespace,
181
+ ndjson: options.ndjson === true,
182
+ shardKey: options.shardKey,
183
+ since: options.since,
184
+ table: options.table,
185
+ traceId: options.traceId,
186
+ until: options.until,
187
+ userId: options.userId
188
+ });
189
+ }
190
+ return runLogsCommand({
191
+ cwd,
192
+ env: options.env,
193
+ format: options.format,
194
+ logger,
195
+ search: options.search,
196
+ status: options.status,
197
+ temporary: options.temporary === true,
198
+ worker: argument[0]
199
+ });
200
+ });
93
201
 
94
- export { execute, runViewCommand };
202
+ export { execute, runLogsCommand };
@@ -509,9 +509,9 @@ const linkCommand = {
509
509
 
510
510
  const logsCommand = {
511
511
  argument: { description: "Worker name (defaults to the name in wrangler config)", name: "worker", type: String },
512
- description: "Stream live logs from a deployed Lunora Worker",
512
+ description: "Stream live logs from a deployed Worker, or read the durable log archive with --durable",
513
513
  group: "Deploy",
514
- loader: () => import('../packem_chunks/handler15.mjs').then((m) => {
514
+ loader: () => import('../packem_chunks/handler21.mjs').then((m) => {
515
515
  return { default: m.execute };
516
516
  }),
517
517
  name: "logs",
@@ -524,7 +524,22 @@ const logsCommand = {
524
524
  description: "Tail a temporary-account deployment when unauthenticated (wrangler tail --temporary). Errors if you're already authenticated.",
525
525
  name: "temporary",
526
526
  type: Boolean
527
- }
527
+ },
528
+ // --- durable-archive path (--durable) ---
529
+ { description: "Read the durable log archive (pipelineLogSink → R2) via R2 SQL instead of tailing live", name: "durable", type: Boolean },
530
+ { description: "durable: Iceberg table the Pipeline writes to (required with --durable)", name: "table", type: String },
531
+ { description: "durable: Iceberg namespace (R2 Data Catalog database) the table lives in", name: "namespace", type: String },
532
+ { description: "durable: lower time bound (epoch-millis or ISO 8601), inclusive", name: "since", type: String },
533
+ { description: "durable: upper time bound (epoch-millis or ISO 8601), inclusive", name: "until", type: String },
534
+ { description: "durable: exact severity filter (trace|debug|log|info|warn|error|fatal)", name: "level", type: String },
535
+ { description: "durable: severity floor — this level and every more-severe one", name: "min-level", type: String },
536
+ { description: "durable: keep function paths starting with this prefix (LIKE 'prefix%')", name: "function-prefix", type: String },
537
+ { description: "durable: trace-id filter", name: "trace-id", type: String },
538
+ { description: "durable: shard-key filter", name: "shard-key", type: String },
539
+ { description: "durable: user-id filter", name: "user-id", type: String },
540
+ { description: "durable: max rows (clamped to 1–10000; default 500)", name: "limit", type: String },
541
+ { description: "durable: resume after a prior page — the ts from its nextCursor", name: "cursor", type: String },
542
+ { description: "durable: emit one JSON object per line instead of a table", name: "ndjson", type: Boolean }
528
543
  ]
529
544
  };
530
545
 
@@ -571,7 +586,7 @@ const prepareCommand = {
571
586
  description: "Run codegen + binding reconcile + wrangler validation (no Vite) — for CI",
572
587
  examples: [["lunora prepare", "Codegen + binding reconcile + validate (CI, before deploy)"]],
573
588
  group: "Deploy",
574
- loader: () => import('../packem_chunks/handler16.mjs').then((m) => {
589
+ loader: () => import('../packem_chunks/handler15.mjs').then((m) => {
575
590
  return { default: m.execute };
576
591
  }),
577
592
  name: "prepare",
@@ -595,7 +610,7 @@ const registryCommand = {
595
610
  ["lunora registry build --check", "Verify the committed catalog is current"]
596
611
  ],
597
612
  group: "Project",
598
- loader: () => import('../packem_chunks/handler17.mjs').then((m) => {
613
+ loader: () => import('../packem_chunks/handler16.mjs').then((m) => {
599
614
  return { default: m.execute };
600
615
  }),
601
616
  name: "registry",
@@ -645,7 +660,7 @@ const rulesCommand = {
645
660
  ["lunora rules check --strict", "Exit non-zero when rules are missing (CI gate)"]
646
661
  ],
647
662
  group: "Project",
648
- loader: () => import('../packem_chunks/handler18.mjs').then((m) => {
663
+ loader: () => import('../packem_chunks/handler17.mjs').then((m) => {
649
664
  return { default: m.execute };
650
665
  }),
651
666
  name: "rules",
@@ -683,7 +698,7 @@ const seedCommand = {
683
698
  ["lunora seed --seed 7 --dry-run", "Print the NDJSON for seed 7 without inserting"]
684
699
  ],
685
700
  group: "Data",
686
- loader: () => import('../packem_chunks/handler19.mjs').then((m) => {
701
+ loader: () => import('../packem_chunks/handler18.mjs').then((m) => {
687
702
  return { default: m.execute };
688
703
  }),
689
704
  name: "seed",
@@ -712,7 +727,7 @@ const verifyCommand = {
712
727
  ["lunora verify --no-typecheck", "Skip the TypeScript type-check"]
713
728
  ],
714
729
  group: "Deploy",
715
- loader: () => import('../packem_chunks/handler20.mjs').then((m) => {
730
+ loader: () => import('../packem_chunks/handler19.mjs').then((m) => {
716
731
  return { default: m.execute };
717
732
  }),
718
733
  name: "verify",
@@ -731,7 +746,7 @@ const viewCommand = {
731
746
  ["lunora view --remote", "Open the deployed studio"]
732
747
  ],
733
748
  group: "Project",
734
- loader: () => import('../packem_chunks/handler21.mjs').then((m) => {
749
+ loader: () => import('../packem_chunks/handler20.mjs').then((m) => {
735
750
  return { default: m.execute };
736
751
  }),
737
752
  name: "view",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/cli",
3
- "version": "1.0.0-alpha.90",
3
+ "version": "1.0.0-alpha.92",
4
4
  "description": "The Lunora CLI: init, dev, deploy, codegen, run, reset, and migrate commands",
5
5
  "keywords": [
6
6
  "agent-skills",
@@ -52,12 +52,14 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "@bomb.sh/tab": "0.0.19",
55
- "@lunora/codegen": "1.0.0-alpha.47",
56
- "@lunora/config": "1.0.0-alpha.71",
55
+ "@lunora/bindings": "1.0.0-alpha.9",
56
+ "@lunora/codegen": "1.0.0-alpha.48",
57
+ "@lunora/config": "1.0.0-alpha.73",
57
58
  "@lunora/container": "1.0.0-alpha.13",
58
- "@lunora/d1": "1.0.0-alpha.33",
59
+ "@lunora/d1": "1.0.0-alpha.35",
59
60
  "@lunora/errors": "1.0.0-alpha.6",
60
- "@lunora/seed": "1.0.0-alpha.27",
61
+ "@lunora/runtime": "1.0.0-alpha.31",
62
+ "@lunora/seed": "1.0.0-alpha.28",
61
63
  "@visulima/cerebro": "3.0.0",
62
64
  "@visulima/error": "6.0.0",
63
65
  "@visulima/fs": "5.0.4",