@lunora/cli 1.0.0-alpha.201 → 1.0.0-alpha.203
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.
- package/dist/bin.mjs +1 -1
- package/dist/index.d.mts +36 -6
- package/dist/index.d.ts +36 -6
- package/dist/index.mjs +1 -1
- package/dist/packem_chunks/handler.mjs +1 -1
- package/dist/packem_chunks/handler13.mjs +1 -1
- package/dist/packem_chunks/handler14.mjs +1 -1
- package/dist/packem_chunks/handler17.mjs +1 -1
- package/dist/packem_chunks/handler19.mjs +1 -1
- package/dist/packem_chunks/handler2.mjs +2 -2
- package/dist/packem_chunks/handler21.mjs +2 -2
- package/dist/packem_chunks/handler25.mjs +2 -2
- package/dist/packem_chunks/handler26.mjs +4 -4
- package/dist/packem_chunks/handler3.mjs +1 -1
- package/dist/packem_chunks/handler4.mjs +1 -1
- package/dist/packem_chunks/handler7.mjs +3 -3
- package/dist/packem_chunks/planDevCommand.mjs +6 -6
- package/dist/packem_chunks/runCodegenCommand.mjs +3 -3
- package/dist/packem_chunks/runDeployCommand.mjs +1 -1
- package/dist/packem_chunks/runInitCommand.mjs +11 -11
- package/dist/packem_shared/COMMANDS-D-2fKisr.mjs +1 -0
- package/dist/packem_shared/cli-HouJioGN.mjs +3 -0
- package/dist/packem_shared/{commands-BOgN2nF7.mjs → commands-BNKj7r1R.mjs} +7 -7
- package/dist/packem_shared/{lint-ignore-report-CDbcbtv7.mjs → lint-ignore-report-ajVhvqY-.mjs} +1 -1
- package/dist/packem_shared/runAddCommand-D1Dj8-pK.mjs +1 -0
- package/dist/packem_shared/wrangler-secrets-CCdt0mUl.mjs +1 -0
- package/package.json +7 -8
- package/dist/packem_shared/COMMANDS-su5nmqYP.mjs +0 -1
- package/dist/packem_shared/cli-RB-BoDnW.mjs +0 -3
- package/dist/packem_shared/detect-package-manager-DSaAqRof.mjs +0 -1
- package/dist/packem_shared/post-codegen-hook-DRdEoTsQ.mjs +0 -1
- package/dist/packem_shared/runAddCommand-BXz-PXbb.mjs +0 -1
- package/dist/packem_shared/wrangler-secrets-CE7jcf8E.mjs +0 -1
package/dist/bin.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{r as e}from"./packem_shared/cli-
|
|
2
|
+
import{r as e}from"./packem_shared/cli-HouJioGN.mjs";try{const r=await e();process.exit(r)}catch(r){process.stderr.write(`${r instanceof Error?r.message:String(r)}
|
|
3
3
|
`),process.exit(1)}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CodegenOptions, Finding, SchemaIR } from '@lunora/codegen';
|
|
2
|
-
import { ensureDevVariables, ensureDevVarsExample, fillDevSecrets, LintTool, LintIgnoreOutcome } from '@lunora/config';
|
|
2
|
+
import { ensureDevVariables, ensureDevVarsExample, fillDevSecrets, LintTool, LintIgnoreOutcome, PackageManager, PackageManagerProbe } from '@lunora/config';
|
|
3
3
|
import { materializeRemoteWranglerConfig } from '@lunora/config/cloudflare';
|
|
4
4
|
export { REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, type WranglerProjectValidationOptions as WranglerValidationOptions, type WranglerValidationReport, type WranglerProjectValidationResult as WranglerValidationResult, validateWranglerProject as validateWrangler, validateWranglerConfig } from '@lunora/config/cloudflare';
|
|
5
5
|
/** Every command name the CLI registers (drives the `CommandName` type + tests). */
|
|
@@ -617,17 +617,44 @@ interface CodegenWatcherOptions {
|
|
|
617
617
|
apiSpec?: CodegenOptions["apiSpec"];
|
|
618
618
|
/** Debounce window for coalescing rapid edits. Defaults to 100ms. */
|
|
619
619
|
debounceMs?: number;
|
|
620
|
+
/**
|
|
621
|
+
* The caller's logs are NDJSON on stdout, so the `postcodegen` hook's own
|
|
622
|
+
* stdout must be routed to stderr or it corrupts the stream. `lunora dev`
|
|
623
|
+
* turns this on for `--json` AND for a detected AI agent.
|
|
624
|
+
*/
|
|
625
|
+
jsonLogs?: boolean;
|
|
620
626
|
logger: Logger;
|
|
621
627
|
/** Override the lunora subdirectory name. Defaults to `"lunora"`. */
|
|
622
628
|
lunoraDirectory?: string;
|
|
623
629
|
/** Project root containing the `lunora/` directory. */
|
|
624
630
|
projectRoot: string;
|
|
631
|
+
/** Process spawner for the `postcodegen` hook. Injectable so tests need no real subprocess. */
|
|
632
|
+
spawner?: Spawner;
|
|
625
633
|
/** Deploy target the emitted `ctx.*` surface is tailored to. Resolved by the caller; falls back to `"target"` in `lunora.json`, then `"cloudflare"`. */
|
|
626
634
|
target?: string;
|
|
627
635
|
}
|
|
628
636
|
interface CodegenWatcherHandle {
|
|
629
|
-
/**
|
|
630
|
-
|
|
637
|
+
/**
|
|
638
|
+
* Stop watching, drop any queued regeneration, and resolve once the run
|
|
639
|
+
* already in flight has finished.
|
|
640
|
+
*
|
|
641
|
+
* Awaiting the result is what keeps a `postcodegen` child from being
|
|
642
|
+
* orphaned by the caller's `process.exit`; a caller that only needs the
|
|
643
|
+
* watcher detached can ignore it.
|
|
644
|
+
*/
|
|
645
|
+
close: () => Promise<void>;
|
|
646
|
+
/**
|
|
647
|
+
* Resolves once the startup regeneration — codegen AND the project's
|
|
648
|
+
* `postcodegen` — has finished.
|
|
649
|
+
*
|
|
650
|
+
* Await it before starting anything that reads generated output. `runCodegen`
|
|
651
|
+
* is synchronous and has already run by the time `startCodegenWatch` returns,
|
|
652
|
+
* but the hook is the step that FINISHES that output, so a worker spawned
|
|
653
|
+
* without waiting can bundle the unfinished copy. Resolves (never rejects)
|
|
654
|
+
* even when codegen or the hook failed — both report for themselves, and a
|
|
655
|
+
* dev server still has to come up.
|
|
656
|
+
*/
|
|
657
|
+
ready: Promise<void>;
|
|
631
658
|
/**
|
|
632
659
|
* `true` when the platform supports recursive watch and the loop is active.
|
|
633
660
|
* `false` when `fs.watch({ recursive })` threw — startup-only codegen was run
|
|
@@ -708,6 +735,12 @@ interface DevCommandOptions {
|
|
|
708
735
|
flavor?: DevFlavor;
|
|
709
736
|
/** Injection seam for tests — defaults to the real IPv6-loopback probe ({@link hasIpv6Loopback}). */
|
|
710
737
|
hasIpv6Loopback?: () => boolean;
|
|
738
|
+
/**
|
|
739
|
+
* Logs are NDJSON on stdout (`--json`, or a detected AI agent). Forwarded to
|
|
740
|
+
* the codegen watcher so a `postcodegen` script's own stdout is routed to
|
|
741
|
+
* stderr instead of corrupting the stream.
|
|
742
|
+
*/
|
|
743
|
+
jsonLogs?: boolean;
|
|
711
744
|
logger: Logger;
|
|
712
745
|
/** Injection seam for tests — defaults to the real remote-config materializer. */
|
|
713
746
|
materializeRemote?: typeof materializeRemoteWranglerConfig;
|
|
@@ -814,9 +847,6 @@ declare const runDevCommand: (options: DevCommandOptions) => Promise<{
|
|
|
814
847
|
code: number;
|
|
815
848
|
plan: DevCommandPlan;
|
|
816
849
|
}>;
|
|
817
|
-
type PackageManager = "pnpm" | "npm" | "yarn" | "bun";
|
|
818
|
-
/** True when `manager` is on PATH — probed by running `<manager> --version`. Injectable for tests. */
|
|
819
|
-
type PackageManagerProbe = (manager: PackageManager) => boolean;
|
|
820
850
|
/** Supported CI providers. */
|
|
821
851
|
type CiProvider = "github" | "gitlab";
|
|
822
852
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CodegenOptions, Finding, SchemaIR } from '@lunora/codegen';
|
|
2
|
-
import { ensureDevVariables, ensureDevVarsExample, fillDevSecrets, LintTool, LintIgnoreOutcome } from '@lunora/config';
|
|
2
|
+
import { ensureDevVariables, ensureDevVarsExample, fillDevSecrets, LintTool, LintIgnoreOutcome, PackageManager, PackageManagerProbe } from '@lunora/config';
|
|
3
3
|
import { materializeRemoteWranglerConfig } from '@lunora/config/cloudflare';
|
|
4
4
|
export { REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, type WranglerProjectValidationOptions as WranglerValidationOptions, type WranglerValidationReport, type WranglerProjectValidationResult as WranglerValidationResult, validateWranglerProject as validateWrangler, validateWranglerConfig } from '@lunora/config/cloudflare';
|
|
5
5
|
/** Every command name the CLI registers (drives the `CommandName` type + tests). */
|
|
@@ -617,17 +617,44 @@ interface CodegenWatcherOptions {
|
|
|
617
617
|
apiSpec?: CodegenOptions["apiSpec"];
|
|
618
618
|
/** Debounce window for coalescing rapid edits. Defaults to 100ms. */
|
|
619
619
|
debounceMs?: number;
|
|
620
|
+
/**
|
|
621
|
+
* The caller's logs are NDJSON on stdout, so the `postcodegen` hook's own
|
|
622
|
+
* stdout must be routed to stderr or it corrupts the stream. `lunora dev`
|
|
623
|
+
* turns this on for `--json` AND for a detected AI agent.
|
|
624
|
+
*/
|
|
625
|
+
jsonLogs?: boolean;
|
|
620
626
|
logger: Logger;
|
|
621
627
|
/** Override the lunora subdirectory name. Defaults to `"lunora"`. */
|
|
622
628
|
lunoraDirectory?: string;
|
|
623
629
|
/** Project root containing the `lunora/` directory. */
|
|
624
630
|
projectRoot: string;
|
|
631
|
+
/** Process spawner for the `postcodegen` hook. Injectable so tests need no real subprocess. */
|
|
632
|
+
spawner?: Spawner;
|
|
625
633
|
/** Deploy target the emitted `ctx.*` surface is tailored to. Resolved by the caller; falls back to `"target"` in `lunora.json`, then `"cloudflare"`. */
|
|
626
634
|
target?: string;
|
|
627
635
|
}
|
|
628
636
|
interface CodegenWatcherHandle {
|
|
629
|
-
/**
|
|
630
|
-
|
|
637
|
+
/**
|
|
638
|
+
* Stop watching, drop any queued regeneration, and resolve once the run
|
|
639
|
+
* already in flight has finished.
|
|
640
|
+
*
|
|
641
|
+
* Awaiting the result is what keeps a `postcodegen` child from being
|
|
642
|
+
* orphaned by the caller's `process.exit`; a caller that only needs the
|
|
643
|
+
* watcher detached can ignore it.
|
|
644
|
+
*/
|
|
645
|
+
close: () => Promise<void>;
|
|
646
|
+
/**
|
|
647
|
+
* Resolves once the startup regeneration — codegen AND the project's
|
|
648
|
+
* `postcodegen` — has finished.
|
|
649
|
+
*
|
|
650
|
+
* Await it before starting anything that reads generated output. `runCodegen`
|
|
651
|
+
* is synchronous and has already run by the time `startCodegenWatch` returns,
|
|
652
|
+
* but the hook is the step that FINISHES that output, so a worker spawned
|
|
653
|
+
* without waiting can bundle the unfinished copy. Resolves (never rejects)
|
|
654
|
+
* even when codegen or the hook failed — both report for themselves, and a
|
|
655
|
+
* dev server still has to come up.
|
|
656
|
+
*/
|
|
657
|
+
ready: Promise<void>;
|
|
631
658
|
/**
|
|
632
659
|
* `true` when the platform supports recursive watch and the loop is active.
|
|
633
660
|
* `false` when `fs.watch({ recursive })` threw — startup-only codegen was run
|
|
@@ -708,6 +735,12 @@ interface DevCommandOptions {
|
|
|
708
735
|
flavor?: DevFlavor;
|
|
709
736
|
/** Injection seam for tests — defaults to the real IPv6-loopback probe ({@link hasIpv6Loopback}). */
|
|
710
737
|
hasIpv6Loopback?: () => boolean;
|
|
738
|
+
/**
|
|
739
|
+
* Logs are NDJSON on stdout (`--json`, or a detected AI agent). Forwarded to
|
|
740
|
+
* the codegen watcher so a `postcodegen` script's own stdout is routed to
|
|
741
|
+
* stderr instead of corrupting the stream.
|
|
742
|
+
*/
|
|
743
|
+
jsonLogs?: boolean;
|
|
711
744
|
logger: Logger;
|
|
712
745
|
/** Injection seam for tests — defaults to the real remote-config materializer. */
|
|
713
746
|
materializeRemote?: typeof materializeRemoteWranglerConfig;
|
|
@@ -814,9 +847,6 @@ declare const runDevCommand: (options: DevCommandOptions) => Promise<{
|
|
|
814
847
|
code: number;
|
|
815
848
|
plan: DevCommandPlan;
|
|
816
849
|
}>;
|
|
817
|
-
type PackageManager = "pnpm" | "npm" | "yarn" | "bun";
|
|
818
|
-
/** True when `manager` is on PATH — probed by running `<manager> --version`. Injectable for tests. */
|
|
819
|
-
type PackageManagerProbe = (manager: PackageManager) => boolean;
|
|
820
850
|
/** Supported CI providers. */
|
|
821
851
|
type CiProvider = "github" | "gitlab";
|
|
822
852
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as o,V as a,r as n}from"./packem_shared/cli-
|
|
1
|
+
import{C as o,V as a,r as n}from"./packem_shared/cli-HouJioGN.mjs";import{runCodegenCommand as t}from"./packem_chunks/runCodegenCommand.mjs";import{runDeployCommand as p}from"./packem_chunks/runDeployCommand.mjs";import{planDevCommand as x,runDevCommand as i}from"./packem_chunks/planDevCommand.mjs";import{runInitCommand as s}from"./packem_chunks/runInitCommand.mjs";import{runMigrateGenerateCommand as u}from"./packem_chunks/runMigrateGenerateCommand.mjs";import{runResetCommand as g}from"./packem_chunks/runResetCommand.mjs";import{runRpcCommand as R}from"./packem_chunks/runRpcCommand.mjs";import{insertSchemaExtension as E}from"./packem_shared/insertSchemaExtension-DY4pA8wE.mjs";import{createLogger as A,pail as c}from"./packem_shared/createLogger-hGafwf-3.mjs";import{diffSnapshots as v,renderAddColumn as _,renderCreateIndex as b,renderCreateTable as h,renderDropIndex as y,renderDropTable as L,renderMigrationFile as O,validatorKindToSqlType as w}from"./packem_shared/diffSnapshots-CIOFQN_a.mjs";import{default as F}from"./packem_shared/schemaIrToSnapshot-qpRoV7HY.mjs";import{createRecordingSpawner as U,defaultSpawner as V}from"./packem_shared/createRecordingSpawner-DJlNacZ6.mjs";import{default as G}from"./packem_shared/parseManifest-CwPTKdtS.mjs";import{D as Q,r as j}from"./packem_shared/import-CrVGrOt3.mjs";import{REQUIRED_COMPATIBILITY_DATE as H,REQUIRED_FLAG as K,validateWranglerProject as Y,validateWranglerConfig as Z}from"@lunora/config/cloudflare";import{buildRegistryIndex as z}from"./packem_shared/buildRegistryIndex-Zi3bBqpc.mjs";import{r as X,a as $,b as rr}from"./packem_shared/commands-BNKj7r1R.mjs";import{runExportCommand as or}from"./packem_shared/runExportCommand-DmXKEWSq.mjs";export{o as COMMANDS,Q as DEFAULT_IMPORT_BATCH_SIZE,H as REQUIRED_COMPATIBILITY_DATE,K as REQUIRED_FLAG,a as VERSION,z as buildRegistryIndex,A as createLogger,U as createRecordingSpawner,V as defaultSpawner,v as diffSnapshots,E as insertSchemaExtension,c as pail,G as parseManifest,x as planDevCommand,_ as renderAddColumn,b as renderCreateIndex,h as renderCreateTable,y as renderDropIndex,L as renderDropTable,O as renderMigrationFile,X as runAddCommand,$ as runBuildIndexCommand,n as runCli,t as runCodegenCommand,p as runDeployCommand,i as runDevCommand,or as runExportCommand,j as runImportCommand,s as runInitCommand,u as runMigrateGenerateCommand,rr as runRegistryViewCommand,g as runResetCommand,R as runRpcCommand,F as schemaIrToSnapshot,Y as validateWrangler,Z as validateWranglerConfig,w as validatorKindToSqlType};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as k,readFileSync as T}from"node:fs";import{applyLintIgnores as N,detectLintTools as I}from"@lunora/config";import{findWranglerFile as A}from"@lunora/config/cloudflare";import{join as v,basename as g}from"@visulima/path";import{d as D}from"../packem_shared/command-DwC11Cwe.mjs";import{n as S,i as U,E as L,s as M,d as m,p as _,r as f,M as F,a as O,b as h,c as E,e as P,D as o,f as j,g as R,h as d,A as $,j as p,w as x,k as B,l as z}from"../packem_shared/lint-ignore-report-
|
|
1
|
+
import{existsSync as k,readFileSync as T}from"node:fs";import{applyLintIgnores as N,detectLintTools as I}from"@lunora/config";import{findWranglerFile as A}from"@lunora/config/cloudflare";import{join as v,basename as g}from"@visulima/path";import{d as D}from"../packem_shared/command-DwC11Cwe.mjs";import{n as S,i as U,E as L,s as M,d as m,p as _,r as f,M as F,a as O,b as h,c as E,e as P,D as o,f as j,g as R,h as d,A as $,j as p,w as x,k as B,l as z}from"../packem_shared/lint-ignore-report-ajVhvqY-.mjs";import{v as H,l as C,i as J,p as W}from"../packem_shared/output-format-DfogXx0p.mjs";import{t as w,a as q}from"../packem_shared/tui-prompts-Dd0pDuNr.mjs";import{r as V}from"../packem_shared/commands-BNKj7r1R.mjs";const G=e=>{const r=e.trim().toLowerCase();return p.find(a=>a.value===r||a.label.toLowerCase()===r||r==="auth0"&&a.value==="auth-auth0"||r==="clerk"&&a.value==="auth-clerk")?.value},y=e=>{try{const r=JSON.parse(T(v(e,"package.json"),"utf8"));return{...r.dependencies,...r.devDependencies}}catch{return{}}},K=async e=>{const r=e.cwd??process.cwd(),t=R(y(r));return t!==void 0?t:e.yes===!0?(e.logger.warn(`add: couldn't detect your framework — using "${d}". Pass a specific item (e.g. \`lunora add auth-ui-vue\`) to override.`),d):await(e.promptSelect??((s,i,n)=>w(s,i,n)))("Which framework is your app?",$,{default:d})??d},Q=async e=>{if(e.provider!==void 0&&e.provider!==""){const t=G(e.provider);return t===void 0?(e.logger.warn(`add: unknown --provider "${e.provider}" — using "${o}" (email & password).`),o):t}if(e.yes===!0)return o;const r=e.promptSelect??((t,a,s)=>w(t,a,s));return j(r)},l=e=>e.promptText??((r,t)=>q(r,t)),X=async e=>{const r=g(e.cwd??process.cwd());if(e.bucket!==void 0&&e.bucket!==""){const t=M(e.bucket);if(t!==void 0)return t;const a=m(r);return e.logger.warn(`add: "${e.bucket}" isn't a valid R2 bucket name (lowercase alphanumeric + hyphens, 3–63 chars) — using "${a}".`),a}return e.yes===!0?m(r):_(l(e),r)},Y=async e=>{const r=t=>{e.logger.warn(`add: ${t}`)};if(e.mailTo!==void 0&&e.mailTo!=="")return f(e.mailTo,r);if(e.yes!==!0)return f(await l(e)(F,{placeholder:"you@yourdomain.com"}),r)},Z=async e=>{const r=g(e.cwd??process.cwd());if(e.db!==void 0&&e.db!==""){const t=O(e.db);if(t!==void 0)return t;const a=h(r);return e.logger.warn(`add: "${e.db}" isn't a usable D1 database name — using "${a}".`),a}return e.yes===!0?h(r):E(l(e),r)},ee=async(e,r)=>e.kind==="auth"?[await Q(r)]:e.kind==="auth-ui"?[await K(r)]:e.kind==="email"?[L]:[e.item],re=(e,r)=>{P(N(e,I(e)),r)},ae=async e=>{const r=e.cwd??process.cwd(),t=e.feature===void 0?void 0:S(e.feature);if(t===void 0)return e.logger.error("add requires a feature or registry item. Usage: lunora add <auth|email|storage|crons|presence|…>"),{code:1,items:[]};if(!k(v(r,"lunora"))||A(r)===void 0)return e.logger.error("add: not a Lunora project here (need a lunora/ directory and a wrangler.jsonc). Run `lunora init` first."),{code:1,items:[]};if(t.kind==="auth-ui"&&U(y(r)))return e.logger.error("add: auth-ui has no React Native port — the screens render DOM elements and a stylesheet, which Metro has nothing to mount. Build the screens with React Native primitives against the same better-auth client (`@lunora/react-native/auth`); `lunora add auth` still installs the server half."),{code:1,items:[]};const a=await ee(t,e),s=[];if(a.includes("storage")){const c=await X(e);s.push(u=>x(u,c))}if(a.includes("mail")){const c=await Y(e);c!==void 0&&s.push(u=>B(u,c))}if(a.some(c=>c==="auth"||c.startsWith("auth-"))){const c=await Z(e);s.push(u=>z(u,c))}const i=s.length>0?c=>{let u=c;for(const b of s)u=b(u);return u}:void 0,n=await V({allowUnsafeSource:e.allowUnsafeSource,cwd:r,from:e.from,logger:e.logger,names:[...a],ref:e.ref,source:e.source,transformManifest:i,yes:!0});return n.code===0&&re(r,e.logger),{code:n.code,items:a}},me=D(async({argument:e,cwd:r,logger:t,options:a})=>{const s=H("add",a.format);if(s!==void 0)return t.error(s),{code:1};const i=C(a.format,t),n=await ae({allowUnsafeSource:a.allowUnsafeSource===!0,bucket:a.bucket,cwd:r,db:a.db,feature:e[0],from:a.from,logger:i,mailTo:a.mailTo,provider:a.provider,ref:a.ref,source:a.source,yes:a.yes===!0});return J(a.format)&&W({code:n.code,items:n.items}),{code:n.code}});export{me as execute,ae as runAddFeature};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{runCodegen as g}from"@lunora/codegen";import{resolveTargetOrThrow as d,resolveDeployDriver as
|
|
1
|
+
import{runCodegen as g}from"@lunora/codegen";import{resolveTargetOrThrow as d,runPostCodegenHook as m,resolveDeployDriver as f}from"@lunora/config";import{p}from"../packem_shared/api-spec-lYyq4vL6.mjs";import{r as u}from"../packem_shared/codegen-error-C04fGQjf.mjs";import{d as h}from"../packem_shared/command-DwC11Cwe.mjs";import{r as w}from"../packem_shared/platform-diagnostics-uOXqysk3.mjs";import{r as v}from"../packem_shared/schema-drift-gate-AscQpYH5.mjs";import{validateWranglerProject as S}from"@lunora/config/cloudflare";const b=async(e,o,a=[],c)=>{const i={crons:a,projectRoot:e},n=f(c);try{const r=await n.infer(i),s=[r.shardNamespaces.length>0?`${String(r.shardNamespaces.length)} shard namespace(s)`:void 0,r.queues.length>0?`${String(r.queues.length)} queue(s)`:void 0,r.workflows.length>0?`${String(r.workflows.length)} workflow(s)`:void 0,r.containers.length>0?`${String(r.containers.length)} container(s)`:void 0,r.globalDatabase?"global database":void 0,r.objectStorage?"object storage":void 0,r.keyValueStore?"key-value store":void 0].filter(l=>l!==void 0);s.length>0&&o.info(`${n.name} target requires: ${s.join(", ")}`)}catch{}const t=await n.provision(i);t.changed&&o.success(`provisioned: ${t.added.join(", ")} → ${t.configPath??"wrangler.jsonc"}`);for(const r of t.warnings)o.warn(r)},j=async e=>{const o=e.cwd??process.cwd(),a=d(o,e.target);e.logger.info("running codegen");let c;try{c=g({apiSpec:e.apiSpec,projectRoot:o,target:a}),e.logger.success("codegen complete"),w(c.platformDiagnostics,e.logger)}catch(r){const s=r instanceof Error?r.message:String(r);return e.logger.error(u(r)),{code:1,error:`codegen failed: ${s}`,validation:{problems:[],wranglerPath:void 0}}}const i=await m({cwd:o,logger:e.logger,spawner:e.spawner});if(i.error!==void 0)return{code:1,error:i.error,validation:{problems:[],wranglerPath:void 0}};const n=v({allowDrift:e.allowSchemaDrift===!0,codegen:c,command:"prepare",logger:e.logger,updateBaseline:e.updateSchemaBaseline===!0});if(n.blocked)return{code:1,error:"schema drift gate blocked prepare",schemaDrift:{blocked:!0,reason:n.reason},validation:{problems:[],wranglerPath:void 0}};await b(o,e.logger,c.cronTriggers,a);const t=S({projectRoot:o});if(t.problems.length>0){e.logger.error("wrangler.jsonc validation failed:");for(const r of t.problems)e.logger.error(` - ${r}`);return{code:1,error:"wrangler validation failed",validation:t}}return n.rebless?.(),e.logger.success("project is ready to deploy"),{code:0,validation:t}},x=h(({cwd:e,logger:o,options:a})=>j({allowSchemaDrift:a.allowSchemaDrift===!0,apiSpec:p(a.apiSpec),cwd:e,logger:o,target:a.target,updateSchemaBaseline:a.updateSchemaBaseline===!0}));export{x as execute,j as runPrepareCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as c}from"../packem_shared/command-DwC11Cwe.mjs";import{r as d,b as s,a as n}from"../packem_shared/commands-
|
|
1
|
+
import{d as c}from"../packem_shared/command-DwC11Cwe.mjs";import{r as d,b as s,a as n}from"../packem_shared/commands-BNKj7r1R.mjs";const w=c(({argument:a,cwd:u,logger:e,options:r})=>{const f=a[0],m=a.slice(1);return f==="add"?d({allowUnsafeSource:r.allowUnsafeSource===!0,cwd:u,diff:r.diff===!0,dryRun:r.dryRun===!0,from:r.from,json:r.json===!0,logger:e,names:m,overwrite:r.overwrite===!0,ref:r.ref,source:r.source,yes:r.yes===!0}):f==="list"?d({cwd:u,from:r.from,json:r.json===!0,list:!0,logger:e,names:[],ref:r.ref,source:r.source}):f==="view"?s({allowUnsafeSource:r.allowUnsafeSource===!0,cwd:u,from:r.from,logger:e,names:m,ref:r.ref,source:r.source}):f==="build"?n({check:r.check===!0,cwd:u,from:r.from,logger:e,names:[],out:r.out}):(e.error("registry: unknown subcommand. Usage: lunora registry <add|list|view|build> [names…]"),{code:1})});export{w as execute};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as p}from"node:fs";import{join as h}from"node:path";import{runCodegen as u}from"@lunora/codegen";import{p as g}from"../packem_shared/api-spec-lYyq4vL6.mjs";import{a as v}from"../packem_shared/codegen-error-C04fGQjf.mjs";import{d as y}from"../packem_shared/command-DwC11Cwe.mjs";import{r as w}from"../packem_shared/deploy-target-D9GPy_tq.mjs";import{
|
|
1
|
+
import{existsSync as p}from"node:fs";import{join as h}from"node:path";import{runCodegen as u}from"@lunora/codegen";import{p as g}from"../packem_shared/api-spec-lYyq4vL6.mjs";import{a as v}from"../packem_shared/codegen-error-C04fGQjf.mjs";import{d as y}from"../packem_shared/command-DwC11Cwe.mjs";import{r as w}from"../packem_shared/deploy-target-D9GPy_tq.mjs";import{p as S}from"../packem_shared/health-probe-QEPfFdgJ.mjs";import{v as k,i as j,p as b,l as x}from"../packem_shared/output-format-DfogXx0p.mjs";import{r as E}from"../packem_shared/schema-drift-gate-AscQpYH5.mjs";import{defaultSpawner as F}from"../packem_shared/createRecordingSpawner-DJlNacZ6.mjs";import{validateWranglerProject as U}from"@lunora/config/cloudflare";import{execArgsFor as D,detectPackageManager as R}from"@lunora/config";const $=async(r,t)=>{if(!p(h(r,"tsconfig.json")))return{warning:"no tsconfig.json found — skipping TypeScript type-check"};const e=D(R(r),"tsc",["--noEmit","-p","tsconfig.json"]),a=await t({args:e.args,command:e.command,cwd:r});return a.code===0?{}:{error:`type errors: tsc --noEmit exited ${String(a.code)}`}},H=async(r,t)=>{if(r.healthUrl===void 0||r.healthUrl==="")return;const e=await S({baseUrl:r.healthUrl,fetchImpl:r.healthFetch});if(e.error===void 0){t.success(`verify: health probe ok (${e.url})`);return}return e.error},T=(r,t,e,a)=>{if(t.length===0&&e.length===0)return r.success("verify: project is valid"),{code:0,errors:[],warnings:[],wranglerPath:a};if(e.length>0){r.warn("verify: warnings:");for(const c of e)r.warn(` - ${c}`)}if(t.length>0){r.error("verify: errors:");for(const c of t){r.error(` - ${c}`);const n=v(c);n!==void 0&&r.error(n)}return{code:1,errors:t,warnings:e,wranglerPath:a}}return r.success("verify: project is valid (with warnings)"),{code:0,errors:[],warnings:e,wranglerPath:a}},C=async r=>{const t=r.cwd??process.cwd(),e=x(r.format,r.logger),a=k("verify",r.format);if(a!==void 0)return r.logger.error(a),{code:1,error:a,errors:[],warnings:[],wranglerPath:void 0};const c=U({projectRoot:t}),n=[...c.report.errors],f=[...c.report.warnings];try{const o=w(t,r.target);if(o.target===void 0){const i=o.error??"unknown deploy target";return e.error(i),{code:1,error:i,errors:[i],warnings:[],wranglerPath:void 0}}const s=u({apiSpec:r.apiSpec,dryRun:!0,projectRoot:t,target:o.target}),d=E({allowDrift:r.allowSchemaDrift===!0,codegen:s,command:"verify",logger:e,readOnly:!0});d.blocked&&n.push(d.reason)}catch(o){const s=o instanceof Error?o.message:String(o);n.push(`codegen failed: ${s}`)}if(r.typecheck!==!1){const o=await $(t,r.spawner??F);o.error!==void 0&&n.push(o.error),o.warning!==void 0&&f.push(o.warning)}const m=await H(r,e);m!==void 0&&n.push(m);const l=T(e,n,f,c.wranglerPath);return j(r.format)&&b(l),l},L=y(async({cwd:r,logger:t,options:e})=>({code:(await C({allowSchemaDrift:e.allowSchemaDrift===!0,apiSpec:g(e.apiSpec),cwd:r,format:e.format,healthUrl:e.healthUrl,logger:t,target:e.target,typecheck:e.typecheck===!1?!1:void 0})).code}));export{L as execute,C as runVerifyCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{writeFileSync as h,existsSync as S,readFileSync as b}from"node:fs";import{isAbsolute as w,join as p}from"node:path";import{byCodepoint as y,scoreAdvisor as x,parseAdvisorMap as j,compareToBaseline as A}from"@lunora/advisor";import{runCodegen as F}from"@lunora/codegen";import{d as M}from"../packem_shared/command-DwC11Cwe.mjs";import{v as R,p as D,l as k,i as E}from"../packem_shared/output-format-DfogXx0p.mjs";import{D as f}from"../packem_shared/cli-
|
|
1
|
+
import{writeFileSync as h,existsSync as S,readFileSync as b}from"node:fs";import{isAbsolute as w,join as p}from"node:path";import{byCodepoint as y,scoreAdvisor as x,parseAdvisorMap as j,compareToBaseline as A}from"@lunora/advisor";import{runCodegen as F}from"@lunora/codegen";import{d as M}from"../packem_shared/command-DwC11Cwe.mjs";import{v as R,p as D,l as k,i as E}from"../packem_shared/output-format-DfogXx0p.mjs";import{D as f}from"../packem_shared/cli-HouJioGN.mjs";const l={clean:"·",exempt:"–",failing:"✗",warned:"!"},u=(e,r)=>e.length>=r?e:e+" ".repeat(r-e.length),B=e=>`${e.id} (${e.visibility} ${e.kind})`,g=e=>{let r=0;for(const n of e)r=Math.max(r,n.id.length);return r},m=(e,r)=>` ${u(String(e.score),3)} ${l[e.coverage]} ${u(e.id,r)} ${e.visibility} ${e.kind}`,T=e=>{if(!e.comparable)return[` baseline not comparable (${e.reason}) — regenerate it; this run cannot verify anything`];if(!e.regressed)return[` no regression against baseline (score ${e.scoreDelta>=0?"+":""}${String(e.scoreDelta)})`];const r=[` REGRESSED against baseline (score ${e.scoreDelta>=0?"+":""}${String(e.scoreDelta)})`];for(const n of e.dropped)r.push(` ${n.id}: ${String(n.before)} → ${String(n.after)}`);for(const n of e.newFailing)r.push(` ${n}: now failing`);for(const n of e.worsened)r.push(` ${n}: more findings than the baseline`);return e.projectRegressed&&r.push(" project: new schema/config rules fired"),r},C=(e,r)=>{const n=e.procedures.filter(i=>i.coverage!=="clean"&&i.coverage!=="exempt"),o=g(n),t=[`advisor health ${String(e.score)}/100 — ${e.grade}`,` ${String(e.summary.clean)} clean · ${String(e.summary.warned)} warned · ${String(e.summary.failing)} failing · ${String(e.summary.exempt)} exempt (${String(e.summary.procedures)} procedures, ${String(e.summary.rulesFired)} rules fired)`];return e.project.checks.length>0&&t.push("",` project ${String(e.project.score)}/100 — ${e.project.checks.map(i=>i.name).join(", ")}`),n.length>0&&t.push("",...n.map(i=>m(i,o)),""," run with --all for every procedure, or --entry <file#export> for one"),r!==void 0&&t.push("",...T(r)),t.join(`
|
|
2
2
|
`)},J=e=>e.coverage==="exempt"?[` exempt: ${e.exemptReason===void 0||e.exemptReason===""?"no reason given":e.exemptReason}`]:e.checks.map(r=>{const n=r.occurrences>1?`, ×${String(r.occurrences)}`:"";return` ${r.name} (−${String(r.weight)}${n})`}),L=e=>{const r=new Map;for(const n of e){const o=r.get(n.file);o===void 0?r.set(n.file,[n]):o.push(n)}return[...r].toSorted(([n],[o])=>y(n,o))},N=e=>{const r=g(e.procedures),n=[`advisor health ${String(e.score)}/100 — ${e.grade}`,"",` legend: ${l.clean} clean ${l.warned} warned ${l.failing} failing ${l.exempt} exempt`];for(const[o,t]of L(e.procedures)){n.push("",` ${o}`);for(const i of t)n.push(m(i,r),...J(i))}return n.join(`
|
|
3
3
|
`)},P=(e,r)=>{const n=e.procedures.find(t=>t.id===r);if(n===void 0){const t=e.procedures.slice(0,10).map(i=>` ${i.id}`);return[`no procedure ${r} in the map. Known ids:`,...t,e.procedures.length>10?" …":""].filter(Boolean).join(`
|
|
4
4
|
`)}const o=[`${B(n)} — ${String(n.score)}/100, ${n.coverage}`,` weight in the global mean: ${String(n.weight)}`];if(n.checks.length===0)return o.push(""," no rule fired"),o.join(`
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{mkdtempSync as u,rmSync as d,existsSync as l,readdirSync as y,statSync as m}from"node:fs";import{tmpdir as p}from"node:os";import{join as f,relative as $}from"node:path";import{d as S}from"../packem_shared/command-DwC11Cwe.mjs";import{
|
|
2
|
-
`):h(o,r),{code:0,descriptor:
|
|
1
|
+
import{mkdtempSync as u,rmSync as d,existsSync as l,readdirSync as y,statSync as m}from"node:fs";import{tmpdir as p}from"node:os";import{join as f,relative as $}from"node:path";import{d as S}from"../packem_shared/command-DwC11Cwe.mjs";import{defaultSpawner as g}from"../packem_shared/createRecordingSpawner-DJlNacZ6.mjs";import{execArgsFor as w,detectPackageManager as z}from"@lunora/config";const B=e=>{const t=[],r=n=>{for(const s of y(n)){const i=f(n,s),o=m(i);o.isDirectory()?r(i):o.isFile()&&t.push({path:$(e,i),sizeBytes:o.size})}};return r(e),t},c=e=>e<1024?`${String(e)} B`:e<1024*1024?`${(e/1024).toFixed(1)} KiB`:`${(e/(1024*1024)).toFixed(2)} MiB`,F=e=>{const t=B(e),r=t.toSorted((i,o)=>o.sizeBytes-i.sizeBytes),n=t.reduce((i,o)=>i+o.sizeBytes,0);return{generatedFiles:t.filter(i=>i.path.includes("_generated")),outdir:e,topModules:r.slice(0,10),totalBytes:n,totalFiles:t.length}},h=(e,t)=>{if(t.info(`outdir: ${e.outdir}`),t.info(`total: ${String(e.totalFiles)} files, ${c(e.totalBytes)}`),e.topModules.length>0){t.info(""),t.info("top modules by size:");for(const r of e.topModules)t.info(` ${c(r.sizeBytes).padStart(10," ")} ${r.path}`)}if(e.generatedFiles.length>0){t.info(""),t.info(`_generated/ files: ${String(e.generatedFiles.length)}`);for(const r of e.generatedFiles)t.info(` ${c(r.sizeBytes).padStart(10," ")} ${r.path}`)}},x=async e=>{const t=e.cwd??process.cwd(),{logger:r}=e;let n,s,i=!1;if(e.inspectOnly)n=e.inspectOnly;else{n=u(f(p(),"lunora-analyze-")),i=!0;const o=w(z(t),"wrangler",["deploy","--dry-run","--outdir",n]);s={args:o.args,command:o.command,cwd:t},r.info(`analyze: building via ${s.command} ${s.args.join(" ")}`);const a=await(e.spawner??g)(s);if(a.code!==0)return r.error(`analyze: wrangler dry-run failed (exit ${String(a.code)})`),d(n,{force:!0,recursive:!0}),{code:a.code,descriptor:s,report:void 0}}try{if(!l(n))return r.error(`analyze: outdir not found at ${n}`),{code:1,descriptor:s,report:void 0};const o=F(n);return e.json?process.stdout.write(`${JSON.stringify(o,void 0,2)}
|
|
2
|
+
`):h(o,r),{code:0,descriptor:s,report:o}}finally{if(i&&l(n))try{d(n,{force:!0,recursive:!0})}catch{}}},C=S(({cwd:e,logger:t,options:r})=>x({cwd:e,json:r.json===!0,logger:t}));export{C as execute,x as runAnalyzeCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readLinkedProject as g,resolveDeployDriver as v}from"@lunora/config";import{d as
|
|
2
|
-
`);return c.rows.length===0?e.logger.info("logs --durable: no matching log records"):c.nextCursor!==void 0&&e.logger.info(`logs --durable: more rows available — pass --cursor ${T(c.nextCursor)} for the next page`),{code:0,rows:c.rows}},
|
|
1
|
+
import{readLinkedProject as g,resolveDeployDriver as v,execArgsFor as h,detectPackageManager as y}from"@lunora/config";import{d as b}from"../packem_shared/command-DwC11Cwe.mjs";import{defaultSpawner as w}from"../packem_shared/createRecordingSpawner-DJlNacZ6.mjs";import{createR2Sql as L}from"@lunora/bindings/r2sql";import{createPipelineLogReader as S}from"@lunora/runtime";const _=new Set(["debug","error","fatal","info","log","trace","warn"]),m=/^\d+$/,d=(e,t)=>{if(e===void 0)return;const a=e.trim();if(m.test(a))return Number(a);const r=Date.parse(a);if(Number.isNaN(r))throw new TypeError(`logs: invalid ${t} "${e}" — pass epoch-millis or an ISO 8601 date`);return r},T=e=>Buffer.from(JSON.stringify(e),"utf8").toString("base64url"),C=e=>{const t=e.trim();if(m.test(t))return{ts:Number(t)};let a;try{a=JSON.parse(Buffer.from(t,"base64url").toString("utf8"))}catch{throw new TypeError(`logs: invalid --cursor "${e}" — expected the token printed by the previous page (or a bare epoch-millis ts)`)}if(typeof a!="object"||a===null||typeof a.ts!="number"||!Number.isFinite(a.ts))throw new TypeError(`logs: invalid --cursor "${e}" — expected the token printed by the previous page (or a bare epoch-millis ts)`);const{ts:r}=a,i=a.seen,n=Array.isArray(i)?i.filter(s=>typeof s=="string"):void 0;return n!==void 0&&n.length>0?{seen:n,ts:r}:{ts:r}},u=(e,t)=>{if(e!==void 0){if(!_.has(e))throw new TypeError(`logs: invalid ${t} "${e}" — expected one of trace, debug, log, info, warn, error, fatal`);return e}},I=e=>{const t={},a=d(e.since,"--since");a!==void 0&&(t.sinceTs=a);const r=d(e.until,"--until");r!==void 0&&(t.untilTs=r);const i=u(e.level,"--level");i!==void 0&&(t.level=i);const n=u(e.minLevel,"--min-level");if(n!==void 0&&(t.minLevel=n),e.functionPrefix!==void 0&&(t.functionPathPrefix=e.functionPrefix),e.traceId!==void 0&&(t.traceId=e.traceId),e.shardKey!==void 0&&(t.shardKey=e.shardKey),e.userId!==void 0&&(t.userId=e.userId),e.limit!==void 0){const s=Number(e.limit);if(!Number.isFinite(s))throw new TypeError(`logs: invalid --limit "${e.limit}" — expected a number`);t.limit=s}return e.cursor!==void 0&&(t.cursor=C(e.cursor)),t},$=e=>{const t=new Date(e.ts).toISOString(),a=e.level.toUpperCase().padEnd(5);return`${t} ${a} ${e.functionPath} ${e.message}`},x=async e=>{const t=e.environment??process.env,a=t.R2_SQL_ACCOUNT_ID,r=t.R2_SQL_TOKEN,i=t.R2_SQL_BUCKET,n=[];if((a===void 0||a.length===0)&&n.push("R2_SQL_ACCOUNT_ID"),(r===void 0||r.length===0)&&n.push("R2_SQL_TOKEN"),(i===void 0||i.length===0)&&n.push("R2_SQL_BUCKET"),(e.table===void 0||e.table.length===0)&&n.push("--table"),n.length>0)return e.logger.error(`logs --durable: R2 SQL not configured (missing ${n.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.`),{code:1,error:"not configured"};let s;try{s=I(e)}catch(o){return e.logger.error(o instanceof Error?o.message:String(o)),{code:1,error:"invalid option"}}const l=L({accountId:a,apiToken:r,bucket:i,fetch:e.fetch}),c=await S(l,{namespace:e.namespace,table:e.table}).query(s);for(const o of c.rows)process.stdout.write(`${e.ndjson===!0?JSON.stringify(o):$(o)}
|
|
2
|
+
`);return c.rows.length===0?e.logger.info("logs --durable: no matching log records"):c.nextCursor!==void 0&&e.logger.info(`logs --durable: more rows available — pass --cursor ${T(c.nextCursor)} for the next page`),{code:0,rows:c.rows}},E=new Set(["json","pretty"]),N=async e=>{const t=e.cwd??process.cwd();if(e.format!==void 0&&!E.has(e.format))return e.logger.error(`logs: unknown --format "${e.format}" — expected pretty | json`),{code:1,descriptor:void 0,error:"invalid format"};const a=e.env??g(t)?.env,r=v(e.target);if(r.toolchain===void 0)return e.logger.error(`logs: deploy target "${r.id}" has no command-line toolchain`),{code:1,descriptor:void 0,error:"no toolchain"};const i=r.toolchain.tail({environment:a,format:e.format,search:e.search,status:e.status,temporary:e.temporary,worker:e.worker}),n=h(y(t),i.tool,i.args),s={args:n.args,command:n.command,cwd:t};return e.logger.info(`tailing logs via ${s.command} ${s.args.join(" ")}`),{code:(await(e.spawner??w)(s)).code,descriptor:s}},Q=b(({argument:e,cwd:t,logger:a,options:r})=>r.durable===!0?x({cursor:r.cursor,functionPrefix:r.functionPrefix,level:r.level,limit:r.limit,logger:a,minLevel:r.minLevel,namespace:r.namespace,ndjson:r.ndjson===!0,shardKey:r.shardKey,since:r.since,table:r.table,traceId:r.traceId,until:r.until,userId:r.userId}):N({cwd:t,env:r.env,format:r.format,logger:a,search:r.search,status:r.status,target:r.target,temporary:r.temporary===!0,worker:e[0]}));export{Q as execute,N as runLogsCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{existsSync as T,readFileSync as O}from"node:fs";import{writeFile as I,mkdir as k}from"node:fs/promises";import{join as b}from"@visulima/path";import{d as B}from"../packem_shared/command-DwC11Cwe.mjs";import{createRequire as U}from"node:module";import{LunoraError as N}from"@lunora/errors";import{
|
|
1
|
+
import{existsSync as T,readFileSync as O}from"node:fs";import{writeFile as I,mkdir as k}from"node:fs/promises";import{join as b}from"@visulima/path";import{d as B}from"../packem_shared/command-DwC11Cwe.mjs";import{createRequire as U}from"node:module";import{LunoraError as N}from"@lunora/errors";import{addArgsFor as Y,detectPackageManager as q,parseSchema as F,applyAdditiveEdit as P}from"@lunora/config";const H=/^\//,K=(e,t)=>{try{const{args:n,command:r}=Y(q(e),[t],{dev:!0});return`${r} ${n.join(" ")}`}catch{return`<your-package-manager> add -D ${t}`}},L=(e,t,n)=>{const r=U(b(n,"noop.cjs"));try{r.resolve(e)}catch{throw new N("INTERNAL",`\`lunora introspect\` needs the \`${t}\` driver to read this database, and it isn't installed.
|
|
2
2
|
|
|
3
3
|
Install it in your project:
|
|
4
4
|
|
|
@@ -96,4 +96,4 @@ export const get = c.query.input({ id: v.id(${f(e.name)}) }).query(({ args, ctx
|
|
|
96
96
|
FROM information_schema.STATISTICS
|
|
97
97
|
WHERE TABLE_SCHEMA = ? AND INDEX_NAME <> 'PRIMARY'
|
|
98
98
|
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX`,E=e=>{const t=new Map;for(const n of e){const r=g(n,"table_name"),s=t.get(r);s===void 0?t.set(r,[n]):s.push(n)}return t},Ae=(e,t)=>{const n=g(e,"data_type").toLowerCase();if(t!=="postgres")return{arrayDepth:0,dataType:n};const r=g(e,"udt_name").toLowerCase();return n==="array"&&r.startsWith("_")?{arrayDepth:1,dataType:r.slice(1)}:{arrayDepth:0,dataType:r===""?n:r}},Se=(e,t)=>{const n=new Map;for(const r of e){const s=g(r,"index_name"),a=t==="postgres"?g(r,"is_unique")==="true":g(r,"NON_UNIQUE")==="0",o=n.get(s);o===void 0?n.set(s,{columns:[g(r,"column_name")],unique:a}):o.columns.push(g(r,"column_name"))}return[...n.entries()].map(([r,s])=>({columns:s.columns,name:r,unique:s.unique}))},Ne=async(e,t,n)=>{const r=t==="postgres",[s,a,o,i]=await Promise.all([e(r?ge:be,[n]),e(r?fe:Ee,[n]),e(r?ve:_e,[n]),e(r?he:ye,[n])]),c=E(a),m=E(o),u=E(i),l=[];for(const[d,p]of E(s)){const y=new Map((m.get(d)??[]).map(v=>[g(v,"column_name"),{column:g(v,"foreign_column"),table:g(v,"foreign_table")}])),A=p.map(v=>{const R=g(v,"column_name"),$=y.get(R);return{...Ae(v,t),name:R,nullable:g(v,"is_nullable").toUpperCase()==="YES",...$===void 0?{}:{references:$}}});l.push({columns:A,indexes:Se(u.get(d)??[],t),name:d,primaryKey:(c.get(d)??[]).map(v=>g(v,"column_name"))})}return l.sort((d,p)=>d.name.localeCompare(p.name)),{dialect:t,tables:l}},we=e=>{try{const t=JSON.parse(O(b(e,"package.json"),"utf8"));return t.dependencies?.lunorash===void 0&&t.devDependencies?.lunorash===void 0?"@lunora/server":"lunorash/server"}catch{return"@lunora/server"}},Re=async(e,t,n)=>{const r=b(t,e.path);return T(r)&&n.force!==!0?(n.logger.warn(`skipped lunora/${e.path} — it already exists (pass --force to overwrite)`),!1):n.dryRun===!0?(n.logger.info(`would write lunora/${e.path} (${String(e.contents.split(`
|
|
99
|
-
`).length)} lines)`),!1):(await k(t,{recursive:!0}),await I(r,e.contents,"utf8"),n.logger.info(`wrote lunora/${e.path}`),!0)},$e=(e,t)=>{const n=t.tables;if(n===void 0||n.length===0)return e.tables;for(const r of n)e.tables.some(s=>s.name===r)||t.logger.warn(`--tables: no table named "${r}" exists in this schema — skipped.`);return e.tables.filter(r=>n.includes(r.name))},Le=async(e,t,n,r)=>{const s=pe(O(e,"utf8"),t,n);for(const a of s.warnings)r.logger.warn(a);return s.text===void 0?(r.logger.info("lunora/schema.ts is already up to date with the database."),!1):r.dryRun===!0?(r.logger.info(`would merge ${String(s.applied)} addition(s) into lunora/schema.ts`),!1):(await I(e,s.text,"utf8"),r.logger.info(`merged ${String(s.applied)} addition(s) into lunora/schema.ts`),!0)},Te=async e=>{const t=e.cwd??process.cwd();if(e.connection===void 0&&(e.url===void 0||e.url===""))return e.logger.error("`lunora introspect` needs a database URL: pass --url, or set DATABASE_URL."),{code:1,written:[]};const n=e.connection===void 0?j(e.url):e.dialect??"postgres",r=e.connection??await J(e.url,n,e.schema,t);let s;try{s=await Ne(r.execute,n,r.schema)}finally{e.connection===void 0&&await r.close()}const a=$e(s,e);if(a.length===0)return e.logger.error("no tables found to introspect — check --schema and --tables."),{code:1,written:[]};const{files:o,warnings:i}=ce({...s,tables:a},{procedures:e.procedures!==!1,serverImport:we(t)}),c=b(t,"lunora"),m=[],u=b(c,"schema.ts"),l=T(u)&&e.force!==!0,d=l?o.filter(p=>p.path!=="schema.ts"):o;l&&await Le(u,{...s,tables:a},n,e)&&m.push("schema.ts");for(const p of d)await Re(p,c,e)&&m.push(p.path);for(const p of i)e.logger.warn(p);return e.logger.info(`introspected ${String(a.length)} table(s) from ${n}. Review the generated files before running \`lunora dev\`.`),{code:0,written:m}},
|
|
99
|
+
`).length)} lines)`),!1):(await k(t,{recursive:!0}),await I(r,e.contents,"utf8"),n.logger.info(`wrote lunora/${e.path}`),!0)},$e=(e,t)=>{const n=t.tables;if(n===void 0||n.length===0)return e.tables;for(const r of n)e.tables.some(s=>s.name===r)||t.logger.warn(`--tables: no table named "${r}" exists in this schema — skipped.`);return e.tables.filter(r=>n.includes(r.name))},Le=async(e,t,n,r)=>{const s=pe(O(e,"utf8"),t,n);for(const a of s.warnings)r.logger.warn(a);return s.text===void 0?(r.logger.info("lunora/schema.ts is already up to date with the database."),!1):r.dryRun===!0?(r.logger.info(`would merge ${String(s.applied)} addition(s) into lunora/schema.ts`),!1):(await I(e,s.text,"utf8"),r.logger.info(`merged ${String(s.applied)} addition(s) into lunora/schema.ts`),!0)},Te=async e=>{const t=e.cwd??process.cwd();if(e.connection===void 0&&(e.url===void 0||e.url===""))return e.logger.error("`lunora introspect` needs a database URL: pass --url, or set DATABASE_URL."),{code:1,written:[]};const n=e.connection===void 0?j(e.url):e.dialect??"postgres",r=e.connection??await J(e.url,n,e.schema,t);let s;try{s=await Ne(r.execute,n,r.schema)}finally{e.connection===void 0&&await r.close()}const a=$e(s,e);if(a.length===0)return e.logger.error("no tables found to introspect — check --schema and --tables."),{code:1,written:[]};const{files:o,warnings:i}=ce({...s,tables:a},{procedures:e.procedures!==!1,serverImport:we(t)}),c=b(t,"lunora"),m=[],u=b(c,"schema.ts"),l=T(u)&&e.force!==!0,d=l?o.filter(p=>p.path!=="schema.ts"):o;l&&await Le(u,{...s,tables:a},n,e)&&m.push("schema.ts");for(const p of d)await Re(p,c,e)&&m.push(p.path);for(const p of i)e.logger.warn(p);return e.logger.info(`introspected ${String(a.length)} table(s) from ${n}. Review the generated files before running \`lunora dev\`.`),{code:0,written:m}},Be=B(async({cwd:e,logger:t,options:n})=>({code:(await Te({cwd:e,dryRun:n.dryRun===!0,force:n.force===!0,logger:t,procedures:n.procedures!==!1,schema:n.schema,tables:n.tables===void 0?void 0:n.tables.split(",").map(s=>s.trim()),url:n.url??process.env.DATABASE_URL})).code}));export{Be as execute,we as resolveServerImport,Te as runIntrospectCommand};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import{V as R}from"../packem_shared/cli-
|
|
2
|
-
`),{action:"created",path:o};const{errors:c,value:i}=w(l);if(c.length>0)return{action:"invalid",error:`parse error at offset ${String(c[0]?.offset??0)}`,path:o};if(!g(i))return{action:"invalid",error:"the file's root is not a JSON object",path:o};const m=i[n];if(m!==void 0&&!g(m))return{action:"invalid",error:`"${n}" is not an object`,path:o};if(S(i,n,a)!==void 0&&!t)return{action:"skipped",path:o};const k=M(l,o,n,a,r);return k===void 0?{action:"updated",path:o}:{action:"invalid",error:k,path:o}},ve=e=>{const{key:r,name:t,path:n}=e;if(!u(n))return{action:"absent",path:n};let a;try{a=v(n,"utf8")}catch(i){return{action:"invalid",error:i instanceof Error?i.message:String(i),path:n}}const{errors:o,value:l}=w(a);if(o.length>0)return{action:"invalid",error:`parse error at offset ${String(o[0]?.offset??0)}`,path:n};if(S(l,r,t)===void 0)return{action:"absent",path:n};const c=M(a,n,r,t,void 0);return c===void 0?{action:"removed",path:n}:{action:"invalid",error:c,path:n}},he=["global","project"],d=(e,r)=>{const t=q(r,e);return t.length>0&&!t.startsWith("..")?t:e},ye=(e,r)=>{const t=e.paths(r);return he.flatMap(n=>{const a=t[n];return a===void 0?[]:[{client:e,path:a,scope:n}]})},be=(e,r,t,n)=>{const a=e.paths(r),o=t==="global"?"project":"global",l=a[t]??(n?void 0:a[o]);if(l!==void 0)return{client:e,path:l,scope:a[t]===void 0?o:t}},we=e=>p.filter(r=>Object.values(r.paths(e)).some(t=>u(t))),_=(e,r,t,n)=>{if(e.length===0)return r();const a=[];for(const o of e){const l=fe(o);if(l===void 0){t.error(`mcp ${n}: unknown client "${o}". Known clients: ${O.join(", ")}.`);return}a.push(l)}return a},Se=e=>e.client.format==="json",ke="https://lunora.sh/mcp",L="lunora-docs",N="lunora",je=e=>u(s(e,"lunora"))&&V(e)!==void 0,$e=e=>{const{args:r,command:t}=
|
|
1
|
+
import{V as R}from"../packem_shared/cli-HouJioGN.mjs";import{d as T}from"../packem_shared/command-DwC11Cwe.mjs";import{existsSync as u,readFileSync as v,mkdirSync as D,realpathSync as I,statSync as J,writeFileSync as W,chmodSync as z,renameSync as G,unlinkSync as H}from"node:fs";import{homedir as b}from"node:os";import{findWranglerFile as V}from"@lunora/config/cloudflare";import{join as s,dirname as K,relative as q}from"@visulima/path";import{stringify as B}from"smol-toml";import{parse as X,modify as Z,applyEdits as Q}from"jsonc-parser";import{detectPackageManager as Y,execArgsFor as ee,readLiveDevServerState as y}from"@lunora/config";import{resolveAdminToken as re}from"@lunora/config/studio-host";import{connectLocalStdio as te}from"@lunora/mcp";const f=e=>({args:[...e.args],command:e.command,...e.env===void 0?{}:{env:e.env}}),h=e=>e.transport==="http"?{type:"http",url:e.url}:f(e),ne=e=>e.transport==="http"?{httpUrl:e.url}:f(e),oe=e=>e.transport==="http"?{serverUrl:e.url}:f(e),ae=e=>({args:["-y","mcp-remote",e],command:"npx"}),le=e=>e.transport==="http"?ae(e.url):f(e),ce=e=>e.transport==="http"?{url:e.url}:f(e),se=e=>e.transport==="http"?{enabled:!0,type:"remote",url:e.url}:{command:[e.command,...e.args],enabled:!0,type:"local",...e.env===void 0?{}:{environment:e.env}},ie=e=>e.transport==="http"?{disabled:!1,type:"streamableHttp",url:e.url}:{disabled:!1,...f(e)},de=({home:e,platform:r})=>{if(r==="darwin")return{global:s(e,"Library","Application Support","Claude","claude_desktop_config.json")};if(r==="win32"){const t=process.env.APPDATA;return t===void 0||t===""?{}:{global:s(t,"Claude","claude_desktop_config.json")}}return r==="linux"?{global:s(e,".config","Claude","claude_desktop_config.json")}:{}},ue=(e,r)=>B({mcp_servers:{[e]:r.transport==="http"?{url:r.url}:{args:[...r.args],command:r.command,...r.env===void 0?{}:{env:r.env}}}}),p=[{buildEntry:h,paths:({projectRoot:e})=>({project:s(e,".mcp.json")}),format:"json",id:"claude-code",key:"mcpServers",label:"Claude Code"},{buildEntry:h,paths:({home:e,projectRoot:r})=>({global:s(e,".cursor","mcp.json"),project:s(r,".cursor","mcp.json")}),format:"json",id:"cursor",key:"mcpServers",label:"Cursor"},{buildEntry:h,paths:({projectRoot:e})=>({project:s(e,".vscode","mcp.json")}),format:"json",id:"vscode",key:"servers",label:"VS Code (GitHub Copilot)"},{buildEntry:ne,paths:({home:e,projectRoot:r})=>({global:s(e,".gemini","settings.json"),project:s(r,".gemini","settings.json")}),format:"json",id:"gemini",key:"mcpServers",label:"Gemini CLI"},{buildEntry:le,paths:de,format:"json",id:"claude-desktop",key:"mcpServers",label:"Claude Desktop"},{buildEntry:oe,paths:({home:e})=>({global:s(e,".codeium","windsurf","mcp_config.json")}),format:"json",id:"windsurf",key:"mcpServers",label:"Windsurf"},{buildEntry:se,paths:({home:e,projectRoot:r})=>({global:s(e,".config","opencode","opencode.json"),project:s(r,"opencode.json")}),format:"json",id:"opencode",key:"mcp",label:"OpenCode"},{buildEntry:ie,paths:({home:e})=>({global:s(e,".cline","mcp.json")}),format:"json",id:"cline",key:"mcpServers",label:"Cline"},{buildEntry:ce,paths:({home:e})=>({global:s(e,".config","zed","settings.json")}),format:"json",id:"zed",key:"context_servers",label:"Zed"},{paths:({home:e,projectRoot:r})=>({global:s(e,".codex","config.toml"),project:s(r,".codex","config.toml")}),format:"manual",id:"codex",label:"Codex CLI",renderSnippet:ue}],O=p.map(e=>e.id),fe=e=>p.find(r=>r.id===e.toLowerCase()),C=(e,r)=>{let t=e,n;try{t=I(e),n=J(t).mode}catch{}const a=`${t}.lunora-${Math.random().toString(36).slice(2,10)}.tmp`;try{W(a,r,"utf8"),n!==void 0&&z(a,n),G(a,t)}catch(o){try{H(a)}catch{}throw o}},me={formattingOptions:{insertSpaces:!0,tabSize:4}},w=e=>{const r=[],t=X(e,r,{allowTrailingComma:!0});return{errors:r,value:t}},g=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),S=(e,r,t)=>{if(!g(e))return;const n=e[r];return g(n)?n[t]:void 0},x=e=>{if(!u(e.path))return"absent";let r;try{r=v(e.path,"utf8")}catch{return"invalid"}if(r.trim().length===0)return"absent";const{errors:t,value:n}=w(r);return t.length>0||!g(n)?"invalid":S(n,e.key,e.name)===void 0?"absent":"present"},ge=e=>x(e)==="present",M=(e,r,t,n,a)=>{try{const o=Z(e,[t,n],a,me);o.length>0&&C(r,Q(e,o));return}catch(o){return o instanceof Error?o.message:String(o)}},pe=e=>{const{entry:r,force:t=!1,key:n,name:a,path:o}=e,l=u(o)?v(o,"utf8"):"";if(l.trim().length===0)return D(K(o),{recursive:!0}),C(o,`${JSON.stringify({[n]:{[a]:r}},void 0,4)}
|
|
2
|
+
`),{action:"created",path:o};const{errors:c,value:i}=w(l);if(c.length>0)return{action:"invalid",error:`parse error at offset ${String(c[0]?.offset??0)}`,path:o};if(!g(i))return{action:"invalid",error:"the file's root is not a JSON object",path:o};const m=i[n];if(m!==void 0&&!g(m))return{action:"invalid",error:`"${n}" is not an object`,path:o};if(S(i,n,a)!==void 0&&!t)return{action:"skipped",path:o};const k=M(l,o,n,a,r);return k===void 0?{action:"updated",path:o}:{action:"invalid",error:k,path:o}},ve=e=>{const{key:r,name:t,path:n}=e;if(!u(n))return{action:"absent",path:n};let a;try{a=v(n,"utf8")}catch(i){return{action:"invalid",error:i instanceof Error?i.message:String(i),path:n}}const{errors:o,value:l}=w(a);if(o.length>0)return{action:"invalid",error:`parse error at offset ${String(o[0]?.offset??0)}`,path:n};if(S(l,r,t)===void 0)return{action:"absent",path:n};const c=M(a,n,r,t,void 0);return c===void 0?{action:"removed",path:n}:{action:"invalid",error:c,path:n}},he=["global","project"],d=(e,r)=>{const t=q(r,e);return t.length>0&&!t.startsWith("..")?t:e},ye=(e,r)=>{const t=e.paths(r);return he.flatMap(n=>{const a=t[n];return a===void 0?[]:[{client:e,path:a,scope:n}]})},be=(e,r,t,n)=>{const a=e.paths(r),o=t==="global"?"project":"global",l=a[t]??(n?void 0:a[o]);if(l!==void 0)return{client:e,path:l,scope:a[t]===void 0?o:t}},we=e=>p.filter(r=>Object.values(r.paths(e)).some(t=>u(t))),_=(e,r,t,n)=>{if(e.length===0)return r();const a=[];for(const o of e){const l=fe(o);if(l===void 0){t.error(`mcp ${n}: unknown client "${o}". Known clients: ${O.join(", ")}.`);return}a.push(l)}return a},Se=e=>e.client.format==="json",ke="https://lunora.sh/mcp",L="lunora-docs",N="lunora",je=e=>u(s(e,"lunora"))&&V(e)!==void 0,$e=e=>{const{args:r,command:t}=ee(e,"lunora",["mcp","serve"]);return{args:r,command:t,transport:"stdio"}},Ee=e=>({transport:"http",url:e}),Oe=e=>({home:e.home,platform:e.platform,projectRoot:e.cwd}),U=(e,r,t)=>be(e,Oe(t),t.scope??r.preferredScope,t.scope!==void 0||!r.allowScopeFallback),Ce=(e,r,t)=>{const n=U(e,r,t);if(n===void 0){t.logger.warn(`${e.label}: has no ${t.scope??r.preferredScope}-scoped config — skipped "${r.name}".`);return}const{path:a}=n,o=e.buildEntry(r.spec);if(t.print===!0){const i=d(a,t.cwd);return t.force!==!0&&ge({key:e.key,name:r.name,path:a})?(t.logger.info(`${e.label}: "${r.name}" already configured in ${i} — a real install would skip it (re-run with --force to replace).`),{action:"printed",path:a}):(t.logger.info(`${e.label} → ${i}
|
|
3
3
|
${JSON.stringify({[e.key]:{[r.name]:o}},void 0,4)}`),{action:"printed",path:a})}const l=pe({entry:o,force:t.force===!0,key:e.key,name:r.name,path:a}),c=d(a,t.cwd);return l.action==="invalid"?t.logger.error(`${e.label}: ${c} is not valid JSON (${l.error??"unknown error"}) — left untouched.`):l.action==="skipped"?t.logger.info(`${e.label}: "${r.name}" already configured in ${c} — re-run with --force to replace it.`):t.logger.success(`${e.label}: ${l.action==="created"?"created":"updated"} ${c} with "${r.name}".`),{action:l.action,path:a}},xe=(e,r,t)=>{const n=U(e,r,t)?.path;if(n===void 0){t.logger.warn(`${e.label}: no known config location on ${t.platform} — skipped.`);return}return t.logger.info(`${e.label}: add this to ${d(n,t.cwd)}
|
|
4
4
|
|
|
5
|
-
${e.renderSnippet(r.name,r.spec)}`),{action:"printed",path:n}},Me=e=>{const r=[];return e.localOnly!==!0&&r.push({allowScopeFallback:!0,name:L,preferredScope:"global",spec:Ee(e.docsUrl??ke)}),e.docsOnly!==!0&&je(e.cwd)&&r.push({allowScopeFallback:!1,name:N,preferredScope:"project",spec:$e(
|
|
5
|
+
${e.renderSnippet(r.name,r.spec)}`),{action:"printed",path:n}},Me=e=>{const r=[];return e.localOnly!==!0&&r.push({allowScopeFallback:!0,name:L,preferredScope:"global",spec:Ee(e.docsUrl??ke)}),e.docsOnly!==!0&&je(e.cwd)&&r.push({allowScopeFallback:!1,name:N,preferredScope:"project",spec:$e(Y(e.cwd))}),r},_e=e=>{const r=e.home??b(),t=e.platform??process.platform;e.logger.info("Supported MCP clients:");for(const n of p){const a=n.paths({home:r,platform:t,projectRoot:e.cwd}),o=l=>{const c=a[l];return c===void 0?"—":d(c,e.cwd)};e.logger.info(` ${n.id.padEnd(15)} ${n.label.padEnd(24)} project: ${o("project").padEnd(30)} global: ${o("global")}`)}return{code:0,written:[]}},Le=e=>e.docsOnly===!0&&e.localOnly===!0?"`--docs-only` and `--local-only` are mutually exclusive — pass at most one.":"`--local-only` was set but this directory is not a Lunora project (no `lunora/` directory and wrangler config).",Ne=(e,r,t)=>{const n=[];for(const a of e)for(const o of r){const l=a.format==="json"?Ce(a,o,t):xe(a,o,t);l!==void 0&&n.push({action:l.action,client:a.id,path:l.path,server:o.name})}return n},Ue=e=>{const r=e.home??b(),t=e.platform??process.platform,n=_(e.clients,()=>we({home:r,platform:t,projectRoot:e.cwd}),e.logger,"install");if(n===void 0)return{code:1,written:[]};if(n.length===0)return e.logger.error(`mcp install: no MCP client config found — name one explicitly, e.g. \`lunora mcp install claude-code\`. Known clients: ${O.join(", ")}.`),{code:1,written:[]};e.clients.length===0&&e.logger.info(`Detected ${String(n.length)} configured client(s): ${n.map(l=>l.label).join(", ")}.`);const a=Me(e);if(a.length===0)return e.logger.error(`mcp install: nothing to install — ${Le(e)}`),{code:1,written:[]};const o=Ne(n,a,{...e,home:r,platform:t});return o.some(l=>l.action==="created"||l.action==="updated")&&e.logger.info("Restart your editor (or reload its MCP servers) to pick up the change."),{code:o.some(l=>l.action==="invalid")?1:0,written:o}},A=100,F=1e3,j=e=>({content:[{text:JSON.stringify(e,void 0,2),type:"text"}]}),Ae=e=>({content:[{text:e,type:"text"}]}),Fe=e=>{const r=typeof e=="string"?Number(e):e;return typeof r!="number"||!Number.isFinite(r)?A:Math.min(F,Math.max(1,Math.floor(r)))},Pe=(e,r)=>{const t=v(e,"utf8").split(`
|
|
6
6
|
`);return t.at(-1)===""&&t.pop(),t.slice(-r).join(`
|
|
7
7
|
`)},Re=e=>[{definition:{description:"Report whether a `lunora dev` server is running for this project, and its URL, studio URL, mode and uptime. Call this first when a query or mutation tool fails to connect.",inputSchema:{properties:{},type:"object"},name:"lunora_dev_status"},handle:async()=>{const r=y(e);return j(r===void 0?{hint:"Start it with `lunora dev` in the project directory.",running:!1}:{background:r.background===!0,logFile:r.logFile,mode:r.mode,pid:r.pid,running:!0,startedAt:r.startedAt,studioUrl:r.studioUrl,url:r.url})}},{definition:{description:"Return the tail of the running dev server's captured log — worker output, request errors, and stack traces. Only available when the server was started in the background (`lunora dev --background`); a foreground server prints to its own terminal.",inputSchema:{properties:{lines:{description:`How many trailing lines to return (default ${String(A)}, max ${String(F)})`,type:"number"}},type:"object"},name:"lunora_dev_logs"},handle:async r=>{const t=y(e);if(t===void 0)return{content:[{text:"no dev server is running — start one with `lunora dev`",type:"text"}],isError:!0};if(t.logFile===void 0||!u(t.logFile))return{content:[{text:"this dev server is not capturing its output to a file (it runs in the foreground) — restart it with `lunora dev --background` to make its logs readable here",type:"text"}],isError:!0};const n=Fe(r.lines),a=Pe(t.logFile,n);return Ae(a.length===0?"(the dev server log is empty)":a)}}],Te=new Set(["127.0.0.1","::1","localhost"]),P=e=>{try{const{hostname:r}=new URL(e);return Te.has(r.startsWith("[")?r.slice(1,-1):r)}catch{return!1}},$=e=>{const r=e.url??y(e.cwd)?.url;if(r===void 0||r.length===0)return;if(e.token!==void 0&&e.token.length>0)return{token:e.token,url:r};if(e.url!==void 0&&!P(e.url))return{url:r};const t=re(e.cwd);return t===void 0||t.length===0?{url:r}:{token:t,url:r}},De=async e=>{await new Promise(r=>{const t=()=>{r()};e.onclose=t,process.stdin.once("close",t),process.stdin.once("end",t)})},Ie=(e,r)=>{if(e===void 0)return"lunora mcp serve: ready (documentation tools). No dev server running yet — start `lunora dev` and the deployment tools start working, no restart needed.\n";if(e.token!==void 0)return`lunora mcp serve: ready — deployment at ${e.url}
|
|
8
8
|
`;const n=r.url!==void 0&&!P(r.url)?"the project's admin token was NOT sent to this non-local --url; pass --token to authenticate deliberately":"no LUNORA_ADMIN_TOKEN in the environment or .dev.vars; the deployment tools will be refused until one is set";return`lunora mcp serve: ready — deployment at ${e.url} (${n})
|
|
9
9
|
`},Je=async(e,r=te)=>{const t=e.writeError??(o=>{process.stderr.write(o)});let n;try{n=await r({allowWrites:e.allowWrites===!0,deployment:()=>$(e),docs:e.noDocs===!0?!1:{...e.docsUrl===void 0?{}:{baseUrl:e.docsUrl}},extraTools:Re(e.cwd),version:e.version})}catch(o){const l=o instanceof Error?o.message:String(o);return t(`lunora mcp serve: failed to start — ${l}
|
|
10
|
-
`),{code:1,deployment:void 0}}const a=$(e);return t(Ie(a,e)),await De(n),{code:0,deployment:a}},We=e=>{const r=[];return e.localOnly!==!0&&r.push(L),e.docsOnly!==!0&&r.push(N),r},ze=(e,r,t,n)=>{const a=ve({key:e.key,name:r,path:t}),o=d(t,n.cwd);return a.action==="removed"?n.logger.success(`${e.label}: removed "${r}" from ${o}.`):a.action==="invalid"&&n.logger.error(`${e.label}: ${o} is not valid JSON (${a.error??"unknown error"}) — left untouched.`),{action:a.action,path:t}},Ge=(e,r,t,n)=>{const a=x({key:e.key,name:r,path:t}),o=d(t,n.cwd);return a==="invalid"?(n.logger.error(`${e.label}: ${o} is not valid JSON — a real run would report it and exit non-zero.`),{action:"invalid",path:t}):a==="absent"?{action:"absent",path:t}:(n.logger.info(`${e.label}: would remove "${r}" from ${o}.`),{action:"removed",path:t})},He=(e,r,t)=>e.flatMap(n=>ye(n,r)).filter(Se).filter(n=>t===void 0||n.scope===t),Ve=e=>{const r=e.home??b(),t=e.platform??process.platform,n=_(e.clients,()=>p,e.logger,"uninstall");if(n===void 0)return{code:1,removed:[]};const a=We(e);if(a.length===0)return e.logger.error("mcp uninstall: nothing to remove — `--docs-only` and `--local-only` are mutually exclusive, pass at most one."),{code:1,removed:[]};const o=[],l={home:r,platform:t,projectRoot:e.cwd};for(const c of He(n,l,e.scope))for(const i of a){const m=e.print===!0?Ge(c.client,i,c.path,e):ze(c.client,i,c.path,e);m.action!=="absent"&&o.push({...m,client:c.client.id,server:i})}return o.length===0?e.logger.info("Nothing to remove — no Lunora MCP servers were configured in the clients checked."):e.print===!0&&e.logger.info("Nothing was changed — re-run without --print to remove these."),{code:o.some(c=>c.action==="invalid")?1:0,removed:o}},E=e=>e.global===!0?"global":e.project===!0?"project":void 0,Ke=async(e,r)=>{const{code:t}=await Je({allowWrites:r.allowWrites===!0,cwd:e,noDocs:r.docs===!1,version:R,...r.docsUrl===void 0?{}:{docsUrl:r.docsUrl},...r.token===void 0?{}:{token:r.token},...r.url===void 0?{}:{url:r.url}});return{code:t}},
|
|
10
|
+
`),{code:1,deployment:void 0}}const a=$(e);return t(Ie(a,e)),await De(n),{code:0,deployment:a}},We=e=>{const r=[];return e.localOnly!==!0&&r.push(L),e.docsOnly!==!0&&r.push(N),r},ze=(e,r,t,n)=>{const a=ve({key:e.key,name:r,path:t}),o=d(t,n.cwd);return a.action==="removed"?n.logger.success(`${e.label}: removed "${r}" from ${o}.`):a.action==="invalid"&&n.logger.error(`${e.label}: ${o} is not valid JSON (${a.error??"unknown error"}) — left untouched.`),{action:a.action,path:t}},Ge=(e,r,t,n)=>{const a=x({key:e.key,name:r,path:t}),o=d(t,n.cwd);return a==="invalid"?(n.logger.error(`${e.label}: ${o} is not valid JSON — a real run would report it and exit non-zero.`),{action:"invalid",path:t}):a==="absent"?{action:"absent",path:t}:(n.logger.info(`${e.label}: would remove "${r}" from ${o}.`),{action:"removed",path:t})},He=(e,r,t)=>e.flatMap(n=>ye(n,r)).filter(Se).filter(n=>t===void 0||n.scope===t),Ve=e=>{const r=e.home??b(),t=e.platform??process.platform,n=_(e.clients,()=>p,e.logger,"uninstall");if(n===void 0)return{code:1,removed:[]};const a=We(e);if(a.length===0)return e.logger.error("mcp uninstall: nothing to remove — `--docs-only` and `--local-only` are mutually exclusive, pass at most one."),{code:1,removed:[]};const o=[],l={home:r,platform:t,projectRoot:e.cwd};for(const c of He(n,l,e.scope))for(const i of a){const m=e.print===!0?Ge(c.client,i,c.path,e):ze(c.client,i,c.path,e);m.action!=="absent"&&o.push({...m,client:c.client.id,server:i})}return o.length===0?e.logger.info("Nothing to remove — no Lunora MCP servers were configured in the clients checked."):e.print===!0&&e.logger.info("Nothing was changed — re-run without --print to remove these."),{code:o.some(c=>c.action==="invalid")?1:0,removed:o}},E=e=>e.global===!0?"global":e.project===!0?"project":void 0,Ke=async(e,r)=>{const{code:t}=await Je({allowWrites:r.allowWrites===!0,cwd:e,noDocs:r.docs===!1,version:R,...r.docsUrl===void 0?{}:{docsUrl:r.docsUrl},...r.token===void 0?{}:{token:r.token},...r.url===void 0?{}:{url:r.url}});return{code:t}},ar=T(async({argument:e,cwd:r,logger:t,options:n})=>{const[a,...o]=e;if(a==="serve")return Ke(r,n);if(a==="uninstall"){const l=E(n),{code:c}=Ve({clients:o,cwd:r,docsOnly:n.docsOnly===!0,localOnly:n.localOnly===!0,logger:t,print:n.print===!0,...l===void 0?{}:{scope:l}});return{code:c}}if(a==="install"){if(n.list===!0)return _e({cwd:r,logger:t});const l=E(n),{code:c}=Ue({clients:o,cwd:r,docsOnly:n.docsOnly===!0,force:n.force===!0,localOnly:n.localOnly===!0,logger:t,print:n.print===!0,...l===void 0?{}:{scope:l},...n.docsUrl===void 0?{}:{docsUrl:n.docsUrl}});return{code:c}}return t.error("mcp: unknown subcommand. Usage: lunora mcp <install|uninstall|serve>"),{code:1}});export{ar as execute};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as i}from"../packem_shared/command-DwC11Cwe.mjs";import{
|
|
1
|
+
import{d as i}from"../packem_shared/command-DwC11Cwe.mjs";import{i as l}from"../packem_shared/docker-DpVxvYpL.mjs";import{defaultSpawner as m}from"../packem_shared/createRecordingSpawner-DJlNacZ6.mjs";import{execArgsFor as g,detectPackageManager as p}from"@lunora/config";const o=new Set(["build","delete","images","info","list","push"]),f=new Set(["build","push"]),h=async e=>{const[a,...t]=e.argument;if(a===void 0||!o.has(a))return e.logger.error(`lunora containers requires a subcommand: ${[...o].toSorted((u,d)=>u.localeCompare(d)).join(" | ")}. Example: lunora containers build ./containers/app --tag app:v1 --push`),{code:1};if(f.has(a)&&!(e.dockerAvailable??l)())return e.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 r=["containers",a,...t];e.tag!==void 0&&r.push("--tag",e.tag),e.push===!0&&r.push("--push"),e.env!==void 0&&r.push("--env",e.env);const s=e.cwd??process.cwd(),c=g(p(s),"wrangler",r),n={args:c.args,command:c.command,cwd:s};return e.logger.info(`running ${n.command} ${n.args.join(" ")}`),{code:(await(e.spawner??m)(n)).code,descriptor:n}},D=i(async({argument:e,cwd:a,logger:t,options:r})=>({code:(await h({argument:e,cwd:a,env:r.env,logger:t,push:r.push===!0,tag:r.tag})).code}));export{D as execute,h as runContainersCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d}from"../packem_shared/command-DwC11Cwe.mjs";import{
|
|
1
|
+
import{d}from"../packem_shared/command-DwC11Cwe.mjs";import{defaultSpawner as a}from"../packem_shared/createRecordingSpawner-DJlNacZ6.mjs";import{execArgsFor as m,detectPackageManager as i}from"@lunora/config";const t=(e,r)=>(r!==void 0&&e.push("--env",r),e),u=e=>{const r=t(["deployments","list"],e.env);return e.json&&r.push("--json"),r},l=e=>{switch(e.subcommand){case"inspect":return e.versionId===void 0?{error:"deployments inspect requires a version id. Usage: lunora deployments inspect <version-id>"}:{args:t(["versions","view",e.versionId],e.env)};case"list":return{args:u(e)};case"promote":{if(e.versionId===void 0)return{error:"deployments promote requires a version id. Usage: lunora deployments promote <version-id> --yes"};if(!e.yes)return{error:"deployments promote shifts 100% of live traffic. Re-run with --yes to confirm."};const r=t(["versions","deploy",`${e.versionId}@100%`,"--yes"],e.env);return e.message!==void 0&&r.push("--message",e.message),{args:r}}case"rollback":{if(!e.yes)return{error:"deployments rollback changes the live version. Re-run with --yes to confirm."};const r=t(["rollback"],e.env);return e.versionId!==void 0&&r.push(e.versionId),r.push("--yes"),e.message!==void 0&&r.push("--message",e.message),{args:r}}default:return{error:`deployments: unknown subcommand "${e.subcommand}"`}}},v=async e=>{const{args:r,error:n}=l(e);if(n!==void 0||r===void 0)return e.logger.error(n??"deployments: nothing to run"),{code:1,descriptor:void 0,error:n};const s=e.cwd??process.cwd(),o=m(i(s),"wrangler",r),c={args:o.args,command:o.command,cwd:s};return e.logger.info(`${c.command} ${c.args.join(" ")}`),{code:(await(e.spawner??a)(c)).code,descriptor:c}},g=e=>e==="list"||e==="inspect"||e==="rollback"||e==="promote",h=d(({argument:e,cwd:r,logger:n,options:s})=>{const o=e[0];return g(o)?v({cwd:r,env:s.env,json:s.json===!0,logger:n,message:s.message,subcommand:o,versionId:e[1],yes:s.yes===!0}):(n.error(`deployments: unknown subcommand "${o??""}" — expected list | inspect | rollback | promote`),{code:1})});export{h as execute,v as runDeploymentsCommand};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{existsSync as h,readFileSync as S}from"node:fs";import{join as V}from"node:path";import{DEV_VARS_FILE as d,DEV_VARS_KEY_PATTERN as k,writeDevVariablesFileAtomically as $,removeDevVariableLine as R,upsertDevVariableLine as P,isPlaceholderValue as A,
|
|
2
|
-
`),{code:0,descriptors:[]}):(t.error(`env: ${e.key} is not set in ${d}`),{code:1,descriptors:[]})},G=r=>{const{devVariablesPath:s,logger:t,options:e}=r;if(!e.key)return t.error("env set requires a key. Usage: lunora env set <KEY> <VALUE>"),{code:1,descriptors:[]};if(!k.test(e.key))return t.error(`env: invalid key "${e.key}" — must match [A-Za-z_][A-Za-z0-9_]*`),{code:1,descriptors:[]};if(e.value===void 0)return t.error("env set requires a value. Usage: lunora env set <KEY> <VALUE>"),{code:1,descriptors:[]};if(Z.test(e.value))return t.error(`env: value for "${e.key}" contains a newline, which .dev.vars cannot represent`),{code:1,descriptors:[]};if(B.test(e.value))return t.error(`env: value for "${e.key}" contains a double-quote or backslash, which .dev.vars cannot round-trip`),{code:1,descriptors:[]};const o=
|
|
3
|
-
`);return{code:0,descriptors:[]}},te=async r=>{const s=r.cwd??process.cwd(),t={cwd:s,devVariablesPath:V(s,d),logger:r.logger,options:r};switch(r.subcommand){case"diff":return J(t);case"doctor":return Q(t);case"generate":return re(t);case"get":return O(t);case"list":return I(t);case"push":return W(t);case"set":return G(t);case"unset":return H(t);default:return r.logger.error(`env: unknown subcommand "${r.subcommand}"`),{code:1,descriptors:[]}}},oe=new Set(["diff","doctor","generate","get","list","push","set","unset"]),se=r=>typeof r=="string"&&oe.has(r),
|
|
1
|
+
import{existsSync as h,readFileSync as S}from"node:fs";import{join as V}from"node:path";import{DEV_VARS_FILE as d,DEV_VARS_KEY_PATTERN as k,writeDevVariablesFileAtomically as $,removeDevVariableLine as R,upsertDevVariableLine as P,isPlaceholderValue as A,detectPackageManager as N,resolveDeployDriver as U,resolveProjectTarget as z,execArgsFor as M,generateSecretValue as Y,DEV_VARS_EXAMPLE_FILE as p,parseDevVariableEntries as _,packageNamesFromBindings as j,inferLunoraBindings as x,requiredSecrets as C,isMintableSecretKey as b}from"@lunora/config";import{d as q}from"../packem_shared/command-DwC11Cwe.mjs";import{defaultSpawner as F}from"../packem_shared/createRecordingSpawner-DJlNacZ6.mjs";import{l as T}from"../packem_shared/wrangler-secrets-CCdt0mUl.mjs";const Z=/[\r\n]/u,B=/["\\]/u,D=r=>new Map(_(r).map(s=>[s.key,s])),y=r=>h(r)?S(r,"utf8"):"",L=r=>r.length<=4?"****":`${r.slice(0,4)}${"*".repeat(Math.min(8,r.length-4))}`,f=r=>D(y(r)),K=r=>r.env??(r.prod===!0?"production":void 0),I=r=>{const s=f(r.devVariablesPath);if(s.size===0)return r.logger.info(`${d}: (empty)`),{code:0,descriptors:[]};for(const t of s.values())r.logger.info(`${t.key}=${L(t.value)}`);return{code:0,descriptors:[]}},O=r=>{const{devVariablesPath:s,logger:t,options:e}=r;if(!e.key)return t.error("env get requires a key. Usage: lunora env get <KEY>"),{code:1,descriptors:[]};const o=f(s).get(e.key);return o?(process.stdout.write(`${o.value}
|
|
2
|
+
`),{code:0,descriptors:[]}):(t.error(`env: ${e.key} is not set in ${d}`),{code:1,descriptors:[]})},G=r=>{const{devVariablesPath:s,logger:t,options:e}=r;if(!e.key)return t.error("env set requires a key. Usage: lunora env set <KEY> <VALUE>"),{code:1,descriptors:[]};if(!k.test(e.key))return t.error(`env: invalid key "${e.key}" — must match [A-Za-z_][A-Za-z0-9_]*`),{code:1,descriptors:[]};if(e.value===void 0)return t.error("env set requires a value. Usage: lunora env set <KEY> <VALUE>"),{code:1,descriptors:[]};if(Z.test(e.value))return t.error(`env: value for "${e.key}" contains a newline, which .dev.vars cannot represent`),{code:1,descriptors:[]};if(B.test(e.value))return t.error(`env: value for "${e.key}" contains a double-quote or backslash, which .dev.vars cannot round-trip`),{code:1,descriptors:[]};const o=y(s);return $(s,P(o,e.key,e.value)),t.success(`env: set ${e.key} (${L(e.value)}) in ${d}`),{code:0,descriptors:[]}},H=r=>{const{devVariablesPath:s,logger:t,options:e}=r;if(!e.key)return t.error("env unset requires a key. Usage: lunora env unset <KEY>"),{code:1,descriptors:[]};if(!k.test(e.key))return t.error(`env: invalid key "${e.key}" — must match [A-Za-z_][A-Za-z0-9_]*`),{code:1,descriptors:[]};const o=y(s);return D(o).has(e.key)?($(s,R(o,e.key)),t.success(`env: unset ${e.key} in ${d}`),{code:0,descriptors:[]}):(t.warn(`env: ${e.key} was not set in ${d}`),{code:0,descriptors:[]})},W=async r=>{const{devVariablesPath:s,logger:t,options:e}=r;if(!e.yes)return t.error("env push uploads secrets to Cloudflare. Re-run with --yes to confirm."),{code:1,descriptors:[]};const o=f(s);if(o.size===0)return t.warn(`${d}: nothing to push (empty)`),{code:0,descriptors:[]};const i=[...o.values()].filter(n=>A(n.value)).map(n=>n.key);if(i.length>0)return t.error(`env push: refusing to upload placeholder value(s) for ${i.join(", ")} — run \`lunora env doctor\` to review, and \`lunora env generate --set\` (or \`lunora env set <KEY> <VALUE>\`) to fill them, then re-run.`),{code:1,descriptors:[]};const c=e.spawner??F,l=e.cwd??process.cwd(),v=N(l),a=[],u=K(e);for(const n of o.values()){const m=U(z(l)).toolchain?.secretPut({environment:u,key:n.key,temporary:e.temporary});if(m===void 0)return t.error("deploy target has no command-line toolchain; cannot push secrets"),{code:1,descriptors:[]};const E=M(v,m.tool,m.args),w={args:E.args,command:E.command,cwd:l,input:n.value};a.push(w),t.info(`pushing ${n.key} -> wrangler secret${u===void 0?"":` (${u})`}`);const g=await c(w);if(g.code!==0)return t.error(`env push: failed at ${n.key} (exit ${String(g.code)})`),{code:g.code,descriptors:a}}return t.success(`env: pushed ${String(o.size)} secret(s)`),{code:0,descriptors:a}},X=r=>(r.options.secretLister??T)({cwd:r.cwd,env:K(r.options),temporary:r.options.temporary}),J=async r=>{const{devVariablesPath:s,logger:t}=r,e=await X(r);if(!e.ok)return t.error(`env diff: ${e.error??"failed to list remote secrets"}`),{code:1,descriptors:[]};const o=new Set(f(s).keys()),i=new Set(e.names),c=[...o].filter(a=>!i.has(a)).toSorted((a,u)=>a.localeCompare(u)),l=e.names.filter(a=>!o.has(a)),v=[...o].filter(a=>i.has(a)).toSorted((a,u)=>a.localeCompare(u));for(const a of c)t.info(`local only (run \`lunora env push\`): ${a}`);for(const a of l)t.info(`remote only (in Cloudflare, not ${d}): ${a}`);return t.info(`in both: ${String(v.length)} secret(s)`),c.length===0&&l.length===0&&t.success("env diff: local and remote secret names match"),{code:0,descriptors:[]}},Q=r=>{const{cwd:s,devVariablesPath:t,logger:e}=r,o=V(s,p);if(!h(o))return e.info(`env doctor: no ${p} to check against — nothing to validate.`),{code:0,descriptors:[]};const i=_(S(o,"utf8")).map(n=>n.key),c=f(t);if(!h(t))return e.error(`env doctor: ${d} is missing. Run \`lunora dev\` to scaffold it, or \`lunora env set <KEY> <VALUE>\`.`),e.info(`expected (from ${p}): ${i.join(", ")}`),{code:1,descriptors:[]};const l=i.filter(n=>!c.has(n)),v=[...c.values()].filter(n=>A(n.value)).map(n=>n.key),a=new Set(i),u=[...c.keys()].filter(n=>!a.has(n));for(const n of l)e.error(`missing: ${n} is in ${p} but not ${d}`);for(const n of v)e.error(`unset: ${n} still has a placeholder value`);for(const n of u)e.info(`extra: ${n} is set locally but not listed in ${p}`);return l.length===0&&v.length===0?(e.success(`env doctor: ${d} looks good (${String(c.size)} var(s)).`),{code:0,descriptors:[]}):{code:1,descriptors:[]}},ee=async r=>{let s=[];try{s=j(await x({projectRoot:r.cwd}))}catch{}const t=C(s).map(o=>o.key).filter(o=>b(o)),e=[...f(r.devVariablesPath).keys()].filter(o=>b(o));return[...new Set([...t,...e])]},re=async r=>{const{devVariablesPath:s,logger:t,options:e}=r;let o;if(e.key===void 0){if(o=await ee(r),o.length===0)return t.info("env generate: no locally-generatable secrets for this project. Name one explicitly: lunora env generate <KEY>"),{code:0,descriptors:[]}}else{if(!k.test(e.key))return t.error(`env: invalid key "${e.key}" — must match [A-Za-z_][A-Za-z0-9_]*`),{code:1,descriptors:[]};o=[e.key]}const i=o.map(c=>({key:c,value:Y()}));if(e.set===!0){let c=y(s);for(const l of i)c=P(c,l.key,l.value);return $(s,c),t.success(`env: generated ${String(i.length)} secret(s) into ${d}: ${i.map(l=>l.key).join(", ")}`),{code:0,descriptors:[]}}for(const c of i)process.stdout.write(`${c.key}=${c.value}
|
|
3
|
+
`);return{code:0,descriptors:[]}},te=async r=>{const s=r.cwd??process.cwd(),t={cwd:s,devVariablesPath:V(s,d),logger:r.logger,options:r};switch(r.subcommand){case"diff":return J(t);case"doctor":return Q(t);case"generate":return re(t);case"get":return O(t);case"list":return I(t);case"push":return W(t);case"set":return G(t);case"unset":return H(t);default:return r.logger.error(`env: unknown subcommand "${r.subcommand}"`),{code:1,descriptors:[]}}},oe=new Set(["diff","doctor","generate","get","list","push","set","unset"]),se=r=>typeof r=="string"&&oe.has(r),ue=q(({argument:r,cwd:s,logger:t,options:e})=>{const o=r[0];return se(o)?te({cwd:s,env:e.env,key:r[1],logger:t,prod:e.prod===!0,set:e.set===!0,subcommand:o,temporary:e.temporary===!0,value:r[2],yes:e.yes===!0}):(t.error(`env: unknown subcommand "${o??""}" — expected list | get | set | unset | push | diff | doctor | generate`),{code:1})});export{ue as execute,te as runEnvCommand};
|