@lunora/config 1.0.0-alpha.111 → 1.0.0-alpha.113

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.
@@ -1,5 +1,223 @@
1
1
  import { D as DeployDriver, I as InferredBindings, S as SchemaInfo } from "../packem_shared/schema-info.d-DS0bUsWE.mjs";
2
2
  import { WranglerVariableIR } from '@lunora/codegen';
3
+ /**
4
+ * Translate a `wrangler.jsonc` into an [Alchemy](https://alchemy.run) program.
5
+ *
6
+ * # Why translate rather than ask for a second config
7
+ *
8
+ * `wrangler.jsonc` is already the source of truth for what an app needs, and
9
+ * Lunora already infers and reconciles it — `inferLunoraBindings` decides that
10
+ * a project needs a shard namespace and a bucket, `reconcileWranglerBindings`
11
+ * writes them. Asking a developer to restate all of that in an
12
+ * `alchemy.run.ts` would give the project two sources of truth that drift, and
13
+ * the drift would surface as a deploy that provisions something the app does
14
+ * not bind.
15
+ *
16
+ * So Alchemy is an implementation detail of `deploy`, not a thing to configure:
17
+ * read the config, emit the program, run it.
18
+ *
19
+ * # Why this emits source rather than calling Alchemy
20
+ *
21
+ * `alchemy@0.93` has thirty dependencies, nine of them Node-shaped —
22
+ * `wrangler`, `miniflare`, `esbuild`, `execa`, `find-process`, `glob`, `open`,
23
+ * `proper-lockfile`, `signal-exit`. `@lunora/config` is imported by
24
+ * `@lunora/vite`, so importing Alchemy here would push that tree into every
25
+ * project that merely wanted to read `lunora.json`, and into any bundle
26
+ * targeting workerd — where none of it survives.
27
+ *
28
+ * Emitting text keeps this module pure and dependency-free. Alchemy is invoked
29
+ * as a CLI against the generated file, so it only has to exist on the machine
30
+ * that deploys.
31
+ *
32
+ * # Adoption, not re-creation
33
+ *
34
+ * Every resource is emitted with `adopt: true`. A project translated from an
35
+ * existing `wrangler.jsonc` already *has* its D1 database and its bucket, with
36
+ * data in them. Without adoption Alchemy would treat them as new and try to
37
+ * create alongside — the one outcome a deploy must never have.
38
+ */
39
+ /** A Durable Object binding as `wrangler.jsonc` spells it. */
40
+ interface WranglerDurableObjectBinding$1 {
41
+ class_name?: string;
42
+ name?: string;
43
+ script_name?: string;
44
+ }
45
+ /** The slice of `wrangler.jsonc` that translates into Alchemy resources. */
46
+ interface WranglerConfigShape {
47
+ compatibility_date?: string;
48
+ compatibility_flags?: ReadonlyArray<string>;
49
+ d1_databases?: ReadonlyArray<{
50
+ binding?: string;
51
+ database_id?: string;
52
+ database_name?: string;
53
+ }>;
54
+ durable_objects?: {
55
+ bindings?: ReadonlyArray<WranglerDurableObjectBinding$1>;
56
+ };
57
+ kv_namespaces?: ReadonlyArray<{
58
+ binding?: string;
59
+ id?: string;
60
+ }>;
61
+ main?: string;
62
+ /** `new_sqlite_classes` marks which DO classes get SQLite storage — Alchemy needs that per namespace. */
63
+ migrations?: ReadonlyArray<{
64
+ new_classes?: ReadonlyArray<string>;
65
+ new_sqlite_classes?: ReadonlyArray<string>;
66
+ }>;
67
+ name?: string;
68
+ queues?: {
69
+ producers?: ReadonlyArray<{
70
+ binding?: string;
71
+ queue?: string;
72
+ }>;
73
+ };
74
+ r2_buckets?: ReadonlyArray<{
75
+ binding?: string;
76
+ bucket_name?: string;
77
+ }>;
78
+ triggers?: {
79
+ crons?: ReadonlyArray<string>;
80
+ };
81
+ vars?: Readonly<Record<string, unknown>>;
82
+ }
83
+ /** What the translation could not carry over, so the caller can say so out loud. */
84
+ interface AlchemyTranslation {
85
+ /** The emitted program source. */
86
+ source: string;
87
+ /**
88
+ * Bindings present in `wrangler.jsonc` that this translation drops.
89
+ *
90
+ * Reported rather than silently omitted: a deploy that quietly loses a
91
+ * Vectorize index produces a worker whose `env.POSTS_SEARCH` is undefined
92
+ * at runtime, and nothing in the build says why.
93
+ */
94
+ unsupported: ReadonlyArray<string>;
95
+ }
96
+ /**
97
+ * Translate a parsed `wrangler.jsonc` into an Alchemy program.
98
+ *
99
+ * Pure: it reads nothing and writes nothing, so the caller decides where the
100
+ * source lands and the whole thing stays testable as a string comparison.
101
+ * @param config The parsed `wrangler.jsonc`.
102
+ * @returns the program source, plus whatever could not be carried over.
103
+ */
104
+ declare const wranglerToAlchemy: (config: WranglerConfigShape) => AlchemyTranslation;
105
+ /** Schema version of the emitted document, so a consumer can gate on shape changes. */
106
+ declare const BINDING_MANIFEST_VERSION = 1;
107
+ /**
108
+ * One resource the built Worker expects to be bound to. `binding` is the name the
109
+ * Worker reads off `env`; the remaining fields are whatever identifies the
110
+ * resource for that type, omitted when the config does not carry them (an id
111
+ * Lunora could not mint is absent here exactly as it is absent from the config).
112
+ */
113
+ interface BindingRequirement {
114
+ /** The `env` property name the Worker reads. */
115
+ binding: string;
116
+ /**
117
+ * Durable Object / Workflow / Container class the Worker must export. Present
118
+ * for the class-backed binding types, so a deployer can assert the bundle
119
+ * exports it before publishing.
120
+ */
121
+ className?: string;
122
+ /** Bucket name (`r2`), database name (`d1`), dataset (`analytics_engine`), queue name (`queue`), index (`vectorize`), pipeline (`pipelines`). */
123
+ resource?: string;
124
+ /** Remote resource id, when the config declares one (`d1`, `kv`, `hyperdrive`). */
125
+ resourceId?: string;
126
+ /** For `durable_object`: whether the class uses SQLite storage (`new_sqlite_classes`). */
127
+ sqlite?: boolean;
128
+ /** The kind of resource, keyed to the wrangler section it came from. */
129
+ type: "ai" | "analytics_engine" | "assets" | "browser" | "container" | "d1" | "durable_object" | "hyperdrive" | "images" | "kv" | "pipeline" | "queue_consumer" | "queue_producer" | "r2" | "vectorize" | "workflow";
130
+ }
131
+ /** The document the `lunora build --emit-bindings` flag writes. */
132
+ interface BindingManifest {
133
+ /** Every resource the Worker expects, sorted by `type` then `binding` so the file is diff-stable. */
134
+ bindings: ReadonlyArray<BindingRequirement>;
135
+ /** `compatibility_date`, when declared. */
136
+ compatibilityDate?: string;
137
+ /** `compatibility_flags`, when declared. */
138
+ compatibilityFlags?: ReadonlyArray<string>;
139
+ /** Cron expressions the Worker must be triggered on (`triggers.crons`). */
140
+ crons: ReadonlyArray<string>;
141
+ /** Worker name from `wrangler.jsonc`. */
142
+ name?: string;
143
+ /**
144
+ * Wrangler sections present in the config that this version does not model,
145
+ * by field name. Empty for a fully-understood config; non-empty is a prompt to
146
+ * extend the collector, and is surfaced to the user rather than silently
147
+ * dropped.
148
+ */
149
+ unknown: ReadonlyArray<string>;
150
+ /** Names of `vars` entries. Values are deliberately excluded — a manifest is committed and read by CI, and a `vars` entry can hold a value a project would rather not publish. */
151
+ vars: ReadonlyArray<string>;
152
+ /** Schema version — {@link BINDING_MANIFEST_VERSION}. */
153
+ version: number;
154
+ }
155
+ /**
156
+ * The wider config this reads. {@link WranglerConfigShape} covers what the
157
+ * Alchemy translation models; a manifest additionally reports the sections that
158
+ * translation lists as unsupported, so those are declared here.
159
+ */
160
+ interface ManifestConfigShape extends WranglerConfigShape {
161
+ ai?: {
162
+ binding?: string;
163
+ };
164
+ analytics_engine_datasets?: ReadonlyArray<{
165
+ binding?: string;
166
+ dataset?: string;
167
+ }>;
168
+ /** Static assets carry a real `binding` the Worker reads (`env.ASSETS`). */
169
+ assets?: {
170
+ binding?: string;
171
+ directory?: string;
172
+ };
173
+ browser?: {
174
+ binding?: string;
175
+ };
176
+ containers?: ReadonlyArray<{
177
+ class_name?: string;
178
+ image?: string;
179
+ max_instances?: number;
180
+ }>;
181
+ hyperdrive?: ReadonlyArray<{
182
+ binding?: string;
183
+ id?: string;
184
+ }>;
185
+ images?: {
186
+ binding?: string;
187
+ };
188
+ pipelines?: ReadonlyArray<{
189
+ binding?: string;
190
+ pipeline?: string;
191
+ }>;
192
+ /** Adds `consumers` — the Alchemy translation models producers only. */
193
+ queues?: {
194
+ consumers?: ReadonlyArray<{
195
+ queue?: string;
196
+ }>;
197
+ producers?: ReadonlyArray<{
198
+ binding?: string;
199
+ queue?: string;
200
+ }>;
201
+ };
202
+ vectorize?: ReadonlyArray<{
203
+ binding?: string;
204
+ index_name?: string;
205
+ }>;
206
+ workflows?: ReadonlyArray<{
207
+ binding?: string;
208
+ class_name?: string;
209
+ name?: string;
210
+ }>;
211
+ }
212
+ /**
213
+ * Build the manifest for a parsed `wrangler.jsonc`.
214
+ *
215
+ * Pure: reads nothing and writes nothing, so the caller decides where the
216
+ * document lands and the mapping stays testable as a plain object comparison.
217
+ * @param config The parsed, already-reconciled `wrangler.jsonc`.
218
+ * @returns the requirements document.
219
+ */
220
+ declare const buildBindingManifest: (config: ManifestConfigShape) => BindingManifest;
3
221
  /** The Cloudflare deploy driver. */
