@lunora/config 1.0.0-alpha.184 → 1.0.0-alpha.185

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 (36) hide show
  1. package/dist/cloudflare/index.mjs +1 -1
  2. package/dist/index.d.mts +25 -42
  3. package/dist/index.d.ts +25 -42
  4. package/dist/index.mjs +1 -1
  5. package/dist/packem_shared/{LUNORA_IGNORED_PATHS-BGbVUqw_.mjs → LUNORA_IGNORED_PATHS-BHABA9u-.mjs} +1 -1
  6. package/dist/packem_shared/PACKAGE_SECRETS_REGISTRY-pX2AR59E.mjs +1 -0
  7. package/dist/packem_shared/POLICY_SCAFFOLD_ENDPOINT-DJBuzyqL.mjs +1 -0
  8. package/dist/packem_shared/REQUIRED_COMPATIBILITY_DATE-lT_LQGqV.mjs +1 -0
  9. package/dist/packem_shared/SCHEMA_EDIT_ENDPOINT-OF4_A2xT.mjs +1 -0
  10. package/dist/packem_shared/applyAdditiveEdit-CH0VhMJ2.mjs +6 -0
  11. package/dist/packem_shared/buildPackageSecretsBlock-DZWcrhvs.mjs +19 -0
  12. package/dist/packem_shared/classifyPolicyEdit-D8NwrHxR.mjs +24 -0
  13. package/dist/packem_shared/collectWranglerSecretVariables-C6dWXkJK.mjs +1 -0
  14. package/dist/packem_shared/{detectFramework-DOn4PtpP.mjs → detectFramework-CUiVEHDQ.mjs} +1 -1
  15. package/dist/packem_shared/package-secrets-registry-C8gAjaaj.mjs +1 -0
  16. package/dist/packem_shared/parseDevVariable-teAAahVD.mjs +1 -0
  17. package/dist/packem_shared/parseSchema-D1Wbr1qv.mjs +1 -0
  18. package/dist/packem_shared/{policy-scaffold.d-fV3db0S_.d.mts → policy-scaffold.d-D2H4_G01.d.mts} +15 -3
  19. package/dist/packem_shared/{policy-scaffold.d-fV3db0S_.d.ts → policy-scaffold.d-D2H4_G01.d.ts} +15 -3
  20. package/dist/packem_shared/{serveJsonHandler-CB85A2S9.mjs → serveJsonHandler-Dv0EdCb9.mjs} +1 -1
  21. package/dist/packem_shared/write-atomic-wWIDQIcK.mjs +1 -0
  22. package/dist/studio-host/index.d.mts +36 -14
  23. package/dist/studio-host/index.d.ts +36 -14
  24. package/dist/studio-host/index.mjs +1 -1
  25. package/package.json +5 -5
  26. package/dist/packem_shared/PACKAGE_SECRETS_REGISTRY-BgmvEPA-.mjs +0 -1
  27. package/dist/packem_shared/POLICY_SCAFFOLD_ENDPOINT-C1gb9ykA.mjs +0 -1
  28. package/dist/packem_shared/REQUIRED_COMPATIBILITY_DATE-Lkm0xwgo.mjs +0 -1
  29. package/dist/packem_shared/SCHEMA_EDIT_ENDPOINT-CknH7oga.mjs +0 -1
  30. package/dist/packem_shared/applyAdditiveEdit-DPhNZsf2.mjs +0 -6
  31. package/dist/packem_shared/buildPackageSecretsBlock-J7bP1P-6.mjs +0 -19
  32. package/dist/packem_shared/classifyPolicyEdit-BfSiVpv-.mjs +0 -24
  33. package/dist/packem_shared/collectWranglerSecretVariables-WNirpc4n.mjs +0 -1
  34. package/dist/packem_shared/parseDevVariable-cacbGJkN.mjs +0 -1
  35. package/dist/packem_shared/parseSchema-B4nFDPzZ.mjs +0 -1
  36. package/dist/packem_shared/write-atomic-ooiPzStx.mjs +0 -1
@@ -1 +1 @@
1
- import{BINDING_MANIFEST_VERSION as o,buildBindingManifest as a}from"../packem_shared/BINDING_MANIFEST_VERSION-Cd00jVOf.mjs";import{C as n}from"../packem_shared/cloudflare-driver-BRcsrarS.mjs";import{collectExportGaps as i,reconcileWranglerBindings as E}from"../packem_shared/collectExportGaps-DHLZ7ulq.mjs";import{reconcileWranglerCompatibilityDate as c}from"../packem_shared/reconcileWranglerCompatibilityDate-7OO_xaKR.mjs";import{reconcileWranglerCrons as R}from"../packem_shared/reconcileWranglerCrons-COMb6ICf.mjs";import{REMOTE_ELIGIBLE_KEYS as f,injectRemoteFlags as p,isRemoteEnvEnabled as I,materializeRemoteWranglerConfig as W,planRemoteBindings as d,resolveRemoteEnabled as x}from"../packem_shared/REMOTE_ELIGIBLE_KEYS-D-edJjVY.mjs";import{WORKERS_CACHE_MIN_DATE as C,isCacheEnabled as A}from"../packem_shared/WORKERS_CACHE_MIN_DATE-0k9ABJtF.mjs";import{WRANGLER_FILES as L,findWranglerFile as T,readWranglerJsonc as b}from"../packem_shared/WRANGLER_FILES-UNW-xY5u.mjs";import{collectWranglerSecretVariables as S,scanWranglerVariablesForSecrets as B}from"../packem_shared/collectWranglerSecretVariables-WNirpc4n.mjs";import{wranglerToAlchemy as v}from"../packem_shared/wranglerToAlchemy-CX9nCwtu.mjs";import{REQUIRED_COMPATIBILITY_DATE as M,REQUIRED_FLAG as O,validateWrangler as V,validateWranglerConfig as h,validateWranglerProject as U,withTailConsumer as j}from"../packem_shared/REQUIRED_COMPATIBILITY_DATE-Lkm0xwgo.mjs";export{o as BINDING_MANIFEST_VERSION,n as CLOUDFLARE_DRIVER,f as REMOTE_ELIGIBLE_KEYS,M as REQUIRED_COMPATIBILITY_DATE,O as REQUIRED_FLAG,C as WORKERS_CACHE_MIN_DATE,L as WRANGLER_FILES,a as buildBindingManifest,i as collectExportGaps,S as collectWranglerSecretVariables,T as findWranglerFile,p as injectRemoteFlags,A as isCacheEnabled,I as isRemoteEnvEnabled,W as materializeRemoteWranglerConfig,d as planRemoteBindings,b as readWranglerJsonc,E as reconcileWranglerBindings,c as reconcileWranglerCompatibilityDate,R as reconcileWranglerCrons,x as resolveRemoteEnabled,B as scanWranglerVariablesForSecrets,V as validateWrangler,h as validateWranglerConfig,U as validateWranglerProject,j as withTailConsumer,v as wranglerToAlchemy};
1
+ import{BINDING_MANIFEST_VERSION as o,buildBindingManifest as a}from"../packem_shared/BINDING_MANIFEST_VERSION-Cd00jVOf.mjs";import{C as n}from"../packem_shared/cloudflare-driver-BRcsrarS.mjs";import{collectExportGaps as i,reconcileWranglerBindings as E}from"../packem_shared/collectExportGaps-DHLZ7ulq.mjs";import{reconcileWranglerCompatibilityDate as c}from"../packem_shared/reconcileWranglerCompatibilityDate-7OO_xaKR.mjs";import{reconcileWranglerCrons as R}from"../packem_shared/reconcileWranglerCrons-COMb6ICf.mjs";import{REMOTE_ELIGIBLE_KEYS as f,injectRemoteFlags as p,isRemoteEnvEnabled as I,materializeRemoteWranglerConfig as W,planRemoteBindings as d,resolveRemoteEnabled as x}from"../packem_shared/REMOTE_ELIGIBLE_KEYS-D-edJjVY.mjs";import{WORKERS_CACHE_MIN_DATE as C,isCacheEnabled as A}from"../packem_shared/WORKERS_CACHE_MIN_DATE-0k9ABJtF.mjs";import{WRANGLER_FILES as L,findWranglerFile as T,readWranglerJsonc as b}from"../packem_shared/WRANGLER_FILES-UNW-xY5u.mjs";import{collectWranglerSecretVariables as S,scanWranglerVariablesForSecrets as B}from"../packem_shared/collectWranglerSecretVariables-C6dWXkJK.mjs";import{wranglerToAlchemy as v}from"../packem_shared/wranglerToAlchemy-CX9nCwtu.mjs";import{REQUIRED_COMPATIBILITY_DATE as M,REQUIRED_FLAG as O,validateWrangler as V,validateWranglerConfig as h,validateWranglerProject as U,withTailConsumer as j}from"../packem_shared/REQUIRED_COMPATIBILITY_DATE-lT_LQGqV.mjs";export{o as BINDING_MANIFEST_VERSION,n as CLOUDFLARE_DRIVER,f as REMOTE_ELIGIBLE_KEYS,M as REQUIRED_COMPATIBILITY_DATE,O as REQUIRED_FLAG,C as WORKERS_CACHE_MIN_DATE,L as WRANGLER_FILES,a as buildBindingManifest,i as collectExportGaps,S as collectWranglerSecretVariables,T as findWranglerFile,p as injectRemoteFlags,A as isCacheEnabled,I as isRemoteEnvEnabled,W as materializeRemoteWranglerConfig,d as planRemoteBindings,b as readWranglerJsonc,E as reconcileWranglerBindings,c as reconcileWranglerCompatibilityDate,R as reconcileWranglerCrons,x as resolveRemoteEnabled,B as scanWranglerVariablesForSecrets,V as validateWrangler,h as validateWranglerConfig,U as validateWranglerProject,j as withTailConsumer,v as wranglerToAlchemy};
package/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@ export type { AgentIR, ContainerIR, WorkflowIR } from '@lunora/codegen';
3
3
  import { Writable } from 'node:stream';
4
4
  import { D as DeployDriver } from "./packem_shared/schema-info.d-DS0bUsWE.mjs";
5
5
  export { type a as DeployRequest, type b as DevRequest, type c as DiscoverSchemaInfoResult, type d as DriverContext, type e as DriverToolchain, type f as InferOptions, type g as InferredAgent, type I as InferredBindings, type h as InferredContainer, type i as InferredWorkflow, type N as NamedResource, type P as ProvisionResult, type R as ResourceGraph, type S as SchemaInfo, type j as SecretRequest, type k as ShardNamespaceResource, type T as TailRequest, type l as ToolchainCommand, m as discoverSchemaInfo, n as inferLunoraBindings, p as packageNamesFromBindings } from "./packem_shared/schema-info.d-DS0bUsWE.mjs";
