@lunora/config 1.0.0-alpha.35 → 1.0.0-alpha.351
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +135 -0
- package/README.md +3 -3
- package/dist/cloudflare/index.d.mts +1252 -0
- package/dist/cloudflare/index.d.ts +1252 -0
- package/dist/cloudflare/index.mjs +1 -0
- package/dist/index.d.mts +1048 -917
- package/dist/index.d.ts +1048 -917
- package/dist/index.mjs +1 -23
- package/dist/packem_shared/ACCENT-CotPTfv7.mjs +7 -0
- package/dist/packem_shared/AGENT_MODE_ENV-D8MvSwPE.mjs +1 -0
- package/dist/packem_shared/AGENT_RULES_DIR-HrrbNZPy.mjs +1 -0
- package/dist/packem_shared/ALLOW_FORWARDED_ENV-BUndghJx.mjs +1 -0
- package/dist/packem_shared/BINDING_MANIFEST_VERSION-CfXEYG8e.mjs +1 -0
- package/dist/packem_shared/CLOUDFLARE_CLI_CONFIG_WARNING_ENV-BKMrOuXV.mjs +1 -0
- package/dist/packem_shared/CLOUDFLARE_DRIVER-CULavrYO.mjs +1 -0
- package/dist/packem_shared/CLOUDFLARE_TOOLCHAIN_VERSIONS-DV5E_f_q.mjs +1 -0
- package/dist/packem_shared/CODEGEN_ENV-ZsCxV1kP.mjs +1 -0
- package/dist/packem_shared/COMPOSED_WORKER_ENTRY-Ciiba5g_.mjs +1 -0
- package/dist/packem_shared/DEFAULT_DEPLOY_TARGET-rR7buNQw.mjs +1 -0
- package/dist/packem_shared/DEFAULT_OBSERVABILITY-bN6UkTMx.mjs +1 -0
- package/dist/packem_shared/DEV_BINDINGS_FILE-C0ZN_XlP.mjs +4 -0
- package/dist/packem_shared/DEV_VARS_EXAMPLE_FILE-CqLorAxT.mjs +6 -0
- package/dist/packem_shared/DEV_WORKER_ENV_VALUE-2XFXmRrP.mjs +1 -0
- package/dist/packem_shared/GLOBAL_FETCH_STRICTLY_PUBLIC_FLAG-f8CnJha3.mjs +1 -0
- package/dist/packem_shared/LINKED_PROJECT_DIR-Ba5qPEwo.mjs +2 -0
- package/dist/packem_shared/LUNORA_EVENT_SOURCE-B9ZVohjO.mjs +1 -0
- package/dist/packem_shared/LUNORA_IGNORED_PATHS-U93uPxrW.mjs +19 -0
- package/dist/packem_shared/LUNORA_TAG-CiQM3BkI.mjs +1 -0
- package/dist/packem_shared/LunoraReporter-f277GLNT.mjs +6 -0
- package/dist/packem_shared/PACKAGE_SECRETS_REGISTRY-38Plje8b.mjs +1 -0
- package/dist/packem_shared/POLICY_SCAFFOLD_ENDPOINT-BmJYwAy2.mjs +1 -0
- package/dist/packem_shared/REMOTE_ELIGIBLE_KEYS-PLeh_74E.mjs +1 -0
- package/dist/packem_shared/REQUIRED_COMPATIBILITY_DATE-OLQlG0oj.mjs +1 -0
- package/dist/packem_shared/SCHEMA_EDIT_ENDPOINT-BeTxqCuQ.mjs +1 -0
- package/dist/packem_shared/SEED_ENDPOINT-2B56PN_H.mjs +1 -0
- package/dist/packem_shared/STUDIO_PATH-CSx_psKS.mjs +1 -0
- package/dist/packem_shared/UNEXPORTED_CLASS_MARKER-DwJCN8fX.mjs +1 -0
- package/dist/packem_shared/WORKERS_CACHE_MIN_DATE-0k9ABJtF.mjs +1 -0
- package/dist/packem_shared/WRANGLER_FILES-UNW-xY5u.mjs +1 -0
- package/dist/packem_shared/acceptsConnection-DHhUYGjT.mjs +2 -0
- package/dist/packem_shared/addArgsFor-CYZKhNIo.mjs +1 -0
- package/dist/packem_shared/applyAdditiveEdit-CH0VhMJ2.mjs +6 -0
- package/dist/packem_shared/applyModify-DKP2l6S9.mjs +1 -0
- package/dist/packem_shared/applyStudioAssetCache-DHQEJuuv.mjs +1 -0
- package/dist/packem_shared/assertWranglerSatisfiesSchema-Dd7ZPhw7.mjs +3 -0
- package/dist/packem_shared/assetContentType-CUb5bpbI.mjs +1 -0
- package/dist/packem_shared/buildPackageSecretsBlock-BWV_VxqV.mjs +19 -0
- package/dist/packem_shared/celld-config-D-L6uskI.mjs +3 -0
- package/dist/packem_shared/classifyPolicyEdit-DJi9Fk8G.mjs +24 -0
- package/dist/packem_shared/collectExportGaps-BPuhGH2J.mjs +2 -0
- package/dist/packem_shared/createConfirm-D5mKTMHj.mjs +7 -0
- package/dist/packem_shared/createDiscoveryCache-npJI4uej.mjs +1 -0
- package/dist/packem_shared/describePreservedCrons-C5KPuPy3.mjs +1 -0
- package/dist/packem_shared/describeWithheldWorkersAi-IIxe3TuI.mjs +1 -0
- package/dist/packem_shared/detectFramework-Dfpvu6rD.mjs +1 -0
- package/dist/packem_shared/discover-info-DC2MrAIM.mjs +1 -0
- package/dist/packem_shared/discoverAgentInfo-pqFMJBtJ.mjs +1 -0
- package/dist/packem_shared/discoverContainerInfo-DzXr7Vm3.mjs +1 -0
- package/dist/packem_shared/discoverSchemaInfo-BBRlXZop.mjs +1 -0
- package/dist/packem_shared/discoverWorkflowInfo-zW7Tt0Tn.mjs +1 -0
- package/dist/packem_shared/guards-Buu_E7mP.mjs +1 -0
- package/dist/packem_shared/hasCloudflareCredentials-byvHpEiD.mjs +1 -0
- package/dist/packem_shared/infer-bindings-C1NFOdMi.mjs +1 -0
- package/dist/packem_shared/infer-bindings.d-CFxssIAC.d.mts +480 -0
- package/dist/packem_shared/infer-bindings.d-CFxssIAC.d.ts +480 -0
- package/dist/packem_shared/inferLunoraBindings-Gp_7yyIo.mjs +1 -0
- package/dist/packem_shared/interpretRemote-CcmGeGZ_.mjs +1 -0
- package/dist/packem_shared/lunora-manifest-DuH_Cmyu.mjs +6 -0
- package/dist/packem_shared/materializeServiceDevConfigs-DLUHefD-.mjs +1 -0
- package/dist/packem_shared/mergeWranglerEnvironment-DXiB-HcS.mjs +1 -0
- package/dist/packem_shared/package-secrets-registry-BeheNwsP.mjs +1 -0
- package/dist/packem_shared/parseDevVariable-teAAahVD.mjs +1 -0
- package/dist/packem_shared/parseSchema-D1Wbr1qv.mjs +1 -0
- package/dist/packem_shared/policy-scaffold.d-D2H4_G01.d.mts +86 -0
- package/dist/packem_shared/policy-scaffold.d-D2H4_G01.d.ts +86 -0
- package/dist/packem_shared/process-tree-once-Ou4SfxKM.mjs +1 -0
- package/dist/packem_shared/readProjectDependencies-l3uhUKjo.mjs +1 -0
- package/dist/packem_shared/reconcile-services-DFqH4eMQ.mjs +1 -0
- package/dist/packem_shared/reconcileBindingsSafely-7IJ58Uit.mjs +1 -0
- package/dist/packem_shared/reconcileWranglerCompatibilityDate-hocXEuRA.mjs +1 -0
- package/dist/packem_shared/renderStudioHtml-ByowDtMl.mjs +15 -0
- package/dist/packem_shared/resolveSchemaDirectory-Ca5P6KuP.mjs +1 -0
- package/dist/packem_shared/runPostCodegenHook-Dx3yTsYZ.mjs +1 -0
- package/dist/packem_shared/scanWranglerVariablesForSecrets-BFTVje1q.mjs +1 -0
- package/dist/packem_shared/serveJsonHandler-Dv0EdCb9.mjs +1 -0
- package/dist/packem_shared/startCelldDevSession-BLFsd6jG.mjs +1 -0
- package/dist/packem_shared/streamContainerLogs-0nko1qpv.mjs +2 -0
- package/dist/packem_shared/validate-bindings-CvNBF3U4.mjs +1 -0
- package/dist/packem_shared/withTailConsumer-DngzpJMK.mjs +1 -0
- package/dist/packem_shared/worker-entry-checks-AIASCYl7.mjs +1 -0
- package/dist/packem_shared/wranglerCodegenInputs-CbisphsH.mjs +1 -0
- package/dist/packem_shared/wranglerToAlchemy-CBO2ucRm.mjs +6 -0
- package/dist/packem_shared/write-atomic-CK6VZaPI.mjs +1 -0
- package/dist/studio-host/index.d.mts +314 -110
- package/dist/studio-host/index.d.ts +314 -110
- package/dist/studio-host/index.mjs +1 -7
- package/package.json +16 -7
- package/dist/packem_shared/ACCENT-DW1XJn8i.mjs +0 -40
- package/dist/packem_shared/AGENT_RULES_DIR-lcgC08aE.mjs +0 -40
- package/dist/packem_shared/DEV_VARS_EXAMPLE_FILE-dJPNTEnK.mjs +0 -37
- package/dist/packem_shared/LINKED_PROJECT_DIR-CXwXzV_C.mjs +0 -52
- package/dist/packem_shared/LUNORA_CONFIG_FILE-CtcIcB5-.mjs +0 -34
- package/dist/packem_shared/LUNORA_EVENT_SOURCE-D2fDeGB6.mjs +0 -86
- package/dist/packem_shared/LunoraReporter-Ci-bDCK9.mjs +0 -70
- package/dist/packem_shared/PACKAGE_SECRETS_REGISTRY-B8t_SdoZ.mjs +0 -70
- package/dist/packem_shared/POLICY_SCAFFOLD_ENDPOINT-CiC2IGKx.mjs +0 -103
- package/dist/packem_shared/REMOTE_ELIGIBLE_KEYS-BC7_e9Bz.mjs +0 -105
- package/dist/packem_shared/REQUIRED_COMPATIBILITY_DATE-2YYyWJUq.mjs +0 -561
- package/dist/packem_shared/SCHEMA_EDIT_ENDPOINT-Df-Wrix-.mjs +0 -99
- package/dist/packem_shared/SEED_ENDPOINT-DVCjaGO-.mjs +0 -61
- package/dist/packem_shared/WRANGLER_FILES-DwSuC-Kn.mjs +0 -25
- package/dist/packem_shared/applyAdditiveEdit-C-snTFEV.mjs +0 -228
- package/dist/packem_shared/buildPackageSecretsBlock-DWDKHViT.mjs +0 -243
- package/dist/packem_shared/classifyPolicyEdit-BHeAqF8P.mjs +0 -99
- package/dist/packem_shared/createConfirm-fvpdgJ9s.mjs +0 -100
- package/dist/packem_shared/detectFramework-Br-BcPBq.mjs +0 -41
- package/dist/packem_shared/discoverContainerInfo-BXFs6Wav.mjs +0 -19
- package/dist/packem_shared/discoverSchemaInfo-BB-CKlTK.mjs +0 -25
- package/dist/packem_shared/discoverWorkflowInfo-CedvR0mn.mjs +0 -19
- package/dist/packem_shared/inferLunoraBindings-ByMwG-gH.mjs +0 -352
- package/dist/packem_shared/loadStudioAssets-Csk5RS4E.mjs +0 -28
- package/dist/packem_shared/parseDevVariable-CJiq2IwE.mjs +0 -30
- package/dist/packem_shared/parseSchema-DSeyktvG.mjs +0 -107
- package/dist/packem_shared/policy-scaffold.d-DCmwn7zQ.d.mts +0 -74
- package/dist/packem_shared/policy-scaffold.d-DCmwn7zQ.d.ts +0 -74
- package/dist/packem_shared/reconcileWranglerBindings-Cruwwx1M.mjs +0 -334
- package/dist/packem_shared/renderStudioHtml-449Ysn75.mjs +0 -37
- package/dist/packem_shared/serveJsonHandler-B4OLTGLS.mjs +0 -86
- package/dist/packem_shared/streamContainerLogs-BZ4cOZwH.mjs +0 -157
package/dist/index.d.mts
CHANGED
|
@@ -1,76 +1,219 @@
|
|
|
1
|
-
import { ContainerIR, WorkflowIR,
|
|
2
|
-
export type { ContainerIR, WorkflowIR } from '@lunora/codegen';
|
|
1
|
+
import { AgentIR, ContainerIR, WorkflowIR, CodegenResult } from '@lunora/codegen';
|
|
2
|
+
export type { AgentIR, ContainerIR, WorkflowIR } from '@lunora/codegen';
|
|
3
|
+
import { ChildProcess } from 'node:child_process';
|
|
4
|
+
import { a as DiscoveryCache, T as ToolchainCommand, D as DeployDriver, P as ProjectionPurpose } from "./packem_shared/infer-bindings.d-CFxssIAC.mjs";
|
|
5
|
+
export { C as COMPOSED_WORKER_ENTRY, b as DURABLE_OBJECT_BINDINGS, type c as DeployRequest, type d as DevRequest, type e as DiscoverSchemaInfoResult, type f as DriverToolchain, g as GENERATED_CLASS_MODULES, h as GENERATED_MODULE_DURABLE_OBJECTS, type G as GeneratedClassModule, type i as InferOptions, type j as InferredAgent, type I as InferredBindings, type k as InferredContainer, type l as InferredWorkflow, M as MERGED_DURABLE_OBJECTS_MODULE, type m as ProjectedConfig, type S as SchemaInfo, type n as SecretRequest, type o as TailRequest, p as createDiscoveryCache, q as discoverSchemaInfo, r as inferLunoraBindings, s as isMergedProject, t as isMergedRoleModule, u as secretSourcesFromBindings } from "./packem_shared/infer-bindings.d-CFxssIAC.mjs";
|
|
3
6
|
import { Writable } from 'node:stream';
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
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";
|
|
8
|
+
interface DiscoverAgentInfoResult {
|
|
9
|
+
/** Discovered agent definitions; `[]` when none are declared or parsing failed. */
|
|
10
|
+
agents: ReadonlyArray<AgentIR>;
|
|
11
|
+
/** Parse error message, when `lunora/agents.ts` exists but could not be analyzed. */
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Discover the project's `defineAgent` declarations. Returns `{ agents: [] }`
|
|
16
|
+
* when the project has no `lunora/agents.ts` (not an error), or
|
|
17
|
+
* `{ agents: [], error }` when the file exists but could not be parsed — callers
|
|
18
|
+
* decide whether that is a warning (validator) or ignorable (inference).
|
|
19
|
+
*/
|
|
20
|
+
declare const discoverAgentInfo: (projectRoot: string, schemaDirectory: string) => DiscoverAgentInfoResult;
|
|
21
|
+
interface DiscoverContainerInfoResult {
|
|
22
|
+
/** Discovered container definitions; `[]` when none are declared or parsing failed. */
|
|
23
|
+
containers: ReadonlyArray<ContainerIR>;
|
|
24
|
+
/** Parse error message, when `lunora/containers.ts` exists but could not be analyzed. */
|
|
25
|
+
error?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Discover the container facts, memoised on `cache` when one is given. */
|
|
28
|
+
declare const discoverContainerInfo: (projectRoot: string, schemaDirectory: string, cache?: DiscoveryCache) => DiscoverContainerInfoResult;
|
|
29
|
+
interface DiscoverWorkflowInfoResult {
|
|
30
|
+
/** Parse error message, when `lunora/workflows.ts` exists but could not be analyzed. */
|
|
31
|
+
error?: string;
|
|
32
|
+
/** Discovered workflow definitions; `[]` when none are declared or parsing failed. */
|
|
33
|
+
workflows: ReadonlyArray<WorkflowIR>;
|
|
34
|
+
}
|
|
6
35
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
|
|
36
|
+
* Discover the project's `defineWorkflow` declarations. Returns
|
|
37
|
+
* `{ workflows: [] }` when the project has no `lunora/workflows.ts` (not an
|
|
38
|
+
* error), or `{ workflows: [], error }` when the file exists but could not be
|
|
39
|
+
* parsed — callers decide whether that is a warning (validator) or ignorable
|
|
40
|
+
* (inference).
|
|
41
|
+
*/
|
|
42
|
+
declare const discoverWorkflowInfo: (projectRoot: string, schemaDirectory: string) => DiscoverWorkflowInfoResult;
|
|
43
|
+
/** Minimal env shape — `process.env` structurally, injectable for tests. */
|
|
44
|
+
type EnvLike = Readonly<Record<string, string | undefined>>;
|
|
45
|
+
/** One detected agent: which tool, and which env var gave it away. */
|
|
46
|
+
interface AgentDetection {
|
|
47
|
+
/** Human-readable agent name, for the "agent detected" log line. */
|
|
48
|
+
name: string;
|
|
49
|
+
/** The environment variable that matched. */
|
|
50
|
+
variable: string;
|
|
51
|
+
}
|
|
52
|
+
/** Env var that forces agent mode on (`1`/`true`) or off (`0`/`false`), overriding detection. */
|
|
53
|
+
declare const AGENT_MODE_ENV = "LUNORA_AGENT_MODE";
|
|
54
|
+
/**
|
|
55
|
+
* Detect the AI agent driving this process, or `undefined` when none is.
|
|
56
|
+
* `LUNORA_AGENT_MODE` wins over `@visulima/find-ai-runner`'s marker table in
|
|
57
|
+
* both directions. Pure — pass a custom `env` in tests.
|
|
58
|
+
*/
|
|
59
|
+
declare const detectAiAgent: (env?: EnvLike) => AgentDetection | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Project-relative directory the Lunora agent skills ("rules") install into.
|
|
62
|
+
* This is the portable [Agent Skills](https://tanstack.com/intent/latest/docs/registry)
|
|
63
|
+
* location — Cursor, Claude Code, and GitHub Copilot all discover skills here.
|
|
64
|
+
*/
|
|
11
65
|
declare const AGENT_RULES_DIR = ".agents/skills";
|
|
12
66
|
/** Env var the once-per-process-tree hint guard ({@link claimAgentRulesHint}) sets. */
|
|
13
67
|
declare const AGENT_RULES_HINT_ENV = "LUNORA_RULES_HINT_SHOWN";
|
|
14
68
|
/**
|
|
15
|
-
* The Lunora agent skills shipped by `@lunora/cli`. The first entry (`lunora`)
|
|
16
|
-
* is the router skill — its presence is what {@link detectAgentRules} treats as
|
|
17
|
-
* "rules installed", since every other skill is reachable through it.
|
|
18
|
-
|
|
69
|
+
* The Lunora agent skills shipped by `@lunora/cli`. The first entry (`lunora`)
|
|
70
|
+
* is the router skill — its presence is what {@link detectAgentRules} treats as
|
|
71
|
+
* "rules installed", since every other skill is reachable through it.
|
|
72
|
+
*
|
|
73
|
+
* `lunora rules install` enumerates `@lunora/cli`'s `skills/` directory rather
|
|
74
|
+
* than reading this list, so a skill missing here still installs — but
|
|
75
|
+
* `lunora rules check` counts against it, and reported "9/9 skills" with an
|
|
76
|
+
* empty "Missing:" line for a project holding all 14. The CLI's rules test
|
|
77
|
+
* pins the two together, since this package cannot see that directory.
|
|
78
|
+
*/
|
|
19
79
|
declare const LUNORA_SKILL_NAMES: ReadonlyArray<string>;
|
|
20
80
|
/** The router skill whose presence marks the rule set as installed. */
|
|
21
81
|
declare const ROOT_SKILL_NAME = "lunora";
|
|
22
82
|
/**
|
|
23
|
-
* The single "rules not installed" message shared by every surface (the CLI
|
|
24
|
-
* `lunora dev` summary and the Vite dev plugin), so the wording and the
|
|
25
|
-
* pointer at `lunora rules install` stay identical wherever it appears.
|
|
26
|
-
*/
|
|
83
|
+
* The single "rules not installed" message shared by every surface (the CLI
|
|
84
|
+
* `lunora dev` summary and the Vite dev plugin), so the wording and the
|
|
85
|
+
* pointer at `lunora rules install` stay identical wherever it appears.
|
|
86
|
+
*/
|
|
27
87
|
declare const AGENT_RULES_HINT = "Lunora AI rules not installed — run `lunora rules install` so your coding agent knows how to use Lunora.";
|
|
28
88
|
/**
|
|
29
|
-
* Process-tree guard so the hint is emitted at most once. The first surface to
|
|
30
|
-
* print it sets {@link AGENT_RULES_HINT_ENV} on `process.env`; later surfaces (a
|
|
31
|
-
* Vite dev-server restart, or a child process that inherited the env) read it
|
|
32
|
-
* and stay quiet. Returns `true` the first time, `false` afterwards.
|
|
33
|
-
*/
|
|
89
|
+
* Process-tree guard so the hint is emitted at most once. The first surface to
|
|
90
|
+
* print it sets {@link AGENT_RULES_HINT_ENV} on `process.env`; later surfaces (a
|
|
91
|
+
* Vite dev-server restart, or a child process that inherited the env) read it
|
|
92
|
+
* and stay quiet. Returns `true` the first time, `false` afterwards.
|
|
93
|
+
*/
|
|
34
94
|
declare const claimAgentRulesHint: () => boolean;
|
|
35
95
|
interface AgentRulesStatus {
|
|
36
96
|
/**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
97
|
+
* True when the `lunora` router skill is installed. We key on the router
|
|
98
|
+
* (not "all nine present") so a project that intentionally trims the set
|
|
99
|
+
* still counts as installed and isn't nagged.
|
|
100
|
+
*/
|
|
41
101
|
readonly installed: boolean;
|
|
42
|
-
/** Skill names with no `SKILL.md` under
|
|
102
|
+
/** Skill names with no `SKILL.md` under `<root>/.agents/skills/<name>/`. */
|
|
43
103
|
readonly missing: ReadonlyArray<string>;
|
|
44
|
-
/** Skill names found under
|
|
104
|
+
/** Skill names found under `<root>/.agents/skills/<name>/SKILL.md`. */
|
|
45
105
|
readonly present: ReadonlyArray<string>;
|
|
46
106
|
}
|
|
47
107
|
/**
|
|
48
|
-
* Detect whether the Lunora agent skills are installed in `projectRoot` by
|
|
49
|
-
* checking the skills folder for each `SKILL.md`. Pure filesystem reads, safe to
|
|
50
|
-
* call on every dev-server / CLI startup — the CLI, the Vite plugin, and the
|
|
51
|
-
* studio host all use it to decide whether to surface the "rules not installed"
|
|
52
|
-
* hint.
|
|
53
|
-
*/
|
|
108
|
+
* Detect whether the Lunora agent skills are installed in `projectRoot` by
|
|
109
|
+
* checking the skills folder for each `SKILL.md`. Pure filesystem reads, safe to
|
|
110
|
+
* call on every dev-server / CLI startup — the CLI, the Vite plugin, and the
|
|
111
|
+
* studio host all use it to decide whether to surface the "rules not installed"
|
|
112
|
+
* hint.
|
|
113
|
+
*/
|
|
54
114
|
declare const detectAgentRules: (projectRoot: string) => AgentRulesStatus;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
115
|
+
/** Spawns the process — injectable so tests run without the binary. */
|
|
116
|
+
type DevProcessSpawner = (command: string, args: ReadonlyArray<string>, options: {
|
|
117
|
+
cwd: string;
|
|
118
|
+
shell: boolean;
|
|
119
|
+
}) => ChildProcess;
|
|
120
|
+
interface DevProcessOptions {
|
|
121
|
+
args: ReadonlyArray<string>;
|
|
122
|
+
command: string;
|
|
123
|
+
cwd: string;
|
|
124
|
+
/** Names the process in errors, e.g. `wrangler dev`. */
|
|
125
|
+
label: string;
|
|
126
|
+
/** The error when `command` is not on PATH, naming the fix. */
|
|
127
|
+
notFound: string;
|
|
128
|
+
/** One line of output; the remainder after the last newline is flushed when the stream ends. */
|
|
129
|
+
onLine: (line: string, stream: "stderr" | "stdout") => void;
|
|
130
|
+
port: number;
|
|
131
|
+
readyTimeoutMs: number;
|
|
132
|
+
/** Windows `.cmd` shims only launch through a shell. */
|
|
133
|
+
shell?: boolean;
|
|
134
|
+
/** Aborting it stops the process while it is still starting; the start then rejects. */
|
|
135
|
+
signal?: AbortSignal;
|
|
136
|
+
spawn?: DevProcessSpawner;
|
|
137
|
+
}
|
|
138
|
+
interface DevProcess {
|
|
139
|
+
/** Resolves with the exit code when the process exits without {@link DevProcess.stop} asking it to. */
|
|
140
|
+
crashed: Promise<number>;
|
|
141
|
+
/** Terminate it; resolves once it has exited. */
|
|
142
|
+
stop: () => Promise<void>;
|
|
143
|
+
}
|
|
144
|
+
/** `true` once something accepts a TCP connection on `port`. */
|
|
145
|
+
declare const acceptsConnection: (port: number) => Promise<boolean>;
|
|
146
|
+
/**
|
|
147
|
+
* Spawn the process and resolve once it accepts connections on `port`; reject,
|
|
148
|
+
* with the process stopped, when it cannot be spawned, exits first, or misses
|
|
149
|
+
* the deadline. The caller checks the port is free beforehand: the probe cannot
|
|
150
|
+
* tell this process from another one already listening there.
|
|
151
|
+
*/
|
|
152
|
+
declare const startDevProcess: (options: DevProcessOptions) => Promise<DevProcess>;
|
|
153
|
+
/**
|
|
154
|
+
* Where a line came from: `celld` (the app, and the session's own notices) or
|
|
155
|
+
* `celld:<worker>`, and `stderr` for a session notice that reports a failure.
|
|
156
|
+
*/
|
|
157
|
+
interface CelldLineOrigin {
|
|
158
|
+
stream: "stderr" | "stdout";
|
|
159
|
+
tag: string;
|
|
160
|
+
}
|
|
161
|
+
interface CelldDevSessionOptions {
|
|
162
|
+
/** Prints one non-empty line of the session's output. */
|
|
163
|
+
log: (line: string, origin: CelldLineOrigin) => void;
|
|
164
|
+
/** Port the app serves on. */
|
|
165
|
+
port: number;
|
|
166
|
+
projectRoot: string;
|
|
167
|
+
spawn?: DevProcessSpawner;
|
|
168
|
+
}
|
|
169
|
+
interface CelldDevSession {
|
|
170
|
+
/**
|
|
171
|
+
* Resolves with an exit code once the app is gone without {@link CelldDevSession.stop}
|
|
172
|
+
* asking: its `celld dev` crashed, or did not come back after a restart.
|
|
173
|
+
*/
|
|
174
|
+
exited: Promise<number>;
|
|
175
|
+
/** Stop watching, cut short a restart in flight, then stop the app. */
|
|
176
|
+
stop: () => Promise<void>;
|
|
60
177
|
}
|
|
61
178
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
179
|
+
* Start the session: register every service, run the app, then watch the
|
|
180
|
+
* service folders. Resolves once the app accepts connections; rejects, with
|
|
181
|
+
* nothing left running, when a service or the app cannot start — including an
|
|
182
|
+
* app `celld dev` cannot run at all (a Vite virtual `main`).
|
|
183
|
+
*/
|
|
184
|
+
declare const startCelldDevSession: (options: CelldDevSessionOptions) => Promise<CelldDevSession>;
|
|
185
|
+
/**
|
|
186
|
+
* The environment switch that turns codegen off — the other spelling of
|
|
187
|
+
* `lunora dev --no-codegen`.
|
|
188
|
+
*
|
|
189
|
+
* The flag alone could not reach the Vite flavors: there the codegen watch lives
|
|
190
|
+
* in `@lunora/vite`, inside the framework dev server the CLI spawns as a separate
|
|
191
|
+
* process, which re-parses its own argv and never sees it. So the flag travels as
|
|
192
|
+
* this variable, and both the plugin and the CLI's own watcher read it — one
|
|
193
|
+
* switch, one meaning, every flavor.
|
|
194
|
+
*
|
|
195
|
+
* It is a DEV switch. `vite build` ignores it deliberately: skipping generation
|
|
196
|
+
* there would also skip the ERROR-level advisory gate that fails the build.
|
|
197
|
+
*
|
|
198
|
+
* One-directional, like `LUNORA_REMOTE`: it can turn codegen off, nothing turns
|
|
199
|
+
* it back on. Settable by hand for a project that runs its framework dev script
|
|
200
|
+
* directly rather than through `lunora dev`.
|
|
201
|
+
*/
|
|
202
|
+
/** Env var that turns codegen off when it spells `0` / `false`. Unset means on. */
|
|
203
|
+
declare const CODEGEN_ENV = "LUNORA_CODEGEN";
|
|
204
|
+
/**
|
|
205
|
+
* Whether a {@link CODEGEN_ENV} value spells an explicit "off".
|
|
206
|
+
*
|
|
207
|
+
* Takes the VALUE, not the environment, mirroring `isRemoteEnvEnabled` in
|
|
208
|
+
* `./cloudflare/remote-bindings` — the same package's existing answer to the same
|
|
209
|
+
* question, with the opposite polarity.
|
|
210
|
+
*/
|
|
211
|
+
declare const isCodegenDisabled: (value: string | undefined) => boolean;
|
|
69
212
|
/** Severity a container output line is surfaced at: `stderr` → `error`, `stdout` → `info`. */
|
|
70
213
|
type ContainerLogLevel = "error" | "info";
|
|
71
214
|
/** One declared container to follow, identified by the names codegen lifts from `defineContainer`. */
|
|
72
215
|
interface ContainerLogSource {
|
|
73
|
-
/** Generated Durable Object class name, e.g. `TranscoderContainer`. Wrangler's dev image is `cloudflare-dev
|
|
216
|
+
/** Generated Durable Object class name, e.g. `TranscoderContainer`. Wrangler's dev image is `cloudflare-dev/<lowercased>`. */
|
|
74
217
|
className: string;
|
|
75
218
|
/** The `lunora/containers.ts` export name, e.g. `transcoder` — used as the display tag. */
|
|
76
219
|
exportName: string;
|
|
@@ -130,25 +273,25 @@ interface DockerLike {
|
|
|
130
273
|
};
|
|
131
274
|
}
|
|
132
275
|
/**
|
|
133
|
-
* Follow the local Docker logs of every declared container, emitting each output
|
|
134
|
-
* line through `onLine` tagged with its export name. Polls for containers (they
|
|
135
|
-
* start lazily on first request and may be replaced on restart), attaches once
|
|
136
|
-
* per container id, and drops streams whose container has gone. Returns
|
|
137
|
-
* immediately with a `close()` handle; all work happens asynchronously.
|
|
138
|
-
*/
|
|
276
|
+
* Follow the local Docker logs of every declared container, emitting each output
|
|
277
|
+
* line through `onLine` tagged with its export name. Polls for containers (they
|
|
278
|
+
* start lazily on first request and may be replaced on restart), attaches once
|
|
279
|
+
* per container id, and drops streams whose container has gone. Returns
|
|
280
|
+
* immediately with a `close()` handle; all work happens asynchronously.
|
|
281
|
+
*/
|
|
139
282
|
declare const streamContainerLogs: (options: ContainerLogStreamOptions) => ContainerLogStreamHandle;
|
|
140
283
|
/**
|
|
141
|
-
* The meta-frameworks Lunora can compose with, plus `"none"` for a standalone
|
|
142
|
-
* SPA / SSR-less project (the current default). Mirrors PLAN4 §2.4.
|
|
143
|
-
*/
|
|
144
|
-
type DetectedFramework = "astro" | "none" | "nuxt" | "react-router" | "solid-start" | "sveltekit" | "tanstack-start" | "tanstack-start-solid";
|
|
145
|
-
/**
|
|
146
|
-
* void's class model (PLAN4 §3). Class A is Vite-native and Lunora owns the
|
|
147
|
-
* worker entry (`createWorker({ httpRouter })`). Class B frameworks own their own
|
|
148
|
-
* Cloudflare adapter, so Lunora injects its worker composition into the
|
|
149
|
-
* framework's server entry via hooks (PLAN4 M4). Class C is non-CF / SSR-less —
|
|
150
|
-
* ship the client adapter + a standalone Lunora worker (today's default).
|
|
151
|
-
*/
|
|
284
|
+
* The meta-frameworks Lunora can compose with, plus `"none"` for a standalone
|
|
285
|
+
* SPA / SSR-less project (the current default). Mirrors PLAN4 §2.4.
|
|
286
|
+
*/
|
|
287
|
+
type DetectedFramework = "astro" | "none" | "nuxt" | "react-router" | "solid-start" | "sveltekit" | "tanstack-start" | "tanstack-start-solid" | "vinext";
|
|
288
|
+
/**
|
|
289
|
+
* void's class model (PLAN4 §3). Class A is Vite-native and Lunora owns the
|
|
290
|
+
* worker entry (`createWorker({ httpRouter })`). Class B frameworks own their own
|
|
291
|
+
* Cloudflare adapter, so Lunora injects its worker composition into the
|
|
292
|
+
* framework's server entry via hooks (PLAN4 M4). Class C is non-CF / SSR-less —
|
|
293
|
+
* ship the client adapter + a standalone Lunora worker (today's default).
|
|
294
|
+
*/
|
|
152
295
|
type FrameworkClass = "A" | "B" | "C";
|
|
153
296
|
interface FrameworkDetection {
|
|
154
297
|
/** void's composition class for the detected framework. */
|
|
@@ -157,170 +300,334 @@ interface FrameworkDetection {
|
|
|
157
300
|
framework: DetectedFramework;
|
|
158
301
|
}
|
|
159
302
|
/**
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
|
|
303
|
+
* Whether the project depends on the unscoped `lunorash` umbrella rather than
|
|
304
|
+
* the granular `@lunora/*` packages.
|
|
305
|
+
*
|
|
306
|
+
* Every generator that writes an import INTO the user's project has to ask:
|
|
307
|
+
* an umbrella-only install — the default for every starter template — never
|
|
308
|
+
* installs `@lunora/server`, so under pnpm's strict layout a scaffolded
|
|
309
|
+
* `from "@lunora/server"` is unresolvable and the worker stops bundling.
|
|
310
|
+
* Codegen answers the same question from its own dependency set
|
|
311
|
+
* (`dependencies.has("lunorash")`); this is that answer for every consumer
|
|
312
|
+
* that has only a project root.
|
|
313
|
+
*/
|
|
314
|
+
declare const projectUsesUmbrella: (root: string) => boolean;
|
|
315
|
+
/**
|
|
316
|
+
* Detect which meta-framework a project uses by inspecting its `package.json`
|
|
317
|
+
* dependencies, and classify it under void's class-A/B/C model (PLAN4 §3).
|
|
318
|
+
*
|
|
319
|
+
* Pure and best-effort: never throws. An unknown / missing / malformed
|
|
320
|
+
* `package.json` yields `{ framework: "none", class: "C" }` so the standalone
|
|
321
|
+
* SPA flow is preserved.
|
|
322
|
+
*/
|
|
167
323
|
declare const detectFramework: (root: string) => FrameworkDetection;
|
|
324
|
+
/** Directory holding per-checkout Lunora state (gitignored by convention). */
|
|
325
|
+
declare const DEV_STATE_DIR = ".lunora";
|
|
326
|
+
/** The dev-server state filename, relative to the project root. */
|
|
327
|
+
declare const DEV_STATE_FILE: string;
|
|
328
|
+
/** Log file a backgrounded dev server's output is captured to, relative to the project root. */
|
|
329
|
+
declare const DEV_LOG_FILE: string;
|
|
330
|
+
/**
|
|
331
|
+
* Where `lunora dev` writes the binding manifest by default, relative to the
|
|
332
|
+
* project root.
|
|
333
|
+
*
|
|
334
|
+
* A fixed path so a supervisor can read it without being told one, and next to
|
|
335
|
+
* the state record because the two are read together: this says what the Worker
|
|
336
|
+
* needs and where it will serve, `dev.json` says whether it is serving yet.
|
|
337
|
+
*/
|
|
338
|
+
declare const DEV_BINDINGS_FILE: string;
|
|
339
|
+
/**
|
|
340
|
+
* Marker env `lunora dev --background` sets on the detached server process
|
|
341
|
+
* (the daemon `lunora dev` or `vite dev`), so it records itself as
|
|
342
|
+
* `background: true` — and, for the CLI daemon, never re-detects an agent and
|
|
343
|
+
* recurses into background mode again.
|
|
344
|
+
*/
|
|
345
|
+
declare const DEV_DAEMON_ENV = "LUNORA_DEV_DAEMON";
|
|
346
|
+
/** Env carrying the capture-log path into the detached server, recorded in the state file. */
|
|
347
|
+
declare const DEV_LOG_FILE_ENV = "LUNORA_DEV_LOG_FILE";
|
|
348
|
+
/**
|
|
349
|
+
* Env carrying the PID of a parent that holds a *provisional* state record it
|
|
350
|
+
* expects the child dev server to supersede. The CLI claims `.lunora/dev.json`
|
|
351
|
+
* with its own PID before spawning the real server (closing the duplicate-start
|
|
352
|
+
* race for the vite flavor and the wrangler daemon), then hands its PID down
|
|
353
|
+
* via this variable; the child's claim (see {@link claimDevServerState}'s
|
|
354
|
+
* `supersedePid`) may replace exactly that record with the authoritative
|
|
355
|
+
* URL + PID.
|
|
356
|
+
*/
|
|
357
|
+
declare const DEV_HANDOFF_ENV = "LUNORA_DEV_HANDOFF_PID";
|
|
358
|
+
/** How the recorded dev server runs. */
|
|
359
|
+
type DevServerMode = "cli" | "vite";
|
|
360
|
+
/** The state record persisted to `.lunora/dev.json`. */
|
|
361
|
+
interface DevServerState {
|
|
362
|
+
/** Whether the server was detached into the background (`lunora dev --background`). */
|
|
363
|
+
background?: boolean;
|
|
364
|
+
/** Absolute path of the log file capturing the server's output, when captured. */
|
|
365
|
+
logFile?: string;
|
|
366
|
+
/** `"cli"` for the `lunora dev` wrangler orchestration, `"vite"` for a Vite dev server. */
|
|
367
|
+
mode: DevServerMode;
|
|
368
|
+
/** PID of the process to signal for shutdown (the orchestrating CLI or the Vite process). */
|
|
369
|
+
pid: number;
|
|
370
|
+
/**
|
|
371
|
+
* ISO-8601 stamp marking when the server at {@link DevServerState.url} was
|
|
372
|
+
* first observed accepting requests — absent until then.
|
|
373
|
+
*
|
|
374
|
+
* The rest of this record exists as soon as the server is STARTING: `url` is
|
|
375
|
+
* the origin it intends to serve on and `pid` is a process that exists, both
|
|
376
|
+
* written before anything is listening. That is enough to find and stop a
|
|
377
|
+
* server, and not enough for a task runner deciding when to start the next
|
|
378
|
+
* thing — which is what this field is for. Poll it rather than sleeping.
|
|
379
|
+
*
|
|
380
|
+
* Deliberately a claim about `url` and nothing else. `lunora dev` observes it
|
|
381
|
+
* by probing; `@lunora/vite` observes it from the listen callback, since its
|
|
382
|
+
* record is only written once Vite has resolved that URL. Both are honest
|
|
383
|
+
* about the one origin this record advertises — neither says anything about a
|
|
384
|
+
* sidecar on another port.
|
|
385
|
+
*
|
|
386
|
+
* Absent forever is a legitimate outcome: a server that never binds, or one
|
|
387
|
+
* slower than the probe was willing to wait. Treat missing as "not ready
|
|
388
|
+
* yet", never as "will never be ready".
|
|
389
|
+
*/
|
|
390
|
+
readyAt?: string;
|
|
391
|
+
/** ISO-8601 stamp written at startup, purely informational (drives `status` uptime). */
|
|
392
|
+
startedAt?: string;
|
|
393
|
+
/** The embedded studio server's URL, when it runs. */
|
|
394
|
+
studioUrl?: string;
|
|
395
|
+
/**
|
|
396
|
+
* The public quick-tunnel URL `lunora dev --tunnel` was assigned, once
|
|
397
|
+
* cloudflared reports it — absent without `--tunnel`, before the URL
|
|
398
|
+
* arrives, and after the tunnel closes. Lets a `--background` start and
|
|
399
|
+
* `lunora dev status` show a URL that otherwise only reaches the log.
|
|
400
|
+
*/
|
|
401
|
+
tunnelUrl?: string;
|
|
402
|
+
/** The primary URL serving the worker/app. */
|
|
403
|
+
url: string;
|
|
404
|
+
}
|
|
168
405
|
/**
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
|
|
406
|
+
* True when a process with `pid` is currently alive AND signalable by this
|
|
407
|
+
* user. Signal `0` performs the existence check without delivering anything.
|
|
408
|
+
*
|
|
409
|
+
* `EPERM` ("alive but another user's process") deliberately counts as NOT
|
|
410
|
+
* alive here: every dev server this module tracks was spawned by the current
|
|
411
|
+
* user, so a PID we cannot signal is by definition a recycled PID — treating
|
|
412
|
+
* it as running would wedge the lockfile permanently and aim `dev stop`'s
|
|
413
|
+
* kill escalation at an innocent process.
|
|
414
|
+
*/
|
|
415
|
+
declare const isProcessAlive: (pid: number) => boolean;
|
|
416
|
+
/**
|
|
417
|
+
* True when the record's PID verifiably still refers to the dev server that
|
|
418
|
+
* wrote the record — not merely "some process exists with that number".
|
|
419
|
+
* Guards against PID reuse: a server process necessarily starts BEFORE its
|
|
420
|
+
* record is written, so a process that started after `startedAt` (+ skew) is
|
|
421
|
+
* a recycled PID wearing the corpse's number. The start-time check runs only
|
|
422
|
+
* where the platform exposes it (Linux); elsewhere liveness alone decides.
|
|
423
|
+
*/
|
|
424
|
+
declare const isRecordedProcessCurrent: (state: DevServerState) => boolean;
|
|
425
|
+
/**
|
|
426
|
+
* Read the state record from `.lunora/dev.json`, or `undefined` when there is
|
|
427
|
+
* no usable record. Best-effort; performs NO liveness check — use
|
|
428
|
+
* {@link readLiveDevServerState} for "is a dev server actually running".
|
|
429
|
+
*/
|
|
430
|
+
declare const readDevServerState: (projectRoot: string) => DevServerState | undefined;
|
|
431
|
+
/**
|
|
432
|
+
* Write the state record to `.lunora/dev.json`, creating the `.lunora/`
|
|
433
|
+
* directory when absent. Returns the absolute path written, or `undefined`
|
|
434
|
+
* when the write failed (state is convenience metadata — a read-only checkout
|
|
435
|
+
* must never crash dev startup).
|
|
436
|
+
*/
|
|
437
|
+
declare const writeDevServerState: (projectRoot: string, state: DevServerState) => string | undefined;
|
|
438
|
+
/**
|
|
439
|
+
* Merge `patch` into the existing state record, when one exists. Used by the
|
|
440
|
+
* CLI to stamp `background`/`logFile` onto the record the Vite plugin wrote.
|
|
441
|
+
* Returns the merged record, or `undefined` when there was nothing to update.
|
|
442
|
+
*
|
|
443
|
+
* Pass `expectedPid` to patch only while the record still belongs to that
|
|
444
|
+
* process — the counterpart to {@link clearDevServerState}'s guard, and needed
|
|
445
|
+
* by any patch that can land LATE. A readiness stamp is the case in point: this
|
|
446
|
+
* process's server can answer after a newer one has replaced the record, and an
|
|
447
|
+
* unguarded merge would mark that newer server ready on the old one's behalf.
|
|
448
|
+
*/
|
|
449
|
+
declare const updateDevServerState: (projectRoot: string, patch: Partial<DevServerState>, options?: {
|
|
450
|
+
expectedPid?: number;
|
|
451
|
+
}) => DevServerState | undefined;
|
|
452
|
+
/**
|
|
453
|
+
* Whether a record reports a server that is accepting requests, as opposed to
|
|
454
|
+
* one that has merely started. Lives here so the CLI's `status`, its JSON
|
|
455
|
+
* output, and any future reader cannot each invent their own answer.
|
|
456
|
+
*/
|
|
457
|
+
declare const isDevServerReady: (state: Pick<DevServerState, "readyAt"> | undefined) => boolean;
|
|
458
|
+
/**
|
|
459
|
+
* Remove `.lunora/dev.json`. Idempotent and never throws. When `expectedPid`
|
|
460
|
+
* is given, the file is only removed while it still records that PID — so a
|
|
461
|
+
* shutting-down server can't clobber the record a newer server just wrote.
|
|
462
|
+
*/
|
|
463
|
+
declare const clearDevServerState: (projectRoot: string, expectedPid?: number) => void;
|
|
464
|
+
/**
|
|
465
|
+
* The state record of a dev server that is verifiably running right now, or
|
|
466
|
+
* `undefined`. A record whose PID is dead — or recycled onto a different
|
|
467
|
+
* process (see {@link isRecordedProcessCurrent}) — is stale: it is cleared on
|
|
468
|
+
* the spot so subsequent starts don't keep re-reading a corpse.
|
|
469
|
+
*/
|
|
470
|
+
declare const readLiveDevServerState: (projectRoot: string) => DevServerState | undefined;
|
|
471
|
+
/** Result of {@link claimDevServerState}: claimed, or lost to the live server already recorded. */
|
|
472
|
+
interface ClaimDevServerStateResult {
|
|
473
|
+
/** The live record that won the race, when `ok` is `false`. */
|
|
474
|
+
existing?: DevServerState;
|
|
475
|
+
/** Whether this process now owns the record. */
|
|
476
|
+
ok: boolean;
|
|
477
|
+
}
|
|
478
|
+
declare const claimDevServerState: (projectRoot: string, state: DevServerState, options?: {
|
|
479
|
+
supersedePid?: number;
|
|
480
|
+
}) => ClaimDevServerStateResult;
|
|
176
481
|
/** The conventional filename for local Cloudflare dev secrets (gitignored). */
|
|
177
482
|
declare const DEV_VARS_FILE: string;
|
|
178
483
|
/** Its committed, secret-free counterpart that scaffolding reads from. */
|
|
179
484
|
declare const DEV_VARS_EXAMPLE_FILE: string;
|
|
180
|
-
/**
|
|
485
|
+
/**
|
|
486
|
+
* A bare `KEY` identifier accepted on the **write** path — `lunora env set`,
|
|
487
|
+
* `env unset`, `env generate`, and {@link upsertDevVariableLine}'s line
|
|
488
|
+
* targeting. Deliberately stricter than what the reader accepts: dotenv keys
|
|
489
|
+
* are `[\w.-]+`, but a key we *write* stays a conventional env-var name so it
|
|
490
|
+
* needs no quoting and round-trips through every consumer. Never use this to
|
|
491
|
+
* decide whether a line in an existing file counts — that is the reader's job.
|
|
492
|
+
*/
|
|
181
493
|
declare const DEV_VARS_KEY_PATTERN: RegExp;
|
|
182
|
-
/**
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
|
|
494
|
+
/**
|
|
495
|
+
* Parse `.dev.vars` content into its `{ key, value }` entries, in file order.
|
|
496
|
+
*
|
|
497
|
+
* Delegates to dotenv's own `parse()` — the literal function `wrangler dev` /
|
|
498
|
+
* `@cloudflare/vite-plugin` run over this file before handing the variables to
|
|
499
|
+
* the worker. Using the library rather than a compatible reimplementation is
|
|
500
|
+
* the point: every line the worker sees, Lunora reads identically, including
|
|
501
|
+
* `export `-prefixed lines, dotted/dashed keys, `KEY: value` separators,
|
|
502
|
+
* quote stripping (single/double/backtick), `\n`/`\r` expansion inside double
|
|
503
|
+
* quotes, `#` comments ending unquoted values, and multi-line quoted values.
|
|
504
|
+
* Duplicate keys resolve last-wins, at the key's first position — dotenv
|
|
505
|
+
* returns an object, so a repeated key overwrites in place.
|
|
506
|
+
*
|
|
507
|
+
* The canonical read of the whole file: every reader of `.dev.vars` (and of
|
|
508
|
+
* `.dev.vars.example`) goes through here or through {@link
|
|
509
|
+
* parseDevVariableLine} below, so the format cannot drift between packages.
|
|
510
|
+
*/
|
|
190
511
|
declare const parseDevVariableEntries: (content: string) => {
|
|
191
512
|
key: string;
|
|
192
513
|
value: string;
|
|
193
514
|
}[];
|
|
194
|
-
interface DiscoverWorkflowInfoResult {
|
|
195
|
-
/** Parse error message, when `lunora/workflows.ts` exists but could not be analyzed. */
|
|
196
|
-
error?: string;
|
|
197
|
-
/** Discovered workflow definitions; `[]` when none are declared or parsing failed. */
|
|
198
|
-
workflows: ReadonlyArray<WorkflowIR>;
|
|
199
|
-
}
|
|
200
515
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
516
|
+
* Escape a runtime string for safe literal interpolation into a `RegExp`
|
|
517
|
+
* source. The one canonical implementation — `@lunora/config`'s own
|
|
518
|
+
* `infer-bindings.ts` (type-only-export detection) and `@lunora/cli`'s `env`
|
|
519
|
+
* command both need this and used to carry their own (functionally
|
|
520
|
+
* identical) copy; grammar this fundamental gets one owner like everything
|
|
521
|
+
* else in this module.
|
|
522
|
+
*/
|
|
523
|
+
declare const escapeRegExp: (value: string) => string;
|
|
524
|
+
/**
|
|
525
|
+
* Surgically upsert a single `KEY="value"` line in raw `.dev.vars` content,
|
|
526
|
+
* leaving every comment, blank line, and untouched entry verbatim. Rebuilding
|
|
527
|
+
* the whole file from the parsed entry map (an earlier approach) silently
|
|
528
|
+
* dropped all `# …` comments and blank lines — including the documentation the
|
|
529
|
+
* registry installer and scaffolder write — and re-quoted lines the user never
|
|
530
|
+
* touched. If the key already has a line it is replaced in place; otherwise the
|
|
531
|
+
* new line is appended with a single trailing newline. Always quotes the value
|
|
532
|
+
* to preserve a whitespace round-trip; callers (`env set`, `env generate --set`,
|
|
533
|
+
* `deploy`'s minted-secret disclosure) reject newline/`"`/`\` up front so the
|
|
534
|
+
* verbatim quote is safe.
|
|
535
|
+
*
|
|
536
|
+
* Duplicate lines for the key are collapsed down to exactly one. The shared
|
|
537
|
+
* read path is last-wins — dotenv overwrites the key as it walks the file — so
|
|
538
|
+
* replacing only the first match would leave a later, untouched duplicate
|
|
539
|
+
* still winning at read time, i.e. a `set` that silently didn't take effect.
|
|
540
|
+
*/
|
|
541
|
+
declare const upsertDevVariableLine: (content: string, key: string, value: string) => string;
|
|
542
|
+
/**
|
|
543
|
+
* Surgically remove every `.dev.vars` line defining `key` (and its own line
|
|
544
|
+
* terminator), preserving all other lines, comments, and blanks verbatim.
|
|
545
|
+
* Backs `lunora env unset`.
|
|
546
|
+
*/
|
|
547
|
+
declare const removeDevVariableLine: (content: string, key: string) => string;
|
|
548
|
+
/**
|
|
549
|
+
* Worker env var the dev tooling sets so the Lunora runtime recognises a
|
|
550
|
+
* development deployment (`@lunora/do`'s `isDevEnvironment`) and therefore
|
|
551
|
+
* streams every RPC dispatch summary to the terminal, keeps argument/error
|
|
552
|
+
* detail unredacted, and runs the studio security audit with `dev: true`.
|
|
553
|
+
*/
|
|
554
|
+
declare const DEV_WORKER_ENV_VAR = "WORKER_ENV";
|
|
555
|
+
/** The value that flags a dev deployment. */
|
|
556
|
+
declare const DEV_WORKER_ENV_VALUE = "development";
|
|
557
|
+
/**
|
|
558
|
+
* Top up `.dev.vars` with the dev-environment flag unless the project already
|
|
559
|
+
* declares it (in `.dev.vars` itself, or in the wrangler config's `vars`).
|
|
560
|
+
*/
|
|
561
|
+
declare const ensureDevWorkerEnv: (projectRoot: string, info: (message: string) => void) => void;
|
|
562
|
+
/** The default deploy target — today's behavior for every project. */
|
|
563
|
+
declare const DEFAULT_DEPLOY_TARGET = "cloudflare";
|
|
564
|
+
/** The ids a caller may select, for error messages and `--target` help text. */
|
|
565
|
+
declare const deployTargetIds: () => ReadonlyArray<string>;
|
|
566
|
+
/**
|
|
567
|
+
* Resolve a target name to its driver.
|
|
568
|
+
* @throws when `target` names no registered driver — never falls back to the default.
|
|
569
|
+
*/
|
|
570
|
+
declare const resolveDeployDriver: (target?: string) => DeployDriver;
|
|
571
|
+
/**
|
|
572
|
+
* Whether `target`'s driver ships a `toolchain` — i.e. whether any tool can
|
|
573
|
+
* actually build, serve or deploy it, as opposed to merely generate for it.
|
|
574
|
+
*
|
|
575
|
+
* One predicate rather than one per caller: the CLI (`deploy`, `dev`) and the
|
|
576
|
+
* Vite plugin (`build`, `dev`) must refuse the same set, and a second copy
|
|
577
|
+
* fails silently — the tool that forgot runs the WRONG pipeline for the target
|
|
578
|
+
* instead of rejecting it.
|
|
579
|
+
* @param target A target id already resolved by `resolveTargetOrThrow`. Unknown
|
|
580
|
+
* ids answer `false` rather than throwing, so this is safe to ask about
|
|
581
|
+
* arbitrary input.
|
|
582
|
+
* @returns `true` when the target can be run.
|
|
583
|
+
*/
|
|
584
|
+
declare const isRunnableTarget: (target: string) => boolean;
|
|
585
|
+
/**
|
|
586
|
+
* The subset of {@link deployTargetIds} that {@link isRunnableTarget} accepts,
|
|
587
|
+
* in the same (alphabetical) order.
|
|
588
|
+
* @returns every target id a tool can build, serve or deploy — used to name the
|
|
589
|
+
* alternatives when one is refused.
|
|
590
|
+
*/
|
|
591
|
+
declare const runnableTargetIds: () => ReadonlyArray<string>;
|
|
592
|
+
/**
|
|
593
|
+
* Whether `lunora dev` serves `target`'s worker with the host's own dev server
|
|
594
|
+
* (`DriverToolchain.devServer === "own"`) instead of workerd. The CLI's flavor
|
|
595
|
+
* choice and the Vite plugin's warning both ask this, so it is answered once.
|
|
596
|
+
*/
|
|
597
|
+
declare const targetRunsOwnDevServer: (target: string) => boolean;
|
|
598
|
+
/** A toolchain command planned against the driver's config projection, with nothing written yet. */
|
|
599
|
+
interface ToolchainInvocation {
|
|
600
|
+
command: ToolchainCommand;
|
|
601
|
+
/** Write the projection, if the driver has one. Call only once the command is going to run. */
|
|
602
|
+
commit: () => void;
|
|
603
|
+
/** The projection the command reads, and every key it left out — `undefined` when the host reads the project config as-is. */
|
|
604
|
+
projection: {
|
|
605
|
+
configPath: string;
|
|
606
|
+
dropped: ReadonlyArray<string>;
|
|
607
|
+
} | undefined;
|
|
291
608
|
}
|
|
292
609
|
/**
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
* Derive the list of `@lunora/*` package names that are actively used by a
|
|
301
|
-
* project, based on its already-resolved {@link InferredBindings}.
|
|
302
|
-
*
|
|
303
|
-
* This is the canonical bridge between binding inference and the package-aware
|
|
304
|
-
* `.dev.vars.example` scaffolding in `scaffold-dev-variables.ts`. The result is
|
|
305
|
-
* a stable, predictable slice of {@link CAPABILITY_SOURCES} source values,
|
|
306
|
-
* filtered to the flags that are `true` in `bindings` — in CAPABILITY_SOURCES
|
|
307
|
-
* declaration order.
|
|
308
|
-
*/
|
|
309
|
-
declare const packageNamesFromBindings: (bindings: InferredBindings) => string[];
|
|
610
|
+
* Plan a toolchain call in the one safe order: project the config (in memory),
|
|
611
|
+
* build the argv against the projection's path — which is where a host refuses
|
|
612
|
+
* an option it cannot honour, so a refusal throws here — and only then offer the
|
|
613
|
+
* write. A refused command therefore leaves nothing on disk, and `configPath`
|
|
614
|
+
* is set on every request whose driver projects.
|
|
615
|
+
*/
|
|
616
|
+
declare const planToolchainInvocation: (driver: DeployDriver, projectRoot: string, purpose: ProjectionPurpose, build: (configPath: string | undefined) => ToolchainCommand) => ToolchainInvocation;
|
|
310
617
|
/** Directory holding per-checkout Lunora state (gitignored by convention). */
|
|
311
618
|
declare const LINKED_PROJECT_DIR = ".lunora";
|
|
312
619
|
/** The canonical link filename, relative to the project root. */
|
|
313
620
|
declare const LINKED_PROJECT_FILE: string;
|
|
314
621
|
/**
|
|
315
|
-
* The link record persisted to `.lunora/project.json`. Every field is optional
|
|
316
|
-
* so a partially-populated link (e.g. a worker name with no URL yet) still
|
|
317
|
-
* round-trips. `linkedAt` is an ISO-8601 stamp written at link time, purely
|
|
318
|
-
* informational.
|
|
319
|
-
*/
|
|
622
|
+
* The link record persisted to `.lunora/project.json`. Every field is optional
|
|
623
|
+
* so a partially-populated link (e.g. a worker name with no URL yet) still
|
|
624
|
+
* round-trips. `linkedAt` is an ISO-8601 stamp written at link time, purely
|
|
625
|
+
* informational.
|
|
626
|
+
*/
|
|
320
627
|
interface LinkedProject {
|
|
321
628
|
/** Cloudflare account id the worker lives under, when known. */
|
|
322
629
|
account?: string;
|
|
323
|
-
/** Cloudflare environment name (`wrangler … --env
|
|
630
|
+
/** Cloudflare environment name (`wrangler … --env <env>`), when scoped. */
|
|
324
631
|
env?: string;
|
|
325
632
|
/** ISO-8601 timestamp recorded when the link was written. */
|
|
326
633
|
linkedAt?: string;
|
|
@@ -330,34 +637,112 @@ interface LinkedProject {
|
|
|
330
637
|
workerUrl?: string;
|
|
331
638
|
}
|
|
332
639
|
/**
|
|
333
|
-
* Read the link record from `.lunora/project.json`, or `undefined` when there
|
|
334
|
-
* is no usable link. Best-effort: a missing file, parse error, or unexpected
|
|
335
|
-
* shape all collapse to `undefined`.
|
|
336
|
-
*/
|
|
640
|
+
* Read the link record from `.lunora/project.json`, or `undefined` when there
|
|
641
|
+
* is no usable link. Best-effort: a missing file, parse error, or unexpected
|
|
642
|
+
* shape all collapse to `undefined`.
|
|
643
|
+
*/
|
|
337
644
|
declare const readLinkedProject: (projectRoot: string) => LinkedProject | undefined;
|
|
338
645
|
/**
|
|
339
|
-
* Write the link record to `.lunora/project.json`, creating the `.lunora/`
|
|
340
|
-
* directory when absent. Only defined fields are persisted (so an empty value
|
|
341
|
-
* never clobbers a known one). Returns the absolute path written.
|
|
342
|
-
*/
|
|
646
|
+
* Write the link record to `.lunora/project.json`, creating the `.lunora/`
|
|
647
|
+
* directory when absent. Only defined fields are persisted (so an empty value
|
|
648
|
+
* never clobbers a known one). Returns the absolute path written.
|
|
649
|
+
*/
|
|
343
650
|
declare const writeLinkedProject: (projectRoot: string, link: LinkedProject) => string;
|
|
344
651
|
/**
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
|
|
652
|
+
* The generated and derived paths a linter or formatter should skip, in
|
|
653
|
+
* gitignore syntax relative to the project root.
|
|
654
|
+
*
|
|
655
|
+
* Committed-on-purpose entries are in here too, deliberately: being tracked by
|
|
656
|
+
* git says nothing about whether a human should be asked to reformat it.
|
|
657
|
+
*/
|
|
658
|
+
declare const LUNORA_IGNORED_PATHS: ReadonlyArray<string>;
|
|
659
|
+
/** A linter or formatter this module knows how to configure. */
|
|
660
|
+
type LintTool = "biome" | "eslint" | "oxlint" | "prettier";
|
|
661
|
+
/**
|
|
662
|
+
* What happened to one tool's configuration.
|
|
663
|
+
*
|
|
664
|
+
* `"manual"` is not a failure — it means the change is correct but not safe to
|
|
665
|
+
* make automatically, and {@link LintIgnoreOutcome.snippet} carries what to
|
|
666
|
+
* paste. `"failed"` IS a failure, but only of this step: the command that
|
|
667
|
+
* triggered it had already done its real work, so it is reported rather than
|
|
668
|
+
* thrown.
|
|
669
|
+
*/
|
|
670
|
+
type LintIgnoreStatus = "created" | "failed" | "manual" | "unchanged" | "updated";
|
|
671
|
+
interface LintIgnoreOutcome {
|
|
672
|
+
/** For `"failed"`: why the writer could not run. The command itself still succeeded. */
|
|
673
|
+
message?: string;
|
|
674
|
+
/** Config file that was written, or the one the user must edit for `"manual"`. */
|
|
675
|
+
path: string;
|
|
676
|
+
/** For `"manual"`: the exact text to add. */
|
|
677
|
+
snippet?: string;
|
|
678
|
+
status: LintIgnoreStatus;
|
|
679
|
+
tool: LintTool;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Which linters/formatters this project already uses, by declared dependency or
|
|
683
|
+
* config file on disk.
|
|
684
|
+
*
|
|
685
|
+
* Both signals matter: a dependency without a config is a tool about to be
|
|
686
|
+
* configured, and a config without a dependency is a tool installed globally or
|
|
687
|
+
* hoisted from a monorepo root. Missing either one means silently skipping a
|
|
688
|
+
* tool the project genuinely runs.
|
|
689
|
+
*/
|
|
690
|
+
declare const detectLintTools: (projectRoot: string) => LintTool[];
|
|
691
|
+
/**
|
|
692
|
+
* Add {@link LUNORA_IGNORED_PATHS} to each tool's configuration.
|
|
693
|
+
*
|
|
694
|
+
* Idempotent: every writer appends only what is missing, so re-running after a
|
|
695
|
+
* `lunora add` neither duplicates entries nor disturbs a project's own rules.
|
|
696
|
+
* @param projectRoot The project to configure.
|
|
697
|
+
* @param tools Which tools to configure — normally {@link detectLintTools}'s result, or the user's selection at `init`.
|
|
698
|
+
* @returns one outcome per tool, in the order given.
|
|
699
|
+
*/
|
|
700
|
+
declare const applyLintIgnores: (projectRoot: string, tools: ReadonlyArray<LintTool>) => LintIgnoreOutcome[];
|
|
701
|
+
/** The painted ` lunora ` badge, prepended to the plugin's branded log lines. */
|
|
702
|
+
declare const LUNORA_TAG: string;
|
|
703
|
+
/** Prefix a message with the Lunora badge (e.g. `lunoraLine("codegen done")`). */
|
|
704
|
+
declare const lunoraLine: (message: string) => string;
|
|
705
|
+
/**
|
|
706
|
+
* A branded schema-advisory line: the level-coloured badge (`warn`/`error`/`info`)
|
|
707
|
+
* — same badges the CLI reporter uses, so the dev server reads as one tool — then
|
|
708
|
+
* the rule name, the detail, and the remediation. Replaces the old dense
|
|
709
|
+
* `lunora-badge … schema advisory [WARN] …` line with the level-appropriate badge.
|
|
710
|
+
*/
|
|
711
|
+
declare const advisoryLine: (level: "ERROR" | "INFO" | "WARN", name: string, detail: string, remediation: string) => string;
|
|
712
|
+
/** The three channels a bundler plugin reports through; `console` satisfies it, as does Rspack's `Logger`. */
|
|
713
|
+
interface FindingLogger {
|
|
714
|
+
error: (message: string) => void;
|
|
715
|
+
warn: (message: string) => void;
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Print every schema advisory and platform-portability diagnostic a codegen run
|
|
719
|
+
* produced, each on its own level-appropriate channel.
|
|
720
|
+
*
|
|
721
|
+
* Codegen returns these without printing — each caller presents them through its
|
|
722
|
+
* own channel. Both bundler plugins present them identically, so this is that one
|
|
723
|
+
* presentation: severity → logger method, rendered by {@link advisoryLine}. It
|
|
724
|
+
* lives here rather than in either plugin because the loops were copied verbatim
|
|
725
|
+
* between them, and a copy is how `vite build` and `rspack build` start
|
|
726
|
+
* disagreeing about what a schema problem looks like.
|
|
727
|
+
*
|
|
728
|
+
* Reporting only — {@link blockingFindingsMessage} decides what BLOCKS.
|
|
729
|
+
*/
|
|
730
|
+
declare const reportCodegenFindings: (result: Pick<CodegenResult, "advisories" | "platformDiagnostics">, logger: FindingLogger) => void;
|
|
731
|
+
/**
|
|
732
|
+
* The one aggregated line a bundler plugin fails a production build with, or
|
|
733
|
+
* `undefined` when nothing is ERROR-level.
|
|
734
|
+
*
|
|
735
|
+
* An ERROR advisory says a call throws at runtime; an `error` platform
|
|
736
|
+
* diagnostic says the emitted surface does not match the declared target. Both
|
|
737
|
+
* are wrong output, not style, so `vite build` / `rspack build` / `lunora deploy`
|
|
738
|
+
* all refuse them.
|
|
739
|
+
*
|
|
740
|
+
* The filter+dedup+sort behind it stays in `@lunora/codegen` (shared with the CLI
|
|
741
|
+
* gates); only the wording and the fold of the two categories live here, which is
|
|
742
|
+
* presentation — and presentation is what this module owns, which is also why
|
|
743
|
+
* this needs no `tag` parameter: {@link LUNORA_TAG} is right above it.
|
|
744
|
+
*/
|
|
745
|
+
declare const blockingFindingsMessage: (result: Pick<CodegenResult, "advisories" | "platformDiagnostics">) => string | undefined;
|
|
361
746
|
/** Severity a formatted line should be surfaced at, mapped onto the three logger channels. */
|
|
362
747
|
type LunoraLineLevel = "error" | "info" | "warn";
|
|
363
748
|
/** A formatted lunora event: the channel to surface it on, the display text, and which event produced it. */
|
|
@@ -372,11 +757,11 @@ interface LunoraFormattedLine {
|
|
|
372
757
|
/** Stable `source` tag every lunora console event carries. Mirrors `REQUEST_LOG_EVENT_SOURCE` in `@lunora/do`. */
|
|
373
758
|
declare const LUNORA_EVENT_SOURCE = "lunora";
|
|
374
759
|
/**
|
|
375
|
-
* Parse a single worker-output line and, when it is a lunora structured event,
|
|
376
|
-
* return its severity plus display text. Returns `undefined` for anything else —
|
|
377
|
-
* non-JSON lines, JSON that isn't a lunora event, or an unrecognised event type
|
|
378
|
-
* — so the caller passes the original line through untouched. Pure and total.
|
|
379
|
-
*/
|
|
760
|
+
* Parse a single worker-output line and, when it is a lunora structured event,
|
|
761
|
+
* return its severity plus display text. Returns `undefined` for anything else —
|
|
762
|
+
* non-JSON lines, JSON that isn't a lunora event, or an unrecognised event type
|
|
763
|
+
* — so the caller passes the original line through untouched. Pure and total.
|
|
764
|
+
*/
|
|
380
765
|
declare const formatLunoraEvent: (line: string) => LunoraFormattedLine | undefined;
|
|
381
766
|
declare class LunoraReporter {
|
|
382
767
|
#private;
|
|
@@ -384,33 +769,83 @@ declare class LunoraReporter {
|
|
|
384
769
|
setStderr(stderr: NodeJS.WriteStream): void;
|
|
385
770
|
log(meta: unknown): void;
|
|
386
771
|
}
|
|
772
|
+
type PackageManager = "pnpm" | "npm" | "yarn" | "bun";
|
|
773
|
+
/** True when `manager` is on PATH — probed by running `<manager> --version`. Injectable for tests. */
|
|
774
|
+
type PackageManagerProbe = (manager: PackageManager) => boolean;
|
|
775
|
+
/**
|
|
776
|
+
* The package managers actually installed on this machine, in preference order
|
|
777
|
+
* ({@link INSTALL_PREFERENCE} — pnpm > bun > yarn > npm). The first entry is the
|
|
778
|
+
* recommended default for the install prompt; the whole list is what the user
|
|
779
|
+
* picks from. Empty when none are found.
|
|
780
|
+
*/
|
|
781
|
+
declare const detectInstalledManagers: (probe?: PackageManagerProbe) => PackageManager[];
|
|
782
|
+
/** The argv that installs a project's dependencies with `manager` (`<manager> install`). */
|
|
783
|
+
declare const installArgsFor: (manager: PackageManager) => {
|
|
784
|
+
args: string[];
|
|
785
|
+
command: string;
|
|
786
|
+
};
|
|
787
|
+
/**
|
|
788
|
+
* The argv that adds `packages` as new dependencies with `manager` — the
|
|
789
|
+
* counterpart to {@link installArgsFor}, which reinstalls what package.json
|
|
790
|
+
* already declares rather than adding something new to it.
|
|
791
|
+
*
|
|
792
|
+
* npm's dev flag is `--save-dev` (its own docs lead with the long form); bun's
|
|
793
|
+
* is the lowercase `-d` (uppercase `-D` is not one of its recognized flags);
|
|
794
|
+
* pnpm and yarn both take `-D`.
|
|
795
|
+
*/
|
|
796
|
+
declare const addArgsFor: (manager: PackageManager, packages: ReadonlyArray<string>, options?: {
|
|
797
|
+
dev?: boolean;
|
|
798
|
+
}) => {
|
|
799
|
+
args: string[];
|
|
800
|
+
command: string;
|
|
801
|
+
};
|
|
387
802
|
/**
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
* {@link
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
*
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*/
|
|
803
|
+
* Resolve the package manager to drive for the project rooted at (or above)
|
|
804
|
+
* `startDirectory`. Every step is a real signal — Lunora never blindly assumes a
|
|
805
|
+
* particular manager, and there is no hardcoded fallback:
|
|
806
|
+
*
|
|
807
|
+
* 1. `@visulima/package` — the nearest lock file (`pnpm-lock.yaml`, `yarn.lock`,
|
|
808
|
+
* `package-lock.json`, `bun.lockb`) or the `packageManager` field of the nearest
|
|
809
|
+
* `package.json`.
|
|
810
|
+
* 2. The manager that launched this CLI, read from `npm_config_user_agent` (so
|
|
811
|
+
* `pnpm dlx lunora …` / `npx lunora …` resolve to the right manager).
|
|
812
|
+
* 3. The first package manager actually installed on this machine
|
|
813
|
+
* ({@link detectInstalledManagers}).
|
|
814
|
+
*
|
|
815
|
+
* Throws when none of those resolve — i.e. there is no lock file / `packageManager`
|
|
816
|
+
* field, the CLI wasn't launched by a known manager, and none is on `PATH`.
|
|
817
|
+
* Surfacing that is better than silently guessing a manager that can't run.
|
|
818
|
+
*/
|
|
819
|
+
declare const detectPackageManager: (startDirectory: string) => PackageManager;
|
|
820
|
+
/** Map a package manager to the argv pair that runs an installed CLI. */
|
|
821
|
+
declare const execArgsFor: (manager: PackageManager, command: string, args: ReadonlyArray<string>) => {
|
|
822
|
+
args: string[];
|
|
823
|
+
command: string;
|
|
824
|
+
};
|
|
825
|
+
/**
|
|
826
|
+
* The argv that runs a driver's {@link ToolchainCommand}: through the package
|
|
827
|
+
* manager for a project dependency, directly for a binary on `PATH`.
|
|
828
|
+
*/
|
|
829
|
+
declare const toolchainExecArgs: (manager: PackageManager, command: ToolchainCommand) => {
|
|
830
|
+
args: string[];
|
|
831
|
+
command: string;
|
|
832
|
+
};
|
|
833
|
+
/**
|
|
834
|
+
* The argv that runs a project SCRIPT with `manager` — the counterpart to
|
|
835
|
+
* {@link execArgsFor}, which runs a BINARY.
|
|
836
|
+
*
|
|
837
|
+
* All four managers accept `<manager> run <script>`, so this is uniform. It is a
|
|
838
|
+
* separate function because reaching for `execArgsFor(manager, "run", [script])`
|
|
839
|
+
* silently produces something else entirely: `pnpm exec run <script>` fails with
|
|
840
|
+
* `Command "run" not found`, and `npx -- run <script>` resolves the registry
|
|
841
|
+
* PACKAGE named `run` and executes it.
|
|
842
|
+
*/
|
|
843
|
+
declare const runScriptArgsFor: (manager: PackageManager, script: string) => {
|
|
844
|
+
args: string[];
|
|
845
|
+
command: string;
|
|
846
|
+
};
|
|
847
|
+
/** The shell command that runs a project script with `manager` (`pnpm dev`, `npm run dev`, …). */
|
|
848
|
+
declare const runScriptCommand: (manager: PackageManager, script: string) => string;
|
|
414
849
|
/** A single secret variable required by a package. */
|
|
415
850
|
interface SecretEntry {
|
|
416
851
|
/** One sentence describing what this secret is and how to obtain it. */
|
|
@@ -420,96 +855,185 @@ interface SecretEntry {
|
|
|
420
855
|
/** The env-var key as it appears in `.dev.vars`, e.g. `AUTH_SECRET`. */
|
|
421
856
|
key: string;
|
|
422
857
|
/**
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
858
|
+
* The placeholder value written into `.dev.vars.example`.
|
|
859
|
+
* Must pass `isPlaceholderValue` from scaffold-dev-variables so the
|
|
860
|
+
* scaffolder regenerates it when generating `.dev.vars`. Use angle-bracket
|
|
861
|
+
* conventions or a recognised marker like `replace-with-openssl-rand-hex-32`.
|
|
862
|
+
* Non-secret env-vars (e.g. `AUTH_URL`) may carry a real default value.
|
|
863
|
+
*/
|
|
429
864
|
placeholderValue: string;
|
|
430
865
|
}
|
|
431
866
|
/**
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
* The canonical registry of per-package secret requirements.
|
|
442
|
-
*
|
|
443
|
-
* Keys are exact npm package names (e.g. `"@lunora/auth"`). Values are
|
|
444
|
-
* non-empty arrays of {@link SecretEntry} — one entry per required secret key.
|
|
445
|
-
*
|
|
446
|
-
* The scaffolder in `scaffold-dev-variables.ts` calls
|
|
447
|
-
* {@link secretsForPackages} to resolve the applicable entries from this map
|
|
448
|
-
* given the set of detected capability package names.
|
|
449
|
-
*/
|
|
867
|
+
* The canonical registry of per-package secret requirements.
|
|
868
|
+
*
|
|
869
|
+
* Keys are exact npm package names (e.g. `"@lunora/auth"`). Values are
|
|
870
|
+
* non-empty arrays of {@link SecretEntry} — one entry per required secret key.
|
|
871
|
+
*
|
|
872
|
+
* The scaffolder in `scaffold-dev-variables.ts` calls
|
|
873
|
+
* {@link secretsForPackages} to resolve the applicable entries from this map
|
|
874
|
+
* given the set of detected capability package names.
|
|
875
|
+
*/
|
|
450
876
|
declare const PACKAGE_SECRETS_REGISTRY: Readonly<Record<string, ReadonlyArray<SecretEntry>>>;
|
|
451
|
-
/**
|
|
452
|
-
* Collect all secret entries required by the given set of package names. The
|
|
453
|
-
* order follows the order of `packageNames` (stable, predictable output), and
|
|
454
|
-
* within each package the entries are returned in registry declaration order.
|
|
455
|
-
*
|
|
456
|
-
* Only packages present in {@link PACKAGE_SECRETS_REGISTRY} contribute entries;
|
|
457
|
-
* unknown package names are silently ignored — this makes the call site resilient
|
|
458
|
-
* to future capability flags whose packages have no secrets.
|
|
459
|
-
*/
|
|
460
877
|
declare const secretsForPackages: (packageNames: ReadonlyArray<string>) => SecretEntry[];
|
|
461
|
-
/**
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
*
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
878
|
+
/**
|
|
879
|
+
* The two channels this needs from a caller's logger. Deliberately structural
|
|
880
|
+
* and this small: the CLI's `Logger`, Vite's `server.config.logger` shim, and a
|
|
881
|
+
* two-line test double all satisfy it without any of them being imported here.
|
|
882
|
+
*/
|
|
883
|
+
interface HookLogger {
|
|
884
|
+
error: (message: string) => void;
|
|
885
|
+
info: (message: string) => void;
|
|
886
|
+
}
|
|
887
|
+
/** What a spawner is handed. A superset-accepting spawner (the CLI's) satisfies this. */
|
|
888
|
+
interface HookSpawnDescriptor {
|
|
889
|
+
args: ReadonlyArray<string>;
|
|
890
|
+
command: string;
|
|
891
|
+
cwd?: string;
|
|
892
|
+
/**
|
|
893
|
+
* Route the child's stdout to the parent's stderr (fd 2). Set whenever the
|
|
894
|
+
* caller's own stdout is a machine-readable stream — `--format json`, or
|
|
895
|
+
* `lunora dev`'s NDJSON — since a `postcodegen` script that prints anything
|
|
896
|
+
* would otherwise interleave with and corrupt it.
|
|
897
|
+
*/
|
|
898
|
+
stdoutToStderr?: boolean;
|
|
899
|
+
}
|
|
900
|
+
/** Run a child process and resolve with its exit code. Injectable so tests need no subprocess. */
|
|
901
|
+
type HookSpawner = (descriptor: HookSpawnDescriptor) => Promise<{
|
|
902
|
+
code: number;
|
|
903
|
+
}>;
|
|
904
|
+
interface PostCodegenHookResult {
|
|
905
|
+
/**
|
|
906
|
+
* The hook's failure message, when it ran and did not succeed.
|
|
907
|
+
*
|
|
908
|
+
* Already logged by the time a caller sees it — read it only to decide
|
|
909
|
+
* whether to ABORT, and to carry into a structured result. Logging it again
|
|
910
|
+
* double-reports.
|
|
911
|
+
*/
|
|
912
|
+
error?: string;
|
|
913
|
+
/** True when a `postcodegen` script existed and was invoked. */
|
|
914
|
+
ran: boolean;
|
|
477
915
|
}
|
|
478
916
|
/**
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
*
|
|
483
|
-
|
|
917
|
+
* Run the project's `postcodegen` script, if it declares one.
|
|
918
|
+
*
|
|
919
|
+
* A failure is reported here and returned rather than thrown, so every caller
|
|
920
|
+
* gets identical reporting and is left with only the decision that actually
|
|
921
|
+
* differs between them: whether it blocks. `deploy` and `prepare` must abort —
|
|
922
|
+
* the whole point is not shipping output the project considers unfinished —
|
|
923
|
+
* while a dev watch loop must not, since the next edit is the chance to fix it.
|
|
924
|
+
*
|
|
925
|
+
* Reporting used to be the caller's job, and all three copied the same
|
|
926
|
+
* `logger.error(result.error)` line. That made "was this surfaced?" a convention
|
|
927
|
+
* rather than a guarantee, and a fourth caller had no way to know it owed one.
|
|
928
|
+
* @returns whether the hook ran, and its (already-logged) error message when it failed.
|
|
929
|
+
*/
|
|
930
|
+
declare const runPostCodegenHook: (options: {
|
|
931
|
+
cwd: string;
|
|
932
|
+
logger: HookLogger;
|
|
933
|
+
spawner?: HookSpawner;
|
|
934
|
+
/** See {@link HookSpawnDescriptor.stdoutToStderr}. */
|
|
935
|
+
stdoutToStderr?: boolean;
|
|
936
|
+
}) => Promise<PostCodegenHookResult>;
|
|
937
|
+
/**
|
|
938
|
+
* The parsed `remote` preference from `lunora.config.*`:
|
|
939
|
+
*
|
|
940
|
+
* - `true` / `false` — the boolean form: enable or explicitly disable remote dev.
|
|
941
|
+
* - `undefined` — no usable preference (file absent, key absent, or malformed).
|
|
942
|
+
*
|
|
943
|
+
* The object form (scoping which binding kinds go remote) is reserved for a
|
|
944
|
+
* future increment; for now an object value is treated as "enabled" (truthy
|
|
945
|
+
* presence) so forward-written configs still turn remote on.
|
|
946
|
+
*/
|
|
947
|
+
type RemotePreference = boolean | undefined;
|
|
948
|
+
/**
|
|
949
|
+
* Interpret a raw `remote` value into a tri-state preference. A boolean passes
|
|
950
|
+
* through; an object is treated as enabled (the documented-but-not-yet-honored
|
|
951
|
+
* scoping form is still an opt-in); anything else (string, number, null) is no
|
|
952
|
+
* preference.
|
|
953
|
+
*/
|
|
484
954
|
declare const interpretRemote: (value: unknown) => RemotePreference;
|
|
485
955
|
/**
|
|
486
|
-
* Read the project's `remote` preference
|
|
487
|
-
*
|
|
488
|
-
|
|
489
|
-
* falls through to the env/flag layers.
|
|
490
|
-
*/
|
|
956
|
+
* Read the project's `remote` preference, or `undefined` when there is no
|
|
957
|
+
* usable one — the caller then falls through to the env/flag layers.
|
|
958
|
+
*/
|
|
491
959
|
declare const readProjectRemotePreference: (projectRoot: string) => RemotePreference;
|
|
492
960
|
/**
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
|
|
961
|
+
* Read the project's deploy `target` from `lunora.config.*`, or `undefined` when
|
|
962
|
+
* absent.
|
|
963
|
+
*
|
|
964
|
+
* Delegates to `@lunora/codegen` rather than re-reading the file here.
|
|
965
|
+
* `runCodegen` has to resolve the same key without this package (config
|
|
966
|
+
* depends on codegen, not the reverse), so the parser lives there and this is a
|
|
967
|
+
* re-export — two readers of one key is exactly the kind of copy that drifts.
|
|
968
|
+
*/
|
|
969
|
+
declare const readProjectTarget: (projectRoot: string) => string | undefined;
|
|
970
|
+
/**
|
|
971
|
+
* Resolve the deploy target for a command: an explicit `--target` wins, then
|
|
972
|
+
* `lunora.config.*`, then the registry default.
|
|
973
|
+
*
|
|
974
|
+
* **This is the canonical resolution point, and the reason it is one place.**
|
|
975
|
+
* Codegen tailors the emitted `ctx.*` surface to a target while deploy picks
|
|
976
|
+
* the driver that ships it. Resolve those separately and they can disagree,
|
|
977
|
+
* producing an app that builds cleanly and fails at runtime with nothing in the
|
|
978
|
+
* build to explain it. Every caller — CLI commands, the Vite plugin,
|
|
979
|
+
* `runCodegen`'s own fallback — resolves through here or through
|
|
980
|
+
* {@link resolveTargetOrThrow}, so there is exactly one precedence order to
|
|
981
|
+
* reason about.
|
|
982
|
+
*/
|
|
983
|
+
declare const resolveProjectTarget: (projectRoot: string, explicit?: string) => string;
|
|
984
|
+
/**
|
|
985
|
+
* Resolve the deploy target as {@link resolveProjectTarget} does, then reject
|
|
986
|
+
* one that no registered driver serves.
|
|
987
|
+
*
|
|
988
|
+
* Lives here rather than in `@lunora/cli` because nothing about it is
|
|
989
|
+
* CLI-shaped and the Vite plugin needs the same guard — a validator only the
|
|
990
|
+
* CLI could reach left `vite build` emitting the default surface for a
|
|
991
|
+
* mis-declared target, silently.
|
|
992
|
+
*
|
|
993
|
+
* Callers that go on to resolve a driver get this for free; the ones that never
|
|
994
|
+
* look a driver up — codegen, the Vite plugin — need it, because otherwise
|
|
995
|
+
* nothing in their path ever rejects the name.
|
|
996
|
+
* @param projectRoot Directory containing `lunora.config.*`.
|
|
997
|
+
* @param explicit A caller-supplied target, if any.
|
|
998
|
+
* @throws when the resolved target names no registered driver.
|
|
999
|
+
* @returns the resolved, registered target id.
|
|
1000
|
+
*/
|
|
1001
|
+
declare const resolveTargetOrThrow: (projectRoot: string, explicit?: string) => string;
|
|
1002
|
+
/**
|
|
1003
|
+
* The `package.json` at `root` as a plain object, or `undefined` when it is
|
|
1004
|
+
* missing, unreadable, or not a JSON object. Best-effort on purpose: every
|
|
1005
|
+
* caller reads one fact off it (a script, a key, the dependencies) and falls
|
|
1006
|
+
* back to its default rather than failing over a broken manifest.
|
|
1007
|
+
*/
|
|
1008
|
+
declare const readProjectManifest: (root: string) => Readonly<Record<string, unknown>> | undefined;
|
|
1009
|
+
/**
|
|
1010
|
+
* The manifest's merged `devDependencies` + `dependencies` map — a runtime
|
|
1011
|
+
* dependency wins a name declared in both — or `{}` when it cannot be read.
|
|
1012
|
+
*/
|
|
1013
|
+
declare const readProjectDependencies: (root: string) => Readonly<Record<string, string>>;
|
|
1014
|
+
/** The names {@link readProjectDependencies} reads — empty when the manifest cannot be read. */
|
|
1015
|
+
declare const readProjectDependencyNames: (root: string) => ReadonlySet<string>;
|
|
1016
|
+
/**
|
|
1017
|
+
* Whether we can interactively prompt — stdin must be a TTY. In CI / piped
|
|
1018
|
+
* contexts this is false, and callers should fall back to a non-interactive
|
|
1019
|
+
* default (skip, or require an explicit `--yes`) rather than hang on a read.
|
|
1020
|
+
*/
|
|
497
1021
|
declare const isInteractive: () => boolean;
|
|
498
1022
|
/**
|
|
499
|
-
* Ask a yes/no question on stdin. With `defaultYes`, an empty answer (just
|
|
500
|
-
* Enter) counts as yes and the prompt should read `[Y/n]`; otherwise empty is
|
|
501
|
-
* no (`[y/N]`). Shared by the CLI (`reset`, `dev`) and the Vite dev server.
|
|
502
|
-
*/
|
|
1023
|
+
* Ask a yes/no question on stdin. With `defaultYes`, an empty answer (just
|
|
1024
|
+
* Enter) counts as yes and the prompt should read `[Y/n]`; otherwise empty is
|
|
1025
|
+
* no (`[y/N]`). Shared by the CLI (`reset`, `dev`) and the Vite dev server.
|
|
1026
|
+
*/
|
|
503
1027
|
declare const promptYesNo: (prompt: string, options?: {
|
|
504
1028
|
defaultYes?: boolean;
|
|
505
1029
|
}) => Promise<boolean>;
|
|
506
1030
|
/**
|
|
507
|
-
* Build a default-yes `confirm(message)` for the scaffolders' `ensureDevVariables`:
|
|
508
|
-
* an interactive `[Y/n]` prompt (optionally prefixed, e.g. `"[lunora] "`) when
|
|
509
|
-
* stdin is a TTY, or an immediate `false` otherwise — so CI declines silently
|
|
510
|
-
* instead of blocking. Keeps the "non-interactive ⇒ decline" policy in one place
|
|
511
|
-
* rather than re-stated at every call site.
|
|
512
|
-
*/
|
|
1031
|
+
* Build a default-yes `confirm(message)` for the scaffolders' `ensureDevVariables`:
|
|
1032
|
+
* an interactive `[Y/n]` prompt (optionally prefixed, e.g. `"[lunora] "`) when
|
|
1033
|
+
* stdin is a TTY, or an immediate `false` otherwise — so CI declines silently
|
|
1034
|
+
* instead of blocking. Keeps the "non-interactive ⇒ decline" policy in one place
|
|
1035
|
+
* rather than re-stated at every call site.
|
|
1036
|
+
*/
|
|
513
1037
|
declare const createConfirm: (prefix?: string) => ((message: string) => Promise<boolean>);
|
|
514
1038
|
/** One choice in a {@link promptSelect} list. `value` is returned; `label` (and optional `description`) are shown. */
|
|
515
1039
|
interface SelectOption<T extends string> {
|
|
@@ -518,272 +1042,87 @@ interface SelectOption<T extends string> {
|
|
|
518
1042
|
value: T;
|
|
519
1043
|
}
|
|
520
1044
|
/**
|
|
521
|
-
* Ask the user to pick one option from a numbered list on stdin. Accepts the
|
|
522
|
-
* 1-based number or the option's `value`/`label` typed verbatim; an empty answer
|
|
523
|
-
* (just Enter) takes `settings.default`. In a non-interactive context (CI /
|
|
524
|
-
* piped — no TTY) it never reads and returns `settings.default` (or `undefined`),
|
|
525
|
-
* mirroring {@link createConfirm}'s "non-interactive ⇒ fall back" policy so
|
|
526
|
-
* automation never blocks.
|
|
527
|
-
*/
|
|
1045
|
+
* Ask the user to pick one option from a numbered list on stdin. Accepts the
|
|
1046
|
+
* 1-based number or the option's `value`/`label` typed verbatim; an empty answer
|
|
1047
|
+
* (just Enter) takes `settings.default`. In a non-interactive context (CI /
|
|
1048
|
+
* piped — no TTY) it never reads and returns `settings.default` (or `undefined`),
|
|
1049
|
+
* mirroring {@link createConfirm}'s "non-interactive ⇒ fall back" policy so
|
|
1050
|
+
* automation never blocks.
|
|
1051
|
+
*/
|
|
528
1052
|
declare const promptSelect: <T extends string>(message: string, options: ReadonlyArray<SelectOption<T>>, settings?: {
|
|
529
1053
|
default?: T;
|
|
530
1054
|
}) => Promise<T | undefined>;
|
|
1055
|
+
/**
|
|
1056
|
+
* Ask a free-text question on stdin, returning the trimmed answer. An empty
|
|
1057
|
+
* answer (just Enter) takes `settings.default`. In a non-interactive context
|
|
1058
|
+
* (CI / piped — no TTY) it never reads and returns `settings.default` (or
|
|
1059
|
+
* `undefined`), mirroring {@link promptSelect}'s "non-interactive ⇒ fall back"
|
|
1060
|
+
* policy so automation never blocks.
|
|
1061
|
+
*/
|
|
1062
|
+
declare const promptText: (message: string, settings?: {
|
|
1063
|
+
default?: string;
|
|
1064
|
+
}) => Promise<string | undefined>;
|
|
531
1065
|
/** One choice in a {@link promptMultiSelect} list. Identical shape to {@link SelectOption}; `value` is returned when picked. */
|
|
532
1066
|
type MultiSelectOption<T extends string> = SelectOption<T>;
|
|
533
1067
|
/**
|
|
534
|
-
* Ask the user to pick zero or more options from a numbered list on stdin.
|
|
535
|
-
* Accepts a comma- or space-separated list of 1-based numbers and/or option
|
|
536
|
-
* `value`/`label`s typed verbatim; an empty answer (just Enter) takes
|
|
537
|
-
* `settings.defaults`. In a non-interactive context (CI / piped — no TTY) it
|
|
538
|
-
* never reads and returns `settings.defaults ?? []`, mirroring {@link promptSelect}'s
|
|
539
|
-
* "non-interactive ⇒ fall back" policy so automation never blocks. Unknown
|
|
540
|
-
* tokens are ignored; the returned list is de-duplicated and preserves option
|
|
541
|
-
* order.
|
|
542
|
-
*/
|
|
1068
|
+
* Ask the user to pick zero or more options from a numbered list on stdin.
|
|
1069
|
+
* Accepts a comma- or space-separated list of 1-based numbers and/or option
|
|
1070
|
+
* `value`/`label`s typed verbatim; an empty answer (just Enter) takes
|
|
1071
|
+
* `settings.defaults`. In a non-interactive context (CI / piped — no TTY) it
|
|
1072
|
+
* never reads and returns `settings.defaults ?? []`, mirroring {@link promptSelect}'s
|
|
1073
|
+
* "non-interactive ⇒ fall back" policy so automation never blocks. Unknown
|
|
1074
|
+
* tokens are ignored; the returned list is de-duplicated and preserves option
|
|
1075
|
+
* order.
|
|
1076
|
+
*/
|
|
543
1077
|
declare const promptMultiSelect: <T extends string>(message: string, options: ReadonlyArray<MultiSelectOption<T>>, settings?: {
|
|
544
1078
|
defaults?: ReadonlyArray<T>;
|
|
545
1079
|
}) => Promise<T[]>;
|
|
546
1080
|
/**
|
|
547
|
-
*
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
/** Which declaration is unexported. */
|
|
561
|
-
kind: "container" | "workflow";
|
|
562
|
-
/** The `_generated/{module}` to re-export from, e.g. `workflows`. */
|
|
563
|
-
module: "containers" | "workflows";
|
|
564
|
-
}
|
|
565
|
-
interface ReconcileBindingsResult {
|
|
566
|
-
/** Short labels for each binding written (e.g. `"SCHEDULER/SchedulerDO"`). */
|
|
567
|
-
added: string[];
|
|
568
|
-
/** `true` when `wrangler.jsonc` was rewritten. */
|
|
569
|
-
changed: boolean;
|
|
570
|
-
/**
|
|
571
|
-
* Declared containers/workflows the worker entry doesn't re-export — the
|
|
572
|
-
* structured form of the corresponding `warnings` entries, for the dev error
|
|
573
|
-
* overlay. Empty when every declaration is wired.
|
|
574
|
-
*/
|
|
575
|
-
exportGaps: ExportGap[];
|
|
576
|
-
/** Reason reconciliation was skipped, for logging. */
|
|
577
|
-
reason?: string;
|
|
578
|
-
/** Non-fatal hints for capabilities that cannot be auto-provisioned. */
|
|
579
|
-
warnings: string[];
|
|
580
|
-
/** Resolved wrangler path, or `undefined` when none was found. */
|
|
581
|
-
wranglerPath?: string;
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* Reconcile inferred Durable Object / D1 bindings into `wrangler.jsonc`.
|
|
585
|
-
*
|
|
586
|
-
* Writes only when something is missing; returns `changed: false` when the
|
|
587
|
-
* config already satisfies the inferred needs.
|
|
588
|
-
*/
|
|
589
|
-
declare const reconcileWranglerBindings: (projectRoot: string, inferred: InferredBindings) => ReconcileBindingsResult;
|
|
590
|
-
/**
|
|
591
|
-
* The wrangler config sections Lunora can safely flip to remote mode in dev,
|
|
592
|
-
* each with the human label used in logs and the structural `shape` the entry
|
|
593
|
-
* lives in.
|
|
594
|
-
*
|
|
595
|
-
* `"array"` is a top-level array of binding objects (`d1_databases`,
|
|
596
|
-
* `kv_namespaces`, `r2_buckets`, `vectorize`, `services`). `"producers"` is
|
|
597
|
-
* `queues.producers[]` — consumers are NOT remoted (their schema has no `remote`
|
|
598
|
-
* field) and the edit path is two levels deep. `"object"` is a single binding
|
|
599
|
-
* object, not an array (`ai`), whose edit path targets the section key directly.
|
|
600
|
-
*
|
|
601
|
-
* Every kind here was confirmed against `wrangler/config-schema.json`: the
|
|
602
|
-
* entry's schema declares a `remote` property. Deliberately omits
|
|
603
|
-
* `durable_objects` (no CF remote-DO mode; shards stay local) and sections whose
|
|
604
|
-
* schema has no `remote` field (`hyperdrive`, `analytics_engine_datasets`,
|
|
605
|
-
* `secrets_store_secrets`, queue consumers, …). Widening further is a one-line
|
|
606
|
-
* table edit.
|
|
607
|
-
*/
|
|
608
|
-
declare const REMOTE_ELIGIBLE_KEYS: {
|
|
609
|
-
readonly ai: {
|
|
610
|
-
readonly label: "AI";
|
|
611
|
-
readonly shape: "object";
|
|
612
|
-
};
|
|
613
|
-
readonly d1_databases: {
|
|
614
|
-
readonly label: "D1";
|
|
615
|
-
readonly shape: "array";
|
|
616
|
-
};
|
|
617
|
-
readonly kv_namespaces: {
|
|
618
|
-
readonly label: "KV";
|
|
619
|
-
readonly shape: "array";
|
|
620
|
-
};
|
|
621
|
-
readonly queues: {
|
|
622
|
-
readonly label: "Queue";
|
|
623
|
-
readonly shape: "producers";
|
|
624
|
-
};
|
|
625
|
-
readonly r2_buckets: {
|
|
626
|
-
readonly label: "R2";
|
|
627
|
-
readonly shape: "array";
|
|
628
|
-
};
|
|
629
|
-
readonly services: {
|
|
630
|
-
readonly label: "Service";
|
|
631
|
-
readonly shape: "array";
|
|
632
|
-
};
|
|
633
|
-
readonly vectorize: {
|
|
634
|
-
readonly label: "Vectorize";
|
|
635
|
-
readonly shape: "array";
|
|
636
|
-
};
|
|
637
|
-
};
|
|
638
|
-
type RemoteEligibleKey = keyof typeof REMOTE_ELIGIBLE_KEYS;
|
|
639
|
-
/** One binding object as it appears in any eligible section. */
|
|
640
|
-
interface BindingEntry {
|
|
641
|
-
binding?: string;
|
|
642
|
-
remote?: boolean;
|
|
643
|
-
}
|
|
644
|
-
/** One binding entry we mark remote, with enough provenance to log + edit it. */
|
|
645
|
-
interface RemoteBindingPlan {
|
|
646
|
-
/** The binding name as declared in the config (e.g. `"DB"`, `"FILES"`). */
|
|
647
|
-
binding: string;
|
|
648
|
-
/** Short kind label for logging (`"D1"`, `"KV"`, `"R2"`, `"Vectorize"`, …). */
|
|
649
|
-
kind: string;
|
|
650
|
-
/**
|
|
651
|
-
* The jsonc edit path within {@link RemoteBindingPlan.section}, relative to
|
|
652
|
-
* the section key: `[index]` for an `"array"` section, `["producers", index]`
|
|
653
|
-
* for a queue producer, or `[]` for the single-object `ai` section. The
|
|
654
|
-
* materializer prepends the section key and appends `"remote"`.
|
|
655
|
-
*/
|
|
656
|
-
path: ReadonlyArray<number | string>;
|
|
657
|
-
/** The wrangler config key the entry lives under. */
|
|
658
|
-
section: RemoteEligibleKey;
|
|
659
|
-
}
|
|
660
|
-
/** The structural slice of a wrangler config the remote planner reads. */
|
|
661
|
-
interface RemoteWranglerShape {
|
|
662
|
-
ai?: BindingEntry | null;
|
|
663
|
-
d1_databases?: ReadonlyArray<BindingEntry | null | undefined>;
|
|
664
|
-
kv_namespaces?: ReadonlyArray<BindingEntry | null | undefined>;
|
|
665
|
-
queues?: {
|
|
666
|
-
producers?: ReadonlyArray<BindingEntry | null | undefined>;
|
|
667
|
-
} | null;
|
|
668
|
-
r2_buckets?: ReadonlyArray<BindingEntry | null | undefined>;
|
|
669
|
-
services?: ReadonlyArray<BindingEntry | null | undefined>;
|
|
670
|
-
vectorize?: ReadonlyArray<BindingEntry | null | undefined>;
|
|
671
|
-
}
|
|
672
|
-
/**
|
|
673
|
-
* Inspect a parsed wrangler config and list every eligible binding that should
|
|
674
|
-
* be flipped to remote mode. Pure — no file-system access, no mutation. An
|
|
675
|
-
* entry already carrying `"remote": true` is still reported (so logging is
|
|
676
|
-
* complete) but the materializer's edit is a harmless no-op for it.
|
|
677
|
-
*/
|
|
678
|
-
declare const planRemoteBindings: (parsed: RemoteWranglerShape) => RemoteBindingPlan[];
|
|
679
|
-
/**
|
|
680
|
-
* Inject `"remote": true` onto each planned binding in the config `text`,
|
|
681
|
-
* comment-preservingly via jsonc edits. Pure string→string; the edits target
|
|
682
|
-
* disjoint entries so applying them sequentially is safe. The edit path is
|
|
683
|
-
* `[section, ...plan.path, "remote"]`, which resolves to the array element, the
|
|
684
|
-
* `queues.producers[i]` entry, or the single `ai` object as the plan demands.
|
|
685
|
-
*/
|
|
686
|
-
declare const injectRemoteFlags: (text: string, plans: ReadonlyArray<RemoteBindingPlan>) => string;
|
|
687
|
-
interface MaterializeOptions {
|
|
688
|
-
/** When `false`, the call is a no-op (returns `enabled: false`). */
|
|
689
|
-
enabled: boolean;
|
|
690
|
-
projectRoot: string;
|
|
691
|
-
}
|
|
692
|
-
interface MaterializeResult {
|
|
693
|
-
/**
|
|
694
|
-
* Removes the generated temp config file. Always present and always safe to
|
|
695
|
-
* call: it is idempotent, a no-op when nothing was written (disabled /
|
|
696
|
-
* fall-through cases), and never throws if the path is already gone. The dev
|
|
697
|
-
* command calls this on every exit path (normal, signal, error).
|
|
698
|
-
*/
|
|
699
|
-
cleanup: () => void;
|
|
700
|
-
/**
|
|
701
|
-
* Absolute path to the generated temp config to pass to
|
|
702
|
-
* `wrangler dev --config`. `undefined` when remote mode is disabled, no
|
|
703
|
-
* wrangler config was found, it failed to parse, or it declared no eligible
|
|
704
|
-
* binding (nothing to remote — run plain local dev).
|
|
705
|
-
*/
|
|
706
|
-
configPath?: string;
|
|
707
|
-
/** Whether remote mode was requested at all. */
|
|
708
|
-
enabled: boolean;
|
|
709
|
-
/** Why no temp config was produced, for logging (only set when none was). */
|
|
710
|
-
reason?: string;
|
|
711
|
-
/** The bindings flipped to remote, for the dev banner. */
|
|
712
|
-
remoteBindings: RemoteBindingPlan[];
|
|
713
|
-
}
|
|
714
|
-
/**
|
|
715
|
-
* Produce a temporary wrangler config with `"remote": true` on every eligible
|
|
716
|
-
* binding, so `lunora dev` can run `wrangler dev --config <temp>` against the
|
|
717
|
-
* deployed D1/KV/R2 without touching the user's file.
|
|
718
|
-
*
|
|
719
|
-
* The temp file is written as a sibling of the source `wrangler.jsonc` (in the
|
|
720
|
-
* project root), NOT an OS temp dir: wrangler resolves a config's relative paths
|
|
721
|
-
* (`main`, `assets`, `migrations_dir`, …) against the **config file's own
|
|
722
|
-
* directory**, so a temp config in `/tmp` would make wrangler look for
|
|
723
|
-
* `/tmp/src/server.ts` and fail to start the worker. Keeping it beside the real
|
|
724
|
-
* config preserves those relative paths. Returns `configPath: undefined` (with a
|
|
725
|
-
* `reason`) for every fall-through case so the caller degrades to plain local
|
|
726
|
-
* dev instead of failing.
|
|
727
|
-
*/
|
|
728
|
-
declare const materializeRemoteWranglerConfig: (options: MaterializeOptions) => MaterializeResult;
|
|
729
|
-
/**
|
|
730
|
-
* Parse a `LUNORA_REMOTE` env value into the on/off decision. Truthy when set to
|
|
731
|
-
* `"1"` or `"true"` (case-insensitive); anything else — unset, `"0"`, `"false"`,
|
|
732
|
-
* empty — is off. Mirrors the `"1" | "true"` convention used across the runtime.
|
|
733
|
-
*/
|
|
734
|
-
declare const isRemoteEnvEnabled: (value: string | undefined) => boolean;
|
|
735
|
-
/** The three inputs that can switch remote-binding dev on, in precedence order. */
|
|
736
|
-
interface RemoteEnableInputs {
|
|
737
|
-
/**
|
|
738
|
-
* The `remote` preference from `lunora.json` (the lowest-priority signal).
|
|
739
|
-
* `undefined` means "no project preference"; an explicit `false` here loses
|
|
740
|
-
* to neither the flag nor the env when those are absent — it just stays off.
|
|
741
|
-
*/
|
|
742
|
-
configPreference?: boolean;
|
|
743
|
-
/** The raw `LUNORA_REMOTE` env value (parsed with {@link isRemoteEnvEnabled}). */
|
|
744
|
-
envValue?: string;
|
|
745
|
-
/** The explicit `--remote` CLI flag — `true` when passed, `undefined`/`false` otherwise. */
|
|
746
|
-
flag?: boolean;
|
|
747
|
-
}
|
|
748
|
-
/**
|
|
749
|
-
* Resolve whether remote-binding dev is on, with a clear precedence:
|
|
750
|
-
*
|
|
751
|
-
* 1. an explicit `--remote` flag (highest — a deliberate per-invocation choice),
|
|
752
|
-
* 2. then `LUNORA_REMOTE` in the environment,
|
|
753
|
-
* 3. then the `remote` key in `lunora.json` (lowest — a project default).
|
|
754
|
-
*
|
|
755
|
-
* The flag and env are one-directional (they can only turn remote *on*); only
|
|
756
|
-
* the config preference carries a meaningful `false`, and it applies solely when
|
|
757
|
-
* neither stronger signal is present. So a project that sets `"remote": false`
|
|
758
|
-
* is still overridable per-run by `--remote` or `LUNORA_REMOTE=1`.
|
|
759
|
-
*/
|
|
760
|
-
declare const resolveRemoteEnabled: (inputs: RemoteEnableInputs) => boolean;
|
|
1081
|
+
* The project's Lunora source directory (the plugin's `schemaDir`), read the way
|
|
1082
|
+
* `@lunora/vite` sees it: the `schemaDir` string literal passed to the `lunora()`
|
|
1083
|
+
* call in `vite.config.*`, else `"lunora"`. The CLI commands that scan the
|
|
1084
|
+
* project (`dev`, `deploy`, `doctor`, `env`, `codegen`) resolve it here, so a
|
|
1085
|
+
* project that moved its functions to `backend/` gets its `ctx.*` reads and
|
|
1086
|
+
* schema facts read from `backend/` instead of from a directory that does not
|
|
1087
|
+
* exist.
|
|
1088
|
+
*
|
|
1089
|
+
* Parsed, never evaluated: a CLI command must not run the project's build
|
|
1090
|
+
* config. A computed `schemaDir`, or a plugin reached any other way, is not seen
|
|
1091
|
+
* and falls back to the default — the same answer as before this was read.
|
|
1092
|
+
*/
|
|
1093
|
+
declare const resolveSchemaDirectory: (projectRoot: string) => string;
|
|
761
1094
|
/** Core (always-scaffolded) secrets followed by the package-specific ones for the detected capabilities. */
|
|
762
1095
|
declare const requiredSecrets: (packageNames: ReadonlyArray<string>) => SecretEntry[];
|
|
763
1096
|
/**
|
|
764
|
-
* Whether an (already-unquoted) value looks like a fill-me-in placeholder —
|
|
765
|
-
* empty, angle-bracketed, or containing a known marker — rather than a real
|
|
766
|
-
* value. Used both when scaffolding (which values to regenerate) and by
|
|
767
|
-
* `lunora env doctor` (which set values are still unfilled).
|
|
768
|
-
*/
|
|
1097
|
+
* Whether an (already-unquoted) value looks like a fill-me-in placeholder —
|
|
1098
|
+
* empty, angle-bracketed, or containing a known marker — rather than a real
|
|
1099
|
+
* value. Used both when scaffolding (which values to regenerate) and by
|
|
1100
|
+
* `lunora env doctor` (which set values are still unfilled).
|
|
1101
|
+
*/
|
|
769
1102
|
declare const isPlaceholderValue: (value: string) => boolean;
|
|
770
1103
|
/**
|
|
771
|
-
* True for a secret
|
|
772
|
-
* 32-byte hex, like `openssl rand -hex 32`) —
|
|
773
|
-
* `LUNORA_ADMIN_TOKEN`, `STORAGE_SIGNING_SECRET
|
|
774
|
-
*
|
|
775
|
-
|
|
1104
|
+
* True for a secret key the registry says Lunora can mint locally (a random
|
|
1105
|
+
* 32-byte hex, like `openssl rand -hex 32`) — `AUTH_SECRET`,
|
|
1106
|
+
* `LUNORA_ADMIN_TOKEN`, `STORAGE_SIGNING_SECRET`, …
|
|
1107
|
+
*
|
|
1108
|
+
* Registry membership, NOT the key's name shape, is the rule. A secret-looking
|
|
1109
|
+
* key nothing in the registry declares (`OPENAI_API_KEY`,
|
|
1110
|
+
* `GITHUB_CLIENT_SECRET`, a project's own `*_TOKEN`) is provider-issued as far
|
|
1111
|
+
* as Lunora knows, so minting for it would write a value the provider rejects at
|
|
1112
|
+
* runtime — over the developer's own half-filled `.dev.vars` — and hide the gap
|
|
1113
|
+
* from `lunora env doctor`, whose job is to report it as unfilled.
|
|
1114
|
+
*/
|
|
776
1115
|
declare const isMintableSecretKey: (key: string) => boolean;
|
|
777
1116
|
/** Mint a fresh strong secret value — 64 hex chars (32 bytes), like `openssl rand -hex 32`. */
|
|
778
1117
|
declare const generateSecretValue: (randomHex?: (bytes: number) => string) => string;
|
|
779
1118
|
/**
|
|
780
|
-
* The outcome of planning a scaffold — a discriminated union so the orchestrator
|
|
781
|
-
* never has to re-derive whether `content` is present.
|
|
782
|
-
*
|
|
783
|
-
* `exists`: `.dev.vars` is already there; nothing to do.
|
|
784
|
-
* `no-example`: nothing to scaffold from (stay silent — the project may not use secrets).
|
|
785
|
-
* `generate`: write `content`, a copy of the example with secret-looking placeholders replaced by fresh random hex (`generatedKeys` lists which).
|
|
786
|
-
*/
|
|
1119
|
+
* The outcome of planning a scaffold — a discriminated union so the orchestrator
|
|
1120
|
+
* never has to re-derive whether `content` is present.
|
|
1121
|
+
*
|
|
1122
|
+
* `exists`: `.dev.vars` is already there; nothing to do.
|
|
1123
|
+
* `no-example`: nothing to scaffold from (stay silent — the project may not use secrets).
|
|
1124
|
+
* `generate`: write `content`, a copy of the example with secret-looking placeholders replaced by fresh random hex (`generatedKeys` lists which).
|
|
1125
|
+
*/
|
|
787
1126
|
type ScaffoldPlan = {
|
|
788
1127
|
content: string;
|
|
789
1128
|
generatedKeys: string[];
|
|
@@ -796,7 +1135,8 @@ type ScaffoldPlan = {
|
|
|
796
1135
|
/** Decide whether (and what) to scaffold. Pure — given the current state of the two files. */
|
|
797
1136
|
declare const planDevVariablesScaffold: (input: {
|
|
798
1137
|
devVarsExists: boolean;
|
|
799
|
-
exampleContent: string | undefined;
|
|
1138
|
+
exampleContent: string | undefined;
|
|
1139
|
+
/** Injectable for deterministic tests; defaults to `crypto.randomBytes`. */
|
|
800
1140
|
randomHex?: (bytes: number) => string;
|
|
801
1141
|
}) => ScaffoldPlan;
|
|
802
1142
|
interface AugmentPlan {
|
|
@@ -808,22 +1148,23 @@ interface AugmentPlan {
|
|
|
808
1148
|
missingKeys: string[];
|
|
809
1149
|
}
|
|
810
1150
|
/**
|
|
811
|
-
* Plan how to top up an existing `.dev.vars` from the example: every example key
|
|
812
|
-
* not already present becomes an appended line (secret placeholders filled with
|
|
813
|
-
* fresh random hex, other values copied). Pure — no I/O. Empty `missingKeys`
|
|
814
|
-
* means the file is already complete.
|
|
815
|
-
*/
|
|
1151
|
+
* Plan how to top up an existing `.dev.vars` from the example: every example key
|
|
1152
|
+
* not already present becomes an appended line (secret placeholders filled with
|
|
1153
|
+
* fresh random hex, other values copied). Pure — no I/O. Empty `missingKeys`
|
|
1154
|
+
* means the file is already complete.
|
|
1155
|
+
*/
|
|
816
1156
|
declare const planDevVariablesAugment: (input: {
|
|
817
1157
|
exampleContent: string;
|
|
818
|
-
existingContent: string;
|
|
1158
|
+
existingContent: string;
|
|
1159
|
+
/** Injectable for deterministic tests; defaults to `crypto.randomBytes`. */
|
|
819
1160
|
randomHex?: (bytes: number) => string;
|
|
820
1161
|
}) => AugmentPlan;
|
|
821
1162
|
interface EnsureDevVariablesDeps {
|
|
822
1163
|
/**
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
1164
|
+
* Ask the user to confirm generating the file. Return `true` to generate.
|
|
1165
|
+
* Consumers pass a TTY-aware prompt; in non-interactive contexts they should
|
|
1166
|
+
* resolve `false` (we then report `"declined"` and the caller can hint).
|
|
1167
|
+
*/
|
|
827
1168
|
confirm: (message: string) => Promise<boolean>;
|
|
828
1169
|
cwd: string;
|
|
829
1170
|
/** Emit a human-facing line (success / hint). */
|
|
@@ -842,41 +1183,51 @@ interface EnsureDevVariablesResult {
|
|
|
842
1183
|
status: EnsureDevVariablesStatus;
|
|
843
1184
|
}
|
|
844
1185
|
/**
|
|
845
|
-
*
|
|
846
|
-
*
|
|
847
|
-
*
|
|
848
|
-
*
|
|
849
|
-
*
|
|
850
|
-
*
|
|
851
|
-
*
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
1186
|
+
* Atomically (over)write a `.dev.vars`-shaped file, owner-only. For a file
|
|
1187
|
+
* holding secrets a torn write would destroy every other local value alongside
|
|
1188
|
+
* the new one, and the new value itself has no other recoverable copy if it
|
|
1189
|
+
* was never disclosed anywhere else (Cloudflare secrets are write-only).
|
|
1190
|
+
* Exported so a caller writing to a `.dev.vars`-shaped path outside this
|
|
1191
|
+
* module (`lunora deploy`'s minted-secret disclosure) reuses this instead of
|
|
1192
|
+
* hand-rolling another copy of the pattern.
|
|
1193
|
+
*/
|
|
1194
|
+
declare const writeDevVariablesFileAtomically: (path: string, content: string) => void;
|
|
1195
|
+
/**
|
|
1196
|
+
* Reconcile the project's `.dev.vars` with its `.dev.vars.example`:
|
|
1197
|
+
*
|
|
1198
|
+
* - file missing → offer to generate it (secret placeholders auto-filled);
|
|
1199
|
+
* - file present but missing keys the example lists → offer to append them;
|
|
1200
|
+
* - file present and complete → nothing to do.
|
|
1201
|
+
*
|
|
1202
|
+
* Prompts via `confirm` (skipped when `yes`); never overwrites existing values.
|
|
1203
|
+
* Returns what happened so the caller can tailor any follow-up. Shared by
|
|
1204
|
+
* `lunora dev` and the `@lunora/vite` dev server. All side effects funnel
|
|
1205
|
+
* through `confirm`/`info`/`randomHex`.
|
|
1206
|
+
*/
|
|
856
1207
|
declare const ensureDevVariables: (deps: EnsureDevVariablesDeps) => Promise<EnsureDevVariablesResult>;
|
|
857
1208
|
/**
|
|
858
|
-
* Build the text that should be merged into `.dev.vars.example` for the given
|
|
859
|
-
* set of package names. Only entries whose key is not already present in
|
|
860
|
-
* `existingKeys` are included (additive / idempotent). Returns an empty string
|
|
861
|
-
* when there is nothing to add.
|
|
862
|
-
*
|
|
863
|
-
* The output is grouped by package with a blank-line separator so the file
|
|
864
|
-
* reads cleanly when multiple packages each contribute several keys.
|
|
865
|
-
*
|
|
866
|
-
* **Safety invariant:** this function never writes a real secret — every value
|
|
867
|
-
* in the output is the entry's `placeholderValue`.
|
|
868
|
-
*/
|
|
1209
|
+
* Build the text that should be merged into `.dev.vars.example` for the given
|
|
1210
|
+
* set of package names. Only entries whose key is not already present in
|
|
1211
|
+
* `existingKeys` are included (additive / idempotent). Returns an empty string
|
|
1212
|
+
* when there is nothing to add.
|
|
1213
|
+
*
|
|
1214
|
+
* The output is grouped by package with a blank-line separator so the file
|
|
1215
|
+
* reads cleanly when multiple packages each contribute several keys.
|
|
1216
|
+
*
|
|
1217
|
+
* **Safety invariant:** this function never writes a real secret — every value
|
|
1218
|
+
* in the output is the entry's `placeholderValue`.
|
|
1219
|
+
*/
|
|
869
1220
|
declare const buildPackageSecretsBlock: (packageNames: ReadonlyArray<string>, existingKeys: ReadonlySet<string>) => string;
|
|
870
1221
|
/**
|
|
871
|
-
* Write (or update) `.dev.vars.example` so that it contains the secrets
|
|
872
|
-
* required by `packageNames`. Existing lines are never removed or rewritten;
|
|
873
|
-
* new entries are appended (with a blank-line separator after existing content).
|
|
874
|
-
*
|
|
875
|
-
* Idempotent: re-running with the same `packageNames` does not duplicate keys
|
|
876
|
-
* already in the file. Returns the list of keys that were actually appended.
|
|
877
|
-
*
|
|
878
|
-
* **Safety invariant:** only placeholder values are written — no real secrets.
|
|
879
|
-
*/
|
|
1222
|
+
* Write (or update) `.dev.vars.example` so that it contains the secrets
|
|
1223
|
+
* required by `packageNames`. Existing lines are never removed or rewritten;
|
|
1224
|
+
* new entries are appended (with a blank-line separator after existing content).
|
|
1225
|
+
*
|
|
1226
|
+
* Idempotent: re-running with the same `packageNames` does not duplicate keys
|
|
1227
|
+
* already in the file. Returns the list of keys that were actually appended.
|
|
1228
|
+
*
|
|
1229
|
+
* **Safety invariant:** only placeholder values are written — no real secrets.
|
|
1230
|
+
*/
|
|
880
1231
|
declare const ensureDevVariablesExample: (cwd: string, packageNames: ReadonlyArray<string>) => string[];
|
|
881
1232
|
interface DevSecretsFillPlan {
|
|
882
1233
|
/** {@link CORE_SECRETS} keys appended because they were absent (each generated). */
|
|
@@ -887,19 +1238,21 @@ interface DevSecretsFillPlan {
|
|
|
887
1238
|
filledKeys: string[];
|
|
888
1239
|
}
|
|
889
1240
|
/**
|
|
890
|
-
* Plan the in-place generation of dev secrets for a `.dev.vars`. First, every
|
|
891
|
-
* line whose
|
|
892
|
-
*
|
|
893
|
-
* generated value
|
|
894
|
-
* secret blank) becomes usable on `lunora dev` / `vite dev` without
|
|
895
|
-
* running `openssl` by hand.
|
|
896
|
-
*
|
|
897
|
-
*
|
|
898
|
-
*
|
|
899
|
-
*
|
|
900
|
-
*
|
|
901
|
-
*
|
|
902
|
-
|
|
1241
|
+
* Plan the in-place generation of dev secrets for a `.dev.vars`. First, every
|
|
1242
|
+
* line whose key is {@link isMintableSecretKey mintable} — registry membership,
|
|
1243
|
+
* NOT the key's name shape — and whose value is empty or a placeholder gets a
|
|
1244
|
+
* freshly generated value, so a `lunora add`-scaffolded `.dev.vars` (which
|
|
1245
|
+
* writes each secret blank) becomes usable on `lunora dev` / `vite dev` without
|
|
1246
|
+
* the user running `openssl` by hand. A provider-issued key (`OPENAI_API_KEY`,
|
|
1247
|
+
* `STRIPE_SECRET_KEY`) is left verbatim so `lunora env doctor` can still report
|
|
1248
|
+
* it as unfilled. Second, any {@link CORE_SECRETS} key absent from
|
|
1249
|
+
* the file is appended (generated) — notably `LUNORA_ADMIN_TOKEN`, which the
|
|
1250
|
+
* local Studio needs to call the worker's admin gate in dev (without it the
|
|
1251
|
+
* Studio shows its login gate).
|
|
1252
|
+
*
|
|
1253
|
+
* Pure (given `randomHex`): real (non-placeholder) values are never touched, and
|
|
1254
|
+
* comments + non-secret entries are preserved verbatim.
|
|
1255
|
+
*/
|
|
903
1256
|
declare const planDevSecretsFill: (input: {
|
|
904
1257
|
existingContent: string;
|
|
905
1258
|
randomHex?: (bytes: number) => string;
|
|
@@ -913,25 +1266,38 @@ interface FillDevSecretsResult {
|
|
|
913
1266
|
status: "created" | "filled" | "unchanged";
|
|
914
1267
|
}
|
|
915
1268
|
/**
|
|
916
|
-
* Generate any missing/empty dev secrets in the project's `.dev.vars`, in place.
|
|
917
|
-
*
|
|
918
|
-
* Complements {@link ensureDevVariables} (which scaffolds `.dev.vars` from
|
|
919
|
-
* `.dev.vars.example`). A `lunora add`-scaffolded project writes secrets blank
|
|
920
|
-
* straight into `.dev.vars` (no example) and never includes `LUNORA_ADMIN_TOKEN`
|
|
921
|
-
* — so the worker boots with empty secrets and the Studio shows its login gate.
|
|
922
|
-
* This fills those gaps at dev startup, so both `lunora dev` and the
|
|
923
|
-
* `@lunora/vite` dev server give a working project with zero manual `openssl`.
|
|
924
|
-
*
|
|
925
|
-
* Never overwrites a real (non-placeholder) value.
|
|
926
|
-
*
|
|
927
|
-
|
|
1269
|
+
* Generate any missing/empty dev secrets in the project's `.dev.vars`, in place.
|
|
1270
|
+
*
|
|
1271
|
+
* Complements {@link ensureDevVariables} (which scaffolds `.dev.vars` from
|
|
1272
|
+
* `.dev.vars.example`). A `lunora add`-scaffolded project writes secrets blank
|
|
1273
|
+
* straight into `.dev.vars` (no example) and never includes `LUNORA_ADMIN_TOKEN`
|
|
1274
|
+
* — so the worker boots with empty secrets and the Studio shows its login gate.
|
|
1275
|
+
* This fills those gaps at dev startup, so both `lunora dev` and the
|
|
1276
|
+
* `@lunora/vite` dev server give a working project with zero manual `openssl`.
|
|
1277
|
+
*
|
|
1278
|
+
* Never overwrites a real (non-placeholder) value. Two writers, on purpose: when
|
|
1279
|
+
* the file does not exist yet, the create goes through {@link createExclusively}
|
|
1280
|
+
* and loses to a peer that creates it first; when it exists, the fill rewrites
|
|
1281
|
+
* it through {@link atomicWrite} (temp + rename, owner-only) with the keys it
|
|
1282
|
+
* just read and planned against.
|
|
1283
|
+
*/
|
|
928
1284
|
declare const fillDevSecrets: (deps: {
|
|
929
1285
|
cwd: string;
|
|
930
1286
|
info?: (message: string) => void;
|
|
931
1287
|
randomHex?: (bytes: number) => string;
|
|
932
1288
|
}) => FillDevSecretsResult;
|
|
1289
|
+
/** Storage backends `.global()` accepts. A closed union, so it is never free text. */
|
|
1290
|
+
type GlobalBackend = "d1" | "hyperdrive";
|
|
933
1291
|
/** Add a new table to `defineSchema({ ... })`. */
|
|
934
1292
|
interface AddTableEdit {
|
|
1293
|
+
/**
|
|
1294
|
+
* Mark the table `.global()`. Pass `{}` for the D1 default, or a backend for
|
|
1295
|
+
* an external store — `lunora introspect` uses `{ backend: "hyperdrive" }`
|
|
1296
|
+
* because the rows live in the database it read.
|
|
1297
|
+
*/
|
|
1298
|
+
readonly global?: {
|
|
1299
|
+
readonly backend?: GlobalBackend;
|
|
1300
|
+
};
|
|
935
1301
|
readonly kind: "addTable";
|
|
936
1302
|
readonly table: string;
|
|
937
1303
|
}
|
|
@@ -941,11 +1307,11 @@ interface AddOptionalColumnEdit {
|
|
|
941
1307
|
readonly kind: "addOptionalColumn";
|
|
942
1308
|
readonly table: string;
|
|
943
1309
|
/**
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1310
|
+
* Inner validator expression text WITHOUT the `v.optional(...)` wrapper, e.g.
|
|
1311
|
+
* `v.string()`. Always wrapped in `v.optional(...)` on apply, because only
|
|
1312
|
+
* optional columns are additive-safe (a required column needs a backfill
|
|
1313
|
+
* migration).
|
|
1314
|
+
*/
|
|
949
1315
|
readonly validator: string;
|
|
950
1316
|
}
|
|
951
1317
|
/** Add a secondary index to an existing table. */
|
|
@@ -959,9 +1325,9 @@ interface AddIndexEdit {
|
|
|
959
1325
|
/** Additive edits — the only requests {@link applyAdditiveEdit} applies. */
|
|
960
1326
|
type AdditiveEdit = AddIndexEdit | AddOptionalColumnEdit | AddTableEdit;
|
|
961
1327
|
/**
|
|
962
|
-
* Destructive edits — never applied directly; routed to the migration handoff
|
|
963
|
-
* (plan 024 Item 5). Carried as data so the editor can describe the request.
|
|
964
|
-
*/
|
|
1328
|
+
* Destructive edits — never applied directly; routed to the migration handoff
|
|
1329
|
+
* (plan 024 Item 5). Carried as data so the editor can describe the request.
|
|
1330
|
+
*/
|
|
965
1331
|
interface DestructiveEdit {
|
|
966
1332
|
readonly column?: string;
|
|
967
1333
|
readonly kind: "changeColumnType" | "dropColumn" | "dropTable" | "makeRequired" | "renameColumn";
|
|
@@ -972,9 +1338,9 @@ interface DestructiveEdit {
|
|
|
972
1338
|
/** Any edit the editor can request. */
|
|
973
1339
|
type SchemaEdit = AdditiveEdit | DestructiveEdit;
|
|
974
1340
|
/**
|
|
975
|
-
* Classify an edit request. Additive edits ({@link AdditiveEdit}) apply
|
|
976
|
-
* directly; everything else changes stored data and is destructive.
|
|
977
|
-
*/
|
|
1341
|
+
* Classify an edit request. Additive edits ({@link AdditiveEdit}) apply
|
|
1342
|
+
* directly; everything else changes stored data and is destructive.
|
|
1343
|
+
*/
|
|
978
1344
|
declare const classifyEdit: (edit: SchemaEdit) => "additive" | "destructive";
|
|
979
1345
|
/** Failure reasons an additive edit can report. */
|
|
980
1346
|
type ApplyFailureReason = "aliased-define-schema" | "destructive" | "duplicate-column" | "duplicate-index" | "duplicate-table" | "invalid-identifier" | "invalid-validator" | "no-define-schema" | "non-object-argument" | "unknown-table";
|
|
@@ -987,10 +1353,10 @@ type ApplyEditResult = {
|
|
|
987
1353
|
text: string;
|
|
988
1354
|
};
|
|
989
1355
|
/**
|
|
990
|
-
* Apply an **additive** edit to a schema source string, preserving formatting.
|
|
991
|
-
* Destructive edits are refused with `{ ok: false, reason: "destructive" }`;
|
|
992
|
-
* route them through the migration handoff (plan 024 Item 5).
|
|
993
|
-
*/
|
|
1356
|
+
* Apply an **additive** edit to a schema source string, preserving formatting.
|
|
1357
|
+
* Destructive edits are refused with `{ ok: false, reason: "destructive" }`;
|
|
1358
|
+
* route them through the migration handoff (plan 024 Item 5).
|
|
1359
|
+
*/
|
|
994
1360
|
declare const applyAdditiveEdit: (source: string, edit: SchemaEdit) => ApplyEditResult;
|
|
995
1361
|
/** A single declared column: its name and the raw validator expression text. */
|
|
996
1362
|
interface SchemaColumn {
|
|
@@ -1029,40 +1395,15 @@ type ParseSchemaResult = {
|
|
|
1029
1395
|
tables: ReadonlyArray<SchemaTable>;
|
|
1030
1396
|
};
|
|
1031
1397
|
/**
|
|
1032
|
-
*
|
|
1033
|
-
*
|
|
1034
|
-
*
|
|
1035
|
-
*/
|
|
1036
|
-
|
|
1037
|
-
/**
|
|
1038
|
-
* Parse the tables (with typed columns + indexes) out of a `lunora/schema.ts`
|
|
1039
|
-
* source string. Returns a tagged result so callers can render a helpful
|
|
1040
|
-
* message per failure mode without throwing.
|
|
1041
|
-
*/
|
|
1398
|
+
* Parse the tables (with typed columns + indexes) out of a `lunora/schema.ts`
|
|
1399
|
+
* source string. Returns a tagged result so callers can render a helpful
|
|
1400
|
+
* message per failure mode without throwing.
|
|
1401
|
+
*/
|
|
1042
1402
|
declare const parseSchema: (source: string) => ParseSchemaResult;
|
|
1043
|
-
interface SchemaInfo {
|
|
1044
|
-
/** Whether the lunora schema declares any `.global()` table. */
|
|
1045
|
-
hasGlobalTable: boolean;
|
|
1046
|
-
/** Names of vector indexes declared via `.vectorize()` / `defineVectorIndex()`. */
|
|
1047
|
-
vectorIndexNames?: ReadonlyArray<string>;
|
|
1048
|
-
}
|
|
1049
|
-
interface DiscoverSchemaInfoResult {
|
|
1050
|
-
/** Parse error message, when the schema exists but could not be analyzed. */
|
|
1051
|
-
error?: string;
|
|
1052
|
-
/** Schema facts, or `undefined` when no `schema.ts` exists or parsing failed. */
|
|
1053
|
-
info: SchemaInfo | undefined;
|
|
1054
|
-
}
|
|
1055
|
-
/**
|
|
1056
|
-
* Discover {@link SchemaInfo} for a project. Returns `{ info: undefined }` when
|
|
1057
|
-
* the project declares no `schema.ts` (not an error), or `{ info: undefined,
|
|
1058
|
-
* error }` when a present schema could not be parsed — callers decide whether a
|
|
1059
|
-
* parse failure is a warning (validator) or simply ignorable (inference).
|
|
1060
|
-
*/
|
|
1061
|
-
declare const discoverSchemaInfo: (projectRoot: string, schemaDirectory: string) => DiscoverSchemaInfoResult;
|
|
1062
1403
|
/**
|
|
1063
|
-
* A badge: the short colored label that prefixes a line. `bg`/`fg` are hex so the
|
|
1064
|
-
* same value drives both colorize's `bgHex().hex()` and the tui
|
|
1065
|
-
*/
|
|
1404
|
+
* A badge: the short colored label that prefixes a line. `bg`/`fg` are hex so the
|
|
1405
|
+
* same value drives both colorize's `bgHex().hex()` and the tui `<Text>` props.
|
|
1406
|
+
*/
|
|
1066
1407
|
interface BadgeSpec {
|
|
1067
1408
|
bg: `#${string}`;
|
|
1068
1409
|
fg: `#${string}`;
|
|
@@ -1078,24 +1419,24 @@ type BadgeName = LevelBadgeName | StepBadgeName;
|
|
|
1078
1419
|
/** The ordered step-phase names, used to register custom pail log types. */
|
|
1079
1420
|
declare const STEP_BADGE_NAMES: ReadonlyArray<StepBadgeName>;
|
|
1080
1421
|
/**
|
|
1081
|
-
* Every badge, keyed by name. Levels get their conventional colors (red/amber/
|
|
1082
|
-
* green/blue/grey); step phases follow create-astro's green→purple→cyan rhythm.
|
|
1083
|
-
*/
|
|
1422
|
+
* Every badge, keyed by name. Levels get their conventional colors (red/amber/
|
|
1423
|
+
* green/blue/grey); step phases follow create-astro's green→purple→cyan rhythm.
|
|
1424
|
+
*/
|
|
1084
1425
|
declare const BADGES: Record<BadgeName, BadgeSpec>;
|
|
1085
1426
|
/**
|
|
1086
|
-
* Luna, the mascot: the folklore rabbit-in-the-moon — a bunny tucked inside the
|
|
1087
|
-
* moon disc. Pure ASCII so it renders the same everywhere (including piped logs).
|
|
1088
|
-
* The CLI signs off the `init` flow with it, the way create-astro closes with
|
|
1089
|
-
* Houston.
|
|
1090
|
-
*/
|
|
1427
|
+
* Luna, the mascot: the folklore rabbit-in-the-moon — a bunny tucked inside the
|
|
1428
|
+
* moon disc. Pure ASCII so it renders the same everywhere (including piped logs).
|
|
1429
|
+
* The CLI signs off the `init` flow with it, the way create-astro closes with
|
|
1430
|
+
* Houston.
|
|
1431
|
+
*/
|
|
1091
1432
|
declare const LUNA_NAME = "Luna";
|
|
1092
1433
|
declare const LUNA_SIGNOFF = "Safe travels, voyager.";
|
|
1093
1434
|
declare const LUNA_BUNNY: string;
|
|
1094
1435
|
/**
|
|
1095
|
-
* {@link LUNA_BUNNY} with its leading newline stripped, ready to render inline
|
|
1096
|
-
* (beside the name + sign-off). Both render paths — the tui mascot frame and the
|
|
1097
|
-
* pail off-TTY fallback — use this so neither re-implements the strip.
|
|
1098
|
-
*/
|
|
1436
|
+
* {@link LUNA_BUNNY} with its leading newline stripped, ready to render inline
|
|
1437
|
+
* (beside the name + sign-off). Both render paths — the tui mascot frame and the
|
|
1438
|
+
* pail off-TTY fallback — use this so neither re-implements the strip.
|
|
1439
|
+
*/
|
|
1099
1440
|
declare const LUNA_ART: string;
|
|
1100
1441
|
/** The colored part of a badge — the word with one space of padding each side. */
|
|
1101
1442
|
declare const padBadge: (text: string) => string;
|
|
@@ -1109,214 +1450,4 @@ declare const badgeWidth: (_spec: BadgeSpec) => number;
|
|
|
1109
1450
|
declare const paintBadge: (spec: BadgeSpec) => string;
|
|
1110
1451
|
/** Dim continuation text (a step's chosen answer, shown under the question). */
|
|
1111
1452
|
declare const paintAnswer: (text: string) => string;
|
|
1112
|
-
|
|
1113
|
-
declare const WRANGLER_FILES: readonly ["wrangler.jsonc", "wrangler.json"];
|
|
1114
|
-
/** Locate the project's wrangler config, or `undefined` when none exists. */
|
|
1115
|
-
declare const findWranglerFile: (projectRoot: string) => string | undefined;
|
|
1116
|
-
interface ReadWranglerResult<T> {
|
|
1117
|
-
/** Parsed config, or `undefined` when the file was not valid JSONC. */
|
|
1118
|
-
parsed: T | undefined;
|
|
1119
|
-
/** Raw file text — needed for comment-preserving `modify`/`applyEdits`. */
|
|
1120
|
-
text: string;
|
|
1121
|
-
}
|
|
1122
|
-
/**
|
|
1123
|
-
* Read and JSONC-parse a wrangler config file. Returns the raw `text` (for
|
|
1124
|
-
* structural edits) alongside `parsed`, which is `undefined` when the file is
|
|
1125
|
-
* not valid JSONC or does not parse to an object. Allows trailing commas, as
|
|
1126
|
-
* wrangler does.
|
|
1127
|
-
*/
|
|
1128
|
-
declare const readWranglerJsonc: <T = unknown>(wranglerPath: string) => ReadWranglerResult<T>;
|
|
1129
|
-
declare const REQUIRED_COMPATIBILITY_DATE: string;
|
|
1130
|
-
declare const REQUIRED_FLAG: string;
|
|
1131
|
-
interface WranglerDurableObjectBinding {
|
|
1132
|
-
class_name?: string;
|
|
1133
|
-
name?: string;
|
|
1134
|
-
}
|
|
1135
|
-
/**
|
|
1136
|
-
* A `tail_consumers` entry: a Worker that receives this Worker's tail events
|
|
1137
|
-
* (logs, exceptions, fetch metadata) for forwarding to an external sink. See
|
|
1138
|
-
* `withTailConsumer` for the wiring helper.
|
|
1139
|
-
*/
|
|
1140
|
-
interface TailConsumer {
|
|
1141
|
-
/** Optional Cloudflare environment of the consumer Worker. */
|
|
1142
|
-
environment?: string;
|
|
1143
|
-
/** Name of the Worker that consumes tail events. */
|
|
1144
|
-
service?: string;
|
|
1145
|
-
}
|
|
1146
|
-
/** A wrangler `containers[]` entry (parsed from untrusted JSONC). */
|
|
1147
|
-
interface WranglerContainerEntry {
|
|
1148
|
-
class_name?: string;
|
|
1149
|
-
image?: string;
|
|
1150
|
-
instance_type?: string | {
|
|
1151
|
-
disk_mb?: number;
|
|
1152
|
-
memory_mib?: number;
|
|
1153
|
-
vcpu?: number;
|
|
1154
|
-
};
|
|
1155
|
-
max_instances?: number;
|
|
1156
|
-
}
|
|
1157
|
-
/**
|
|
1158
|
-
* A wrangler `workflows[]` entry (parsed from untrusted JSONC). Unlike
|
|
1159
|
-
* containers, workflows are NOT Durable Objects — the entry stands alone (no
|
|
1160
|
-
* `durable_objects` binding, no migration class).
|
|
1161
|
-
*/
|
|
1162
|
-
interface WranglerWorkflowEntry {
|
|
1163
|
-
binding?: string;
|
|
1164
|
-
class_name?: string;
|
|
1165
|
-
name?: string;
|
|
1166
|
-
}
|
|
1167
|
-
/** A wrangler `queues.producers[]` entry — a `Queue` binding sending to `queue`. */
|
|
1168
|
-
interface WranglerQueueProducer {
|
|
1169
|
-
binding?: string;
|
|
1170
|
-
delivery_delay?: number;
|
|
1171
|
-
queue?: string;
|
|
1172
|
-
}
|
|
1173
|
-
/** A wrangler `queues.consumers[]` entry — push (worker) or `type: "http_pull"`. */
|
|
1174
|
-
interface WranglerQueueConsumer {
|
|
1175
|
-
dead_letter_queue?: string;
|
|
1176
|
-
max_batch_size?: number;
|
|
1177
|
-
max_batch_timeout?: number;
|
|
1178
|
-
max_retries?: number;
|
|
1179
|
-
queue?: string;
|
|
1180
|
-
retry_delay?: number;
|
|
1181
|
-
type?: string;
|
|
1182
|
-
}
|
|
1183
|
-
interface WranglerConfig {
|
|
1184
|
-
analytics_engine_datasets?: ReadonlyArray<{
|
|
1185
|
-
binding?: string;
|
|
1186
|
-
dataset?: string;
|
|
1187
|
-
} | null | undefined>;
|
|
1188
|
-
assets?: {
|
|
1189
|
-
binding?: string;
|
|
1190
|
-
directory?: string;
|
|
1191
|
-
html_handling?: string;
|
|
1192
|
-
not_found_handling?: string;
|
|
1193
|
-
};
|
|
1194
|
-
browser?: {
|
|
1195
|
-
binding?: string;
|
|
1196
|
-
};
|
|
1197
|
-
compatibility_date?: string;
|
|
1198
|
-
compatibility_flags?: ReadonlyArray<string>;
|
|
1199
|
-
containers?: ReadonlyArray<WranglerContainerEntry | null | undefined>;
|
|
1200
|
-
d1_databases?: ReadonlyArray<{
|
|
1201
|
-
binding?: string;
|
|
1202
|
-
}>;
|
|
1203
|
-
dispatch_namespaces?: ReadonlyArray<{
|
|
1204
|
-
binding?: string;
|
|
1205
|
-
namespace?: string;
|
|
1206
|
-
outbound?: unknown;
|
|
1207
|
-
} | null | undefined>;
|
|
1208
|
-
durable_objects?: {
|
|
1209
|
-
bindings?: ReadonlyArray<WranglerDurableObjectBinding>;
|
|
1210
|
-
};
|
|
1211
|
-
flagship?: ReadonlyArray<{
|
|
1212
|
-
app_id?: string;
|
|
1213
|
-
binding?: string;
|
|
1214
|
-
} | null | undefined>;
|
|
1215
|
-
hyperdrive?: ReadonlyArray<{
|
|
1216
|
-
binding?: string;
|
|
1217
|
-
id?: string;
|
|
1218
|
-
localConnectionString?: string;
|
|
1219
|
-
} | null | undefined>;
|
|
1220
|
-
images?: {
|
|
1221
|
-
binding?: string;
|
|
1222
|
-
};
|
|
1223
|
-
kv_namespaces?: ReadonlyArray<{
|
|
1224
|
-
binding?: string;
|
|
1225
|
-
id?: string;
|
|
1226
|
-
} | null | undefined>;
|
|
1227
|
-
logpush?: boolean;
|
|
1228
|
-
migrations?: ReadonlyArray<{
|
|
1229
|
-
new_classes?: ReadonlyArray<string>;
|
|
1230
|
-
new_sqlite_classes?: ReadonlyArray<string>;
|
|
1231
|
-
} | null | undefined>;
|
|
1232
|
-
mtls_certificates?: ReadonlyArray<{
|
|
1233
|
-
binding?: string;
|
|
1234
|
-
certificate_id?: string;
|
|
1235
|
-
} | null | undefined>;
|
|
1236
|
-
observability?: {
|
|
1237
|
-
enabled?: boolean;
|
|
1238
|
-
head_sampling_rate?: number;
|
|
1239
|
-
logs?: {
|
|
1240
|
-
enabled?: boolean;
|
|
1241
|
-
head_sampling_rate?: number;
|
|
1242
|
-
};
|
|
1243
|
-
};
|
|
1244
|
-
pipelines?: ReadonlyArray<{
|
|
1245
|
-
binding?: string;
|
|
1246
|
-
pipeline?: string;
|
|
1247
|
-
} | null | undefined>;
|
|
1248
|
-
placement?: {
|
|
1249
|
-
mode?: string;
|
|
1250
|
-
};
|
|
1251
|
-
queues?: {
|
|
1252
|
-
consumers?: ReadonlyArray<WranglerQueueConsumer | null | undefined>;
|
|
1253
|
-
producers?: ReadonlyArray<WranglerQueueProducer | null | undefined>;
|
|
1254
|
-
};
|
|
1255
|
-
r2_buckets?: ReadonlyArray<{
|
|
1256
|
-
binding?: string;
|
|
1257
|
-
}>;
|
|
1258
|
-
secrets_store_secrets?: ReadonlyArray<{
|
|
1259
|
-
binding?: string;
|
|
1260
|
-
secret_name?: string;
|
|
1261
|
-
store_id?: string;
|
|
1262
|
-
} | null | undefined>;
|
|
1263
|
-
send_email?: ReadonlyArray<{
|
|
1264
|
-
allowed_destination_addresses?: ReadonlyArray<string>;
|
|
1265
|
-
destination_address?: string;
|
|
1266
|
-
name?: string;
|
|
1267
|
-
} | null | undefined>;
|
|
1268
|
-
services?: ReadonlyArray<{
|
|
1269
|
-
binding?: string;
|
|
1270
|
-
entrypoint?: string;
|
|
1271
|
-
environment?: string;
|
|
1272
|
-
service?: string;
|
|
1273
|
-
} | null | undefined>;
|
|
1274
|
-
tail_consumers?: ReadonlyArray<TailConsumer | null | undefined>;
|
|
1275
|
-
vars?: Record<string, unknown>;
|
|
1276
|
-
vectorize?: ReadonlyArray<{
|
|
1277
|
-
binding?: string;
|
|
1278
|
-
index_name?: string;
|
|
1279
|
-
} | null | undefined>;
|
|
1280
|
-
workflows?: ReadonlyArray<WranglerWorkflowEntry | null | undefined>;
|
|
1281
|
-
}
|
|
1282
|
-
interface WranglerValidationReport {
|
|
1283
|
-
errors: string[];
|
|
1284
|
-
valid: boolean;
|
|
1285
|
-
warnings: string[];
|
|
1286
|
-
}
|
|
1287
|
-
/**
|
|
1288
|
-
* Return a new `WranglerConfig` with `consumer` present in `tail_consumers`,
|
|
1289
|
-
* wiring this Worker to forward its tail events (logs/exceptions) to another
|
|
1290
|
-
* Worker that fans them out to an external sink. Pure and idempotent: an
|
|
1291
|
-
* existing entry with the same `service` + `environment` is left untouched
|
|
1292
|
-
* rather than duplicated, so it is safe to call on every codegen/deploy.
|
|
1293
|
-
*/
|
|
1294
|
-
declare const withTailConsumer: (wrangler: WranglerConfig, consumer: TailConsumer) => WranglerConfig;
|
|
1295
|
-
/**
|
|
1296
|
-
* Pure validator: given a parsed `WranglerConfig` object and an optional
|
|
1297
|
-
* `SchemaInfo`, produce a structured report. Performs no I/O.
|
|
1298
|
-
*/
|
|
1299
|
-
declare const validateWranglerConfig: (wrangler: WranglerConfig | undefined, schema?: SchemaInfo) => WranglerValidationReport;
|
|
1300
|
-
/**
|
|
1301
|
-
* Convenience alias matching the original task-spec signature
|
|
1302
|
-
* `validateWrangler(wranglerJson, schema)` returning
|
|
1303
|
-
* `{ valid, errors, warnings }`.
|
|
1304
|
-
*/
|
|
1305
|
-
declare const validateWrangler: typeof validateWranglerConfig;
|
|
1306
|
-
interface WranglerProjectValidationOptions {
|
|
1307
|
-
projectRoot: string;
|
|
1308
|
-
schemaDir?: string;
|
|
1309
|
-
}
|
|
1310
|
-
interface WranglerProjectValidationResult {
|
|
1311
|
-
problems: ReadonlyArray<string>;
|
|
1312
|
-
report: WranglerValidationReport;
|
|
1313
|
-
wranglerPath: string | undefined;
|
|
1314
|
-
}
|
|
1315
|
-
/**
|
|
1316
|
-
* File-system aware variant: reads `wrangler.jsonc`/`wrangler.json` from
|
|
1317
|
-
* the given project root, discovers the schema (if any), and delegates to
|
|
1318
|
-
* `validateWranglerConfig`. Returns the legacy
|
|
1319
|
-
* `{ problems, wranglerPath }` shape plus the structured `report`.
|
|
1320
|
-
*/
|
|
1321
|
-
declare const validateWranglerProject: (options: WranglerProjectValidationOptions) => WranglerProjectValidationResult;
|
|
1322
|
-
export { ACCENT, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DiscoverContainerInfoResult, type DiscoverSchemaInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type ExportGap, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type InferOptions, type InferredBindings, type InferredContainer, type InferredWorkflow, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MaterializeOptions, type MaterializeResult, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type ParseSchemaResult, REMOTE_ELIGIBLE_KEYS, REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, ROOT_SKILL_NAME, type ReadWranglerResult, type ReconcileBindingsResult, type RemoteBindingPlan, type RemoteEnableInputs, type RemotePreference, type RemoteWranglerShape, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaInfo, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, type TailConsumer, WRANGLER_FILES, type WranglerConfig, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, applyAdditiveEdit, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, classifyEdit, createConfirm, detectAgentRules, detectFramework, discoverContainerInfo, discoverSchemaInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, fillDevSecrets, findWranglerFile, formatLunoraEvent, generateSecretValue, inferLunoraBindings, injectRemoteFlags, interpretRemote, isInteractive, isMintableSecretKey, isPlaceholderValue, isRemoteEnvEnabled, materializeRemoteWranglerConfig, packageNamesFromBindings, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, planRemoteBindings, promptMultiSelect, promptSelect, promptYesNo, readLinkedProject, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, requiredSecrets, resolveRemoteEnabled, secretsForPackages, streamContainerLogs, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeLinkedProject };
|
|
1453
|
+
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 CelldDevSession, type CelldDevSessionOptions, type CelldLineOrigin, 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, DEV_WORKER_ENV_VALUE, DEV_WORKER_ENV_VAR, type DeployDriver, type DestructiveEdit, type DetectedFramework, type DevProcess, type DevProcessOptions, type DevProcessSpawner, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverWorkflowInfoResult, type DiscoveryCache, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type FillDevSecretsResult, type FindingLogger, 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_EVENT_SOURCE, LUNORA_IGNORED_PATHS, LUNORA_SKILL_NAMES, LUNORA_TAG, type LevelBadgeName, type LinkedProject, type LintIgnoreOutcome, type LintIgnoreStatus, type LintTool, type LunoraFormattedLine, type LunoraLineLevel, LunoraReporter, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type PackageManager, type PackageManagerProbe, type ParseSchemaResult, type PostCodegenHookResult, type ProjectionPurpose, ROOT_SKILL_NAME, type RemotePreference, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, type ToolchainCommand, type ToolchainInvocation, acceptsConnection, addArgsFor, advisoryLine, applyAdditiveEdit, applyLintIgnores, badgeLead, badgeWidth, blockingFindingsMessage, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, createConfirm, deployTargetIds, detectAgentRules, detectAiAgent, detectFramework, detectInstalledManagers, detectLintTools, detectPackageManager, discoverAgentInfo, discoverContainerInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, ensureDevWorkerEnv, escapeRegExp, execArgsFor, fillDevSecrets, formatLunoraEvent, generateSecretValue, installArgsFor, interpretRemote, isCodegenDisabled, isDevServerReady, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, isRunnableTarget, lunoraLine, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, planToolchainInvocation, projectUsesUmbrella, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencies, readProjectDependencyNames, readProjectManifest, readProjectRemotePreference, readProjectTarget, removeDevVariableLine, reportCodegenFindings, requiredSecrets, resolveDeployDriver, resolveProjectTarget, resolveSchemaDirectory, resolveTargetOrThrow, runPostCodegenHook, runScriptArgsFor, runScriptCommand, runnableTargetIds, secretsForPackages, startCelldDevSession, startDevProcess, streamContainerLogs, targetRunsOwnDevServer, toolchainExecArgs, updateDevServerState, upsertDevVariableLine, writeDevServerState, writeDevVariablesFileAtomically, writeLinkedProject };
|