4
222
  declare const CLOUDFLARE_DRIVER: DeployDriver;
5
223
  /**
@@ -333,108 +551,6 @@ declare const scanWranglerVariablesForSecrets: (variables: Record<string, unknow
333
551
  * per-environment `env.&lt;name>.vars` overrides are out of scope for now.
334
552
  */
335
553
  declare const collectWranglerSecretVariables: (projectRoot: string) => WranglerVariableIR[];
336
- /**
337
- * Translate a `wrangler.jsonc` into an [Alchemy](https://alchemy.run) program.
338
- *
339
- * # Why translate rather than ask for a second config
340
- *
341
- * `wrangler.jsonc` is already the source of truth for what an app needs, and
342
- * Lunora already infers and reconciles it — `inferLunoraBindings` decides that
343
- * a project needs a shard namespace and a bucket, `reconcileWranglerBindings`
344
- * writes them. Asking a developer to restate all of that in an
345
- * `alchemy.run.ts` would give the project two sources of truth that drift, and
346
- * the drift would surface as a deploy that provisions something the app does
347
- * not bind.
348
- *
349
- * So Alchemy is an implementation detail of `deploy`, not a thing to configure:
350
- * read the config, emit the program, run it.
351
- *
352
- * # Why this emits source rather than calling Alchemy
353
- *
354
- * `alchemy@0.93` has thirty dependencies, nine of them Node-shaped —
355
- * `wrangler`, `miniflare`, `esbuild`, `execa`, `find-process`, `glob`, `open`,
356
- * `proper-lockfile`, `signal-exit`. `@lunora/config` is imported by
357
- * `@lunora/vite`, so importing Alchemy here would push that tree into every
358
- * project that merely wanted to read `lunora.json`, and into any bundle
359
- * targeting workerd — where none of it survives.
360
- *
361
- * Emitting text keeps this module pure and dependency-free. Alchemy is invoked
362
- * as a CLI against the generated file, so it only has to exist on the machine
363
- * that deploys.
364
- *
365
- * # Adoption, not re-creation
366
- *
367
- * Every resource is emitted with `adopt: true`. A project translated from an
368
- * existing `wrangler.jsonc` already *has* its D1 database and its bucket, with
369
- * data in them. Without adoption Alchemy would treat them as new and try to
370
- * create alongside — the one outcome a deploy must never have.
371
- */
372
- /** A Durable Object binding as `wrangler.jsonc` spells it. */
373
- interface WranglerDurableObjectBinding$1 {
374
- class_name?: string;
375
- name?: string;
376
- script_name?: string;
377
- }
378
- /** The slice of `wrangler.jsonc` that translates into Alchemy resources. */
379
- interface WranglerConfigShape {
380
- compatibility_date?: string;
381
- compatibility_flags?: ReadonlyArray<string>;
382
- d1_databases?: ReadonlyArray<{
383
- binding?: string;
384
- database_id?: string;
385
- database_name?: string;
386
- }>;
387
- durable_objects?: {
388
- bindings?: ReadonlyArray<WranglerDurableObjectBinding$1>;
389
- };
390
- kv_namespaces?: ReadonlyArray<{
391
- binding?: string;
392
- id?: string;
393
- }>;
394
- main?: string;
395
- /** `new_sqlite_classes` marks which DO classes get SQLite storage — Alchemy needs that per namespace. */
396
- migrations?: ReadonlyArray<{
397
- new_classes?: ReadonlyArray<string>;
398
- new_sqlite_classes?: ReadonlyArray<string>;
399
- }>;
400
- name?: string;
401
- queues?: {
402
- producers?: ReadonlyArray<{
403
- binding?: string;
404
- queue?: string;
405
- }>;
406
- };
407
- r2_buckets?: ReadonlyArray<{
408
- binding?: string;
409
- bucket_name?: string;
410
- }>;
411
- triggers?: {
412
- crons?: ReadonlyArray<string>;
413
- };
414
- vars?: Readonly<Record<string, unknown>>;
415
- }
416
- /** What the translation could not carry over, so the caller can say so out loud. */
417
- interface AlchemyTranslation {
418
- /** The emitted program source. */
419
- source: string;
420
- /**
421
- * Bindings present in `wrangler.jsonc` that this translation drops.
422
- *
423
- * Reported rather than silently omitted: a deploy that quietly loses a
424
- * Vectorize index produces a worker whose `env.POSTS_SEARCH` is undefined
425
- * at runtime, and nothing in the build says why.
426
- */
427
- unsupported: ReadonlyArray<string>;
428
- }
429
- /**
430
- * Translate a parsed `wrangler.jsonc` into an Alchemy program.
431
- *
432
- * Pure: it reads nothing and writes nothing, so the caller decides where the
433
- * source lands and the whole thing stays testable as a string comparison.
434
- * @param config The parsed `wrangler.jsonc`.
435
- * @returns the program source, plus whatever could not be carried over.
436
- */
437
- declare const wranglerToAlchemy: (config: WranglerConfigShape) => AlchemyTranslation;
438
554
  declare const REQUIRED_COMPATIBILITY_DATE: string;
439
555
  declare const REQUIRED_FLAG: string;