6
- export { type A as AdditivePolicyEdit, type D as DestructivePolicyEdit, type P as PolicyEdit, type a as PolicyScaffoldFailureReason, type b as ScaffoldFileResult, type S as ScaffoldPolicyEdit, type c as WireResult, type W as WireRlsEdit, d as classifyPolicyEdit, s as scaffoldPolicyFile, w as wireRlsIntoProcedure } from "./packem_shared/policy-scaffold.d-fV3db0S_.mjs";
6
+ export { type A as AdditivePolicyEdit, type D as DestructivePolicyEdit, type P as PolicyEdit, type a as PolicyScaffoldFailureReason, type b as ScaffoldFileResult, type S as ScaffoldPolicyEdit, type c as WireResult, type W as WireRlsEdit, d as classifyPolicyEdit, r as resolveServerModule, s as scaffoldPolicyFile, w as wireRlsIntoProcedure } from "./packem_shared/policy-scaffold.d-D2H4_G01.mjs";
7
7
  interface DiscoverAgentInfoResult {
8
8
  /** Discovered agent definitions; `[]` when none are declared or parsing failed. */
9
9
  agents: ReadonlyArray<AgentIR>;
@@ -235,6 +235,19 @@ interface FrameworkDetection {
235
235
  * best-effort reader instead of re-parsing `package.json` themselves.
236
236
  */
237
237
  declare const readProjectDependencyNames: (root: string) => ReadonlySet<string>;
238
+ /**
239
+ * Whether the project depends on the unscoped `lunorash` umbrella rather than
240
+ * the granular `@lunora/*` packages.
241
+ *
242
+ * Every generator that writes an import INTO the user's project has to ask:
243
+ * an umbrella-only install — the default for every starter template — never
244
+ * installs `@lunora/server`, so under pnpm's strict layout a scaffolded
245
+ * `from "@lunora/server"` is unresolvable and the worker stops bundling.
246
+ * Codegen answers the same question from its own dependency set
247
+ * (`dependencies.has("lunorash")`); this is that answer for every consumer
248
+ * that has only a project root.
249
+ */
250
+ declare const projectUsesUmbrella: (root: string) => boolean;
238
251
  /**
239
252
  * Detect which meta-framework a project uses by inspecting its `package.json`
240
253
  * dependencies, and classify it under void's class-A/B/C model (PLAN4 §3).
@@ -670,33 +683,6 @@ declare const runScriptArgsFor: (manager: PackageManager, script: string) => {
670
683
  };
671
684
  /** The shell command that runs a project script with `manager` (`pnpm dev`, `npm run dev`, …). */
672
685
  declare const runScriptCommand: (manager: PackageManager, script: string) => string;
673
- /**
674
- * Per-package secret-requirements registry for `.dev.vars` scaffolding.
675
- *
676
- * Each entry maps a `@lunora/*` package name → the secrets it requires at
677
- * runtime, expressed as `{ key, description, docsUrl }` records. The scaffolder
678
- * in {@link ./scaffold-dev-variables} reads this registry to emit package-aware
679
- * `.dev.vars.example` entries (placeholders + inline doc-pointer comments).
680
- *
681
- * ## Adding a new add-on
682
- *
683
- * When a new `@lunora/*` package requires runtime secrets, add one entry to
684
- * {@link PACKAGE_SECRETS_REGISTRY} keyed by its exact npm package name. Each
685
- * `SecretEntry` in the array needs:
686
- *
687
- * - `key` — the env-var name the package reads from `env` (e.g. `RESEND_API_KEY`).
688
- * - `description` — one line describing the secret and how to obtain it.
689
- * - `docsUrl` — a stable URL to the package/provider docs.
690
- *
691
- * The registry lives in `@lunora/config` so that add-ons themselves never need
692
- * to depend on it (no circular coupling). Add-ons document their secrets in
693
- * their own READMEs; the registry duplicates that knowledge in a machine-readable
694
- * form that the scaffolder can consume.
695
- *
696
- * **Never write a real secret value** in this file — `placeholderValue` entries
697
- * are the only allowed values (they must pass `isPlaceholderValue` from
698
- * scaffold-dev-variables).
699
- */
700
686
  /** A single secret variable required by a package. */
701
687
  interface SecretEntry {
702
688
  /** One sentence describing what this secret is and how to obtain it. */
@@ -725,15 +711,6 @@ interface SecretEntry {
725
711
  * given the set of detected capability package names.
726
712
  */
727
713
  declare const PACKAGE_SECRETS_REGISTRY: Readonly<Record<string, ReadonlyArray<SecretEntry>>>;
728
- /**
729
- * Collect all secret entries required by the given set of package names. The
730
- * order follows the order of `packageNames` (stable, predictable output), and
731
- * within each package the entries are returned in registry declaration order.
732
- *
733
- * Only packages present in {@link PACKAGE_SECRETS_REGISTRY} contribute entries;
734
- * unknown package names are silently ignored — this makes the call site resilient
735
- * to future capability flags whose packages have no secrets.
736
- */
737
714
  declare const secretsForPackages: (packageNames: ReadonlyArray<string>) => SecretEntry[];
738
715
  /**
739
716
  * The two channels this needs from a caller's logger. Deliberately structural
@@ -940,10 +917,16 @@ declare const requiredSecrets: (packageNames: ReadonlyArray<string>) => SecretEn
940
917
  */
941
918
  declare const isPlaceholderValue: (value: string) => boolean;
942
919
  /**
943
- * True for a secret-looking key whose value Lunora can mint locally (a random
944
- * 32-byte hex, like `openssl rand -hex 32`) — e.g. `AUTH_SECRET`,
945
- * `LUNORA_ADMIN_TOKEN`, `STORAGE_SIGNING_SECRET`. False for provider-issued keys
946
- * ({@link PROVIDER_SECRET_KEYS}) and any non-secret key.
920
+ * True for a secret key the registry says Lunora can mint locally (a random
921
+ * 32-byte hex, like `openssl rand -hex 32`) — `AUTH_SECRET`,
922
+ * `LUNORA_ADMIN_TOKEN`, `STORAGE_SIGNING_SECRET`,
923
+ *
924
+ * Registry membership, NOT the key's name shape, is the rule. A secret-looking
925
+ * key nothing in the registry declares (`OPENAI_API_KEY`,
926
+ * `GITHUB_CLIENT_SECRET`, a project's own `*_TOKEN`) is provider-issued as far
927
+ * as Lunora knows, so minting for it would write a value the provider rejects at
928
+ * runtime — over the developer's own half-filled `.dev.vars` — and hide the gap
929
+ * from `lunora env doctor`, whose job is to report it as unfilled.
947
930
  */
948
931
  declare const isMintableSecretKey: (key: string) => boolean;
949
932
  /** Mint a fresh strong secret value — 64 hex chars (32 bytes), like `openssl rand -hex 32`. */
@@ -1278,4 +1261,4 @@ declare const badgeWidth: (_spec: BadgeSpec) => number;
1278
1261
  declare const paintBadge: (spec: BadgeSpec) => string;
1279
1262
  /** Dim continuation text (a step's chosen answer, shown under the question). */
1280
1263
  declare const paintAnswer: (text: string) => string;
1281
- export { ACCENT, AGENT_MODE_ENV, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentDetection, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, CODEGEN_ENV, type ClaimDevServerStateResult, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEFAULT_DEPLOY_TARGET, DEV_BINDINGS_FILE, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DeployDriver, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type HookLogger, type HookSpawnDescriptor, type HookSpawner, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_IGNORED_PATHS, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LintIgnoreOutcome, type LintIgnoreStatus, type LintTool, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type PackageManager, type PackageManagerProbe, type ParseSchemaResult, type PostCodegenHookResult, ROOT_SKILL_NAME, type RemotePreference, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, addArgsFor, applyAdditiveEdit, applyLintIgnores, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, createConfirm, deployTargetIds, detectAgentRules, detectAiAgent, detectFramework, detectInstalledManagers, detectLintTools, detectPackageManager, discoverAgentInfo, discoverContainerInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, escapeRegExp, execArgsFor, fillDevSecrets, formatLunoraEvent, generateSecretValue, installArgsFor, interpretRemote, isCodegenDisabled, isDevServerReady, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, isRunnableTarget, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readProjectTarget, removeDevVariableLine, requiredSecrets, resolveDeployDriver, resolveProjectTarget, resolveTargetOrThrow, runPostCodegenHook, runScriptArgsFor, runScriptCommand, runnableTargetIds, secretsForPackages, streamContainerLogs, updateDevServerState, upsertDevVariableLine, writeDevServerState, writeDevVariablesFileAtomically, writeLinkedProject };
1264
+ export { ACCENT, AGENT_MODE_ENV, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentDetection, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, CODEGEN_ENV, type ClaimDevServerStateResult, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEFAULT_DEPLOY_TARGET, DEV_BINDINGS_FILE, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DeployDriver, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type HookLogger, type HookSpawnDescriptor, type HookSpawner, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_IGNORED_PATHS, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LintIgnoreOutcome, type LintIgnoreStatus, type LintTool, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type PackageManager, type PackageManagerProbe, type ParseSchemaResult, type PostCodegenHookResult, ROOT_SKILL_NAME, type RemotePreference, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, addArgsFor, applyAdditiveEdit, applyLintIgnores, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, createConfirm, deployTargetIds, detectAgentRules, detectAiAgent, detectFramework, detectInstalledManagers, detectLintTools, detectPackageManager, discoverAgentInfo, discoverContainerInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, escapeRegExp, execArgsFor, fillDevSecrets, formatLunoraEvent, generateSecretValue, installArgsFor, interpretRemote, isCodegenDisabled, isDevServerReady, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, isRunnableTarget, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, projectUsesUmbrella, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readProjectTarget, removeDevVariableLine, requiredSecrets, resolveDeployDriver, resolveProjectTarget, resolveTargetOrThrow, runPostCodegenHook, runScriptArgsFor, runScriptCommand, runnableTargetIds, secretsForPackages, streamContainerLogs, updateDevServerState, upsertDevVariableLine, writeDevServerState, writeDevVariablesFileAtomically, writeLinkedProject };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export type { AgentIR, ContainerIR, WorkflowIR } from '@lunora/codegen';
3
3
  import { Writable } from 'node:stream';
4
4
  import { D as DeployDriver } from "./packem_shared/schema-info.d-DS0bUsWE.js";
5
5
  export { type a as DeployRequest, type b as DevRequest, type c as DiscoverSchemaInfoResult, type d as DriverContext, type e as DriverToolchain, type f as InferOptions, type g as InferredAgent, type I as InferredBindings, type h as InferredContainer, type i as InferredWorkflow, type N as NamedResource, type P as ProvisionResult, type R as ResourceGraph, type S as SchemaInfo, type j as SecretRequest, type k as ShardNamespaceResource, type T as TailRequest, type l as ToolchainCommand, m as discoverSchemaInfo, n as inferLunoraBindings, p as packageNamesFromBindings } from "./packem_shared/schema-info.d-DS0bUsWE.js";
6
- export { type A as AdditivePolicyEdit, type D as DestructivePolicyEdit, type P as PolicyEdit, type a as PolicyScaffoldFailureReason, type b as ScaffoldFileResult, type S as ScaffoldPolicyEdit, type c as WireResult, type W as WireRlsEdit, d as classifyPolicyEdit, s as scaffoldPolicyFile, w as wireRlsIntoProcedure } from "./packem_shared/policy-scaffold.d-fV3db0S_.js";
6
+ export { type A as AdditivePolicyEdit, type D as DestructivePolicyEdit, type P as PolicyEdit, type a as PolicyScaffoldFailureReason, type b as ScaffoldFileResult, type S as ScaffoldPolicyEdit, type c as WireResult, type W as WireRlsEdit, d as classifyPolicyEdit, r as resolveServerModule, s as scaffoldPolicyFile, w as wireRlsIntoProcedure } from "./packem_shared/policy-scaffold.d-D2H4_G01.js";
7
7
  interface DiscoverAgentInfoResult {
8
8
  /** Discovered agent definitions; `[]` when none are declared or parsing failed. */
9
9
  agents: ReadonlyArray<AgentIR>;
@@ -235,6 +235,19 @@ interface FrameworkDetection {
235
235
  * best-effort reader instead of re-parsing `package.json` themselves.
236
236
  */
237
237
  declare const readProjectDependencyNames: (root: string) => ReadonlySet<string>;
238
+ /**
239
+ * Whether the project depends on the unscoped `lunorash` umbrella rather than
240
+ * the granular `@lunora/*` packages.
241
+ *
242
+ * Every generator that writes an import INTO the user's project has to ask:
243
+ * an umbrella-only install — the default for every starter template — never
244
+ * installs `@lunora/server`, so under pnpm's strict layout a scaffolded
245
+ * `from "@lunora/server"` is unresolvable and the worker stops bundling.
246
+ * Codegen answers the same question from its own dependency set
247
+ * (`dependencies.has("lunorash")`); this is that answer for every consumer
248
+ * that has only a project root.
249
+ */
250
+ declare const projectUsesUmbrella: (root: string) => boolean;
238
251
  /**
239
252
  * Detect which meta-framework a project uses by inspecting its `package.json`
240
253
  * dependencies, and classify it under void's class-A/B/C model (PLAN4 §3).
@@ -670,33 +683,6 @@ declare const runScriptArgsFor: (manager: PackageManager, script: string) => {
670
683
  };
671
684
  /** The shell command that runs a project script with `manager` (`pnpm dev`, `npm run dev`, …). */
672
685
  declare const runScriptCommand: (manager: PackageManager, script: string) => string;
673
- /**
674
- * Per-package secret-requirements registry for `.dev.vars` scaffolding.
675
- *
676
- * Each entry maps a `@lunora/*` package name → the secrets it requires at
677
- * runtime, expressed as `{ key, description, docsUrl }` records. The scaffolder
678
- * in {@link ./scaffold-dev-variables} reads this registry to emit package-aware
679
- * `.dev.vars.example` entries (placeholders + inline doc-pointer comments).
680
- *
681
- * ## Adding a new add-on
682
- *
683
- * When a new `@lunora/*` package requires runtime secrets, add one entry to
684
- * {@link PACKAGE_SECRETS_REGISTRY} keyed by its exact npm package name. Each
685
- * `SecretEntry` in the array needs:
686
- *
687
- * - `key` — the env-var name the package reads from `env` (e.g. `RESEND_API_KEY`).
688
- * - `description` — one line describing the secret and how to obtain it.
689
- * - `docsUrl` — a stable URL to the package/provider docs.
690
- *
691
- * The registry lives in `@lunora/config` so that add-ons themselves never need
692
- * to depend on it (no circular coupling). Add-ons document their secrets in
693
- * their own READMEs; the registry duplicates that knowledge in a machine-readable
694
- * form that the scaffolder can consume.
695
- *
696
- * **Never write a real secret value** in this file — `placeholderValue` entries
697
- * are the only allowed values (they must pass `isPlaceholderValue` from
698
- * scaffold-dev-variables).
699
- */
700
686
  /** A single secret variable required by a package. */
701
687
  interface SecretEntry {
702
688
  /** One sentence describing what this secret is and how to obtain it. */
@@ -725,15 +711,6 @@ interface SecretEntry {
725
711
  * given the set of detected capability package names.
726
712
  */
727
713
  declare const PACKAGE_SECRETS_REGISTRY: Readonly<Record<string, ReadonlyArray<SecretEntry>>>;
728
- /**
729
- * Collect all secret entries required by the given set of package names. The
730
- * order follows the order of `packageNames` (stable, predictable output), and
731
- * within each package the entries are returned in registry declaration order.
732
- *
733
- * Only packages present in {@link PACKAGE_SECRETS_REGISTRY} contribute entries;
734
- * unknown package names are silently ignored — this makes the call site resilient
735
- * to future capability flags whose packages have no secrets.
736
- */
737
714
  declare const secretsForPackages: (packageNames: ReadonlyArray<string>) => SecretEntry[];
738
715
  /**
739
716
  * The two channels this needs from a caller's logger. Deliberately structural
@@ -940,10 +917,16 @@ declare const requiredSecrets: (packageNames: ReadonlyArray<string>) => SecretEn
940
917
  */
941
918
  declare const isPlaceholderValue: (value: string) => boolean;
942
919
  /**
943
- * True for a secret-looking key whose value Lunora can mint locally (a random
944
- * 32-byte hex, like `openssl rand -hex 32`) — e.g. `AUTH_SECRET`,
945
- * `LUNORA_ADMIN_TOKEN`, `STORAGE_SIGNING_SECRET`. False for provider-issued keys
946
- * ({@link PROVIDER_SECRET_KEYS}) and any non-secret key.
920
+ * True for a secret key the registry says Lunora can mint locally (a random
921
+ * 32-byte hex, like `openssl rand -hex 32`) — `AUTH_SECRET`,
922
+ * `LUNORA_ADMIN_TOKEN`, `STORAGE_SIGNING_SECRET`,
923
+ *
924
+ * Registry membership, NOT the key's name shape, is the rule. A secret-looking
925
+ * key nothing in the registry declares (`OPENAI_API_KEY`,
926
+ * `GITHUB_CLIENT_SECRET`, a project's own `*_TOKEN`) is provider-issued as far
927
+ * as Lunora knows, so minting for it would write a value the provider rejects at
928
+ * runtime — over the developer's own half-filled `.dev.vars` — and hide the gap
929
+ * from `lunora env doctor`, whose job is to report it as unfilled.
947
930
  */
948
931
  declare const isMintableSecretKey: (key: string) => boolean;
949
932
  /** Mint a fresh strong secret value — 64 hex chars (32 bytes), like `openssl rand -hex 32`. */
@@ -1278,4 +1261,4 @@ declare const badgeWidth: (_spec: BadgeSpec) => number;
1278
1261
  declare const paintBadge: (spec: BadgeSpec) => string;
1279
1262
  /** Dim continuation text (a step's chosen answer, shown under the question). */
1280
1263
  declare const paintAnswer: (text: string) => string;
1281
- export { ACCENT, AGENT_MODE_ENV, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentDetection, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, CODEGEN_ENV, type ClaimDevServerStateResult, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEFAULT_DEPLOY_TARGET, DEV_BINDINGS_FILE, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DeployDriver, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type HookLogger, type HookSpawnDescriptor, type HookSpawner, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_IGNORED_PATHS, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LintIgnoreOutcome, type LintIgnoreStatus, type LintTool, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type PackageManager, type PackageManagerProbe, type ParseSchemaResult, type PostCodegenHookResult, ROOT_SKILL_NAME, type RemotePreference, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, addArgsFor, applyAdditiveEdit, applyLintIgnores, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, createConfirm, deployTargetIds, detectAgentRules, detectAiAgent, detectFramework, detectInstalledManagers, detectLintTools, detectPackageManager, discoverAgentInfo, discoverContainerInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, escapeRegExp, execArgsFor, fillDevSecrets, formatLunoraEvent, generateSecretValue, installArgsFor, interpretRemote, isCodegenDisabled, isDevServerReady, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, isRunnableTarget, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readProjectTarget, removeDevVariableLine, requiredSecrets, resolveDeployDriver, resolveProjectTarget, resolveTargetOrThrow, runPostCodegenHook, runScriptArgsFor, runScriptCommand, runnableTargetIds, secretsForPackages, streamContainerLogs, updateDevServerState, upsertDevVariableLine, writeDevServerState, writeDevVariablesFileAtomically, writeLinkedProject };
1264
+ export { ACCENT, AGENT_MODE_ENV, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentDetection, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, CODEGEN_ENV, type ClaimDevServerStateResult, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEFAULT_DEPLOY_TARGET, DEV_BINDINGS_FILE, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DeployDriver, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type HookLogger, type HookSpawnDescriptor, type HookSpawner, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_IGNORED_PATHS, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LintIgnoreOutcome, type LintIgnoreStatus, type LintTool, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type PackageManager, type PackageManagerProbe, type ParseSchemaResult, type PostCodegenHookResult, ROOT_SKILL_NAME, type RemotePreference, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, addArgsFor, applyAdditiveEdit, applyLintIgnores, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, createConfirm, deployTargetIds, detectAgentRules, detectAiAgent, detectFramework, detectInstalledManagers, detectLintTools, detectPackageManager, discoverAgentInfo, discoverContainerInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, escapeRegExp, execArgsFor, fillDevSecrets, formatLunoraEvent, generateSecretValue, installArgsFor, interpretRemote, isCodegenDisabled, isDevServerReady, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, isRunnableTarget, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, projectUsesUmbrella, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readProjectTarget, removeDevVariableLine, requiredSecrets, resolveDeployDriver, resolveProjectTarget, resolveTargetOrThrow, runPostCodegenHook, runScriptArgsFor, runScriptCommand, runnableTargetIds, secretsForPackages, streamContainerLogs, updateDevServerState, upsertDevVariableLine, writeDevServerState, writeDevVariablesFileAtomically, writeLinkedProject };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{AGENT_MODE_ENV as t,detectAiAgent as o}from"./packem_shared/AGENT_MODE_ENV-D8MvSwPE.mjs";import{discoverAgentInfo as i}from"./packem_shared/discoverAgentInfo-CTdCSfYM.mjs";import{AGENT_RULES_DIR as s,AGENT_RULES_HINT as n,AGENT_RULES_HINT_ENV as p,LUNORA_SKILL_NAMES as l,ROOT_SKILL_NAME as _,claimAgentRulesHint as c,detectAgentRules as d}from"./packem_shared/AGENT_RULES_DIR-3-Sx1gHU.mjs";import{CODEGEN_ENV as A,isCodegenDisabled as D}from"./packem_shared/CODEGEN_ENV-ZsCxV1kP.mjs";import{discoverContainerInfo as f}from"./packem_shared/discoverContainerInfo-EhZtEBQs.mjs";import{streamContainerLogs as N}from"./packem_shared/streamContainerLogs-0nko1qpv.mjs";import{detectFramework as T,readProjectDependencyNames as I}from"./packem_shared/detectFramework-DOn4PtpP.mjs";import{DEV_BINDINGS_FILE as g,DEV_DAEMON_ENV as x,DEV_HANDOFF_ENV as V,DEV_LOG_FILE as P,DEV_LOG_FILE_ENV as F,DEV_STATE_DIR as u,DEV_STATE_FILE as O,claimDevServerState as C,clearDevServerState as G,isDevServerReady as U,isProcessAlive as b,isRecordedProcessCurrent as y,readDevServerState as M,readLiveDevServerState as k,updateDevServerState as B,writeDevServerState as w}from"./packem_shared/DEV_BINDINGS_FILE-pyOiNLP4.mjs";import{DEV_VARS_EXAMPLE_FILE as K,DEV_VARS_FILE as j,DEV_VARS_KEY_PATTERN as h,escapeRegExp as Y,parseDevVariableEntries as W,removeDevVariableLine as J,upsertDevVariableLine as q}from"./packem_shared/DEV_VARS_EXAMPLE_FILE-CqLorAxT.mjs";import{DEFAULT_DEPLOY_TARGET as z,deployTargetIds as Q,isRunnableTarget as Z,resolveDeployDriver as $,runnableTargetIds as ee}from"./packem_shared/DEFAULT_DEPLOY_TARGET-DpDlbJNG.mjs";import{inferLunoraBindings as te,packageNamesFromBindings as oe}from"./packem_shared/inferLunoraBindings-7kPfAt6p.mjs";import{LINKED_PROJECT_DIR as ie,LINKED_PROJECT_FILE as Ee,readLinkedProject as se,writeLinkedProject as ne}from"./packem_shared/LINKED_PROJECT_DIR-Ba5qPEwo.mjs";import{LUNORA_IGNORED_PATHS as le,applyLintIgnores as _e,detectLintTools as ce}from"./packem_shared/LUNORA_IGNORED_PATHS-BGbVUqw_.mjs";import{LUNORA_EVENT_SOURCE as me,formatLunoraEvent as Ae}from"./packem_shared/LUNORA_EVENT_SOURCE-DYdcDU9G.mjs";import{default as Se}from"./packem_shared/LunoraReporter-f277GLNT.mjs";import{addArgsFor as Le,detectInstalledManagers as Ne,detectPackageManager as ve,execArgsFor as Te,installArgsFor as Ie,runScriptArgsFor as Re,runScriptCommand as ge}from"./packem_shared/addArgsFor-B4D4zvM0.mjs";import{PACKAGE_SECRETS_REGISTRY as Ve,secretsForPackages as Pe}from"./packem_shared/PACKAGE_SECRETS_REGISTRY-BgmvEPA-.mjs";import{runPostCodegenHook as ue}from"./packem_shared/runPostCodegenHook-BF3XTBFz.mjs";import{LUNORA_CONFIG_FILE as Ce,interpretRemote as Ge,readProjectRemotePreference as Ue,readProjectTarget as be,resolveProjectTarget as ye,resolveTargetOrThrow as Me}from"./packem_shared/LUNORA_CONFIG_FILE-CJqaLqNo.mjs";import{createConfirm as Be,isInteractive as we,promptMultiSelect as He,promptSelect as Ke,promptText as je,promptYesNo as he}from"./packem_shared/createConfirm-D5mKTMHj.mjs";import{buildPackageSecretsBlock as We,ensureDevVariables as Je,ensureDevVarsExample as qe,fillDevSecrets as Xe,generateSecretValue as ze,isMintableSecretKey as Qe,isPlaceholderValue as Ze,planDevSecretsFill as $e,planDevVariablesAugment as er,planDevVariablesScaffold as rr,requiredSecrets as tr,writeDevVariablesFileAtomically as or}from"./packem_shared/buildPackageSecretsBlock-J7bP1P-6.mjs";import{applyAdditiveEdit as ir,classifyEdit as Er}from"./packem_shared/applyAdditiveEdit-DPhNZsf2.mjs";import{parseSchema as nr}from"./packem_shared/parseSchema-B4nFDPzZ.mjs";import{classifyPolicyEdit as lr,scaffoldPolicyFile as _r,wireRlsIntoProcedure as cr}from"./packem_shared/classifyPolicyEdit-BfSiVpv-.mjs";import{discoverSchemaInfo as mr}from"./packem_shared/discoverSchemaInfo-Bg2CUZXG.mjs";import{ACCENT as Dr,BADGES as Sr,BADGE_COLUMN_WIDTH as fr,LUNA_ART as Lr,LUNA_BUNNY as Nr,LUNA_NAME as vr,LUNA_SIGNOFF as Tr,STEP_BADGE_NAMES as Ir,badgeLead as Rr,badgeWidth as gr,padBadge as xr,paintAnswer as Vr,paintBadge as Pr}from"./packem_shared/ACCENT-CotPTfv7.mjs";import{discoverWorkflowInfo as ur}from"./packem_shared/discoverWorkflowInfo-BsPvlo6O.mjs";export{Dr as ACCENT,t as AGENT_MODE_ENV,s as AGENT_RULES_DIR,n as AGENT_RULES_HINT,p as AGENT_RULES_HINT_ENV,Sr as BADGES,fr as BADGE_COLUMN_WIDTH,A as CODEGEN_ENV,z as DEFAULT_DEPLOY_TARGET,g as DEV_BINDINGS_FILE,x as DEV_DAEMON_ENV,V as DEV_HANDOFF_ENV,P as DEV_LOG_FILE,F as DEV_LOG_FILE_ENV,u as DEV_STATE_DIR,O as DEV_STATE_FILE,K as DEV_VARS_EXAMPLE_FILE,j as DEV_VARS_FILE,h as DEV_VARS_KEY_PATTERN,ie as LINKED_PROJECT_DIR,Ee as LINKED_PROJECT_FILE,Lr as LUNA_ART,Nr as LUNA_BUNNY,vr as LUNA_NAME,Tr as LUNA_SIGNOFF,Ce as LUNORA_CONFIG_FILE,me as LUNORA_EVENT_SOURCE,le as LUNORA_IGNORED_PATHS,l as LUNORA_SKILL_NAMES,Se as LunoraReporter,Ve as PACKAGE_SECRETS_REGISTRY,_ as ROOT_SKILL_NAME,Ir as STEP_BADGE_NAMES,Le as addArgsFor,ir as applyAdditiveEdit,_e as applyLintIgnores,Rr as badgeLead,gr as badgeWidth,We as buildPackageSecretsBlock,c as claimAgentRulesHint,C as claimDevServerState,Er as classifyEdit,lr as classifyPolicyEdit,G as clearDevServerState,Be as createConfirm,Q as deployTargetIds,d as detectAgentRules,o as detectAiAgent,T as detectFramework,Ne as detectInstalledManagers,ce as detectLintTools,ve as detectPackageManager,i as discoverAgentInfo,f as discoverContainerInfo,mr as discoverSchemaInfo,ur as discoverWorkflowInfo,Je as ensureDevVariables,qe as ensureDevVarsExample,Y as escapeRegExp,Te as execArgsFor,Xe as fillDevSecrets,Ae as formatLunoraEvent,ze as generateSecretValue,te as inferLunoraBindings,Ie as installArgsFor,Ge as interpretRemote,D as isCodegenDisabled,U as isDevServerReady,we as isInteractive,Qe as isMintableSecretKey,Ze as isPlaceholderValue,b as isProcessAlive,y as isRecordedProcessCurrent,Z as isRunnableTarget,oe as packageNamesFromBindings,xr as padBadge,Vr as paintAnswer,Pr as paintBadge,W as parseDevVariableEntries,nr as parseSchema,$e as planDevSecretsFill,er as planDevVariablesAugment,rr as planDevVariablesScaffold,He as promptMultiSelect,Ke as promptSelect,je as promptText,he as promptYesNo,M as readDevServerState,se as readLinkedProject,k as readLiveDevServerState,I as readProjectDependencyNames,Ue as readProjectRemotePreference,be as readProjectTarget,J as removeDevVariableLine,tr as requiredSecrets,$ as resolveDeployDriver,ye as resolveProjectTarget,Me as resolveTargetOrThrow,ue as runPostCodegenHook,Re as runScriptArgsFor,ge as runScriptCommand,ee as runnableTargetIds,_r as scaffoldPolicyFile,Pe as secretsForPackages,N as streamContainerLogs,B as updateDevServerState,q as upsertDevVariableLine,cr as wireRlsIntoProcedure,w as writeDevServerState,or as writeDevVariablesFileAtomically,ne as writeLinkedProject};
1
+ import{AGENT_MODE_ENV as o,detectAiAgent as t}from"./packem_shared/AGENT_MODE_ENV-D8MvSwPE.mjs";import{discoverAgentInfo as s}from"./packem_shared/discoverAgentInfo-CTdCSfYM.mjs";import{AGENT_RULES_DIR as E,AGENT_RULES_HINT as l,AGENT_RULES_HINT_ENV as n,LUNORA_SKILL_NAMES as p,ROOT_SKILL_NAME as _,claimAgentRulesHint as c,detectAgentRules as d}from"./packem_shared/AGENT_RULES_DIR-3-Sx1gHU.mjs";import{CODEGEN_ENV as A,isCodegenDisabled as D}from"./packem_shared/CODEGEN_ENV-ZsCxV1kP.mjs";import{discoverContainerInfo as f}from"./packem_shared/discoverContainerInfo-EhZtEBQs.mjs";import{streamContainerLogs as N}from"./packem_shared/streamContainerLogs-0nko1qpv.mjs";import{detectFramework as T,projectUsesUmbrella as I,readProjectDependencyNames as R}from"./packem_shared/detectFramework-CUiVEHDQ.mjs";import{DEV_BINDINGS_FILE as x,DEV_DAEMON_ENV as V,DEV_HANDOFF_ENV as P,DEV_LOG_FILE as u,DEV_LOG_FILE_ENV as F,DEV_STATE_DIR as O,DEV_STATE_FILE as C,claimDevServerState as G,clearDevServerState as U,isDevServerReady as b,isProcessAlive as M,isRecordedProcessCurrent as y,readDevServerState as k,readLiveDevServerState as B,updateDevServerState as w,writeDevServerState as j}from"./packem_shared/DEV_BINDINGS_FILE-pyOiNLP4.mjs";import{DEV_VARS_EXAMPLE_FILE as K,DEV_VARS_FILE as h,DEV_VARS_KEY_PATTERN as Y,escapeRegExp as W,parseDevVariableEntries as J,removeDevVariableLine as q,upsertDevVariableLine as X}from"./packem_shared/DEV_VARS_EXAMPLE_FILE-CqLorAxT.mjs";import{DEFAULT_DEPLOY_TARGET as Q,deployTargetIds as Z,isRunnableTarget as $,resolveDeployDriver as ee,runnableTargetIds as re}from"./packem_shared/DEFAULT_DEPLOY_TARGET-DpDlbJNG.mjs";import{inferLunoraBindings as te,packageNamesFromBindings as ae}from"./packem_shared/inferLunoraBindings-7kPfAt6p.mjs";import{LINKED_PROJECT_DIR as ie,LINKED_PROJECT_FILE as Ee,readLinkedProject as le,writeLinkedProject as ne}from"./packem_shared/LINKED_PROJECT_DIR-Ba5qPEwo.mjs";import{LUNORA_IGNORED_PATHS as _e,applyLintIgnores as ce,detectLintTools as de}from"./packem_shared/LUNORA_IGNORED_PATHS-BHABA9u-.mjs";import{LUNORA_EVENT_SOURCE as Ae,formatLunoraEvent as De}from"./packem_shared/LUNORA_EVENT_SOURCE-DYdcDU9G.mjs";import{default as fe}from"./packem_shared/LunoraReporter-f277GLNT.mjs";import{addArgsFor as Ne,detectInstalledManagers as ve,detectPackageManager as Te,execArgsFor as Ie,installArgsFor as Re,runScriptArgsFor as ge,runScriptCommand as xe}from"./packem_shared/addArgsFor-B4D4zvM0.mjs";import{P as Pe,s as ue}from"./packem_shared/package-secrets-registry-C8gAjaaj.mjs";import{runPostCodegenHook as Oe}from"./packem_shared/runPostCodegenHook-BF3XTBFz.mjs";import{LUNORA_CONFIG_FILE as Ge,interpretRemote as Ue,readProjectRemotePreference as be,readProjectTarget as Me,resolveProjectTarget as ye,resolveTargetOrThrow as ke}from"./packem_shared/LUNORA_CONFIG_FILE-CJqaLqNo.mjs";import{createConfirm as we,isInteractive as je,promptMultiSelect as He,promptSelect as Ke,promptText as he,promptYesNo as Ye}from"./packem_shared/createConfirm-D5mKTMHj.mjs";import{buildPackageSecretsBlock as Je,ensureDevVariables as qe,ensureDevVarsExample as Xe,fillDevSecrets as ze,generateSecretValue as Qe,isMintableSecretKey as Ze,isPlaceholderValue as $e,planDevSecretsFill as er,planDevVariablesAugment as rr,planDevVariablesScaffold as or,requiredSecrets as tr,writeDevVariablesFileAtomically as ar}from"./packem_shared/buildPackageSecretsBlock-DZWcrhvs.mjs";import{applyAdditiveEdit as ir,classifyEdit as Er}from"./packem_shared/applyAdditiveEdit-CH0VhMJ2.mjs";import{parseSchema as nr}from"./packem_shared/parseSchema-D1Wbr1qv.mjs";import{classifyPolicyEdit as _r,resolveServerModule as cr,scaffoldPolicyFile as dr,wireRlsIntoProcedure as mr}from"./packem_shared/classifyPolicyEdit-D8NwrHxR.mjs";import{discoverSchemaInfo as Dr}from"./packem_shared/discoverSchemaInfo-Bg2CUZXG.mjs";import{ACCENT as fr,BADGES as Lr,BADGE_COLUMN_WIDTH as Nr,LUNA_ART as vr,LUNA_BUNNY as Tr,LUNA_NAME as Ir,LUNA_SIGNOFF as Rr,STEP_BADGE_NAMES as gr,badgeLead as xr,badgeWidth as Vr,padBadge as Pr,paintAnswer as ur,paintBadge as Fr}from"./packem_shared/ACCENT-CotPTfv7.mjs";import{discoverWorkflowInfo as Cr}from"./packem_shared/discoverWorkflowInfo-BsPvlo6O.mjs";export{fr as ACCENT,o as AGENT_MODE_ENV,E as AGENT_RULES_DIR,l as AGENT_RULES_HINT,n as AGENT_RULES_HINT_ENV,Lr as BADGES,Nr as BADGE_COLUMN_WIDTH,A as CODEGEN_ENV,Q as DEFAULT_DEPLOY_TARGET,x as DEV_BINDINGS_FILE,V as DEV_DAEMON_ENV,P as DEV_HANDOFF_ENV,u as DEV_LOG_FILE,F as DEV_LOG_FILE_ENV,O as DEV_STATE_DIR,C as DEV_STATE_FILE,K as DEV_VARS_EXAMPLE_FILE,h as DEV_VARS_FILE,Y as DEV_VARS_KEY_PATTERN,ie as LINKED_PROJECT_DIR,Ee as LINKED_PROJECT_FILE,vr as LUNA_ART,Tr as LUNA_BUNNY,Ir as LUNA_NAME,Rr as LUNA_SIGNOFF,Ge as LUNORA_CONFIG_FILE,Ae as LUNORA_EVENT_SOURCE,_e as LUNORA_IGNORED_PATHS,p as LUNORA_SKILL_NAMES,fe as LunoraReporter,Pe as PACKAGE_SECRETS_REGISTRY,_ as ROOT_SKILL_NAME,gr as STEP_BADGE_NAMES,Ne as addArgsFor,ir as applyAdditiveEdit,ce as applyLintIgnores,xr as badgeLead,Vr as badgeWidth,Je as buildPackageSecretsBlock,c as claimAgentRulesHint,G as claimDevServerState,Er as classifyEdit,_r as classifyPolicyEdit,U as clearDevServerState,we as createConfirm,Z as deployTargetIds,d as detectAgentRules,t as detectAiAgent,T as detectFramework,ve as detectInstalledManagers,de as detectLintTools,Te as detectPackageManager,s as discoverAgentInfo,f as discoverContainerInfo,Dr as discoverSchemaInfo,Cr as discoverWorkflowInfo,qe as ensureDevVariables,Xe as ensureDevVarsExample,W as escapeRegExp,Ie as execArgsFor,ze as fillDevSecrets,De as formatLunoraEvent,Qe as generateSecretValue,te as inferLunoraBindings,Re as installArgsFor,Ue as interpretRemote,D as isCodegenDisabled,b as isDevServerReady,je as isInteractive,Ze as isMintableSecretKey,$e as isPlaceholderValue,M as isProcessAlive,y as isRecordedProcessCurrent,$ as isRunnableTarget,ae as packageNamesFromBindings,Pr as padBadge,ur as paintAnswer,Fr as paintBadge,J as parseDevVariableEntries,nr as parseSchema,er as planDevSecretsFill,rr as planDevVariablesAugment,or as planDevVariablesScaffold,I as projectUsesUmbrella,He as promptMultiSelect,Ke as promptSelect,he as promptText,Ye as promptYesNo,k as readDevServerState,le as readLinkedProject,B as readLiveDevServerState,R as readProjectDependencyNames,be as readProjectRemotePreference,Me as readProjectTarget,q as removeDevVariableLine,tr as requiredSecrets,ee as resolveDeployDriver,ye as resolveProjectTarget,cr as resolveServerModule,ke as resolveTargetOrThrow,Oe as runPostCodegenHook,ge as runScriptArgsFor,xe as runScriptCommand,re as runnableTargetIds,dr as scaffoldPolicyFile,ue as secretsForPackages,N as streamContainerLogs,w as updateDevServerState,X as upsertDevVariableLine,mr as wireRlsIntoProcedure,j as writeDevServerState,ar as writeDevVariablesFileAtomically,ne as writeLinkedProject};
@@ -1,4 +1,4 @@
1
- import{existsSync as g,readFileSync as m,writeFileSync as d}from"node:fs";import{join as l,dirname as x}from"node:path";import{parse as v}from"jsonc-parser";import{readProjectDependencyNames as F}from"./detectFramework-DOn4PtpP.mjs";import{a as $}from"./jsonc-edit-BZgQIdAH.mjs";const c=["lunora/_generated/","lunora/.lunora-schema.json","lunora.advisor.map.json",".lunora/",".wrangler/"],f={biome:{configFiles:["biome.json","biome.jsonc"],packages:["@biomejs/biome"],shadowable:!0},eslint:{configFiles:["eslint.config.js","eslint.config.mjs","eslint.config.cjs","eslint.config.ts","eslint.config.mts","eslint.config.cts"],packages:["eslint"],shadowable:!0},oxlint:{configFiles:[".oxlintrc.json"],packages:["oxlint"],shadowable:!0},prettier:{configFiles:[".prettierrc",".prettierrc.json",".prettierrc.js",".prettierrc.mjs",".prettierrc.cjs","prettier.config.js","prettier.config.mjs","prettier.config.cjs"],packages:["prettier"],shadowable:!1}},k=Object.keys(f),y=(e,n)=>f[n].configFiles.map(t=>l(e,t)).find(t=>g(t)),w=(e,n)=>{let t=e;for(;;){const s=y(t,n);if(s!==void 0)return s;if(g(l(t,".git")))return;const i=x(t);if(i===t)return;t=i}},j=(e,n)=>{const t=y(e,n);if(t!==void 0)return{action:"extend",path:t};const s=g(l(e,".git")),i=f[n].shadowable&&!s?w(x(e),n):void 0,[a=""]=f[n].configFiles;return i===void 0?{action:"create",path:l(e,a)}:{action:"report",path:i}},J=e=>{const n=F(e),t=()=>{try{return JSON.parse(m(l(e,"package.json"),"utf8")).prettier!==void 0}catch{return!1}};return k.filter(s=>f[s].packages.some(i=>n.has(i))||y(e,s)!==void 0||s==="prettier"&&t())},L="# Lunora generated + derived artifacts",O=e=>{const n=l(e,".prettierignore"),t=g(n)?m(n,"utf8"):void 0,s=t===void 0?[]:t.split(`
1
+ import{existsSync as g,readFileSync as m,writeFileSync as d}from"node:fs";import{join as l,dirname as x}from"node:path";import{parse as v}from"jsonc-parser";import{readProjectDependencyNames as F}from"./detectFramework-CUiVEHDQ.mjs";import{a as $}from"./jsonc-edit-BZgQIdAH.mjs";const c=["lunora/_generated/","lunora/.lunora-schema.json","lunora.advisor.map.json",".lunora/",".wrangler/"],f={biome:{configFiles:["biome.json","biome.jsonc"],packages:["@biomejs/biome"],shadowable:!0},eslint:{configFiles:["eslint.config.js","eslint.config.mjs","eslint.config.cjs","eslint.config.ts","eslint.config.mts","eslint.config.cts"],packages:["eslint"],shadowable:!0},oxlint:{configFiles:[".oxlintrc.json"],packages:["oxlint"],shadowable:!0},prettier:{configFiles:[".prettierrc",".prettierrc.json",".prettierrc.js",".prettierrc.mjs",".prettierrc.cjs","prettier.config.js","prettier.config.mjs","prettier.config.cjs"],packages:["prettier"],shadowable:!1}},k=Object.keys(f),y=(e,n)=>f[n].configFiles.map(t=>l(e,t)).find(t=>g(t)),w=(e,n)=>{let t=e;for(;;){const s=y(t,n);if(s!==void 0)return s;if(g(l(t,".git")))return;const i=x(t);if(i===t)return;t=i}},j=(e,n)=>{const t=y(e,n);if(t!==void 0)return{action:"extend",path:t};const s=g(l(e,".git")),i=f[n].shadowable&&!s?w(x(e),n):void 0,[a=""]=f[n].configFiles;return i===void 0?{action:"create",path:l(e,a)}:{action:"report",path:i}},J=e=>{const n=F(e),t=()=>{try{return JSON.parse(m(l(e,"package.json"),"utf8")).prettier!==void 0}catch{return!1}};return k.filter(s=>f[s].packages.some(i=>n.has(i))||y(e,s)!==void 0||s==="prettier"&&t())},L="# Lunora generated + derived artifacts",O=e=>{const n=l(e,".prettierignore"),t=g(n)?m(n,"utf8"):void 0,s=t===void 0?[]:t.split(`
2
2
  `).map(o=>o.trim()),i=c.filter(o=>!s.includes(o));if(i.length===0)return{path:n,status:t===void 0?"created":"unchanged",tool:"prettier"};const a=`${L}
3
3
  ${i.join(`
4
4
  `)}
@@ -0,0 +1 @@
1
+ import{C as S,M as a,P as C,s as R}from"./package-secrets-registry-C8gAjaaj.mjs";export{S as CORE_SECRETS,a as MINTABLE_SECRET_KEYS,C as PACKAGE_SECRETS_REGISTRY,R as secretsForPackages};
@@ -0,0 +1 @@
1
+ import{existsSync as d,readFileSync as y}from"node:fs";import{join as s,isAbsolute as a,relative as m}from"node:path";import{runCodegen as p,CodegenDiagnosticError as g}from"@lunora/codegen";import{LunoraError as k}from"@lunora/errors";import{classifyPolicyEdit as v,scaffoldPolicyFile as b,resolveServerModule as l,wireRlsIntoProcedure as h}from"./classifyPolicyEdit-D8NwrHxR.mjs";import{w as c,s as w}from"./write-atomic-wWIDQIcK.mjs";const O="/__lunora/policy-scaffold",u=o=>o==="unknown-procedure"?404:o==="already-wired"||o==="destructive"?409:422,f=(o,r)=>{let e=[];try{p(w(o))}catch(t){if(t instanceof g)e=[t.message];else return{body:{error:t instanceof Error?t.message:String(t),ok:!1},status:500}}return{body:{...r,diagnostics:e,ok:!0},status:200}},R=o=>({body:{edit:o,message:"Rewriting an existing policy predicate changes evaluation semantics and must be done by hand. The scaffolder only adds new, deny-by-default rules.",needsManualEdit:!0,ok:!1},status:409}),N=(o,r)=>{const e=b(r,l(o.projectRoot));if(!e.ok)return{body:{error:e.reason,ok:!1},status:u(e.reason)};const t=o.schemaDirectory??"lunora",n=s(o.projectRoot,t,e.fileName);return d(n)?{body:{error:"file-exists",fileName:e.fileName,ok:!1},status:409}:(c(n,e.source),f(o,{fileName:e.fileName}))},P=(o,r,e)=>{if(typeof e!="string"||e.length===0||a(e)||e.includes("\\"))return;const t=s(o,r),n=s(t,`${e}.ts`),i=m(t,n);if(!(i.startsWith("..")||a(i)))return n},F=(o,r)=>{const e=P(o.projectRoot,o.schemaDirectory??"lunora",r.filePath);if(e===void 0||!d(e))return{body:{error:"unknown-procedure",ok:!1},status:404};const t=h(y(e,"utf8"),r,l(o.projectRoot));return t.ok?(c(e,t.text),f(o,{exportName:r.exportName})):{body:{error:t.reason,ok:!1},status:u(t.reason)}},A=o=>{if(o.method!=="POST")return{body:{error:"method-not-allowed",ok:!1},status:405};const{body:r}=o;if(r==null||typeof r!="object"||typeof r.kind!="string")return{body:{error:"invalid-edit",ok:!1},status:400};const e=r;if(v(e)==="destructive")return R(e);if(e.kind==="scaffoldPolicy")return N(o,e);if(e.kind==="wireRls")return F(o,e);throw new k("INTERNAL",`unhandled additive policy edit kind: ${String(e.kind)}`)};export{O as POLICY_SCAFFOLD_ENDPOINT,A as handlePolicyScaffoldRequest};
@@ -0,0 +1 @@
1
+ import{existsSync as f,readFileSync as O}from"node:fs";import{dirname as j,join as p}from"node:path";import{WORKER_ENTRY_FALLBACKS as D}from"./inferLunoraBindings-7kPfAt6p.mjs";import{discoverSchemaInfo as x}from"./discoverSchemaInfo-Bg2CUZXG.mjs";import{isCacheEnabled as N,WORKERS_CACHE_MIN_DATE as _}from"./WORKERS_CACHE_MIN_DATE-0k9ABJtF.mjs";import{findWranglerFile as I,readWranglerJsonc as L}from"./WRANGLER_FILES-UNW-xY5u.mjs";const C=new Set(["1","enabled","on","true","yes"]),T=e=>typeof e=="string"&&C.has(e.trim().toLowerCase()),v="2026-04-07",Ce="web_socket_auto_reply_to_close",E=/^\d{4}-\d{2}-\d{2}$/,$=["d1_databases","durable_objects","kv_namespaces","queues","r2_buckets","secrets_store_secrets","services","tail_consumers","vars","vectorize","workflows"],S=["assets","compatibility_date","exports","logpush","main","migrations","observability","placement"],R=(e,s)=>{if(s===void 0)return{merged:e,unverifiedKeys:[]};const t=e.env?.[s];if(t===void 0){const r=Object.keys(e.env??{}).toSorted((c,d)=>c.localeCompare(d)),l=r.length>0?` (declared: ${r.join(", ")}).`:" (no environments are declared).";return{error:`--env "${s}" names no environment declared in wrangler.jsonc's "env" block${l}`,merged:e,unverifiedKeys:[]}}const n={...e},i=Object.keys(t).filter(r=>r!=="env");for(const r of i)S.includes(r)&&(n[r]=t[r]);for(const r of $)n[r]=t[r];const a=new Set([...$,...S]),o=i.filter(r=>!a.has(r)).map(String);return{merged:n,unverifiedKeys:o}},B=(e,s,t)=>{if(s.length===0)return;const n=e.vectorize??[],i=new Set(n.filter(Boolean).map(a=>a?.index_name));for(const a of s)i.has(a)||t.push(`schema declares vector index "${a}"; wrangler "vectorize" must include a binding with index_name "${a}"`)},W=new Set(["basic","dev","lite","standard","standard-1","standard-2","standard-3","standard-4"]),q={disk_mb:2e4,memory_mib:12288,vcpu:4},U=(e,s,t)=>{const n=e.instance_type;if(n===void 0)return;if(typeof n=="string"){W.has(n)||t.push(`${s} has unknown instance_type "${n}" — expected lite, basic, standard-1..4, or a custom { vcpu, memory_mib, disk_mb } object`);return}for(const[r,l]of Object.entries(q)){const c=n[r];c!==void 0&&(typeof c!="number"||c<=0||c>l)&&t.push(`${s} custom instance_type ${r} must be a positive number ≤ ${String(l)} (got ${String(c)})`)}const{disk_mb:i,memory_mib:a,vcpu:o}=n;if(typeof o=="number"&&typeof a=="number"&&a<o*3072&&t.push(`${s} custom instance_type needs ≥ 3 GiB (3072 MiB) memory per vCPU (got ${String(a)} MiB for ${String(o)} vCPU)`),typeof a=="number"&&typeof i=="number"){const r=Math.floor(a/1024*2e3);i>r&&t.push(`${s} custom instance_type allows ≤ 2 GB disk per GiB memory (≤ ${String(r)} MB for ${String(a)} MiB memory; got ${String(i)} MB)`)}},F=(e,s,t)=>{const{boundClasses:n,classKinds:i,errors:a,warnings:o}=t;if(!e||typeof e!="object"||typeof e.class_name!="string"||e.class_name.length===0){a.push(`${s} must have a non-empty "class_name" naming its container-enabled Durable Object class`);return}(typeof e.image!="string"||e.image.length===0)&&a.push(`${s} ("${e.class_name}") must have an "image" — a Dockerfile path or a registry reference`),n.has(e.class_name)||a.push(`${s} class "${e.class_name}" has no matching durable_objects binding — your dev server auto-reconciles this on startup; add { "name": "...", "class_name": "${e.class_name}" } to fix it by hand`);const r=i.get(e.class_name);r!=="sqlite"&&a.push(r==="classic"?`${s} class "${e.class_name}" is registered via "new_classes" but containers require SQLite-backed DOs — move it to "new_sqlite_classes"`:`${s} class "${e.class_name}" is missing from migrations — add a migration entry with "new_sqlite_classes": ["${e.class_name}"]`),U(e,`${s} ("${e.class_name}")`,a),e.max_instances===void 0&&o.push(`${s} ("${e.class_name}") declares no max_instances — set a cap so a traffic spike can't fan out unbounded container spend`)},m=e=>typeof e=="string"&&e.length>0,b=e=>Array.isArray(e)?e.filter(s=>s!==null&&typeof s=="object"):[],h=e=>Array.isArray(e)?e.filter(s=>m(s)):[],k=e=>{const s=new Map;for(const t of b(e)){for(const n of h(t.new_classes))s.set(n,"classic");for(const n of h(t.new_sqlite_classes))s.set(n,"sqlite");for(const n of b(t.renamed_classes))if(m(n.from)&&m(n.to)){const i=s.get(n.from)??"sqlite";s.delete(n.from),s.set(n.to,i)}for(const n of h(t.deleted_classes))s.delete(n)}return s},P=e=>new Set(k(e).keys()),K=(e,s)=>{const t=P(e.migrations);for(const n of b(e.durable_objects?.bindings))n.script_name===void 0&&m(n.class_name)&&!t.has(n.class_name)&&s.push(`durable_objects.bindings declares class "${n.class_name}" but it is missing from migrations — add a migration entry with "new_sqlite_classes": ["${n.class_name}"] (or "new_classes" for a non-SQLite-backed class), or let the dev server auto-reconcile it on the next start`)},G=(e,s,t)=>{if(e.containers===void 0)return;if(!Array.isArray(e.containers)){s.push("containers must be an array of { class_name, image, ... } entries");return}const n=e.containers;if(n.length===0)return;const i=new Set(b(e.durable_objects?.bindings).map(o=>o.class_name)),a=k(e.migrations);for(const[o,r]of n.entries())F(r,`containers[${String(o)}]`,{boundClasses:i,classKinds:a,errors:s,warnings:t});e.observability?.enabled!==!0&&t.push('containers are configured but observability is not enabled — container logs will not be captured (add { "observability": { "enabled": true } })')},y=e=>e,g=(e,s,t,n)=>{if(e!==void 0){if(!Array.isArray(e)){n.push(t.arrayMessage);return}for(const[i,a]of y(e).entries()){const o=`${s}[${String(i)}]`;if(!a||typeof a!="object"){n.push(t.objectMessage(o));continue}for(const r of t.fields)m(a[r.field])||n.push(r.message(o))}}},Y={arrayMessage:"workflows must be an array of { name, binding, class_name } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding" naming the Workflow binding (e.g. WORKFLOW_ORDER_PIPELINE)`},{field:"class_name",message:e=>`${e} must have a non-empty "class_name" naming the exported WorkflowEntrypoint class`},{field:"name",message:e=>`${e} must have a non-empty "name" naming the deployed workflow`}],objectMessage:e=>`${e} must be a { name, binding, class_name } object`},Q={arrayMessage:"queues.producers must be an array of { binding, queue } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding" naming the Queue producer (e.g. QUEUE_EMAIL)`},{field:"queue",message:e=>`${e} must have a non-empty "queue" naming the deployed queue`}],objectMessage:e=>`${e} must be a { binding, queue } object`},H={arrayMessage:"queues.consumers must be an array of { queue } entries",fields:[{field:"queue",message:e=>`${e} must have a non-empty "queue" naming the consumed queue`}],objectMessage:e=>`${e} must be a { queue } object`},V=(e,s)=>{if(e.queues!==void 0){if(typeof e.queues!="object"||Array.isArray(e.queues)){s.push("queues must be a { producers, consumers } object");return}g(e.queues.producers,"queues.producers",Q,s),g(e.queues.consumers,"queues.consumers",H,s)}},z={arrayMessage:"secrets_store_secrets must be an array of { binding, store_id, secret_name } entries",fields:["binding","store_id","secret_name"].map(e=>({field:e,message:s=>`${s} must have a non-empty "${e}"`})),objectMessage:e=>`${e} must be a { binding, store_id, secret_name } object`},X=[{arrayMessage:"kv_namespaces must be an array of { binding, id } entries",bindingMessage:e=>`${e} must have a non-empty "binding" naming the KV namespace binding`,hintField:"id",hintMessage:(e,s)=>`${e} ("${s}") has no "id" — run \`wrangler kv namespace create\` and set the namespace id, or the binding can't resolve`,key:"kv_namespaces"},{arrayMessage:"flagship must be an array of { binding, app_id } entries",bindingMessage:e=>`${e} must have a non-empty "binding" naming the Flagship binding`,hintField:"app_id",hintMessage:(e,s)=>`${e} ("${s}") has no "app_id" — create a Flagship app and set its id, or the binding can't resolve`,key:"flagship"},{arrayMessage:"hyperdrive must be an array of { binding, id } entries",bindingMessage:e=>`${e} must have a non-empty "binding" naming the Hyperdrive binding`,hintField:"id",hintMessage:(e,s)=>`${e} ("${s}") has no "id" — run \`wrangler hyperdrive create\` and set the id, or the binding can't connect`,key:"hyperdrive"},{arrayMessage:"pipelines must be an array of { binding, stream } entries",bindingMessage:e=>`${e} must have a non-empty "binding" naming the Pipelines binding`,hintField:["stream","pipeline"],hintMessage:(e,s)=>`${e} ("${s}") has no "stream" — run \`wrangler pipelines create <name>\` and set the stream name, or the binding can't resolve`,key:"pipelines"},{arrayMessage:"analytics_engine_datasets must be an array of { binding, dataset } entries",bindingMessage:e=>`${e} must have a non-empty "binding" naming the Analytics Engine binding`,hintField:"dataset",hintMessage:(e,s)=>`${e} ("${s}") has no "dataset" — it defaults to the binding name; set it explicitly to avoid drift`,key:"analytics_engine_datasets"}],J=(e,s,t,n)=>{const i=e[s.key];if(i!==void 0){if(!Array.isArray(i)){t.push(s.arrayMessage);return}for(const[a,o]of y(i).entries()){const r=`${s.key}[${String(a)}]`;if(!o||typeof o!="object"||!m(o.binding)){t.push(s.bindingMessage(r));continue}(typeof s.hintField=="string"?[s.hintField]:s.hintField).some(c=>m(o[c]))||n.push(s.hintMessage(r,o.binding))}}},Z=[{key:"browser",message:'browser must be an object with a non-empty "binding" (e.g. { "binding": "BROWSER" })'},{key:"images",message:'images must be an object with a non-empty "binding" (e.g. { "binding": "IMAGES" })'}],ee=(e,s,t)=>{const n=e[s.key];n!==void 0&&(typeof n!="object"||Array.isArray(n)||!m(n.binding))&&t.push(s.message)},se=[{arrayMessage:"services must be an array of { binding, service, entrypoint? } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding" naming the service binding`},{field:"service",message:e=>`${e} must have a non-empty "service" naming the target Worker`}],key:"services",objectMessage:e=>`${e} must be a { binding, service, entrypoint? } object`},{arrayMessage:"dispatch_namespaces must be an array of { binding, namespace } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding"`},{field:"namespace",message:e=>`${e} must have a non-empty "namespace" naming the dispatch namespace`}],key:"dispatch_namespaces",objectMessage:e=>`${e} must be a { binding, namespace } object`},{arrayMessage:"mtls_certificates must be an array of { binding, certificate_id } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding"`},{field:"certificate_id",message:e=>`${e} must have a non-empty "certificate_id" (upload via \`wrangler mtls-certificate upload\`)`}],key:"mtls_certificates",objectMessage:e=>`${e} must be a { binding, certificate_id } object`},{arrayMessage:"r2_buckets must be an array of { binding, bucket_name } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding" naming the R2 bucket binding`},{field:"bucket_name",message:e=>`${e} must have a non-empty "bucket_name" naming the deployed bucket`}],key:"r2_buckets",objectMessage:e=>`${e} must be a { binding, bucket_name } object`}],ne=(e,s)=>{const{d1_databases:t}=e;if(t!==void 0){if(!Array.isArray(t)){s.push("d1_databases must be an array of { binding, database_id | database_name } entries");return}for(const[n,i]of y(t).entries()){const a=`d1_databases[${String(n)}]`;if(!i||typeof i!="object"){s.push(`${a} must be a { binding, database_id | database_name } object`);continue}m(i.binding)||s.push(`${a} must have a non-empty "binding" naming the D1 binding`),!m(i.database_id)&&!m(i.database_name)&&s.push(`${a} must have a "database_id" or a "database_name" — run \`wrangler d1 create\` and set one, or the binding can't resolve`)}}},te=(e,s,t)=>{const n=e.send_email;if(n===void 0)return;if(!Array.isArray(n)){s.push("send_email must be an array of { name, destination_address? } entries");return}const i=n;for(const[a,o]of i.entries())(!o||typeof o!="object"||typeof o.name!="string"||o.name.length===0)&&t.push(`send_email[${String(a)}] has no non-empty "name" naming the send-email binding — set one before deploying`)},ie=(e,s)=>{e.logpush!==void 0&&typeof e.logpush!="boolean"&&s.push('logpush must be a boolean (set "logpush": true to enable Cloudflare Logpush)')},ae=(e,s)=>{const{placement:t}=e;if(t!==void 0){if(typeof t!="object"||Array.isArray(t)){s.push('placement must be an object (e.g. { "mode": "smart" })');return}t.mode!==void 0&&t.mode!=="smart"&&s.push('placement.mode must be "smart" (the only supported Smart Placement mode)')}},oe=(e,s)=>{const{observability:t}=e;if(t===void 0)return;if(typeof t!="object"||Array.isArray(t)){s.push('observability must be an object (e.g. { "enabled": true, "head_sampling_rate": 1 })');return}const n=(i,a)=>{i!==void 0&&(typeof i!="number"||Number.isNaN(i)||i<0||i>1)&&s.push(`${a} must be a number in [0, 1] (the fraction of requests sampled)`)};n(t.head_sampling_rate,"observability.head_sampling_rate"),t.logs!==void 0&&(typeof t.logs!="object"||Array.isArray(t.logs)?s.push("observability.logs must be an object"):n(t.logs.head_sampling_rate,"observability.logs.head_sampling_rate"))},re=(e,s)=>{const{cache:t}=e;if(t!==void 0){if(typeof t!="object"||t===null||Array.isArray(t)){s.push('cache must be an object (e.g. { "enabled": true })');return}t.enabled!==void 0&&typeof t.enabled!="boolean"&&s.push("cache.enabled must be a boolean (true or false)")}},ce=(e,s)=>{const{exports:t}=e;if(t!==void 0){if(typeof t!="object"||t===null||Array.isArray(t)){s.push("exports must be an object keyed by entrypoint name");return}for(const[n,i]of Object.entries(t)){if(typeof i!="object"||i===null){s.push(`exports["${n}"] must be an object`);continue}i.type!==void 0&&typeof i.type!="string"&&s.push(`exports["${n}"].type must be a string`),i.cache!==void 0&&(typeof i.cache!="object"||i.cache===null||Array.isArray(i.cache)?s.push(`exports["${n}"].cache must be an object`):i.cache.enabled!==void 0&&typeof i.cache.enabled!="boolean"&&s.push(`exports["${n}"].cache.enabled must be a boolean`))}}},de=(e,s)=>{const{assets:t}=e;if(t!==void 0){if(typeof t!="object"||Array.isArray(t)){s.push('assets must be an object (e.g. { "directory": "./dist/client", "binding": "ASSETS" })');return}(typeof t.directory!="string"||t.directory.length===0)&&s.push('assets must declare a non-empty "directory" pointing at the built client output (e.g. "./dist/client")'),t.binding!==void 0&&(typeof t.binding!="string"||t.binding.length===0)&&s.push('assets.binding must be a non-empty string (e.g. "ASSETS")'),t.html_handling!==void 0&&typeof t.html_handling!="string"&&s.push("assets.html_handling must be a string"),t.not_found_handling!==void 0&&typeof t.not_found_handling!="string"&&s.push("assets.not_found_handling must be a string")}},le=(e,s)=>{const t=e.tail_consumers;if(t===void 0)return;if(!Array.isArray(t)){s.push("tail_consumers must be an array of { service, environment? } entries");return}const n=t;for(const[i,a]of n.entries())(!a||typeof a!="object"||typeof a.service!="string"||a.service.length===0)&&s.push(`tail_consumers[${String(i)}] must have a non-empty "service" naming the consumer Worker`)},Te=(e,s)=>{const t=e.tail_consumers??[];return t.some(i=>!!i&&i?.service===s.service&&i?.environment===s.environment)?e:{...e,tail_consumers:[...t,s]}},me=(e,s)=>{const{vars:t}=e;if(!t||typeof t!="object")return;const n=t.LUNORA_ALLOWED_ORIGINS,i=t.LUNORA_CORS_ALLOW_CREDENTIALS,a=typeof n=="string"&&n.split(",").some(r=>r.trim()==="*"),o=T(i);a&&o&&s.push('vars.LUNORA_ALLOWED_ORIGINS includes a "*" wildcard while vars.LUNORA_CORS_ALLOW_CREDENTIALS is on — browsers reject this combination and it defeats the allowlist; name explicit origins or drop credentials')},ue=(e,s,t)=>{const{error:n,merged:i,unverifiedKeys:a}=R(e,s);return n!==void 0?{error:n,wrangler:i}:(a.length>0&&t.push(`env.${String(s)} overrides ${a.join(", ")}, which this validator doesn't have a verified inheritance rule for — validated against the TOP-LEVEL value only. Double-check ${a.length===1?"it":"them"} by hand for "${String(s)}".`),{wrangler:i})},M=(e,s,t)=>{const n=[],i=[];if(!e||typeof e!="object")return n.push("wrangler config is not a valid object"),{errors:n,valid:!1,warnings:i};const{error:a,wrangler:o}=ue(e,t,i);if(a!==void 0)return n.push(a),{errors:n,valid:!1,warnings:i};b(o.durable_objects?.bindings).find(d=>d.name==="SHARD"&&d.class_name==="ShardDO")||n.push('durable_objects.bindings must include { "name": "SHARD", "class_name": "ShardDO" } — your dev server auto-reconciles this on startup, or add the binding manually'),K(o,n);const c=o.compatibility_date??"";c&&!E.test(c)?n.push(`compatibility_date must be in YYYY-MM-DD format (got "${c}")`):c<v&&n.push(`compatibility_date must be >= "${v}" (got "${c||"<missing>"}")`),N(o)&&E.test(c)&&c<_&&n.push(`cache.enabled requires compatibility_date >= "${_}" (got "${c||"<missing>"}")`),s?.hasGlobalTable&&(b(o.d1_databases).find(w=>w.binding==="DB")||n.push('schema declares .global() tables; d1_databases must include a binding named "DB" — your dev server auto-reconciles this on startup, or add the binding manually')),ne(o,n),B(o,s?.vectorIndexNames??[],n),le(o,n),G(o,n,i),g(o.workflows,"workflows",Y,n),V(o,n),g(o.secrets_store_secrets,"secrets_store_secrets",z,n);for(const d of X)J(o,d,n,i);for(const d of se)g(o[d.key],d.key,d,n);for(const d of Z)ee(o,d,n);return te(o,n,i),ie(o,n),ae(o,n),oe(o,n),de(o,n),re(o,n),ce(o,n),me(o,n),{errors:n,valid:n.length===0,warnings:i}},Be=M,be=(e,s,t)=>{const n=[];for(const i of e){const a=i?.image;typeof a!="string"||!(a.startsWith("./")||a.startsWith("../")||a.startsWith("/")||a.includes("Dockerfile"))||f(a.startsWith("/")?a:p(s,a))||n.push(`containers image "${a}" does not exist (resolved relative to ${t}); create the Dockerfile or point image at a registry reference`)}return n},ge=(e,s,t)=>{if(typeof e=="string"&&e.length>0){const n=p(j(t),e);return f(n)?n:void 0}return D.map(n=>p(s,n)).find(n=>f(n))},fe=/\/\/[^\n]*|\/\*.*?\*\/|"[^"\n]*"|'[^'\n]*'|`[^`]*`/gsu,pe=e=>e.replaceAll(fe,s=>s.replaceAll(/[^\n]/gu," ")),he=/\bexport\s*\*\s*(?:as\s+\w+\s*)?from\b/u,ye=/\bexport\b/gu,_e=/^\s*(?:(?:abstract|async|declare|default)\s+)*/u,ve=/^(?:class|const|function|let|var)\s+(?<name>[$A-Z_a-z][\w$]*)/u,Ee=/^\s*(?:const|let|var)\s*\{/u,$e=/^[$A-Z_a-z][\w$]*/u,Se=/^type\b/u,Ae=/\s+/u,je=e=>{const s=[];for(const t of e.split(",")){const n=t.trim().split(Ae).filter(Boolean),i=n.at(-1);i!==void 0&&n[0]!=="type"&&s.push(i)}return s},Re=e=>{const s=[];for(const t of e.split(",")){const n=t.includes(":")?t.slice(t.indexOf(":")+1):t,i=$e.exec(n.trim());i&&s.push(i[0])}return s},A=e=>{const s=e.indexOf("{"),t=e.indexOf("}",s);return s===-1||t===-1?void 0:e.slice(s+1,t)},ke=e=>{const s=e.trimStart();if(Se.test(s))return[];if(s.startsWith("{")){const n=A(s);return n===void 0?[]:je(n)}if(Ee.test(e)){const n=A(e);return n===void 0?[]:Re(n)}const t=ve.exec(e.replace(_e,""));return t?.groups?.name===void 0?[]:[t.groups.name]},Me=e=>{const s=new Set;for(const t of e.matchAll(ye))for(const n of ke(e.slice(t.index+6)))s.add(n);return s},we=(e,s,t)=>{const n=ge(e.main,s,t);if(n===void 0)return[];let i;try{i=O(n,"utf8")}catch{return[]}const a=pe(i);if(he.test(a))return[];const o=[];for(const c of b(e.durable_objects?.bindings))typeof c.class_name=="string"&&c.class_name.length>0&&c.script_name===void 0&&o.push({className:c.class_name,label:"durable_objects.bindings"});for(const c of e.workflows??[])typeof c?.class_name=="string"&&c.class_name.length>0&&c.script_name===void 0&&o.push({className:c.class_name,label:"workflows"});const r=Me(a);return o.filter(c=>!r.has(c.className)).map(c=>`${c.label} declares class "${c.className}" but the worker entry (${n}) does not export it — wrangler refuses to bundle a Worker whose Durable Object classes are not exported. Add \`export { ${c.className} } from "…";\` to the entry.`)},We=e=>{const s=e.schemaDir??"lunora",t=I(e.projectRoot);if(!t){const u=`wrangler.jsonc not found in ${e.projectRoot}; create one declaring at least the SHARD durable object binding.`;return{problems:[u],report:{errors:[u],valid:!1,warnings:[]},wranglerPath:void 0}}const{parsed:n}=L(t);if(n===void 0){const u=`failed to parse ${t} as JSONC.`;return{problems:[u],report:{errors:[u],valid:!1,warnings:[]},wranglerPath:t}}const{error:i,merged:a}=R(n,e.environment);if(i!==void 0)return{problems:[i],report:{errors:[i],valid:!1,warnings:[]},wranglerPath:t};const{error:o,info:r}=x(e.projectRoot,s),l=M(n,r,e.environment);o!==void 0&&l.warnings.push(`schema parse failed in ${s}/schema.ts: ${o}`);const c=j(t);l.errors.push(...be(a.containers??[],c,t)),l.warnings.push(...we(a,e.projectRoot,t));const d=a.assets?.directory;if(typeof d=="string"&&d.length>0){const u=d.startsWith("/")?d:p(c,d);f(u)||l.warnings.push(`assets.directory "${d}" does not exist yet — it is created by the client build; run the build before deploy`)}return l.valid=l.errors.length===0,{problems:l.errors,report:l,wranglerPath:t}};export{v as REQUIRED_COMPATIBILITY_DATE,Ce as REQUIRED_FLAG,Be as validateWrangler,M as validateWranglerConfig,We as validateWranglerProject,Te as withTailConsumer};
@@ -0,0 +1 @@
1
+ import{existsSync as a,readFileSync as d}from"node:fs";import{runCodegen as l,CodegenDiagnosticError as c}from"@lunora/codegen";import{classifyEdit as f,applyAdditiveEdit as p}from"./applyAdditiveEdit-CH0VhMJ2.mjs";import{parseSchema as u}from"./parseSchema-D1Wbr1qv.mjs";import{w as m,s as b}from"./write-atomic-wWIDQIcK.mjs";import{join as y}from"node:path";const C="/__lunora/schema-edit",g=e=>e==="destructive"||e==="duplicate-table"||e==="duplicate-column"||e==="duplicate-index"?409:e==="unknown-table"?404:e==="invalid-identifier"||e==="invalid-validator"?400:422,h=e=>({body:{error:e.reason,ok:!1},status:422}),k=e=>{if(!a(e))return{response:{body:{error:"no-schema-file",ok:!1},status:404}};const r=u(d(e,"utf8"));return r.ok?{tables:r.tables}:{response:h(r)}},v=e=>({body:{edit:e,message:"This edit changes stored data and must go through a migration. Review the migration before applying.",needsMigration:!0,ok:!1},status:409}),E=(e,r)=>{const t=e.body;if(t==null||typeof t!="object"||typeof t.kind!="string")return{body:{error:"invalid-edit",ok:!1},status:400};if(f(t)==="destructive")return v(t);if(!a(r))return{body:{error:"no-schema-file",ok:!1},status:404};const o=p(d(r,"utf8"),t);if(!o.ok)return{body:{error:o.reason,ok:!1},status:g(o.reason)};m(r,o.text);let i=[];try{l(b(e))}catch(s){if(s instanceof c)i=[s.message];else return{body:{error:s instanceof Error?s.message:String(s),ok:!1},status:500}}const n=u(o.text);return{body:{diagnostics:i,ok:!0,tables:n.ok?n.tables:[]},status:200}},D=e=>{const r=y(e.projectRoot,e.schemaDirectory??"lunora","schema.ts");if(e.method==="GET"){const t=k(r);return"response"in t?t.response:{body:{ok:!0,tables:t.tables},status:200}}return e.method==="POST"?E(e,r):{body:{error:"method-not-allowed",ok:!1},status:405}};export{C as SCHEMA_EDIT_ENDPOINT,D as handleSchemaEditRequest};
@@ -0,0 +1,6 @@
1
+ import{Project as p,SyntaxKind as n}from"ts-morph";import{collectCalls as m}from"./parseSchema-D1Wbr1qv.mjs";const v=/^[A-Za-z_$][\w$]*$/u,b=new Set(["any","array","bigint","boolean","bytes","date","id","literal","null","number","object","optional","record","storage","string","timestamp","union"]),u=e=>{if(e.getKind()===n.ParenthesizedExpression)return u(e.asKindOrThrow(n.ParenthesizedExpression).getExpression());if(e.getKind()!==n.CallExpression)return!1;const t=e.asKindOrThrow(n.CallExpression),r=t.getExpression();if(r.getKind()!==n.PropertyAccessExpression)return!1;const i=r.asKindOrThrow(n.PropertyAccessExpression);return i.getExpression().getKind()!==n.Identifier||i.getExpression().getText()!=="v"||!b.has(i.getName())?!1:t.getArguments().every(s=>c(s))},c=e=>{const t=e.getKind();return t===n.ParenthesizedExpression?c(e.asKindOrThrow(n.ParenthesizedExpression).getExpression()):t===n.StringLiteral||t===n.NumericLiteral||t===n.TrueKeyword||t===n.FalseKeyword||t===n.NullKeyword?!0:t===n.PrefixUnaryExpression?e.asKindOrThrow(n.PrefixUnaryExpression).getOperand().getKind()===n.NumericLiteral:t===n.ObjectLiteralExpression?e.asKindOrThrow(n.ObjectLiteralExpression).getProperties().every(r=>{if(r.getKind()!==n.PropertyAssignment)return!1;const i=r.getInitializer();return i!==void 0&&c(i)}):t===n.ArrayLiteralExpression?e.asKindOrThrow(n.ArrayLiteralExpression).getElements().every(r=>c(r)):u(e)},y=e=>{if(typeof e!="string"||e.trim().length===0)return!1;const t=new p({compilerOptions:{allowJs:!0},useInMemoryFileSystem:!0}),r=t.createSourceFile("validator.ts",`const __v = (${e});`,{overwrite:!0});if(t.getProgram().getSyntacticDiagnostics(r).length>0||r.getStatements().length!==1)return!1;const s=r.getVariableDeclaration("__v")?.getInitializer();return s!==void 0&&u(s)},E=new Set(["addIndex","addOptionalColumn","addTable"]),A=new Set(["d1","hyperdrive"]),T=e=>E.has(e.kind)?"additive":"destructive",d=e=>typeof e=="string"&&v.test(e),h=e=>{if(!d(e.table)||e.kind==="addTable"&&e.global?.backend!==void 0&&!A.has(e.global.backend))return"invalid-identifier";if(e.kind==="addOptionalColumn"){if(!d(e.column))return"invalid-identifier";if(!y(e.validator))return"invalid-validator"}if(e.kind==="addIndex"&&(!d(e.name)||!Array.isArray(e.fields)||!e.fields.every(t=>d(t))))return"invalid-identifier"},O=e=>{const r=new p({compilerOptions:{allowJs:!0},useInMemoryFileSystem:!0}).createSourceFile("schema.ts",e,{overwrite:!0});let i;for(const o of r.getDescendantsOfKind(n.CallExpression))if(o.getExpression().getText()==="defineSchema"){i=o;break}if(i===void 0)return{reason:r.getImportDeclarations().some(l=>l.getNamedImports().some(a=>a.getName()==="defineSchema"&&a.getAliasNode()!==void 0))?"aliased-define-schema":"no-define-schema"};const s=i.getArguments()[0];return s?.getKind()!==n.ObjectLiteralExpression?{reason:"non-object-argument"}:{object:s.asKindOrThrow(n.ObjectLiteralExpression),sourceFile:r}},g=(e,t)=>{for(const r of e.getProperties())if(r.getKind()===n.PropertyAssignment&&r.getNameNode().getText().replaceAll(/["']/gu,"")===t)return r},K=e=>{const t=e.getInitializer(),i=(t===void 0?void 0:m(t).find(s=>s.getExpression().getText()==="defineTable"))?.getArguments()[0];return i?.getKind()===n.ObjectLiteralExpression?i.asKindOrThrow(n.ObjectLiteralExpression):void 0},w=(e,t)=>{if(g(e,t.table)!==void 0)return"duplicate-table";const r=t.global?.backend,i=r===void 0?"":`{ backend: ${JSON.stringify(r)} }`,s=t.global===void 0?"":`.global(${i})`;e.addPropertyAssignment({initializer:`defineTable({
2
+ // Add your column validators here.
3
+ // Example:
4
+ // text: v.string(),
5
+ // createdAt: v.number(),
6
+ })${s}`,name:t.table})},k=(e,t)=>{const r=g(e,t.table);if(r===void 0)return"unknown-table";const i=K(r);if(i===void 0)return"unknown-table";if(i.getProperties().some(o=>o.getKind()===n.PropertyAssignment&&o.getNameNode().getText().replaceAll(/["']/gu,"")===t.column))return"duplicate-column";i.addPropertyAssignment({initializer:`v.optional(${t.validator})`,name:t.column})},S=(e,t)=>{if(e===void 0)return"unknown-table";const r=e.getInitializer();if(r===void 0)return"unknown-table";if(m(r).some(l=>{const a=l.getExpression();if(a.getKind()!==n.PropertyAccessExpression)return!1;const x=a.asKindOrThrow(n.PropertyAccessExpression),[f]=l.getArguments();return x.getName()==="index"&&f?.getKind()===n.StringLiteral&&f.asKindOrThrow(n.StringLiteral).getLiteralText()===t.name}))return"duplicate-index";const s=t.fields.map(l=>JSON.stringify(l)).join(", "),o=t.unique===!0?", { unique: true }":"";e.setInitializer(`${r.getText()}.index(${JSON.stringify(t.name)}, [${s}]${o})`)},N=(e,t)=>{if(T(t)==="destructive")return{ok:!1,reason:"destructive"};const r=t,i=h(r);if(i!==void 0)return{ok:!1,reason:i};const s=O(e);if("reason"in s)return{ok:!1,reason:s.reason};const{object:o,sourceFile:l}=s;let a;return r.kind==="addTable"?a=w(o,r):r.kind==="addOptionalColumn"?a=k(o,r):a=S(g(o,r.table),r),a!==void 0?{ok:!1,reason:a}:{ok:!0,text:l.getFullText()}};export{N as applyAdditiveEdit,T as classifyEdit};
@@ -0,0 +1,19 @@
1
+ import{randomBytes as V}from"node:crypto";import{existsSync as y,readFileSync as f,writeFileSync as _,renameSync as A,rmSync as x,statSync as b}from"node:fs";import{join as g}from"node:path";import{LunoraError as L}from"@lunora/errors";import{DEV_VARS_FILE as u,DEV_VARS_EXAMPLE_FILE as m,parseDevVariableLine as h,parseDevVariableEntries as K,DEV_VARS_NEWLINE as C}from"./DEV_VARS_EXAMPLE_FILE-CqLorAxT.mjs";import{C as R,M,s as F}from"./package-secrets-registry-C8gAjaaj.mjs";const D=e=>[...R,...F(e)],S=32,j=["replace","openssl","changeme","change-me","change_me","change-this","change_this","your-","your_","example","placeholder","todo","fill-me","fill_me","fill-in","fill_in","xxx"],T=/[.*+?^${}()|[\]\\]/gu,z=/[a-z0-9]$/u,N=e=>{const t=e.trim().toLowerCase();return t===""||t.startsWith("<")&&t.endsWith(">")?!0:j.some(r=>{const s=r.replaceAll(T,String.raw`\$&`),o=z.test(r)?`(^|[^a-z0-9])${s}([^a-z0-9]|$)`:`(^|[^a-z0-9])${s}`;return new RegExp(o,"u").test(t)})},p=e=>V(e).toString("hex"),B=e=>M.has(e),H=(e,t,r)=>B(e)&&N(t)?r(S):void 0,se=(e=p)=>e(S),P=(e,t,r)=>e.split(C).map(s=>{const n=h(s),o=n?H(n.key,n.value,t):void 0;return!n||o===void 0?s:(r.push(n.key),`${n.key}="${o}"`)}),I=e=>{if(e.devVarsExists)return{status:"exists"};if(e.exampleContent===void 0)return{status:"no-example"};const t=[];return{content:P(e.exampleContent,e.randomHex??p,t).join(`
2
+ `),generatedKeys:t,status:"generate"}},W=e=>e.includes('"')||e.includes("\\")?"":e.replaceAll("\r",String.raw`\r`).replaceAll(`
3
+ `,String.raw`\n`),E=e=>{const t=e.randomHex??p,r=new Set(K(e.existingContent).map(d=>d.key)),s=[],n=[],o=[];for(const d of e.exampleContent.split(C)){const i=h(d);if(!i||r.has(i.key))continue;const a=H(i.key,i.value,t);o.push(i.key),a===void 0?s.push(`${i.key}="${W(i.value)}"`):(n.push(i.key),s.push(`${i.key}="${a}"`))}return{additions:s,generatedKeys:n,missingKeys:o}},w=e=>e.length>0?` (generated ${e.join(", ")})`:"",$=(e,t,r={})=>{const s=`${e}.tmp-${String(process.pid)}`;try{_(s,t,{encoding:"utf8",...r}),A(s,e)}catch(n){throw x(s,{force:!0}),n}},re=(e,t)=>{$(e,t,{mode:384})},k=5,v=e=>{try{const t=b(e);return{mtimeMs:t.mtimeMs,size:t.size}}catch{return}},G=(e,t)=>e===void 0||t===void 0?!1:e.mtimeMs===t.mtimeMs&&e.size===t.size,O=(e,t)=>{for(let r=0;r<k;r+=1){const s=v(e),n=f(e,"utf8"),o=t(n);if(o.length===0)return[];const d=n.length>0&&!n.endsWith(`
4
+ `)?`
5
+ `:"",i=`${n}${d}${o.join(`
6
+ `)}
7
+ `,a=`${e}.tmp-${String(process.pid)}-${V(6).toString("hex")}`;try{_(a,i,{encoding:"utf8",mode:384});const c=v(e);if(!G(s,c)){x(a,{force:!0});continue}return A(a,e),o}catch(c){throw x(a,{force:!0}),c}}throw new L("INTERNAL",`Failed to append to ${e} after ${String(k)} attempts — a concurrent writer kept winning the race.`)},oe=async e=>{const t=g(e.cwd,u),r=g(e.cwd,m);if(!y(r))return{addedKeys:[],generatedKeys:[],status:"no-example"};const s=f(r,"utf8");if(!y(t)){const l=I({devVarsExists:!1,exampleContent:s,randomHex:e.randomHex});return l.status!=="generate"?{addedKeys:[],generatedKeys:[],status:"no-example"}:e.yes===!0||await e.confirm(`No ${u} found. Generate it from ${m} (secrets auto-filled)?`)?y(t)?{addedKeys:[],generatedKeys:[],status:"skipped-exists"}:($(t,l.content,{flag:"wx",mode:384}),e.info(`Created ${u}${w(l.generatedKeys)}.`),{addedKeys:[],generatedKeys:l.generatedKeys,status:"generated"}):(e.info(`Skipped — copy ${m} to ${u} and fill it in when you're ready.`),{addedKeys:[],generatedKeys:[],status:"declined"})}const n=E({existingContent:f(t,"utf8"),exampleContent:s,randomHex:e.randomHex});if(n.missingKeys.length===0)return{addedKeys:[],generatedKeys:[],status:"exists"};const o=n.missingKeys.join(", ");if(!(e.yes===!0||await e.confirm(`${u} is missing ${String(n.missingKeys.length)} key(s) from ${m} (${o}). Add them?`)))return e.info(`Skipped — add ${o} to ${u} when you're ready.`),{addedKeys:[],generatedKeys:[],status:"declined"};const a=O(t,l=>E({existingContent:l,exampleContent:s,randomHex:e.randomHex}).additions).map(l=>h(l)?.key).filter(l=>l!==void 0);if(a.length===0)return{addedKeys:[],generatedKeys:[],status:"exists"};const c=n.generatedKeys.filter(l=>a.includes(l));return e.info(`Updated ${u} — added ${a.join(", ")}${w(c)}.`),{addedKeys:a,generatedKeys:c,status:"augmented"}},U=e=>[`# ${e.description}`,`# Docs: ${e.docsUrl}`,`${e.key}="${e.placeholderValue}"`].join(`
8
+ `),X=(e,t)=>{const r=D(e).filter(s=>!t.has(s.key));return r.length===0?"":r.map(s=>U(s)).join(`
9
+
10
+ `)},ie=(e,t)=>{const r=g(e,m),s=y(r)?f(r,"utf8"):"",n=new Set(K(s).map(i=>i.key)),o=X(t,n);if(o==="")return[];const d=s.length>0&&!s.endsWith(`
11
+ `)?`
12
+ `:"";return $(r,`${s}${d}
13
+ ${o}
14
+ `),D(t).filter(i=>!n.has(i.key)).map(i=>i.key)},Y=e=>{const t=e.randomHex??p,r=[],s=P(e.existingContent,t,r),n=new Set(K(e.existingContent).map(c=>c.key)),o=[],d=[];for(const c of R)n.has(c.key)||(o.push(c.key),d.push(`# ${c.description}`,`${c.key}="${t(S)}"`));const i=s.join(`
15
+ `);if(d.length===0)return{addedKeys:o,content:i,filledKeys:r};const a=i===""||i.endsWith(`
16
+ `)?"":`
17
+ `;return{addedKeys:o,content:`${i}${a}${d.join(`
18
+ `)}
19
+ `,filledKeys:r}},ae=e=>{const t=g(e.cwd,u),r=y(t),s=r?f(t,"utf8"):"",n=Y({existingContent:s,randomHex:e.randomHex});if(n.filledKeys.length===0&&n.addedKeys.length===0)return{addedKeys:[],filledKeys:[],status:"unchanged"};$(t,n.content,{mode:384});const o=[...n.filledKeys,...n.addedKeys];return e.info?.(`Generated ${String(o.length)} dev secret(s) in ${u}: ${o.join(", ")}`),{addedKeys:n.addedKeys,filledKeys:n.filledKeys,status:r?"filled":"created"}};export{X as buildPackageSecretsBlock,oe as ensureDevVariables,ie as ensureDevVarsExample,ae as fillDevSecrets,se as generateSecretValue,B as isMintableSecretKey,N as isPlaceholderValue,Y as planDevSecretsFill,E as planDevVariablesAugment,I as planDevVariablesScaffold,D as requiredSecrets,re as writeDevVariablesFileAtomically};
@@ -0,0 +1,24 @@
1
+ import{Project as p,SyntaxKind as o}from"ts-morph";import{projectUsesUmbrella as u}from"./detectFramework-CUiVEHDQ.mjs";const f=new Set(["action","mutation","query","stream"]),l=/^[A-Za-z_$][\w$]*$/u,d=new Set(["@lunora/server","lunorash/server"]),y=e=>u(e)?"lunorash/server":"@lunora/server",m=new Set(["scaffoldPolicy","wireRls"]),$=e=>m.has(e.kind)?"additive":"destructive",v=(e,s)=>{if(typeof e.name!="string"||typeof e.table!="string"||!l.test(e.name)||!l.test(e.table))return{ok:!1,reason:"invalid-identifier"};const r=`${e.name}Policies`,t=`${e.name}Roles`,n=JSON.stringify(e.table),i=`import { definePermission, definePolicies, definePolicy, defineRole } from "${s}";
2
+
3
+ /**
4
+ * Access rules for the ${e.table} table — scaffolded by the Lunora studio
5
+ * (plan 025). The \`when\` predicates below DENY by default (\`() => false\`);
6
+ * replace each TODO with the real condition, then wire \`${r}\`
7
+ * into the procedures that read/write ${e.table} via
8
+ * \`.use(rls(${r}, { roles: ${t} }))\`.
9
+ */
10
+ export const ${r} = definePolicies([
11
+ definePolicy({
12
+ on: "read",
13
+ table: ${n},
14
+ // TODO: return \`true\` to allow, a \`WhereInput\` to filter, or \`false\` to deny.
15
+ when: () => false,
16
+ }),
17
+ ]);
18
+
19
+ /** Named permissions \`${r}\` can check with \`ctx.auth.can(...)\`. */
20
+ export const ${e.name}View = definePermission("${e.name}:view");
21
+
22
+ /** Roles that grant the permissions above; register via \`rls(policies, { roles })\`. */
23
+ export const ${t} = [defineRole("${e.name}-admin", { permissions: [${e.name}View] })];
24
+ `;return{fileName:`${e.name}.policies.ts`,ok:!0,source:i}},h=e=>{const s=e.getExpression();if(s.getKind()!==o.PropertyAccessExpression)return;const r=s.asKindOrThrow(o.PropertyAccessExpression);return f.has(r.getName())?r.getExpression():void 0},g=(e,s)=>{const r=e.getImportDeclaration(t=>d.has(t.getModuleSpecifierValue()));if(r===void 0){e.addImportDeclaration({moduleSpecifier:s,namedImports:["rls"]});return}r.getNamedImports().some(t=>t.getName()==="rls")||r.addNamedImport("rls")},w=e=>{const s=e.getDescendantsOfKind(o.CallExpression);e.getKind()===o.CallExpression&&s.push(e.asKindOrThrow(o.CallExpression));for(const r of s){const t=r.getExpression();if(t.getKind()!==o.PropertyAccessExpression)continue;const n=t.asKindOrThrow(o.PropertyAccessExpression),[i]=r.getArguments();if(n.getName()==="use"&&i?.getKind()===o.CallExpression&&i.asKindOrThrow(o.CallExpression).getExpression().getText()==="rls")return!0}return!1},I=(e,s,r)=>{if(typeof s.policies!="string"||!l.test(s.policies))return{ok:!1,reason:"invalid-identifier"};const n=new p({compilerOptions:{allowJs:!0},useInMemoryFileSystem:!0}).createSourceFile("procedure.ts",e,{overwrite:!0}),i=n.getVariableDeclaration(s.exportName),c=i?.getInitializer();if(i===void 0||c?.getKind()!==o.CallExpression)return{ok:!1,reason:"unknown-procedure"};const a=h(c.asKindOrThrow(o.CallExpression));return a===void 0?{ok:!1,reason:"unsupported-procedure-shape"}:w(a)?{ok:!1,reason:"already-wired"}:(a.replaceWithText(`${a.getText()}.use(rls(${s.policies}))`),g(n,r),{ok:!0,text:n.getFullText()})};export{$ as classifyPolicyEdit,y as resolveServerModule,v as scaffoldPolicyFile,I as wireRlsIntoProcedure};
@@ -0,0 +1 @@
1
+ import{relative as s}from"node:path";import{secretKindOf as a,redact as c}from"@lunora/codegen";import{i as f,a as d}from"./package-secrets-registry-C8gAjaaj.mjs";import{isPlaceholderValue as l}from"./buildPackageSecretsBlock-DZWcrhvs.mjs";import{findWranglerFile as m,readWranglerJsonc as u}from"./WRANGLER_FILES-UNW-xY5u.mjs";const p=8,g=(e,r)=>{if(e===void 0)return[];const n=[];for(const[t,i]of Object.entries(e)){if(typeof i!="string"||l(i)||f(t))continue;const o=a(i)??(d(t)&&i.length>=p?"secret_named_var":void 0);o!==void 0&&n.push({file:r,key:t,kind:o,preview:c(i)})}return n},V=e=>{const r=m(e);if(r===void 0)return[];const{parsed:n}=u(r);return n===void 0?[]:g(n.vars,s(e,r))};export{V as collectWranglerSecretVariables,g as scanWranglerVariablesForSecrets};
@@ -1 +1 @@
1
- import{existsSync as a,readFileSync as c}from"node:fs";import{join as o}from"node:path";const d=[{class:"A",dependency:"@tanstack/react-start",framework:"tanstack-start"},{class:"A",dependency:"@tanstack/solid-start",framework:"tanstack-start-solid"},{class:"A",dependency:"@react-router/dev",framework:"react-router"},{class:"A",dependency:"vinext",framework:"vinext"},{class:"A",dependency:"@solidjs/start",framework:"solid-start"},{class:"A",dependency:"solid-start",framework:"solid-start"},{class:"B",dependency:"@sveltejs/kit",framework:"sveltekit"},{class:"B",dependency:"nuxt",framework:"nuxt"},{class:"B",dependency:"astro",framework:"astro"}],n={class:"C",framework:"none"},i=t=>{const e=o(t,"package.json");if(!a(e))return new Set;try{const s=c(e,"utf8"),r=JSON.parse(s);return new Set([...Object.keys(r.dependencies??{}),...Object.keys(r.devDependencies??{})])}catch{return new Set}},p=t=>{const e=i(t);if(e.size===0)return n;for(const s of d)if(e.has(s.dependency))return{class:s.class,framework:s.framework};return n};export{p as detectFramework,i as readProjectDependencyNames};
1
+ import{existsSync as c,readFileSync as o}from"node:fs";import{join as d}from"node:path";const l=[{class:"A",dependency:"@tanstack/react-start",framework:"tanstack-start"},{class:"A",dependency:"@tanstack/solid-start",framework:"tanstack-start-solid"},{class:"A",dependency:"@react-router/dev",framework:"react-router"},{class:"A",dependency:"vinext",framework:"vinext"},{class:"A",dependency:"@solidjs/start",framework:"solid-start"},{class:"A",dependency:"solid-start",framework:"solid-start"},{class:"B",dependency:"@sveltejs/kit",framework:"sveltekit"},{class:"B",dependency:"nuxt",framework:"nuxt"},{class:"B",dependency:"astro",framework:"astro"}],n={class:"C",framework:"none"},a=e=>{const s=d(e,"package.json");if(!c(s))return new Set;try{const t=o(s,"utf8"),r=JSON.parse(t);return new Set([...Object.keys(r.dependencies??{}),...Object.keys(r.devDependencies??{})])}catch{return new Set}},p=e=>a(e).has("lunorash"),f=e=>{const s=a(e);if(s.size===0)return n;for(const t of l)if(s.has(t.dependency))return{class:t.class,framework:t.framework};return n};export{f as detectFramework,p as projectUsesUmbrella,a as readProjectDependencyNames};
@@ -0,0 +1 @@
1
+ const a=e=>e.replaceAll(/([a-z\d])([A-Z])/gu,"$1_$2").toUpperCase().split(/[_-]+/u).filter(s=>s.length>0),n=new Set(["CREDENTIAL","CREDENTIALS","DSN","PASSPHRASE","PASSWD","PASSWORD","SECRET","TOKEN"]),p=["ACCESS_KEY","API_KEY","ENCRYPTION_KEY","PRIVATE_KEY","SIGNING_KEY"],c=/(?:apikey|passphrase|passwd|password|secret|token)$/iu,i=e=>a(e).some(s=>s==="PUBLIC"||s==="PUBLISHABLE"),l=e=>{if(i(e))return!1;const s=a(e);if(s.some(o=>n.has(o)))return!0;const t=s.join("_");return p.some(o=>t===o||t.endsWith(`_${o}`))||c.test(e)},d=[{description:"Bearer token the local Lunora Studio uses to call the worker's admin endpoints (data browser, schema edits) in dev. Generate with: openssl rand -hex 32",docsUrl:"https://lunora.sh/docs/packages/studio",key:"LUNORA_ADMIN_TOKEN",placeholderValue:"replace-with-openssl-rand-hex-32"}],h=["BETTER_AUTH_SECRET","STORAGE_SIGNING_SECRET"],r={"@lunora/auth":[{description:"32-byte random secret used to sign sessions and tokens. Generate with: openssl rand -hex 32",docsUrl:"https://lunora.sh/docs/packages/auth#secrets",key:"AUTH_SECRET",placeholderValue:"replace-with-openssl-rand-hex-32"},{description:"Public base URL of your worker (used by better-auth for redirects and cookie domain). For local dev this is typically http://localhost:8787",docsUrl:"https://lunora.sh/docs/packages/auth#secrets",key:"AUTH_URL",placeholderValue:"http://localhost:8787"}],"@lunora/mail":[{description:"Resend API key for sending transactional email via @lunora/mail. Obtain at https://resend.com/api-keys",docsUrl:"https://lunora.sh/docs/packages/mail#secrets",key:"RESEND_API_KEY",placeholderValue:"<your-resend-api-key>"}],"@lunora/notify":[{description:"Public VAPID key (base64url) for Web Push. Generate a keypair once with: npx web-push generate-vapid-keys — the public key is also shipped to the browser to subscribe.",docsUrl:"https://lunora.sh/docs/packages/notify#web-push",key:"VAPID_PUBLIC_KEY",placeholderValue:"<your-vapid-public-key>"},{description:"Private VAPID key (base64url) for Web Push — the application-server signing key. Generate with: npx web-push generate-vapid-keys",docsUrl:"https://lunora.sh/docs/packages/notify#web-push",key:"VAPID_PRIVATE_KEY",placeholderValue:"<your-vapid-private-key>"},{description:"VAPID `sub` contact — a mailto: or https: URL identifying the application server (e.g. mailto:you@example.com).",docsUrl:"https://lunora.sh/docs/packages/notify#web-push",key:"VAPID_SUBJECT",placeholderValue:"mailto:you@example.com"},{description:"Firebase project id for FCM (HTTP v1) push. Found in the Firebase console project settings.",docsUrl:"https://lunora.sh/docs/packages/notify#fcm",key:"FCM_PROJECT_ID",placeholderValue:"<your-firebase-project-id>"},{description:"OAuth2 access token for FCM (HTTP v1). Convenient for dev but expires — in production supply a getAccessToken() in defineNotify instead. Obtain via the Google Cloud SDK / a service account.",docsUrl:"https://lunora.sh/docs/packages/notify#fcm",key:"FCM_ACCESS_TOKEN",placeholderValue:"<your-fcm-access-token>"}],"@lunora/payment":[{description:"Stripe secret key (sk_test_…). Required when using the Stripe adapter. Obtain at https://dashboard.stripe.com/apikeys",docsUrl:"https://lunora.sh/docs/packages/payment#stripe",key:"STRIPE_SECRET_KEY",placeholderValue:"<your-stripe-secret-key>"},{description:"Stripe webhook signing secret (whsec_…) for verifying event payloads. Obtain at https://dashboard.stripe.com/webhooks",docsUrl:"https://lunora.sh/docs/packages/payment#stripe",key:"STRIPE_WEBHOOK_SECRET",placeholderValue:"<your-stripe-webhook-secret>"},{description:"Polar access token for the Polar payment adapter. Obtain at https://polar.sh/settings/tokens",docsUrl:"https://lunora.sh/docs/packages/payment#polar",key:"POLAR_ACCESS_TOKEN",placeholderValue:"<your-polar-access-token>"},{description:"Polar webhook secret for verifying event payloads from Polar. Obtain at https://polar.sh/settings/webhooks",docsUrl:"https://lunora.sh/docs/packages/payment#polar",key:"POLAR_WEBHOOK_SECRET",placeholderValue:"<your-polar-webhook-secret>"},{description:"Autumn secret key (am_sk_…) for the Autumn payment adapter. Obtain at https://app.useautumn.com/dev",docsUrl:"https://lunora.sh/docs/packages/payment#autumn",key:"AUTUMN_SECRET_KEY",placeholderValue:"<your-autumn-secret-key>"},{description:"Autumn webhook signing secret for verifying Standard Webhooks event payloads. Obtain from your Autumn dashboard webhook settings.",docsUrl:"https://lunora.sh/docs/packages/payment#autumn",key:"AUTUMN_WEBHOOK_SECRET",placeholderValue:"<your-autumn-webhook-secret>"},{description:"Dodo Payments API key (bearer token) for the Dodo Payments adapter. Obtain at https://app.dodopayments.com/developer/api-keys",docsUrl:"https://lunora.sh/docs/packages/payment#dodo-payments",key:"DODO_PAYMENTS_API_KEY",placeholderValue:"<your-dodo-payments-api-key>"},{description:"Dodo Payments webhook signing secret (whsec_…) for verifying event payloads. Obtain at https://app.dodopayments.com/developer/webhooks",docsUrl:"https://lunora.sh/docs/packages/payment#dodo-payments",key:"DODO_PAYMENTS_WEBHOOK_KEY",placeholderValue:"<your-dodo-payments-webhook-secret>"},{description:"Creem API key for the Creem payment adapter. Obtain at https://www.creem.io/dashboard/developers",docsUrl:"https://lunora.sh/docs/packages/payment#creem",key:"CREEM_API_KEY",placeholderValue:"<your-creem-api-key>"},{description:"Creem webhook signing secret for verifying the creem-signature header. Obtain from your Creem dashboard webhook settings.",docsUrl:"https://lunora.sh/docs/packages/payment#creem",key:"CREEM_WEBHOOK_SECRET",placeholderValue:"<your-creem-webhook-secret>"}]},u=new Set([...h,...[...d,...Object.values(r).flat()].filter(e=>l(e.key)&&!e.placeholderValue.startsWith("<")).map(e=>e.key)]),y=e=>{const s=[];for(const t of e){const o=r[t];o!==void 0&&s.push(...o)}return s};export{d as C,u as M,r as P,l as a,i,y as s};
@@ -0,0 +1 @@
1
+ import{readFileSync as n}from"node:fs";import{join as s}from"node:path";import{parseDevVariableEntries as i}from"./DEV_VARS_EXAMPLE_FILE-CqLorAxT.mjs";const a=(o,r)=>{const e=i(o).find(t=>t.key===r);return e===void 0||e.value===""?void 0:e.value},d=o=>{let r;try{r=a(n(s(o,".dev.vars"),"utf8"),"LUNORA_ADMIN_TOKEN")}catch{r=void 0}const e=process.env.LUNORA_ADMIN_TOKEN;return typeof e=="string"&&e!==""&&e!==r&&console.warn("[lunora] LUNORA_ADMIN_TOKEN is exported in this shell but differs from .dev.vars — the local worker only verifies the .dev.vars token, so the studio uses that one."),r};export{a as parseDevVariable,d as resolveAdminToken};
@@ -0,0 +1 @@
1
+ import{Project as m,SyntaxKind as n}from"ts-morph";const f=/^v\s*\.\s*optional\s*\(/u,x=/\.shardBy\(\s*["']([^"']+)["']\s*\)/u,T=/\.global\(\s*(?:\{[^{}]*\}\s*)?\)/u,p=/["']/gu,u=e=>{const t=e.getDescendantsOfKind(n.CallExpression);return e.getKind()===n.CallExpression&&t.push(e.asKindOrThrow(n.CallExpression)),t},A=e=>f.test(e.trim()),h=e=>e?.getKind()!==n.ArrayLiteralExpression?[]:e.asKindOrThrow(n.ArrayLiteralExpression).getElements().filter(t=>t.getKind()===n.StringLiteral).map(t=>t.asKindOrThrow(n.StringLiteral).getLiteralText()),E=e=>{if(e?.getKind()!==n.ObjectLiteralExpression)return!1;const t=e.asKindOrThrow(n.ObjectLiteralExpression).getProperty("unique");return t?.getKind()===n.PropertyAssignment&&t.getInitializer()?.getText()==="true"},K=e=>{const t=e.getExpression();if(t.getKind()!==n.PropertyAccessExpression||t.asKindOrThrow(n.PropertyAccessExpression).getName()!=="index")return;const[r,a,s]=e.getArguments();if(r?.getKind()===n.StringLiteral)return{fields:h(a),name:r.asKindOrThrow(n.StringLiteral).getLiteralText(),unique:E(s)}},O=e=>{const t=e.getInitializer();if(t===void 0)return[];const r=[];for(const a of u(t)){const s=K(a);s!==void 0&&r.push(s)}return r},y=e=>{const t=[],r=e.getInitializer(),s=(r===void 0?void 0:u(r).find(l=>l.getExpression().getText()==="defineTable"))?.getArguments()[0];if(s?.getKind()!==n.ObjectLiteralExpression)return t;for(const l of s.getProperties()){if(l.getKind()!==n.PropertyAssignment)continue;const i=l,o=i.getName().replaceAll(p,""),c=i.getInitializer()?.getText()??"";t.push({name:o,optional:A(c),validator:c})}return t},P=e=>{const r=new m({compilerOptions:{allowJs:!0},useInMemoryFileSystem:!0}).createSourceFile("schema.ts",e,{overwrite:!0}),a=r.getDescendantsOfKind(n.CallExpression).find(i=>i.getExpression().getText()==="defineSchema");if(a===void 0)return{ok:!1,reason:r.getImportDeclarations().some(o=>o.getNamedImports().some(c=>c.getName()==="defineSchema"&&c.getAliasNode()!==void 0))?"aliased-define-schema":"no-define-schema"};const s=a.getArguments()[0];if(s?.getKind()!==n.ObjectLiteralExpression)return{ok:!1,reason:"non-object-argument"};const l=[];for(const i of s.getProperties()){if(i.getKind()!==n.PropertyAssignment)continue;const o=i,c=o.getName().replaceAll(p,""),g=o.getInitializer()?.getText()??"",d=x.exec(g);l.push({columns:y(o),global:T.test(g),indexes:O(o),name:c,...d?.[1]===void 0?{}:{shardBy:d[1]}})}return{ok:!0,tables:l}};export{u as collectCalls,P as parseSchema};
@@ -1,3 +1,10 @@
1
+ /**
2
+ * The server-module specifier to scaffold into a project's own source:
3
+ * `lunorash/server` when the project depends on the umbrella, `@lunora/server`
4
+ * when it installs the granular packages. Same detection codegen and the Vite
5
+ * compose plugin use, so a scaffolded file imports what the emitted code does.
6
+ */
7
+ declare const resolveServerModule: (projectRoot: string) => string;
1
8
  /** Scaffold a new policy/role/permission stub file under `lunora/`. */
2
9
  interface ScaffoldPolicyEdit {
3
10
  readonly kind: "scaffoldPolicy";
@@ -61,8 +68,13 @@ type WireResult = {
61
68
  * predicate is a `() => false` skeleton with a TODO — the scaffolder never
62
69
  * authors real logic, the developer fills it in. Pure (no I/O); the handler
63
70
  * writes the returned source and refuses to overwrite an existing file.
71
+ *
72
+ * `serverModule` is the specifier the PROJECT can resolve the builders from
73
+ * (see {@link resolveServerModule}) — an umbrella-only install has no
74
+ * `@lunora/server` on disk, so hard-coding it would scaffold a file that
75
+ * cannot be bundled.
64
76
  */
65
- declare const scaffoldPolicyFile: (edit: ScaffoldPolicyEdit) => ScaffoldFileResult;
77
+ declare const scaffoldPolicyFile: (edit: ScaffoldPolicyEdit, serverModule: string) => ScaffoldFileResult;
66
78
  /**
67
79
  * Append `.use(rls(<policies>))` to a procedure's builder chain, preserving the
68
80
  * terminal `.query(handler)` (and its handler body) byte-for-byte. Only the
@@ -70,5 +82,5 @@ declare const scaffoldPolicyFile: (edit: ScaffoldPolicyEdit) => ScaffoldFileResu
70
82
  * has no chain and is reported `unsupported-procedure-shape` so the editor can
71
83
  * tell the developer to convert it rather than silently rewriting their code.
72
84
  */
73
- declare const wireRlsIntoProcedure: (source: string, edit: WireRlsEdit) => WireResult;
74
- export { AdditivePolicyEdit as A, DestructivePolicyEdit as D, PolicyEdit as P, ScaffoldPolicyEdit as S, WireRlsEdit as W, PolicyScaffoldFailureReason as a, ScaffoldFileResult as b, WireResult as c, classifyPolicyEdit as d, scaffoldPolicyFile as s, wireRlsIntoProcedure as w };
85
+ declare const wireRlsIntoProcedure: (source: string, edit: WireRlsEdit, serverModule: string) => WireResult;
86
+ export { AdditivePolicyEdit as A, DestructivePolicyEdit as D, PolicyEdit as P, ScaffoldPolicyEdit as S, WireRlsEdit as W, PolicyScaffoldFailureReason as a, ScaffoldFileResult as b, WireResult as c, classifyPolicyEdit as d, resolveServerModule as r, scaffoldPolicyFile as s, wireRlsIntoProcedure as w };
@@ -1,3 +1,10 @@
1
+ /**
2
+ * The server-module specifier to scaffold into a project's own source:
3
+ * `lunorash/server` when the project depends on the umbrella, `@lunora/server`
4
+ * when it installs the granular packages. Same detection codegen and the Vite
5
+ * compose plugin use, so a scaffolded file imports what the emitted code does.
6
+ */
7
+ declare const resolveServerModule: (projectRoot: string) => string;
1
8
  /** Scaffold a new policy/role/permission stub file under `lunora/`. */
2
9
  interface ScaffoldPolicyEdit {
3
10
  readonly kind: "scaffoldPolicy";
@@ -61,8 +68,13 @@ type WireResult = {
61
68
  * predicate is a `() => false` skeleton with a TODO — the scaffolder never
62
69
  * authors real logic, the developer fills it in. Pure (no I/O); the handler
63
70
  * writes the returned source and refuses to overwrite an existing file.
71
+ *
72
+ * `serverModule` is the specifier the PROJECT can resolve the builders from
73
+ * (see {@link resolveServerModule}) — an umbrella-only install has no
74
+ * `@lunora/server` on disk, so hard-coding it would scaffold a file that
75
+ * cannot be bundled.
64
76
  */
65
- declare const scaffoldPolicyFile: (edit: ScaffoldPolicyEdit) => ScaffoldFileResult;
77
+ declare const scaffoldPolicyFile: (edit: ScaffoldPolicyEdit, serverModule: string) => ScaffoldFileResult;
66
78
  /**
67
79
  * Append `.use(rls(<policies>))` to a procedure's builder chain, preserving the
68
80
  * terminal `.query(handler)` (and its handler body) byte-for-byte. Only the
@@ -70,5 +82,5 @@ declare const scaffoldPolicyFile: (edit: ScaffoldPolicyEdit) => ScaffoldFileResu
70
82
  * has no chain and is reported `unsupported-procedure-shape` so the editor can
71
83
  * tell the developer to convert it rather than silently rewriting their code.
72
84
  */
73
- declare const wireRlsIntoProcedure: (source: string, edit: WireRlsEdit) => WireResult;
74
- export { AdditivePolicyEdit as A, DestructivePolicyEdit as D, PolicyEdit as P, ScaffoldPolicyEdit as S, WireRlsEdit as W, PolicyScaffoldFailureReason as a, ScaffoldFileResult as b, WireResult as c, classifyPolicyEdit as d, scaffoldPolicyFile as s, wireRlsIntoProcedure as w };
85
+ declare const wireRlsIntoProcedure: (source: string, edit: WireRlsEdit, serverModule: string) => WireResult;
86
+ export { AdditivePolicyEdit as A, DestructivePolicyEdit as D, PolicyEdit as P, ScaffoldPolicyEdit as S, WireRlsEdit as W, PolicyScaffoldFailureReason as a, ScaffoldFileResult as b, WireResult as c, classifyPolicyEdit as d, resolveServerModule as r, scaffoldPolicyFile as s, wireRlsIntoProcedure as w };
@@ -1 +1 @@
1
- import{headerValue as a}from"./ALLOW_FORWARDED_ENV-BUndghJx.mjs";const l=1e6,g=async t=>await new Promise((o,e)=>{const n=[];let i=0;t.on("data",c=>{if(i+=c.length,i>l){e(new Error("request body too large"));return}n.push(c)}),t.on("end",()=>{o(Buffer.concat(n).toString("utf8"))}),t.on("error",e)}),s=(t,o,e)=>{t.statusCode=o,t.setHeader("Content-Type","application/json; charset=utf-8"),t.end(JSON.stringify(e))},u=new Set(["none","same-origin","same-site"]),y=t=>{const o=a(t.headers["sec-fetch-site"]);if(o!==void 0)return u.has(o)?void 0:"cross-origin request rejected";const e=a(t.headers.origin);if(e===void 0||e==="null")return;let n;try{n=new URL(e).host.toLowerCase()}catch{return"invalid origin header"}return n===a(t.headers.host)?void 0:"cross-origin request rejected"},p=t=>{const o=(t.method??"GET").toUpperCase(),e=o!=="GET"&&o!=="HEAD",n=y(t);if(n!==void 0)return n;if(e&&!a(t.headers["content-type"])?.startsWith("application/json"))return"content-type must be application/json"},v=(t,o,e,n,i)=>{(async()=>{try{const r=p(t);if(r!==void 0){s(o,403,{error:r,ok:!1});return}const d=t.method==="GET"?"":await g(t);let h;try{h=d===""?void 0:JSON.parse(d)}catch{s(o,400,{error:"invalid-json",ok:!1});return}const f=e({body:h,method:t.method??"POST",projectRoot:n,schemaDirectory:i});s(o,f.status,f.body)}catch(r){s(o,500,{error:r instanceof Error?r.message:String(r),ok:!1})}})().catch(()=>{})};export{v as serveJsonHandler};
1
+ import{headerValue as a}from"./ALLOW_FORWARDED_ENV-BUndghJx.mjs";const l=1e6,g=async t=>await new Promise((o,e)=>{const n=[];let i=0;t.on("data",c=>{if(i+=c.length,i>l){e(new Error("request body too large"));return}n.push(c)}),t.on("end",()=>{o(Buffer.concat(n).toString("utf8"))}),t.on("error",e)}),s=(t,o,e)=>{t.statusCode=o,t.setHeader("Content-Type","application/json; charset=utf-8"),t.end(JSON.stringify(e))},u=new Set(["none","same-origin","same-site"]),y=t=>{const o=a(t.headers["sec-fetch-site"]);if(o!==void 0)return u.has(o)?void 0:"cross-origin request rejected";const e=a(t.headers.origin);if(e===void 0||e==="null")return;let n;try{n=new URL(e).host.toLowerCase()}catch{return"invalid origin header"}return n===a(t.headers.host)?void 0:"cross-origin request rejected"},p=t=>{const o=(t.method??"GET").toUpperCase(),e=o!=="GET"&&o!=="HEAD",n=y(t);if(n!==void 0)return n;if(e&&!a(t.headers["content-type"])?.startsWith("application/json"))return"content-type must be application/json"},v=(t,o,e,n,i={})=>{(async()=>{try{const r=p(t);if(r!==void 0){s(o,403,{error:r,ok:!1});return}const d=t.method==="GET"?"":await g(t);let h;try{h=d===""?void 0:JSON.parse(d)}catch{s(o,400,{error:"invalid-json",ok:!1});return}const f=e({...i,body:h,method:t.method??"POST",projectRoot:n});s(o,f.status,f.body)}catch(r){s(o,500,{error:r instanceof Error?r.message:String(r),ok:!1})}})().catch(()=>{})};export{v as serveJsonHandler};
@@ -0,0 +1 @@
1
+ import{collectWranglerSecretVariables as c}from"./collectWranglerSecretVariables-C6dWXkJK.mjs";import{writeFileSync as a,renameSync as i,rmSync as n}from"node:fs";const m=r=>({apiSpec:r.apiSpec,lunoraDirectory:r.schemaDirectory??"lunora",projectRoot:r.projectRoot,wranglerVariables:c(r.projectRoot)}),s=(r,t)=>{const o=`${r}.lunora-tmp`;try{a(o,t,"utf8"),i(o,r)}catch(e){throw n(o,{force:!0}),e}};export{m as s,s as w};
@@ -1,5 +1,6 @@
1
1
  import { IncomingMessage, ServerResponse } from 'node:http';
2
- import { D as DestructivePolicyEdit, S as ScaffoldPolicyEdit, W as WireRlsEdit } from "../packem_shared/policy-scaffold.d-fV3db0S_.mjs";
2
+ import { CodegenOptions } from '@lunora/codegen';
3
+ import { D as DestructivePolicyEdit, S as ScaffoldPolicyEdit, W as WireRlsEdit } from "../packem_shared/policy-scaffold.d-D2H4_G01.mjs";
3
4
  /**
4
5
  * Parse a single `KEY=value` (optionally quoted) out of a `.dev.vars` body,
5
6
  * returning `undefined` when the key is absent or its value is empty. A thin
@@ -9,11 +10,18 @@ import { D as DestructivePolicyEdit, S as ScaffoldPolicyEdit, W as WireRlsEdit }
9
10
  */
10
11
  declare const parseDevVariable: (contents: string, key: string) => string | undefined;
11
12
  /**
12
- * Resolve the worker's admin token so the studio can auto-authenticate in
13
- * dev. Prefers the `LUNORA_ADMIN_TOKEN` env var, then the project's `.dev.vars`
14
- * the same file `@cloudflare/vite-plugin` / `wrangler dev` feed the worker, so
15
- * the token the studio sends matches the one the worker's admin gate
16
- * verifies. Returns `undefined` when neither is set (the studio then prompts).
13
+ * Resolve the worker's admin token so the studio can auto-authenticate in dev.
14
+ *
15
+ * The ONLY source is the project's `.dev.vars` the file
16
+ * `@cloudflare/vite-plugin` / `wrangler dev` feed the local worker, and
17
+ * therefore the only token the worker's admin gate can verify. A shell-exported
18
+ * `LUNORA_ADMIN_TOKEN` (the documented way to run `lunora backup` /
19
+ * `lunora deploy --migrate` against **production**) never reaches the local
20
+ * worker's `env`, so embedding it would both fail the gate and put a production
21
+ * bearer into every `/__lunora` document served on the developer's machine.
22
+ * When the two disagree we say so once and keep using `.dev.vars`.
23
+ *
24
+ * Returns `undefined` when `.dev.vars` carries no token (the studio then prompts).
17
25
  */
18
26
  declare const resolveAdminToken: (root: string) => string | undefined;
19
27
  /**
@@ -157,6 +165,8 @@ interface WirePolicyEdit extends WireRlsEdit {
157
165
  type PolicyScaffoldBody = DestructivePolicyEdit | ScaffoldPolicyEdit | WirePolicyEdit;
158
166
  /** A request adapted from the host transport. */
159
167
  interface PolicyScaffoldRequest {
168
+ /** API-spec mode the host runs codegen with; forwarded to the regeneration. */
169
+ readonly apiSpec?: CodegenOptions["apiSpec"];
160
170
  /** Parsed JSON body of the `POST`. */
161
171
  readonly body?: unknown;
162
172
  /** HTTP method — only `POST` is handled. */
@@ -195,6 +205,8 @@ declare const renderStudioHtml: (config: StudioHtmlConfig) => string;
195
205
  declare const SCHEMA_EDIT_ENDPOINT = "/__lunora/schema-edit";
196
206
  /** A request adapted from the host transport. */
197
207
  interface SchemaEditRequest {
208
+ /** API-spec mode the host runs codegen with; forwarded to the regeneration. */
209
+ readonly apiSpec?: CodegenOptions["apiSpec"];
198
210
  /** Parsed JSON body for a `POST`; ignored for `GET`. */
199
211
  readonly body?: unknown;
200
212
  /** HTTP method (`GET` / `POST`). */
@@ -260,16 +272,25 @@ interface SeedResponse {
260
272
  * than fabricating parents), and return them JSON-safe for the client to insert.
261
273
  */
262
274
  declare const handleSeedRequest: (request: SeedRequest) => SeedResponse;
275
+ /**
276
+ * The host's project configuration, forwarded verbatim to the handler. Separate
277
+ * from `projectRoot` (which every host has) because these two come from the
278
+ * host's own Lunora options.
279
+ */
280
+ interface LocalEndpointContext {
281
+ /** API-spec mode the host runs codegen with, so a studio edit regenerates the same spec files. */
282
+ readonly apiSpec?: CodegenOptions["apiSpec"];
283
+ /** Override the lunora subdirectory name. Defaults to `"lunora"`. */
284
+ readonly schemaDirectory?: string;
285
+ }
263
286
  /** A request adapted from a host transport, passed to a local-dev handler. */
264
- interface LocalEndpointRequest {
287
+ interface LocalEndpointRequest extends LocalEndpointContext {
265
288
  /** Parsed JSON body of the request (`undefined` for `GET` / an empty body). */
266
289
  readonly body?: unknown;
267
290
  /** HTTP method. */
268
291
  readonly method: string;
269
292
  /** Project root containing the `lunora/` directory. */
270
293
  readonly projectRoot: string;
271
- /** Override the lunora subdirectory name. Defaults to `"lunora"`. */
272
- readonly schemaDirectory?: string;
273
294
  }
274
295
  /** A response a local-dev handler returns, serialised back as JSON with its status. */
275
296
  interface LocalEndpointResponse {
@@ -285,11 +306,12 @@ type LocalEndpointHandler = (request: LocalEndpointRequest) => LocalEndpointResp
285
306
  * handler's `{ status, body }` is serialised back as JSON. A malformed body is a
286
307
  * `400`; an unexpected throw (e.g. the body-size guard) is a `500`.
287
308
  *
288
- * `schemaDirectory` (when the host configures a custom `schemaDir`) is forwarded
289
- * to the handler so the schema/seed/policy endpoints target the right directory
290
- * instead of always defaulting to `"lunora"`.
309
+ * `context` carries the host's own Lunora options through to the handler: its
310
+ * `schemaDirectory` (so a custom `schemaDir` targets the right directory instead
311
+ * of defaulting to `"lunora"`) and its `apiSpec`, so a studio edit regenerates
312
+ * with the same options the host's own codegen run uses.
291
313
  */
292
- declare const serveJsonHandler: (request: IncomingMessage, response: ServerResponse, handle: LocalEndpointHandler, projectRoot: string, schemaDirectory?: string) => void;
314
+ declare const serveJsonHandler: (request: IncomingMessage, response: ServerResponse, handle: LocalEndpointHandler, projectRoot: string, context?: LocalEndpointContext) => void;
293
315
  /** A single header value, lower-cased and trimmed; `undefined` when absent or array-valued. */
294
316
  declare const headerValue: (raw: string | string[] | undefined) => string | undefined;
295
317
  /**
@@ -322,7 +344,7 @@ declare const ALLOW_FORWARDED_ENV = "LUNORA_STUDIO_ALLOW_FORWARDED";
322
344
  * the dev server, not just as an opaque 403 in the browser.
323
345
  */
324
346
  declare const transportRejectionReason: (request: IncomingMessage, logger?: WarnLogger) => string | undefined;
325
- export { ALLOW_FORWARDED_ENV, type LocalEndpointHandler, type LocalEndpointRequest, type LocalEndpointResponse, POLICY_SCAFFOLD_ENDPOINT, type PolicyScaffoldBody, type PolicyScaffoldRequest, type PolicyScaffoldResponse, SCHEMA_EDIT_ENDPOINT, SEED_ENDPOINT, type SchemaEditRequest, type SchemaEditResponse, type SeedRequest, type SeedRequestBody, type SeedResponse, type StudioAssets, type StudioHtmlConfig, type WarnLogger, type WirePolicyEdit, applyStudioAssetCache, assetContentType, handlePolicyScaffoldRequest, handleSchemaEditRequest, handleSeedRequest, headerValue, isLoopbackAddress, isStandaloneModulePath, loadStudioAssets,
347
+ export { ALLOW_FORWARDED_ENV, type LocalEndpointContext, type LocalEndpointHandler, type LocalEndpointRequest, type LocalEndpointResponse, POLICY_SCAFFOLD_ENDPOINT, type PolicyScaffoldBody, type PolicyScaffoldRequest, type PolicyScaffoldResponse, SCHEMA_EDIT_ENDPOINT, SEED_ENDPOINT, type SchemaEditRequest, type SchemaEditResponse, type SeedRequest, type SeedRequestBody, type SeedResponse, type StudioAssets, type StudioHtmlConfig, type WarnLogger, type WirePolicyEdit, applyStudioAssetCache, assetContentType, handlePolicyScaffoldRequest, handleSchemaEditRequest, handleSeedRequest, headerValue, isLoopbackAddress, isStandaloneModulePath, loadStudioAssets,
326
348
  /**
327
349
  * `@lunora/config/studio-host` — internal, build-time-shared helpers for hosting
328
350
  * the prebuilt `@lunora/studio` SPA during local dev.
@@ -1,5 +1,6 @@
1
1
  import { IncomingMessage, ServerResponse } from 'node:http';
2
- import { D as DestructivePolicyEdit, S as ScaffoldPolicyEdit, W as WireRlsEdit } from "../packem_shared/policy-scaffold.d-fV3db0S_.js";
2
+ import { CodegenOptions } from '@lunora/codegen';
3
+ import { D as DestructivePolicyEdit, S as ScaffoldPolicyEdit, W as WireRlsEdit } from "../packem_shared/policy-scaffold.d-D2H4_G01.js";
3
4
  /**
4
5
  * Parse a single `KEY=value` (optionally quoted) out of a `.dev.vars` body,
5
6
  * returning `undefined` when the key is absent or its value is empty. A thin
@@ -9,11 +10,18 @@ import { D as DestructivePolicyEdit, S as ScaffoldPolicyEdit, W as WireRlsEdit }
9
10
  */
10
11
  declare const parseDevVariable: (contents: string, key: string) => string | undefined;
11
12
  /**
12
- * Resolve the worker's admin token so the studio can auto-authenticate in
13
- * dev. Prefers the `LUNORA_ADMIN_TOKEN` env var, then the project's `.dev.vars`
14
- * the same file `@cloudflare/vite-plugin` / `wrangler dev` feed the worker, so
15
- * the token the studio sends matches the one the worker's admin gate
16
- * verifies. Returns `undefined` when neither is set (the studio then prompts).
13
+ * Resolve the worker's admin token so the studio can auto-authenticate in dev.
14
+ *
15
+ * The ONLY source is the project's `.dev.vars` the file
16
+ * `@cloudflare/vite-plugin` / `wrangler dev` feed the local worker, and
17
+ * therefore the only token the worker's admin gate can verify. A shell-exported
18
+ * `LUNORA_ADMIN_TOKEN` (the documented way to run `lunora backup` /
19
+ * `lunora deploy --migrate` against **production**) never reaches the local
20
+ * worker's `env`, so embedding it would both fail the gate and put a production
21
+ * bearer into every `/__lunora` document served on the developer's machine.
22
+ * When the two disagree we say so once and keep using `.dev.vars`.
23
+ *
24
+ * Returns `undefined` when `.dev.vars` carries no token (the studio then prompts).
17
25
  */
18
26
  declare const resolveAdminToken: (root: string) => string | undefined;
19
27
  /**
@@ -157,6 +165,8 @@ interface WirePolicyEdit extends WireRlsEdit {
157
165
  type PolicyScaffoldBody = DestructivePolicyEdit | ScaffoldPolicyEdit | WirePolicyEdit;
158
166
  /** A request adapted from the host transport. */
159
167
  interface PolicyScaffoldRequest {
168
+ /** API-spec mode the host runs codegen with; forwarded to the regeneration. */
169
+ readonly apiSpec?: CodegenOptions["apiSpec"];
160
170
  /** Parsed JSON body of the `POST`. */
161
171
  readonly body?: unknown;
162
172
  /** HTTP method — only `POST` is handled. */
@@ -195,6 +205,8 @@ declare const renderStudioHtml: (config: StudioHtmlConfig) => string;
195
205
  declare const SCHEMA_EDIT_ENDPOINT = "/__lunora/schema-edit";
196
206
  /** A request adapted from the host transport. */
197
207
  interface SchemaEditRequest {
208
+ /** API-spec mode the host runs codegen with; forwarded to the regeneration. */
209
+ readonly apiSpec?: CodegenOptions["apiSpec"];
198
210
  /** Parsed JSON body for a `POST`; ignored for `GET`. */
199
211
  readonly body?: unknown;
200
212
  /** HTTP method (`GET` / `POST`). */
@@ -260,16 +272,25 @@ interface SeedResponse {
260
272
  * than fabricating parents), and return them JSON-safe for the client to insert.
261
273
  */
262
274
  declare const handleSeedRequest: (request: SeedRequest) => SeedResponse;
275
+ /**
276
+ * The host's project configuration, forwarded verbatim to the handler. Separate
277
+ * from `projectRoot` (which every host has) because these two come from the
278
+ * host's own Lunora options.
279
+ */
280
+ interface LocalEndpointContext {
281
+ /** API-spec mode the host runs codegen with, so a studio edit regenerates the same spec files. */
282
+ readonly apiSpec?: CodegenOptions["apiSpec"];
283
+ /** Override the lunora subdirectory name. Defaults to `"lunora"`. */
284
+ readonly schemaDirectory?: string;
285
+ }
263
286
  /** A request adapted from a host transport, passed to a local-dev handler. */
264
- interface LocalEndpointRequest {
287
+ interface LocalEndpointRequest extends LocalEndpointContext {
265
288
  /** Parsed JSON body of the request (`undefined` for `GET` / an empty body). */
266
289
  readonly body?: unknown;
267
290
  /** HTTP method. */
268
291
  readonly method: string;
269
292
  /** Project root containing the `lunora/` directory. */
270
293
  readonly projectRoot: string;
271
- /** Override the lunora subdirectory name. Defaults to `"lunora"`. */
272
- readonly schemaDirectory?: string;
273
294
  }
274
295
  /** A response a local-dev handler returns, serialised back as JSON with its status. */
275
296
  interface LocalEndpointResponse {
@@ -285,11 +306,12 @@ type LocalEndpointHandler = (request: LocalEndpointRequest) => LocalEndpointResp
285
306
  * handler's `{ status, body }` is serialised back as JSON. A malformed body is a
286
307
  * `400`; an unexpected throw (e.g. the body-size guard) is a `500`.
287
308
  *
288
- * `schemaDirectory` (when the host configures a custom `schemaDir`) is forwarded
289
- * to the handler so the schema/seed/policy endpoints target the right directory
290
- * instead of always defaulting to `"lunora"`.
309
+ * `context` carries the host's own Lunora options through to the handler: its
310
+ * `schemaDirectory` (so a custom `schemaDir` targets the right directory instead
311
+ * of defaulting to `"lunora"`) and its `apiSpec`, so a studio edit regenerates
312
+ * with the same options the host's own codegen run uses.
291
313
  */
292
- declare const serveJsonHandler: (request: IncomingMessage, response: ServerResponse, handle: LocalEndpointHandler, projectRoot: string, schemaDirectory?: string) => void;
314
+ declare const serveJsonHandler: (request: IncomingMessage, response: ServerResponse, handle: LocalEndpointHandler, projectRoot: string, context?: LocalEndpointContext) => void;
293
315
  /** A single header value, lower-cased and trimmed; `undefined` when absent or array-valued. */
294
316
  declare const headerValue: (raw: string | string[] | undefined) => string | undefined;
295
317
  /**
@@ -322,7 +344,7 @@ declare const ALLOW_FORWARDED_ENV = "LUNORA_STUDIO_ALLOW_FORWARDED";
322
344
  * the dev server, not just as an opaque 403 in the browser.
323
345
  */
324
346
  declare const transportRejectionReason: (request: IncomingMessage, logger?: WarnLogger) => string | undefined;
325
- export { ALLOW_FORWARDED_ENV, type LocalEndpointHandler, type LocalEndpointRequest, type LocalEndpointResponse, POLICY_SCAFFOLD_ENDPOINT, type PolicyScaffoldBody, type PolicyScaffoldRequest, type PolicyScaffoldResponse, SCHEMA_EDIT_ENDPOINT, SEED_ENDPOINT, type SchemaEditRequest, type SchemaEditResponse, type SeedRequest, type SeedRequestBody, type SeedResponse, type StudioAssets, type StudioHtmlConfig, type WarnLogger, type WirePolicyEdit, applyStudioAssetCache, assetContentType, handlePolicyScaffoldRequest, handleSchemaEditRequest, handleSeedRequest, headerValue, isLoopbackAddress, isStandaloneModulePath, loadStudioAssets,
347
+ export { ALLOW_FORWARDED_ENV, type LocalEndpointContext, type LocalEndpointHandler, type LocalEndpointRequest, type LocalEndpointResponse, POLICY_SCAFFOLD_ENDPOINT, type PolicyScaffoldBody, type PolicyScaffoldRequest, type PolicyScaffoldResponse, SCHEMA_EDIT_ENDPOINT, SEED_ENDPOINT, type SchemaEditRequest, type SchemaEditResponse, type SeedRequest, type SeedRequestBody, type SeedResponse, type StudioAssets, type StudioHtmlConfig, type WarnLogger, type WirePolicyEdit, applyStudioAssetCache, assetContentType, handlePolicyScaffoldRequest, handleSchemaEditRequest, handleSeedRequest, headerValue, isLoopbackAddress, isStandaloneModulePath, loadStudioAssets,
326
348
  /**
327
349
  * `@lunora/config/studio-host` — internal, build-time-shared helpers for hosting
328
350
  * the prebuilt `@lunora/studio` SPA during local dev.
@@ -1 +1 @@
1
- import{parseDevVariable as t,resolveAdminToken as r}from"../packem_shared/parseDevVariable-cacbGJkN.mjs";import{applyStudioAssetCache as s,sendStudioDocument as d}from"../packem_shared/applyStudioAssetCache-DHQEJuuv.mjs";import{assetContentType as l,isStandaloneModulePath as p,loadStudioAssets as m,readStandaloneAsset as S,resolveStandaloneDirectory as i,studioAssetsStamp as f}from"../packem_shared/assetContentType-CUb5bpbI.mjs";import{POLICY_SCAFFOLD_ENDPOINT as D,handlePolicyScaffoldRequest as A}from"../packem_shared/POLICY_SCAFFOLD_ENDPOINT-C1gb9ykA.mjs";import{default as x}from"../packem_shared/renderStudioHtml-ByowDtMl.mjs";import{SCHEMA_EDIT_ENDPOINT as h,handleSchemaEditRequest as N}from"../packem_shared/SCHEMA_EDIT_ENDPOINT-CknH7oga.mjs";import{SEED_ENDPOINT as R,handleSeedRequest as _}from"../packem_shared/SEED_ENDPOINT-DVzCYp6l.mjs";import{serveJsonHandler as T}from"../packem_shared/serveJsonHandler-CB85A2S9.mjs";import{ALLOW_FORWARDED_ENV as I,headerValue as L,isLoopbackAddress as v,transportRejectionReason as y}from"../packem_shared/ALLOW_FORWARDED_ENV-BUndghJx.mjs";export{I as ALLOW_FORWARDED_ENV,D as POLICY_SCAFFOLD_ENDPOINT,h as SCHEMA_EDIT_ENDPOINT,R as SEED_ENDPOINT,s as applyStudioAssetCache,l as assetContentType,A as handlePolicyScaffoldRequest,N as handleSchemaEditRequest,_ as handleSeedRequest,L as headerValue,v as isLoopbackAddress,p as isStandaloneModulePath,m as loadStudioAssets,t as parseDevVariable,S as readStandaloneAsset,x as renderStudioHtml,r as resolveAdminToken,i as resolveStandaloneDirectory,d as sendStudioDocument,T as serveJsonHandler,f as studioAssetsStamp,y as transportRejectionReason};
1
+ import{parseDevVariable as t,resolveAdminToken as r}from"../packem_shared/parseDevVariable-teAAahVD.mjs";import{applyStudioAssetCache as s,sendStudioDocument as d}from"../packem_shared/applyStudioAssetCache-DHQEJuuv.mjs";import{assetContentType as l,isStandaloneModulePath as p,loadStudioAssets as m,readStandaloneAsset as S,resolveStandaloneDirectory as i,studioAssetsStamp as f}from"../packem_shared/assetContentType-CUb5bpbI.mjs";import{POLICY_SCAFFOLD_ENDPOINT as D,handlePolicyScaffoldRequest as A}from"../packem_shared/POLICY_SCAFFOLD_ENDPOINT-DJBuzyqL.mjs";import{default as x}from"../packem_shared/renderStudioHtml-ByowDtMl.mjs";import{SCHEMA_EDIT_ENDPOINT as h,handleSchemaEditRequest as N}from"../packem_shared/SCHEMA_EDIT_ENDPOINT-OF4_A2xT.mjs";import{SEED_ENDPOINT as R,handleSeedRequest as _}from"../packem_shared/SEED_ENDPOINT-DVzCYp6l.mjs";import{serveJsonHandler as T}from"../packem_shared/serveJsonHandler-Dv0EdCb9.mjs";import{ALLOW_FORWARDED_ENV as I,headerValue as L,isLoopbackAddress as v,transportRejectionReason as y}from"../packem_shared/ALLOW_FORWARDED_ENV-BUndghJx.mjs";export{I as ALLOW_FORWARDED_ENV,D as POLICY_SCAFFOLD_ENDPOINT,h as SCHEMA_EDIT_ENDPOINT,R as SEED_ENDPOINT,s as applyStudioAssetCache,l as assetContentType,A as handlePolicyScaffoldRequest,N as handleSchemaEditRequest,_ as handleSeedRequest,L as headerValue,v as isLoopbackAddress,p as isStandaloneModulePath,m as loadStudioAssets,t as parseDevVariable,S as readStandaloneAsset,x as renderStudioHtml,r as resolveAdminToken,i as resolveStandaloneDirectory,d as sendStudioDocument,T as serveJsonHandler,f as studioAssetsStamp,y as transportRejectionReason};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/config",
3
- "version": "1.0.0-alpha.184",
3
+ "version": "1.0.0-alpha.185",
4
4
  "description": "Internal shared CLI + Vite config layer for Lunora: wrangler.jsonc validation, binding inference, and .dev.vars scaffolding",
5
5
  "keywords": [
6
6
  "bindings",
@@ -54,10 +54,10 @@
54
54
  "access": "public"
55
55
  },
56
56
  "dependencies": {
57
- "@lunora/codegen": "1.0.0-alpha.150",
58
- "@lunora/container": "1.0.0-alpha.40",
59
- "@lunora/errors": "1.0.0-alpha.29",
60
- "@lunora/seed": "1.0.0-alpha.101",
57
+ "@lunora/codegen": "1.0.0-alpha.151",
58
+ "@lunora/container": "1.0.0-alpha.41",
59
+ "@lunora/errors": "1.0.0-alpha.30",
60
+ "@lunora/seed": "1.0.0-alpha.102",
61
61
  "@visulima/colorize": "2.1.1",
62
62
  "@visulima/find-ai-runner": "1.0.1",
63
63
  "@visulima/package": "5.0.12",
@@ -1 +0,0 @@
1
- const r=[{description:"Bearer token the local Lunora Studio uses to call the worker's admin endpoints (data browser, schema edits) in dev. Generate with: openssl rand -hex 32",docsUrl:"https://lunora.sh/docs/packages/studio",key:"LUNORA_ADMIN_TOKEN",placeholderValue:"replace-with-openssl-rand-hex-32"}],t={"@lunora/auth":[{description:"32-byte random secret used to sign sessions and tokens. Generate with: openssl rand -hex 32",docsUrl:"https://lunora.sh/docs/packages/auth#secrets",key:"AUTH_SECRET",placeholderValue:"replace-with-openssl-rand-hex-32"},{description:"Public base URL of your worker (used by better-auth for redirects and cookie domain). For local dev this is typically http://localhost:8787",docsUrl:"https://lunora.sh/docs/packages/auth#secrets",key:"AUTH_URL",placeholderValue:"http://localhost:8787"}],"@lunora/mail":[{description:"Resend API key for sending transactional email via @lunora/mail. Obtain at https://resend.com/api-keys",docsUrl:"https://lunora.sh/docs/packages/mail#secrets",key:"RESEND_API_KEY",placeholderValue:"<your-resend-api-key>"}],"@lunora/notify":[{description:"Public VAPID key (base64url) for Web Push. Generate a keypair once with: npx web-push generate-vapid-keys — the public key is also shipped to the browser to subscribe.",docsUrl:"https://lunora.sh/docs/packages/notify#web-push",key:"VAPID_PUBLIC_KEY",placeholderValue:"<your-vapid-public-key>"},{description:"Private VAPID key (base64url) for Web Push — the application-server signing key. Generate with: npx web-push generate-vapid-keys",docsUrl:"https://lunora.sh/docs/packages/notify#web-push",key:"VAPID_PRIVATE_KEY",placeholderValue:"<your-vapid-private-key>"},{description:"VAPID `sub` contact — a mailto: or https: URL identifying the application server (e.g. mailto:you@example.com).",docsUrl:"https://lunora.sh/docs/packages/notify#web-push",key:"VAPID_SUBJECT",placeholderValue:"mailto:you@example.com"},{description:"Firebase project id for FCM (HTTP v1) push. Found in the Firebase console project settings.",docsUrl:"https://lunora.sh/docs/packages/notify#fcm",key:"FCM_PROJECT_ID",placeholderValue:"<your-firebase-project-id>"},{description:"OAuth2 access token for FCM (HTTP v1). Convenient for dev but expires — in production supply a getAccessToken() in defineNotify instead. Obtain via the Google Cloud SDK / a service account.",docsUrl:"https://lunora.sh/docs/packages/notify#fcm",key:"FCM_ACCESS_TOKEN",placeholderValue:"<your-fcm-access-token>"}],"@lunora/payment":[{description:"Stripe secret key (sk_test_…). Required when using the Stripe adapter. Obtain at https://dashboard.stripe.com/apikeys",docsUrl:"https://lunora.sh/docs/packages/payment#stripe",key:"STRIPE_SECRET_KEY",placeholderValue:"<your-stripe-secret-key>"},{description:"Stripe webhook signing secret (whsec_…) for verifying event payloads. Obtain at https://dashboard.stripe.com/webhooks",docsUrl:"https://lunora.sh/docs/packages/payment#stripe",key:"STRIPE_WEBHOOK_SECRET",placeholderValue:"<your-stripe-webhook-secret>"},{description:"Polar access token for the Polar payment adapter. Obtain at https://polar.sh/settings/tokens",docsUrl:"https://lunora.sh/docs/packages/payment#polar",key:"POLAR_ACCESS_TOKEN",placeholderValue:"<your-polar-access-token>"},{description:"Polar webhook secret for verifying event payloads from Polar. Obtain at https://polar.sh/settings/webhooks",docsUrl:"https://lunora.sh/docs/packages/payment#polar",key:"POLAR_WEBHOOK_SECRET",placeholderValue:"<your-polar-webhook-secret>"},{description:"Autumn secret key (am_sk_…) for the Autumn payment adapter. Obtain at https://app.useautumn.com/dev",docsUrl:"https://lunora.sh/docs/packages/payment#autumn",key:"AUTUMN_SECRET_KEY",placeholderValue:"<your-autumn-secret-key>"},{description:"Autumn webhook signing secret for verifying Standard Webhooks event payloads. Obtain from your Autumn dashboard webhook settings.",docsUrl:"https://lunora.sh/docs/packages/payment#autumn",key:"AUTUMN_WEBHOOK_SECRET",placeholderValue:"<your-autumn-webhook-secret>"},{description:"Dodo Payments API key (bearer token) for the Dodo Payments adapter. Obtain at https://app.dodopayments.com/developer/api-keys",docsUrl:"https://lunora.sh/docs/packages/payment#dodo-payments",key:"DODO_PAYMENTS_API_KEY",placeholderValue:"<your-dodo-payments-api-key>"},{description:"Dodo Payments webhook signing secret (whsec_…) for verifying event payloads. Obtain at https://app.dodopayments.com/developer/webhooks",docsUrl:"https://lunora.sh/docs/packages/payment#dodo-payments",key:"DODO_PAYMENTS_WEBHOOK_KEY",placeholderValue:"<your-dodo-payments-webhook-secret>"},{description:"Creem API key for the Creem payment adapter. Obtain at https://www.creem.io/dashboard/developers",docsUrl:"https://lunora.sh/docs/packages/payment#creem",key:"CREEM_API_KEY",placeholderValue:"<your-creem-api-key>"},{description:"Creem webhook signing secret for verifying the creem-signature header. Obtain from your Creem dashboard webhook settings.",docsUrl:"https://lunora.sh/docs/packages/payment#creem",key:"CREEM_WEBHOOK_SECRET",placeholderValue:"<your-creem-webhook-secret>"}]},n=s=>{const e=[];for(const a of s){const o=t[a];o!==void 0&&e.push(...o)}return e};export{r as CORE_SECRETS,t as PACKAGE_SECRETS_REGISTRY,n as secretsForPackages};
@@ -1 +0,0 @@
1
- import{existsSync as c,readFileSync as f}from"node:fs";import{join as s,isAbsolute as a,relative as y}from"node:path";import{runCodegen as m,CodegenDiagnosticError as p}from"@lunora/codegen";import{LunoraError as k}from"@lunora/errors";import{classifyPolicyEdit as g,scaffoldPolicyFile as h,wireRlsIntoProcedure as b}from"./classifyPolicyEdit-BfSiVpv-.mjs";import{w as l}from"./write-atomic-ooiPzStx.mjs";const j="/__lunora/policy-scaffold",d=e=>e==="unknown-procedure"?404:e==="already-wired"||e==="destructive"?409:422,u=(e,o)=>{let r=[];try{m({lunoraDirectory:e.schemaDirectory??"lunora",projectRoot:e.projectRoot})}catch(t){if(t instanceof p)r=[t.message];else return{body:{error:t instanceof Error?t.message:String(t),ok:!1},status:500}}return{body:{...o,diagnostics:r,ok:!0},status:200}},v=e=>({body:{edit:e,message:"Rewriting an existing policy predicate changes evaluation semantics and must be done by hand. The scaffolder only adds new, deny-by-default rules.",needsManualEdit:!0,ok:!1},status:409}),w=(e,o)=>{const r=h(o);if(!r.ok)return{body:{error:r.reason,ok:!1},status:d(r.reason)};const t=e.schemaDirectory??"lunora",n=s(e.projectRoot,t,r.fileName);return c(n)?{body:{error:"file-exists",fileName:r.fileName,ok:!1},status:409}:(l(n,r.source),u(e,{fileName:r.fileName}))},R=(e,o,r)=>{if(typeof r!="string"||r.length===0||a(r)||r.includes("\\"))return;const t=s(e,o),n=s(t,`${r}.ts`),i=y(t,n);if(!(i.startsWith("..")||a(i)))return n},N=(e,o)=>{const r=R(e.projectRoot,e.schemaDirectory??"lunora",o.filePath);if(r===void 0||!c(r))return{body:{error:"unknown-procedure",ok:!1},status:404};const t=b(f(r,"utf8"),o);return t.ok?(l(r,t.text),u(e,{exportName:o.exportName})):{body:{error:t.reason,ok:!1},status:d(t.reason)}},C=e=>{if(e.method!=="POST")return{body:{error:"method-not-allowed",ok:!1},status:405};const{body:o}=e;if(o==null||typeof o!="object"||typeof o.kind!="string")return{body:{error:"invalid-edit",ok:!1},status:400};const r=o;if(g(r)==="destructive")return v(r);if(r.kind==="scaffoldPolicy")return w(e,r);if(r.kind==="wireRls")return N(e,r);throw new k("INTERNAL",`unhandled additive policy edit kind: ${String(r.kind)}`)};export{j as POLICY_SCAFFOLD_ENDPOINT,C as handlePolicyScaffoldRequest};
@@ -1 +0,0 @@
1
- import{existsSync as f,readFileSync as M}from"node:fs";import{dirname as A,join as p}from"node:path";import{WORKER_ENTRY_FALLBACKS as O}from"./inferLunoraBindings-7kPfAt6p.mjs";import{discoverSchemaInfo as D}from"./discoverSchemaInfo-Bg2CUZXG.mjs";import{isCacheEnabled as x,WORKERS_CACHE_MIN_DATE as _}from"./WORKERS_CACHE_MIN_DATE-0k9ABJtF.mjs";import{findWranglerFile as N,readWranglerJsonc as I}from"./WRANGLER_FILES-UNW-xY5u.mjs";const v="2026-04-07",Ie="web_socket_auto_reply_to_close",$=/^\d{4}-\d{2}-\d{2}$/,E=["d1_databases","durable_objects","kv_namespaces","queues","r2_buckets","secrets_store_secrets","services","tail_consumers","vars","vectorize","workflows"],S=["assets","compatibility_date","exports","logpush","main","migrations","observability","placement"],R=(e,s)=>{if(s===void 0)return{merged:e,unverifiedKeys:[]};const t=e.env?.[s];if(t===void 0){const c=Object.keys(e.env??{}).toSorted((r,l)=>r.localeCompare(l)),d=c.length>0?` (declared: ${c.join(", ")}).`:" (no environments are declared).";return{error:`--env "${s}" names no environment declared in wrangler.jsonc's "env" block${d}`,merged:e,unverifiedKeys:[]}}const n={...e},a=Object.keys(t).filter(c=>c!=="env");for(const c of a)S.includes(c)&&(n[c]=t[c]);for(const c of E)n[c]=t[c];const i=new Set([...E,...S]),o=a.filter(c=>!i.has(c)).map(String);return{merged:n,unverifiedKeys:o}},C=(e,s,t)=>{if(s.length===0)return;const n=e.vectorize??[],a=new Set(n.filter(Boolean).map(i=>i?.index_name));for(const i of s)a.has(i)||t.push(`schema declares vector index "${i}"; wrangler "vectorize" must include a binding with index_name "${i}"`)},L=new Set(["basic","dev","lite","standard","standard-1","standard-2","standard-3","standard-4"]),T={disk_mb:2e4,memory_mib:12288,vcpu:4},B=(e,s,t)=>{const n=e.instance_type;if(n===void 0)return;if(typeof n=="string"){L.has(n)||t.push(`${s} has unknown instance_type "${n}" — expected lite, basic, standard-1..4, or a custom { vcpu, memory_mib, disk_mb } object`);return}for(const[c,d]of Object.entries(T)){const r=n[c];r!==void 0&&(typeof r!="number"||r<=0||r>d)&&t.push(`${s} custom instance_type ${c} must be a positive number ≤ ${String(d)} (got ${String(r)})`)}const{disk_mb:a,memory_mib:i,vcpu:o}=n;if(typeof o=="number"&&typeof i=="number"&&i<o*3072&&t.push(`${s} custom instance_type needs ≥ 3 GiB (3072 MiB) memory per vCPU (got ${String(i)} MiB for ${String(o)} vCPU)`),typeof i=="number"&&typeof a=="number"){const c=Math.floor(i/1024*2e3);a>c&&t.push(`${s} custom instance_type allows ≤ 2 GB disk per GiB memory (≤ ${String(c)} MB for ${String(i)} MiB memory; got ${String(a)} MB)`)}},W=(e,s,t)=>{const{boundClasses:n,errors:a,nonSqliteClasses:i,sqliteClasses:o,warnings:c}=t;if(!e||typeof e!="object"||typeof e.class_name!="string"||e.class_name.length===0){a.push(`${s} must have a non-empty "class_name" naming its container-enabled Durable Object class`);return}(typeof e.image!="string"||e.image.length===0)&&a.push(`${s} ("${e.class_name}") must have an "image" — a Dockerfile path or a registry reference`),n.has(e.class_name)||a.push(`${s} class "${e.class_name}" has no matching durable_objects binding — run \`lunora dev\` to auto-reconcile wrangler.jsonc, or add { "name": "...", "class_name": "${e.class_name}" }`),o.has(e.class_name)||a.push(i.has(e.class_name)?`${s} class "${e.class_name}" is registered via "new_classes" but containers require SQLite-backed DOs — move it to "new_sqlite_classes"`:`${s} class "${e.class_name}" is missing from migrations — add a migration entry with "new_sqlite_classes": ["${e.class_name}"]`),B(e,`${s} ("${e.class_name}")`,a),e.max_instances===void 0&&c.push(`${s} ("${e.class_name}") declares no max_instances — set a cap so a traffic spike can't fan out unbounded container spend`)},m=e=>typeof e=="string"&&e.length>0,b=e=>Array.isArray(e)?e.filter(s=>s!==null&&typeof s=="object"):[],h=e=>Array.isArray(e)?e.filter(s=>m(s)):[],q=e=>{const s=new Set;for(const t of b(e)){for(const n of h(t.new_classes))s.add(n);for(const n of h(t.new_sqlite_classes))s.add(n);for(const n of b(t.renamed_classes))m(n.from)&&m(n.to)&&(s.delete(n.from),s.add(n.to));for(const n of h(t.deleted_classes))s.delete(n)}return s},U=(e,s)=>{const t=q(e.migrations);for(const n of b(e.durable_objects?.bindings))n.script_name===void 0&&m(n.class_name)&&!t.has(n.class_name)&&s.push(`durable_objects.bindings declares class "${n.class_name}" but it is missing from migrations — add a migration entry with "new_sqlite_classes": ["${n.class_name}"] (or "new_classes" for a non-SQLite-backed class), or run \`lunora dev\` to auto-reconcile wrangler.jsonc`)},F=(e,s,t)=>{if(e.containers===void 0)return;if(!Array.isArray(e.containers)){s.push("containers must be an array of { class_name, image, ... } entries");return}const n=e.containers;if(n.length===0)return;const a=new Set(b(e.durable_objects?.bindings).map(d=>d.class_name)),i=e.migrations??[],o=new Set(i.flatMap(d=>[...d?.new_sqlite_classes??[]])),c=new Set(i.flatMap(d=>[...d?.new_classes??[]]));for(const[d,r]of n.entries())W(r,`containers[${String(d)}]`,{boundClasses:a,errors:s,nonSqliteClasses:c,sqliteClasses:o,warnings:t});e.observability?.enabled!==!0&&t.push('containers are configured but observability is not enabled — container logs will not be captured (add { "observability": { "enabled": true } })')},y=e=>e,g=(e,s,t,n)=>{if(e!==void 0){if(!Array.isArray(e)){n.push(t.arrayMessage);return}for(const[a,i]of y(e).entries()){const o=`${s}[${String(a)}]`;if(!i||typeof i!="object"){n.push(t.objectMessage(o));continue}for(const c of t.fields)m(i[c.field])||n.push(c.message(o))}}},P={arrayMessage:"workflows must be an array of { name, binding, class_name } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding" naming the Workflow binding (e.g. WORKFLOW_ORDER_PIPELINE)`},{field:"class_name",message:e=>`${e} must have a non-empty "class_name" naming the exported WorkflowEntrypoint class`},{field:"name",message:e=>`${e} must have a non-empty "name" naming the deployed workflow`}],objectMessage:e=>`${e} must be a { name, binding, class_name } object`},K={arrayMessage:"queues.producers must be an array of { binding, queue } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding" naming the Queue producer (e.g. QUEUE_EMAIL)`},{field:"queue",message:e=>`${e} must have a non-empty "queue" naming the deployed queue`}],objectMessage:e=>`${e} must be a { binding, queue } object`},G={arrayMessage:"queues.consumers must be an array of { queue } entries",fields:[{field:"queue",message:e=>`${e} must have a non-empty "queue" naming the consumed queue`}],objectMessage:e=>`${e} must be a { queue } object`},Y=(e,s)=>{if(e.queues!==void 0){if(typeof e.queues!="object"||Array.isArray(e.queues)){s.push("queues must be a { producers, consumers } object");return}g(e.queues.producers,"queues.producers",K,s),g(e.queues.consumers,"queues.consumers",G,s)}},H={arrayMessage:"secrets_store_secrets must be an array of { binding, store_id, secret_name } entries",fields:["binding","store_id","secret_name"].map(e=>({field:e,message:s=>`${s} must have a non-empty "${e}"`})),objectMessage:e=>`${e} must be a { binding, store_id, secret_name } object`},Q=[{arrayMessage:"kv_namespaces must be an array of { binding, id } entries",bindingMessage:e=>`${e} must have a non-empty "binding" naming the KV namespace binding`,hintField:"id",hintMessage:(e,s)=>`${e} ("${s}") has no "id" — run \`wrangler kv namespace create\` and set the namespace id, or the binding can't resolve`,key:"kv_namespaces"},{arrayMessage:"flagship must be an array of { binding, app_id } entries",bindingMessage:e=>`${e} must have a non-empty "binding" naming the Flagship binding`,hintField:"app_id",hintMessage:(e,s)=>`${e} ("${s}") has no "app_id" — create a Flagship app and set its id, or the binding can't resolve`,key:"flagship"},{arrayMessage:"hyperdrive must be an array of { binding, id } entries",bindingMessage:e=>`${e} must have a non-empty "binding" naming the Hyperdrive binding`,hintField:"id",hintMessage:(e,s)=>`${e} ("${s}") has no "id" — run \`wrangler hyperdrive create\` and set the id, or the binding can't connect`,key:"hyperdrive"},{arrayMessage:"pipelines must be an array of { binding, stream } entries",bindingMessage:e=>`${e} must have a non-empty "binding" naming the Pipelines binding`,hintField:["stream","pipeline"],hintMessage:(e,s)=>`${e} ("${s}") has no "stream" — run \`wrangler pipelines create <name>\` and set the stream name, or the binding can't resolve`,key:"pipelines"},{arrayMessage:"analytics_engine_datasets must be an array of { binding, dataset } entries",bindingMessage:e=>`${e} must have a non-empty "binding" naming the Analytics Engine binding`,hintField:"dataset",hintMessage:(e,s)=>`${e} ("${s}") has no "dataset" — it defaults to the binding name; set it explicitly to avoid drift`,key:"analytics_engine_datasets"}],V=(e,s,t,n)=>{const a=e[s.key];if(a!==void 0){if(!Array.isArray(a)){t.push(s.arrayMessage);return}for(const[i,o]of y(a).entries()){const c=`${s.key}[${String(i)}]`;if(!o||typeof o!="object"||!m(o.binding)){t.push(s.bindingMessage(c));continue}(typeof s.hintField=="string"?[s.hintField]:s.hintField).some(r=>m(o[r]))||n.push(s.hintMessage(c,o.binding))}}},z=[{key:"browser",message:'browser must be an object with a non-empty "binding" (e.g. { "binding": "BROWSER" })'},{key:"images",message:'images must be an object with a non-empty "binding" (e.g. { "binding": "IMAGES" })'}],X=(e,s,t)=>{const n=e[s.key];n!==void 0&&(typeof n!="object"||Array.isArray(n)||!m(n.binding))&&t.push(s.message)},J=[{arrayMessage:"services must be an array of { binding, service, entrypoint? } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding" naming the service binding`},{field:"service",message:e=>`${e} must have a non-empty "service" naming the target Worker`}],key:"services",objectMessage:e=>`${e} must be a { binding, service, entrypoint? } object`},{arrayMessage:"dispatch_namespaces must be an array of { binding, namespace } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding"`},{field:"namespace",message:e=>`${e} must have a non-empty "namespace" naming the dispatch namespace`}],key:"dispatch_namespaces",objectMessage:e=>`${e} must be a { binding, namespace } object`},{arrayMessage:"mtls_certificates must be an array of { binding, certificate_id } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding"`},{field:"certificate_id",message:e=>`${e} must have a non-empty "certificate_id" (upload via \`wrangler mtls-certificate upload\`)`}],key:"mtls_certificates",objectMessage:e=>`${e} must be a { binding, certificate_id } object`},{arrayMessage:"r2_buckets must be an array of { binding, bucket_name } entries",fields:[{field:"binding",message:e=>`${e} must have a non-empty "binding" naming the R2 bucket binding`},{field:"bucket_name",message:e=>`${e} must have a non-empty "bucket_name" naming the deployed bucket`}],key:"r2_buckets",objectMessage:e=>`${e} must be a { binding, bucket_name } object`}],Z=(e,s)=>{const{d1_databases:t}=e;if(t!==void 0){if(!Array.isArray(t)){s.push("d1_databases must be an array of { binding, database_id | database_name } entries");return}for(const[n,a]of y(t).entries()){const i=`d1_databases[${String(n)}]`;if(!a||typeof a!="object"){s.push(`${i} must be a { binding, database_id | database_name } object`);continue}m(a.binding)||s.push(`${i} must have a non-empty "binding" naming the D1 binding`),!m(a.database_id)&&!m(a.database_name)&&s.push(`${i} must have a "database_id" or a "database_name" — run \`wrangler d1 create\` and set one, or the binding can't resolve`)}}},ee=(e,s,t)=>{const n=e.send_email;if(n===void 0)return;if(!Array.isArray(n)){s.push("send_email must be an array of { name, destination_address? } entries");return}const a=n;for(const[i,o]of a.entries())(!o||typeof o!="object"||typeof o.name!="string"||o.name.length===0)&&t.push(`send_email[${String(i)}] has no non-empty "name" naming the send-email binding — set one before deploying`)},se=(e,s)=>{e.logpush!==void 0&&typeof e.logpush!="boolean"&&s.push('logpush must be a boolean (set "logpush": true to enable Cloudflare Logpush)')},ne=(e,s)=>{const{placement:t}=e;if(t!==void 0){if(typeof t!="object"||Array.isArray(t)){s.push('placement must be an object (e.g. { "mode": "smart" })');return}t.mode!==void 0&&t.mode!=="smart"&&s.push('placement.mode must be "smart" (the only supported Smart Placement mode)')}},te=(e,s)=>{const{observability:t}=e;if(t===void 0)return;if(typeof t!="object"||Array.isArray(t)){s.push('observability must be an object (e.g. { "enabled": true, "head_sampling_rate": 1 })');return}const n=(a,i)=>{a!==void 0&&(typeof a!="number"||Number.isNaN(a)||a<0||a>1)&&s.push(`${i} must be a number in [0, 1] (the fraction of requests sampled)`)};n(t.head_sampling_rate,"observability.head_sampling_rate"),t.logs!==void 0&&(typeof t.logs!="object"||Array.isArray(t.logs)?s.push("observability.logs must be an object"):n(t.logs.head_sampling_rate,"observability.logs.head_sampling_rate"))},ae=(e,s)=>{const{cache:t}=e;if(t!==void 0){if(typeof t!="object"||t===null||Array.isArray(t)){s.push('cache must be an object (e.g. { "enabled": true })');return}t.enabled!==void 0&&typeof t.enabled!="boolean"&&s.push("cache.enabled must be a boolean (true or false)")}},ie=(e,s)=>{const{exports:t}=e;if(t!==void 0){if(typeof t!="object"||t===null||Array.isArray(t)){s.push("exports must be an object keyed by entrypoint name");return}for(const[n,a]of Object.entries(t)){if(typeof a!="object"||a===null){s.push(`exports["${n}"] must be an object`);continue}a.type!==void 0&&typeof a.type!="string"&&s.push(`exports["${n}"].type must be a string`),a.cache!==void 0&&(typeof a.cache!="object"||a.cache===null||Array.isArray(a.cache)?s.push(`exports["${n}"].cache must be an object`):a.cache.enabled!==void 0&&typeof a.cache.enabled!="boolean"&&s.push(`exports["${n}"].cache.enabled must be a boolean`))}}},oe=(e,s)=>{const{assets:t}=e;if(t!==void 0){if(typeof t!="object"||Array.isArray(t)){s.push('assets must be an object (e.g. { "directory": "./dist/client", "binding": "ASSETS" })');return}(typeof t.directory!="string"||t.directory.length===0)&&s.push('assets must declare a non-empty "directory" pointing at the built client output (e.g. "./dist/client")'),t.binding!==void 0&&(typeof t.binding!="string"||t.binding.length===0)&&s.push('assets.binding must be a non-empty string (e.g. "ASSETS")'),t.html_handling!==void 0&&typeof t.html_handling!="string"&&s.push("assets.html_handling must be a string"),t.not_found_handling!==void 0&&typeof t.not_found_handling!="string"&&s.push("assets.not_found_handling must be a string")}},re=(e,s)=>{const t=e.tail_consumers;if(t===void 0)return;if(!Array.isArray(t)){s.push("tail_consumers must be an array of { service, environment? } entries");return}const n=t;for(const[a,i]of n.entries())(!i||typeof i!="object"||typeof i.service!="string"||i.service.length===0)&&s.push(`tail_consumers[${String(a)}] must have a non-empty "service" naming the consumer Worker`)},Ce=(e,s)=>{const t=e.tail_consumers??[];return t.some(a=>!!a&&a?.service===s.service&&a?.environment===s.environment)?e:{...e,tail_consumers:[...t,s]}},ce=new Set(["1","enabled","on","true","yes"]),de=(e,s)=>{const{vars:t}=e;if(!t||typeof t!="object")return;const n=t.LUNORA_ALLOWED_ORIGINS,a=t.LUNORA_CORS_ALLOW_CREDENTIALS,i=typeof n=="string"&&n.split(",").some(c=>c.trim()==="*"),o=typeof a=="string"&&ce.has(a.trim().toLowerCase());i&&o&&s.push('vars.LUNORA_ALLOWED_ORIGINS includes a "*" wildcard while vars.LUNORA_CORS_ALLOW_CREDENTIALS is on — browsers reject this combination and it defeats the allowlist; name explicit origins or drop credentials')},le=(e,s,t)=>{const{error:n,merged:a,unverifiedKeys:i}=R(e,s);return n!==void 0?{error:n,wrangler:a}:(i.length>0&&t.push(`env.${String(s)} overrides ${i.join(", ")}, which this validator doesn't have a verified inheritance rule for — validated against the TOP-LEVEL value only. Double-check ${i.length===1?"it":"them"} by hand for "${String(s)}".`),{wrangler:a})},k=(e,s,t)=>{const n=[],a=[];if(!e||typeof e!="object")return n.push("wrangler config is not a valid object"),{errors:n,valid:!1,warnings:a};const{error:i,wrangler:o}=le(e,t,a);if(i!==void 0)return n.push(i),{errors:n,valid:!1,warnings:a};b(o.durable_objects?.bindings).find(l=>l.name==="SHARD"&&l.class_name==="ShardDO")||n.push('durable_objects.bindings must include { "name": "SHARD", "class_name": "ShardDO" } — run `lunora dev` to auto-reconcile wrangler.jsonc, or add the binding manually'),U(o,n);const r=o.compatibility_date??"";r&&!$.test(r)?n.push(`compatibility_date must be in YYYY-MM-DD format (got "${r}")`):r<v&&n.push(`compatibility_date must be >= "${v}" (got "${r||"<missing>"}")`),x(o)&&$.test(r)&&r<_&&n.push(`cache.enabled requires compatibility_date >= "${_}" (got "${r||"<missing>"}")`),s?.hasGlobalTable&&(b(o.d1_databases).find(w=>w.binding==="DB")||n.push('schema declares .global() tables; d1_databases must include a binding named "DB" — run `lunora dev` to auto-reconcile wrangler.jsonc, or add the binding manually')),Z(o,n),C(o,s?.vectorIndexNames??[],n),re(o,n),F(o,n,a),g(o.workflows,"workflows",P,n),Y(o,n),g(o.secrets_store_secrets,"secrets_store_secrets",H,n);for(const l of Q)V(o,l,n,a);for(const l of J)g(o[l.key],l.key,l,n);for(const l of z)X(o,l,n);return ee(o,n,a),se(o,n),ne(o,n),te(o,n),oe(o,n),ae(o,n),ie(o,n),de(o,n),{errors:n,valid:n.length===0,warnings:a}},Le=k,me=(e,s,t)=>{const n=[];for(const a of e){const i=a?.image;typeof i!="string"||!(i.startsWith("./")||i.startsWith("../")||i.startsWith("/")||i.includes("Dockerfile"))||f(i.startsWith("/")?i:p(s,i))||n.push(`containers image "${i}" does not exist (resolved relative to ${t}); create the Dockerfile or point image at a registry reference`)}return n},ue=(e,s,t)=>{if(typeof e=="string"&&e.length>0){const n=p(A(t),e);return f(n)?n:void 0}return O.map(n=>p(s,n)).find(n=>f(n))},be=/\/\/[^\n]*|\/\*.*?\*\/|"[^"\n]*"|'[^'\n]*'|`[^`]*`/gsu,ge=e=>e.replaceAll(be,s=>s.replaceAll(/[^\n]/gu," ")),fe=/\bexport\s*\*\s*(?:as\s+\w+\s*)?from\b/u,pe=/\bexport\b/gu,he=/^\s*(?:(?:abstract|async|declare|default)\s+)*/u,ye=/^(?:class|const|function|let|var)\s+(?<name>[$A-Z_a-z][\w$]*)/u,_e=/^\s*(?:const|let|var)\s*\{/u,ve=/^[$A-Z_a-z][\w$]*/u,$e=/^type\b/u,Ee=/\s+/u,Se=e=>{const s=[];for(const t of e.split(",")){const n=t.trim().split(Ee).filter(Boolean),a=n.at(-1);a!==void 0&&n[0]!=="type"&&s.push(a)}return s},je=e=>{const s=[];for(const t of e.split(",")){const n=t.includes(":")?t.slice(t.indexOf(":")+1):t,a=ve.exec(n.trim());a&&s.push(a[0])}return s},j=e=>{const s=e.indexOf("{"),t=e.indexOf("}",s);return s===-1||t===-1?void 0:e.slice(s+1,t)},Ae=e=>{const s=e.trimStart();if($e.test(s))return[];if(s.startsWith("{")){const n=j(s);return n===void 0?[]:Se(n)}if(_e.test(e)){const n=j(e);return n===void 0?[]:je(n)}const t=ye.exec(e.replace(he,""));return t?.groups?.name===void 0?[]:[t.groups.name]},Re=e=>{const s=new Set;for(const t of e.matchAll(pe))for(const n of Ae(e.slice(t.index+6)))s.add(n);return s},ke=(e,s,t)=>{const n=ue(e.main,s,t);if(n===void 0)return[];let a;try{a=M(n,"utf8")}catch{return[]}const i=ge(a);if(fe.test(i))return[];const o=[];for(const r of b(e.durable_objects?.bindings))typeof r.class_name=="string"&&r.class_name.length>0&&r.script_name===void 0&&o.push({className:r.class_name,label:"durable_objects.bindings"});for(const r of e.workflows??[])typeof r?.class_name=="string"&&r.class_name.length>0&&r.script_name===void 0&&o.push({className:r.class_name,label:"workflows"});const c=Re(i);return o.filter(r=>!c.has(r.className)).map(r=>`${r.label} declares class "${r.className}" but the worker entry (${n}) does not export it — wrangler refuses to bundle a Worker whose Durable Object classes are not exported. Add \`export { ${r.className} } from "…";\` to the entry.`)},Te=e=>{const s=e.schemaDir??"lunora",t=N(e.projectRoot);if(!t){const u=`wrangler.jsonc not found in ${e.projectRoot}; create one declaring at least the SHARD durable object binding.`;return{problems:[u],report:{errors:[u],valid:!1,warnings:[]},wranglerPath:void 0}}const{parsed:n}=I(t);if(n===void 0){const u=`failed to parse ${t} as JSONC.`;return{problems:[u],report:{errors:[u],valid:!1,warnings:[]},wranglerPath:t}}const{error:a,merged:i}=R(n,e.environment);if(a!==void 0)return{problems:[a],report:{errors:[a],valid:!1,warnings:[]},wranglerPath:t};const{error:o,info:c}=D(e.projectRoot,s),d=k(n,c,e.environment);o!==void 0&&d.warnings.push(`schema parse failed in ${s}/schema.ts: ${o}`);const r=A(t);d.errors.push(...me(i.containers??[],r,t)),d.warnings.push(...ke(i,e.projectRoot,t));const l=i.assets?.directory;if(typeof l=="string"&&l.length>0){const u=l.startsWith("/")?l:p(r,l);f(u)||d.warnings.push(`assets.directory "${l}" does not exist yet — it is created by the client build; run the build before deploy`)}return d.valid=d.errors.length===0,{problems:d.errors,report:d,wranglerPath:t}};export{v as REQUIRED_COMPATIBILITY_DATE,Ie as REQUIRED_FLAG,Le as validateWrangler,k as validateWranglerConfig,Te as validateWranglerProject,Ce as withTailConsumer};
@@ -1 +0,0 @@
1
- import{existsSync as a,readFileSync as d}from"node:fs";import{runCodegen as l,CodegenDiagnosticError as c}from"@lunora/codegen";import{classifyEdit as f,applyAdditiveEdit as p}from"./applyAdditiveEdit-DPhNZsf2.mjs";import{parseSchema as u}from"./parseSchema-B4nFDPzZ.mjs";import{w as m}from"./write-atomic-ooiPzStx.mjs";import{join as y}from"node:path";const x="/__lunora/schema-edit",b=e=>e==="destructive"||e==="duplicate-table"||e==="duplicate-column"||e==="duplicate-index"?409:e==="unknown-table"?404:e==="invalid-identifier"||e==="invalid-validator"?400:422,g=e=>({body:{error:e.reason,ok:!1},status:422}),h=e=>{if(!a(e))return{response:{body:{error:"no-schema-file",ok:!1},status:404}};const r=u(d(e,"utf8"));return r.ok?{tables:r.tables}:{response:g(r)}},k=e=>({body:{edit:e,message:"This edit changes stored data and must go through a migration. Review the migration before applying.",needsMigration:!0,ok:!1},status:409}),v=(e,r)=>{const t=e.body;if(t==null||typeof t!="object"||typeof t.kind!="string")return{body:{error:"invalid-edit",ok:!1},status:400};if(f(t)==="destructive")return k(t);if(!a(r))return{body:{error:"no-schema-file",ok:!1},status:404};const o=p(d(r,"utf8"),t);if(!o.ok)return{body:{error:o.reason,ok:!1},status:b(o.reason)};m(r,o.text);let i=[];try{l({lunoraDirectory:e.schemaDirectory??"lunora",projectRoot:e.projectRoot})}catch(s){if(s instanceof c)i=[s.message];else return{body:{error:s instanceof Error?s.message:String(s),ok:!1},status:500}}const n=u(o.text);return{body:{diagnostics:i,ok:!0,tables:n.ok?n.tables:[]},status:200}},F=e=>{const r=y(e.projectRoot,e.schemaDirectory??"lunora","schema.ts");if(e.method==="GET"){const t=h(r);return"response"in t?t.response:{body:{ok:!0,tables:t.tables},status:200}}return e.method==="POST"?v(e,r):{body:{error:"method-not-allowed",ok:!1},status:405}};export{x as SCHEMA_EDIT_ENDPOINT,F as handleSchemaEditRequest};
@@ -1,6 +0,0 @@
1
- import{Project as p,SyntaxKind as n}from"ts-morph";import{collectCalls as x}from"./parseSchema-B4nFDPzZ.mjs";const b=/^[A-Za-z_$][\w$]*$/u,v=new Set(["any","array","bigint","boolean","bytes","date","id","literal","null","number","object","optional","record","storage","string","timestamp","union"]),u=e=>{if(e.getKind()===n.ParenthesizedExpression)return u(e.asKindOrThrow(n.ParenthesizedExpression).getExpression());if(e.getKind()!==n.CallExpression)return!1;const r=e.asKindOrThrow(n.CallExpression),t=r.getExpression();if(t.getKind()!==n.PropertyAccessExpression)return!1;const i=t.asKindOrThrow(n.PropertyAccessExpression);return i.getExpression().getKind()!==n.Identifier||i.getExpression().getText()!=="v"||!v.has(i.getName())?!1:r.getArguments().every(s=>c(s))},c=e=>{const r=e.getKind();return r===n.ParenthesizedExpression?c(e.asKindOrThrow(n.ParenthesizedExpression).getExpression()):r===n.StringLiteral||r===n.NumericLiteral||r===n.TrueKeyword||r===n.FalseKeyword||r===n.NullKeyword?!0:r===n.PrefixUnaryExpression?e.asKindOrThrow(n.PrefixUnaryExpression).getOperand().getKind()===n.NumericLiteral:r===n.ObjectLiteralExpression?e.asKindOrThrow(n.ObjectLiteralExpression).getProperties().every(t=>{if(t.getKind()!==n.PropertyAssignment)return!1;const i=t.getInitializer();return i!==void 0&&c(i)}):r===n.ArrayLiteralExpression?e.asKindOrThrow(n.ArrayLiteralExpression).getElements().every(t=>c(t)):u(e)},y=e=>{if(typeof e!="string"||e.trim().length===0)return!1;const r=new p({compilerOptions:{allowJs:!0},useInMemoryFileSystem:!0}),t=r.createSourceFile("validator.ts",`const __v = (${e});`,{overwrite:!0});if(r.getProgram().getSyntacticDiagnostics(t).length>0||t.getStatements().length!==1)return!1;const s=t.getVariableDeclaration("__v")?.getInitializer();return s!==void 0&&u(s)},E=new Set(["addIndex","addOptionalColumn","addTable"]),A=new Set(["d1","hyperdrive"]),T=e=>E.has(e.kind)?"additive":"destructive",d=e=>typeof e=="string"&&b.test(e),O=e=>{if(!d(e.table)||e.kind==="addTable"&&e.global?.backend!==void 0&&!A.has(e.global.backend))return"invalid-identifier";if(e.kind==="addOptionalColumn"){if(!d(e.column))return"invalid-identifier";if(!y(e.validator))return"invalid-validator"}if(e.kind==="addIndex"&&(!d(e.name)||!Array.isArray(e.fields)||!e.fields.every(r=>d(r))))return"invalid-identifier"},h=e=>{const t=new p({compilerOptions:{allowJs:!0},useInMemoryFileSystem:!0}).createSourceFile("schema.ts",e,{overwrite:!0});let i;for(const a of t.getDescendantsOfKind(n.CallExpression))if(a.getExpression().getText()==="defineSchema"){i=a;break}if(i===void 0)return{reason:t.getImportDeclarations().some(l=>l.getNamedImports().some(o=>o.getName()==="defineSchema"&&o.getAliasNode()!==void 0))?"aliased-define-schema":"no-define-schema"};const s=i.getArguments()[0];return s?.getKind()!==n.ObjectLiteralExpression?{reason:"non-object-argument"}:{object:s.asKindOrThrow(n.ObjectLiteralExpression),sourceFile:t}},g=(e,r)=>{for(const t of e.getProperties())if(t.getKind()===n.PropertyAssignment&&t.getNameNode().getText().replaceAll(/["']/gu,"")===r)return t},K=e=>{const t=e.getInitializer()?.getDescendantsOfKind(n.CallExpression).find(i=>i.getExpression().getText()==="defineTable")?.getArguments()[0];return t?.getKind()===n.ObjectLiteralExpression?t.asKindOrThrow(n.ObjectLiteralExpression):void 0},w=(e,r)=>{if(g(e,r.table)!==void 0)return"duplicate-table";const t=r.global?.backend,i=t===void 0?"":`{ backend: ${JSON.stringify(t)} }`,s=r.global===void 0?"":`.global(${i})`;e.addPropertyAssignment({initializer:`defineTable({
2
- // Add your column validators here.
3
- // Example:
4
- // text: v.string(),
5
- // createdAt: v.number(),
6
- })${s}`,name:r.table})},k=(e,r)=>{const t=g(e,r.table);if(t===void 0)return"unknown-table";const i=K(t);if(i===void 0)return"unknown-table";if(i.getProperties().some(a=>a.getKind()===n.PropertyAssignment&&a.getNameNode().getText().replaceAll(/["']/gu,"")===r.column))return"duplicate-column";i.addPropertyAssignment({initializer:`v.optional(${r.validator})`,name:r.column})},S=(e,r)=>{if(e===void 0)return"unknown-table";const t=e.getInitializer();if(t===void 0)return"unknown-table";if(x(t).some(l=>{const o=l.getExpression();if(o.getKind()!==n.PropertyAccessExpression)return!1;const m=o.asKindOrThrow(n.PropertyAccessExpression),[f]=l.getArguments();return m.getName()==="index"&&f?.getKind()===n.StringLiteral&&f.asKindOrThrow(n.StringLiteral).getLiteralText()===r.name}))return"duplicate-index";const s=r.fields.map(l=>JSON.stringify(l)).join(", "),a=r.unique===!0?", { unique: true }":"";e.setInitializer(`${t.getText()}.index(${JSON.stringify(r.name)}, [${s}]${a})`)},N=(e,r)=>{if(T(r)==="destructive")return{ok:!1,reason:"destructive"};const t=r,i=O(t);if(i!==void 0)return{ok:!1,reason:i};const s=h(e);if("reason"in s)return{ok:!1,reason:s.reason};const{object:a,sourceFile:l}=s;let o;return t.kind==="addTable"?o=w(a,t):t.kind==="addOptionalColumn"?o=k(a,t):o=S(g(a,t.table),t),o!==void 0?{ok:!1,reason:o}:{ok:!0,text:l.getFullText()}};export{N as applyAdditiveEdit,T as classifyEdit};
@@ -1,19 +0,0 @@
1
- import{randomBytes as R}from"node:crypto";import{existsSync as y,readFileSync as f,writeFileSync as V,renameSync as A,rmSync as h,statSync as F}from"node:fs";import{join as g}from"node:path";import{LunoraError as L}from"@lunora/errors";import{DEV_VARS_FILE as u,DEV_VARS_EXAMPLE_FILE as m,parseDevVariableLine as x,parseDevVariableEntries as S,DEV_VARS_NEWLINE as C}from"./DEV_VARS_EXAMPLE_FILE-CqLorAxT.mjs";import{CORE_SECRETS as K,PACKAGE_SECRETS_REGISTRY as T,secretsForPackages as j}from"./PACKAGE_SECRETS_REGISTRY-BgmvEPA-.mjs";const M=/(?:key|password|secret|token)$/iu,D=e=>M.test(e),P=e=>[...K,...j(e)],E=32,I=["replace","openssl","changeme","change-me","change_me","change-this","change_this","your-","your_","example","placeholder","todo","fill-me","fill_me","fill-in","fill_in","xxx"],z=/[.*+?^${}()|[\]\\]/gu,N=/[a-z0-9]$/u,W=e=>{const t=e.trim().toLowerCase();return t===""||t.startsWith("<")&&t.endsWith(">")?!0:I.some(r=>{const s=r.replaceAll(z,String.raw`\$&`),o=N.test(r)?`(^|[^a-z0-9])${s}([^a-z0-9]|$)`:`(^|[^a-z0-9])${s}`;return new RegExp(o,"u").test(t)})},p=e=>R(e).toString("hex"),B=new Set([...K,...Object.values(T).flat()].filter(e=>D(e.key)&&e.placeholderValue.startsWith("<")).map(e=>e.key)),G=e=>D(e)&&!B.has(e),H=(e,t,r)=>G(e)&&W(t)?r(E):void 0,ie=(e=p)=>e(E),b=(e,t,r)=>e.split(C).map(s=>{const n=x(s),o=n?H(n.key,n.value,t):void 0;return!n||o===void 0?s:(r.push(n.key),`${n.key}="${o}"`)}),O=e=>{if(e.devVarsExists)return{status:"exists"};if(e.exampleContent===void 0)return{status:"no-example"};const t=[];return{content:b(e.exampleContent,e.randomHex??p,t).join(`
2
- `),generatedKeys:t,status:"generate"}},U=e=>e.includes('"')||e.includes("\\")?"":e.replaceAll("\r",String.raw`\r`).replaceAll(`
3
- `,String.raw`\n`),k=e=>{const t=e.randomHex??p,r=new Set(S(e.existingContent).map(d=>d.key)),s=[],n=[],o=[];for(const d of e.exampleContent.split(C)){const i=x(d);if(!i||r.has(i.key))continue;const a=H(i.key,i.value,t);o.push(i.key),a===void 0?s.push(`${i.key}="${U(i.value)}"`):(n.push(i.key),s.push(`${i.key}="${a}"`))}return{additions:s,generatedKeys:n,missingKeys:o}},w=e=>e.length>0?` (generated ${e.join(", ")})`:"",$=(e,t,r={})=>{const s=`${e}.tmp-${String(process.pid)}`;try{V(s,t,{encoding:"utf8",...r}),A(s,e)}catch(n){throw h(s,{force:!0}),n}},ae=(e,t)=>{$(e,t,{mode:384})},v=5,_=e=>{try{const t=F(e);return{mtimeMs:t.mtimeMs,size:t.size}}catch{return}},X=(e,t)=>e===void 0||t===void 0?!1:e.mtimeMs===t.mtimeMs&&e.size===t.size,Y=(e,t)=>{for(let r=0;r<v;r+=1){const s=_(e),n=f(e,"utf8"),o=t(n);if(o.length===0)return[];const d=n.length>0&&!n.endsWith(`
4
- `)?`
5
- `:"",i=`${n}${d}${o.join(`
6
- `)}
7
- `,a=`${e}.tmp-${String(process.pid)}-${R(6).toString("hex")}`;try{V(a,i,{encoding:"utf8",mode:384});const c=_(e);if(!X(s,c)){h(a,{force:!0});continue}return A(a,e),o}catch(c){throw h(a,{force:!0}),c}}throw new L("INTERNAL",`Failed to append to ${e} after ${String(v)} attempts — a concurrent writer kept winning the race.`)},ce=async e=>{const t=g(e.cwd,u),r=g(e.cwd,m);if(!y(r))return{addedKeys:[],generatedKeys:[],status:"no-example"};const s=f(r,"utf8");if(!y(t)){const l=O({devVarsExists:!1,exampleContent:s,randomHex:e.randomHex});return l.status!=="generate"?{addedKeys:[],generatedKeys:[],status:"no-example"}:e.yes===!0||await e.confirm(`No ${u} found. Generate it from ${m} (secrets auto-filled)?`)?y(t)?{addedKeys:[],generatedKeys:[],status:"skipped-exists"}:($(t,l.content,{flag:"wx",mode:384}),e.info(`Created ${u}${w(l.generatedKeys)}.`),{addedKeys:[],generatedKeys:l.generatedKeys,status:"generated"}):(e.info(`Skipped — copy ${m} to ${u} and fill it in when you're ready.`),{addedKeys:[],generatedKeys:[],status:"declined"})}const n=k({existingContent:f(t,"utf8"),exampleContent:s,randomHex:e.randomHex});if(n.missingKeys.length===0)return{addedKeys:[],generatedKeys:[],status:"exists"};const o=n.missingKeys.join(", ");if(!(e.yes===!0||await e.confirm(`${u} is missing ${String(n.missingKeys.length)} key(s) from ${m} (${o}). Add them?`)))return e.info(`Skipped — add ${o} to ${u} when you're ready.`),{addedKeys:[],generatedKeys:[],status:"declined"};const a=Y(t,l=>k({existingContent:l,exampleContent:s,randomHex:e.randomHex}).additions).map(l=>x(l)?.key).filter(l=>l!==void 0);if(a.length===0)return{addedKeys:[],generatedKeys:[],status:"exists"};const c=n.generatedKeys.filter(l=>a.includes(l));return e.info(`Updated ${u} — added ${a.join(", ")}${w(c)}.`),{addedKeys:a,generatedKeys:c,status:"augmented"}},q=e=>[`# ${e.description}`,`# Docs: ${e.docsUrl}`,`${e.key}="${e.placeholderValue}"`].join(`
8
- `),J=(e,t)=>{const r=P(e).filter(s=>!t.has(s.key));return r.length===0?"":r.map(s=>q(s)).join(`
9
-
10
- `)},de=(e,t)=>{const r=g(e,m),s=y(r)?f(r,"utf8"):"",n=new Set(S(s).map(i=>i.key)),o=J(t,n);if(o==="")return[];const d=s.length>0&&!s.endsWith(`
11
- `)?`
12
- `:"";return $(r,`${s}${d}
13
- ${o}
14
- `),P(t).filter(i=>!n.has(i.key)).map(i=>i.key)},Q=e=>{const t=e.randomHex??p,r=[],s=b(e.existingContent,t,r),n=new Set(S(e.existingContent).map(c=>c.key)),o=[],d=[];for(const c of K)n.has(c.key)||(o.push(c.key),d.push(`# ${c.description}`,`${c.key}="${t(E)}"`));const i=s.join(`
15
- `);if(d.length===0)return{addedKeys:o,content:i,filledKeys:r};const a=i===""||i.endsWith(`
16
- `)?"":`
17
- `;return{addedKeys:o,content:`${i}${a}${d.join(`
18
- `)}
19
- `,filledKeys:r}},le=e=>{const t=g(e.cwd,u),r=y(t),s=r?f(t,"utf8"):"",n=Q({existingContent:s,randomHex:e.randomHex});if(n.filledKeys.length===0&&n.addedKeys.length===0)return{addedKeys:[],filledKeys:[],status:"unchanged"};$(t,n.content,{mode:384});const o=[...n.filledKeys,...n.addedKeys];return e.info?.(`Generated ${String(o.length)} dev secret(s) in ${u}: ${o.join(", ")}`),{addedKeys:n.addedKeys,filledKeys:n.filledKeys,status:r?"filled":"created"}};export{J as buildPackageSecretsBlock,ce as ensureDevVariables,de as ensureDevVarsExample,le as fillDevSecrets,ie as generateSecretValue,G as isMintableSecretKey,W as isPlaceholderValue,Q as planDevSecretsFill,k as planDevVariablesAugment,O as planDevVariablesScaffold,P as requiredSecrets,ae as writeDevVariablesFileAtomically};
@@ -1,24 +0,0 @@
1
- import{Project as c,SyntaxKind as o}from"ts-morph";const p=new Set(["action","mutation","query","stream"]),l=/^[A-Za-z_$][\w$]*$/u,u=new Set(["scaffoldPolicy","wireRls"]),h=e=>u.has(e.kind)?"additive":"destructive",x=e=>{if(typeof e.name!="string"||typeof e.table!="string"||!l.test(e.name)||!l.test(e.table))return{ok:!1,reason:"invalid-identifier"};const r=`${e.name}Policies`,s=`${e.name}Roles`,t=JSON.stringify(e.table),n=`import { definePermission, definePolicies, definePolicy, defineRole } from "@lunora/server";
2
-
3
- /**
4
- * Access rules for the ${e.table} table — scaffolded by the Lunora studio
5
- * (plan 025). The \`when\` predicates below DENY by default (\`() => false\`);
6
- * replace each TODO with the real condition, then wire \`${r}\`
7
- * into the procedures that read/write ${e.table} via
8
- * \`.use(rls(${r}, { roles: ${s} }))\`.
9
- */
10
- export const ${r} = definePolicies([
11
- definePolicy({
12
- on: "read",
13
- table: ${t},
14
- // TODO: return \`true\` to allow, a \`WhereInput\` to filter, or \`false\` to deny.
15
- when: () => false,
16
- }),
17
- ]);
18
-
19
- /** Named permissions \`${r}\` can check with \`ctx.auth.can(...)\`. */
20
- export const ${e.name}View = definePermission("${e.name}:view");
21
-
22
- /** Roles that grant the permissions above; register via \`rls(policies, { roles })\`. */
23
- export const ${s} = [defineRole("${e.name}-admin", { permissions: [${e.name}View] })];
24
- `;return{fileName:`${e.name}.policies.ts`,ok:!0,source:n}},f=e=>{const r=e.getExpression();if(r.getKind()!==o.PropertyAccessExpression)return;const s=r.asKindOrThrow(o.PropertyAccessExpression);return p.has(s.getName())?s.getExpression():void 0},d=e=>{const r=e.getImportDeclaration(s=>s.getModuleSpecifierValue()==="@lunora/server");if(r===void 0){e.addImportDeclaration({moduleSpecifier:"@lunora/server",namedImports:["rls"]});return}r.getNamedImports().some(s=>s.getName()==="rls")||r.addNamedImport("rls")},m=e=>{const r=e.getDescendantsOfKind(o.CallExpression);e.getKind()===o.CallExpression&&r.push(e.asKindOrThrow(o.CallExpression));for(const s of r){const t=s.getExpression();if(t.getKind()!==o.PropertyAccessExpression)continue;const n=t.asKindOrThrow(o.PropertyAccessExpression),[i]=s.getArguments();if(n.getName()==="use"&&i?.getKind()===o.CallExpression&&i.asKindOrThrow(o.CallExpression).getExpression().getText()==="rls")return!0}return!1},w=(e,r)=>{if(typeof r.policies!="string"||!l.test(r.policies))return{ok:!1,reason:"invalid-identifier"};const t=new c({compilerOptions:{allowJs:!0},useInMemoryFileSystem:!0}).createSourceFile("procedure.ts",e,{overwrite:!0}),n=t.getVariableDeclaration(r.exportName),i=n?.getInitializer();if(n===void 0||i?.getKind()!==o.CallExpression)return{ok:!1,reason:"unknown-procedure"};const a=f(i.asKindOrThrow(o.CallExpression));return a===void 0?{ok:!1,reason:"unsupported-procedure-shape"}:m(a)?{ok:!1,reason:"already-wired"}:(a.replaceWithText(`${a.getText()}.use(rls(${r.policies}))`),d(t),{ok:!0,text:t.getFullText()})};export{h as classifyPolicyEdit,x as scaffoldPolicyFile,w as wireRlsIntoProcedure};
@@ -1 +0,0 @@
1
- import{relative as c}from"node:path";import{secretKindOf as E,redact as a}from"@lunora/codegen";import{isPlaceholderValue as S}from"./buildPackageSecretsBlock-J7bP1P-6.mjs";import{findWranglerFile as _,readWranglerJsonc as l}from"./WRANGLER_FILES-UNW-xY5u.mjs";const d=8,f=new Set(["CREDENTIAL","CREDENTIALS","DSN","PASSPHRASE","PASSWD","PASSWORD","SECRET","TOKEN"]),p=["ACCESS_KEY","API_KEY","ENCRYPTION_KEY","PRIVATE_KEY","SIGNING_KEY"],u=new Set(["PUBLIC","PUBLISHABLE"]),K=/[_-]/u,i=e=>e.toUpperCase().split(K),m=e=>{const r=e.toUpperCase().replaceAll("-","_");return i(e).some(n=>f.has(n))?!0:p.some(n=>r===n||r.endsWith(`_${n}`))},A=e=>i(e).some(r=>u.has(r)),N=(e,r)=>{if(e===void 0)return[];const n=[];for(const[o,t]of Object.entries(e)){if(typeof t!="string"||S(t)||A(o))continue;const s=E(t)??(m(o)&&t.length>=d?"secret_named_var":void 0);s!==void 0&&n.push({file:r,key:o,kind:s,preview:a(t)})}return n},h=e=>{const r=_(e);if(r===void 0)return[];const{parsed:n}=l(r);return n===void 0?[]:N(n.vars,c(e,r))};export{h as collectWranglerSecretVariables,N as scanWranglerVariablesForSecrets};
@@ -1 +0,0 @@
1
- import{readFileSync as n}from"node:fs";import{join as i}from"node:path";import{parseDevVariableEntries as s}from"./DEV_VARS_EXAMPLE_FILE-CqLorAxT.mjs";const v=(e,r)=>{const o=s(e).find(t=>t.key===r);return o===void 0||o.value===""?void 0:o.value},m=e=>{const r=process.env.LUNORA_ADMIN_TOKEN;if(typeof r=="string"&&r!=="")return r;try{return v(n(i(e,".dev.vars"),"utf8"),"LUNORA_ADMIN_TOKEN")}catch{return}};export{v as parseDevVariable,m as resolveAdminToken};
@@ -1 +0,0 @@
1
- import{Project as u,SyntaxKind as n}from"ts-morph";const m=/^v\s*\.\s*optional\s*\(/u,f=/\.shardBy\(\s*["']([^"']+)["']\s*\)/u,x=/\.global\(\s*(?:\{[^{}]*\}\s*)?\)/u,p=/["']/gu,T=e=>{const t=e.getDescendantsOfKind(n.CallExpression);return e.getKind()===n.CallExpression&&t.push(e.asKindOrThrow(n.CallExpression)),t},A=e=>m.test(e.trim()),h=e=>e?.getKind()!==n.ArrayLiteralExpression?[]:e.asKindOrThrow(n.ArrayLiteralExpression).getElements().filter(t=>t.getKind()===n.StringLiteral).map(t=>t.asKindOrThrow(n.StringLiteral).getLiteralText()),E=e=>{if(e?.getKind()!==n.ObjectLiteralExpression)return!1;const t=e.asKindOrThrow(n.ObjectLiteralExpression).getProperty("unique");return t?.getKind()===n.PropertyAssignment&&t.getInitializer()?.getText()==="true"},K=e=>{const t=e.getExpression();if(t.getKind()!==n.PropertyAccessExpression||t.asKindOrThrow(n.PropertyAccessExpression).getName()!=="index")return;const[s,i,r]=e.getArguments();if(s?.getKind()===n.StringLiteral)return{fields:h(i),name:s.asKindOrThrow(n.StringLiteral).getLiteralText(),unique:E(r)}},O=e=>{const t=e.getInitializer();if(t===void 0)return[];const s=[];for(const i of T(t)){const r=K(i);r!==void 0&&s.push(r)}return s},y=e=>{const t=[],i=e.getInitializer()?.getDescendantsOfKind(n.CallExpression).find(r=>r.getExpression().getText()==="defineTable")?.getArguments()[0];if(i?.getKind()!==n.ObjectLiteralExpression)return t;for(const r of i.getProperties()){if(r.getKind()!==n.PropertyAssignment)continue;const l=r,a=l.getName().replaceAll(p,""),o=l.getInitializer()?.getText()??"";t.push({name:a,optional:A(o),validator:o})}return t},P=e=>{const s=new u({compilerOptions:{allowJs:!0},useInMemoryFileSystem:!0}).createSourceFile("schema.ts",e,{overwrite:!0}),i=s.getDescendantsOfKind(n.CallExpression).find(a=>a.getExpression().getText()==="defineSchema");if(i===void 0)return{ok:!1,reason:s.getImportDeclarations().some(o=>o.getNamedImports().some(c=>c.getName()==="defineSchema"&&c.getAliasNode()!==void 0))?"aliased-define-schema":"no-define-schema"};const r=i.getArguments()[0];if(r?.getKind()!==n.ObjectLiteralExpression)return{ok:!1,reason:"non-object-argument"};const l=[];for(const a of r.getProperties()){if(a.getKind()!==n.PropertyAssignment)continue;const o=a,c=o.getName().replaceAll(p,""),g=o.getInitializer()?.getText()??"",d=f.exec(g);l.push({columns:y(o),global:x.test(g),indexes:O(o),name:c,...d?.[1]===void 0?{}:{shardBy:d[1]}})}return{ok:!0,tables:l}};export{T as collectCalls,P as parseSchema};
@@ -1 +0,0 @@
1
- import{writeFileSync as c,renameSync as m,rmSync as n}from"node:fs";const a=(t,e)=>{const r=`${t}.lunora-tmp`;try{c(r,e,"utf8"),m(r,t)}catch(o){throw n(r,{force:!0}),o}};export{a as w};