@lunora/cli 1.0.0-alpha.57 → 1.0.0-alpha.58

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 (30) hide show
  1. package/dist/bin.mjs +1 -1
  2. package/dist/index.mjs +5 -5
  3. package/dist/packem_chunks/handler.mjs +2 -2
  4. package/dist/packem_chunks/handler10.mjs +1 -1
  5. package/dist/packem_chunks/handler11.mjs +1 -1
  6. package/dist/packem_chunks/handler16.mjs +1 -1
  7. package/dist/packem_chunks/handler17.mjs +1 -1
  8. package/dist/packem_chunks/handler19.mjs +1 -1
  9. package/dist/packem_chunks/handler20.mjs +1 -1
  10. package/dist/packem_chunks/handler21.mjs +1 -1
  11. package/dist/packem_chunks/handler3.mjs +5 -2
  12. package/dist/packem_chunks/handler4.mjs +1 -1
  13. package/dist/packem_chunks/handler7.mjs +1 -1
  14. package/dist/packem_chunks/planDevCommand.mjs +1 -1
  15. package/dist/packem_chunks/runCodegenCommand.mjs +1 -1
  16. package/dist/packem_chunks/runDeployCommand.mjs +1 -1
  17. package/dist/packem_chunks/runInitCommand.mjs +2 -2
  18. package/dist/packem_chunks/runMigrateGenerateCommand.mjs +4 -3
  19. package/dist/packem_chunks/runRpcCommand.mjs +2 -1
  20. package/dist/packem_shared/{COMMANDS-B0ftFD_3.mjs → COMMANDS-DsWLzOXZ.mjs} +23 -2
  21. package/dist/packem_shared/{DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs → DEFAULT_IMPORT_BATCH_SIZE-CRQmmBZM.mjs} +3 -2
  22. package/dist/packem_shared/{api-spec-CtA6ilu4.mjs → api-spec-Bx0iKbxA.mjs} +3 -1
  23. package/dist/packem_shared/{buildRegistryIndex-BcYe607_.mjs → buildRegistryIndex-CqM5FwGI.mjs} +1 -1
  24. package/dist/packem_shared/{commands-BK6Pt3Ni.mjs → commands-vnRRkhNE.mjs} +12 -9
  25. package/dist/packem_shared/{open-url-Dfq6fAyT.mjs → open-url-4PBLY9X0.mjs} +3 -2
  26. package/dist/packem_shared/{parseManifest--vZf2FY1.mjs → parseManifest-BBrXCg9V.mjs} +16 -9
  27. package/dist/packem_shared/runAddCommand-BCcJzs_k.mjs +4 -0
  28. package/dist/packem_shared/{storage-C8SAm5zu.mjs → storage-bGfgwOgF.mjs} +1 -1
  29. package/package.json +7 -6
  30. package/dist/packem_shared/runAddCommand-DWjH0Heb.mjs +0 -4
package/dist/bin.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { runCli } from './packem_shared/COMMANDS-B0ftFD_3.mjs';
2
+ import { runCli } from './packem_shared/COMMANDS-DsWLzOXZ.mjs';
3
3
 
