@cat-factory/cli 0.12.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/envMerge.d.ts +82 -0
- package/dist/envMerge.d.ts.map +1 -0
- package/dist/envMerge.js +293 -0
- package/dist/envMerge.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { type EnvEntry } from './env.js';
|
|
2
|
+
/**
|
|
3
|
+
* What the write did, and what it did to each key an operator might care about.
|
|
4
|
+
*
|
|
5
|
+
* Four categories rather than a boolean, because "nothing was overwritten" is the claim this kind of
|
|
6
|
+
* command makes and only the split can state it: `kept` is a value the file already held and this
|
|
7
|
+
* run reused, `changed` is one it REPLACED (the case that owes the operator a sentence), `added` is
|
|
8
|
+
* new, and `preserved` is everything in the file the caller does not manage and therefore must not
|
|
9
|
+
* lose.
|
|
10
|
+
*/
|
|
11
|
+
export interface EnvMerge {
|
|
12
|
+
text: string;
|
|
13
|
+
kept: readonly string[];
|
|
14
|
+
changed: readonly string[];
|
|
15
|
+
added: readonly string[];
|
|
16
|
+
preserved: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The header written above the content the merge did not manage.
|
|
20
|
+
*
|
|
21
|
+
* Exported because a consumer rendering its own report matches on it. Recognition on the way IN goes
|
|
22
|
+
* through {@link CARRIED_OVER_PREFIX}, not through this: it introduces an UNMANAGED assignment, so
|
|
23
|
+
* the ordinary comment-block rule carries it over, and a merge that then prepended a fresh copy grew
|
|
24
|
+
* the file by one line per run.
|
|
25
|
+
*/
|
|
26
|
+
export declare const CARRIED_OVER_HEADER = "# Carried over unchanged from the previous file; this command does not manage these.";
|
|
27
|
+
/**
|
|
28
|
+
* Merge the managed entries into an existing `.env`, keeping every unmanaged line VERBATIM.
|
|
29
|
+
*
|
|
30
|
+
* `existing` is `null` for a file that does not exist yet, which writes the whole thing. The managed
|
|
31
|
+
* values are quoted on the way out where they need it (see {@link quoteEnvValue}); the kept/changed
|
|
32
|
+
* comparison stays against the UNQUOTED form, which is what both sides hold.
|
|
33
|
+
*/
|
|
34
|
+
export declare function mergeEnvFile(existing: string | null, entries: readonly EnvEntry[]): EnvMerge;
|
|
35
|
+
/**
|
|
36
|
+
* Quote a managed value when leaving it bare would make the reader disagree with the writer.
|
|
37
|
+
*
|
|
38
|
+
* `renderEnvFile` emits a bare `KEY=value`, and a `.env` is typically read with `node:util`'s
|
|
39
|
+
* `parseEnv`, which treats an unquoted `#` as the start of a comment and strips surrounding
|
|
40
|
+
* whitespace: `parseEnv('A=with # hash')` is `{ A: 'with' }`. So a value READ as `cf-acc #2` (from a
|
|
41
|
+
* quoted line an operator wrote), offered as a prompt default and accepted unchanged would be
|
|
42
|
+
* written back as a DIFFERENT value while the merge report called it unchanged.
|
|
43
|
+
*
|
|
44
|
+
* Double quotes preferred, single quotes when the value contains a double one, because `parseEnv`
|
|
45
|
+
* supports both delimiters and NO escape inside either (`A="he said \"hi\""` parses as `he said \`).
|
|
46
|
+
* A value carrying both quote characters is therefore unrepresentable, so it throws rather than
|
|
47
|
+
* writing a file that reads back as something else: the whole promise of such a command is that the
|
|
48
|
+
* file it wrote is the file the reader will read.
|
|
49
|
+
*/
|
|
50
|
+
export declare function quoteEnvValue(value: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* The `KEY=` assignments a `.env` holds, by key, with each value unquoted.
|
|
53
|
+
*
|
|
54
|
+
* Hand-rolled rather than `node:util`'s `parseEnv`, because what a merge needs is the SET of keys and
|
|
55
|
+
* whether each still holds the value being written, and the comparison has to be against the same
|
|
56
|
+
* unquoted form the writer produces. A value the caller does not manage is never read for its
|
|
57
|
+
* meaning, only skipped, so the shallow read is sufficient exactly where it is used.
|
|
58
|
+
*
|
|
59
|
+
* An assignment with an EMPTY value is kept, so `preserved` can report a `FOO=` line the merge
|
|
60
|
+
* carried over. A caller using this for prompt DEFAULTS filters those itself, because blank usually
|
|
61
|
+
* means absent to whatever reads the file.
|
|
62
|
+
*/
|
|
63
|
+
export declare function readAssignments(text: string): Record<string, string>;
|
|
64
|
+
/**
|
|
65
|
+
* One line per managed key, with every secret's value WITHHELD rather than masked.
|
|
66
|
+
*
|
|
67
|
+
* `secretKeys` is the caller's, and it is a SET rather than a predicate on purpose: a pattern match
|
|
68
|
+
* (`key.includes('TOKEN')`) passes today and quietly stops covering the next secret whose name does
|
|
69
|
+
* not say so, and the failure is one nobody sees: a token on somebody's scrollback.
|
|
70
|
+
*
|
|
71
|
+
* Withheld and not masked, because a masked value still states its length and its prefix, and this
|
|
72
|
+
* output is routinely pasted into an issue when the setup did not work.
|
|
73
|
+
*/
|
|
74
|
+
export declare function describeEntries(entries: readonly EnvEntry[], secretKeys: ReadonlySet<string>): readonly string[];
|
|
75
|
+
/**
|
|
76
|
+
* What the write did, in the order an operator wants it: what changed, then what was left alone.
|
|
77
|
+
*
|
|
78
|
+
* `changed` leads because it is the only category that can surprise anyone, and the promise such a
|
|
79
|
+
* command makes is that it never overwrites a value without saying so.
|
|
80
|
+
*/
|
|
81
|
+
export declare function describeMerge(merge: EnvMerge, path: string): readonly string[];
|
|
82
|
+
//# sourceMappingURL=envMerge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envMerge.d.ts","sourceRoot":"","sources":["../src/envMerge.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,KAAK,QAAQ,EAAiB,MAAM,UAAU,CAAA;AAEvD;;;;;;;;GAQG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CAC7B;AAcD;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,yFAA+D,CAAA;AAO/F;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ,CAoB5F;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASnD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMpE;AAyJD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,SAAS,QAAQ,EAAE,EAC5B,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,GAC9B,SAAS,MAAM,EAAE,CAKnB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAW9E"}
|
package/dist/envMerge.js
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
// MERGING into an existing `.env`, which is the other half of writing one.
|
|
2
|
+
//
|
|
3
|
+
// `env.ts` renders a fresh file. This is what a setup command needs the second time it runs, and the
|
|
4
|
+
// two belong together: a generator that can only overwrite is a generator nobody runs twice.
|
|
5
|
+
//
|
|
6
|
+
// Published rather than kept inside whichever command needed it first, because five judgements here
|
|
7
|
+
// are each a SILENT failure when you get them wrong (the command reports success and the file means
|
|
8
|
+
// something else), and every consumer that writes its own generator has to make all five:
|
|
9
|
+
//
|
|
10
|
+
// 1. **Unmanaged content is carried over VERBATIM**, never re-rendered from a parse, and a
|
|
11
|
+
// multi-line quoted value is ONE assignment rather than a line and some debris. A parse-then-
|
|
12
|
+
// requote round trip is how a PEM acquires a stray escape and stops matching the certificate it
|
|
13
|
+
// was pasted from; a line-at-a-time strip is how one loses its opening line and has the rest
|
|
14
|
+
// re-filed as somebody else's content, which the reader then takes for a set of garbage keys.
|
|
15
|
+
// 2. **The report is four categories, not a boolean.** "Nothing was overwritten" is the claim such
|
|
16
|
+
// a command makes, and only `kept` / `changed` / `added` / `preserved` can state it.
|
|
17
|
+
// 3. **A managed value is QUOTED where the READER would otherwise disagree with the writer.**
|
|
18
|
+
// `renderEnvFile` emits a bare `KEY=value`; `node:util`'s `parseEnv` treats an unquoted `#` as a
|
|
19
|
+
// comment, so `A=cf-kargo #2` reads back as `cf-kargo`. A value carrying both quote characters
|
|
20
|
+
// is unrepresentable and THROWS rather than being written as something else.
|
|
21
|
+
// 4. **The carried-over header must be RECOGNISED as well as written**, or the file grows by one
|
|
22
|
+
// identical line per run, and recognised by a STABLE PREFIX rather than the whole sentence, or
|
|
23
|
+
// the day the wording changes every file written by a previous run grows one anyway.
|
|
24
|
+
// 5. **Secrets are withheld by an ENUMERATED list**, never a pattern match: `key.includes('TOKEN')`
|
|
25
|
+
// passes today and quietly stops covering the next secret whose name does not say so.
|
|
26
|
+
//
|
|
27
|
+
// The list of secrets itself stays the CALLER's, because only a caller knows its own; the withholding
|
|
28
|
+
// behaviour does not.
|
|
29
|
+
import { renderEnvFile } from './env.js';
|
|
30
|
+
/**
|
|
31
|
+
* The part of the header that IDENTIFIES it, and the only part any recognition may depend on.
|
|
32
|
+
*
|
|
33
|
+
* Split off the sentence because recognising the whole of it is a trap that has already fired: the
|
|
34
|
+
* header used to name `configure`, and generalising the wording for a published helper meant every
|
|
35
|
+
* file a previous run had written carried a line the next run no longer matched. It was then filed as
|
|
36
|
+
* an ordinary comment above unmanaged content, a fresh header was prepended above it, and the file
|
|
37
|
+
* kept both, which is precisely the growth rule 4 exists to prevent. Matching a prefix that does not
|
|
38
|
+
* carry the changeable half makes the next rewording free.
|
|
39
|
+
*/
|
|
40
|
+
const CARRIED_OVER_PREFIX = '# Carried over unchanged from the previous file;';
|
|
41
|
+
/**
|
|
42
|
+
* The header written above the content the merge did not manage.
|
|
43
|
+
*
|
|
44
|
+
* Exported because a consumer rendering its own report matches on it. Recognition on the way IN goes
|
|
45
|
+
* through {@link CARRIED_OVER_PREFIX}, not through this: it introduces an UNMANAGED assignment, so
|
|
46
|
+
* the ordinary comment-block rule carries it over, and a merge that then prepended a fresh copy grew
|
|
47
|
+
* the file by one line per run.
|
|
48
|
+
*/
|
|
49
|
+
export const CARRIED_OVER_HEADER = `${CARRIED_OVER_PREFIX} this command does not manage these.`;
|
|
50
|
+
/** Whether a line is the carried-over header, in whichever words the run that wrote it used. */
|
|
51
|
+
function isCarriedOverHeader(line) {
|
|
52
|
+
return line.trim().startsWith(CARRIED_OVER_PREFIX);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Merge the managed entries into an existing `.env`, keeping every unmanaged line VERBATIM.
|
|
56
|
+
*
|
|
57
|
+
* `existing` is `null` for a file that does not exist yet, which writes the whole thing. The managed
|
|
58
|
+
* values are quoted on the way out where they need it (see {@link quoteEnvValue}); the kept/changed
|
|
59
|
+
* comparison stays against the UNQUOTED form, which is what both sides hold.
|
|
60
|
+
*/
|
|
61
|
+
export function mergeEnvFile(existing, entries) {
|
|
62
|
+
const managed = entries.map((entry) => entry.key);
|
|
63
|
+
const previous = existing === null ? {} : readAssignments(existing);
|
|
64
|
+
const kept = [];
|
|
65
|
+
const changed = [];
|
|
66
|
+
const added = [];
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
const before = previous[entry.key];
|
|
69
|
+
if (before === undefined)
|
|
70
|
+
added.push(entry.key);
|
|
71
|
+
else if (before === entry.value)
|
|
72
|
+
kept.push(entry.key);
|
|
73
|
+
else
|
|
74
|
+
changed.push(entry.key);
|
|
75
|
+
}
|
|
76
|
+
const leftover = existing === null ? '' : stripAssignments(existing, managed);
|
|
77
|
+
const preserved = Object.keys(previous).filter((key) => !managed.includes(key));
|
|
78
|
+
const tail = leftover.length > 0 ? `\n${CARRIED_OVER_HEADER}\n${leftover}\n` : '';
|
|
79
|
+
const rendered = renderEnvFile(entries.map((entry) => ({ ...entry, value: quoteEnvValue(entry.value) })));
|
|
80
|
+
return { text: `${rendered}${tail}`, kept, changed, added, preserved };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Quote a managed value when leaving it bare would make the reader disagree with the writer.
|
|
84
|
+
*
|
|
85
|
+
* `renderEnvFile` emits a bare `KEY=value`, and a `.env` is typically read with `node:util`'s
|
|
86
|
+
* `parseEnv`, which treats an unquoted `#` as the start of a comment and strips surrounding
|
|
87
|
+
* whitespace: `parseEnv('A=with # hash')` is `{ A: 'with' }`. So a value READ as `cf-acc #2` (from a
|
|
88
|
+
* quoted line an operator wrote), offered as a prompt default and accepted unchanged would be
|
|
89
|
+
* written back as a DIFFERENT value while the merge report called it unchanged.
|
|
90
|
+
*
|
|
91
|
+
* Double quotes preferred, single quotes when the value contains a double one, because `parseEnv`
|
|
92
|
+
* supports both delimiters and NO escape inside either (`A="he said \"hi\""` parses as `he said \`).
|
|
93
|
+
* A value carrying both quote characters is therefore unrepresentable, so it throws rather than
|
|
94
|
+
* writing a file that reads back as something else: the whole promise of such a command is that the
|
|
95
|
+
* file it wrote is the file the reader will read.
|
|
96
|
+
*/
|
|
97
|
+
export function quoteEnvValue(value) {
|
|
98
|
+
if (!/[#\n"']/.test(value) && value.trim() === value)
|
|
99
|
+
return value;
|
|
100
|
+
if (!value.includes('"'))
|
|
101
|
+
return `"${value}"`;
|
|
102
|
+
if (!value.includes("'"))
|
|
103
|
+
return `'${value}'`;
|
|
104
|
+
throw new Error(`A value containing both \` " \` and \` ' \` cannot be written to a .env file: neither quoting ` +
|
|
105
|
+
`style survives, and \`parseEnv\` supports no escape inside either. Choose a value without ` +
|
|
106
|
+
`one of them.`);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The `KEY=` assignments a `.env` holds, by key, with each value unquoted.
|
|
110
|
+
*
|
|
111
|
+
* Hand-rolled rather than `node:util`'s `parseEnv`, because what a merge needs is the SET of keys and
|
|
112
|
+
* whether each still holds the value being written, and the comparison has to be against the same
|
|
113
|
+
* unquoted form the writer produces. A value the caller does not manage is never read for its
|
|
114
|
+
* meaning, only skipped, so the shallow read is sufficient exactly where it is used.
|
|
115
|
+
*
|
|
116
|
+
* An assignment with an EMPTY value is kept, so `preserved` can report a `FOO=` line the merge
|
|
117
|
+
* carried over. A caller using this for prompt DEFAULTS filters those itself, because blank usually
|
|
118
|
+
* means absent to whatever reads the file.
|
|
119
|
+
*/
|
|
120
|
+
export function readAssignments(text) {
|
|
121
|
+
const found = {};
|
|
122
|
+
for (const line of readEnvLines(text)) {
|
|
123
|
+
if (line.kind === 'assignment')
|
|
124
|
+
found[line.key] = line.value;
|
|
125
|
+
}
|
|
126
|
+
return found;
|
|
127
|
+
}
|
|
128
|
+
/** `export FOO=bar` and `FOO=bar` alike, since both appear in a hand-written file. */
|
|
129
|
+
const ASSIGNMENT = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=(.*)$/;
|
|
130
|
+
/**
|
|
131
|
+
* Split a `.env` into logical lines, joining a QUOTED VALUE that spans several of them.
|
|
132
|
+
*
|
|
133
|
+
* The one place the multi-line rule lives, because both readers need it and neither can be right
|
|
134
|
+
* alone: a line-at-a-time reader takes `KEY="-----BEGIN CERTIFICATE-----` for the whole value, and a
|
|
135
|
+
* line-at-a-time stripper drops that first line and re-emits the certificate's body as unmanaged
|
|
136
|
+
* content, which the merge then writes back under the carried-over header and the reader takes for a
|
|
137
|
+
* set of garbage keys (a base64 line ending `Qm9keQ==` even parses as an assignment). A PEM is the
|
|
138
|
+
* commonest such value and is exactly what the module header promises to survive.
|
|
139
|
+
*
|
|
140
|
+
* Continuation is decided by the OPENING quote only: a value whose first character is `"` or `'` and
|
|
141
|
+
* which does not close it on the same line continues until a line that does. That matches what
|
|
142
|
+
* `node:util`'s `parseEnv` accepts, which is the reader this writer has to agree with, and it leaves
|
|
143
|
+
* every ordinary bare value exactly as it was.
|
|
144
|
+
*/
|
|
145
|
+
function readEnvLines(text) {
|
|
146
|
+
const physical = text.split('\n');
|
|
147
|
+
const out = [];
|
|
148
|
+
for (let index = 0; index < physical.length; index++) {
|
|
149
|
+
const line = physical[index];
|
|
150
|
+
if (line.trim().startsWith('#')) {
|
|
151
|
+
out.push({ kind: 'comment', text: line });
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (line.trim().length === 0) {
|
|
155
|
+
out.push({ kind: 'blank', text: line });
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const match = ASSIGNMENT.exec(line);
|
|
159
|
+
const key = match?.[1];
|
|
160
|
+
if (key === undefined) {
|
|
161
|
+
out.push({ kind: 'other', text: line });
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const raw = match?.[2] ?? '';
|
|
165
|
+
const quote = unclosedQuote(raw);
|
|
166
|
+
if (quote === null) {
|
|
167
|
+
out.push({ kind: 'assignment', key, value: unquote(raw), text: line });
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const spanned = [raw];
|
|
171
|
+
// Tracked rather than read back off the last element, which would count the OPENING quote in
|
|
172
|
+
// `raw` as its own closer for a `KEY="` that is the file's final line.
|
|
173
|
+
let closed = false;
|
|
174
|
+
while (!closed && index + 1 < physical.length) {
|
|
175
|
+
const next = physical[++index];
|
|
176
|
+
spanned.push(next);
|
|
177
|
+
closed = next.includes(quote);
|
|
178
|
+
}
|
|
179
|
+
// An unterminated quote is REFUSED rather than guessed at. Where the value ends is then
|
|
180
|
+
// unknowable, so every answer this module gives about the file (which keys it holds, what is
|
|
181
|
+
// unmanaged, what it preserved) would be a guess reported as a fact, and the whole point of the
|
|
182
|
+
// four-way report is that it can be trusted. `parseEnv` cannot read such a file either.
|
|
183
|
+
if (!closed) {
|
|
184
|
+
throw new Error(`${key} opens a ${quote === '"' ? 'double' : 'single'}-quoted value that is never closed, ` +
|
|
185
|
+
`so where it ends cannot be known and neither can what else this file holds. Close the ` +
|
|
186
|
+
`quote (or remove it) and run this again.`);
|
|
187
|
+
}
|
|
188
|
+
const joined = spanned.join('\n');
|
|
189
|
+
out.push({
|
|
190
|
+
kind: 'assignment',
|
|
191
|
+
key,
|
|
192
|
+
value: unquote(joined),
|
|
193
|
+
text: `${line.slice(0, line.length - raw.length)}${joined}`,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* The quote character a value OPENS and does not close on its own line, or null.
|
|
200
|
+
*
|
|
201
|
+
* The opening character only, and never a quote found mid-value: `A=it's fine` opens nothing, so
|
|
202
|
+
* treating a stray apostrophe as a continuation would swallow every line after it.
|
|
203
|
+
*/
|
|
204
|
+
function unclosedQuote(raw) {
|
|
205
|
+
const value = raw.trimStart();
|
|
206
|
+
const quote = value.startsWith('"') ? '"' : value.startsWith("'") ? "'" : null;
|
|
207
|
+
if (quote === null)
|
|
208
|
+
return null;
|
|
209
|
+
return value.indexOf(quote, 1) === -1 ? quote : null;
|
|
210
|
+
}
|
|
211
|
+
function unquote(raw) {
|
|
212
|
+
const value = raw.trim();
|
|
213
|
+
const quoted = (value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"));
|
|
214
|
+
return quoted && value.length >= 2 ? value.slice(1, -1) : value;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Everything in the file that is NOT an assignment to a managed key, with each dropped key's
|
|
218
|
+
* leading comment block dropped with it.
|
|
219
|
+
*
|
|
220
|
+
* The comments go too because they were written by a previous run to describe the value beneath
|
|
221
|
+
* them; kept, they would sit above whatever unmanaged variable happened to follow and describe it
|
|
222
|
+
* wrongly.
|
|
223
|
+
*
|
|
224
|
+
* The carried-over header is dropped wherever it appears rather than only above a managed key: the
|
|
225
|
+
* merge re-writes it, and it introduces UNMANAGED content, so the ordinary comment-block rule carries
|
|
226
|
+
* it over and the file grows by one line per run. Matched by {@link isCarriedOverHeader}, so a header
|
|
227
|
+
* a previous version of this code wrote in different words is still recognised.
|
|
228
|
+
*
|
|
229
|
+
* A managed key whose value spans several lines takes ALL of them with it, which is what reading
|
|
230
|
+
* through {@link readEnvLines} buys: dropped a line at a time, the continuation lines are neither
|
|
231
|
+
* comments nor blanks nor assignments to a managed key, so they survive as "unmanaged" content and
|
|
232
|
+
* the file is written back corrupted.
|
|
233
|
+
*/
|
|
234
|
+
function stripAssignments(text, managed) {
|
|
235
|
+
const out = [];
|
|
236
|
+
let comments = [];
|
|
237
|
+
for (const line of readEnvLines(text)) {
|
|
238
|
+
if (line.kind === 'comment') {
|
|
239
|
+
if (!isCarriedOverHeader(line.text))
|
|
240
|
+
comments.push(line.text);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (line.kind === 'blank') {
|
|
244
|
+
// A blank line ends a comment block: whatever it introduced is above it, so the comments are
|
|
245
|
+
// free-standing and belong with the content that is kept.
|
|
246
|
+
out.push(...comments, line.text);
|
|
247
|
+
comments = [];
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if (line.kind === 'assignment' && managed.includes(line.key)) {
|
|
251
|
+
comments = [];
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
out.push(...comments, line.text);
|
|
255
|
+
comments = [];
|
|
256
|
+
}
|
|
257
|
+
out.push(...comments);
|
|
258
|
+
return out.join('\n').replace(/^\n+|\n+$/g, '');
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* One line per managed key, with every secret's value WITHHELD rather than masked.
|
|
262
|
+
*
|
|
263
|
+
* `secretKeys` is the caller's, and it is a SET rather than a predicate on purpose: a pattern match
|
|
264
|
+
* (`key.includes('TOKEN')`) passes today and quietly stops covering the next secret whose name does
|
|
265
|
+
* not say so, and the failure is one nobody sees: a token on somebody's scrollback.
|
|
266
|
+
*
|
|
267
|
+
* Withheld and not masked, because a masked value still states its length and its prefix, and this
|
|
268
|
+
* output is routinely pasted into an issue when the setup did not work.
|
|
269
|
+
*/
|
|
270
|
+
export function describeEntries(entries, secretKeys) {
|
|
271
|
+
return entries.map((entry) => ` ${entry.key}=${secretKeys.has(entry.key) ? '(set, not shown)' : entry.value || '(empty)'}`);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* What the write did, in the order an operator wants it: what changed, then what was left alone.
|
|
275
|
+
*
|
|
276
|
+
* `changed` leads because it is the only category that can surprise anyone, and the promise such a
|
|
277
|
+
* command makes is that it never overwrites a value without saying so.
|
|
278
|
+
*/
|
|
279
|
+
export function describeMerge(merge, path) {
|
|
280
|
+
const lines = [`Wrote ${path}.`];
|
|
281
|
+
if (merge.changed.length > 0) {
|
|
282
|
+
lines.push(` replaced: ${merge.changed.join(', ')} (the previous values are gone)`);
|
|
283
|
+
}
|
|
284
|
+
if (merge.added.length > 0)
|
|
285
|
+
lines.push(` added: ${merge.added.join(', ')}`);
|
|
286
|
+
if (merge.kept.length > 0)
|
|
287
|
+
lines.push(` unchanged: ${merge.kept.join(', ')}`);
|
|
288
|
+
if (merge.preserved.length > 0) {
|
|
289
|
+
lines.push(` left alone (not managed here): ${merge.preserved.join(', ')}`);
|
|
290
|
+
}
|
|
291
|
+
return lines;
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=envMerge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envMerge.js","sourceRoot":"","sources":["../src/envMerge.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { decodeToken, normalizeApiServerUrl, readApiServerCommand, readTokenComm
|
|
|
9
9
|
export { DEFAULT_INGRESS_PORT, INGRESS_HOST_TEMPLATE, type IngressReadiness, ingressHostTemplate, ingressUrlPort, } from './k3s-ingress.js';
|
|
10
10
|
export { classifyHost, hasServerVersion, type HostDetections, type HostState, isRecreateOffer, type Offer, type OfferId, parseK3dClusters, parseKindClusters, probeHost, RECREATE_OFFERS, recreateOfferFor, recreateTargetForContext, type ToolDetection, } from './k3s-probe.js';
|
|
11
11
|
export { buildFrontendEnv, buildLocalEnv, type EnvEntry, type FrontendEnvInput, type LocalEnvInput, renderEnvFile, } from './env.js';
|
|
12
|
+
export { CARRIED_OVER_HEADER, describeEntries, describeMerge, type EnvMerge, mergeEnvFile, quoteEnvValue, readAssignments, } from './envMerge.js';
|
|
12
13
|
export { buildGitignore, mergeGitignore, REQUIRED_GITIGNORE_RULES } from './gitignore.js';
|
|
13
14
|
export { type Io, createConsoleIo } from './io.js';
|
|
14
15
|
export { type BootstrapInput, buildPlan, type PlannedFile } from './plan.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,UAAU,EACf,SAAS,EACT,YAAY,EACZ,KAAK,UAAU,EACf,eAAe,EACf,SAAS,EACT,QAAQ,GACT,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC9E,OAAO,EAAE,KAAK,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AACnF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAA;AACzC,OAAO,EACL,KAAK,OAAO,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,KAAK,SAAS,EACd,iBAAiB,EACjB,UAAU,EACV,KAAK,WAAW,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,mBAAmB,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACtF,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,0BAA0B,EAC1B,YAAY,EACZ,KAAK,eAAe,EACpB,+BAA+B,GAChC,MAAM,kBAAkB,CAAA;AAUzB,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,mBAAmB,EACnB,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,eAAe,EACf,KAAK,KAAK,EACV,KAAK,OAAO,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,aAAa,GACd,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,UAAU,EACf,SAAS,EACT,YAAY,EACZ,KAAK,UAAU,EACf,eAAe,EACf,SAAS,EACT,QAAQ,GACT,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC9E,OAAO,EAAE,KAAK,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AACnF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAA;AACzC,OAAO,EACL,KAAK,OAAO,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,KAAK,SAAS,EACd,iBAAiB,EACjB,UAAU,EACV,KAAK,WAAW,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,mBAAmB,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACtF,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,0BAA0B,EAC1B,YAAY,EACZ,KAAK,eAAe,EACpB,+BAA+B,GAChC,MAAM,kBAAkB,CAAA;AAUzB,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,mBAAmB,EACnB,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,eAAe,EACf,KAAK,KAAK,EACV,KAAK,OAAO,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,aAAa,GACd,MAAM,UAAU,CAAA;AAKjB,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,KAAK,QAAQ,EACb,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AACzF,OAAO,EAAE,KAAK,EAAE,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,KAAK,cAAc,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AAC5E,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EACL,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,eAAe,EACf,KAAK,aAAa,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,aAAa,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,SAAS,EACT,aAAa,EACb,aAAa,EACb,KAAK,WAAW,GACjB,MAAM,UAAU,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,11 @@ export { decodeToken, normalizeApiServerUrl, readApiServerCommand, readTokenComm
|
|
|
20
20
|
export { DEFAULT_INGRESS_PORT, INGRESS_HOST_TEMPLATE, ingressHostTemplate, ingressUrlPort, } from './k3s-ingress.js';
|
|
21
21
|
export { classifyHost, hasServerVersion, isRecreateOffer, parseK3dClusters, parseKindClusters, probeHost, RECREATE_OFFERS, recreateOfferFor, recreateTargetForContext, } from './k3s-probe.js';
|
|
22
22
|
export { buildFrontendEnv, buildLocalEnv, renderEnvFile, } from './env.js';
|
|
23
|
+
// The MERGE half of writing a `.env`, beside the render half it completes. Exported for the same
|
|
24
|
+
// reason the k3s reads are: other in-repo tooling (the acceptance suite's `configure`) writes a
|
|
25
|
+
// `.env` a person may already have edited, and the five ways to get that subtly wrong are each a
|
|
26
|
+
// silent failure. See the module header for what they are.
|
|
27
|
+
export { CARRIED_OVER_HEADER, describeEntries, describeMerge, mergeEnvFile, quoteEnvValue, readAssignments, } from './envMerge.js';
|
|
23
28
|
export { buildGitignore, mergeGitignore, REQUIRED_GITIGNORE_RULES } from './gitignore.js';
|
|
24
29
|
export { createConsoleIo } from './io.js';
|
|
25
30
|
export { buildPlan } from './plan.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,8FAA8F;AAC9F,OAAO,EAEL,SAAS,EACT,YAAY,EAEZ,eAAe,EACf,SAAS,EACT,QAAQ,GACT,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,SAAS,EAAsB,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC9E,OAAO,EAAuB,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AACnF,OAAO,EAAmB,MAAM,SAAS,CAAA;AACzC,OAAO,EAEL,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAE1B,iBAAiB,EACjB,UAAU,GAEX,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,mBAAmB,EAAgC,QAAQ,EAAE,MAAM,UAAU,CAAA;AACtF,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,0BAA0B,EAC1B,YAAY,EAEZ,+BAA+B,GAChC,MAAM,kBAAkB,CAAA;AACzB,gGAAgG;AAChG,iGAAiG;AACjG,kGAAkG;AAClG,6FAA6F;AAC7F,EAAE;AACF,kGAAkG;AAClG,kGAAkG;AAClG,6FAA6F;AAC7F,qFAAqF;AACrF,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EAErB,mBAAmB,EACnB,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAGhB,eAAe,EAGf,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,wBAAwB,GAEzB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,gBAAgB,EAChB,aAAa,EAIb,aAAa,GACd,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AACzF,OAAO,EAAW,eAAe,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAuB,SAAS,EAAoB,MAAM,WAAW,CAAA;AAC5E,OAAO,EAAE,eAAe,EAA2C,MAAM,cAAc,CAAA;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EACL,kBAAkB,EAElB,eAAe,EAEf,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,GAEjB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EAGnB,aAAa,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,SAAS,EACT,aAAa,EACb,aAAa,GAEd,MAAM,UAAU,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,8FAA8F;AAC9F,OAAO,EAEL,SAAS,EACT,YAAY,EAEZ,eAAe,EACf,SAAS,EACT,QAAQ,GACT,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,SAAS,EAAsB,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC9E,OAAO,EAAuB,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AACnF,OAAO,EAAmB,MAAM,SAAS,CAAA;AACzC,OAAO,EAEL,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAE1B,iBAAiB,EACjB,UAAU,GAEX,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,mBAAmB,EAAgC,QAAQ,EAAE,MAAM,UAAU,CAAA;AACtF,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,0BAA0B,EAC1B,YAAY,EAEZ,+BAA+B,GAChC,MAAM,kBAAkB,CAAA;AACzB,gGAAgG;AAChG,iGAAiG;AACjG,kGAAkG;AAClG,6FAA6F;AAC7F,EAAE;AACF,kGAAkG;AAClG,kGAAkG;AAClG,6FAA6F;AAC7F,qFAAqF;AACrF,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EAErB,mBAAmB,EACnB,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAGhB,eAAe,EAGf,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,wBAAwB,GAEzB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,gBAAgB,EAChB,aAAa,EAIb,aAAa,GACd,MAAM,UAAU,CAAA;AACjB,iGAAiG;AACjG,gGAAgG;AAChG,iGAAiG;AACjG,2DAA2D;AAC3D,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,aAAa,EAEb,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AACzF,OAAO,EAAW,eAAe,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAuB,SAAS,EAAoB,MAAM,WAAW,CAAA;AAC5E,OAAO,EAAE,eAAe,EAA2C,MAAM,cAAc,CAAA;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EACL,kBAAkB,EAElB,eAAe,EAEf,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,GAEjB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EAGnB,aAAa,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,SAAS,EACT,aAAa,EACb,aAAa,GAEd,MAAM,UAAU,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Bootstrap CLI for the Agent Architecture Board: scaffold a local-mode deployment (Node/local backend + frontend SPA) on your own machine — generates the crypto secrets, populates and gitignores the .env files, and mints a GitHub/GitLab personal access token by opening the browser at the right pre-scoped URL.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bootstrap",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"typescript": "7.0.2",
|
|
42
42
|
"valibot": "^1.4.2",
|
|
43
43
|
"vitest": "^4.1.10",
|
|
44
|
-
"@cat-factory/contracts": "0.
|
|
45
|
-
"@cat-factory/kernel": "0.
|
|
44
|
+
"@cat-factory/contracts": "0.320.0",
|
|
45
|
+
"@cat-factory/kernel": "0.310.0"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "tsc -b tsconfig.build.json",
|