440
556
  interface WranglerDurableObjectBinding {
@@ -658,4 +774,4 @@ interface WranglerProjectValidationResult {
658
774
  * `{ problems, wranglerPath }` shape plus the structured `report`.
659
775
  */
660
776
  declare const validateWranglerProject: (options: WranglerProjectValidationOptions) => WranglerProjectValidationResult;
661
- export { type AlchemyTranslation, CLOUDFLARE_DRIVER, type ExportGap, type MaterializeOptions, type MaterializeResult, REMOTE_ELIGIBLE_KEYS, REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, type ReadWranglerResult, type ReconcileBindingsResult, type ReconcileCompatibilityDateResult, type ReconcileResult as ReconcileCronsResult, type RemoteBindingPlan, type RemoteEnableInputs, type RemoteWranglerShape, type TailConsumer, WORKERS_CACHE_MIN_DATE, WRANGLER_FILES, type WranglerCacheShape, type WranglerConfig, type WranglerConfigShape, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, collectWranglerSecretVariables, findWranglerFile, injectRemoteFlags, isCacheEnabled, isRemoteEnvEnabled, materializeRemoteWranglerConfig, planRemoteBindings, readWranglerJsonc, reconcileWranglerBindings, reconcileWranglerCompatibilityDate, reconcileWranglerCrons, resolveRemoteEnabled, scanWranglerVariablesForSecrets, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, wranglerToAlchemy };
777
+ export { type AlchemyTranslation, BINDING_MANIFEST_VERSION, type BindingManifest, type BindingRequirement, CLOUDFLARE_DRIVER, type ExportGap, type ManifestConfigShape, type MaterializeOptions, type MaterializeResult, REMOTE_ELIGIBLE_KEYS, REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, type ReadWranglerResult, type ReconcileBindingsResult, type ReconcileCompatibilityDateResult, type ReconcileResult as ReconcileCronsResult, type RemoteBindingPlan, type RemoteEnableInputs, type RemoteWranglerShape, type TailConsumer, WORKERS_CACHE_MIN_DATE, WRANGLER_FILES, type WranglerCacheShape, type WranglerConfig, type WranglerConfigShape, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, buildBindingManifest, collectWranglerSecretVariables, findWranglerFile, injectRemoteFlags, isCacheEnabled, isRemoteEnvEnabled, materializeRemoteWranglerConfig, planRemoteBindings, readWranglerJsonc, reconcileWranglerBindings, reconcileWranglerCompatibilityDate, reconcileWranglerCrons, resolveRemoteEnabled, scanWranglerVariablesForSecrets, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, wranglerToAlchemy };
@@ -1,5 +1,223 @@
1
1
  import { D as DeployDriver, I as InferredBindings, S as SchemaInfo } from "../packem_shared/schema-info.d-DS0bUsWE.js";
2
2
  import { WranglerVariableIR } from '@lunora/codegen';
3
+ /**
4
+ * Translate a `wrangler.jsonc` into an [Alchemy](https://alchemy.run) program.
5
+ *
6
+ * # Why translate rather than ask for a second config
7
+ *
8
+ * `wrangler.jsonc` is already the source of truth for what an app needs, and
9
+ * Lunora already infers and reconciles it — `inferLunoraBindings` decides that
10
+ * a project needs a shard namespace and a bucket, `reconcileWranglerBindings`
11
+ * writes them. Asking a developer to restate all of that in an
12
+ * `alchemy.run.ts` would give the project two sources of truth that drift, and
13
+ * the drift would surface as a deploy that provisions something the app does
14
+ * not bind.
15
+ *
16
+ * So Alchemy is an implementation detail of `deploy`, not a thing to configure:
17
+ * read the config, emit the program, run it.
18
+ *
19
+ * # Why this emits source rather than calling Alchemy
20
+ *
21
+ * `alchemy@0.93` has thirty dependencies, nine of them Node-shaped —
22
+ * `wrangler`, `miniflare`, `esbuild`, `execa`, `find-process`, `glob`, `open`,
23
+ * `proper-lockfile`, `signal-exit`. `@lunora/config` is imported by
24
+ * `@lunora/vite`, so importing Alchemy here would push that tree into every
25
+ * project that merely wanted to read `lunora.json`, and into any bundle
26
+ * targeting workerd — where none of it survives.
27
+ *
28
+ * Emitting text keeps this module pure and dependency-free. Alchemy is invoked
29
+ * as a CLI against the generated file, so it only has to exist on the machine
30
+ * that deploys.
31
+ *
32
+ * # Adoption, not re-creation
33
+ *
34
+ * Every resource is emitted with `adopt: true`. A project translated from an
35
+ * existing `wrangler.jsonc` already *has* its D1 database and its bucket, with
36
+ * data in them. Without adoption Alchemy would treat them as new and try to
37
+ * create alongside — the one outcome a deploy must never have.
38
+ */
39
+ /** A Durable Object binding as `wrangler.jsonc` spells it. */
40
+ interface WranglerDurableObjectBinding$1 {
41
+ class_name?: string;
42
+ name?: string;
43
+ script_name?: string;
44
+ }
45
+ /** The slice of `wrangler.jsonc` that translates into Alchemy resources. */
46
+ interface WranglerConfigShape {
47
+ compatibility_date?: string;
48
+ compatibility_flags?: ReadonlyArray<string>;
49
+ d1_databases?: ReadonlyArray<{
50
+ binding?: string;
51
+ database_id?: string;
52
+ database_name?: string;
53
+ }>;
54
+ durable_objects?: {
55
+ bindings?: ReadonlyArray<WranglerDurableObjectBinding$1>;
56
+ };
57
+ kv_namespaces?: ReadonlyArray<{
58
+ binding?: string;
59
+ id?: string;
60
+ }>;
61
+ main?: string;
62
+ /** `new_sqlite_classes` marks which DO classes get SQLite storage — Alchemy needs that per namespace. */
63
+ migrations?: ReadonlyArray<{
64
+ new_classes?: ReadonlyArray<string>;
65
+ new_sqlite_classes?: ReadonlyArray<string>;
66
+ }>;
67
+ name?: string;
68
+ queues?: {
69
+ producers?: ReadonlyArray<{
70
+ binding?: string;
71
+ queue?: string;
72
+ }>;
73
+ };
74
+ r2_buckets?: ReadonlyArray<{
75
+ binding?: string;
76
+ bucket_name?: string;
77
+ }>;
78
+ triggers?: {
79
+ crons?: ReadonlyArray<string>;
80
+ };
81
+ vars?: Readonly<Record<string, unknown>>;
82
+ }
83
+ /** What the translation could not carry over, so the caller can say so out loud. */
84
+ interface AlchemyTranslation {
85
+ /** The emitted program source. */
86
+ source: string;
87
+ /**
88
+ * Bindings present in `wrangler.jsonc` that this translation drops.
89
+ *
90
+ * Reported rather than silently omitted: a deploy that quietly loses a
91
+ * Vectorize index produces a worker whose `env.POSTS_SEARCH` is undefined
92
+ * at runtime, and nothing in the build says why.
93
+ */
94
+ unsupported: ReadonlyArray<string>;
95
+ }
96
+ /**
97
+ * Translate a parsed `wrangler.jsonc` into an Alchemy program.
98
+ *
99
+ * Pure: it reads nothing and writes nothing, so the caller decides where the
100
+ * source lands and the whole thing stays testable as a string comparison.
101
+ * @param config The parsed `wrangler.jsonc`.
102
+ * @returns the program source, plus whatever could not be carried over.
103
+ */
104
+ declare const wranglerToAlchemy: (config: WranglerConfigShape) => AlchemyTranslation;
105
+ /** Schema version of the emitted document, so a consumer can gate on shape changes. */
106
+ declare const BINDING_MANIFEST_VERSION = 1;
107
+ /**
108
+ * One resource the built Worker expects to be bound to. `binding` is the name the
109
+ * Worker reads off `env`; the remaining fields are whatever identifies the
110
+ * resource for that type, omitted when the config does not carry them (an id
111
+ * Lunora could not mint is absent here exactly as it is absent from the config).
112
+ */
113
+ interface BindingRequirement {
114
+ /** The `env` property name the Worker reads. */
115
+ binding: string;
116
+ /**
117
+ * Durable Object / Workflow / Container class the Worker must export. Present
118
+ * for the class-backed binding types, so a deployer can assert the bundle
119
+ * exports it before publishing.
120
+ */
121
+ className?: string;
122
+ /** Bucket name (`r2`), database name (`d1`), dataset (`analytics_engine`), queue name (`queue`), index (`vectorize`), pipeline (`pipelines`). */
123
+ resource?: string;
124
+ /** Remote resource id, when the config declares one (`d1`, `kv`, `hyperdrive`). */
125
+ resourceId?: string;
126
+ /** For `durable_object`: whether the class uses SQLite storage (`new_sqlite_classes`). */
127
+ sqlite?: boolean;
128
+ /** The kind of resource, keyed to the wrangler section it came from. */
129
+ type: "ai" | "analytics_engine" | "assets" | "browser" | "container" | "d1" | "durable_object" | "hyperdrive" | "images" | "kv" | "pipeline" | "queue_consumer" | "queue_producer" | "r2" | "vectorize" | "workflow";
130
+ }
131
+ /** The document the `lunora build --emit-bindings` flag writes. */
132
+ interface BindingManifest {
133
+ /** Every resource the Worker expects, sorted by `type` then `binding` so the file is diff-stable. */
134
+ bindings: ReadonlyArray<BindingRequirement>;
135
+ /** `compatibility_date`, when declared. */
136
+ compatibilityDate?: string;
137
+ /** `compatibility_flags`, when declared. */
138
+ compatibilityFlags?: ReadonlyArray<string>;
139
+ /** Cron expressions the Worker must be triggered on (`triggers.crons`). */
140
+ crons: ReadonlyArray<string>;
141
+ /** Worker name from `wrangler.jsonc`. */
142
+ name?: string;
143
+ /**
144
+ * Wrangler sections present in the config that this version does not model,
145
+ * by field name. Empty for a fully-understood config; non-empty is a prompt to
146
+ * extend the collector, and is surfaced to the user rather than silently
147
+ * dropped.
148
+ */
149
+ unknown: ReadonlyArray<string>;
150
+ /** Names of `vars` entries. Values are deliberately excluded — a manifest is committed and read by CI, and a `vars` entry can hold a value a project would rather not publish. */
151
+ vars: ReadonlyArray<string>;
152
+ /** Schema version — {@link BINDING_MANIFEST_VERSION}. */
153
+ version: number;
154
+ }
155
+ /**
156
+ * The wider config this reads. {@link WranglerConfigShape} covers what the
157
+ * Alchemy translation models; a manifest additionally reports the sections that
158
+ * translation lists as unsupported, so those are declared here.
159
+ */
160
+ interface ManifestConfigShape extends WranglerConfigShape {
161
+ ai?: {
162
+ binding?: string;
163
+ };
164
+ analytics_engine_datasets?: ReadonlyArray<{
165
+ binding?: string;
166
+ dataset?: string;
167
+ }>;
168
+ /** Static assets carry a real `binding` the Worker reads (`env.ASSETS`). */
169
+ assets?: {
170
+ binding?: string;
171
+ directory?: string;
172
+ };
173
+ browser?: {
174
+ binding?: string;
175
+ };
176
+ containers?: ReadonlyArray<{
177
+ class_name?: string;
178
+ image?: string;
179
+ max_instances?: number;
180
+ }>;
181
+ hyperdrive?: ReadonlyArray<{
182
+ binding?: string;
183
+ id?: string;
184
+ }>;
185
+ images?: {
186
+ binding?: string;
187
+ };
188
+ pipelines?: ReadonlyArray<{
189
+ binding?: string;
190
+ pipeline?: string;
191
+ }>;
192
+ /** Adds `consumers` — the Alchemy translation models producers only. */
193
+ queues?: {
194
+ consumers?: ReadonlyArray<{
195
+ queue?: string;
196
+ }>;
197
+ producers?: ReadonlyArray<{
198
+ binding?: string;
199
+ queue?: string;
200
+ }>;
201
+ };
202
+ vectorize?: ReadonlyArray<{
203
+ binding?: string;
204
+ index_name?: string;
205
+ }>;
206
+ workflows?: ReadonlyArray<{
207
+ binding?: string;
208
+ class_name?: string;
209
+ name?: string;
210
+ }>;
211
+ }
212
+ /**
213
+ * Build the manifest for a parsed `wrangler.jsonc`.
214
+ *
215
+ * Pure: reads nothing and writes nothing, so the caller decides where the
216
+ * document lands and the mapping stays testable as a plain object comparison.
217
+ * @param config The parsed, already-reconciled `wrangler.jsonc`.
218
+ * @returns the requirements document.
219
+ */
220
+ declare const buildBindingManifest: (config: ManifestConfigShape) => BindingManifest;
3
221
  /** The Cloudflare deploy driver. */
4
222
  declare const CLOUDFLARE_DRIVER: DeployDriver;
5
223
  /**
@@ -333,108 +551,6 @@ declare const scanWranglerVariablesForSecrets: (variables: Record<string, unknow
333
551
  * per-environment `env.&lt;name>.vars` overrides are out of scope for now.
334
552
  */
335
553
  declare const collectWranglerSecretVariables: (projectRoot: string) => WranglerVariableIR[];
336
- /**
337
- * Translate a `wrangler.jsonc` into an [Alchemy](https://alchemy.run) program.
338
- *
339
- * # Why translate rather than ask for a second config
340
- *
341
- * `wrangler.jsonc` is already the source of truth for what an app needs, and
342
- * Lunora already infers and reconciles it — `inferLunoraBindings` decides that
343
- * a project needs a shard namespace and a bucket, `reconcileWranglerBindings`
344
- * writes them. Asking a developer to restate all of that in an
345
- * `alchemy.run.ts` would give the project two sources of truth that drift, and
346
- * the drift would surface as a deploy that provisions something the app does
347
- * not bind.
348
- *
349
- * So Alchemy is an implementation detail of `deploy`, not a thing to configure:
350
- * read the config, emit the program, run it.
351
- *
352
- * # Why this emits source rather than calling Alchemy
353
- *
354
- * `alchemy@0.93` has thirty dependencies, nine of them Node-shaped —
355
- * `wrangler`, `miniflare`, `esbuild`, `execa`, `find-process`, `glob`, `open`,
356
- * `proper-lockfile`, `signal-exit`. `@lunora/config` is imported by
357
- * `@lunora/vite`, so importing Alchemy here would push that tree into every
358
- * project that merely wanted to read `lunora.json`, and into any bundle
359
- * targeting workerd — where none of it survives.
360
- *
361
- * Emitting text keeps this module pure and dependency-free. Alchemy is invoked
362
- * as a CLI against the generated file, so it only has to exist on the machine
363
- * that deploys.
364
- *
365
- * # Adoption, not re-creation
366
- *
367
- * Every resource is emitted with `adopt: true`. A project translated from an
368
- * existing `wrangler.jsonc` already *has* its D1 database and its bucket, with
369
- * data in them. Without adoption Alchemy would treat them as new and try to
370
- * create alongside — the one outcome a deploy must never have.
371
- */
372
- /** A Durable Object binding as `wrangler.jsonc` spells it. */
373
- interface WranglerDurableObjectBinding$1 {
374
- class_name?: string;
375
- name?: string;
376
- script_name?: string;
377
- }
378
- /** The slice of `wrangler.jsonc` that translates into Alchemy resources. */
379
- interface WranglerConfigShape {
380
- compatibility_date?: string;
381
- compatibility_flags?: ReadonlyArray<string>;
382
- d1_databases?: ReadonlyArray<{
383
- binding?: string;
384
- database_id?: string;
385
- database_name?: string;
386
- }>;
387
- durable_objects?: {
388
- bindings?: ReadonlyArray<WranglerDurableObjectBinding$1>;
389
- };
390
- kv_namespaces?: ReadonlyArray<{
391
- binding?: string;
392
- id?: string;
393
- }>;
394
- main?: string;
395
- /** `new_sqlite_classes` marks which DO classes get SQLite storage — Alchemy needs that per namespace. */
396
- migrations?: ReadonlyArray<{
397
- new_classes?: ReadonlyArray<string>;
398
- new_sqlite_classes?: ReadonlyArray<string>;
399
- }>;
400
- name?: string;
401
- queues?: {
402
- producers?: ReadonlyArray<{
403
- binding?: string;
404
- queue?: string;
405
- }>;
406
- };
407
- r2_buckets?: ReadonlyArray<{
408
- binding?: string;
409
- bucket_name?: string;
410
- }>;
411
- triggers?: {
412
- crons?: ReadonlyArray<string>;
413
- };
414
- vars?: Readonly<Record<string, unknown>>;
415
- }
416
- /** What the translation could not carry over, so the caller can say so out loud. */
417
- interface AlchemyTranslation {
418
- /** The emitted program source. */
419
- source: string;
420
- /**
421
- * Bindings present in `wrangler.jsonc` that this translation drops.
422
- *
423
- * Reported rather than silently omitted: a deploy that quietly loses a
424
- * Vectorize index produces a worker whose `env.POSTS_SEARCH` is undefined
425
- * at runtime, and nothing in the build says why.
426
- */
427
- unsupported: ReadonlyArray<string>;
428
- }
429
- /**
430
- * Translate a parsed `wrangler.jsonc` into an Alchemy program.
431
- *
432
- * Pure: it reads nothing and writes nothing, so the caller decides where the
433
- * source lands and the whole thing stays testable as a string comparison.
434
- * @param config The parsed `wrangler.jsonc`.
435
- * @returns the program source, plus whatever could not be carried over.
436
- */
437
- declare const wranglerToAlchemy: (config: WranglerConfigShape) => AlchemyTranslation;
438
554
  declare const REQUIRED_COMPATIBILITY_DATE: string;
439
555
  declare const REQUIRED_FLAG: string;
440
556
  interface WranglerDurableObjectBinding {
@@ -658,4 +774,4 @@ interface WranglerProjectValidationResult {
658
774
  * `{ problems, wranglerPath }` shape plus the structured `report`.
659
775
  */
660
776
  declare const validateWranglerProject: (options: WranglerProjectValidationOptions) => WranglerProjectValidationResult;
661
- export { type AlchemyTranslation, CLOUDFLARE_DRIVER, type ExportGap, type MaterializeOptions, type MaterializeResult, REMOTE_ELIGIBLE_KEYS, REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, type ReadWranglerResult, type ReconcileBindingsResult, type ReconcileCompatibilityDateResult, type ReconcileResult as ReconcileCronsResult, type RemoteBindingPlan, type RemoteEnableInputs, type RemoteWranglerShape, type TailConsumer, WORKERS_CACHE_MIN_DATE, WRANGLER_FILES, type WranglerCacheShape, type WranglerConfig, type WranglerConfigShape, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, collectWranglerSecretVariables, findWranglerFile, injectRemoteFlags, isCacheEnabled, isRemoteEnvEnabled, materializeRemoteWranglerConfig, planRemoteBindings, readWranglerJsonc, reconcileWranglerBindings, reconcileWranglerCompatibilityDate, reconcileWranglerCrons, resolveRemoteEnabled, scanWranglerVariablesForSecrets, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, wranglerToAlchemy };
777
+ export { type AlchemyTranslation, BINDING_MANIFEST_VERSION, type BindingManifest, type BindingRequirement, CLOUDFLARE_DRIVER, type ExportGap, type ManifestConfigShape, type MaterializeOptions, type MaterializeResult, REMOTE_ELIGIBLE_KEYS, REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, type ReadWranglerResult, type ReconcileBindingsResult, type ReconcileCompatibilityDateResult, type ReconcileResult as ReconcileCronsResult, type RemoteBindingPlan, type RemoteEnableInputs, type RemoteWranglerShape, type TailConsumer, WORKERS_CACHE_MIN_DATE, WRANGLER_FILES, type WranglerCacheShape, type WranglerConfig, type WranglerConfigShape, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, buildBindingManifest, collectWranglerSecretVariables, findWranglerFile, injectRemoteFlags, isCacheEnabled, isRemoteEnvEnabled, materializeRemoteWranglerConfig, planRemoteBindings, readWranglerJsonc, reconcileWranglerBindings, reconcileWranglerCompatibilityDate, reconcileWranglerCrons, resolveRemoteEnabled, scanWranglerVariablesForSecrets, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, wranglerToAlchemy };
@@ -1 +1 @@
1
- import{default as o}from"../packem_shared/CLOUDFLARE_DRIVER-DS7cF7Cl.mjs";import{reconcileWranglerBindings as l}from"../packem_shared/reconcileWranglerBindings-BCwTpuLO.mjs";import{reconcileWranglerCompatibilityDate as t}from"../packem_shared/reconcileWranglerCompatibilityDate-BXNiEQ7p.mjs";import{reconcileWranglerCrons as E}from"../packem_shared/reconcileWranglerCrons-BmQa_kGL.mjs";import{REMOTE_ELIGIBLE_KEYS as g,injectRemoteFlags as R,isRemoteEnvEnabled as c,materializeRemoteWranglerConfig as f,planRemoteBindings as s,resolveRemoteEnabled as W}from"../packem_shared/REMOTE_ELIGIBLE_KEYS-ws6iE0y-.mjs";import{WORKERS_CACHE_MIN_DATE as d,isCacheEnabled as x}from"../packem_shared/WORKERS_CACHE_MIN_DATE-B1h_wNDN.mjs";import{WRANGLER_FILES as I,findWranglerFile as _,readWranglerJsonc as A}from"../packem_shared/WRANGLER_FILES-Bi_18Pj6.mjs";import{collectWranglerSecretVariables as D,scanWranglerVariablesForSecrets as T}from"../packem_shared/collectWranglerSecretVariables-jPUxMC9j.mjs";import{wranglerToAlchemy as F}from"../packem_shared/wranglerToAlchemy-Fh5KfTPB.mjs";import{REQUIRED_COMPATIBILITY_DATE as S,REQUIRED_FLAG as B,validateWrangler as O,validateWranglerConfig as h,validateWranglerProject as G,withTailConsumer as M}from"../packem_shared/REQUIRED_COMPATIBILITY_DATE-BwmyesjD.mjs";export{o as CLOUDFLARE_DRIVER,g as REMOTE_ELIGIBLE_KEYS,S as REQUIRED_COMPATIBILITY_DATE,B as REQUIRED_FLAG,d as WORKERS_CACHE_MIN_DATE,I as WRANGLER_FILES,D as collectWranglerSecretVariables,_ as findWranglerFile,R as injectRemoteFlags,x as isCacheEnabled,c as isRemoteEnvEnabled,f as materializeRemoteWranglerConfig,s as planRemoteBindings,A as readWranglerJsonc,l as reconcileWranglerBindings,t as reconcileWranglerCompatibilityDate,E as reconcileWranglerCrons,W as resolveRemoteEnabled,T as scanWranglerVariablesForSecrets,O as validateWrangler,h as validateWranglerConfig,G as validateWranglerProject,M as withTailConsumer,F as wranglerToAlchemy};
1
+ import{BINDING_MANIFEST_VERSION as o,buildBindingManifest as a}from"../packem_shared/BINDING_MANIFEST_VERSION-BNab7wQ-.mjs";import{default as n}from"../packem_shared/CLOUDFLARE_DRIVER-DS7cF7Cl.mjs";import{reconcileWranglerBindings as i}from"../packem_shared/reconcileWranglerBindings-BCwTpuLO.mjs";import{reconcileWranglerCompatibilityDate as m}from"../packem_shared/reconcileWranglerCompatibilityDate-BXNiEQ7p.mjs";import{reconcileWranglerCrons as R}from"../packem_shared/reconcileWranglerCrons-BmQa_kGL.mjs";import{REMOTE_ELIGIBLE_KEYS as f,injectRemoteFlags as s,isRemoteEnvEnabled as I,materializeRemoteWranglerConfig as d,planRemoteBindings as p,resolveRemoteEnabled as W}from"../packem_shared/REMOTE_ELIGIBLE_KEYS-ws6iE0y-.mjs";import{WORKERS_CACHE_MIN_DATE as x,isCacheEnabled as C}from"../packem_shared/WORKERS_CACHE_MIN_DATE-B1h_wNDN.mjs";import{WRANGLER_FILES as D,findWranglerFile as L,readWranglerJsonc as T}from"../packem_shared/WRANGLER_FILES-Bi_18Pj6.mjs";import{collectWranglerSecretVariables as F,scanWranglerVariablesForSecrets as S}from"../packem_shared/collectWranglerSecretVariables-jPUxMC9j.mjs";import{wranglerToAlchemy as N}from"../packem_shared/wranglerToAlchemy-Fh5KfTPB.mjs";import{REQUIRED_COMPATIBILITY_DATE as M,REQUIRED_FLAG as O,validateWrangler as G,validateWranglerConfig as V,validateWranglerProject as h,withTailConsumer as u}from"../packem_shared/REQUIRED_COMPATIBILITY_DATE-BwmyesjD.mjs";export{o as BINDING_MANIFEST_VERSION,n as CLOUDFLARE_DRIVER,f as REMOTE_ELIGIBLE_KEYS,M as REQUIRED_COMPATIBILITY_DATE,O as REQUIRED_FLAG,x as WORKERS_CACHE_MIN_DATE,D as WRANGLER_FILES,a as buildBindingManifest,F as collectWranglerSecretVariables,L as findWranglerFile,s as injectRemoteFlags,C as isCacheEnabled,I as isRemoteEnvEnabled,d as materializeRemoteWranglerConfig,p as planRemoteBindings,T as readWranglerJsonc,i as reconcileWranglerBindings,m as reconcileWranglerCompatibilityDate,R as reconcileWranglerCrons,W as resolveRemoteEnabled,S as scanWranglerVariablesForSecrets,G as validateWrangler,V as validateWranglerConfig,h as validateWranglerProject,u as withTailConsumer,N as wranglerToAlchemy};
package/dist/index.d.mts CHANGED
@@ -422,6 +422,56 @@ declare const readLinkedProject: (projectRoot: string) => LinkedProject | undefi
422
422
  * never clobbers a known one). Returns the absolute path written.
423
423
  */
424
424
  declare const writeLinkedProject: (projectRoot: string, link: LinkedProject) => string;
425
+ /**
426
+ * The generated and derived paths a linter or formatter should skip, in
427
+ * gitignore syntax relative to the project root.
428
+ *
429
+ * Committed-on-purpose entries are in here too, deliberately: being tracked by
430
+ * git says nothing about whether a human should be asked to reformat it.
431
+ */
432
+ declare const LUNORA_IGNORED_PATHS: ReadonlyArray<string>;
433
+ /** A linter or formatter this module knows how to configure. */
434
+ type LintTool = "biome" | "eslint" | "oxlint" | "prettier";
435
+ /**
436
+ * What happened to one tool's configuration.
437
+ *
438
+ * `"manual"` is not a failure — it means the change is correct but not safe to
439
+ * make automatically, and {@link LintIgnoreOutcome.snippet} carries what to
440
+ * paste. `"failed"` IS a failure, but only of this step: the command that
441
+ * triggered it had already done its real work, so it is reported rather than
442
+ * thrown.
443
+ */
444
+ type LintIgnoreStatus = "created" | "failed" | "manual" | "unchanged" | "updated";
445
+ interface LintIgnoreOutcome {
446
+ /** For `"failed"`: why the writer could not run. The command itself still succeeded. */
447
+ message?: string;
448
+ /** Config file that was written, or the one the user must edit for `"manual"`. */
449
+ path: string;
450
+ /** For `"manual"`: the exact text to add. */
451
+ snippet?: string;
452
+ status: LintIgnoreStatus;
453
+ tool: LintTool;
454
+ }
455
+ /**
456
+ * Which linters/formatters this project already uses, by declared dependency or
457
+ * config file on disk.
458
+ *
459
+ * Both signals matter: a dependency without a config is a tool about to be
460
+ * configured, and a config without a dependency is a tool installed globally or
461
+ * hoisted from a monorepo root. Missing either one means silently skipping a
462
+ * tool the project genuinely runs.
463
+ */
464
+ declare const detectLintTools: (projectRoot: string) => LintTool[];
465
+ /**
466
+ * Add {@link LUNORA_IGNORED_PATHS} to each tool's configuration.
467
+ *
468
+ * Idempotent: every writer appends only what is missing, so re-running after a
469
+ * `lunora add` neither duplicates entries nor disturbs a project's own rules.
470
+ * @param projectRoot The project to configure.
471
+ * @param tools Which tools to configure — normally {@link detectLintTools}'s result, or the user's selection at `init`.
472
+ * @returns one outcome per tool, in the order given.
473
+ */
474
+ declare const applyLintIgnores: (projectRoot: string, tools: ReadonlyArray<LintTool>) => LintIgnoreOutcome[];
425
475
  /** Severity a formatted line should be surfaced at, mapped onto the three logger channels. */
426
476
  type LunoraLineLevel = "error" | "info" | "warn";
427
477
  /** A formatted lunora event: the channel to surface it on, the display text, and which event produced it. */
@@ -1002,4 +1052,4 @@ declare const badgeWidth: (_spec: BadgeSpec) => number;
1002
1052
  declare const paintBadge: (spec: BadgeSpec) => string;
1003
1053
  /** Dim continuation text (a step's chosen answer, shown under the question). */
1004
1054
  declare const paintAnswer: (text: string) => string;
1005
- 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, DEFAULT_DEPLOY_TARGET, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DeployDriver, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, 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 MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type ParseSchemaResult, ROOT_SKILL_NAME, type RemotePreference, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, applyAdditiveEdit, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, createConfirm, deployTargetIds, detectAgentRules, detectAiAgent, detectFramework, discoverAgentInfo, discoverContainerInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, escapeRegExp, fillDevSecrets, formatLunoraEvent, generateSecretValue, interpretRemote, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readProjectTarget, requiredSecrets, resolveDeployDriver, resolveProjectTarget, resolveTargetOrThrow, secretsForPackages, streamContainerLogs, updateDevServerState, upsertDevVariableLine, writeDevServerState, writeDevVariablesFileAtomically, writeLinkedProject };
1055
+ 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, DEFAULT_DEPLOY_TARGET, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DeployDriver, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_IGNORED_PATHS, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LintIgnoreOutcome, type LintIgnoreStatus, type LintTool, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type ParseSchemaResult, ROOT_SKILL_NAME, type RemotePreference, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, applyAdditiveEdit, applyLintIgnores, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, createConfirm, deployTargetIds, detectAgentRules, detectAiAgent, detectFramework, detectLintTools, discoverAgentInfo, discoverContainerInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, escapeRegExp, fillDevSecrets, formatLunoraEvent, generateSecretValue, interpretRemote, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readProjectTarget, requiredSecrets, resolveDeployDriver, resolveProjectTarget, resolveTargetOrThrow, secretsForPackages, streamContainerLogs, updateDevServerState, upsertDevVariableLine, writeDevServerState, writeDevVariablesFileAtomically, writeLinkedProject };
package/dist/index.d.ts CHANGED
@@ -422,6 +422,56 @@ declare const readLinkedProject: (projectRoot: string) => LinkedProject | undefi
422
422
  * never clobbers a known one). Returns the absolute path written.