4
4
  try {
5
5
  const code = await runCli();
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- export { COMMANDS, VERSION, runCli } from './packem_shared/COMMANDS-B0ftFD_3.mjs';
1
+ export { COMMANDS, VERSION, runCli } from './packem_shared/COMMANDS-DsWLzOXZ.mjs';
2
2
  export { runCodegenCommand } from './packem_chunks/runCodegenCommand.mjs';
3
- export { DEFAULT_IMPORT_BATCH_SIZE, runExportCommand, runImportCommand } from './packem_shared/DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs';
3
+ export { DEFAULT_IMPORT_BATCH_SIZE, runExportCommand, runImportCommand } from './packem_shared/DEFAULT_IMPORT_BATCH_SIZE-CRQmmBZM.mjs';
4
4
  export { runDeployCommand } from './packem_chunks/runDeployCommand.mjs';
5
5
  export { planDevCommand, runDevCommand } from './packem_chunks/planDevCommand.mjs';
6
6
  export { runInitCommand } from './packem_chunks/runInitCommand.mjs';
@@ -13,7 +13,7 @@ export { createLogger, pail } from './packem_shared/createLogger-B40gPzQo.mjs';
13
13
  export { diffSnapshots, renderAddColumn, renderCreateIndex, renderCreateTable, renderDropIndex, renderDropTable, renderMigrationFile, validatorKindToSqlType } from './packem_shared/diffSnapshots-BeDvvNiF.mjs';
14
14
  export { default as schemaIrToSnapshot } from './packem_shared/schemaIrToSnapshot-DdsljJT-.mjs';
15
15
  export { createRecordingSpawner, defaultSpawner } from './packem_shared/createRecordingSpawner-DxI3mebw.mjs';
16
- export { default as parseManifest } from './packem_shared/parseManifest--vZf2FY1.mjs';
16
+ export { default as parseManifest } from './packem_shared/parseManifest-BBrXCg9V.mjs';
17
17
  export { REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, validateWranglerProject as validateWrangler, validateWranglerConfig } from '@lunora/config';
18
- export { buildRegistryIndex } from './packem_shared/buildRegistryIndex-BcYe607_.mjs';
19
- export { r as runAddCommand, a as runBuildIndexCommand, b as runRegistryViewCommand } from './packem_shared/commands-BK6Pt3Ni.mjs';
18
+ export { buildRegistryIndex } from './packem_shared/buildRegistryIndex-CqM5FwGI.mjs';
19
+ export { r as runAddCommand, a as runBuildIndexCommand, b as runRegistryViewCommand } from './packem_shared/commands-vnRRkhNE.mjs';
@@ -4,8 +4,8 @@ import { join, basename } from '@visulima/path';
4
4
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
5
5
  import { v as validateOutputFormat, i as isJsonFormat, p as printJson, l as loggerForFormat } from '../packem_shared/output-format-wUvAN6AL.mjs';
6
6
  import { t as tuiText, a as tuiSelect } from '../packem_shared/tui-prompts-BjEN8XgP.mjs';
7
- import { n as normalizeFeature, E as EMAIL_ITEM, s as sanitizeBucketName, d as deriveBucketName, p as promptBucketName, r as resolveTypedDestination, M as MAIL_DESTINATION_PROMPT, a as sanitizeDatabaseName, b as deriveDatabaseName, c as promptDatabaseName, D as DEFAULT_AUTH_ITEM, e as promptAuthProvider, A as AUTH_PROVIDER_OPTIONS, w as withStorageBucketName, f as withMailDestination, g as withAuthDatabaseName } from '../packem_shared/storage-C8SAm5zu.mjs';
8
- import { r as runAddCommand } from '../packem_shared/commands-BK6Pt3Ni.mjs';
7
+ import { n as normalizeFeature, E as EMAIL_ITEM, s as sanitizeBucketName, d as deriveBucketName, p as promptBucketName, r as resolveTypedDestination, M as MAIL_DESTINATION_PROMPT, a as sanitizeDatabaseName, b as deriveDatabaseName, c as promptDatabaseName, D as DEFAULT_AUTH_ITEM, e as promptAuthProvider, A as AUTH_PROVIDER_OPTIONS, w as withStorageBucketName, f as withMailDestination, g as withAuthDatabaseName } from '../packem_shared/storage-bGfgwOgF.mjs';
8
+ import { r as runAddCommand } from '../packem_shared/commands-vnRRkhNE.mjs';
9
9
 
10
10
  const providerToItem = (provider) => {
11
11
  const value = provider.trim().toLowerCase();
@@ -1,6 +1,6 @@
1
1
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
2
2
  import { a as resolveProductionWorkerUrl } from '../packem_shared/resolve-target-qbsJ_5sF.mjs';
3
- import { runExportCommand } from '../packem_shared/DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs';
3
+ import { runExportCommand } from '../packem_shared/DEFAULT_IMPORT_BATCH_SIZE-CRQmmBZM.mjs';
4
4
 
5
5
  const execute = defineHandler(
6
6
  ({ argument, cwd, logger, options }) => runExportCommand({
@@ -1,6 +1,6 @@
1
1
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
2
2
  import { a as resolveProductionWorkerUrl } from '../packem_shared/resolve-target-qbsJ_5sF.mjs';
3
- import { runImportCommand } from '../packem_shared/DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs';
3
+ import { runImportCommand } from '../packem_shared/DEFAULT_IMPORT_BATCH_SIZE-CRQmmBZM.mjs';
4
4
 
5
5
  const execute = defineHandler(({ argument, cwd, logger, options }) => {
6
6
  const file = argument[0];
@@ -1,6 +1,6 @@
1
1
  import { runCodegen } from '@lunora/codegen';
2
2
  import { validateWranglerProject, inferLunoraBindings, reconcileWranglerBindings } from '@lunora/config';
3
- import { p as parseApiSpec } from '../packem_shared/api-spec-CtA6ilu4.mjs';
3
+ import { p as parseApiSpec } from '../packem_shared/api-spec-Bx0iKbxA.mjs';
4
4
  import { r as renderCodegenFailure } from '../packem_shared/codegen-error-DJG-ghs_.mjs';
5
5
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
6
6
  import { r as runSchemaDriftGate } from '../packem_shared/schema-drift-gate-BtBt0as0.mjs';
@@ -1,5 +1,5 @@
1
1
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
2
- import { r as runAddCommand, b as runRegistryViewCommand, a as runBuildIndexCommand } from '../packem_shared/commands-BK6Pt3Ni.mjs';
2
+ import { r as runAddCommand, b as runRegistryViewCommand, a as runBuildIndexCommand } from '../packem_shared/commands-vnRRkhNE.mjs';
3
3
 
4
4
  const execute = defineHandler(({ argument, cwd, logger, options }) => {
5
5
  const subcommand = argument[0];
@@ -8,7 +8,7 @@ import { Project } from 'ts-morph';
8
8
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
9
9
  import { a as resolveProductionWorkerUrl } from '../packem_shared/resolve-target-qbsJ_5sF.mjs';
10
10
  import { b as tuiConfirm } from '../packem_shared/tui-prompts-BjEN8XgP.mjs';
11
- import { runImportCommand } from '../packem_shared/DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs';
11
+ import { runImportCommand } from '../packem_shared/DEFAULT_IMPORT_BATCH_SIZE-CRQmmBZM.mjs';
12
12
  import { runResetCommand } from './runResetCommand.mjs';
13
13
 
14
14
  const isLocalUrl = (url) => {
@@ -1,7 +1,7 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { runCodegen } from '@lunora/codegen';
4
- import { p as parseApiSpec } from '../packem_shared/api-spec-CtA6ilu4.mjs';
4
+ import { p as parseApiSpec } from '../packem_shared/api-spec-Bx0iKbxA.mjs';
5
5
  import { a as renderCodegenHint } from '../packem_shared/codegen-error-DJG-ghs_.mjs';
6
6
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
7
7
  import { e as execArgsFor, d as detectPackageManager } from '../packem_shared/detect-package-manager-Cxo6Tpyx.mjs';
@@ -2,7 +2,7 @@ import { readFileSync, existsSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { parse } from 'jsonc-parser';
4
4
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
5
- import { o as openUrl } from '../packem_shared/open-url-Dfq6fAyT.mjs';
5
+ import { o as openUrl } from '../packem_shared/open-url-4PBLY9X0.mjs';
6
6
 
7
7
  const DEFAULT_DEV_PORT = 8787;
8
8
  const STUDIO_PATH = "/_lunora/studio";
@@ -1,10 +1,11 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
3
  import { join } from 'node:path';
4
+ import { LunoraError } from '@lunora/errors';
4
5
  import { r as resolveAdminBaseUrl } from '../packem_shared/admin-url-4UzT-CI4.mjs';
5
6
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
6
7
  import { a as resolveProductionWorkerUrl } from '../packem_shared/resolve-target-qbsJ_5sF.mjs';
7
- import { runExportCommand, runImportCommand } from '../packem_shared/DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs';
8
+ import { runExportCommand, runImportCommand } from '../packem_shared/DEFAULT_IMPORT_BATCH_SIZE-CRQmmBZM.mjs';
8
9
 
9
10
  const DEFAULT_BACKUP_DIR = ".lunora-backups";
10
11
  const MANIFEST_FILE = "manifest.json";
@@ -22,7 +23,9 @@ const readManifest = async (directory) => {
22
23
  parsed = JSON.parse(await readFile(path, "utf8"));
23
24
  } catch (error) {
24
25
  const message = error instanceof Error ? error.message : String(error);
25
- throw new Error(`backup: ${path} exists but is not valid JSON (${message}) — refusing to overwrite it; fix or remove it manually`, { cause: error });
26
+ throw new LunoraError("INTERNAL", `backup: ${path} exists but is not valid JSON (${message}) — refusing to overwrite it; fix or remove it manually`, {
27
+ cause: error
28
+ });
26
29
  }
27
30
  if (!Array.isArray(parsed)) {
28
31
  throw new TypeError(`backup: ${path} exists but is not a JSON array — refusing to overwrite it; fix or remove it manually`);
@@ -1,4 +1,4 @@
1
- import { p as parseApiSpec } from '../packem_shared/api-spec-CtA6ilu4.mjs';
1
+ import { p as parseApiSpec } from '../packem_shared/api-spec-Bx0iKbxA.mjs';
2
2
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
3
3
  import { runDeployCommand } from './runDeployCommand.mjs';
4
4
 
@@ -1,5 +1,5 @@
1
1
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
2
- import { o as openUrl } from '../packem_shared/open-url-Dfq6fAyT.mjs';
2
+ import { o as openUrl } from '../packem_shared/open-url-4PBLY9X0.mjs';
3
3
 
4
4
  const DEFAULT_DOCS_URL = "https://lunora.anolilab.dev/docs";
5
5
  const trimSlashes = (value) => {
@@ -1,6 +1,6 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import { detectAgentRules, resolveRemoteEnabled, readProjectRemotePreference, detectFramework, inferLunoraBindings, packageNamesFromBindings, ensureDevVarsExample, ensureDevVariables, isInteractive, DEV_VARS_FILE, DEV_VARS_EXAMPLE_FILE, fillDevSecrets, discoverContainerInfo, streamContainerLogs, claimAgentRulesHint, AGENT_RULES_HINT, materializeRemoteWranglerConfig, formatLunoraEvent } from '@lunora/config';
3
- import { p as parseApiSpec } from '../packem_shared/api-spec-CtA6ilu4.mjs';
3
+ import { p as parseApiSpec } from '../packem_shared/api-spec-Bx0iKbxA.mjs';
4
4
  import { existsSync, watch } from 'node:fs';
5
5
  import { join } from 'node:path';
6
6
  import { runCodegen } from '@lunora/codegen';
@@ -1,5 +1,5 @@
1
1
  import { runCodegen } from '@lunora/codegen';
2
- import { p as parseApiSpec } from '../packem_shared/api-spec-CtA6ilu4.mjs';
2
+ import { p as parseApiSpec } from '../packem_shared/api-spec-Bx0iKbxA.mjs';
3
3
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
4
4
  import { v as validateOutputFormat, p as printJson, l as loggerForFormat, i as isJsonFormat } from '../packem_shared/output-format-wUvAN6AL.mjs';
5
5
 
@@ -4,7 +4,7 @@ import { readLinkedProject, writeLinkedProject, validateWranglerProject, inferLu
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
9
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
10
10
  import { e as execArgsFor, d as detectPackageManager } from '../packem_shared/detect-package-manager-Cxo6Tpyx.mjs';
@@ -11,11 +11,11 @@ import { d as detectPackageManager, a as detectInstalledManagers, i as installAr
11
11
  import MagicString from 'magic-string';
12
12
  import { Project, SyntaxKind } from 'ts-morph';
13
13
  import { P as PromptCancelledError } from '../packem_shared/prompt-cancelled-APzX1Im-.mjs';
14
- import { c as resolveTagVersions, d as resolveSourceRef, e as resolvePinnedSourceRef, f as resolveDistTag, r as runAddCommand } from '../packem_shared/commands-BK6Pt3Ni.mjs';
14
+ import { c as resolveTagVersions, d as resolveSourceRef, e as resolvePinnedSourceRef, f as resolveDistTag, r as runAddCommand } from '../packem_shared/commands-vnRRkhNE.mjs';
15
15
  import { defaultSpawner } from '../packem_shared/createRecordingSpawner-DxI3mebw.mjs';
16
16
  import { d as tuiMascot, e as tuiStep, f as tuiMoonrise, t as tuiText, g as tuiHeadline, h as tuiInfo, a as tuiSelect, b as tuiConfirm, w as withTuiSpinner, i as tuiNextSteps, j as tuiTasks, k as tuiMultiSelect, l as withTuiBadgeProgress } from '../packem_shared/tui-prompts-BjEN8XgP.mjs';
17
17
  import { logStep } from '../packem_shared/createLogger-B40gPzQo.mjs';
18
- import { E as EMAIL_ITEM, p as promptBucketName, w as withStorageBucketName, M as MAIL_DESTINATION_PROMPT, r as resolveTypedDestination, f as withMailDestination, e as promptAuthProvider, c as promptDatabaseName, g as withAuthDatabaseName } from '../packem_shared/storage-C8SAm5zu.mjs';
18
+ import { E as EMAIL_ITEM, p as promptBucketName, w as withStorageBucketName, M as MAIL_DESTINATION_PROMPT, r as resolveTypedDestination, f as withMailDestination, e as promptAuthProvider, c as promptDatabaseName, g as withAuthDatabaseName } from '../packem_shared/storage-bGfgwOgF.mjs';
19
19
  import dns from 'node:dns/promises';
20
20
 
21
21
  const GITHUB_CONTENT = `name: Deploy
@@ -1,6 +1,7 @@
1
1
  import { existsSync, mkdirSync, writeFileSync, mkdtempSync, rmSync, readFileSync } from 'node:fs';
2
2
  import { tmpdir } from 'node:os';
3
3
  import { discoverSchema, discoverMigrations } from '@lunora/codegen';
4
+ import { LunoraError } from '@lunora/errors';
4
5
  import { join } from '@visulima/path';
5
6
  import { Project } from 'ts-morph';
6
7
  import { r as resolveAdminBaseUrl } from '../packem_shared/admin-url-4UzT-CI4.mjs';
@@ -8,7 +9,7 @@ import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
8
9
  import { diffSnapshots, renderMigrationFile } from '../packem_shared/diffSnapshots-BeDvvNiF.mjs';
9
10
  import { a as resolveProductionWorkerUrl } from '../packem_shared/resolve-target-qbsJ_5sF.mjs';
10
11
  import schemaIrToSnapshot from '../packem_shared/schemaIrToSnapshot-DdsljJT-.mjs';
11
- import { runExportCommand, runImportCommand } from '../packem_shared/DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs';
12
+ import { runExportCommand, runImportCommand } from '../packem_shared/DEFAULT_IMPORT_BATCH_SIZE-CRQmmBZM.mjs';
12
13
 
13
14
  const SNAPSHOT_FILENAME = ".snapshot.json";
14
15
  const NON_ALPHANUMERIC = /[^\da-z]+/gu;
@@ -41,12 +42,12 @@ const loadSnapshot = (path) => {
41
42
  const raw = readFileSync(path, "utf8");
42
43
  const parsed = JSON.parse(raw);
43
44
  if (parsed.version !== 1) {
44
- throw new Error(`unsupported snapshot version: ${parsed.version}`);
45
+ throw new LunoraError("INTERNAL", `unsupported snapshot version: ${parsed.version}`);
45
46
  }
46
47
  return parsed;
47
48
  } catch (error) {
48
49
  const message = error instanceof Error ? error.message : String(error);
49
- throw new Error(`failed to read ${path}: ${message}`, { cause: error });
50
+ throw new LunoraError("INTERNAL", `failed to read ${path}: ${message}`, { cause: error });
50
51
  }
51
52
  };
52
53
  const runMigrateGenerateCommand = (options) => {
@@ -1,3 +1,4 @@
1
+ import { LunoraError } from '@lunora/errors';
1
2
  import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
2
3
  import { r as resolveWorkerUrl } from '../packem_shared/resolve-target-qbsJ_5sF.mjs';
3
4
 
@@ -9,7 +10,7 @@ const parseArgsJson = (raw) => {
9
10
  return JSON.parse(raw);
10
11
  } catch (error) {
11
12
  const message = error instanceof Error ? error.message : String(error);
12
- throw new Error(`failed to parse --args as JSON: ${message}`, { cause: error });
13
+ throw new LunoraError("INTERNAL", `failed to parse --args as JSON: ${message}`, { cause: error });
13
14
  }
14
15
  };
15
16
  const TRAILING_SLASH = /\/$/u;
@@ -1,9 +1,11 @@
1
1
  import { readFileSync, writeFileSync } from 'node:fs';
2
+ import { resolveHint, isLunoraError, flattenHint, findSolutionByMessage } from '@lunora/errors';
2
3
  import { createCerebro } from '@visulima/cerebro';
3
4
  import completionCommand from '@visulima/cerebro/command/completion';
4
5
  import versionCommand from '@visulima/cerebro/command/version';
5
- import { A as API_SPEC_HELP } from './api-spec-CtA6ilu4.mjs';
6
+ import { A as API_SPEC_HELP } from './api-spec-Bx0iKbxA.mjs';
6
7
  import { createLogger } from './createLogger-B40gPzQo.mjs';
8
+ import { VisulimaError, renderError } from '@visulima/error';
7
9
  import { tmpdir } from 'node:os';
8
10
  import { join } from 'node:path';
9
11
 
@@ -711,6 +713,21 @@ const viewCommand = {
711
713
  options: [{ description: "Open the deployed worker URL instead of localhost", name: "remote", type: Boolean }]
712
714
  };
713
715
 
716
+ const NO_STACK = { filterStacktrace: () => false, hideErrorCodeView: true };
717
+ const renderLunoraError = (error, options = {}) => {
718
+ const message = error instanceof Error ? error.message : String(error);
719
+ const hint = resolveHint(isLunoraError(error) ? { code: error.code, hint: error.hint, message } : message);
720
+ const rendered = new VisulimaError({
721
+ // `renderError` iterates `hint` as lines; the shared flattener returns one
722
+ // string, so split it back to lines for the terminal renderer.
723
+ hint: hint === void 0 ? void 0 : flattenHint(hint).split("\n"),
724
+ message: options.reason === void 0 ? message : `${options.reason}: ${message}`,
725
+ name: error instanceof Error && error.name.length > 0 ? error.name : "Error"
726
+ });
727
+ rendered.stack = "";
728
+ return renderError(rendered, NO_STACK);
729
+ };
730
+
714
731
  const editDistance = (a, b) => {
715
732
  const distances = Array.from({ length: b.length + 1 }, (_, index) => index);
716
733
  for (let row = 1; row <= a.length; row += 1) {
@@ -925,7 +942,11 @@ const reportRunError = (error) => {
925
942
  const message = error instanceof Error ? error.message : String(error);
926
943
  const unknown = UNKNOWN_COMMAND.exec(message);
927
944
  if (!unknown?.groups) {
928
- logger.error(message);
945
+ if (isLunoraError(error) || findSolutionByMessage(message) !== void 0) {
946
+ logger.error(renderLunoraError(error));
947
+ } else {
948
+ logger.error(message);
949
+ }
929
950
  return;
930
951
  }
931
952
  const name = unknown.groups.name ?? "";
@@ -1,5 +1,6 @@
1
1
  import { createWriteStream, createReadStream } from 'node:fs';
2
2
  import { unlink, stat } from 'node:fs/promises';
3
+ import { LunoraError } from '@lunora/errors';
3
4
  import { r as resolveAdminBaseUrl } from './admin-url-4UzT-CI4.mjs';
4
5
 
5
6
  const EXPORT_ENDPOINT_PATH = "/_lunora/admin/export";
@@ -183,7 +184,7 @@ const runImportCommand = async (options) => {
183
184
  });
184
185
  if (!response.ok) {
185
186
  const text = await response.text().catch(() => "<no body>");
186
- throw new Error(`import batch failed (HTTP ${String(response.status)}): ${text}`);
187
+ throw new LunoraError("INTERNAL", `import batch failed (HTTP ${String(response.status)}): ${text}`);
187
188
  }
188
189
  const json = await response.json();
189
190
  if (json.inserted) {
@@ -213,7 +214,7 @@ const runImportCommand = async (options) => {
213
214
  parsedDocument = JSON.parse(trimmed);
214
215
  } catch (error) {
215
216
  const message = error instanceof Error ? error.message : String(error);
216
- throw new Error(`invalid JSON on line ${String(lineNumber)}: ${message}`, { cause: error });
217
+ throw new LunoraError("INTERNAL", `invalid JSON on line ${String(lineNumber)}: ${message}`, { cause: error });
217
218
  }
218
219
  batch.push(JSON.stringify({ doc: parsedDocument, table: options.table }));
219
220
  };
@@ -1,3 +1,5 @@
1
+ import { LunoraError } from '@lunora/errors';
2
+
1
3
  const API_SPEC_VALUES = ["both", "none", "openapi", "openrpc"];
2
4
  const API_SPEC_HELP = API_SPEC_VALUES.join(" | ");
3
5
  const parseApiSpec = (value) => {
@@ -7,7 +9,7 @@ const parseApiSpec = (value) => {
7
9
  if (API_SPEC_VALUES.includes(value)) {
8
10
  return value;
9
11
  }
10
- throw new Error(`invalid --api-spec "${value}" — expected one of: ${API_SPEC_HELP}`);
12
+ throw new LunoraError("INTERNAL", `invalid --api-spec "${value}" — expected one of: ${API_SPEC_HELP}`);
11
13
  };
12
14
 
13
15
  export { API_SPEC_HELP as A, parseApiSpec as p };
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
2
2
  import { join } from '@visulima/path';
3
- import parseManifest from './parseManifest--vZf2FY1.mjs';
3
+ import parseManifest from './parseManifest-BBrXCg9V.mjs';
4
4
 
5
5
  const CONTROL_CHARS = /[\u0000-\u001F\u007F-\u009F]/gu;
6
6
  const stripControlChars = (value) => value === void 0 ? void 0 : value.replaceAll(CONTROL_CHARS, "");
@@ -3,13 +3,14 @@ import { dirname, join } from '@visulima/path';
3
3
  import { DEV_VARS_FILE, parseDevVariableEntries } from '@lunora/config';
4
4
  import { modify, applyEdits, parse } from 'jsonc-parser';
5
5
  import { fileURLToPath } from 'node:url';
6
+ import { LunoraError } from '@lunora/errors';
6
7
  import { b as tuiConfirm } from './tui-prompts-BjEN8XgP.mjs';
7
- import { collectCatalog, buildRegistryIndex } from './buildRegistryIndex-BcYe607_.mjs';
8
+ import { collectCatalog, buildRegistryIndex } from './buildRegistryIndex-CqM5FwGI.mjs';
8
9
  import { insertSchemaExtension } from './insertSchemaExtension-DAqbfr9Z.mjs';
9
10
  import { createHash } from 'node:crypto';
10
11
  import { tmpdir } from 'node:os';
11
12
  import { downloadTemplate } from 'giget';
12
- import parseManifest from './parseManifest--vZf2FY1.mjs';
13
+ import parseManifest from './parseManifest-BBrXCg9V.mjs';
13
14
 
14
15
  const DEFAULT_SOURCE_REF_FALLBACK = "alpha";
15
16
  const STABLE_BRANCH = "main";
@@ -54,7 +55,7 @@ const resolveVersionRef = (version) => {
54
55
  const resolveSourceRef = (ref) => {
55
56
  if (ref !== void 0 && ref.length > 0) {
56
57
  if (!isSafeRef(ref)) {
57
- throw new Error(`invalid --ref "${ref}" — a ref may contain letters, digits, ".", "_", "-", "/", "@" and must not contain "..".`);
58
+ throw new LunoraError("INTERNAL", `invalid --ref "${ref}" — a ref may contain letters, digits, ".", "_", "-", "/", "@" and must not contain "..".`);
58
59
  }
59
60
  return ref;
60
61
  }
@@ -457,11 +458,12 @@ export const schema = defineSchema({});
457
458
  return { kind: "skipped", path: schemaPath };
458
459
  }
459
460
  if (result.reason === "invalid-identifier") {
460
- throw new Error(
461
+ throw new LunoraError(
462
+ "INTERNAL",
461
463
  `schema-extension item "${itemKey}" is not a valid JS identifier — it is spliced into lunora/schema.ts as \`import { ${itemKey} }\` / \`.extend(${itemKey}.extension)\`. Rename the item to a valid identifier (no leading digit, no "-").`
462
464
  );
463
465
  }
464
- throw new Error(`schema-extension merge failed for "${itemKey}": ${result.reason}`);
466
+ throw new LunoraError("INTERNAL", `schema-extension merge failed for "${itemKey}": ${result.reason}`);
465
467
  };
466
468
  const previewWholeFile = (file, current, incoming, exists, logger) => {
467
469
  const lines = renderDiff(current, incoming);
@@ -549,7 +551,8 @@ const DEFAULT_SOURCE_BASE = "gh:anolilab/lunora/registry";
549
551
  const VALID_ITEM_NAME = /^[A-Za-z0-9][\w-]*$/u;
550
552
  const assertSafeItemName = (name) => {
551
553
  if (!VALID_ITEM_NAME.test(name)) {
552
- throw new Error(
554
+ throw new LunoraError(
555
+ "INTERNAL",
553
556
  `invalid registry item name "${name}" — names must match ${VALID_ITEM_NAME.source} (letters, digits, "-", "_"; no path separators or "..")`
554
557
  );
555
558
  }
@@ -601,7 +604,7 @@ const resolveItemDirectory = async (name, options) => {
601
604
  if (options.from !== void 0) {
602
605
  const directory = join(options.from, name);
603
606
  if (!existsSync(directory)) {
604
- throw new Error(`registry item not found in local source: ${directory}`);
607
+ throw new LunoraError("INTERNAL", `registry item not found in local source: ${directory}`);
605
608
  }
606
609
  return { cleanup: () => {
607
610
  }, directory };
@@ -612,7 +615,7 @@ const resolveItemDirectory = async (name, options) => {
612
615
  const resolveRegistryRoot = async (options) => {
613
616
  if (options.from !== void 0) {
614
617
  if (!existsSync(options.from)) {
615
- throw new Error(`registry root not found: ${options.from}`);
618
+ throw new LunoraError("INTERNAL", `registry root not found: ${options.from}`);
616
619
  }
617
620
  return { cleanup: () => {
618
621
  }, root: options.from };
@@ -635,7 +638,7 @@ const resolvePlan = async (names, options) => {
635
638
  return;
636
639
  }
637
640
  if (inProgress.has(name)) {
638
- throw new Error(`cyclic registry dependency detected at "${name}"`);
641
+ throw new LunoraError("INTERNAL", `cyclic registry dependency detected at "${name}"`);
639
642
  }
640
643
  inProgress.add(name);
641
644
  const { cleanup, directory } = await resolveItemDirectory(name, options);
@@ -1,5 +1,6 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import { platform } from 'node:os';
3
+ import { LunoraError } from '@lunora/errors';
3
4
 
4
5
  const platformCommand = () => {
5
6
  const os = platform();
@@ -29,10 +30,10 @@ const openUrl = async (url, options = {}) => {
29
30
  try {
30
31
  parsed = new URL(url);
31
32
  } catch {
32
- throw new Error(`Invalid URL: ${url}`);
33
+ throw new LunoraError("INTERNAL", `Invalid URL: ${url}`);
33
34
  }
34
35
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
35
- throw new Error(`Refusing to open non-http(s) URL: ${url}`);
36
+ throw new LunoraError("INTERNAL", `Refusing to open non-http(s) URL: ${url}`);
36
37
  }
37
38
  const opener = options.opener ?? platformOpener;
38
39
  await opener(url);
@@ -1,17 +1,20 @@
1
+ import { LunoraError } from '@lunora/errors';
2
+
1
3
  const NEWLINE_PRESENT = /[\r\n]/u;
2
4
  const VALID_ENV_NAME = /^[A-Za-z_]\w*$/u;
3
5
  const VALID_ITEM_NAME = /^[A-Za-z0-9][\w-]*$/u;
4
6
  const parseManifest = (raw, itemName) => {
5
7
  if (typeof raw !== "object" || raw === null) {
6
- throw new Error(`registry.json for "${itemName}" is not an object`);
8
+ throw new LunoraError("INTERNAL", `registry.json for "${itemName}" is not an object`);
7
9
  }
8
10
  const record = raw;
9
11
  const { name } = record;
10
12
  if (typeof name !== "string" || name.length === 0) {
11
- throw new Error(`registry.json for "${itemName}" is missing a string "name"`);
13
+ throw new LunoraError("INTERNAL", `registry.json for "${itemName}" is missing a string "name"`);
12
14
  }
13
15
  if (!VALID_ITEM_NAME.test(name)) {
14
- throw new Error(
16
+ throw new LunoraError(
17
+ "INTERNAL",
15
18
  `registry.json for "${itemName}": name "${name}" must match ${VALID_ITEM_NAME.source} (letters, digits, "-", "_"; no path separators, "..", or code)`
16
19
  );
17
20
  }
@@ -21,7 +24,7 @@ const parseManifest = (raw, itemName) => {
21
24
  }
22
25
  const files = filesRaw.map((entry, index) => {
23
26
  if (typeof entry !== "object" || entry === null) {
24
- throw new Error(`registry.json "${itemName}": files[${String(index)}] is not an object`);
27
+ throw new LunoraError("INTERNAL", `registry.json "${itemName}": files[${String(index)}] is not an object`);
25
28
  }
26
29
  const fileRecord = entry;
27
30
  const { from } = fileRecord;
@@ -31,14 +34,17 @@ const parseManifest = (raw, itemName) => {
31
34
  throw new TypeError(`registry.json "${itemName}": files[${String(index)}] needs string "from" and "to"`);
32
35
  }
33
36
  if (merge !== "create-or-skip" && merge !== "schema-extension") {
34
- throw new Error(`registry.json "${itemName}": files[${String(index)}].merge must be "create-or-skip" or "schema-extension"`);
37
+ throw new LunoraError("INTERNAL", `registry.json "${itemName}": files[${String(index)}].merge must be "create-or-skip" or "schema-extension"`);
35
38
  }
36
39
  for (const [field, value] of [
37
40
  ["from", from],
38
41
  ["to", to]
39
42
  ]) {
40
43
  if (value.includes("..") || value.startsWith("/")) {
41
- throw new Error(`registry.json "${itemName}": files[${String(index)}].${field} "${value}" must be a relative path without ".."`);
44
+ throw new LunoraError(
45
+ "INTERNAL",
46
+ `registry.json "${itemName}": files[${String(index)}].${field} "${value}" must be a relative path without ".."`
47
+ );
42
48
  }
43
49
  }
44
50
  return { from, merge, to };
@@ -59,15 +65,16 @@ const parseManifest = (raw, itemName) => {
59
65
  ).map((entry) => {
60
66
  const hasValue = typeof entry.value === "string";
61
67
  if (!VALID_ENV_NAME.test(entry.name)) {
62
- throw new Error(
68
+ throw new LunoraError(
69
+ "INTERNAL",
63
70
  `registry.json "${itemName}": envVars["${entry.name}"].name must match ${VALID_ENV_NAME.source} (letters, digits, underscore; no "=" or newline)`
64
71
  );
65
72
  }
66
73
  if (hasValue && NEWLINE_PRESENT.test(entry.value)) {
67
- throw new Error(`registry.json "${itemName}": envVars["${entry.name}"].value must not contain a newline`);
74
+ throw new LunoraError("INTERNAL", `registry.json "${itemName}": envVars["${entry.name}"].value must not contain a newline`);
68
75
  }
69
76
  if (typeof entry.description === "string" && NEWLINE_PRESENT.test(entry.description)) {
70
- throw new Error(`registry.json "${itemName}": envVars["${entry.name}"].description must not contain a newline`);
77
+ throw new LunoraError("INTERNAL", `registry.json "${itemName}": envVars["${entry.name}"].description must not contain a newline`);
71
78
  }
72
79
  return {
73
80
  ...typeof entry.description === "string" ? { description: entry.description } : {},
@@ -0,0 +1,4 @@
1
+ import 'node:fs';
2
+ import '@visulima/path';
3
+ export { r as runAddCommand, a as runBuildIndexCommand, g as runListCommand, b as runRegistryViewCommand } from './commands-vnRRkhNE.mjs';
4
+ import './buildRegistryIndex-CqM5FwGI.mjs';
@@ -1,4 +1,4 @@
1
- import { s as setBindingField } from './commands-BK6Pt3Ni.mjs';
1
+ import { s as setBindingField } from './commands-vnRRkhNE.mjs';
2
2
 
3
3
  const INVALID_SLUG_CHARS = /[^a-z0-9]+/u;
4
4
  const toKebabSlug = (input, min, max) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/cli",
3
- "version": "1.0.0-alpha.57",
3
+ "version": "1.0.0-alpha.58",
4
4
  "description": "The Lunora CLI: init, dev, deploy, codegen, run, reset, and migrate commands",
5
5
  "keywords": [
6
6
  "agent-skills",
@@ -52,11 +52,12 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "@bomb.sh/tab": "0.0.17",
55
- "@lunora/codegen": "1.0.0-alpha.28",
56
- "@lunora/config": "1.0.0-alpha.45",
57
- "@lunora/container": "1.0.0-alpha.5",
58
- "@lunora/d1": "1.0.0-alpha.21",
59
- "@lunora/seed": "1.0.0-alpha.13",
55
+ "@lunora/codegen": "1.0.0-alpha.29",
56
+ "@lunora/config": "1.0.0-alpha.46",
57
+ "@lunora/container": "1.0.0-alpha.6",
58
+ "@lunora/d1": "1.0.0-alpha.22",
59
+ "@lunora/errors": "1.0.0-alpha.1",
60
+ "@lunora/seed": "1.0.0-alpha.14",
60
61
  "@visulima/cerebro": "3.0.0-alpha.32",
61
62
  "@visulima/error": "6.0.0-alpha.34",
62
63
  "@visulima/fs": "5.0.0-alpha.32",
@@ -1,4 +0,0 @@
1
- import 'node:fs';
2
- import '@visulima/path';
3
- export { r as runAddCommand, a as runBuildIndexCommand, g as runListCommand, b as runRegistryViewCommand } from './commands-BK6Pt3Ni.mjs';
4
- import './buildRegistryIndex-BcYe607_.mjs';