@lunora/config 1.0.0-alpha.8 → 1.0.0-alpha.80
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 +6 -0
- package/__assets__/package-og.svg +1 -1
- package/dist/index.d.mts +885 -461
- package/dist/index.d.ts +885 -461
- package/dist/index.mjs +17 -9
- package/dist/packem_shared/AGENT_MODE_ENV-B5R7jpY7.mjs +17 -0
- package/dist/packem_shared/DEV_DAEMON_ENV-FIEtW7Fz.mjs +163 -0
- package/dist/packem_shared/{LUNORA_EVENT_SOURCE-D2fDeGB6.mjs → LUNORA_EVENT_SOURCE-M1KM9_pR.mjs} +28 -2
- package/dist/packem_shared/PACKAGE_SECRETS_REGISTRY-NCTSphDk.mjs +138 -0
- package/dist/packem_shared/{POLICY_SCAFFOLD_ENDPOINT-CiC2IGKx.mjs → POLICY_SCAFFOLD_ENDPOINT-CvTZpaZF.mjs} +7 -10
- package/dist/packem_shared/{REMOTE_ELIGIBLE_KEYS-BC7_e9Bz.mjs → REMOTE_ELIGIBLE_KEYS-C-F_Flgy.mjs} +1 -6
- package/dist/packem_shared/{REQUIRED_COMPATIBILITY_DATE-DRSNSOOp.mjs → REQUIRED_COMPATIBILITY_DATE-DP0SFVy9.mjs} +134 -3
- package/dist/packem_shared/{SCHEMA_EDIT_ENDPOINT-Df-Wrix-.mjs → SCHEMA_EDIT_ENDPOINT-Bt2SNkpV.mjs} +4 -8
- package/dist/packem_shared/{SEED_ENDPOINT-DVCjaGO-.mjs → SEED_ENDPOINT-7izz_Jao.mjs} +1 -1
- package/dist/packem_shared/WORKERS_CACHE_MIN_DATE-CaXbS7CX.mjs +11 -0
- package/dist/packem_shared/assetContentType-ByZjeV3D.mjs +72 -0
- package/dist/packem_shared/{buildPackageSecretsBlock-S74dgmwy.mjs → buildPackageSecretsBlock-BxOcyaAY.mjs} +115 -21
- package/dist/packem_shared/collectWranglerSecretVariables-BRWIvT-e.mjs +56 -0
- package/dist/packem_shared/{createConfirm-fvpdgJ9s.mjs → createConfirm-BMikeJC9.mjs} +22 -5
- package/dist/packem_shared/{detectFramework-Br-BcPBq.mjs → detectFramework-U08038Yp.mjs} +3 -3
- package/dist/packem_shared/discoverAgentInfo-eXA3hF4v.mjs +19 -0
- package/dist/packem_shared/{inferLunoraBindings-DIku9mTN.mjs → inferLunoraBindings-BcvvtpSG.mjs} +145 -50
- package/dist/packem_shared/jsonc-edit-SbcD7MAe.mjs +9 -0
- package/dist/packem_shared/parseDevVariable-B0FEvfHC.mjs +21 -0
- package/dist/packem_shared/{policy-scaffold.d-DCmwn7zQ.d.ts → policy-scaffold.d-CFd2FlqG.d.mts} +22 -22
- package/dist/packem_shared/{policy-scaffold.d-DCmwn7zQ.d.mts → policy-scaffold.d-CFd2FlqG.d.ts} +22 -22
- package/dist/packem_shared/{reconcileWranglerBindings-DTHmqTbL.mjs → reconcileWranglerBindings-2Cww5VLa.mjs} +114 -29
- package/dist/packem_shared/reconcileWranglerCompatibilityDate-C8c497ag.mjs +31 -0
- package/dist/packem_shared/reconcileWranglerCrons-DvsceVFz.mjs +29 -0
- package/dist/packem_shared/{serveJsonHandler-B4OLTGLS.mjs → serveJsonHandler-Cl2Wqkv8.mjs} +2 -2
- package/dist/packem_shared/streamContainerLogs-BZ4cOZwH.mjs +157 -0
- package/dist/packem_shared/write-atomic-B2REqapi.mjs +14 -0
- package/dist/studio-host/index.d.mts +134 -92
- package/dist/studio-host/index.d.ts +134 -92
- package/dist/studio-host/index.mjs +6 -6
- package/package.json +11 -8
- package/dist/packem_shared/PACKAGE_SECRETS_REGISTRY-CySy5vR_.mjs +0 -62
- package/dist/packem_shared/loadStudioAssets-Csk5RS4E.mjs +0 -28
- package/dist/packem_shared/parseDevVariable-CJiq2IwE.mjs +0 -30
package/dist/index.d.ts
CHANGED
|
@@ -1,42 +1,73 @@
|
|
|
1
|
-
import { ContainerIR, WorkflowIR } from '@lunora/codegen';
|
|
2
|
-
export type { ContainerIR, WorkflowIR } from '@lunora/codegen';
|
|
1
|
+
import { AgentIR, ContainerIR, WorkflowIR, QueueIR, WranglerVariableIR } from '@lunora/codegen';
|
|
2
|
+
export type { AgentIR, ContainerIR, WorkflowIR } from '@lunora/codegen';
|
|
3
|
+
import { Writable } from 'node:stream';
|
|
3
4
|
import 'ts-morph';
|
|
4
|
-
export { type A as AdditivePolicyEdit, type D as DestructivePolicyEdit, type P as PolicyEdit, type a as PolicyScaffoldFailureReason, type b as ScaffoldFileResult, type S as ScaffoldPolicyEdit, type c as WireResult, type W as WireRlsEdit, d as classifyPolicyEdit, s as scaffoldPolicyFile, w as wireRlsIntoProcedure } from "./packem_shared/policy-scaffold.d-
|
|
5
|
+
export { type A as AdditivePolicyEdit, type D as DestructivePolicyEdit, type P as PolicyEdit, type a as PolicyScaffoldFailureReason, type b as ScaffoldFileResult, type S as ScaffoldPolicyEdit, type c as WireResult, type W as WireRlsEdit, d as classifyPolicyEdit, s as scaffoldPolicyFile, w as wireRlsIntoProcedure } from "./packem_shared/policy-scaffold.d-CFd2FlqG.js";
|
|
6
|
+
/** Minimal env shape — `process.env` structurally, injectable for tests. */
|
|
7
|
+
type EnvLike = Readonly<Record<string, string | undefined>>;
|
|
8
|
+
/** One detected agent: which tool, and which env var gave it away. */
|
|
9
|
+
interface AgentDetection {
|
|
10
|
+
/** Human-readable agent name, for the "agent detected" log line. */
|
|
11
|
+
name: string;
|
|
12
|
+
/** The environment variable that matched. */
|
|
13
|
+
variable: string;
|
|
14
|
+
}
|
|
15
|
+
/** Env var that forces agent mode on (`1`/`true`) or off (`0`/`false`), overriding detection. */
|
|
16
|
+
declare const AGENT_MODE_ENV = "LUNORA_AGENT_MODE";
|
|
17
|
+
/**
|
|
18
|
+
* Detect the AI agent driving this process, or `undefined` when none is.
|
|
19
|
+
* `LUNORA_AGENT_MODE` wins over `@visulima/find-ai-runner`'s marker table in
|
|
20
|
+
* both directions. Pure — pass a custom `env` in tests.
|
|
21
|
+
*/
|
|
22
|
+
declare const detectAiAgent: (env?: EnvLike) => AgentDetection | undefined;
|
|
23
|
+
interface DiscoverAgentInfoResult {
|
|
24
|
+
/** Discovered agent definitions; `[]` when none are declared or parsing failed. */
|
|
25
|
+
agents: ReadonlyArray<AgentIR>;
|
|
26
|
+
/** Parse error message, when `lunora/agents.ts` exists but could not be analyzed. */
|
|
27
|
+
error?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Discover the project's `defineAgent` declarations. Returns `{ agents: [] }`
|
|
31
|
+
* when the project has no `lunora/agents.ts` (not an error), or
|
|
32
|
+
* `{ agents: [], error }` when the file exists but could not be parsed — callers
|
|
33
|
+
* decide whether that is a warning (validator) or ignorable (inference).
|
|
34
|
+
*/
|
|
35
|
+
declare const discoverAgentInfo: (projectRoot: string, schemaDirectory: string) => DiscoverAgentInfoResult;
|
|
5
36
|
/**
|
|
6
|
-
* Project-relative directory the Lunora agent skills ("rules") install into.
|
|
7
|
-
* This is the portable [Agent Skills](https://tanstack.com/intent/latest/docs/registry)
|
|
8
|
-
* location — Cursor, Claude Code, and GitHub Copilot all discover skills here.
|
|
9
|
-
*/
|
|
37
|
+
* Project-relative directory the Lunora agent skills ("rules") install into.
|
|
38
|
+
* This is the portable [Agent Skills](https://tanstack.com/intent/latest/docs/registry)
|
|
39
|
+
* location — Cursor, Claude Code, and GitHub Copilot all discover skills here.
|
|
40
|
+
*/
|
|
10
41
|
declare const AGENT_RULES_DIR = ".agents/skills";
|
|
11
42
|
/** Env var the once-per-process-tree hint guard ({@link claimAgentRulesHint}) sets. */
|
|
12
43
|
declare const AGENT_RULES_HINT_ENV = "LUNORA_RULES_HINT_SHOWN";
|
|
13
44
|
/**
|
|
14
|
-
* The Lunora agent skills shipped by `@lunora/cli`. The first entry (`lunora`)
|
|
15
|
-
* is the router skill — its presence is what {@link detectAgentRules} treats as
|
|
16
|
-
* "rules installed", since every other skill is reachable through it.
|
|
17
|
-
*/
|
|
45
|
+
* The Lunora agent skills shipped by `@lunora/cli`. The first entry (`lunora`)
|
|
46
|
+
* is the router skill — its presence is what {@link detectAgentRules} treats as
|
|
47
|
+
* "rules installed", since every other skill is reachable through it.
|
|
48
|
+
*/
|
|
18
49
|
declare const LUNORA_SKILL_NAMES: ReadonlyArray<string>;
|
|
19
50
|
/** The router skill whose presence marks the rule set as installed. */
|
|
20
51
|
declare const ROOT_SKILL_NAME = "lunora";
|
|
21
52
|
/**
|
|
22
|
-
* The single "rules not installed" message shared by every surface (the CLI
|
|
23
|
-
* `lunora dev` summary and the Vite dev plugin), so the wording and the
|
|
24
|
-
* pointer at `lunora rules install` stay identical wherever it appears.
|
|
25
|
-
*/
|
|
53
|
+
* The single "rules not installed" message shared by every surface (the CLI
|
|
54
|
+
* `lunora dev` summary and the Vite dev plugin), so the wording and the
|
|
55
|
+
* pointer at `lunora rules install` stay identical wherever it appears.
|
|
56
|
+
*/
|
|
26
57
|
declare const AGENT_RULES_HINT = "Lunora AI rules not installed — run `lunora rules install` so your coding agent knows how to use Lunora.";
|
|
27
58
|
/**
|
|
28
|
-
* Process-tree guard so the hint is emitted at most once. The first surface to
|
|
29
|
-
* print it sets {@link AGENT_RULES_HINT_ENV} on `process.env`; later surfaces (a
|
|
30
|
-
* Vite dev-server restart, or a child process that inherited the env) read it
|
|
31
|
-
* and stay quiet. Returns `true` the first time, `false` afterwards.
|
|
32
|
-
*/
|
|
59
|
+
* Process-tree guard so the hint is emitted at most once. The first surface to
|
|
60
|
+
* print it sets {@link AGENT_RULES_HINT_ENV} on `process.env`; later surfaces (a
|
|
61
|
+
* Vite dev-server restart, or a child process that inherited the env) read it
|
|
62
|
+
* and stay quiet. Returns `true` the first time, `false` afterwards.
|
|
63
|
+
*/
|
|
33
64
|
declare const claimAgentRulesHint: () => boolean;
|
|
34
65
|
interface AgentRulesStatus {
|
|
35
66
|
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
67
|
+
* True when the `lunora` router skill is installed. We key on the router
|
|
68
|
+
* (not "all nine present") so a project that intentionally trims the set
|
|
69
|
+
* still counts as installed and isn't nagged.
|
|
70
|
+
*/
|
|
40
71
|
readonly installed: boolean;
|
|
41
72
|
/** Skill names with no `SKILL.md` under `<root>/.agents/skills/<name>/`. */
|
|
42
73
|
readonly missing: ReadonlyArray<string>;
|
|
@@ -44,12 +75,12 @@ interface AgentRulesStatus {
|
|
|
44
75
|
readonly present: ReadonlyArray<string>;
|
|
45
76
|
}
|
|
46
77
|
/**
|
|
47
|
-
* Detect whether the Lunora agent skills are installed in `projectRoot` by
|
|
48
|
-
* checking the skills folder for each `SKILL.md`. Pure filesystem reads, safe to
|
|
49
|
-
* call on every dev-server / CLI startup — the CLI, the Vite plugin, and the
|
|
50
|
-
* studio host all use it to decide whether to surface the "rules not installed"
|
|
51
|
-
* hint.
|
|
52
|
-
*/
|
|
78
|
+
* Detect whether the Lunora agent skills are installed in `projectRoot` by
|
|
79
|
+
* checking the skills folder for each `SKILL.md`. Pure filesystem reads, safe to
|
|
80
|
+
* call on every dev-server / CLI startup — the CLI, the Vite plugin, and the
|
|
81
|
+
* studio host all use it to decide whether to surface the "rules not installed"
|
|
82
|
+
* hint.
|
|
83
|
+
*/
|
|
53
84
|
declare const detectAgentRules: (projectRoot: string) => AgentRulesStatus;
|
|
54
85
|
interface DiscoverContainerInfoResult {
|
|
55
86
|
/** Discovered container definitions; `[]` when none are declared or parsing failed. */
|
|
@@ -58,25 +89,96 @@ interface DiscoverContainerInfoResult {
|
|
|
58
89
|
error?: string;
|
|
59
90
|
}
|
|
60
91
|
/**
|
|
61
|
-
* Discover the project's `defineContainer` declarations. Returns
|
|
62
|
-
* `{ containers: [] }` when the project has no `lunora/containers.ts` (not an
|
|
63
|
-
* error), or `{ containers: [], error }` when the file exists but could not be
|
|
64
|
-
* parsed — callers decide whether that is a warning (validator) or ignorable
|
|
65
|
-
* (inference).
|
|
66
|
-
*/
|
|
92
|
+
* Discover the project's `defineContainer` declarations. Returns
|
|
93
|
+
* `{ containers: [] }` when the project has no `lunora/containers.ts` (not an
|
|
94
|
+
* error), or `{ containers: [], error }` when the file exists but could not be
|
|
95
|
+
* parsed — callers decide whether that is a warning (validator) or ignorable
|
|
96
|
+
* (inference).
|
|
97
|
+
*/
|
|
67
98
|
declare const discoverContainerInfo: (projectRoot: string, schemaDirectory: string) => DiscoverContainerInfoResult;
|
|
99
|
+
/** Severity a container output line is surfaced at: `stderr` → `error`, `stdout` → `info`. */
|
|
100
|
+
type ContainerLogLevel = "error" | "info";
|
|
101
|
+
/** One declared container to follow, identified by the names codegen lifts from `defineContainer`. */
|
|
102
|
+
interface ContainerLogSource {
|
|
103
|
+
/** Generated Durable Object class name, e.g. `TranscoderContainer`. Wrangler's dev image is `cloudflare-dev/<lowercased>`. */
|
|
104
|
+
className: string;
|
|
105
|
+
/** The `lunora/containers.ts` export name, e.g. `transcoder` — used as the display tag. */
|
|
106
|
+
exportName: string;
|
|
107
|
+
}
|
|
108
|
+
/** A single line of container output handed back to the caller. */
|
|
109
|
+
interface ContainerLogLine {
|
|
110
|
+
/** `"error"` for the container's stderr, `"info"` for its stdout. */
|
|
111
|
+
level: ContainerLogLevel;
|
|
112
|
+
/** The container's export name (`transcoder`), for tagging the line. */
|
|
113
|
+
name: string;
|
|
114
|
+
/** One output line, with the trailing newline (and any `\r`) stripped. */
|
|
115
|
+
text: string;
|
|
116
|
+
}
|
|
117
|
+
interface ContainerLogStreamOptions {
|
|
118
|
+
/** The declared containers to follow. An empty list yields an inert handle. */
|
|
119
|
+
containers: ReadonlyArray<ContainerLogSource>;
|
|
120
|
+
/** Injected Docker client — defaults to a real lazily-imported `dockerode` instance. Tests pass a stub. */
|
|
121
|
+
docker?: DockerLike;
|
|
122
|
+
/** Called once per container output line. */
|
|
123
|
+
onLine: (line: ContainerLogLine) => void;
|
|
124
|
+
/** Called once when the Docker engine can't be reached (re-armed after it recovers). Defaults to silent. */
|
|
125
|
+
onUnavailable?: (message: string) => void;
|
|
126
|
+
/** Poll interval override, in ms. */
|
|
127
|
+
pollIntervalMs?: number;
|
|
128
|
+
}
|
|
129
|
+
/** Handle controlling a running log stream. */
|
|
130
|
+
interface ContainerLogStreamHandle {
|
|
131
|
+
/** Stop polling and tear down every attached log stream. Idempotent. */
|
|
132
|
+
close: () => void;
|
|
133
|
+
}
|
|
134
|
+
/** The minimal structural slice of a `dockerode` log stream this module consumes. */
|
|
135
|
+
interface DockerLogStream {
|
|
136
|
+
destroy: () => void;
|
|
137
|
+
on: (event: "data" | "end" | "error", listener: (chunk?: Buffer) => void) => void;
|
|
138
|
+
}
|
|
139
|
+
/** The minimal structural slice of a `dockerode` instance this module consumes. */
|
|
140
|
+
interface DockerLike {
|
|
141
|
+
getContainer: (id: string) => {
|
|
142
|
+
logs: (options: {
|
|
143
|
+
follow: true;
|
|
144
|
+
stderr: true;
|
|
145
|
+
stdout: true;
|
|
146
|
+
tail: "all";
|
|
147
|
+
timestamps: false;
|
|
148
|
+
}) => Promise<DockerLogStream>;
|
|
149
|
+
};
|
|
150
|
+
listContainers: (options: {
|
|
151
|
+
filters: {
|
|
152
|
+
status: ["running"];
|
|
153
|
+
};
|
|
154
|
+
}) => Promise<{
|
|
155
|
+
Id: string;
|
|
156
|
+
Image: string;
|
|
157
|
+
}[]>;
|
|
158
|
+
modem: {
|
|
159
|
+
demuxStream: (stream: DockerLogStream, stdout: Writable, stderr: Writable) => void;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
68
162
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
|
|
163
|
+
* Follow the local Docker logs of every declared container, emitting each output
|
|
164
|
+
* line through `onLine` tagged with its export name. Polls for containers (they
|
|
165
|
+
* start lazily on first request and may be replaced on restart), attaches once
|
|
166
|
+
* per container id, and drops streams whose container has gone. Returns
|
|
167
|
+
* immediately with a `close()` handle; all work happens asynchronously.
|
|
168
|
+
*/
|
|
169
|
+
declare const streamContainerLogs: (options: ContainerLogStreamOptions) => ContainerLogStreamHandle;
|
|
170
|
+
/**
|
|
171
|
+
* The meta-frameworks Lunora can compose with, plus `"none"` for a standalone
|
|
172
|
+
* SPA / SSR-less project (the current default). Mirrors PLAN4 §2.4.
|
|
173
|
+
*/
|
|
72
174
|
type DetectedFramework = "astro" | "none" | "nuxt" | "react-router" | "solid-start" | "sveltekit" | "tanstack-start" | "tanstack-start-solid";
|
|
73
175
|
/**
|
|
74
|
-
* void's class model (PLAN4 §3). Class A is Vite-native and Lunora owns the
|
|
75
|
-
* worker entry (`createWorker({ httpRouter })`). Class B frameworks own their own
|
|
76
|
-
* Cloudflare adapter, so Lunora injects its worker composition into the
|
|
77
|
-
* framework's server entry via hooks (PLAN4 M4). Class C is non-CF / SSR-less —
|
|
78
|
-
* ship the client adapter + a standalone Lunora worker (today's default).
|
|
79
|
-
*/
|
|
176
|
+
* void's class model (PLAN4 §3). Class A is Vite-native and Lunora owns the
|
|
177
|
+
* worker entry (`createWorker({ httpRouter })`). Class B frameworks own their own
|
|
178
|
+
* Cloudflare adapter, so Lunora injects its worker composition into the
|
|
179
|
+
* framework's server entry via hooks (PLAN4 M4). Class C is non-CF / SSR-less —
|
|
180
|
+
* ship the client adapter + a standalone Lunora worker (today's default).
|
|
181
|
+
*/
|
|
80
182
|
type FrameworkClass = "A" | "B" | "C";
|
|
81
183
|
interface FrameworkDetection {
|
|
82
184
|
/** void's composition class for the detected framework. */
|
|
@@ -85,36 +187,147 @@ interface FrameworkDetection {
|
|
|
85
187
|
framework: DetectedFramework;
|
|
86
188
|
}
|
|
87
189
|
/**
|
|
88
|
-
*
|
|
89
|
-
* dependencies
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
190
|
+
* Read and parse the project `package.json`, returning its merged
|
|
191
|
+
* `dependencies` + `devDependencies` name set (empty on any failure). Public
|
|
192
|
+
* so sibling consumers (e.g. the CLI's Vite-project detection) share one
|
|
193
|
+
* best-effort reader instead of re-parsing `package.json` themselves.
|
|
194
|
+
*/
|
|
195
|
+
declare const readProjectDependencyNames: (root: string) => ReadonlySet<string>;
|
|
196
|
+
/**
|
|
197
|
+
* Detect which meta-framework a project uses by inspecting its `package.json`
|
|
198
|
+
* dependencies, and classify it under void's class-A/B/C model (PLAN4 §3).
|
|
199
|
+
*
|
|
200
|
+
* Pure and best-effort: never throws. An unknown / missing / malformed
|
|
201
|
+
* `package.json` yields `{ framework: "none", class: "C" }` so the standalone
|
|
202
|
+
* SPA flow is preserved.
|
|
203
|
+
*/
|
|
95
204
|
declare const detectFramework: (root: string) => FrameworkDetection;
|
|
205
|
+
/** Directory holding per-checkout Lunora state (gitignored by convention). */
|
|
206
|
+
declare const DEV_STATE_DIR = ".lunora";
|
|
207
|
+
/** The dev-server state filename, relative to the project root. */
|
|
208
|
+
declare const DEV_STATE_FILE: string;
|
|
209
|
+
/** Log file a backgrounded dev server's output is captured to, relative to the project root. */
|
|
210
|
+
declare const DEV_LOG_FILE: string;
|
|
96
211
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
*/
|
|
212
|
+
* Marker env `lunora dev --background` sets on the detached server process
|
|
213
|
+
* (the daemon `lunora dev` or `vite dev`), so it records itself as
|
|
214
|
+
* `background: true` — and, for the CLI daemon, never re-detects an agent and
|
|
215
|
+
* recurses into background mode again.
|
|
216
|
+
*/
|
|
217
|
+
declare const DEV_DAEMON_ENV = "LUNORA_DEV_DAEMON";
|
|
218
|
+
/** Env carrying the capture-log path into the detached server, recorded in the state file. */
|
|
219
|
+
declare const DEV_LOG_FILE_ENV = "LUNORA_DEV_LOG_FILE";
|
|
220
|
+
/**
|
|
221
|
+
* Env carrying the PID of a parent that holds a *provisional* state record it
|
|
222
|
+
* expects the child dev server to supersede. The CLI claims `.lunora/dev.json`
|
|
223
|
+
* with its own PID before spawning the real server (closing the duplicate-start
|
|
224
|
+
* race for the vite flavor and the wrangler daemon), then hands its PID down
|
|
225
|
+
* via this variable; the child's claim (see {@link claimDevServerState}'s
|
|
226
|
+
* `supersedePid`) may replace exactly that record with the authoritative
|
|
227
|
+
* URL + PID.
|
|
228
|
+
*/
|
|
229
|
+
declare const DEV_HANDOFF_ENV = "LUNORA_DEV_HANDOFF_PID";
|
|
230
|
+
/** How the recorded dev server runs. */
|
|
231
|
+
type DevServerMode = "cli" | "vite";
|
|
232
|
+
/** The state record persisted to `.lunora/dev.json`. */
|
|
233
|
+
interface DevServerState {
|
|
234
|
+
/** Whether the server was detached into the background (`lunora dev --background`). */
|
|
235
|
+
background?: boolean;
|
|
236
|
+
/** Absolute path of the log file capturing the server's output, when captured. */
|
|
237
|
+
logFile?: string;
|
|
238
|
+
/** `"cli"` for the `lunora dev` wrangler orchestration, `"vite"` for a Vite dev server. */
|
|
239
|
+
mode: DevServerMode;
|
|
240
|
+
/** PID of the process to signal for shutdown (the orchestrating CLI or the Vite process). */
|
|
241
|
+
pid: number;
|
|
242
|
+
/** ISO-8601 stamp written at startup, purely informational (drives `status` uptime). */
|
|
243
|
+
startedAt?: string;
|
|
244
|
+
/** The embedded studio server's URL, when it runs. */
|
|
245
|
+
studioUrl?: string;
|
|
246
|
+
/** The primary URL serving the worker/app. */
|
|
247
|
+
url: string;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* True when a process with `pid` is currently alive AND signalable by this
|
|
251
|
+
* user. Signal `0` performs the existence check without delivering anything.
|
|
252
|
+
*
|
|
253
|
+
* `EPERM` ("alive but another user's process") deliberately counts as NOT
|
|
254
|
+
* alive here: every dev server this module tracks was spawned by the current
|
|
255
|
+
* user, so a PID we cannot signal is by definition a recycled PID — treating
|
|
256
|
+
* it as running would wedge the lockfile permanently and aim `dev stop`'s
|
|
257
|
+
* kill escalation at an innocent process.
|
|
258
|
+
*/
|
|
259
|
+
declare const isProcessAlive: (pid: number) => boolean;
|
|
260
|
+
/**
|
|
261
|
+
* True when the record's PID verifiably still refers to the dev server that
|
|
262
|
+
* wrote the record — not merely "some process exists with that number".
|
|
263
|
+
* Guards against PID reuse: a server process necessarily starts BEFORE its
|
|
264
|
+
* record is written, so a process that started after `startedAt` (+ skew) is
|
|
265
|
+
* a recycled PID wearing the corpse's number. The start-time check runs only
|
|
266
|
+
* where the platform exposes it (Linux); elsewhere liveness alone decides.
|
|
267
|
+
*/
|
|
268
|
+
declare const isRecordedProcessCurrent: (state: DevServerState) => boolean;
|
|
269
|
+
/**
|
|
270
|
+
* Read the state record from `.lunora/dev.json`, or `undefined` when there is
|
|
271
|
+
* no usable record. Best-effort; performs NO liveness check — use
|
|
272
|
+
* {@link readLiveDevServerState} for "is a dev server actually running".
|
|
273
|
+
*/
|
|
274
|
+
declare const readDevServerState: (projectRoot: string) => DevServerState | undefined;
|
|
275
|
+
/**
|
|
276
|
+
* Write the state record to `.lunora/dev.json`, creating the `.lunora/`
|
|
277
|
+
* directory when absent. Returns the absolute path written, or `undefined`
|
|
278
|
+
* when the write failed (state is convenience metadata — a read-only checkout
|
|
279
|
+
* must never crash dev startup).
|
|
280
|
+
*/
|
|
281
|
+
declare const writeDevServerState: (projectRoot: string, state: DevServerState) => string | undefined;
|
|
282
|
+
/**
|
|
283
|
+
* Merge `patch` into the existing state record, when one exists. Used by the
|
|
284
|
+
* CLI to stamp `background`/`logFile` onto the record the Vite plugin wrote.
|
|
285
|
+
* Returns the merged record, or `undefined` when there was nothing to update.
|
|
286
|
+
*/
|
|
287
|
+
declare const updateDevServerState: (projectRoot: string, patch: Partial<DevServerState>) => DevServerState | undefined;
|
|
288
|
+
/**
|
|
289
|
+
* Remove `.lunora/dev.json`. Idempotent and never throws. When `expectedPid`
|
|
290
|
+
* is given, the file is only removed while it still records that PID — so a
|
|
291
|
+
* shutting-down server can't clobber the record a newer server just wrote.
|
|
292
|
+
*/
|
|
293
|
+
declare const clearDevServerState: (projectRoot: string, expectedPid?: number) => void;
|
|
294
|
+
/**
|
|
295
|
+
* The state record of a dev server that is verifiably running right now, or
|
|
296
|
+
* `undefined`. A record whose PID is dead — or recycled onto a different
|
|
297
|
+
* process (see {@link isRecordedProcessCurrent}) — is stale: it is cleared on
|
|
298
|
+
* the spot so subsequent starts don't keep re-reading a corpse.
|
|
299
|
+
*/
|
|
300
|
+
declare const readLiveDevServerState: (projectRoot: string) => DevServerState | undefined;
|
|
301
|
+
/** Result of {@link claimDevServerState}: claimed, or lost to the live server already recorded. */
|
|
302
|
+
interface ClaimDevServerStateResult {
|
|
303
|
+
/** The live record that won the race, when `ok` is `false`. */
|
|
304
|
+
existing?: DevServerState;
|
|
305
|
+
/** Whether this process now owns the record. */
|
|
306
|
+
ok: boolean;
|
|
307
|
+
}
|
|
308
|
+
declare const claimDevServerState: (projectRoot: string, state: DevServerState, options?: {
|
|
309
|
+
supersedePid?: number;
|
|
310
|
+
}) => ClaimDevServerStateResult;
|
|
311
|
+
/**
|
|
312
|
+
* The `.dev.vars` line grammar — one owner, shared by every reader/writer of the
|
|
313
|
+
* file so the format can't drift between packages. `@lunora/cli`'s `env`
|
|
314
|
+
* command (parse/serialize) and `@lunora/config`'s scaffolder (comment-
|
|
315
|
+
* preserving rewrite) do different *transforms*, but they agree on these
|
|
316
|
+
* primitives: the filename, what a `KEY` looks like, how lines split, and how
|
|
317
|
+
* quotes strip.
|
|
318
|
+
*/
|
|
104
319
|
/** The conventional filename for local Cloudflare dev secrets (gitignored). */
|
|
105
320
|
declare const DEV_VARS_FILE: string;
|
|
106
321
|
/** Its committed, secret-free counterpart that scaffolding reads from. */
|
|
107
322
|
declare const DEV_VARS_EXAMPLE_FILE: string;
|
|
108
323
|
/** A bare `KEY` identifier — the part left of `=` in a `.dev.vars` line. */
|
|
109
324
|
declare const DEV_VARS_KEY_PATTERN: RegExp;
|
|
110
|
-
/**
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
|
|
116
|
-
* comment-preserving rewrite) use this instead of hand-rolling the split loop.
|
|
117
|
-
*/
|
|
325
|
+
/**
|
|
326
|
+
* Parse `.dev.vars` content into its `{ key, value }` entries, in file order,
|
|
327
|
+
* with values unquoted and comments/blank/invalid lines dropped. The canonical
|
|
328
|
+
* read of the whole file — callers that just want the variables (rather than a
|
|
329
|
+
* comment-preserving rewrite) use this instead of hand-rolling the split loop.
|
|
330
|
+
*/
|
|
118
331
|
declare const parseDevVariableEntries: (content: string) => {
|
|
119
332
|
key: string;
|
|
120
333
|
value: string;
|
|
@@ -126,69 +339,104 @@ interface DiscoverWorkflowInfoResult {
|
|
|
126
339
|
workflows: ReadonlyArray<WorkflowIR>;
|
|
127
340
|
}
|
|
128
341
|
/**
|
|
129
|
-
* Discover the project's `defineWorkflow` declarations. Returns
|
|
130
|
-
* `{ workflows: [] }` when the project has no `lunora/workflows.ts` (not an
|
|
131
|
-
* error), or `{ workflows: [], error }` when the file exists but could not be
|
|
132
|
-
* parsed — callers decide whether that is a warning (validator) or ignorable
|
|
133
|
-
* (inference).
|
|
134
|
-
*/
|
|
342
|
+
* Discover the project's `defineWorkflow` declarations. Returns
|
|
343
|
+
* `{ workflows: [] }` when the project has no `lunora/workflows.ts` (not an
|
|
344
|
+
* error), or `{ workflows: [], error }` when the file exists but could not be
|
|
345
|
+
* parsed — callers decide whether that is a warning (validator) or ignorable
|
|
346
|
+
* (inference).
|
|
347
|
+
*/
|
|
135
348
|
declare const discoverWorkflowInfo: (projectRoot: string, schemaDirectory: string) => DiscoverWorkflowInfoResult;
|
|
136
349
|
interface DurableObjectSpec {
|
|
137
350
|
binding: string;
|
|
138
351
|
className: string;
|
|
139
352
|
}
|
|
140
353
|
/**
|
|
141
|
-
* A `defineContainer` declaration plus whether its generated DO class is
|
|
142
|
-
* exported by the worker entry. Only exported containers are safe to
|
|
143
|
-
* provision — wrangler rejects a `containers[].class_name` (and its Durable
|
|
144
|
-
* Object binding) that the worker doesn't export.
|
|
145
|
-
*/
|
|
354
|
+
* A `defineContainer` declaration plus whether its generated DO class is
|
|
355
|
+
* exported by the worker entry. Only exported containers are safe to
|
|
356
|
+
* provision — wrangler rejects a `containers[].class_name` (and its Durable
|
|
357
|
+
* Object binding) that the worker doesn't export.
|
|
358
|
+
*/
|
|
146
359
|
interface InferredContainer extends ContainerIR {
|
|
147
360
|
exported: boolean;
|
|
148
361
|
}
|
|
149
362
|
/**
|
|
150
|
-
* A `defineWorkflow` declaration plus whether its generated
|
|
151
|
-
* `WorkflowEntrypoint` class is exported by the worker entry. Only exported
|
|
152
|
-
* workflows are safe to provision — wrangler rejects a `workflows[].class_name`
|
|
153
|
-
* the worker doesn't export. Workflows are NOT Durable Objects, so this never
|
|
154
|
-
* implies a `durable_objects` binding or migration.
|
|
155
|
-
*/
|
|
363
|
+
* A `defineWorkflow` declaration plus whether its generated
|
|
364
|
+
* `WorkflowEntrypoint` class is exported by the worker entry. Only exported
|
|
365
|
+
* workflows are safe to provision — wrangler rejects a `workflows[].class_name`
|
|
366
|
+
* the worker doesn't export. Workflows are NOT Durable Objects, so this never
|
|
367
|
+
* implies a `durable_objects` binding or migration.
|
|
368
|
+
*/
|
|
156
369
|
interface InferredWorkflow extends WorkflowIR {
|
|
157
370
|
exported: boolean;
|
|
158
371
|
}
|
|
372
|
+
/**
|
|
373
|
+
* A `defineAgent` declaration plus whether its generated agent
|
|
374
|
+
* `WorkflowEntrypoint` class (e.g. `SupportAgentWorkflow`) is exported by the
|
|
375
|
+
* worker entry. An agent compiles onto a Cloudflare Workflow, so — exactly like
|
|
376
|
+
* {@link InferredWorkflow} — only exported agents are safe to provision
|
|
377
|
+
* (wrangler rejects a `workflows[].class_name` the worker doesn't export), and
|
|
378
|
+
* an agent is NOT a Durable Object (no `durable_objects` binding or migration).
|
|
379
|
+
*/
|
|
380
|
+
interface InferredAgent extends AgentIR {
|
|
381
|
+
exported: boolean;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* A queue declared in `lunora/queues.ts`. Unlike workflows, a queue needs no
|
|
385
|
+
* worker-entry class export (its `queue()` handler rides `createWorker`), so
|
|
386
|
+
* there is no `exported` flag — every declared queue is reconcilable into the
|
|
387
|
+
* wrangler `queues.producers[]` / `queues.consumers[]`.
|
|
388
|
+
*/
|
|
389
|
+
type InferredQueue = QueueIR;
|
|
159
390
|
interface InferredBindings {
|
|
391
|
+
/** Agents declared in `lunora/agents.ts` (exported or not — see {@link InferredAgent.exported}); reconciled into `workflows[]`. */
|
|
392
|
+
agents: InferredAgent[];
|
|
160
393
|
/** Containers declared in `lunora/containers.ts` (exported or not — see {@link InferredContainer.exported}). */
|
|
161
394
|
containers: InferredContainer[];
|
|
162
395
|
/** Durable Objects the worker entry exports → safe to bind. */
|
|
163
396
|
durableObjects: DurableObjectSpec[];
|
|
397
|
+
/**
|
|
398
|
+
* The wrangler `flagship[].binding` name implied by `lunora/flags.ts` when it
|
|
399
|
+
* uses the Flagship provider in binding mode — `undefined` for HTTP-mode
|
|
400
|
+
* Flagship, a custom OpenFeature provider, or no flags. The binding needs an
|
|
401
|
+
* un-mintable `app_id`, so it is reconciled as a hint, not auto-written.
|
|
402
|
+
*/
|
|
403
|
+
flagshipBinding?: string;
|
|
164
404
|
/** Schema declares a `.global()` table → needs the `DB` D1 binding. */
|
|
165
405
|
needsD1: boolean;
|
|
406
|
+
/** Queues declared in `lunora/queues.ts` → reconciled into `queues.producers[]` / `queues.consumers[]`. */
|
|
407
|
+
queues: InferredQueue[];
|
|
166
408
|
/** Human-readable provenance for each inferred binding / hint, for logging. */
|
|
167
409
|
signals: string[];
|
|
168
410
|
/** `@lunora/ai` is imported or `env.AI` is used → needs the `ai` Workers AI binding. */
|
|
169
411
|
usesAi: boolean;
|
|
170
|
-
/** `@lunora/analytics` is imported → self-describing `analytics_engine_datasets` binding (auto-writeable). */
|
|
412
|
+
/** `@lunora/bindings/analytics` is imported → self-describing `analytics_engine_datasets` binding (auto-writeable). */
|
|
171
413
|
usesAnalytics: boolean;
|
|
172
414
|
/** `@lunora/auth` is imported (sessions may be D1- or `SessionDO`-backed). */
|
|
173
415
|
usesAuth: boolean;
|
|
174
416
|
/** `@lunora/browser` is imported → self-describing `browser` binding (auto-writeable). */
|
|
175
417
|
usesBrowser: boolean;
|
|
418
|
+
/** `lunora/flags.ts` declares a feature-flag provider (any OpenFeature provider — Flagship or custom). */
|
|
419
|
+
usesFlags: boolean;
|
|
176
420
|
/** `@lunora/hyperdrive` is imported (binding needs an un-mintable remote `id`; hint-only). */
|
|
177
421
|
usesHyperdrive: boolean;
|
|
178
|
-
/** `@lunora/images` is imported → self-describing `images` binding (auto-writeable). */
|
|
422
|
+
/** `@lunora/bindings/images` is imported → self-describing `images` binding (auto-writeable). */
|
|
179
423
|
usesImages: boolean;
|
|
180
|
-
/** `@lunora/kv` is imported (namespace binding name + id are user-defined; hint-only). */
|
|
424
|
+
/** `@lunora/bindings/kv` is imported (namespace binding name + id are user-defined; hint-only). */
|
|
181
425
|
usesKv: boolean;
|
|
182
426
|
/** `@lunora/mail` is imported (Resend API key must be set in `.dev.vars`; no binding). */
|
|
183
427
|
usesMail: boolean;
|
|
184
428
|
/** `@lunora/payment` is imported (provider secrets must be set in `.dev.vars`; no binding). */
|
|
185
429
|
usesPayment: boolean;
|
|
186
|
-
/**
|
|
430
|
+
/** `ctx.pipelines` is used (binding needs an un-mintable remote pipeline name; hint-only). */
|
|
187
431
|
usesPipelines: boolean;
|
|
188
432
|
/** `@lunora/scheduler` is imported. */
|
|
189
433
|
usesScheduler: boolean;
|
|
190
434
|
/** `@lunora/storage` is imported (R2 bucket binding name is user-defined). */
|
|
191
435
|
usesStorage: boolean;
|
|
436
|
+
/** `@lunora/x402/charge` is imported — the charge rail settles USDC to a recipient address (a public `[vars]` entry, user-named; hint-only). */
|
|
437
|
+
usesX402Charge: boolean;
|
|
438
|
+
/** `@lunora/x402/pay` is imported — the agent-wallet pay rail signs from a Secrets Store binding paired with a spend policy (ActionCtx-only; hint-only). */
|
|
439
|
+
usesX402Pay: boolean;
|
|
192
440
|
/** Workflows declared in `lunora/workflows.ts` (exported or not — see {@link InferredWorkflow.exported}). */
|
|
193
441
|
workflows: InferredWorkflow[];
|
|
194
442
|
}
|
|
@@ -200,33 +448,33 @@ interface InferOptions {
|
|
|
200
448
|
schemaDir?: string;
|
|
201
449
|
}
|
|
202
450
|
/**
|
|
203
|
-
* Scan a Lunora project and report which Cloudflare bindings its code implies.
|
|
204
|
-
* Read-only: performs no writes. Binding provisioning is driven by the worker
|
|
205
|
-
* entry's Durable Object exports plus the schema's D1 need; capability imports
|
|
206
|
-
* surface as hints.
|
|
207
|
-
*/
|
|
451
|
+
* Scan a Lunora project and report which Cloudflare bindings its code implies.
|
|
452
|
+
* Read-only: performs no writes. Binding provisioning is driven by the worker
|
|
453
|
+
* entry's Durable Object exports plus the schema's D1 need; capability imports
|
|
454
|
+
* surface as hints.
|
|
455
|
+
*/
|
|
208
456
|
declare const inferLunoraBindings: (options: InferOptions) => Promise<InferredBindings>;
|
|
209
457
|
/**
|
|
210
|
-
* Derive the list of `@lunora/*` package names that are actively used by a
|
|
211
|
-
* project, based on its already-resolved {@link InferredBindings}.
|
|
212
|
-
*
|
|
213
|
-
* This is the canonical bridge between binding inference and the package-aware
|
|
214
|
-
* `.dev.vars.example` scaffolding in `scaffold-dev-variables.ts`. The result is
|
|
215
|
-
* a stable, predictable slice of {@link CAPABILITY_SOURCES} source values,
|
|
216
|
-
* filtered to the flags that are `true` in `bindings` — in CAPABILITY_SOURCES
|
|
217
|
-
* declaration order.
|
|
218
|
-
*/
|
|
458
|
+
* Derive the list of `@lunora/*` package names that are actively used by a
|
|
459
|
+
* project, based on its already-resolved {@link InferredBindings}.
|
|
460
|
+
*
|
|
461
|
+
* This is the canonical bridge between binding inference and the package-aware
|
|
462
|
+
* `.dev.vars.example` scaffolding in `scaffold-dev-variables.ts`. The result is
|
|
463
|
+
* a stable, predictable slice of {@link CAPABILITY_SOURCES} source values,
|
|
464
|
+
* filtered to the flags that are `true` in `bindings` — in CAPABILITY_SOURCES
|
|
465
|
+
* declaration order.
|
|
466
|
+
*/
|
|
219
467
|
declare const packageNamesFromBindings: (bindings: InferredBindings) => string[];
|
|
220
468
|
/** Directory holding per-checkout Lunora state (gitignored by convention). */
|
|
221
469
|
declare const LINKED_PROJECT_DIR = ".lunora";
|
|
222
470
|
/** The canonical link filename, relative to the project root. */
|
|
223
471
|
declare const LINKED_PROJECT_FILE: string;
|
|
224
472
|
/**
|
|
225
|
-
* The link record persisted to `.lunora/project.json`. Every field is optional
|
|
226
|
-
* so a partially-populated link (e.g. a worker name with no URL yet) still
|
|
227
|
-
* round-trips. `linkedAt` is an ISO-8601 stamp written at link time, purely
|
|
228
|
-
* informational.
|
|
229
|
-
*/
|
|
473
|
+
* The link record persisted to `.lunora/project.json`. Every field is optional
|
|
474
|
+
* so a partially-populated link (e.g. a worker name with no URL yet) still
|
|
475
|
+
* round-trips. `linkedAt` is an ISO-8601 stamp written at link time, purely
|
|
476
|
+
* informational.
|
|
477
|
+
*/
|
|
230
478
|
interface LinkedProject {
|
|
231
479
|
/** Cloudflare account id the worker lives under, when known. */
|
|
232
480
|
account?: string;
|
|
@@ -240,34 +488,17 @@ interface LinkedProject {
|
|
|
240
488
|
workerUrl?: string;
|
|
241
489
|
}
|
|
242
490
|
/**
|
|
243
|
-
* Read the link record from `.lunora/project.json`, or `undefined` when there
|
|
244
|
-
* is no usable link. Best-effort: a missing file, parse error, or unexpected
|
|
245
|
-
* shape all collapse to `undefined`.
|
|
246
|
-
*/
|
|
491
|
+
* Read the link record from `.lunora/project.json`, or `undefined` when there
|
|
492
|
+
* is no usable link. Best-effort: a missing file, parse error, or unexpected
|
|
493
|
+
* shape all collapse to `undefined`.
|
|
494
|
+
*/
|
|
247
495
|
declare const readLinkedProject: (projectRoot: string) => LinkedProject | undefined;
|
|
248
496
|
/**
|
|
249
|
-
* Write the link record to `.lunora/project.json`, creating the `.lunora/`
|
|
250
|
-
* directory when absent. Only defined fields are persisted (so an empty value
|
|
251
|
-
* never clobbers a known one). Returns the absolute path written.
|
|
252
|
-
*/
|
|
497
|
+
* Write the link record to `.lunora/project.json`, creating the `.lunora/`
|
|
498
|
+
* directory when absent. Only defined fields are persisted (so an empty value
|
|
499
|
+
* never clobbers a known one). Returns the absolute path written.
|
|
500
|
+
*/
|
|
253
501
|
declare const writeLinkedProject: (projectRoot: string, link: LinkedProject) => string;
|
|
254
|
-
/**
|
|
255
|
-
* Shared formatter for the structured log events the Lunora runtime emits to the
|
|
256
|
-
* worker's `console` during development. Both the CLI `dev` command and the Vite
|
|
257
|
-
* plugin pipe worker output through `formatLunoraEvent` so a developer sees
|
|
258
|
-
* attributed, readable lines instead of raw JSON.
|
|
259
|
-
*
|
|
260
|
-
* The runtime emits two event shapes, each a single `console` line tagged
|
|
261
|
-
* `source: "lunora"` (see `@lunora/do`'s `request-log.ts`): a `type: "log"`
|
|
262
|
-
* event per `ctx.log.*` call, and a `type: "request"` event per RPC dispatch
|
|
263
|
-
* (opt-in for successful calls, always for errors).
|
|
264
|
-
*
|
|
265
|
-
* This module is intentionally dependency-free and colour-free: it returns the
|
|
266
|
-
* severity plus a plain display string, leaving ANSI/level colouring to each
|
|
267
|
-
* caller (the CLI routes through its `pail` logger; the Vite plugin dims inline).
|
|
268
|
-
* Any line that is not a lunora event returns `undefined`, signalling the caller
|
|
269
|
-
* to pass it through unchanged.
|
|
270
|
-
*/
|
|
271
502
|
/** Severity a formatted line should be surfaced at, mapped onto the three logger channels. */
|
|
272
503
|
type LunoraLineLevel = "error" | "info" | "warn";
|
|
273
504
|
/** A formatted lunora event: the channel to surface it on, the display text, and which event produced it. */
|
|
@@ -282,11 +513,11 @@ interface LunoraFormattedLine {
|
|
|
282
513
|
/** Stable `source` tag every lunora console event carries. Mirrors `REQUEST_LOG_EVENT_SOURCE` in `@lunora/do`. */
|
|
283
514
|
declare const LUNORA_EVENT_SOURCE = "lunora";
|
|
284
515
|
/**
|
|
285
|
-
* Parse a single worker-output line and, when it is a lunora structured event,
|
|
286
|
-
* return its severity plus display text. Returns `undefined` for anything else —
|
|
287
|
-
* non-JSON lines, JSON that isn't a lunora event, or an unrecognised event type
|
|
288
|
-
* — so the caller passes the original line through untouched. Pure and total.
|
|
289
|
-
*/
|
|
516
|
+
* Parse a single worker-output line and, when it is a lunora structured event,
|
|
517
|
+
* return its severity plus display text. Returns `undefined` for anything else —
|
|
518
|
+
* non-JSON lines, JSON that isn't a lunora event, or an unrecognised event type
|
|
519
|
+
* — so the caller passes the original line through untouched. Pure and total.
|
|
520
|
+
*/
|
|
290
521
|
declare const formatLunoraEvent: (line: string) => LunoraFormattedLine | undefined;
|
|
291
522
|
declare class LunoraReporter {
|
|
292
523
|
#private;
|
|
@@ -295,32 +526,32 @@ declare class LunoraReporter {
|
|
|
295
526
|
log(meta: unknown): void;
|
|
296
527
|
}
|
|
297
528
|
/**
|
|
298
|
-
* Per-package secret-requirements registry for `.dev.vars` scaffolding.
|
|
299
|
-
*
|
|
300
|
-
* Each entry maps a `@lunora/*` package name → the secrets it requires at
|
|
301
|
-
* runtime, expressed as `{ key, description, docsUrl }` records. The scaffolder
|
|
302
|
-
* in {@link ./scaffold-dev-variables} reads this registry to emit package-aware
|
|
303
|
-
* `.dev.vars.example` entries (placeholders + inline doc-pointer comments).
|
|
304
|
-
*
|
|
305
|
-
* ## Adding a new add-on
|
|
306
|
-
*
|
|
307
|
-
* When a new `@lunora/*` package requires runtime secrets, add one entry to
|
|
308
|
-
* {@link PACKAGE_SECRETS_REGISTRY} keyed by its exact npm package name. Each
|
|
309
|
-
* `SecretEntry` in the array needs:
|
|
310
|
-
*
|
|
311
|
-
* - `key` — the env-var name the package reads from `env` (e.g. `RESEND_API_KEY`).
|
|
312
|
-
* - `description` — one line describing the secret and how to obtain it.
|
|
313
|
-
* - `docsUrl` — a stable URL to the package/provider docs.
|
|
314
|
-
*
|
|
315
|
-
* The registry lives in `@lunora/config` so that add-ons themselves never need
|
|
316
|
-
* to depend on it (no circular coupling). Add-ons document their secrets in
|
|
317
|
-
* their own READMEs; the registry duplicates that knowledge in a machine-readable
|
|
318
|
-
* form that the scaffolder can consume.
|
|
319
|
-
*
|
|
320
|
-
* **Never write a real secret value** in this file — `placeholderValue` entries
|
|
321
|
-
* are the only allowed values (they must pass `isPlaceholderValue` from
|
|
322
|
-
* scaffold-dev-variables).
|
|
323
|
-
*/
|
|
529
|
+
* Per-package secret-requirements registry for `.dev.vars` scaffolding.
|
|
530
|
+
*
|
|
531
|
+
* Each entry maps a `@lunora/*` package name → the secrets it requires at
|
|
532
|
+
* runtime, expressed as `{ key, description, docsUrl }` records. The scaffolder
|
|
533
|
+
* in {@link ./scaffold-dev-variables} reads this registry to emit package-aware
|
|
534
|
+
* `.dev.vars.example` entries (placeholders + inline doc-pointer comments).
|
|
535
|
+
*
|
|
536
|
+
* ## Adding a new add-on
|
|
537
|
+
*
|
|
538
|
+
* When a new `@lunora/*` package requires runtime secrets, add one entry to
|
|
539
|
+
* {@link PACKAGE_SECRETS_REGISTRY} keyed by its exact npm package name. Each
|
|
540
|
+
* `SecretEntry` in the array needs:
|
|
541
|
+
*
|
|
542
|
+
* - `key` — the env-var name the package reads from `env` (e.g. `RESEND_API_KEY`).
|
|
543
|
+
* - `description` — one line describing the secret and how to obtain it.
|
|
544
|
+
* - `docsUrl` — a stable URL to the package/provider docs.
|
|
545
|
+
*
|
|
546
|
+
* The registry lives in `@lunora/config` so that add-ons themselves never need
|
|
547
|
+
* to depend on it (no circular coupling). Add-ons document their secrets in
|
|
548
|
+
* their own READMEs; the registry duplicates that knowledge in a machine-readable
|
|
549
|
+
* form that the scaffolder can consume.
|
|
550
|
+
*
|
|
551
|
+
* **Never write a real secret value** in this file — `placeholderValue` entries
|
|
552
|
+
* are the only allowed values (they must pass `isPlaceholderValue` from
|
|
553
|
+
* scaffold-dev-variables).
|
|
554
|
+
*/
|
|
324
555
|
/** A single secret variable required by a package. */
|
|
325
556
|
interface SecretEntry {
|
|
326
557
|
/** One sentence describing what this secret is and how to obtain it. */
|
|
@@ -330,87 +561,87 @@ interface SecretEntry {
|
|
|
330
561
|
/** The env-var key as it appears in `.dev.vars`, e.g. `AUTH_SECRET`. */
|
|
331
562
|
key: string;
|
|
332
563
|
/**
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
564
|
+
* The placeholder value written into `.dev.vars.example`.
|
|
565
|
+
* Must pass `isPlaceholderValue` from scaffold-dev-variables so the
|
|
566
|
+
* scaffolder regenerates it when generating `.dev.vars`. Use angle-bracket
|
|
567
|
+
* conventions or a recognised marker like `replace-with-openssl-rand-hex-32`.
|
|
568
|
+
* Non-secret env-vars (e.g. `AUTH_URL`) may carry a real default value.
|
|
569
|
+
*/
|
|
339
570
|
placeholderValue: string;
|
|
340
571
|
}
|
|
341
572
|
/**
|
|
342
|
-
* The canonical registry of per-package secret requirements.
|
|
343
|
-
*
|
|
344
|
-
* Keys are exact npm package names (e.g. `"@lunora/auth"`). Values are
|
|
345
|
-
* non-empty arrays of {@link SecretEntry} — one entry per required secret key.
|
|
346
|
-
*
|
|
347
|
-
* The scaffolder in `scaffold-dev-variables.ts` calls
|
|
348
|
-
* {@link secretsForPackages} to resolve the applicable entries from this map
|
|
349
|
-
* given the set of detected capability package names.
|
|
350
|
-
*/
|
|
573
|
+
* The canonical registry of per-package secret requirements.
|
|
574
|
+
*
|
|
575
|
+
* Keys are exact npm package names (e.g. `"@lunora/auth"`). Values are
|
|
576
|
+
* non-empty arrays of {@link SecretEntry} — one entry per required secret key.
|
|
577
|
+
*
|
|
578
|
+
* The scaffolder in `scaffold-dev-variables.ts` calls
|
|
579
|
+
* {@link secretsForPackages} to resolve the applicable entries from this map
|
|
580
|
+
* given the set of detected capability package names.
|
|
581
|
+
*/
|
|
351
582
|
declare const PACKAGE_SECRETS_REGISTRY: Readonly<Record<string, ReadonlyArray<SecretEntry>>>;
|
|
352
583
|
/**
|
|
353
|
-
* Collect all secret entries required by the given set of package names. The
|
|
354
|
-
* order follows the order of `packageNames` (stable, predictable output), and
|
|
355
|
-
* within each package the entries are returned in registry declaration order.
|
|
356
|
-
*
|
|
357
|
-
* Only packages present in {@link PACKAGE_SECRETS_REGISTRY} contribute entries;
|
|
358
|
-
* unknown package names are silently ignored — this makes the call site resilient
|
|
359
|
-
* to future capability flags whose packages have no secrets.
|
|
360
|
-
*/
|
|
584
|
+
* Collect all secret entries required by the given set of package names. The
|
|
585
|
+
* order follows the order of `packageNames` (stable, predictable output), and
|
|
586
|
+
* within each package the entries are returned in registry declaration order.
|
|
587
|
+
*
|
|
588
|
+
* Only packages present in {@link PACKAGE_SECRETS_REGISTRY} contribute entries;
|
|
589
|
+
* unknown package names are silently ignored — this makes the call site resilient
|
|
590
|
+
* to future capability flags whose packages have no secrets.
|
|
591
|
+
*/
|
|
361
592
|
declare const secretsForPackages: (packageNames: ReadonlyArray<string>) => SecretEntry[];
|
|
362
593
|
/** The canonical project-config filename probed at the project root. */
|
|
363
594
|
declare const LUNORA_CONFIG_FILE = "lunora.json";
|
|
364
595
|
/**
|
|
365
|
-
* The parsed `remote` preference from `lunora.json`:
|
|
366
|
-
*
|
|
367
|
-
* - `true` / `false` — the boolean form: enable or explicitly disable remote dev.
|
|
368
|
-
* - `undefined` — no usable preference (file absent, key absent, or malformed).
|
|
369
|
-
*
|
|
370
|
-
* The object form (scoping which binding kinds go remote) is reserved for a
|
|
371
|
-
* future increment; for now an object value is treated as "enabled" (truthy
|
|
372
|
-
* presence) so forward-written configs still turn remote on.
|
|
373
|
-
*/
|
|
596
|
+
* The parsed `remote` preference from `lunora.json`:
|
|
597
|
+
*
|
|
598
|
+
* - `true` / `false` — the boolean form: enable or explicitly disable remote dev.
|
|
599
|
+
* - `undefined` — no usable preference (file absent, key absent, or malformed).
|
|
600
|
+
*
|
|
601
|
+
* The object form (scoping which binding kinds go remote) is reserved for a
|
|
602
|
+
* future increment; for now an object value is treated as "enabled" (truthy
|
|
603
|
+
* presence) so forward-written configs still turn remote on.
|
|
604
|
+
*/
|
|
374
605
|
type RemotePreference = boolean | undefined;
|
|
375
606
|
/** The structural slice of `lunora.json` Lunora reads. */
|
|
376
607
|
interface LunoraProjectConfig {
|
|
377
608
|
remote?: unknown;
|
|
378
609
|
}
|
|
379
610
|
/**
|
|
380
|
-
* Interpret a raw `remote` value into a tri-state preference. A boolean passes
|
|
381
|
-
* through; an object is treated as enabled (the documented-but-not-yet-honored
|
|
382
|
-
* scoping form is still an opt-in); anything else (string, number, null) is no
|
|
383
|
-
* preference.
|
|
384
|
-
*/
|
|
611
|
+
* Interpret a raw `remote` value into a tri-state preference. A boolean passes
|
|
612
|
+
* through; an object is treated as enabled (the documented-but-not-yet-honored
|
|
613
|
+
* scoping form is still an opt-in); anything else (string, number, null) is no
|
|
614
|
+
* preference.
|
|
615
|
+
*/
|
|
385
616
|
declare const interpretRemote: (value: unknown) => RemotePreference;
|
|
386
617
|
/**
|
|
387
|
-
* Read the project's `remote` preference from `lunora.json`, or `undefined` when
|
|
388
|
-
* there's no usable preference. Best-effort: never throws — a missing file,
|
|
389
|
-
* parse error, or unexpected shape all collapse to `undefined` so the caller
|
|
390
|
-
* falls through to the env/flag layers.
|
|
391
|
-
*/
|
|
618
|
+
* Read the project's `remote` preference from `lunora.json`, or `undefined` when
|
|
619
|
+
* there's no usable preference. Best-effort: never throws — a missing file,
|
|
620
|
+
* parse error, or unexpected shape all collapse to `undefined` so the caller
|
|
621
|
+
* falls through to the env/flag layers.
|
|
622
|
+
*/
|
|
392
623
|
declare const readProjectRemotePreference: (projectRoot: string) => RemotePreference;
|
|
393
624
|
/**
|
|
394
|
-
* Whether we can interactively prompt — stdin must be a TTY. In CI / piped
|
|
395
|
-
* contexts this is false, and callers should fall back to a non-interactive
|
|
396
|
-
* default (skip, or require an explicit `--yes`) rather than hang on a read.
|
|
397
|
-
*/
|
|
625
|
+
* Whether we can interactively prompt — stdin must be a TTY. In CI / piped
|
|
626
|
+
* contexts this is false, and callers should fall back to a non-interactive
|
|
627
|
+
* default (skip, or require an explicit `--yes`) rather than hang on a read.
|
|
628
|
+
*/
|
|
398
629
|
declare const isInteractive: () => boolean;
|
|
399
630
|
/**
|
|
400
|
-
* Ask a yes/no question on stdin. With `defaultYes`, an empty answer (just
|
|
401
|
-
* Enter) counts as yes and the prompt should read `[Y/n]`; otherwise empty is
|
|
402
|
-
* no (`[y/N]`). Shared by the CLI (`reset`, `dev`) and the Vite dev server.
|
|
403
|
-
*/
|
|
631
|
+
* Ask a yes/no question on stdin. With `defaultYes`, an empty answer (just
|
|
632
|
+
* Enter) counts as yes and the prompt should read `[Y/n]`; otherwise empty is
|
|
633
|
+
* no (`[y/N]`). Shared by the CLI (`reset`, `dev`) and the Vite dev server.
|
|
634
|
+
*/
|
|
404
635
|
declare const promptYesNo: (prompt: string, options?: {
|
|
405
636
|
defaultYes?: boolean;
|
|
406
637
|
}) => Promise<boolean>;
|
|
407
638
|
/**
|
|
408
|
-
* Build a default-yes `confirm(message)` for the scaffolders' `ensureDevVariables`:
|
|
409
|
-
* an interactive `[Y/n]` prompt (optionally prefixed, e.g. `"[lunora] "`) when
|
|
410
|
-
* stdin is a TTY, or an immediate `false` otherwise — so CI declines silently
|
|
411
|
-
* instead of blocking. Keeps the "non-interactive ⇒ decline" policy in one place
|
|
412
|
-
* rather than re-stated at every call site.
|
|
413
|
-
*/
|
|
639
|
+
* Build a default-yes `confirm(message)` for the scaffolders' `ensureDevVariables`:
|
|
640
|
+
* an interactive `[Y/n]` prompt (optionally prefixed, e.g. `"[lunora] "`) when
|
|
641
|
+
* stdin is a TTY, or an immediate `false` otherwise — so CI declines silently
|
|
642
|
+
* instead of blocking. Keeps the "non-interactive ⇒ decline" policy in one place
|
|
643
|
+
* rather than re-stated at every call site.
|
|
644
|
+
*/
|
|
414
645
|
declare const createConfirm: (prefix?: string) => ((message: string) => Promise<boolean>);
|
|
415
646
|
/** One choice in a {@link promptSelect} list. `value` is returned; `label` (and optional `description`) are shown. */
|
|
416
647
|
interface SelectOption<T extends string> {
|
|
@@ -419,49 +650,59 @@ interface SelectOption<T extends string> {
|
|
|
419
650
|
value: T;
|
|
420
651
|
}
|
|
421
652
|
/**
|
|
422
|
-
* Ask the user to pick one option from a numbered list on stdin. Accepts the
|
|
423
|
-
* 1-based number or the option's `value`/`label` typed verbatim; an empty answer
|
|
424
|
-
* (just Enter) takes `settings.default`. In a non-interactive context (CI /
|
|
425
|
-
* piped — no TTY) it never reads and returns `settings.default` (or `undefined`),
|
|
426
|
-
* mirroring {@link createConfirm}'s "non-interactive ⇒ fall back" policy so
|
|
427
|
-
* automation never blocks.
|
|
428
|
-
*/
|
|
653
|
+
* Ask the user to pick one option from a numbered list on stdin. Accepts the
|
|
654
|
+
* 1-based number or the option's `value`/`label` typed verbatim; an empty answer
|
|
655
|
+
* (just Enter) takes `settings.default`. In a non-interactive context (CI /
|
|
656
|
+
* piped — no TTY) it never reads and returns `settings.default` (or `undefined`),
|
|
657
|
+
* mirroring {@link createConfirm}'s "non-interactive ⇒ fall back" policy so
|
|
658
|
+
* automation never blocks.
|
|
659
|
+
*/
|
|
429
660
|
declare const promptSelect: <T extends string>(message: string, options: ReadonlyArray<SelectOption<T>>, settings?: {
|
|
430
661
|
default?: T;
|
|
431
662
|
}) => Promise<T | undefined>;
|
|
663
|
+
/**
|
|
664
|
+
* Ask a free-text question on stdin, returning the trimmed answer. An empty
|
|
665
|
+
* answer (just Enter) takes `settings.default`. In a non-interactive context
|
|
666
|
+
* (CI / piped — no TTY) it never reads and returns `settings.default` (or
|
|
667
|
+
* `undefined`), mirroring {@link promptSelect}'s "non-interactive ⇒ fall back"
|
|
668
|
+
* policy so automation never blocks.
|
|
669
|
+
*/
|
|
670
|
+
declare const promptText: (message: string, settings?: {
|
|
671
|
+
default?: string;
|
|
672
|
+
}) => Promise<string | undefined>;
|
|
432
673
|
/** One choice in a {@link promptMultiSelect} list. Identical shape to {@link SelectOption}; `value` is returned when picked. */
|
|
433
674
|
type MultiSelectOption<T extends string> = SelectOption<T>;
|
|
434
675
|
/**
|
|
435
|
-
* Ask the user to pick zero or more options from a numbered list on stdin.
|
|
436
|
-
* Accepts a comma- or space-separated list of 1-based numbers and/or option
|
|
437
|
-
* `value`/`label`s typed verbatim; an empty answer (just Enter) takes
|
|
438
|
-
* `settings.defaults`. In a non-interactive context (CI / piped — no TTY) it
|
|
439
|
-
* never reads and returns `settings.defaults ?? []`, mirroring {@link promptSelect}'s
|
|
440
|
-
* "non-interactive ⇒ fall back" policy so automation never blocks. Unknown
|
|
441
|
-
* tokens are ignored; the returned list is de-duplicated and preserves option
|
|
442
|
-
* order.
|
|
443
|
-
*/
|
|
676
|
+
* Ask the user to pick zero or more options from a numbered list on stdin.
|
|
677
|
+
* Accepts a comma- or space-separated list of 1-based numbers and/or option
|
|
678
|
+
* `value`/`label`s typed verbatim; an empty answer (just Enter) takes
|
|
679
|
+
* `settings.defaults`. In a non-interactive context (CI / piped — no TTY) it
|
|
680
|
+
* never reads and returns `settings.defaults ?? []`, mirroring {@link promptSelect}'s
|
|
681
|
+
* "non-interactive ⇒ fall back" policy so automation never blocks. Unknown
|
|
682
|
+
* tokens are ignored; the returned list is de-duplicated and preserves option
|
|
683
|
+
* order.
|
|
684
|
+
*/
|
|
444
685
|
declare const promptMultiSelect: <T extends string>(message: string, options: ReadonlyArray<MultiSelectOption<T>>, settings?: {
|
|
445
686
|
defaults?: ReadonlyArray<T>;
|
|
446
687
|
}) => Promise<T[]>;
|
|
447
688
|
/**
|
|
448
|
-
* A container/workflow that is declared (so codegen emits its class) but the
|
|
449
|
-
* worker entry never re-exports — the one wiring step the generators can't always
|
|
450
|
-
* do for the developer. wrangler rejects a `class_name` the deployed worker
|
|
451
|
-
* doesn't export, so a deploy fails late on this; surfacing it as structured data
|
|
452
|
-
* lets the Vite plugin raise it in the dev error overlay (not just the console)
|
|
453
|
-
* the moment the gap appears. The human-readable form is also folded into
|
|
454
|
-
* {@link ReconcileBindingsResult.warnings}.
|
|
455
|
-
*/
|
|
689
|
+
* A container/workflow that is declared (so codegen emits its class) but the
|
|
690
|
+
* worker entry never re-exports — the one wiring step the generators can't always
|
|
691
|
+
* do for the developer. wrangler rejects a `class_name` the deployed worker
|
|
692
|
+
* doesn't export, so a deploy fails late on this; surfacing it as structured data
|
|
693
|
+
* lets the Vite plugin raise it in the dev error overlay (not just the console)
|
|
694
|
+
* the moment the gap appears. The human-readable form is also folded into
|
|
695
|
+
* {@link ReconcileBindingsResult.warnings}.
|
|
696
|
+
*/
|
|
456
697
|
interface ExportGap {
|
|
457
698
|
/** Generated class wrangler needs exported, e.g. `OrderPipelineWorkflow`. */
|
|
458
699
|
className: string;
|
|
459
|
-
/** The `lunora/{containers,workflows}.ts` export name, e.g. `orderPipeline`. */
|
|
700
|
+
/** The `lunora/{agents,containers,workflows}.ts` export name, e.g. `orderPipeline`. */
|
|
460
701
|
exportName: string;
|
|
461
702
|
/** Which declaration is unexported. */
|
|
462
|
-
kind: "container" | "workflow";
|
|
703
|
+
kind: "agent" | "container" | "workflow";
|
|
463
704
|
/** The `_generated/{module}` to re-export from, e.g. `workflows`. */
|
|
464
|
-
module: "containers" | "workflows";
|
|
705
|
+
module: "agents" | "containers" | "workflows";
|
|
465
706
|
}
|
|
466
707
|
interface ReconcileBindingsResult {
|
|
467
708
|
/** Short labels for each binding written (e.g. `"SCHEDULER/SchedulerDO"`). */
|
|
@@ -469,10 +710,10 @@ interface ReconcileBindingsResult {
|
|
|
469
710
|
/** `true` when `wrangler.jsonc` was rewritten. */
|
|
470
711
|
changed: boolean;
|
|
471
712
|
/**
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
713
|
+
* Declared containers/workflows the worker entry doesn't re-export — the
|
|
714
|
+
* structured form of the corresponding `warnings` entries, for the dev error
|
|
715
|
+
* overlay. Empty when every declaration is wired.
|
|
716
|
+
*/
|
|
476
717
|
exportGaps: ExportGap[];
|
|
477
718
|
/** Reason reconciliation was skipped, for logging. */
|
|
478
719
|
reason?: string;
|
|
@@ -482,30 +723,68 @@ interface ReconcileBindingsResult {
|
|
|
482
723
|
wranglerPath?: string;
|
|
483
724
|
}
|
|
484
725
|
/**
|
|
485
|
-
* Reconcile inferred Durable Object / D1 bindings into `wrangler.jsonc`.
|
|
486
|
-
*
|
|
487
|
-
* Writes only when something is missing; returns `changed: false` when the
|
|
488
|
-
* config already satisfies the inferred needs.
|
|
489
|
-
*/
|
|
726
|
+
* Reconcile inferred Durable Object / D1 bindings into `wrangler.jsonc`.
|
|
727
|
+
*
|
|
728
|
+
* Writes only when something is missing; returns `changed: false` when the
|
|
729
|
+
* config already satisfies the inferred needs.
|
|
730
|
+
*/
|
|
490
731
|
declare const reconcileWranglerBindings: (projectRoot: string, inferred: InferredBindings) => ReconcileBindingsResult;
|
|
732
|
+
interface ReconcileCompatibilityDateResult {
|
|
733
|
+
/** `true` when `wrangler.jsonc` was rewritten. */
|
|
734
|
+
changed: boolean;
|
|
735
|
+
/** The new date value, or the existing one when unchanged. */
|
|
736
|
+
date: string | undefined;
|
|
737
|
+
/** Human-readable reason when reconciliation was skipped. */
|
|
738
|
+
reason?: string;
|
|
739
|
+
/** Resolved wrangler path, or `undefined` when none was found. */
|
|
740
|
+
wranglerPath?: string;
|
|
741
|
+
}
|
|
491
742
|
/**
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
*
|
|
506
|
-
* `
|
|
507
|
-
*
|
|
508
|
-
|
|
743
|
+
* Reconcile the `compatibility_date` in `wrangler.jsonc` when Workers Cache
|
|
744
|
+
* is enabled but the date is below the minimum required.
|
|
745
|
+
*/
|
|
746
|
+
declare const reconcileWranglerCompatibilityDate: (projectRoot: string) => ReconcileCompatibilityDateResult;
|
|
747
|
+
interface ReconcileResult {
|
|
748
|
+
/** `true` when `wrangler.jsonc` was rewritten. */
|
|
749
|
+
changed: boolean;
|
|
750
|
+
/** Human-readable reason when reconciliation was skipped (for logging). */
|
|
751
|
+
reason?: string;
|
|
752
|
+
/** Resolved wrangler path, or `undefined` when none was found. */
|
|
753
|
+
wranglerPath?: string;
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Reconcile the codegen-derived cron schedules into the project's
|
|
757
|
+
* `wrangler.jsonc` `triggers.crons` array, preserving comments and formatting
|
|
758
|
+
* via `jsonc-parser`'s structural edits.
|
|
759
|
+
*
|
|
760
|
+
* When `triggers.crons` already matches `cronTriggers`, nothing is written (so
|
|
761
|
+
* we don't churn the file or trip the dev server's file watcher). When the
|
|
762
|
+
* project declares no crons, a stale non-empty array is cleared so removed
|
|
763
|
+
* crons stop firing.
|
|
764
|
+
*
|
|
765
|
+
* This intentionally writes the SAME `triggers.crons` shape the
|
|
766
|
+
* `@lunora/config` validator accepts, so the wrangler validator never fights
|
|
767
|
+
* the generated value.
|
|
768
|
+
*/
|
|
769
|
+
declare const reconcileWranglerCrons: (projectRoot: string, cronTriggers: ReadonlyArray<string>) => ReconcileResult;
|
|
770
|
+
/**
|
|
771
|
+
* The wrangler config sections Lunora can safely flip to remote mode in dev,
|
|
772
|
+
* each with the human label used in logs and the structural `shape` the entry
|
|
773
|
+
* lives in.
|
|
774
|
+
*
|
|
775
|
+
* `"array"` is a top-level array of binding objects (`d1_databases`,
|
|
776
|
+
* `kv_namespaces`, `r2_buckets`, `vectorize`, `services`). `"producers"` is
|
|
777
|
+
* `queues.producers[]` — consumers are NOT remoted (their schema has no `remote`
|
|
778
|
+
* field) and the edit path is two levels deep. `"object"` is a single binding
|
|
779
|
+
* object, not an array (`ai`), whose edit path targets the section key directly.
|
|
780
|
+
*
|
|
781
|
+
* Every kind here was confirmed against `wrangler/config-schema.json`: the
|
|
782
|
+
* entry's schema declares a `remote` property. Deliberately omits
|
|
783
|
+
* `durable_objects` (no CF remote-DO mode; shards stay local) and sections whose
|
|
784
|
+
* schema has no `remote` field (`hyperdrive`, `analytics_engine_datasets`,
|
|
785
|
+
* `secrets_store_secrets`, queue consumers, …). Widening further is a one-line
|
|
786
|
+
* table edit.
|
|
787
|
+
*/
|
|
509
788
|
declare const REMOTE_ELIGIBLE_KEYS: {
|
|
510
789
|
readonly ai: {
|
|
511
790
|
readonly label: "AI";
|
|
@@ -549,11 +828,11 @@ interface RemoteBindingPlan {
|
|
|
549
828
|
/** Short kind label for logging (`"D1"`, `"KV"`, `"R2"`, `"Vectorize"`, …). */
|
|
550
829
|
kind: string;
|
|
551
830
|
/**
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
831
|
+
* The jsonc edit path within {@link RemoteBindingPlan.section}, relative to
|
|
832
|
+
* the section key: `[index]` for an `"array"` section, `["producers", index]`
|
|
833
|
+
* for a queue producer, or `[]` for the single-object `ai` section. The
|
|
834
|
+
* materializer prepends the section key and appends `"remote"`.
|
|
835
|
+
*/
|
|
557
836
|
path: ReadonlyArray<number | string>;
|
|
558
837
|
/** The wrangler config key the entry lives under. */
|
|
559
838
|
section: RemoteEligibleKey;
|
|
@@ -571,19 +850,19 @@ interface RemoteWranglerShape {
|
|
|
571
850
|
vectorize?: ReadonlyArray<BindingEntry | null | undefined>;
|
|
572
851
|
}
|
|
573
852
|
/**
|
|
574
|
-
* Inspect a parsed wrangler config and list every eligible binding that should
|
|
575
|
-
* be flipped to remote mode. Pure — no file-system access, no mutation. An
|
|
576
|
-
* entry already carrying `"remote": true` is still reported (so logging is
|
|
577
|
-
* complete) but the materializer's edit is a harmless no-op for it.
|
|
578
|
-
*/
|
|
853
|
+
* Inspect a parsed wrangler config and list every eligible binding that should
|
|
854
|
+
* be flipped to remote mode. Pure — no file-system access, no mutation. An
|
|
855
|
+
* entry already carrying `"remote": true` is still reported (so logging is
|
|
856
|
+
* complete) but the materializer's edit is a harmless no-op for it.
|
|
857
|
+
*/
|
|
579
858
|
declare const planRemoteBindings: (parsed: RemoteWranglerShape) => RemoteBindingPlan[];
|
|
580
859
|
/**
|
|
581
|
-
* Inject `"remote": true` onto each planned binding in the config `text`,
|
|
582
|
-
* comment-preservingly via jsonc edits. Pure string→string; the edits target
|
|
583
|
-
* disjoint entries so applying them sequentially is safe. The edit path is
|
|
584
|
-
* `[section, ...plan.path, "remote"]`, which resolves to the array element, the
|
|
585
|
-
* `queues.producers[i]` entry, or the single `ai` object as the plan demands.
|
|
586
|
-
*/
|
|
860
|
+
* Inject `"remote": true` onto each planned binding in the config `text`,
|
|
861
|
+
* comment-preservingly via jsonc edits. Pure string→string; the edits target
|
|
862
|
+
* disjoint entries so applying them sequentially is safe. The edit path is
|
|
863
|
+
* `[section, ...plan.path, "remote"]`, which resolves to the array element, the
|
|
864
|
+
* `queues.producers[i]` entry, or the single `ai` object as the plan demands.
|
|
865
|
+
*/
|
|
587
866
|
declare const injectRemoteFlags: (text: string, plans: ReadonlyArray<RemoteBindingPlan>) => string;
|
|
588
867
|
interface MaterializeOptions {
|
|
589
868
|
/** When `false`, the call is a no-op (returns `enabled: false`). */
|
|
@@ -592,18 +871,18 @@ interface MaterializeOptions {
|
|
|
592
871
|
}
|
|
593
872
|
interface MaterializeResult {
|
|
594
873
|
/**
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
874
|
+
* Removes the generated temp config file. Always present and always safe to
|
|
875
|
+
* call: it is idempotent, a no-op when nothing was written (disabled /
|
|
876
|
+
* fall-through cases), and never throws if the path is already gone. The dev
|
|
877
|
+
* command calls this on every exit path (normal, signal, error).
|
|
878
|
+
*/
|
|
600
879
|
cleanup: () => void;
|
|
601
880
|
/**
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
881
|
+
* Absolute path to the generated temp config to pass to
|
|
882
|
+
* `wrangler dev --config`. `undefined` when remote mode is disabled, no
|
|
883
|
+
* wrangler config was found, it failed to parse, or it declared no eligible
|
|
884
|
+
* binding (nothing to remote — run plain local dev).
|
|
885
|
+
*/
|
|
607
886
|
configPath?: string;
|
|
608
887
|
/** Whether remote mode was requested at all. */
|
|
609
888
|
enabled: boolean;
|
|
@@ -613,33 +892,33 @@ interface MaterializeResult {
|
|
|
613
892
|
remoteBindings: RemoteBindingPlan[];
|
|
614
893
|
}
|
|
615
894
|
/**
|
|
616
|
-
* Produce a temporary wrangler config with `"remote": true` on every eligible
|
|
617
|
-
* binding, so `lunora dev` can run `wrangler dev --config <temp>` against the
|
|
618
|
-
* deployed D1/KV/R2 without touching the user's file.
|
|
619
|
-
*
|
|
620
|
-
* The temp file is written as a sibling of the source `wrangler.jsonc` (in the
|
|
621
|
-
* project root), NOT an OS temp dir: wrangler resolves a config's relative paths
|
|
622
|
-
* (`main`, `assets`, `migrations_dir`, …) against the **config file's own
|
|
623
|
-
* directory**, so a temp config in `/tmp` would make wrangler look for
|
|
624
|
-
* `/tmp/src/server.ts` and fail to start the worker. Keeping it beside the real
|
|
625
|
-
* config preserves those relative paths. Returns `configPath: undefined` (with a
|
|
626
|
-
* `reason`) for every fall-through case so the caller degrades to plain local
|
|
627
|
-
* dev instead of failing.
|
|
628
|
-
*/
|
|
895
|
+
* Produce a temporary wrangler config with `"remote": true` on every eligible
|
|
896
|
+
* binding, so `lunora dev` can run `wrangler dev --config <temp>` against the
|
|
897
|
+
* deployed D1/KV/R2 without touching the user's file.
|
|
898
|
+
*
|
|
899
|
+
* The temp file is written as a sibling of the source `wrangler.jsonc` (in the
|
|
900
|
+
* project root), NOT an OS temp dir: wrangler resolves a config's relative paths
|
|
901
|
+
* (`main`, `assets`, `migrations_dir`, …) against the **config file's own
|
|
902
|
+
* directory**, so a temp config in `/tmp` would make wrangler look for
|
|
903
|
+
* `/tmp/src/server.ts` and fail to start the worker. Keeping it beside the real
|
|
904
|
+
* config preserves those relative paths. Returns `configPath: undefined` (with a
|
|
905
|
+
* `reason`) for every fall-through case so the caller degrades to plain local
|
|
906
|
+
* dev instead of failing.
|
|
907
|
+
*/
|
|
629
908
|
declare const materializeRemoteWranglerConfig: (options: MaterializeOptions) => MaterializeResult;
|
|
630
909
|
/**
|
|
631
|
-
* Parse a `LUNORA_REMOTE` env value into the on/off decision. Truthy when set to
|
|
632
|
-
* `"1"` or `"true"` (case-insensitive); anything else — unset, `"0"`, `"false"`,
|
|
633
|
-
* empty — is off. Mirrors the `"1" | "true"` convention used across the runtime.
|
|
634
|
-
*/
|
|
910
|
+
* Parse a `LUNORA_REMOTE` env value into the on/off decision. Truthy when set to
|
|
911
|
+
* `"1"` or `"true"` (case-insensitive); anything else — unset, `"0"`, `"false"`,
|
|
912
|
+
* empty — is off. Mirrors the `"1" | "true"` convention used across the runtime.
|
|
913
|
+
*/
|
|
635
914
|
declare const isRemoteEnvEnabled: (value: string | undefined) => boolean;
|
|
636
915
|
/** The three inputs that can switch remote-binding dev on, in precedence order. */
|
|
637
916
|
interface RemoteEnableInputs {
|
|
638
917
|
/**
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
918
|
+
* The `remote` preference from `lunora.json` (the lowest-priority signal).
|
|
919
|
+
* `undefined` means "no project preference"; an explicit `false` here loses
|
|
920
|
+
* to neither the flag nor the env when those are absent — it just stays off.
|
|
921
|
+
*/
|
|
643
922
|
configPreference?: boolean;
|
|
644
923
|
/** The raw `LUNORA_REMOTE` env value (parsed with {@link isRemoteEnvEnabled}). */
|
|
645
924
|
envValue?: string;
|
|
@@ -647,33 +926,44 @@ interface RemoteEnableInputs {
|
|
|
647
926
|
flag?: boolean;
|
|
648
927
|
}
|
|
649
928
|
/**
|
|
650
|
-
* Resolve whether remote-binding dev is on, with a clear precedence:
|
|
651
|
-
*
|
|
652
|
-
* 1. an explicit `--remote` flag (highest — a deliberate per-invocation choice),
|
|
653
|
-
* 2. then `LUNORA_REMOTE` in the environment,
|
|
654
|
-
* 3. then the `remote` key in `lunora.json` (lowest — a project default).
|
|
655
|
-
*
|
|
656
|
-
* The flag and env are one-directional (they can only turn remote *on*); only
|
|
657
|
-
* the config preference carries a meaningful `false`, and it applies solely when
|
|
658
|
-
* neither stronger signal is present. So a project that sets `"remote": false`
|
|
659
|
-
* is still overridable per-run by `--remote` or `LUNORA_REMOTE=1`.
|
|
660
|
-
*/
|
|
929
|
+
* Resolve whether remote-binding dev is on, with a clear precedence:
|
|
930
|
+
*
|
|
931
|
+
* 1. an explicit `--remote` flag (highest — a deliberate per-invocation choice),
|
|
932
|
+
* 2. then `LUNORA_REMOTE` in the environment,
|
|
933
|
+
* 3. then the `remote` key in `lunora.json` (lowest — a project default).
|
|
934
|
+
*
|
|
935
|
+
* The flag and env are one-directional (they can only turn remote *on*); only
|
|
936
|
+
* the config preference carries a meaningful `false`, and it applies solely when
|
|
937
|
+
* neither stronger signal is present. So a project that sets `"remote": false`
|
|
938
|
+
* is still overridable per-run by `--remote` or `LUNORA_REMOTE=1`.
|
|
939
|
+
*/
|
|
661
940
|
declare const resolveRemoteEnabled: (inputs: RemoteEnableInputs) => boolean;
|
|
941
|
+
/** Core (always-scaffolded) secrets followed by the package-specific ones for the detected capabilities. */
|
|
942
|
+
declare const requiredSecrets: (packageNames: ReadonlyArray<string>) => SecretEntry[];
|
|
662
943
|
/**
|
|
663
|
-
* Whether an (already-unquoted) value looks like a fill-me-in placeholder —
|
|
664
|
-
* empty, angle-bracketed, or containing a known marker — rather than a real
|
|
665
|
-
* value. Used both when scaffolding (which values to regenerate) and by
|
|
666
|
-
* `lunora env doctor` (which set values are still unfilled).
|
|
667
|
-
*/
|
|
944
|
+
* Whether an (already-unquoted) value looks like a fill-me-in placeholder —
|
|
945
|
+
* empty, angle-bracketed, or containing a known marker — rather than a real
|
|
946
|
+
* value. Used both when scaffolding (which values to regenerate) and by
|
|
947
|
+
* `lunora env doctor` (which set values are still unfilled).
|
|
948
|
+
*/
|
|
668
949
|
declare const isPlaceholderValue: (value: string) => boolean;
|
|
669
950
|
/**
|
|
670
|
-
*
|
|
671
|
-
*
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
*/
|
|
951
|
+
* True for a secret-looking key whose value Lunora can mint locally (a random
|
|
952
|
+
* 32-byte hex, like `openssl rand -hex 32`) — e.g. `AUTH_SECRET`,
|
|
953
|
+
* `LUNORA_ADMIN_TOKEN`, `STORAGE_SIGNING_SECRET`. False for provider-issued keys
|
|
954
|
+
* ({@link PROVIDER_SECRET_KEYS}) and any non-secret key.
|
|
955
|
+
*/
|
|
956
|
+
declare const isMintableSecretKey: (key: string) => boolean;
|
|
957
|
+
/** Mint a fresh strong secret value — 64 hex chars (32 bytes), like `openssl rand -hex 32`. */
|
|
958
|
+
declare const generateSecretValue: (randomHex?: (bytes: number) => string) => string;
|
|
959
|
+
/**
|
|
960
|
+
* The outcome of planning a scaffold — a discriminated union so the orchestrator
|
|
961
|
+
* never has to re-derive whether `content` is present.
|
|
962
|
+
*
|
|
963
|
+
* `exists`: `.dev.vars` is already there; nothing to do.
|
|
964
|
+
* `no-example`: nothing to scaffold from (stay silent — the project may not use secrets).
|
|
965
|
+
* `generate`: write `content`, a copy of the example with secret-looking placeholders replaced by fresh random hex (`generatedKeys` lists which).
|
|
966
|
+
*/
|
|
677
967
|
type ScaffoldPlan = {
|
|
678
968
|
content: string;
|
|
679
969
|
generatedKeys: string[];
|
|
@@ -686,7 +976,8 @@ type ScaffoldPlan = {
|
|
|
686
976
|
/** Decide whether (and what) to scaffold. Pure — given the current state of the two files. */
|
|
687
977
|
declare const planDevVariablesScaffold: (input: {
|
|
688
978
|
devVarsExists: boolean;
|
|
689
|
-
exampleContent: string | undefined;
|
|
979
|
+
exampleContent: string | undefined;
|
|
980
|
+
/** Injectable for deterministic tests; defaults to `crypto.randomBytes`. */
|
|
690
981
|
randomHex?: (bytes: number) => string;
|
|
691
982
|
}) => ScaffoldPlan;
|
|
692
983
|
interface AugmentPlan {
|
|
@@ -698,22 +989,23 @@ interface AugmentPlan {
|
|
|
698
989
|
missingKeys: string[];
|
|
699
990
|
}
|
|
700
991
|
/**
|
|
701
|
-
* Plan how to top up an existing `.dev.vars` from the example: every example key
|
|
702
|
-
* not already present becomes an appended line (secret placeholders filled with
|
|
703
|
-
* fresh random hex, other values copied). Pure — no I/O. Empty `missingKeys`
|
|
704
|
-
* means the file is already complete.
|
|
705
|
-
*/
|
|
992
|
+
* Plan how to top up an existing `.dev.vars` from the example: every example key
|
|
993
|
+
* not already present becomes an appended line (secret placeholders filled with
|
|
994
|
+
* fresh random hex, other values copied). Pure — no I/O. Empty `missingKeys`
|
|
995
|
+
* means the file is already complete.
|
|
996
|
+
*/
|
|
706
997
|
declare const planDevVariablesAugment: (input: {
|
|
707
998
|
exampleContent: string;
|
|
708
|
-
existingContent: string;
|
|
999
|
+
existingContent: string;
|
|
1000
|
+
/** Injectable for deterministic tests; defaults to `crypto.randomBytes`. */
|
|
709
1001
|
randomHex?: (bytes: number) => string;
|
|
710
1002
|
}) => AugmentPlan;
|
|
711
1003
|
interface EnsureDevVariablesDeps {
|
|
712
1004
|
/**
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
1005
|
+
* Ask the user to confirm generating the file. Return `true` to generate.
|
|
1006
|
+
* Consumers pass a TTY-aware prompt; in non-interactive contexts they should
|
|
1007
|
+
* resolve `false` (we then report `"declined"` and the caller can hint).
|
|
1008
|
+
*/
|
|
717
1009
|
confirm: (message: string) => Promise<boolean>;
|
|
718
1010
|
cwd: string;
|
|
719
1011
|
/** Emit a human-facing line (success / hint). */
|
|
@@ -732,42 +1024,94 @@ interface EnsureDevVariablesResult {
|
|
|
732
1024
|
status: EnsureDevVariablesStatus;
|
|
733
1025
|
}
|
|
734
1026
|
/**
|
|
735
|
-
* Reconcile the project's `.dev.vars` with its `.dev.vars.example`:
|
|
736
|
-
*
|
|
737
|
-
* - file missing → offer to generate it (secret placeholders auto-filled);
|
|
738
|
-
* - file present but missing keys the example lists → offer to append them;
|
|
739
|
-
* - file present and complete → nothing to do.
|
|
740
|
-
*
|
|
741
|
-
* Prompts via `confirm` (skipped when `yes`); never overwrites existing values.
|
|
742
|
-
* Returns what happened so the caller can tailor any follow-up. Shared by
|
|
743
|
-
* `lunora dev` and the `@lunora/vite` dev server. All side effects funnel
|
|
744
|
-
* through `confirm`/`info`/`randomHex`.
|
|
745
|
-
*/
|
|
1027
|
+
* Reconcile the project's `.dev.vars` with its `.dev.vars.example`:
|
|
1028
|
+
*
|
|
1029
|
+
* - file missing → offer to generate it (secret placeholders auto-filled);
|
|
1030
|
+
* - file present but missing keys the example lists → offer to append them;
|
|
1031
|
+
* - file present and complete → nothing to do.
|
|
1032
|
+
*
|
|
1033
|
+
* Prompts via `confirm` (skipped when `yes`); never overwrites existing values.
|
|
1034
|
+
* Returns what happened so the caller can tailor any follow-up. Shared by
|
|
1035
|
+
* `lunora dev` and the `@lunora/vite` dev server. All side effects funnel
|
|
1036
|
+
* through `confirm`/`info`/`randomHex`.
|
|
1037
|
+
*/
|
|
746
1038
|
declare const ensureDevVariables: (deps: EnsureDevVariablesDeps) => Promise<EnsureDevVariablesResult>;
|
|
747
1039
|
/**
|
|
748
|
-
* Build the text that should be merged into `.dev.vars.example` for the given
|
|
749
|
-
* set of package names. Only entries whose key is not already present in
|
|
750
|
-
* `existingKeys` are included (additive / idempotent). Returns an empty string
|
|
751
|
-
* when there is nothing to add.
|
|
752
|
-
*
|
|
753
|
-
* The output is grouped by package with a blank-line separator so the file
|
|
754
|
-
* reads cleanly when multiple packages each contribute several keys.
|
|
755
|
-
*
|
|
756
|
-
* **Safety invariant:** this function never writes a real secret — every value
|
|
757
|
-
* in the output is the entry's `placeholderValue`.
|
|
758
|
-
*/
|
|
1040
|
+
* Build the text that should be merged into `.dev.vars.example` for the given
|
|
1041
|
+
* set of package names. Only entries whose key is not already present in
|
|
1042
|
+
* `existingKeys` are included (additive / idempotent). Returns an empty string
|
|
1043
|
+
* when there is nothing to add.
|
|
1044
|
+
*
|
|
1045
|
+
* The output is grouped by package with a blank-line separator so the file
|
|
1046
|
+
* reads cleanly when multiple packages each contribute several keys.
|
|
1047
|
+
*
|
|
1048
|
+
* **Safety invariant:** this function never writes a real secret — every value
|
|
1049
|
+
* in the output is the entry's `placeholderValue`.
|
|
1050
|
+
*/
|
|
759
1051
|
declare const buildPackageSecretsBlock: (packageNames: ReadonlyArray<string>, existingKeys: ReadonlySet<string>) => string;
|
|
760
1052
|
/**
|
|
761
|
-
* Write (or update) `.dev.vars.example` so that it contains the secrets
|
|
762
|
-
* required by `packageNames`. Existing lines are never removed or rewritten;
|
|
763
|
-
* new entries are appended (with a blank-line separator after existing content).
|
|
764
|
-
*
|
|
765
|
-
* Idempotent: re-running with the same `packageNames` does not duplicate keys
|
|
766
|
-
* already in the file. Returns the list of keys that were actually appended.
|
|
767
|
-
*
|
|
768
|
-
* **Safety invariant:** only placeholder values are written — no real secrets.
|
|
769
|
-
*/
|
|
1053
|
+
* Write (or update) `.dev.vars.example` so that it contains the secrets
|
|
1054
|
+
* required by `packageNames`. Existing lines are never removed or rewritten;
|
|
1055
|
+
* new entries are appended (with a blank-line separator after existing content).
|
|
1056
|
+
*
|
|
1057
|
+
* Idempotent: re-running with the same `packageNames` does not duplicate keys
|
|
1058
|
+
* already in the file. Returns the list of keys that were actually appended.
|
|
1059
|
+
*
|
|
1060
|
+
* **Safety invariant:** only placeholder values are written — no real secrets.
|
|
1061
|
+
*/
|
|
770
1062
|
declare const ensureDevVariablesExample: (cwd: string, packageNames: ReadonlyArray<string>) => string[];
|
|
1063
|
+
interface DevSecretsFillPlan {
|
|
1064
|
+
/** {@link CORE_SECRETS} keys appended because they were absent (each generated). */
|
|
1065
|
+
addedKeys: string[];
|
|
1066
|
+
/** The full new file content to write. */
|
|
1067
|
+
content: string;
|
|
1068
|
+
/** Existing empty/placeholder secret-keyed entries filled with fresh values. */
|
|
1069
|
+
filledKeys: string[];
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Plan the in-place generation of dev secrets for a `.dev.vars`. First, every
|
|
1073
|
+
* line whose KEY looks like a secret (`*_SECRET`, `*_TOKEN`, `*_KEY`,
|
|
1074
|
+
* `*_PASSWORD`) and whose value is empty or a placeholder gets a freshly
|
|
1075
|
+
* generated value — so a `lunora add`-scaffolded `.dev.vars` (which writes each
|
|
1076
|
+
* secret blank) becomes usable on `lunora dev` / `vite dev` without the user
|
|
1077
|
+
* running `openssl` by hand. Second, any {@link CORE_SECRETS} key absent from
|
|
1078
|
+
* the file is appended (generated) — notably `LUNORA_ADMIN_TOKEN`, which the
|
|
1079
|
+
* local Studio needs to call the worker's admin gate in dev (without it the
|
|
1080
|
+
* Studio shows its login gate).
|
|
1081
|
+
*
|
|
1082
|
+
* Pure (given `randomHex`): real (non-placeholder) values are never touched, and
|
|
1083
|
+
* comments + non-secret entries are preserved verbatim.
|
|
1084
|
+
*/
|
|
1085
|
+
declare const planDevSecretsFill: (input: {
|
|
1086
|
+
existingContent: string;
|
|
1087
|
+
randomHex?: (bytes: number) => string;
|
|
1088
|
+
}) => DevSecretsFillPlan;
|
|
1089
|
+
interface FillDevSecretsResult {
|
|
1090
|
+
/** Core secret keys appended (generated) because they were missing. */
|
|
1091
|
+
addedKeys: string[];
|
|
1092
|
+
/** Existing empty/placeholder secrets filled with generated values. */
|
|
1093
|
+
filledKeys: string[];
|
|
1094
|
+
/** `created` = no `.dev.vars` existed; `filled` = topped up an existing one; `unchanged` = nothing to do. */
|
|
1095
|
+
status: "created" | "filled" | "unchanged";
|
|
1096
|
+
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Generate any missing/empty dev secrets in the project's `.dev.vars`, in place.
|
|
1099
|
+
*
|
|
1100
|
+
* Complements {@link ensureDevVariables} (which scaffolds `.dev.vars` from
|
|
1101
|
+
* `.dev.vars.example`). A `lunora add`-scaffolded project writes secrets blank
|
|
1102
|
+
* straight into `.dev.vars` (no example) and never includes `LUNORA_ADMIN_TOKEN`
|
|
1103
|
+
* — so the worker boots with empty secrets and the Studio shows its login gate.
|
|
1104
|
+
* This fills those gaps at dev startup, so both `lunora dev` and the
|
|
1105
|
+
* `@lunora/vite` dev server give a working project with zero manual `openssl`.
|
|
1106
|
+
*
|
|
1107
|
+
* Never overwrites a real (non-placeholder) value. The write is atomic + owner-
|
|
1108
|
+
* only (temp + rename, `mode: 0o600`), matching the other `.dev.vars` writers.
|
|
1109
|
+
*/
|
|
1110
|
+
declare const fillDevSecrets: (deps: {
|
|
1111
|
+
cwd: string;
|
|
1112
|
+
info?: (message: string) => void;
|
|
1113
|
+
randomHex?: (bytes: number) => string;
|
|
1114
|
+
}) => FillDevSecretsResult;
|
|
771
1115
|
/** Add a new table to `defineSchema({ ... })`. */
|
|
772
1116
|
interface AddTableEdit {
|
|
773
1117
|
readonly kind: "addTable";
|
|
@@ -779,11 +1123,11 @@ interface AddOptionalColumnEdit {
|
|
|
779
1123
|
readonly kind: "addOptionalColumn";
|
|
780
1124
|
readonly table: string;
|
|
781
1125
|
/**
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
1126
|
+
* Inner validator expression text WITHOUT the `v.optional(...)` wrapper, e.g.
|
|
1127
|
+
* `v.string()`. Always wrapped in `v.optional(...)` on apply, because only
|
|
1128
|
+
* optional columns are additive-safe (a required column needs a backfill
|
|
1129
|
+
* migration).
|
|
1130
|
+
*/
|
|
787
1131
|
readonly validator: string;
|
|
788
1132
|
}
|
|
789
1133
|
/** Add a secondary index to an existing table. */
|
|
@@ -797,9 +1141,9 @@ interface AddIndexEdit {
|
|
|
797
1141
|
/** Additive edits — the only requests {@link applyAdditiveEdit} applies. */
|
|
798
1142
|
type AdditiveEdit = AddIndexEdit | AddOptionalColumnEdit | AddTableEdit;
|
|
799
1143
|
/**
|
|
800
|
-
* Destructive edits — never applied directly; routed to the migration handoff
|
|
801
|
-
* (plan 024 Item 5). Carried as data so the editor can describe the request.
|
|
802
|
-
*/
|
|
1144
|
+
* Destructive edits — never applied directly; routed to the migration handoff
|
|
1145
|
+
* (plan 024 Item 5). Carried as data so the editor can describe the request.
|
|
1146
|
+
*/
|
|
803
1147
|
interface DestructiveEdit {
|
|
804
1148
|
readonly column?: string;
|
|
805
1149
|
readonly kind: "changeColumnType" | "dropColumn" | "dropTable" | "makeRequired" | "renameColumn";
|
|
@@ -810,9 +1154,9 @@ interface DestructiveEdit {
|
|
|
810
1154
|
/** Any edit the editor can request. */
|
|
811
1155
|
type SchemaEdit = AdditiveEdit | DestructiveEdit;
|
|
812
1156
|
/**
|
|
813
|
-
* Classify an edit request. Additive edits ({@link AdditiveEdit}) apply
|
|
814
|
-
* directly; everything else changes stored data and is destructive.
|
|
815
|
-
*/
|
|
1157
|
+
* Classify an edit request. Additive edits ({@link AdditiveEdit}) apply
|
|
1158
|
+
* directly; everything else changes stored data and is destructive.
|
|
1159
|
+
*/
|
|
816
1160
|
declare const classifyEdit: (edit: SchemaEdit) => "additive" | "destructive";
|
|
817
1161
|
/** Failure reasons an additive edit can report. */
|
|
818
1162
|
type ApplyFailureReason = "aliased-define-schema" | "destructive" | "duplicate-column" | "duplicate-index" | "duplicate-table" | "invalid-identifier" | "invalid-validator" | "no-define-schema" | "non-object-argument" | "unknown-table";
|
|
@@ -825,10 +1169,10 @@ type ApplyEditResult = {
|
|
|
825
1169
|
text: string;
|
|
826
1170
|
};
|
|
827
1171
|
/**
|
|
828
|
-
* Apply an **additive** edit to a schema source string, preserving formatting.
|
|
829
|
-
* Destructive edits are refused with `{ ok: false, reason: "destructive" }`;
|
|
830
|
-
* route them through the migration handoff (plan 024 Item 5).
|
|
831
|
-
*/
|
|
1172
|
+
* Apply an **additive** edit to a schema source string, preserving formatting.
|
|
1173
|
+
* Destructive edits are refused with `{ ok: false, reason: "destructive" }`;
|
|
1174
|
+
* route them through the migration handoff (plan 024 Item 5).
|
|
1175
|
+
*/
|
|
832
1176
|
declare const applyAdditiveEdit: (source: string, edit: SchemaEdit) => ApplyEditResult;
|
|
833
1177
|
/** A single declared column: its name and the raw validator expression text. */
|
|
834
1178
|
interface SchemaColumn {
|
|
@@ -867,16 +1211,10 @@ type ParseSchemaResult = {
|
|
|
867
1211
|
tables: ReadonlyArray<SchemaTable>;
|
|
868
1212
|
};
|
|
869
1213
|
/**
|
|
870
|
-
*
|
|
871
|
-
*
|
|
872
|
-
*
|
|
873
|
-
*/
|
|
874
|
-
|
|
875
|
-
/**
|
|
876
|
-
* Parse the tables (with typed columns + indexes) out of a `lunora/schema.ts`
|
|
877
|
-
* source string. Returns a tagged result so callers can render a helpful
|
|
878
|
-
* message per failure mode without throwing.
|
|
879
|
-
*/
|
|
1214
|
+
* Parse the tables (with typed columns + indexes) out of a `lunora/schema.ts`
|
|
1215
|
+
* source string. Returns a tagged result so callers can render a helpful
|
|
1216
|
+
* message per failure mode without throwing.
|
|
1217
|
+
*/
|
|
880
1218
|
declare const parseSchema: (source: string) => ParseSchemaResult;
|
|
881
1219
|
interface SchemaInfo {
|
|
882
1220
|
/** Whether the lunora schema declares any `.global()` table. */
|
|
@@ -891,16 +1229,16 @@ interface DiscoverSchemaInfoResult {
|
|
|
891
1229
|
info: SchemaInfo | undefined;
|
|
892
1230
|
}
|
|
893
1231
|
/**
|
|
894
|
-
* Discover {@link SchemaInfo} for a project. Returns `{ info: undefined }` when
|
|
895
|
-
* the project declares no `schema.ts` (not an error), or `{ info: undefined,
|
|
896
|
-
* error }` when a present schema could not be parsed — callers decide whether a
|
|
897
|
-
* parse failure is a warning (validator) or simply ignorable (inference).
|
|
898
|
-
*/
|
|
1232
|
+
* Discover {@link SchemaInfo} for a project. Returns `{ info: undefined }` when
|
|
1233
|
+
* the project declares no `schema.ts` (not an error), or `{ info: undefined,
|
|
1234
|
+
* error }` when a present schema could not be parsed — callers decide whether a
|
|
1235
|
+
* parse failure is a warning (validator) or simply ignorable (inference).
|
|
1236
|
+
*/
|
|
899
1237
|
declare const discoverSchemaInfo: (projectRoot: string, schemaDirectory: string) => DiscoverSchemaInfoResult;
|
|
900
1238
|
/**
|
|
901
|
-
* A badge: the short colored label that prefixes a line. `bg`/`fg` are hex so the
|
|
902
|
-
* same value drives both colorize's `bgHex().hex()` and the tui `<Text>` props.
|
|
903
|
-
*/
|
|
1239
|
+
* A badge: the short colored label that prefixes a line. `bg`/`fg` are hex so the
|
|
1240
|
+
* same value drives both colorize's `bgHex().hex()` and the tui `<Text>` props.
|
|
1241
|
+
*/
|
|
904
1242
|
interface BadgeSpec {
|
|
905
1243
|
bg: `#${string}`;
|
|
906
1244
|
fg: `#${string}`;
|
|
@@ -916,24 +1254,24 @@ type BadgeName = LevelBadgeName | StepBadgeName;
|
|
|
916
1254
|
/** The ordered step-phase names, used to register custom pail log types. */
|
|
917
1255
|
declare const STEP_BADGE_NAMES: ReadonlyArray<StepBadgeName>;
|
|
918
1256
|
/**
|
|
919
|
-
* Every badge, keyed by name. Levels get their conventional colors (red/amber/
|
|
920
|
-
* green/blue/grey); step phases follow create-astro's green→purple→cyan rhythm.
|
|
921
|
-
*/
|
|
1257
|
+
* Every badge, keyed by name. Levels get their conventional colors (red/amber/
|
|
1258
|
+
* green/blue/grey); step phases follow create-astro's green→purple→cyan rhythm.
|
|
1259
|
+
*/
|
|
922
1260
|
declare const BADGES: Record<BadgeName, BadgeSpec>;
|
|
923
1261
|
/**
|
|
924
|
-
* Luna, the mascot: the folklore rabbit-in-the-moon — a bunny tucked inside the
|
|
925
|
-
* moon disc. Pure ASCII so it renders the same everywhere (including piped logs).
|
|
926
|
-
* The CLI signs off the `init` flow with it, the way create-astro closes with
|
|
927
|
-
* Houston.
|
|
928
|
-
*/
|
|
1262
|
+
* Luna, the mascot: the folklore rabbit-in-the-moon — a bunny tucked inside the
|
|
1263
|
+
* moon disc. Pure ASCII so it renders the same everywhere (including piped logs).
|
|
1264
|
+
* The CLI signs off the `init` flow with it, the way create-astro closes with
|
|
1265
|
+
* Houston.
|
|
1266
|
+
*/
|
|
929
1267
|
declare const LUNA_NAME = "Luna";
|
|
930
1268
|
declare const LUNA_SIGNOFF = "Safe travels, voyager.";
|
|
931
1269
|
declare const LUNA_BUNNY: string;
|
|
932
1270
|
/**
|
|
933
|
-
* {@link LUNA_BUNNY} with its leading newline stripped, ready to render inline
|
|
934
|
-
* (beside the name + sign-off). Both render paths — the tui mascot frame and the
|
|
935
|
-
* pail off-TTY fallback — use this so neither re-implements the strip.
|
|
936
|
-
*/
|
|
1271
|
+
* {@link LUNA_BUNNY} with its leading newline stripped, ready to render inline
|
|
1272
|
+
* (beside the name + sign-off). Both render paths — the tui mascot frame and the
|
|
1273
|
+
* pail off-TTY fallback — use this so neither re-implements the strip.
|
|
1274
|
+
*/
|
|
937
1275
|
declare const LUNA_ART: string;
|
|
938
1276
|
/** The colored part of a badge — the word with one space of padding each side. */
|
|
939
1277
|
declare const padBadge: (text: string) => string;
|
|
@@ -947,6 +1285,37 @@ declare const badgeWidth: (_spec: BadgeSpec) => number;
|
|
|
947
1285
|
declare const paintBadge: (spec: BadgeSpec) => string;
|
|
948
1286
|
/** Dim continuation text (a step's chosen answer, shown under the question). */
|
|
949
1287
|
declare const paintAnswer: (text: string) => string;
|
|
1288
|
+
/**
|
|
1289
|
+
* Single source of truth for "does this wrangler config enable Workers
|
|
1290
|
+
* Cache?" and "what compatibility_date does that require?".
|
|
1291
|
+
*
|
|
1292
|
+
* Before this module, `reconcile-compatibility-date.ts` (auto-bump) and
|
|
1293
|
+
* `wrangler-validator.ts` (validation) each carried their own
|
|
1294
|
+
* `WORKERS_CACHE_MIN_DATE` literal and their own top-level/`exports[]`
|
|
1295
|
+
* cache-enabled walk — two copies of the same fact that could silently drift
|
|
1296
|
+
* apart (a date bumped in one file without the other would either validate a
|
|
1297
|
+
* config the reconciler wouldn't produce, or vice versa).
|
|
1298
|
+
*/
|
|
1299
|
+
/** The `compatibility_date` Workers Cache (`cache.enabled: true`) requires. */
|
|
1300
|
+
declare const WORKERS_CACHE_MIN_DATE = "2026-05-01";
|
|
1301
|
+
/** The subset of a parsed `wrangler.jsonc` the cache-enabled check reads. */
|
|
1302
|
+
interface WranglerCacheShape {
|
|
1303
|
+
cache?: {
|
|
1304
|
+
enabled?: boolean;
|
|
1305
|
+
} | null;
|
|
1306
|
+
exports?: Record<string, {
|
|
1307
|
+
cache?: {
|
|
1308
|
+
enabled?: boolean;
|
|
1309
|
+
} | null;
|
|
1310
|
+
} | null> | null;
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Whether Workers Cache is enabled anywhere in a parsed wrangler config — the
|
|
1314
|
+
* top-level `cache.enabled` toggle, or a per-export override in
|
|
1315
|
+
* `exports[name].cache.enabled` (Workers can scope cache per named export).
|
|
1316
|
+
* `undefined`/`null` (an unparsed or absent config) is treated as disabled.
|
|
1317
|
+
*/
|
|
1318
|
+
declare const isCacheEnabled: (parsed: WranglerCacheShape | null | undefined) => boolean;
|
|
950
1319
|
/** Candidate wrangler config filenames, in the order every consumer probes them. */
|
|
951
1320
|
declare const WRANGLER_FILES: readonly ["wrangler.jsonc", "wrangler.json"];
|
|
952
1321
|
/** Locate the project's wrangler config, or `undefined` when none exists. */
|
|
@@ -958,12 +1327,29 @@ interface ReadWranglerResult<T> {
|
|
|
958
1327
|
text: string;
|
|
959
1328
|
}
|
|
960
1329
|
/**
|
|
961
|
-
* Read and JSONC-parse a wrangler config file. Returns the raw `text` (for
|
|
962
|
-
* structural edits) alongside `parsed`, which is `undefined` when the file is
|
|
963
|
-
* not valid JSONC or does not parse to an object. Allows trailing commas, as
|
|
964
|
-
* wrangler does.
|
|
965
|
-
*/
|
|
1330
|
+
* Read and JSONC-parse a wrangler config file. Returns the raw `text` (for
|
|
1331
|
+
* structural edits) alongside `parsed`, which is `undefined` when the file is
|
|
1332
|
+
* not valid JSONC or does not parse to an object. Allows trailing commas, as
|
|
1333
|
+
* wrangler does.
|
|
1334
|
+
*/
|
|
966
1335
|
declare const readWranglerJsonc: <T = unknown>(wranglerPath: string) => ReadWranglerResult<T>;
|
|
1336
|
+
/**
|
|
1337
|
+
* Pure scan of a `vars` map for plaintext secrets — the FS-free core, exported for
|
|
1338
|
+
* unit tests. A variable is flagged when, for a **string** value that is neither a
|
|
1339
|
+
* placeholder nor a public/publishable key, EITHER the value matches a known
|
|
1340
|
+
* secret shape (`secretKindOf`) OR the key name strongly implies a secret and the
|
|
1341
|
+
* value is long enough to plausibly be one. `kind` is the matched shape, or
|
|
1342
|
+
* `secret_named_var` for the key-name path.
|
|
1343
|
+
*/
|
|
1344
|
+
declare const scanWranglerVariablesForSecrets: (variables: Record<string, unknown> | undefined, file: string) => WranglerVariableIR[];
|
|
1345
|
+
/**
|
|
1346
|
+
* Read the project's `wrangler.jsonc` and return its plaintext-secret `vars` as IR
|
|
1347
|
+
* for the `plaintext_secret_in_wrangler_vars` lint. Returns `[]` when there is no
|
|
1348
|
+
* wrangler config, it doesn't parse, or nothing looks like a secret. Scans the
|
|
1349
|
+
* top-level `vars` block (mirroring the existing `validateCorsVariables` scope);
|
|
1350
|
+
* per-environment `env.<name>.vars` overrides are out of scope for now.
|
|
1351
|
+
*/
|
|
1352
|
+
declare const collectWranglerSecretVariables: (projectRoot: string) => WranglerVariableIR[];
|
|
967
1353
|
declare const REQUIRED_COMPATIBILITY_DATE: string;
|
|
968
1354
|
declare const REQUIRED_FLAG: string;
|
|
969
1355
|
interface WranglerDurableObjectBinding {
|
|
@@ -971,10 +1357,10 @@ interface WranglerDurableObjectBinding {
|
|
|
971
1357
|
name?: string;
|
|
972
1358
|
}
|
|
973
1359
|
/**
|
|
974
|
-
* A `tail_consumers` entry: a Worker that receives this Worker's tail events
|
|
975
|
-
* (logs, exceptions, fetch metadata) for forwarding to an external sink. See
|
|
976
|
-
* `withTailConsumer` for the wiring helper.
|
|
977
|
-
*/
|
|
1360
|
+
* A `tail_consumers` entry: a Worker that receives this Worker's tail events
|
|
1361
|
+
* (logs, exceptions, fetch metadata) for forwarding to an external sink. See
|
|
1362
|
+
* `withTailConsumer` for the wiring helper.
|
|
1363
|
+
*/
|
|
978
1364
|
interface TailConsumer {
|
|
979
1365
|
/** Optional Cloudflare environment of the consumer Worker. */
|
|
980
1366
|
environment?: string;
|
|
@@ -993,15 +1379,31 @@ interface WranglerContainerEntry {
|
|
|
993
1379
|
max_instances?: number;
|
|
994
1380
|
}
|
|
995
1381
|
/**
|
|
996
|
-
* A wrangler `workflows[]` entry (parsed from untrusted JSONC). Unlike
|
|
997
|
-
* containers, workflows are NOT Durable Objects — the entry stands alone (no
|
|
998
|
-
* `durable_objects` binding, no migration class).
|
|
999
|
-
*/
|
|
1382
|
+
* A wrangler `workflows[]` entry (parsed from untrusted JSONC). Unlike
|
|
1383
|
+
* containers, workflows are NOT Durable Objects — the entry stands alone (no
|
|
1384
|
+
* `durable_objects` binding, no migration class).
|
|
1385
|
+
*/
|
|
1000
1386
|
interface WranglerWorkflowEntry {
|
|
1001
1387
|
binding?: string;
|
|
1002
1388
|
class_name?: string;
|
|
1003
1389
|
name?: string;
|
|
1004
1390
|
}
|
|
1391
|
+
/** A wrangler `queues.producers[]` entry — a `Queue` binding sending to `queue`. */
|
|
1392
|
+
interface WranglerQueueProducer {
|
|
1393
|
+
binding?: string;
|
|
1394
|
+
delivery_delay?: number;
|
|
1395
|
+
queue?: string;
|
|
1396
|
+
}
|
|
1397
|
+
/** A wrangler `queues.consumers[]` entry — push (worker) or `type: "http_pull"`. */
|
|
1398
|
+
interface WranglerQueueConsumer {
|
|
1399
|
+
dead_letter_queue?: string;
|
|
1400
|
+
max_batch_size?: number;
|
|
1401
|
+
max_batch_timeout?: number;
|
|
1402
|
+
max_retries?: number;
|
|
1403
|
+
queue?: string;
|
|
1404
|
+
retry_delay?: number;
|
|
1405
|
+
type?: string;
|
|
1406
|
+
}
|
|
1005
1407
|
interface WranglerConfig {
|
|
1006
1408
|
analytics_engine_datasets?: ReadonlyArray<{
|
|
1007
1409
|
binding?: string;
|
|
@@ -1016,6 +1418,9 @@ interface WranglerConfig {
|
|
|
1016
1418
|
browser?: {
|
|
1017
1419
|
binding?: string;
|
|
1018
1420
|
};
|
|
1421
|
+
cache?: {
|
|
1422
|
+
enabled?: boolean;
|
|
1423
|
+
} | null;
|
|
1019
1424
|
compatibility_date?: string;
|
|
1020
1425
|
compatibility_flags?: ReadonlyArray<string>;
|
|
1021
1426
|
containers?: ReadonlyArray<WranglerContainerEntry | null | undefined>;
|
|
@@ -1030,6 +1435,16 @@ interface WranglerConfig {
|
|
|
1030
1435
|
durable_objects?: {
|
|
1031
1436
|
bindings?: ReadonlyArray<WranglerDurableObjectBinding>;
|
|
1032
1437
|
};
|
|
1438
|
+
exports?: Record<string, {
|
|
1439
|
+
cache?: {
|
|
1440
|
+
enabled?: boolean;
|
|
1441
|
+
} | null;
|
|
1442
|
+
type?: string;
|
|
1443
|
+
} | null> | null;
|
|
1444
|
+
flagship?: ReadonlyArray<{
|
|
1445
|
+
app_id?: string;
|
|
1446
|
+
binding?: string;
|
|
1447
|
+
} | null | undefined>;
|
|
1033
1448
|
hyperdrive?: ReadonlyArray<{
|
|
1034
1449
|
binding?: string;
|
|
1035
1450
|
id?: string;
|
|
@@ -1066,9 +1481,18 @@ interface WranglerConfig {
|
|
|
1066
1481
|
placement?: {
|
|
1067
1482
|
mode?: string;
|
|
1068
1483
|
};
|
|
1484
|
+
queues?: {
|
|
1485
|
+
consumers?: ReadonlyArray<WranglerQueueConsumer | null | undefined>;
|
|
1486
|
+
producers?: ReadonlyArray<WranglerQueueProducer | null | undefined>;
|
|
1487
|
+
};
|
|
1069
1488
|
r2_buckets?: ReadonlyArray<{
|
|
1070
1489
|
binding?: string;
|
|
1071
1490
|
}>;
|
|
1491
|
+
secrets_store_secrets?: ReadonlyArray<{
|
|
1492
|
+
binding?: string;
|
|
1493
|
+
secret_name?: string;
|
|
1494
|
+
store_id?: string;
|
|
1495
|
+
} | null | undefined>;
|
|
1072
1496
|
send_email?: ReadonlyArray<{
|
|
1073
1497
|
allowed_destination_addresses?: ReadonlyArray<string>;
|
|
1074
1498
|
destination_address?: string;
|
|
@@ -1094,23 +1518,23 @@ interface WranglerValidationReport {
|
|
|
1094
1518
|
warnings: string[];
|
|
1095
1519
|
}
|
|
1096
1520
|
/**
|
|
1097
|
-
* Return a new `WranglerConfig` with `consumer` present in `tail_consumers`,
|
|
1098
|
-
* wiring this Worker to forward its tail events (logs/exceptions) to another
|
|
1099
|
-
* Worker that fans them out to an external sink. Pure and idempotent: an
|
|
1100
|
-
* existing entry with the same `service` + `environment` is left untouched
|
|
1101
|
-
* rather than duplicated, so it is safe to call on every codegen/deploy.
|
|
1102
|
-
*/
|
|
1521
|
+
* Return a new `WranglerConfig` with `consumer` present in `tail_consumers`,
|
|
1522
|
+
* wiring this Worker to forward its tail events (logs/exceptions) to another
|
|
1523
|
+
* Worker that fans them out to an external sink. Pure and idempotent: an
|
|
1524
|
+
* existing entry with the same `service` + `environment` is left untouched
|
|
1525
|
+
* rather than duplicated, so it is safe to call on every codegen/deploy.
|
|
1526
|
+
*/
|
|
1103
1527
|
declare const withTailConsumer: (wrangler: WranglerConfig, consumer: TailConsumer) => WranglerConfig;
|
|
1104
1528
|
/**
|
|
1105
|
-
* Pure validator: given a parsed `WranglerConfig` object and an optional
|
|
1106
|
-
* `SchemaInfo`, produce a structured report. Performs no I/O.
|
|
1107
|
-
*/
|
|
1529
|
+
* Pure validator: given a parsed `WranglerConfig` object and an optional
|
|
1530
|
+
* `SchemaInfo`, produce a structured report. Performs no I/O.
|
|
1531
|
+
*/
|
|
1108
1532
|
declare const validateWranglerConfig: (wrangler: WranglerConfig | undefined, schema?: SchemaInfo) => WranglerValidationReport;
|
|
1109
1533
|
/**
|
|
1110
|
-
* Convenience alias matching the original task-spec signature
|
|
1111
|
-
* `validateWrangler(wranglerJson, schema)` returning
|
|
1112
|
-
* `{ valid, errors, warnings }`.
|
|
1113
|
-
*/
|
|
1534
|
+
* Convenience alias matching the original task-spec signature
|
|
1535
|
+
* `validateWrangler(wranglerJson, schema)` returning
|
|
1536
|
+
* `{ valid, errors, warnings }`.
|
|
1537
|
+
*/
|
|
1114
1538
|
declare const validateWrangler: typeof validateWranglerConfig;
|
|
1115
1539
|
interface WranglerProjectValidationOptions {
|
|
1116
1540
|
projectRoot: string;
|
|
@@ -1122,10 +1546,10 @@ interface WranglerProjectValidationResult {
|
|
|
1122
1546
|
wranglerPath: string | undefined;
|
|
1123
1547
|
}
|
|
1124
1548
|
/**
|
|
1125
|
-
* File-system aware variant: reads `wrangler.jsonc`/`wrangler.json` from
|
|
1126
|
-
* the given project root, discovers the schema (if any), and delegates to
|
|
1127
|
-
* `validateWranglerConfig`. Returns the legacy
|
|
1128
|
-
* `{ problems, wranglerPath }` shape plus the structured `report`.
|
|
1129
|
-
*/
|
|
1549
|
+
* File-system aware variant: reads `wrangler.jsonc`/`wrangler.json` from
|
|
1550
|
+
* the given project root, discovers the schema (if any), and delegates to
|
|
1551
|
+
* `validateWranglerConfig`. Returns the legacy
|
|
1552
|
+
* `{ problems, wranglerPath }` shape plus the structured `report`.
|
|
1553
|
+
*/
|
|
1130
1554
|
declare const validateWranglerProject: (options: WranglerProjectValidationOptions) => WranglerProjectValidationResult;
|
|
1131
|
-
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, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DestructiveEdit, type DetectedFramework, type DiscoverContainerInfoResult, type DiscoverSchemaInfoResult, type DiscoverWorkflowInfoResult, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type ExportGap, 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, findWranglerFile, formatLunoraEvent, inferLunoraBindings, injectRemoteFlags, interpretRemote, isInteractive, isPlaceholderValue, isRemoteEnvEnabled, materializeRemoteWranglerConfig, packageNamesFromBindings, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevVariablesAugment, planDevVariablesScaffold, planRemoteBindings, promptMultiSelect, promptSelect, promptYesNo, readLinkedProject, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, resolveRemoteEnabled, secretsForPackages, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeLinkedProject };
|
|
1555
|
+
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, type ClaimDevServerStateResult, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, 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 InferredAgent, 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 ReconcileCompatibilityDateResult, type ReconcileResult as ReconcileCronsResult, 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, WORKERS_CACHE_MIN_DATE, WRANGLER_FILES, type WranglerCacheShape, type WranglerConfig, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, applyAdditiveEdit, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, collectWranglerSecretVariables, createConfirm, detectAgentRules, detectAiAgent, detectFramework, discoverAgentInfo, discoverContainerInfo, discoverSchemaInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, fillDevSecrets, findWranglerFile, formatLunoraEvent, generateSecretValue, inferLunoraBindings, injectRemoteFlags, interpretRemote, isCacheEnabled, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, isRemoteEnvEnabled, materializeRemoteWranglerConfig, packageNamesFromBindings, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, planRemoteBindings, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, reconcileWranglerCompatibilityDate, reconcileWranglerCrons, requiredSecrets, resolveRemoteEnabled, scanWranglerVariablesForSecrets, secretsForPackages, streamContainerLogs, updateDevServerState, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeDevServerState, writeLinkedProject };
|