423
423
  */
424
424
  declare const writeLinkedProject: (projectRoot: string, link: LinkedProject) => string;
425
+ /**
426
+ * The generated and derived paths a linter or formatter should skip, in
427
+ * gitignore syntax relative to the project root.
428
+ *
429
+ * Committed-on-purpose entries are in here too, deliberately: being tracked by
430
+ * git says nothing about whether a human should be asked to reformat it.
431
+ */
432
+ declare const LUNORA_IGNORED_PATHS: ReadonlyArray<string>;
433
+ /** A linter or formatter this module knows how to configure. */
434
+ type LintTool = "biome" | "eslint" | "oxlint" | "prettier";
435
+ /**
436
+ * What happened to one tool's configuration.
437
+ *
438
+ * `"manual"` is not a failure — it means the change is correct but not safe to
439
+ * make automatically, and {@link LintIgnoreOutcome.snippet} carries what to
440
+ * paste. `"failed"` IS a failure, but only of this step: the command that
441
+ * triggered it had already done its real work, so it is reported rather than
442
+ * thrown.
443
+ */
444
+ type LintIgnoreStatus = "created" | "failed" | "manual" | "unchanged" | "updated";
445
+ interface LintIgnoreOutcome {
446
+ /** For `"failed"`: why the writer could not run. The command itself still succeeded. */
447
+ message?: string;
448
+ /** Config file that was written, or the one the user must edit for `"manual"`. */
449
+ path: string;
450
+ /** For `"manual"`: the exact text to add. */
451
+ snippet?: string;
452
+ status: LintIgnoreStatus;
453
+ tool: LintTool;
454
+ }
455
+ /**
456
+ * Which linters/formatters this project already uses, by declared dependency or
457
+ * config file on disk.
458
+ *
459
+ * Both signals matter: a dependency without a config is a tool about to be
460
+ * configured, and a config without a dependency is a tool installed globally or
461
+ * hoisted from a monorepo root. Missing either one means silently skipping a
462
+ * tool the project genuinely runs.
463
+ */
464
+ declare const detectLintTools: (projectRoot: string) => LintTool[];
465
+ /**
466
+ * Add {@link LUNORA_IGNORED_PATHS} to each tool's configuration.
467
+ *
468
+ * Idempotent: every writer appends only what is missing, so re-running after a
469
+ * `lunora add` neither duplicates entries nor disturbs a project's own rules.
470
+ * @param projectRoot The project to configure.
471
+ * @param tools Which tools to configure — normally {@link detectLintTools}'s result, or the user's selection at `init`.
472
+ * @returns one outcome per tool, in the order given.
473
+ */
474
+ declare const applyLintIgnores: (projectRoot: string, tools: ReadonlyArray<LintTool>) => LintIgnoreOutcome[];
425
475
  /** Severity a formatted line should be surfaced at, mapped onto the three logger channels. */
426
476
  type LunoraLineLevel = "error" | "info" | "warn";
427
477
  /** A formatted lunora event: the channel to surface it on, the display text, and which event produced it. */
@@ -1002,4 +1052,4 @@ declare const badgeWidth: (_spec: BadgeSpec) => number;
1002
1052
  declare const paintBadge: (spec: BadgeSpec) => string;
1003
1053
  /** Dim continuation text (a step's chosen answer, shown under the question). */
1004
1054
  declare const paintAnswer: (text: string) => string;
1005
- 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, DEFAULT_DEPLOY_TARGET, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DeployDriver, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, 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 MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type ParseSchemaResult, ROOT_SKILL_NAME, type RemotePreference, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, applyAdditiveEdit, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, createConfirm, deployTargetIds, detectAgentRules, detectAiAgent, detectFramework, discoverAgentInfo, discoverContainerInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, escapeRegExp, fillDevSecrets, formatLunoraEvent, generateSecretValue, interpretRemote, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readProjectTarget, requiredSecrets, resolveDeployDriver, resolveProjectTarget, resolveTargetOrThrow, secretsForPackages, streamContainerLogs, updateDevServerState, upsertDevVariableLine, writeDevServerState, writeDevVariablesFileAtomically, writeLinkedProject };
1055
+ 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, DEFAULT_DEPLOY_TARGET, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DeployDriver, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_IGNORED_PATHS, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LintIgnoreOutcome, type LintIgnoreStatus, type LintTool, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type ParseSchemaResult, ROOT_SKILL_NAME, type RemotePreference, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, applyAdditiveEdit, applyLintIgnores, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, createConfirm, deployTargetIds, detectAgentRules, detectAiAgent, detectFramework, detectLintTools, discoverAgentInfo, discoverContainerInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, escapeRegExp, fillDevSecrets, formatLunoraEvent, generateSecretValue, interpretRemote, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readProjectTarget, requiredSecrets, resolveDeployDriver, resolveProjectTarget, resolveTargetOrThrow, secretsForPackages, streamContainerLogs, updateDevServerState, upsertDevVariableLine, writeDevServerState, writeDevVariablesFileAtomically, writeLinkedProject };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{AGENT_MODE_ENV as t,detectAiAgent as o}from"./packem_shared/AGENT_MODE_ENV-B54hVQ_w.mjs";import{discoverAgentInfo as E}from"./packem_shared/discoverAgentInfo-BJm0QtoI.mjs";import{AGENT_RULES_DIR as _,AGENT_RULES_HINT as s,AGENT_RULES_HINT_ENV as p,LUNORA_SKILL_NAMES as l,ROOT_SKILL_NAME as c,claimAgentRulesHint as n,detectAgentRules as m}from"./packem_shared/AGENT_RULES_DIR-hP9TiDNx.mjs";import{discoverContainerInfo as d}from"./packem_shared/discoverContainerInfo-CYG9j2LY.mjs";import{streamContainerLogs as D}from"./packem_shared/streamContainerLogs-BPYBNrWS.mjs";import{detectFramework as L,readProjectDependencyNames as N}from"./packem_shared/detectFramework-VTQfCNXy.mjs";import{DEV_DAEMON_ENV as T,DEV_HANDOFF_ENV as R,DEV_LOG_FILE as I,DEV_LOG_FILE_ENV as V,DEV_STATE_DIR as x,DEV_STATE_FILE as P,claimDevServerState as g,clearDevServerState as F,isProcessAlive as u,isRecordedProcessCurrent as O,readDevServerState as G,readLiveDevServerState as U,updateDevServerState as C,writeDevServerState as b}from"./packem_shared/DEV_DAEMON_ENV-D9Z83rlU.mjs";import{DEV_VARS_EXAMPLE_FILE as M,DEV_VARS_FILE as B,DEV_VARS_KEY_PATTERN as k,escapeRegExp as w,parseDevVariableEntries as K,upsertDevVariableLine as j}from"./packem_shared/DEV_VARS_EXAMPLE_FILE-BL0hrPx3.mjs";import{DEFAULT_DEPLOY_TARGET as H,deployTargetIds as Y,resolveDeployDriver as W}from"./packem_shared/DEFAULT_DEPLOY_TARGET-CBoD0Zha.mjs";import{inferLunoraBindings as q,packageNamesFromBindings as X}from"./packem_shared/inferLunoraBindings-tf2nExl_.mjs";import{LINKED_PROJECT_DIR as Q,LINKED_PROJECT_FILE as Z,readLinkedProject as $,writeLinkedProject as ee}from"./packem_shared/LINKED_PROJECT_DIR-CMzUvj-1.mjs";import{LUNORA_EVENT_SOURCE as te,formatLunoraEvent as oe}from"./packem_shared/LUNORA_EVENT_SOURCE-ZclWASXS.mjs";import{default as Ee}from"./packem_shared/LunoraReporter-BnXUqh8t.mjs";import{PACKAGE_SECRETS_REGISTRY as _e,secretsForPackages as se}from"./packem_shared/PACKAGE_SECRETS_REGISTRY-BgmvEPA-.mjs";import{LUNORA_CONFIG_FILE as le,interpretRemote as ce,readProjectRemotePreference as ne,readProjectTarget as me,resolveProjectTarget as Ae,resolveTargetOrThrow as de}from"./packem_shared/LUNORA_CONFIG_FILE-DoVUD52W.mjs";import{createConfirm as De,isInteractive as fe,promptMultiSelect as Le,promptSelect as Ne,promptText as ve,promptYesNo as Te}from"./packem_shared/createConfirm-7IL0kZyE.mjs";import{buildPackageSecretsBlock as Ie,ensureDevVariables as Ve,ensureDevVarsExample as xe,fillDevSecrets as Pe,generateSecretValue as ge,isMintableSecretKey as Fe,isPlaceholderValue as ue,planDevSecretsFill as Oe,planDevVariablesAugment as Ge,planDevVariablesScaffold as Ue,requiredSecrets as Ce,writeDevVariablesFileAtomically as be}from"./packem_shared/buildPackageSecretsBlock-DlAPMSwt.mjs";import{applyAdditiveEdit as Me,classifyEdit as Be}from"./packem_shared/applyAdditiveEdit-Cff30cSa.mjs";import{parseSchema as we}from"./packem_shared/parseSchema-BQjgz6bk.mjs";import{classifyPolicyEdit as je,scaffoldPolicyFile as he,wireRlsIntoProcedure as He}from"./packem_shared/classifyPolicyEdit-BzC_MfYK.mjs";import{discoverSchemaInfo as We}from"./packem_shared/discoverSchemaInfo-C8X9mo-i.mjs";import{ACCENT as qe,BADGES as Xe,BADGE_COLUMN_WIDTH as ze,LUNA_ART as Qe,LUNA_BUNNY as Ze,LUNA_NAME as $e,LUNA_SIGNOFF as er,STEP_BADGE_NAMES as rr,badgeLead as tr,badgeWidth as or,padBadge as ar,paintAnswer as Er,paintBadge as ir}from"./packem_shared/ACCENT-CLeV5v0K.mjs";import{discoverWorkflowInfo as sr}from"./packem_shared/discoverWorkflowInfo-Bbc0u2gE.mjs";export{qe as ACCENT,t as AGENT_MODE_ENV,_ as AGENT_RULES_DIR,s as AGENT_RULES_HINT,p as AGENT_RULES_HINT_ENV,Xe as BADGES,ze as BADGE_COLUMN_WIDTH,H as DEFAULT_DEPLOY_TARGET,T as DEV_DAEMON_ENV,R as DEV_HANDOFF_ENV,I as DEV_LOG_FILE,V as DEV_LOG_FILE_ENV,x as DEV_STATE_DIR,P as DEV_STATE_FILE,M as DEV_VARS_EXAMPLE_FILE,B as DEV_VARS_FILE,k as DEV_VARS_KEY_PATTERN,Q as LINKED_PROJECT_DIR,Z as LINKED_PROJECT_FILE,Qe as LUNA_ART,Ze as LUNA_BUNNY,$e as LUNA_NAME,er as LUNA_SIGNOFF,le as LUNORA_CONFIG_FILE,te as LUNORA_EVENT_SOURCE,l as LUNORA_SKILL_NAMES,Ee as LunoraReporter,_e as PACKAGE_SECRETS_REGISTRY,c as ROOT_SKILL_NAME,rr as STEP_BADGE_NAMES,Me as applyAdditiveEdit,tr as badgeLead,or as badgeWidth,Ie as buildPackageSecretsBlock,n as claimAgentRulesHint,g as claimDevServerState,Be as classifyEdit,je as classifyPolicyEdit,F as clearDevServerState,De as createConfirm,Y as deployTargetIds,m as detectAgentRules,o as detectAiAgent,L as detectFramework,E as discoverAgentInfo,d as discoverContainerInfo,We as discoverSchemaInfo,sr as discoverWorkflowInfo,Ve as ensureDevVariables,xe as ensureDevVarsExample,w as escapeRegExp,Pe as fillDevSecrets,oe as formatLunoraEvent,ge as generateSecretValue,q as inferLunoraBindings,ce as interpretRemote,fe as isInteractive,Fe as isMintableSecretKey,ue as isPlaceholderValue,u as isProcessAlive,O as isRecordedProcessCurrent,X as packageNamesFromBindings,ar as padBadge,Er as paintAnswer,ir as paintBadge,K as parseDevVariableEntries,we as parseSchema,Oe as planDevSecretsFill,Ge as planDevVariablesAugment,Ue as planDevVariablesScaffold,Le as promptMultiSelect,Ne as promptSelect,ve as promptText,Te as promptYesNo,G as readDevServerState,$ as readLinkedProject,U as readLiveDevServerState,N as readProjectDependencyNames,ne as readProjectRemotePreference,me as readProjectTarget,Ce as requiredSecrets,W as resolveDeployDriver,Ae as resolveProjectTarget,de as resolveTargetOrThrow,he as scaffoldPolicyFile,se as secretsForPackages,D as streamContainerLogs,C as updateDevServerState,j as upsertDevVariableLine,He as wireRlsIntoProcedure,b as writeDevServerState,be as writeDevVariablesFileAtomically,ee as writeLinkedProject};
1
+ import{AGENT_MODE_ENV as t,detectAiAgent as o}from"./packem_shared/AGENT_MODE_ENV-B54hVQ_w.mjs";import{discoverAgentInfo as E}from"./packem_shared/discoverAgentInfo-BJm0QtoI.mjs";import{AGENT_RULES_DIR as _,AGENT_RULES_HINT as p,AGENT_RULES_HINT_ENV as s,LUNORA_SKILL_NAMES as l,ROOT_SKILL_NAME as c,claimAgentRulesHint as n,detectAgentRules as A}from"./packem_shared/AGENT_RULES_DIR-hP9TiDNx.mjs";import{discoverContainerInfo as d}from"./packem_shared/discoverContainerInfo-CYG9j2LY.mjs";import{streamContainerLogs as D}from"./packem_shared/streamContainerLogs-BPYBNrWS.mjs";import{detectFramework as L,readProjectDependencyNames as N}from"./packem_shared/detectFramework-VTQfCNXy.mjs";import{DEV_DAEMON_ENV as T,DEV_HANDOFF_ENV as R,DEV_LOG_FILE as I,DEV_LOG_FILE_ENV as x,DEV_STATE_DIR as V,DEV_STATE_FILE as P,claimDevServerState as g,clearDevServerState as O,isProcessAlive as F,isRecordedProcessCurrent as u,readDevServerState as G,readLiveDevServerState as U,updateDevServerState as C,writeDevServerState as y}from"./packem_shared/DEV_DAEMON_ENV-D9Z83rlU.mjs";import{DEV_VARS_EXAMPLE_FILE as M,DEV_VARS_FILE as B,DEV_VARS_KEY_PATTERN as k,escapeRegExp as w,parseDevVariableEntries as K,upsertDevVariableLine as j}from"./packem_shared/DEV_VARS_EXAMPLE_FILE-BL0hrPx3.mjs";import{DEFAULT_DEPLOY_TARGET as h,deployTargetIds as Y,resolveDeployDriver as W}from"./packem_shared/DEFAULT_DEPLOY_TARGET-CBoD0Zha.mjs";import{inferLunoraBindings as q,packageNamesFromBindings as X}from"./packem_shared/inferLunoraBindings-tf2nExl_.mjs";import{LINKED_PROJECT_DIR as Q,LINKED_PROJECT_FILE as Z,readLinkedProject as $,writeLinkedProject as ee}from"./packem_shared/LINKED_PROJECT_DIR-CMzUvj-1.mjs";import{LUNORA_IGNORED_PATHS as te,applyLintIgnores as oe,detectLintTools as ae}from"./packem_shared/LUNORA_IGNORED_PATHS-DIdyP0js.mjs";import{LUNORA_EVENT_SOURCE as ie,formatLunoraEvent as _e}from"./packem_shared/LUNORA_EVENT_SOURCE-ZclWASXS.mjs";import{default as se}from"./packem_shared/LunoraReporter-BnXUqh8t.mjs";import{PACKAGE_SECRETS_REGISTRY as ce,secretsForPackages as ne}from"./packem_shared/PACKAGE_SECRETS_REGISTRY-BgmvEPA-.mjs";import{LUNORA_CONFIG_FILE as me,interpretRemote as de,readProjectRemotePreference as Se,readProjectTarget as De,resolveProjectTarget as fe,resolveTargetOrThrow as Le}from"./packem_shared/LUNORA_CONFIG_FILE-DoVUD52W.mjs";import{createConfirm as ve,isInteractive as Te,promptMultiSelect as Re,promptSelect as Ie,promptText as xe,promptYesNo as Ve}from"./packem_shared/createConfirm-7IL0kZyE.mjs";import{buildPackageSecretsBlock as ge,ensureDevVariables as Oe,ensureDevVarsExample as Fe,fillDevSecrets as ue,generateSecretValue as Ge,isMintableSecretKey as Ue,isPlaceholderValue as Ce,planDevSecretsFill as ye,planDevVariablesAugment as be,planDevVariablesScaffold as Me,requiredSecrets as Be,writeDevVariablesFileAtomically as ke}from"./packem_shared/buildPackageSecretsBlock-DlAPMSwt.mjs";import{applyAdditiveEdit as Ke,classifyEdit as je}from"./packem_shared/applyAdditiveEdit-Cff30cSa.mjs";import{parseSchema as he}from"./packem_shared/parseSchema-BQjgz6bk.mjs";import{classifyPolicyEdit as We,scaffoldPolicyFile as Je,wireRlsIntoProcedure as qe}from"./packem_shared/classifyPolicyEdit-BzC_MfYK.mjs";import{discoverSchemaInfo as ze}from"./packem_shared/discoverSchemaInfo-C8X9mo-i.mjs";import{ACCENT as Ze,BADGES as $e,BADGE_COLUMN_WIDTH as er,LUNA_ART as rr,LUNA_BUNNY as tr,LUNA_NAME as or,LUNA_SIGNOFF as ar,STEP_BADGE_NAMES as Er,badgeLead as ir,badgeWidth as _r,padBadge as pr,paintAnswer as sr,paintBadge as lr}from"./packem_shared/ACCENT-CLeV5v0K.mjs";import{discoverWorkflowInfo as nr}from"./packem_shared/discoverWorkflowInfo-Bbc0u2gE.mjs";export{Ze as ACCENT,t as AGENT_MODE_ENV,_ as AGENT_RULES_DIR,p as AGENT_RULES_HINT,s as AGENT_RULES_HINT_ENV,$e as BADGES,er as BADGE_COLUMN_WIDTH,h as DEFAULT_DEPLOY_TARGET,T as DEV_DAEMON_ENV,R as DEV_HANDOFF_ENV,I as DEV_LOG_FILE,x as DEV_LOG_FILE_ENV,V as DEV_STATE_DIR,P as DEV_STATE_FILE,M as DEV_VARS_EXAMPLE_FILE,B as DEV_VARS_FILE,k as DEV_VARS_KEY_PATTERN,Q as LINKED_PROJECT_DIR,Z as LINKED_PROJECT_FILE,rr as LUNA_ART,tr as LUNA_BUNNY,or as LUNA_NAME,ar as LUNA_SIGNOFF,me as LUNORA_CONFIG_FILE,ie as LUNORA_EVENT_SOURCE,te as LUNORA_IGNORED_PATHS,l as LUNORA_SKILL_NAMES,se as LunoraReporter,ce as PACKAGE_SECRETS_REGISTRY,c as ROOT_SKILL_NAME,Er as STEP_BADGE_NAMES,Ke as applyAdditiveEdit,oe as applyLintIgnores,ir as badgeLead,_r as badgeWidth,ge as buildPackageSecretsBlock,n as claimAgentRulesHint,g as claimDevServerState,je as classifyEdit,We as classifyPolicyEdit,O as clearDevServerState,ve as createConfirm,Y as deployTargetIds,A as detectAgentRules,o as detectAiAgent,L as detectFramework,ae as detectLintTools,E as discoverAgentInfo,d as discoverContainerInfo,ze as discoverSchemaInfo,nr as discoverWorkflowInfo,Oe as ensureDevVariables,Fe as ensureDevVarsExample,w as escapeRegExp,ue as fillDevSecrets,_e as formatLunoraEvent,Ge as generateSecretValue,q as inferLunoraBindings,de as interpretRemote,Te as isInteractive,Ue as isMintableSecretKey,Ce as isPlaceholderValue,F as isProcessAlive,u as isRecordedProcessCurrent,X as packageNamesFromBindings,pr as padBadge,sr as paintAnswer,lr as paintBadge,K as parseDevVariableEntries,he as parseSchema,ye as planDevSecretsFill,be as planDevVariablesAugment,Me as planDevVariablesScaffold,Re as promptMultiSelect,Ie as promptSelect,xe as promptText,Ve as promptYesNo,G as readDevServerState,$ as readLinkedProject,U as readLiveDevServerState,N as readProjectDependencyNames,Se as readProjectRemotePreference,De as readProjectTarget,Be as requiredSecrets,W as resolveDeployDriver,fe as resolveProjectTarget,Le as resolveTargetOrThrow,Je as scaffoldPolicyFile,ne as secretsForPackages,D as streamContainerLogs,C as updateDevServerState,j as upsertDevVariableLine,qe as wireRlsIntoProcedure,y as writeDevServerState,ke as writeDevVariablesFileAtomically,ee as writeLinkedProject};
@@ -0,0 +1 @@
1
+ const f=1,c=new Set(["$schema","account_id","compatibility_date","compatibility_flags","keep_vars","main","migrations","minify","name","observability","placement","routes","rules","triggers","upload_source_maps","vars","workers_dev"]),u=e=>{const s=new Set;for(const o of e.migrations??[])for(const n of o.new_sqlite_classes??[])s.add(n);return s},l=e=>Object.fromEntries(Object.entries(e).filter(([,s])=>s!==void 0)),a=[{bindingKey:"binding",field:"analytics_engine_datasets",resourceKey:"dataset",type:"analytics_engine"},{bindingKey:"class_name",field:"containers",resourceKey:"image",type:"container"},{bindingKey:"binding",field:"d1_databases",resourceIdKey:"database_id",resourceKey:"database_name",type:"d1"},{bindingKey:"binding",field:"hyperdrive",resourceIdKey:"id",type:"hyperdrive"},{bindingKey:"binding",field:"kv_namespaces",resourceIdKey:"id",type:"kv"},{bindingKey:"binding",field:"pipelines",resourceKey:"pipeline",type:"pipeline"},{bindingKey:"binding",field:"r2_buckets",resourceKey:"bucket_name",type:"r2"},{bindingKey:"binding",field:"vectorize",resourceKey:"index_name",type:"vectorize"},{bindingKey:"binding",field:"workflows",resourceKey:"name",type:"workflow"}],d=[{field:"ai",type:"ai"},{field:"assets",type:"assets"},{field:"browser",type:"browser"},{field:"images",type:"images"}],p=new Set([...a.map(e=>e.field),...d.map(e=>e.field),"durable_objects","queues"]),r=(e,s)=>{const o=s===void 0?void 0:e[s];return typeof o=="string"&&o!==""?o:void 0},b=(e,s)=>{const o=[];for(const n of a)for(const i of e[n.field]??[]){const t=r(i,n.bindingKey);if(t===void 0){s.push(n.field);continue}o.push({binding:t,className:r(i,"class_name"),resource:r(i,n.resourceKey),resourceId:r(i,n.resourceIdKey),type:n.type})}return o},y=(e,s)=>{const o=u(e),n=[];for(const i of e.durable_objects?.bindings??[]){if(i.name===void 0||i.name===""){s.push("durable_objects");continue}n.push({binding:i.name,className:i.class_name,sqlite:i.script_name===void 0&&i.class_name!==void 0?o.has(i.class_name):void 0,type:"durable_object"})}return n},m=(e,s)=>{const o=[];for(const n of e.queues?.producers??[]){if(n.binding===void 0||n.binding===""){s.push("queues.producers");continue}o.push({binding:n.binding,resource:n.queue,type:"queue_producer"})}for(const n of e.queues?.consumers??[]){if(n.queue===void 0||n.queue===""){s.push("queues.consumers");continue}o.push({binding:n.queue,resource:n.queue,type:"queue_consumer"})}return o},g=(e,s)=>[...b(e,s),...y(e,s),...m(e,s),...d.filter(o=>e[o.field]?.binding!==void 0).map(o=>({binding:e[o.field]?.binding,type:o.type}))],_=e=>{const s=[],o=g(e,s).map(i=>l(i)).toSorted((i,t)=>i.type.localeCompare(t.type)||i.binding.localeCompare(t.binding)),n=[...Object.keys(e).filter(i=>!c.has(i)&&!p.has(i)),...s.map(i=>`${i} (entry with no binding name)`)].toSorted((i,t)=>i.localeCompare(t));return{bindings:o,...e.compatibility_date===void 0?{}:{compatibilityDate:e.compatibility_date},...e.compatibility_flags===void 0?{}:{compatibilityFlags:e.compatibility_flags},crons:e.triggers?.crons??[],...e.name===void 0?{}:{name:e.name},unknown:n,vars:Object.keys(e.vars??{}).toSorted((i,t)=>i.localeCompare(t)),version:1}};export{f as BINDING_MANIFEST_VERSION,_ as buildBindingManifest};
@@ -0,0 +1,19 @@
1
+ import{existsSync as g,readFileSync as m,writeFileSync as d}from"node:fs";import{join as l,dirname as b}from"node:path";import{parse as y}from"jsonc-parser";import{readProjectDependencyNames as w}from"./detectFramework-VTQfCNXy.mjs";import{e as $}from"./jsonc-edit-BZVpxVA0.mjs";const c=["lunora/_generated/","lunora/.lunora-schema.json","lunora.advisor.map.json",".lunora/",".wrangler/"],f={biome:{configFiles:["biome.json","biome.jsonc"],packages:["@biomejs/biome"],shadowable:!0},eslint:{configFiles:["eslint.config.js","eslint.config.mjs","eslint.config.cjs","eslint.config.ts","eslint.config.mts","eslint.config.cts"],packages:["eslint"],shadowable:!0},oxlint:{configFiles:[".oxlintrc.json"],packages:["oxlint"],shadowable:!0},prettier:{configFiles:[".prettierrc",".prettierrc.json",".prettierrc.js",".prettierrc.mjs",".prettierrc.cjs","prettier.config.js","prettier.config.mjs","prettier.config.cjs"],packages:["prettier"],shadowable:!1}},A=Object.keys(f),h=(e,r)=>f[r].configFiles.map(t=>l(e,t)).find(t=>g(t)),F=(e,r)=>{let t=e;for(;;){const n=h(t,r);if(n!==void 0)return n;if(g(l(t,".git")))return;const i=b(t);if(i===t)return;t=i}},j=(e,r)=>{const t=h(e,r);if(t!==void 0)return{action:"extend",path:t};const n=g(l(e,".git")),i=f[r].shadowable&&!n?F(b(e),r):void 0,[s=""]=f[r].configFiles;return i===void 0?{action:"create",path:l(e,s)}:{action:"report",path:i}},G=e=>{const r=w(e),t=()=>{try{return JSON.parse(m(l(e,"package.json"),"utf8")).prettier!==void 0}catch{return!1}};return A.filter(n=>f[n].packages.some(i=>r.has(i))||h(e,n)!==void 0||n==="prettier"&&t())},k="# Lunora generated + derived artifacts",S=e=>{const r=l(e,".prettierignore"),t=g(r)?m(r,"utf8"):void 0,n=t===void 0?[]:t.split(`
2
+ `).map(o=>o.trim()),i=c.filter(o=>!n.includes(o));if(i.length===0)return{path:r,status:t===void 0?"created":"unchanged",tool:"prettier"};const s=`${k}
3
+ ${i.join(`
4
+ `)}
5
+ `;return t===void 0?(d(r,s,"utf8"),{path:r,status:"created",tool:"prettier"}):(d(r,`${t.endsWith(`
6
+ `)?t:`${t}
7
+ `}
8
+ ${s}`,"utf8"),{path:r,status:"updated",tool:"prettier"})},v=(e,r,t,n)=>{const i=g(e),s=i?m(e,"utf8"):`{}
9
+ `;let o=y(s)??{};for(const a of r)o=o!==null&&typeof o=="object"?o[a]:void 0;const p=Array.isArray(o)?o:[],u=t.filter(a=>!p.includes(a));return u.length===0&&i?{path:e,status:"unchanged",tool:n}:(d(e,$(s,r,[...p,...u]),"utf8"),{path:e,status:i?"updated":"created",tool:n})},x=(e,r)=>`"${e}": [${r.map(t=>`"${t}"`).join(", ")}]`,L=()=>x("files.includes",c.map(e=>`!${e.endsWith("/")?`${e}**`:e}`)),N=e=>{const{action:r,path:t}=j(e,"oxlint");return r==="report"?{path:t,snippet:x("ignorePatterns",c),status:"manual",tool:"oxlint"}:v(t,["ignorePatterns"],c,"oxlint")},O=e=>{const{action:r,path:t}=j(e,"biome");if(r==="report")return{path:t,snippet:L(),status:"manual",tool:"biome"};const n=r==="extend",i=n?m(t,"utf8"):`{}
10
+ `,s=(y(i)??{}).files??{};if(Array.isArray(s.ignore))return v(t,["files","ignore"],c,"biome");const o=Array.isArray(s.includes)?s.includes:[],p=o.length===0?["**"]:o,u=c.map(a=>`!${a.endsWith("/")?`${a}**`:a}`).filter(a=>!o.includes(a));return u.length===0&&n?{path:t,status:"unchanged",tool:"biome"}:(d(t,$(i,["files","includes"],[...p,...u]),"utf8"),{path:t,status:n?"updated":"created",tool:"biome"})},P=()=>`{
11
+ // Lunora generated + derived artifacts.
12
+ ignores: [${c.map(e=>`"${e.endsWith("/")?`${e}**`:e}"`).join(", ")}],
13
+ }`,W=e=>{const{action:r,path:t}=j(e,"eslint"),n=P();if(r!=="create"){const s=m(t,"utf8"),o=c.every(p=>s.includes(p))?"unchanged":"manual";return{path:t,...o==="manual"?{snippet:n}:{},status:o,tool:"eslint"}}const i=l(e,"eslint.config.mjs");return d(i,`// Flat config. Add your own entries alongside the ignores below.
14
+ export default [
15
+ ${n.replaceAll(`
16
+ `,`
17
+ `)},
18
+ ];
19
+ `,"utf8"),{path:i,status:"created",tool:"eslint"}},_={biome:O,eslint:W,oxlint:N,prettier:S},H=(e,r)=>r.map(t=>{try{return _[t](e)}catch(n){return{message:n instanceof Error?n.message:String(n),path:e,status:"failed",tool:t}}});export{c as LUNORA_IGNORED_PATHS,H as applyLintIgnores,G as detectLintTools};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/config",
3
- "version": "1.0.0-alpha.111",
3
+ "version": "1.0.0-alpha.113",
4
4
  "description": "Internal shared CLI + Vite config layer for Lunora: wrangler.jsonc validation, binding inference, and .dev.vars scaffolding",
5
5
  "keywords": [
6
6
  "bindings",
@@ -54,10 +54,10 @@
54
54
  "access": "public"
55
55
  },
56
56
  "dependencies": {
57
- "@lunora/codegen": "1.0.0-alpha.85",
57
+ "@lunora/codegen": "1.0.0-alpha.86",
58
58
  "@lunora/container": "1.0.0-alpha.20",
59
59
  "@lunora/errors": "1.0.0-alpha.12",
60
- "@lunora/seed": "1.0.0-alpha.58",
60
+ "@lunora/seed": "1.0.0-alpha.59",
61
61
  "@visulima/colorize": "2.0.0",
62
62
  "@visulima/find-ai-runner": "1.0.0",
63
63
  "dockerode": "^5.0.1",