@kitsy/cnos 1.6.1 → 1.7.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/build/index.cjs +1332 -156
- package/dist/build/index.d.cts +1 -1
- package/dist/build/index.d.ts +1 -1
- package/dist/build/index.js +36 -14
- package/dist/{chunk-JYWQFMW5.js → chunk-2DGT7N7E.js} +1 -1
- package/dist/{chunk-S7H2UULC.js → chunk-2TL42I6M.js} +1323 -139
- package/dist/{chunk-MW4OVAT3.js → chunk-5KIQCYFH.js} +1 -1
- package/dist/{chunk-N32UN66E.js → chunk-CV3SLBYZ.js} +8 -8
- package/dist/{chunk-XSUP7JKH.js → chunk-GHGJFRDL.js} +6 -2
- package/dist/{chunk-BMAD24KC.js → chunk-OA7FQGAG.js} +1 -1
- package/dist/{chunk-6FAX2VKQ.js → chunk-PFT56ID2.js} +195 -28
- package/dist/{chunk-VGZREX5D.js → chunk-RYIARE4M.js} +1 -1
- package/dist/{chunk-UR7CHHNN.js → chunk-TT4NV56Z.js} +3 -2
- package/dist/{chunk-UJBQS7CJ.js → chunk-UL63DFLS.js} +1 -1
- package/dist/configure/index.cjs +1309 -155
- package/dist/configure/index.d.cts +3 -3
- package/dist/configure/index.d.ts +3 -3
- package/dist/configure/index.js +8 -8
- package/dist/{plugin-CKrBlWGI.d.cts → core-BJ8xewez.d.cts} +142 -60
- package/dist/{plugin-CKrBlWGI.d.ts → core-BJ8xewez.d.ts} +142 -60
- package/dist/{envNaming-B7Mztkcf.d.ts → envNaming-BRyiuPoI.d.ts} +1 -1
- package/dist/{envNaming-gMVnPOfe.d.cts → envNaming-rx71gpi0.d.cts} +1 -1
- package/dist/index.cjs +1548 -227
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -10
- package/dist/internal.cjs +831 -122
- package/dist/internal.d.cts +56 -3
- package/dist/internal.d.ts +56 -3
- package/dist/internal.js +30 -3
- package/dist/plugin/basic-schema.cjs +49 -23
- package/dist/plugin/basic-schema.d.cts +1 -1
- package/dist/plugin/basic-schema.d.ts +1 -1
- package/dist/plugin/basic-schema.js +2 -2
- package/dist/plugin/cli-args.cjs +38 -23
- package/dist/plugin/cli-args.d.cts +1 -1
- package/dist/plugin/cli-args.d.ts +1 -1
- package/dist/plugin/cli-args.js +2 -2
- package/dist/plugin/dotenv.cjs +46 -31
- package/dist/plugin/dotenv.d.cts +2 -2
- package/dist/plugin/dotenv.d.ts +2 -2
- package/dist/plugin/dotenv.js +2 -2
- package/dist/plugin/env-export.cjs +56 -27
- package/dist/plugin/env-export.d.cts +2 -2
- package/dist/plugin/env-export.d.ts +2 -2
- package/dist/plugin/env-export.js +2 -2
- package/dist/plugin/filesystem.cjs +61 -39
- package/dist/plugin/filesystem.d.cts +1 -1
- package/dist/plugin/filesystem.d.ts +1 -1
- package/dist/plugin/filesystem.js +2 -2
- package/dist/plugin/process-env.cjs +40 -25
- package/dist/plugin/process-env.d.cts +2 -2
- package/dist/plugin/process-env.d.ts +2 -2
- package/dist/plugin/process-env.js +2 -2
- package/dist/runtime/index.cjs +1548 -227
- package/dist/runtime/index.d.cts +3 -1
- package/dist/runtime/index.d.ts +3 -1
- package/dist/runtime/index.js +10 -10
- package/dist/toPublicEnv-CCSgdvI9.d.ts +13 -0
- package/dist/toPublicEnv-ivRtLjcw.d.cts +13 -0
- package/package.json +1 -1
- package/dist/toPublicEnv-CmBsy53P.d.cts +0 -7
- package/dist/toPublicEnv-q6VwWxXZ.d.ts +0 -7
package/dist/internal.cjs
CHANGED
|
@@ -40,6 +40,7 @@ __export(internal_exports, {
|
|
|
40
40
|
clearAllVaultSessionKeys: () => clearAllVaultSessionKeys,
|
|
41
41
|
clearVaultSessionKey: () => clearVaultSessionKey,
|
|
42
42
|
compareSchemaToGraph: () => compareSchemaToGraph,
|
|
43
|
+
createRemoteRootCacheKey: () => createRemoteRootCacheKey,
|
|
43
44
|
createSecretVault: () => createSecretVault,
|
|
44
45
|
createSecretVaultProvider: () => createSecretVaultProvider,
|
|
45
46
|
deleteLocalSecret: () => deleteLocalSecret,
|
|
@@ -56,23 +57,32 @@ __export(internal_exports, {
|
|
|
56
57
|
getVaultPassphraseEnvVar: () => getVaultPassphraseEnvVar,
|
|
57
58
|
getVaultSessionKeyEnvVar: () => getVaultSessionKeyEnvVar,
|
|
58
59
|
graphRequiresSecretHydration: () => graphRequiresSecretHydration,
|
|
60
|
+
isDerivedValue: () => isDerivedValue,
|
|
61
|
+
isImmutableGitRef: () => isImmutableGitRef,
|
|
59
62
|
isPassphraseEnvRef: () => isPassphraseEnvRef,
|
|
60
63
|
isSecretReference: () => isSecretReference,
|
|
61
64
|
listLocalSecrets: () => listLocalSecrets,
|
|
62
65
|
listSecretVaults: () => listSecretVaults,
|
|
63
66
|
loadManifest: () => loadManifest,
|
|
67
|
+
normalizeDerivedValue: () => normalizeDerivedValue,
|
|
68
|
+
parseDerivation: () => parseDerivation,
|
|
69
|
+
parseGitUri: () => parseGitUri,
|
|
64
70
|
parseYaml: () => parseYaml,
|
|
65
71
|
proposeMapping: () => proposeMapping,
|
|
66
72
|
readKeychain: () => readKeychain,
|
|
67
73
|
readLocalSecret: () => readLocalSecret,
|
|
74
|
+
readRemoteRootCacheMetadata: () => readRemoteRootCacheMetadata,
|
|
68
75
|
readRuntimeGraphFromEnv: () => readRuntimeGraphFromEnv,
|
|
69
76
|
readServerProjectionFromEnv: () => readServerProjectionFromEnv,
|
|
70
77
|
readVaultMetadata: () => readVaultMetadata,
|
|
71
78
|
removeLocalVaultFiles: () => removeLocalVaultFiles,
|
|
79
|
+
resolveCnosCacheRoot: () => resolveCnosCacheRoot,
|
|
72
80
|
resolveCodegenPaths: () => resolveCodegenPaths,
|
|
73
81
|
resolveConfigDocumentPath: () => resolveConfigDocumentPath,
|
|
74
82
|
resolveConfiguredVaultPassphrase: () => resolveConfiguredVaultPassphrase,
|
|
75
83
|
resolveManifestRoot: () => resolveManifestRoot,
|
|
84
|
+
resolveRemoteRootCachePaths: () => resolveRemoteRootCachePaths,
|
|
85
|
+
resolveRootUri: () => resolveRootUri,
|
|
76
86
|
resolveSecretPassphrase: () => resolveSecretPassphrase,
|
|
77
87
|
resolveSecretStoreRoot: () => resolveSecretStoreRoot,
|
|
78
88
|
resolveSecretVaultFile: () => resolveSecretVaultFile,
|
|
@@ -85,12 +95,15 @@ __export(internal_exports, {
|
|
|
85
95
|
serializeSecretPayload: () => serializeSecretPayload,
|
|
86
96
|
serializeServerProjection: () => serializeServerProjection,
|
|
87
97
|
stringifyYaml: () => stringifyYaml,
|
|
98
|
+
validateDerivedTargetNamespace: () => validateDerivedTargetNamespace,
|
|
99
|
+
validateParsedDerivation: () => validateParsedDerivation,
|
|
88
100
|
validateRuntime: () => validateRuntime,
|
|
89
101
|
watchFiles: () => watchFiles,
|
|
90
102
|
watchSchema: () => watchSchema,
|
|
91
103
|
writeCodegenOutput: () => writeCodegenOutput,
|
|
92
104
|
writeKeychain: () => writeKeychain,
|
|
93
105
|
writeLocalSecret: () => writeLocalSecret,
|
|
106
|
+
writeRemoteRootCacheMetadata: () => writeRemoteRootCacheMetadata,
|
|
94
107
|
writeVaultSessionKey: () => writeVaultSessionKey
|
|
95
108
|
});
|
|
96
109
|
module.exports = __toCommonJS(internal_exports);
|
|
@@ -124,6 +137,317 @@ var CnosAuthenticationError = class extends CnosError {
|
|
|
124
137
|
super(message);
|
|
125
138
|
}
|
|
126
139
|
};
|
|
140
|
+
var CnosDerivedExpressionError = class extends CnosError {
|
|
141
|
+
constructor(message, expression) {
|
|
142
|
+
super(expression ? `${message} (${expression})` : message);
|
|
143
|
+
this.expression = expression;
|
|
144
|
+
}
|
|
145
|
+
expression;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// ../core/src/derive/builtins.ts
|
|
149
|
+
function stringify(value) {
|
|
150
|
+
if (value === void 0 || value === null) {
|
|
151
|
+
return "";
|
|
152
|
+
}
|
|
153
|
+
if (typeof value === "string") {
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
157
|
+
return String(value);
|
|
158
|
+
}
|
|
159
|
+
return JSON.stringify(value);
|
|
160
|
+
}
|
|
161
|
+
var DERIVE_BUILTINS = {
|
|
162
|
+
concat: (...args) => args.map((value) => stringify(value)).join(""),
|
|
163
|
+
coalesce: (...args) => args.find((value) => value !== void 0 && value !== null),
|
|
164
|
+
when: (condition, whenTrue, whenFalse) => condition ? whenTrue : whenFalse,
|
|
165
|
+
exists: (value) => value !== void 0 && value !== null,
|
|
166
|
+
eq: (left, right) => left === right,
|
|
167
|
+
ne: (left, right) => left !== right
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// ../core/src/derive/parser.ts
|
|
171
|
+
function isWhitespace(value) {
|
|
172
|
+
return value === " " || value === "\n" || value === "\r" || value === " ";
|
|
173
|
+
}
|
|
174
|
+
function skipWhitespace(state) {
|
|
175
|
+
while (isWhitespace(state.source[state.index])) {
|
|
176
|
+
state.index += 1;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function isIdentifierStart(value) {
|
|
180
|
+
return typeof value === "string" && /[A-Za-z_]/.test(value);
|
|
181
|
+
}
|
|
182
|
+
function isIdentifierPart(value) {
|
|
183
|
+
return typeof value === "string" && /[A-Za-z0-9_.-]/.test(value);
|
|
184
|
+
}
|
|
185
|
+
function errorAt(state, message) {
|
|
186
|
+
throw new CnosDerivedExpressionError(`${message} at position ${state.index + 1}`, state.source);
|
|
187
|
+
}
|
|
188
|
+
function parseStringLiteral(state) {
|
|
189
|
+
const quote = state.source[state.index];
|
|
190
|
+
if (quote !== "'") {
|
|
191
|
+
errorAt(state, "Expected string literal");
|
|
192
|
+
}
|
|
193
|
+
state.index += 1;
|
|
194
|
+
let value = "";
|
|
195
|
+
while (state.index < state.source.length) {
|
|
196
|
+
const current = state.source[state.index];
|
|
197
|
+
if (current === "\\") {
|
|
198
|
+
const next = state.source[state.index + 1];
|
|
199
|
+
if (next === void 0) {
|
|
200
|
+
errorAt(state, "Unterminated escape sequence");
|
|
201
|
+
}
|
|
202
|
+
value += next;
|
|
203
|
+
state.index += 2;
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (current === "'") {
|
|
207
|
+
state.index += 1;
|
|
208
|
+
return {
|
|
209
|
+
type: "literal",
|
|
210
|
+
value
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
value += current;
|
|
214
|
+
state.index += 1;
|
|
215
|
+
}
|
|
216
|
+
errorAt(state, "Unterminated string literal");
|
|
217
|
+
}
|
|
218
|
+
function parseNumberLiteral(state) {
|
|
219
|
+
const start = state.index;
|
|
220
|
+
while (/[0-9]/.test(state.source[state.index] ?? "")) {
|
|
221
|
+
state.index += 1;
|
|
222
|
+
}
|
|
223
|
+
if (state.source[state.index] === ".") {
|
|
224
|
+
state.index += 1;
|
|
225
|
+
while (/[0-9]/.test(state.source[state.index] ?? "")) {
|
|
226
|
+
state.index += 1;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
type: "literal",
|
|
231
|
+
value: Number(state.source.slice(start, state.index))
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function parseIdentifier(state) {
|
|
235
|
+
if (!isIdentifierStart(state.source[state.index])) {
|
|
236
|
+
errorAt(state, "Expected identifier");
|
|
237
|
+
}
|
|
238
|
+
const start = state.index;
|
|
239
|
+
state.index += 1;
|
|
240
|
+
while (isIdentifierPart(state.source[state.index])) {
|
|
241
|
+
state.index += 1;
|
|
242
|
+
}
|
|
243
|
+
return state.source.slice(start, state.index);
|
|
244
|
+
}
|
|
245
|
+
function parseArguments(state) {
|
|
246
|
+
const args = [];
|
|
247
|
+
skipWhitespace(state);
|
|
248
|
+
if (state.source[state.index] === ")") {
|
|
249
|
+
state.index += 1;
|
|
250
|
+
return args;
|
|
251
|
+
}
|
|
252
|
+
while (state.index < state.source.length) {
|
|
253
|
+
args.push(parseExpressionNode(state));
|
|
254
|
+
skipWhitespace(state);
|
|
255
|
+
const current = state.source[state.index];
|
|
256
|
+
if (current === ",") {
|
|
257
|
+
state.index += 1;
|
|
258
|
+
skipWhitespace(state);
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (current === ")") {
|
|
262
|
+
state.index += 1;
|
|
263
|
+
return args;
|
|
264
|
+
}
|
|
265
|
+
errorAt(state, 'Expected "," or ")"');
|
|
266
|
+
}
|
|
267
|
+
errorAt(state, "Unterminated function call");
|
|
268
|
+
}
|
|
269
|
+
function parseIdentifierOrCall(state) {
|
|
270
|
+
const identifier = parseIdentifier(state);
|
|
271
|
+
skipWhitespace(state);
|
|
272
|
+
if (state.source[state.index] === "(") {
|
|
273
|
+
if (!(identifier in DERIVE_BUILTINS)) {
|
|
274
|
+
throw new CnosDerivedExpressionError(`Unknown derive function: ${identifier}`, state.source);
|
|
275
|
+
}
|
|
276
|
+
state.index += 1;
|
|
277
|
+
return {
|
|
278
|
+
type: "call",
|
|
279
|
+
name: identifier,
|
|
280
|
+
args: parseArguments(state)
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
if (identifier === "true" || identifier === "false") {
|
|
284
|
+
return {
|
|
285
|
+
type: "literal",
|
|
286
|
+
value: identifier === "true"
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
if (identifier === "null") {
|
|
290
|
+
return {
|
|
291
|
+
type: "literal",
|
|
292
|
+
value: null
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
type: "ref",
|
|
297
|
+
path: identifier
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
function parseExpressionNode(state) {
|
|
301
|
+
skipWhitespace(state);
|
|
302
|
+
const current = state.source[state.index];
|
|
303
|
+
if (current === "'") {
|
|
304
|
+
return parseStringLiteral(state);
|
|
305
|
+
}
|
|
306
|
+
if (/[0-9]/.test(current ?? "")) {
|
|
307
|
+
return parseNumberLiteral(state);
|
|
308
|
+
}
|
|
309
|
+
if (isIdentifierStart(current)) {
|
|
310
|
+
return parseIdentifierOrCall(state);
|
|
311
|
+
}
|
|
312
|
+
errorAt(state, "Unexpected token");
|
|
313
|
+
}
|
|
314
|
+
function parseExpression(source) {
|
|
315
|
+
const state = {
|
|
316
|
+
source,
|
|
317
|
+
index: 0
|
|
318
|
+
};
|
|
319
|
+
const ast = parseExpressionNode(state);
|
|
320
|
+
skipWhitespace(state);
|
|
321
|
+
if (state.index !== source.length) {
|
|
322
|
+
errorAt(state, "Unexpected trailing input");
|
|
323
|
+
}
|
|
324
|
+
return ast;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// ../core/src/derive/templateParser.ts
|
|
328
|
+
function toLiteral(value) {
|
|
329
|
+
return {
|
|
330
|
+
type: "literal",
|
|
331
|
+
value
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
function toRef(path17) {
|
|
335
|
+
return {
|
|
336
|
+
type: "ref",
|
|
337
|
+
path: path17
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
function parseTemplate(source) {
|
|
341
|
+
const parts = [];
|
|
342
|
+
let cursor = 0;
|
|
343
|
+
while (cursor < source.length) {
|
|
344
|
+
const start = source.indexOf("${", cursor);
|
|
345
|
+
if (start < 0) {
|
|
346
|
+
if (cursor < source.length) {
|
|
347
|
+
parts.push(toLiteral(source.slice(cursor)));
|
|
348
|
+
}
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
if (start > cursor) {
|
|
352
|
+
parts.push(toLiteral(source.slice(cursor, start)));
|
|
353
|
+
}
|
|
354
|
+
const end = source.indexOf("}", start + 2);
|
|
355
|
+
if (end < 0) {
|
|
356
|
+
throw new CnosDerivedExpressionError(`Invalid derivation template: unclosed \${...} at position ${start + 1}`, source);
|
|
357
|
+
}
|
|
358
|
+
const ref = source.slice(start + 2, end).trim();
|
|
359
|
+
if (!ref) {
|
|
360
|
+
throw new CnosDerivedExpressionError(`Invalid derivation template: empty reference at position ${start + 1}`, source);
|
|
361
|
+
}
|
|
362
|
+
if (!/^[A-Za-z_][A-Za-z0-9_.-]*$/.test(ref)) {
|
|
363
|
+
throw new CnosDerivedExpressionError(`Invalid derivation template reference "${ref}"`, source);
|
|
364
|
+
}
|
|
365
|
+
parts.push(toRef(ref));
|
|
366
|
+
cursor = end + 1;
|
|
367
|
+
}
|
|
368
|
+
if (parts.length === 0) {
|
|
369
|
+
return toLiteral("");
|
|
370
|
+
}
|
|
371
|
+
if (parts.length === 1) {
|
|
372
|
+
return parts[0];
|
|
373
|
+
}
|
|
374
|
+
return {
|
|
375
|
+
type: "call",
|
|
376
|
+
name: "concat",
|
|
377
|
+
args: parts
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// ../core/src/derive/evaluator.ts
|
|
382
|
+
function isDerivedValue(value) {
|
|
383
|
+
return Boolean(
|
|
384
|
+
value && typeof value === "object" && !Array.isArray(value) && "$derive" in value
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
function extractRefs(node, refs = /* @__PURE__ */ new Set()) {
|
|
388
|
+
if (node.type === "ref") {
|
|
389
|
+
refs.add(node.path);
|
|
390
|
+
return refs;
|
|
391
|
+
}
|
|
392
|
+
if (node.type === "call") {
|
|
393
|
+
for (const arg of node.args) {
|
|
394
|
+
extractRefs(arg, refs);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return refs;
|
|
398
|
+
}
|
|
399
|
+
function parseDerivation(value) {
|
|
400
|
+
const source = typeof value.$derive === "string" ? value.$derive : value.$derive?.expr;
|
|
401
|
+
if (typeof source !== "string") {
|
|
402
|
+
throw new CnosDerivedExpressionError("Derived value requires either a template string or { expr } object");
|
|
403
|
+
}
|
|
404
|
+
const type = typeof value.$derive === "string" ? "template" : "expression";
|
|
405
|
+
const ast = type === "template" ? parseTemplate(source) : parseExpression(source);
|
|
406
|
+
const refs = Array.from(extractRefs(ast)).sort((left, right) => left.localeCompare(right));
|
|
407
|
+
return {
|
|
408
|
+
type,
|
|
409
|
+
raw: source,
|
|
410
|
+
ast,
|
|
411
|
+
refs,
|
|
412
|
+
runtimeRefs: [],
|
|
413
|
+
isRuntimeDependent: false
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// ../core/src/derive/validate.ts
|
|
418
|
+
var FORBIDDEN_TARGET_NAMESPACES = /* @__PURE__ */ new Set(["public", "meta", "secret"]);
|
|
419
|
+
var FORBIDDEN_REF_NAMESPACES = /* @__PURE__ */ new Set(["public", "secret"]);
|
|
420
|
+
function validateDerivedTargetNamespace(manifest, namespace) {
|
|
421
|
+
if (FORBIDDEN_TARGET_NAMESPACES.has(namespace)) {
|
|
422
|
+
throw new CnosManifestError(`Cannot define derived values under namespace "${namespace}".`);
|
|
423
|
+
}
|
|
424
|
+
if (manifest.runtimeNamespaces[namespace]) {
|
|
425
|
+
throw new CnosManifestError(`Cannot define derived values under runtime namespace "${namespace}".`);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
function validateParsedDerivation(manifest, parsed) {
|
|
429
|
+
for (const ref of parsed.refs) {
|
|
430
|
+
const namespace = ref.split(".")[0] ?? "";
|
|
431
|
+
if (FORBIDDEN_REF_NAMESPACES.has(namespace)) {
|
|
432
|
+
throw new CnosDerivedExpressionError(`Derived expressions cannot reference ${namespace}.* keys.`, parsed.raw);
|
|
433
|
+
}
|
|
434
|
+
if (manifest.runtimeNamespaces[namespace]) {
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
if (!manifest.namespaces[namespace] && namespace !== "value" && namespace !== "meta") {
|
|
438
|
+
throw new CnosDerivedExpressionError(`Unknown derive reference namespace: ${namespace}`, parsed.raw);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
function normalizeDerivedValue(templateOrExpr, expr = false) {
|
|
443
|
+
return expr ? {
|
|
444
|
+
$derive: {
|
|
445
|
+
expr: templateOrExpr
|
|
446
|
+
}
|
|
447
|
+
} : {
|
|
448
|
+
$derive: templateOrExpr
|
|
449
|
+
};
|
|
450
|
+
}
|
|
127
451
|
|
|
128
452
|
// ../core/src/keychain/linux.ts
|
|
129
453
|
var import_node_child_process = require("child_process");
|
|
@@ -232,17 +556,17 @@ async function writeKeychain(entry, value) {
|
|
|
232
556
|
}
|
|
233
557
|
|
|
234
558
|
// ../core/src/manifest/loadManifest.ts
|
|
235
|
-
var
|
|
236
|
-
var
|
|
559
|
+
var import_promises5 = require("fs/promises");
|
|
560
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
237
561
|
|
|
238
562
|
// ../core/src/utils/path.ts
|
|
239
|
-
var
|
|
240
|
-
var
|
|
241
|
-
var
|
|
563
|
+
var import_promises4 = require("fs/promises");
|
|
564
|
+
var import_node_os3 = __toESM(require("os"), 1);
|
|
565
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
242
566
|
|
|
243
567
|
// ../core/src/discovery/findCnosrc.ts
|
|
244
|
-
var
|
|
245
|
-
var
|
|
568
|
+
var import_promises3 = require("fs/promises");
|
|
569
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
246
570
|
|
|
247
571
|
// ../core/src/utils/yaml.ts
|
|
248
572
|
var import_yaml = require("yaml");
|
|
@@ -253,10 +577,315 @@ function stringifyYaml(value) {
|
|
|
253
577
|
return (0, import_yaml.stringify)(value);
|
|
254
578
|
}
|
|
255
579
|
|
|
580
|
+
// ../core/src/discovery/resolveRoot.ts
|
|
581
|
+
var import_promises2 = require("fs/promises");
|
|
582
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
583
|
+
var import_node_child_process4 = require("child_process");
|
|
584
|
+
var import_node_os2 = __toESM(require("os"), 1);
|
|
585
|
+
|
|
586
|
+
// ../core/src/discovery/parseGitUri.ts
|
|
587
|
+
function isGitRootUri(uri) {
|
|
588
|
+
return /^git\+[a-z]+:\/\//i.test(uri);
|
|
589
|
+
}
|
|
590
|
+
function parseGitUri(uri) {
|
|
591
|
+
if (!isGitRootUri(uri)) {
|
|
592
|
+
throw new CnosDiscoveryError(`Unsupported git root URI: ${uri}`);
|
|
593
|
+
}
|
|
594
|
+
const withoutPrefix = uri.slice("git+".length);
|
|
595
|
+
const hashIndex = withoutPrefix.indexOf("#");
|
|
596
|
+
if (hashIndex < 0) {
|
|
597
|
+
throw new CnosDiscoveryError(
|
|
598
|
+
`Git root URI must include a #ref (tag, branch, or commit). Got: ${uri}`
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
const cloneUrl = withoutPrefix.slice(0, hashIndex);
|
|
602
|
+
const fragment = withoutPrefix.slice(hashIndex + 1);
|
|
603
|
+
const separatorIndex = fragment.indexOf(":");
|
|
604
|
+
const ref = (separatorIndex >= 0 ? fragment.slice(0, separatorIndex) : fragment).trim();
|
|
605
|
+
const subpath = (separatorIndex >= 0 ? fragment.slice(separatorIndex + 1) : ".cnos").trim() || ".cnos";
|
|
606
|
+
const protocol = cloneUrl.slice(0, cloneUrl.indexOf("://"));
|
|
607
|
+
if (!cloneUrl || !ref) {
|
|
608
|
+
throw new CnosDiscoveryError(
|
|
609
|
+
`Git root URI must include both a clone URL and #ref. Got: ${uri}`
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
return {
|
|
613
|
+
uri,
|
|
614
|
+
cloneUrl,
|
|
615
|
+
ref,
|
|
616
|
+
subpath,
|
|
617
|
+
transport: protocol === "https" ? "https" : protocol === "ssh" ? "ssh" : protocol === "file" ? "file" : "custom"
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// ../core/src/discovery/cache/cacheManager.ts
|
|
622
|
+
var SEMVER_TAG_RE = /^v?\d+\.\d+(?:\.\d+)?(?:[-+][A-Za-z0-9.-]+)?$/;
|
|
623
|
+
var COMMIT_SHA_RE = /^[0-9a-f]{40}$/i;
|
|
624
|
+
function isImmutableGitRef(ref) {
|
|
625
|
+
return SEMVER_TAG_RE.test(ref) || COMMIT_SHA_RE.test(ref);
|
|
626
|
+
}
|
|
627
|
+
function resolveRemoteRootCacheTtlSeconds(mode = "runtime", processEnv = process.env, override) {
|
|
628
|
+
if (typeof override === "number" && Number.isFinite(override) && override >= 0) {
|
|
629
|
+
return override;
|
|
630
|
+
}
|
|
631
|
+
const fromEnv = Number(processEnv.CNOS_CACHE_TTL ?? "");
|
|
632
|
+
if (Number.isFinite(fromEnv) && fromEnv >= 0) {
|
|
633
|
+
return fromEnv;
|
|
634
|
+
}
|
|
635
|
+
switch (mode) {
|
|
636
|
+
case "build":
|
|
637
|
+
return 0;
|
|
638
|
+
case "dev":
|
|
639
|
+
return 30;
|
|
640
|
+
case "runtime":
|
|
641
|
+
default:
|
|
642
|
+
return 300;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
function isRemoteRootCacheFresh(metadata, options) {
|
|
646
|
+
if (!metadata || options.forceRefresh) {
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
if (metadata.uri !== options.uri || metadata.ref !== options.ref) {
|
|
650
|
+
return false;
|
|
651
|
+
}
|
|
652
|
+
if (metadata.isImmutable) {
|
|
653
|
+
return true;
|
|
654
|
+
}
|
|
655
|
+
const ttlSeconds = resolveRemoteRootCacheTtlSeconds(
|
|
656
|
+
options.mode,
|
|
657
|
+
options.processEnv,
|
|
658
|
+
options.ttlSeconds
|
|
659
|
+
);
|
|
660
|
+
if (ttlSeconds <= 0) {
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
const cachedAtMs = Date.parse(metadata.cachedAt);
|
|
664
|
+
if (Number.isNaN(cachedAtMs)) {
|
|
665
|
+
return false;
|
|
666
|
+
}
|
|
667
|
+
return Date.now() - cachedAtMs <= ttlSeconds * 1e3;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// ../core/src/discovery/cache/cacheMetadata.ts
|
|
671
|
+
var import_promises = require("fs/promises");
|
|
672
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
673
|
+
async function readRemoteRootCacheMetadata(metaPath) {
|
|
674
|
+
try {
|
|
675
|
+
const source = await (0, import_promises.readFile)(metaPath, "utf8");
|
|
676
|
+
const parsed = JSON.parse(source);
|
|
677
|
+
if (!parsed || typeof parsed.uri !== "string" || typeof parsed.cloneUrl !== "string" || typeof parsed.ref !== "string" || typeof parsed.subpath !== "string" || typeof parsed.resolvedCommit !== "string" || typeof parsed.cachedAt !== "string" || typeof parsed.isImmutable !== "boolean") {
|
|
678
|
+
return void 0;
|
|
679
|
+
}
|
|
680
|
+
return parsed;
|
|
681
|
+
} catch {
|
|
682
|
+
return void 0;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
async function writeRemoteRootCacheMetadata(metaPath, metadata) {
|
|
686
|
+
await (0, import_promises.mkdir)(import_node_path.default.dirname(metaPath), { recursive: true });
|
|
687
|
+
await (0, import_promises.writeFile)(metaPath, `${JSON.stringify(metadata, null, 2)}
|
|
688
|
+
`, "utf8");
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// ../core/src/discovery/cache/cachePaths.ts
|
|
692
|
+
var import_node_crypto = require("crypto");
|
|
693
|
+
var import_node_os = __toESM(require("os"), 1);
|
|
694
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
695
|
+
function resolveCnosCacheRoot(processEnv = process.env) {
|
|
696
|
+
return import_node_path2.default.resolve(
|
|
697
|
+
expandHomePath(processEnv.CNOS_CACHE_DIR ?? import_node_path2.default.join(import_node_os.default.homedir(), ".cnos", "cache"))
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
function createRemoteRootCacheKey(uri) {
|
|
701
|
+
return (0, import_node_crypto.createHash)("sha256").update(uri).digest("hex");
|
|
702
|
+
}
|
|
703
|
+
function resolveRemoteRootCachePaths(uri, processEnv = process.env) {
|
|
704
|
+
const cacheRoot = resolveCnosCacheRoot(processEnv);
|
|
705
|
+
const cacheDir = import_node_path2.default.join(cacheRoot, "roots", createRemoteRootCacheKey(uri));
|
|
706
|
+
return {
|
|
707
|
+
cacheRoot,
|
|
708
|
+
cacheDir,
|
|
709
|
+
repoDir: import_node_path2.default.join(cacheDir, "repo"),
|
|
710
|
+
metaPath: import_node_path2.default.join(cacheDir, ".cnos-cache-meta.json")
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// ../core/src/discovery/resolveRoot.ts
|
|
715
|
+
async function pathExists(targetPath) {
|
|
716
|
+
try {
|
|
717
|
+
await (0, import_promises2.access)(targetPath);
|
|
718
|
+
return true;
|
|
719
|
+
} catch {
|
|
720
|
+
return false;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
function expandHomePath2(targetPath) {
|
|
724
|
+
if (targetPath === "~") {
|
|
725
|
+
return import_node_os2.default.homedir();
|
|
726
|
+
}
|
|
727
|
+
if (targetPath.startsWith("~/") || targetPath.startsWith("~\\")) {
|
|
728
|
+
return import_node_path3.default.join(import_node_os2.default.homedir(), targetPath.slice(2));
|
|
729
|
+
}
|
|
730
|
+
return targetPath;
|
|
731
|
+
}
|
|
732
|
+
function isLocalRootUri(rootUri) {
|
|
733
|
+
return !isGitRootUri2(rootUri) && !isCnosHostedRootUri(rootUri);
|
|
734
|
+
}
|
|
735
|
+
function isCnosHostedRootUri(rootUri) {
|
|
736
|
+
return rootUri.startsWith("cnos://");
|
|
737
|
+
}
|
|
738
|
+
function isGitRootUri2(rootUri) {
|
|
739
|
+
return rootUri.startsWith("git+");
|
|
740
|
+
}
|
|
741
|
+
async function runGitCommand(args, options = {}) {
|
|
742
|
+
return new Promise((resolve, reject) => {
|
|
743
|
+
const child = (0, import_node_child_process4.spawn)("git", args, {
|
|
744
|
+
cwd: options.cwd,
|
|
745
|
+
env: options.processEnv ?? process.env,
|
|
746
|
+
shell: process.platform === "win32",
|
|
747
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
748
|
+
});
|
|
749
|
+
let stdout = "";
|
|
750
|
+
let stderr = "";
|
|
751
|
+
child.stdout.on("data", (chunk) => {
|
|
752
|
+
stdout += chunk.toString();
|
|
753
|
+
});
|
|
754
|
+
child.stderr.on("data", (chunk) => {
|
|
755
|
+
stderr += chunk.toString();
|
|
756
|
+
});
|
|
757
|
+
child.on("error", (error) => {
|
|
758
|
+
reject(
|
|
759
|
+
new CnosDiscoveryError(
|
|
760
|
+
`Failed to run git. Make sure git is installed and available on PATH. ${error.message}`
|
|
761
|
+
)
|
|
762
|
+
);
|
|
763
|
+
});
|
|
764
|
+
child.on("close", (code) => {
|
|
765
|
+
if (code === 0) {
|
|
766
|
+
resolve(stdout.trim());
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
const details = stderr.trim() || stdout.trim();
|
|
770
|
+
reject(
|
|
771
|
+
new CnosDiscoveryError(
|
|
772
|
+
details ? `Git command failed: ${details}` : `Git command failed with exit code ${code ?? 1}`
|
|
773
|
+
)
|
|
774
|
+
);
|
|
775
|
+
});
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
async function resolveLocalRoot(rootUri, cnosrcDir) {
|
|
779
|
+
const candidateRoot = rootUri.startsWith("~") ? expandHomePath2(rootUri) : rootUri;
|
|
780
|
+
const manifestRoot = import_node_path3.default.resolve(cnosrcDir, candidateRoot);
|
|
781
|
+
const manifestPath = import_node_path3.default.join(manifestRoot, "cnos.yml");
|
|
782
|
+
if (!await pathExists(manifestPath)) {
|
|
783
|
+
throw new CnosDiscoveryError(`.cnosrc.yml points to ${manifestRoot} but no cnos.yml found there.`);
|
|
784
|
+
}
|
|
785
|
+
return {
|
|
786
|
+
manifestRoot,
|
|
787
|
+
resolution: {
|
|
788
|
+
rootUri,
|
|
789
|
+
protocol: "local",
|
|
790
|
+
remote: false,
|
|
791
|
+
readOnly: false
|
|
792
|
+
}
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
async function ensureGitCheckout(parsed, repoDir, processEnv) {
|
|
796
|
+
const hasRepo = await pathExists(import_node_path3.default.join(repoDir, ".git"));
|
|
797
|
+
if (!hasRepo) {
|
|
798
|
+
await (0, import_promises2.mkdir)(import_node_path3.default.dirname(repoDir), { recursive: true });
|
|
799
|
+
await runGitCommand(["clone", "--no-checkout", parsed.cloneUrl, repoDir], { processEnv });
|
|
800
|
+
} else {
|
|
801
|
+
await runGitCommand(["-C", repoDir, "remote", "set-url", "origin", parsed.cloneUrl], {
|
|
802
|
+
processEnv
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
await runGitCommand(["-C", repoDir, "fetch", "--tags", "--force", "origin"], { processEnv });
|
|
806
|
+
await runGitCommand(["-C", repoDir, "checkout", "--force", parsed.ref], { processEnv });
|
|
807
|
+
await runGitCommand(["-C", repoDir, "clean", "-fdx"], { processEnv });
|
|
808
|
+
}
|
|
809
|
+
async function resolveGitRoot(rootUri, options = {}) {
|
|
810
|
+
const processEnv = options.processEnv ?? process.env;
|
|
811
|
+
const parsed = parseGitUri(rootUri);
|
|
812
|
+
const cachePaths = resolveRemoteRootCachePaths(rootUri, processEnv);
|
|
813
|
+
const metadata = await readRemoteRootCacheMetadata(cachePaths.metaPath);
|
|
814
|
+
const immutable = isImmutableGitRef(parsed.ref);
|
|
815
|
+
const cacheFresh = isRemoteRootCacheFresh(metadata, {
|
|
816
|
+
uri: rootUri,
|
|
817
|
+
ref: parsed.ref,
|
|
818
|
+
...options.cacheMode ? { mode: options.cacheMode } : {},
|
|
819
|
+
processEnv,
|
|
820
|
+
...typeof options.cacheTtlSeconds === "number" ? { ttlSeconds: options.cacheTtlSeconds } : {},
|
|
821
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
822
|
+
});
|
|
823
|
+
if (!cacheFresh) {
|
|
824
|
+
try {
|
|
825
|
+
await ensureGitCheckout(parsed, cachePaths.repoDir, processEnv);
|
|
826
|
+
} catch (error) {
|
|
827
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
828
|
+
const authHint = parsed.transport === "ssh" ? " Check your SSH key and git access." : " Check the URL and your git credential helper or token setup.";
|
|
829
|
+
throw new CnosDiscoveryError(`Failed to resolve remote git root ${rootUri}. ${message}${authHint}`);
|
|
830
|
+
}
|
|
831
|
+
const resolvedCommit = await runGitCommand(["-C", cachePaths.repoDir, "rev-parse", "HEAD"], {
|
|
832
|
+
processEnv
|
|
833
|
+
});
|
|
834
|
+
await writeRemoteRootCacheMetadata(cachePaths.metaPath, {
|
|
835
|
+
uri: rootUri,
|
|
836
|
+
cloneUrl: parsed.cloneUrl,
|
|
837
|
+
ref: parsed.ref,
|
|
838
|
+
subpath: parsed.subpath,
|
|
839
|
+
resolvedCommit,
|
|
840
|
+
cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
841
|
+
isImmutable: immutable
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
const nextMetadata = metadata && cacheFresh ? metadata : await readRemoteRootCacheMetadata(cachePaths.metaPath);
|
|
845
|
+
const manifestRoot = import_node_path3.default.join(cachePaths.repoDir, parsed.subpath);
|
|
846
|
+
if (!await pathExists(import_node_path3.default.join(manifestRoot, "cnos.yml"))) {
|
|
847
|
+
throw new CnosDiscoveryError(
|
|
848
|
+
`Git root ${rootUri} resolved to ${manifestRoot} but no cnos.yml was found there. Check the :subpath segment.`
|
|
849
|
+
);
|
|
850
|
+
}
|
|
851
|
+
return {
|
|
852
|
+
manifestRoot,
|
|
853
|
+
resolution: {
|
|
854
|
+
rootUri,
|
|
855
|
+
protocol: "git",
|
|
856
|
+
remote: true,
|
|
857
|
+
readOnly: true,
|
|
858
|
+
cacheDir: cachePaths.cacheDir,
|
|
859
|
+
cacheMetaPath: cachePaths.metaPath,
|
|
860
|
+
ref: parsed.ref,
|
|
861
|
+
subpath: parsed.subpath,
|
|
862
|
+
immutable,
|
|
863
|
+
...nextMetadata?.resolvedCommit ? { resolvedCommit: nextMetadata.resolvedCommit } : {},
|
|
864
|
+
...nextMetadata?.cachedAt ? { cachedAt: nextMetadata.cachedAt } : {}
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
async function resolveRootUri(rootUri, cnosrcDir, options = {}) {
|
|
869
|
+
if (isLocalRootUri(rootUri)) {
|
|
870
|
+
return resolveLocalRoot(rootUri, cnosrcDir);
|
|
871
|
+
}
|
|
872
|
+
if (isGitRootUri2(rootUri)) {
|
|
873
|
+
return resolveGitRoot(rootUri, options);
|
|
874
|
+
}
|
|
875
|
+
if (isCnosHostedRootUri(rootUri)) {
|
|
876
|
+
throw new CnosDiscoveryError(
|
|
877
|
+
`The cnos:// remote root protocol is reserved but not implemented yet. Use git+https:// or git+ssh:// for now.`
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
throw new CnosDiscoveryError(
|
|
881
|
+
`Unknown root protocol: ${rootUri}. Supported root protocols are local paths, git+https://..., and git+ssh://....`
|
|
882
|
+
);
|
|
883
|
+
}
|
|
884
|
+
|
|
256
885
|
// ../core/src/discovery/findCnosrc.ts
|
|
257
886
|
async function exists(targetPath) {
|
|
258
887
|
try {
|
|
259
|
-
await (0,
|
|
888
|
+
await (0, import_promises3.access)(targetPath);
|
|
260
889
|
return true;
|
|
261
890
|
} catch {
|
|
262
891
|
return false;
|
|
@@ -277,13 +906,13 @@ function validateCnosrc(value, filePath) {
|
|
|
277
906
|
};
|
|
278
907
|
}
|
|
279
908
|
async function findCnosrc(startDir = process.cwd(), maxLevels = 3) {
|
|
280
|
-
let current =
|
|
909
|
+
let current = import_node_path4.default.resolve(startDir);
|
|
281
910
|
for (let depth = 0; depth <= maxLevels; depth += 1) {
|
|
282
|
-
const candidate =
|
|
911
|
+
const candidate = import_node_path4.default.join(current, ".cnosrc.yml");
|
|
283
912
|
if (await exists(candidate)) {
|
|
284
913
|
return candidate;
|
|
285
914
|
}
|
|
286
|
-
const parent =
|
|
915
|
+
const parent = import_node_path4.default.dirname(current);
|
|
287
916
|
if (parent === current) {
|
|
288
917
|
break;
|
|
289
918
|
}
|
|
@@ -291,27 +920,22 @@ async function findCnosrc(startDir = process.cwd(), maxLevels = 3) {
|
|
|
291
920
|
}
|
|
292
921
|
return void 0;
|
|
293
922
|
}
|
|
294
|
-
async function discoverCnosAnchor(startDir = process.cwd(), maxLevels = 3) {
|
|
923
|
+
async function discoverCnosAnchor(startDir = process.cwd(), maxLevels = 3, options = {}) {
|
|
295
924
|
const anchorPath = await findCnosrc(startDir, maxLevels);
|
|
296
925
|
if (!anchorPath) {
|
|
297
926
|
throw new CnosDiscoveryError(
|
|
298
927
|
"No .cnosrc.yml found. Run cnos init or create .cnosrc.yml in your package root."
|
|
299
928
|
);
|
|
300
929
|
}
|
|
301
|
-
const source = await (0,
|
|
930
|
+
const source = await (0, import_promises3.readFile)(anchorPath, "utf8");
|
|
302
931
|
const parsed = validateCnosrc(parseYaml(source), anchorPath);
|
|
303
|
-
const consumerRoot =
|
|
304
|
-
const
|
|
305
|
-
const manifestPath = import_node_path.default.join(manifestRoot, "cnos.yml");
|
|
306
|
-
if (!await exists(manifestPath)) {
|
|
307
|
-
throw new CnosDiscoveryError(
|
|
308
|
-
`.cnosrc.yml points to ${manifestRoot} but no cnos.yml found there.`
|
|
309
|
-
);
|
|
310
|
-
}
|
|
932
|
+
const consumerRoot = import_node_path4.default.dirname(anchorPath);
|
|
933
|
+
const resolvedRoot = await resolveRootUri(parsed.root, consumerRoot, options);
|
|
311
934
|
return {
|
|
312
935
|
anchorPath,
|
|
313
936
|
consumerRoot,
|
|
314
|
-
manifestRoot,
|
|
937
|
+
manifestRoot: resolvedRoot.manifestRoot,
|
|
938
|
+
rootResolution: resolvedRoot.resolution,
|
|
315
939
|
...parsed.workspace ? { workspace: parsed.workspace } : {}
|
|
316
940
|
};
|
|
317
941
|
}
|
|
@@ -321,21 +945,21 @@ var PRIMARY_CNOS_DIR = ".cnos";
|
|
|
321
945
|
var LEGACY_CNOS_DIR = "cnos";
|
|
322
946
|
async function exists2(filePath) {
|
|
323
947
|
try {
|
|
324
|
-
await (0,
|
|
948
|
+
await (0, import_promises4.access)(filePath);
|
|
325
949
|
return true;
|
|
326
950
|
} catch {
|
|
327
951
|
return false;
|
|
328
952
|
}
|
|
329
953
|
}
|
|
330
954
|
async function resolveCnosRoot(root = process.cwd()) {
|
|
331
|
-
const basePath =
|
|
955
|
+
const basePath = import_node_path5.default.resolve(root);
|
|
332
956
|
const candidates = [
|
|
333
|
-
|
|
334
|
-
|
|
957
|
+
import_node_path5.default.join(basePath, PRIMARY_CNOS_DIR),
|
|
958
|
+
import_node_path5.default.join(basePath, LEGACY_CNOS_DIR),
|
|
335
959
|
basePath
|
|
336
960
|
];
|
|
337
961
|
for (const candidate of candidates) {
|
|
338
|
-
if (await exists2(
|
|
962
|
+
if (await exists2(import_node_path5.default.join(candidate, "cnos.yml"))) {
|
|
339
963
|
return candidate;
|
|
340
964
|
}
|
|
341
965
|
}
|
|
@@ -345,42 +969,68 @@ async function resolveCnosRoot(root = process.cwd()) {
|
|
|
345
969
|
}
|
|
346
970
|
async function resolveManifestRoot(options = {}) {
|
|
347
971
|
if (options.root) {
|
|
972
|
+
if (options.root.startsWith("git+") || options.root.startsWith("cnos://")) {
|
|
973
|
+
const consumerRoot2 = import_node_path5.default.resolve(options.cwd ?? process.cwd());
|
|
974
|
+
const resolvedRoot2 = await resolveRootUri(options.root, consumerRoot2, {
|
|
975
|
+
...options.processEnv ? { processEnv: options.processEnv } : {},
|
|
976
|
+
...options.cacheMode ? { cacheMode: options.cacheMode } : {},
|
|
977
|
+
...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
|
|
978
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
979
|
+
});
|
|
980
|
+
return {
|
|
981
|
+
manifestRoot: resolvedRoot2.manifestRoot,
|
|
982
|
+
consumerRoot: consumerRoot2,
|
|
983
|
+
rootResolution: resolvedRoot2.resolution
|
|
984
|
+
};
|
|
985
|
+
}
|
|
348
986
|
const manifestRoot = await resolveCnosRoot(options.root);
|
|
349
|
-
const resolvedRoot =
|
|
350
|
-
const consumerRoot =
|
|
987
|
+
const resolvedRoot = import_node_path5.default.resolve(options.root);
|
|
988
|
+
const consumerRoot = import_node_path5.default.basename(manifestRoot) === PRIMARY_CNOS_DIR || import_node_path5.default.basename(manifestRoot) === LEGACY_CNOS_DIR ? import_node_path5.default.dirname(manifestRoot) : resolvedRoot;
|
|
351
989
|
return {
|
|
352
990
|
manifestRoot,
|
|
353
|
-
consumerRoot
|
|
991
|
+
consumerRoot,
|
|
992
|
+
rootResolution: {
|
|
993
|
+
rootUri: manifestRoot,
|
|
994
|
+
protocol: "local",
|
|
995
|
+
remote: false,
|
|
996
|
+
readOnly: false
|
|
997
|
+
}
|
|
354
998
|
};
|
|
355
999
|
}
|
|
356
|
-
const discovered = await discoverCnosAnchor(options.cwd ?? process.cwd()
|
|
1000
|
+
const discovered = await discoverCnosAnchor(options.cwd ?? process.cwd(), 3, {
|
|
1001
|
+
...options.processEnv ? { processEnv: options.processEnv } : {},
|
|
1002
|
+
...options.cacheMode ? { cacheMode: options.cacheMode } : {},
|
|
1003
|
+
...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
|
|
1004
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
1005
|
+
});
|
|
357
1006
|
return {
|
|
358
1007
|
manifestRoot: discovered.manifestRoot,
|
|
359
1008
|
consumerRoot: discovered.consumerRoot,
|
|
1009
|
+
rootResolution: discovered.rootResolution,
|
|
360
1010
|
anchorPath: discovered.anchorPath,
|
|
361
1011
|
...discovered.workspace ? { workspace: discovered.workspace } : {}
|
|
362
1012
|
};
|
|
363
1013
|
}
|
|
364
1014
|
function expandHomePath(targetPath) {
|
|
365
1015
|
if (targetPath === "~") {
|
|
366
|
-
return
|
|
1016
|
+
return import_node_os3.default.homedir();
|
|
367
1017
|
}
|
|
368
1018
|
if (targetPath.startsWith("~/") || targetPath.startsWith("~\\")) {
|
|
369
|
-
return
|
|
1019
|
+
return import_node_path5.default.join(import_node_os3.default.homedir(), targetPath.slice(2));
|
|
370
1020
|
}
|
|
371
1021
|
return targetPath;
|
|
372
1022
|
}
|
|
373
1023
|
function resolveNamespaceDirectory(workspaceRoot, namespace, profile) {
|
|
374
1024
|
const rootFolder = namespace === "value" ? "values" : namespace === "secret" ? "secrets" : namespace;
|
|
375
1025
|
if (profile && profile !== "base") {
|
|
376
|
-
return
|
|
1026
|
+
return import_node_path5.default.resolve(workspaceRoot, "profiles", profile, rootFolder);
|
|
377
1027
|
}
|
|
378
|
-
return
|
|
1028
|
+
return import_node_path5.default.resolve(workspaceRoot, rootFolder);
|
|
379
1029
|
}
|
|
380
1030
|
function resolveConfigDocumentPath(workspaceRoot, namespace, configPath, profile) {
|
|
381
1031
|
const namespaceRoot = resolveNamespaceDirectory(workspaceRoot, namespace, profile);
|
|
382
1032
|
const fileName = `${configPath.split(".").shift() ?? "app"}.yml`;
|
|
383
|
-
return
|
|
1033
|
+
return import_node_path5.default.resolve(namespaceRoot, fileName);
|
|
384
1034
|
}
|
|
385
1035
|
|
|
386
1036
|
// ../core/src/manifest/normalizeManifest.ts
|
|
@@ -434,6 +1084,13 @@ var DEFAULT_NAMESPACES = {
|
|
|
434
1084
|
readonly: true
|
|
435
1085
|
}
|
|
436
1086
|
};
|
|
1087
|
+
var DEFAULT_RUNTIME_NAMESPACES = {
|
|
1088
|
+
process: {
|
|
1089
|
+
description: "Live process runtime values.",
|
|
1090
|
+
serverOnly: true,
|
|
1091
|
+
builtIn: true
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
437
1094
|
function validateResolveFrom(resolveFrom) {
|
|
438
1095
|
const validValues = ["cli.profile", "env.CNOS_PROFILE", "default"];
|
|
439
1096
|
for (const entry of resolveFrom) {
|
|
@@ -456,7 +1113,7 @@ function normalizeWorkspaceItems(items) {
|
|
|
456
1113
|
}
|
|
457
1114
|
function normalizeNamespaces(namespaces) {
|
|
458
1115
|
const normalized = Object.fromEntries(
|
|
459
|
-
Object.entries(namespaces ?? {}).map(([namespace, definition]) => [
|
|
1116
|
+
Object.entries(namespaces ?? {}).filter(([namespace]) => namespace !== "runtime").map(([namespace, definition]) => [
|
|
460
1117
|
namespace,
|
|
461
1118
|
{
|
|
462
1119
|
kind: definition.kind ?? "data",
|
|
@@ -472,6 +1129,29 @@ function normalizeNamespaces(namespaces) {
|
|
|
472
1129
|
...normalized
|
|
473
1130
|
};
|
|
474
1131
|
}
|
|
1132
|
+
function normalizeRuntimeNamespaces(namespaces) {
|
|
1133
|
+
const runtimeEntries = namespaces?.runtime ?? {};
|
|
1134
|
+
const normalized = Object.fromEntries(
|
|
1135
|
+
Object.entries(runtimeEntries).map(([namespace, definition]) => [
|
|
1136
|
+
namespace,
|
|
1137
|
+
{
|
|
1138
|
+
...definition.description?.trim() ? {
|
|
1139
|
+
description: definition.description.trim()
|
|
1140
|
+
} : {},
|
|
1141
|
+
serverOnly: definition.server_only ?? true
|
|
1142
|
+
}
|
|
1143
|
+
])
|
|
1144
|
+
);
|
|
1145
|
+
for (const namespace of Object.keys(normalized)) {
|
|
1146
|
+
if (DEFAULT_NAMESPACES[namespace] || namespace === "runtime") {
|
|
1147
|
+
throw new CnosManifestError(`Runtime namespace "${namespace}" conflicts with a built-in or reserved namespace.`);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
return {
|
|
1151
|
+
...DEFAULT_RUNTIME_NAMESPACES,
|
|
1152
|
+
...normalized
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
475
1155
|
function normalizeVaults(vaults) {
|
|
476
1156
|
return Object.fromEntries(
|
|
477
1157
|
Object.entries(vaults ?? {}).map(([name, definition]) => {
|
|
@@ -563,6 +1243,7 @@ function normalizeManifest(manifest) {
|
|
|
563
1243
|
const defaultProfile = manifest.profiles?.default?.trim() || "base";
|
|
564
1244
|
const workspaceItems = normalizeWorkspaceItems(manifest.workspaces?.items);
|
|
565
1245
|
const resolveFrom = validateResolveFrom(manifest.profiles?.resolveFrom ?? DEFAULT_RESOLVE_FROM);
|
|
1246
|
+
const runtimeNamespaces = normalizeRuntimeNamespaces(manifest.namespaces);
|
|
566
1247
|
const filesystemValues = {
|
|
567
1248
|
root: "./",
|
|
568
1249
|
format: "yaml",
|
|
@@ -636,6 +1317,7 @@ function normalizeManifest(manifest) {
|
|
|
636
1317
|
}
|
|
637
1318
|
},
|
|
638
1319
|
namespaces: normalizeNamespaces(manifest.namespaces),
|
|
1320
|
+
runtimeNamespaces,
|
|
639
1321
|
vaults: normalizeVaults(manifest.vaults),
|
|
640
1322
|
writePolicy: {
|
|
641
1323
|
define: {
|
|
@@ -654,13 +1336,17 @@ function normalizeManifest(manifest) {
|
|
|
654
1336
|
async function loadManifest(options = {}) {
|
|
655
1337
|
const resolved = await resolveManifestRoot({
|
|
656
1338
|
...options.root ? { root: options.root } : {},
|
|
657
|
-
...options.cwd ? { cwd: options.cwd } : {}
|
|
1339
|
+
...options.cwd ? { cwd: options.cwd } : {},
|
|
1340
|
+
...options.processEnv ? { processEnv: options.processEnv } : {},
|
|
1341
|
+
...options.cacheMode ? { cacheMode: options.cacheMode } : {},
|
|
1342
|
+
...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
|
|
1343
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
658
1344
|
});
|
|
659
1345
|
const manifestRoot = resolved.manifestRoot;
|
|
660
|
-
const manifestPath =
|
|
1346
|
+
const manifestPath = import_node_path6.default.join(manifestRoot, "cnos.yml");
|
|
661
1347
|
let source;
|
|
662
1348
|
try {
|
|
663
|
-
source = await (0,
|
|
1349
|
+
source = await (0, import_promises5.readFile)(manifestPath, "utf8");
|
|
664
1350
|
} catch {
|
|
665
1351
|
throw new CnosManifestError("Unable to read CNOS manifest", manifestPath);
|
|
666
1352
|
}
|
|
@@ -670,10 +1356,11 @@ async function loadManifest(options = {}) {
|
|
|
670
1356
|
}
|
|
671
1357
|
return {
|
|
672
1358
|
manifestRoot,
|
|
673
|
-
repoRoot:
|
|
1359
|
+
repoRoot: import_node_path6.default.dirname(manifestRoot),
|
|
674
1360
|
consumerRoot: resolved.consumerRoot,
|
|
675
1361
|
...resolved.anchorPath ? { anchorPath: resolved.anchorPath } : {},
|
|
676
1362
|
...resolved.workspace ? { anchoredWorkspace: resolved.workspace } : {},
|
|
1363
|
+
rootResolution: resolved.rootResolution,
|
|
677
1364
|
manifestPath,
|
|
678
1365
|
manifest: normalizeManifest(rawManifest),
|
|
679
1366
|
rawManifest
|
|
@@ -681,12 +1368,12 @@ async function loadManifest(options = {}) {
|
|
|
681
1368
|
}
|
|
682
1369
|
|
|
683
1370
|
// ../core/src/manifest/loadWorkspaceFile.ts
|
|
684
|
-
var
|
|
685
|
-
var
|
|
1371
|
+
var import_promises6 = require("fs/promises");
|
|
1372
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
686
1373
|
|
|
687
1374
|
// ../core/src/profiles/expandProfileChain.ts
|
|
688
|
-
var
|
|
689
|
-
var
|
|
1375
|
+
var import_promises7 = require("fs/promises");
|
|
1376
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
690
1377
|
|
|
691
1378
|
// ../core/src/promotions/validatePromotion.ts
|
|
692
1379
|
var DEFAULT_DATA_NAMESPACE = {
|
|
@@ -737,42 +1424,42 @@ function validateProjectionIssue(manifest, key, target) {
|
|
|
737
1424
|
}
|
|
738
1425
|
|
|
739
1426
|
// ../core/src/workspaces/resolveWorkspaceContext.ts
|
|
740
|
-
var
|
|
741
|
-
var
|
|
1427
|
+
var import_promises8 = require("fs/promises");
|
|
1428
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
742
1429
|
|
|
743
1430
|
// ../core/src/secrets/auditLog.ts
|
|
744
|
-
var
|
|
745
|
-
var
|
|
1431
|
+
var import_promises11 = require("fs/promises");
|
|
1432
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
746
1433
|
|
|
747
1434
|
// ../core/src/utils/secretStore.ts
|
|
748
|
-
var
|
|
749
|
-
var
|
|
750
|
-
var
|
|
1435
|
+
var import_node_crypto2 = require("crypto");
|
|
1436
|
+
var import_promises10 = require("fs/promises");
|
|
1437
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
751
1438
|
|
|
752
1439
|
// ../core/src/secrets/sessionStore.ts
|
|
753
|
-
var
|
|
754
|
-
var
|
|
1440
|
+
var import_promises9 = require("fs/promises");
|
|
1441
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
755
1442
|
function buildSessionRoot(processEnv = process.env) {
|
|
756
|
-
return
|
|
1443
|
+
return import_node_path10.default.join(import_node_path10.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets")), "sessions");
|
|
757
1444
|
}
|
|
758
1445
|
function buildSessionPath(vault, processEnv) {
|
|
759
|
-
return
|
|
1446
|
+
return import_node_path10.default.join(buildSessionRoot(processEnv), `${vault}.json`);
|
|
760
1447
|
}
|
|
761
1448
|
async function writeVaultSessionKey(vault, derivedKey, processEnv) {
|
|
762
1449
|
const filePath = buildSessionPath(vault, processEnv);
|
|
763
|
-
await (0,
|
|
1450
|
+
await (0, import_promises9.mkdir)(import_node_path10.default.dirname(filePath), { recursive: true });
|
|
764
1451
|
const document = {
|
|
765
1452
|
version: 1,
|
|
766
1453
|
vault,
|
|
767
1454
|
derivedKey: derivedKey.toString("hex"),
|
|
768
1455
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
769
1456
|
};
|
|
770
|
-
await (0,
|
|
1457
|
+
await (0, import_promises9.writeFile)(filePath, JSON.stringify(document, null, 2), "utf8");
|
|
771
1458
|
return filePath;
|
|
772
1459
|
}
|
|
773
1460
|
async function readVaultSessionKey(vault, processEnv) {
|
|
774
1461
|
try {
|
|
775
|
-
const source = await (0,
|
|
1462
|
+
const source = await (0, import_promises9.readFile)(buildSessionPath(vault, processEnv), "utf8");
|
|
776
1463
|
const document = JSON.parse(source);
|
|
777
1464
|
if (document.version !== 1 || typeof document.derivedKey !== "string") {
|
|
778
1465
|
return void 0;
|
|
@@ -784,13 +1471,13 @@ async function readVaultSessionKey(vault, processEnv) {
|
|
|
784
1471
|
}
|
|
785
1472
|
}
|
|
786
1473
|
async function clearVaultSessionKey(vault, processEnv) {
|
|
787
|
-
await (0,
|
|
1474
|
+
await (0, import_promises9.rm)(buildSessionPath(vault, processEnv), { force: true });
|
|
788
1475
|
}
|
|
789
1476
|
async function clearAllVaultSessionKeys(processEnv) {
|
|
790
1477
|
const root = buildSessionRoot(processEnv);
|
|
791
1478
|
try {
|
|
792
|
-
const entries = await (0,
|
|
793
|
-
await Promise.all(entries.map((entry) => (0,
|
|
1479
|
+
const entries = await (0, import_promises9.readdir)(root);
|
|
1480
|
+
await Promise.all(entries.map((entry) => (0, import_promises9.rm)(import_node_path10.default.join(root, entry), { force: true })));
|
|
794
1481
|
} catch {
|
|
795
1482
|
}
|
|
796
1483
|
}
|
|
@@ -812,7 +1499,7 @@ function isSecretReference(value) {
|
|
|
812
1499
|
return isObject(value) && typeof value.provider === "string" && value.provider.trim().length > 0 && typeof value.ref === "string" && value.ref.trim().length > 0 && (value.vault === void 0 && true || typeof value.vault === "string" && value.vault.trim().length > 0) && Object.keys(value).every((key) => ["provider", "ref", "vault"].includes(key));
|
|
813
1500
|
}
|
|
814
1501
|
function resolveSecretStoreRoot(processEnv = process.env) {
|
|
815
|
-
return
|
|
1502
|
+
return import_node_path11.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
|
|
816
1503
|
}
|
|
817
1504
|
function normalizeVaultToken(vault = "default") {
|
|
818
1505
|
return vault.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
|
|
@@ -844,22 +1531,22 @@ function resolveVaultSessionKey(vault = "default", processEnv = process.env) {
|
|
|
844
1531
|
}
|
|
845
1532
|
}
|
|
846
1533
|
function deriveVaultKey(passphrase, salt, iterations = PBKDF2_ITERATIONS) {
|
|
847
|
-
return (0,
|
|
1534
|
+
return (0, import_node_crypto2.pbkdf2Sync)(passphrase, salt, iterations, KEY_LENGTH, "sha512");
|
|
848
1535
|
}
|
|
849
1536
|
function buildMetaPath(storeRoot, vault = "default") {
|
|
850
|
-
return
|
|
1537
|
+
return import_node_path11.default.join(storeRoot, "vaults", vault, META_FILENAME);
|
|
851
1538
|
}
|
|
852
1539
|
function resolveSecretVaultFile(storeRoot, vault = "default") {
|
|
853
1540
|
return buildMetaPath(storeRoot, vault);
|
|
854
1541
|
}
|
|
855
1542
|
function buildKeystorePath(storeRoot, vault = "default") {
|
|
856
|
-
return
|
|
1543
|
+
return import_node_path11.default.join(storeRoot, "vaults", vault, KEYSTORE_FILENAME);
|
|
857
1544
|
}
|
|
858
1545
|
function buildLegacyVaultFile(storeRoot, vault = "default") {
|
|
859
|
-
return
|
|
1546
|
+
return import_node_path11.default.join(storeRoot, "vaults", `${vault}.json`);
|
|
860
1547
|
}
|
|
861
1548
|
function buildLegacyVaultStoreRoot(storeRoot, vault = "default") {
|
|
862
|
-
return
|
|
1549
|
+
return import_node_path11.default.join(storeRoot, "vaults", vault, "store");
|
|
863
1550
|
}
|
|
864
1551
|
function assertVaultMetadata(value, filePath) {
|
|
865
1552
|
if (!isObject(value)) {
|
|
@@ -872,7 +1559,7 @@ function assertVaultMetadata(value, filePath) {
|
|
|
872
1559
|
}
|
|
873
1560
|
async function exists3(targetPath) {
|
|
874
1561
|
try {
|
|
875
|
-
await (0,
|
|
1562
|
+
await (0, import_promises10.stat)(targetPath);
|
|
876
1563
|
return true;
|
|
877
1564
|
} catch {
|
|
878
1565
|
return false;
|
|
@@ -899,8 +1586,8 @@ async function assertNoLegacyVaultFormat(storeRoot, vault = "default") {
|
|
|
899
1586
|
);
|
|
900
1587
|
}
|
|
901
1588
|
function encryptPayload(payload, key) {
|
|
902
|
-
const iv = (0,
|
|
903
|
-
const cipher = (0,
|
|
1589
|
+
const iv = (0, import_node_crypto2.randomBytes)(IV_LENGTH);
|
|
1590
|
+
const cipher = (0, import_node_crypto2.createCipheriv)("aes-256-gcm", key, iv);
|
|
904
1591
|
const plaintext = Buffer.from(JSON.stringify(payload), "utf8");
|
|
905
1592
|
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
906
1593
|
const tag = cipher.getAuthTag();
|
|
@@ -925,7 +1612,7 @@ function decryptPayload(buffer, key) {
|
|
|
925
1612
|
const iv = buffer.subarray(ivOffset, tagOffset);
|
|
926
1613
|
const tag = buffer.subarray(tagOffset, cipherOffset);
|
|
927
1614
|
const ciphertext = buffer.subarray(cipherOffset);
|
|
928
|
-
const decipher = (0,
|
|
1615
|
+
const decipher = (0, import_node_crypto2.createDecipheriv)("aes-256-gcm", key, iv);
|
|
929
1616
|
decipher.setAuthTag(tag);
|
|
930
1617
|
try {
|
|
931
1618
|
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
@@ -956,15 +1643,15 @@ function buildInitialPayload() {
|
|
|
956
1643
|
async function writeVaultFiles(storeRoot, vault, meta, payload, key) {
|
|
957
1644
|
const metaPath = buildMetaPath(storeRoot, vault);
|
|
958
1645
|
const keystorePath = buildKeystorePath(storeRoot, vault);
|
|
959
|
-
await (0,
|
|
960
|
-
await (0,
|
|
961
|
-
await (0,
|
|
1646
|
+
await (0, import_promises10.mkdir)(import_node_path11.default.dirname(metaPath), { recursive: true });
|
|
1647
|
+
await (0, import_promises10.writeFile)(metaPath, stringifyYaml(meta), "utf8");
|
|
1648
|
+
await (0, import_promises10.writeFile)(keystorePath, encryptPayload(payload, key));
|
|
962
1649
|
}
|
|
963
1650
|
async function readVaultMetadata(storeRoot, vault = "default") {
|
|
964
1651
|
await assertNoLegacyVaultFormat(storeRoot, vault);
|
|
965
1652
|
const metaPath = buildMetaPath(storeRoot, vault);
|
|
966
1653
|
try {
|
|
967
|
-
const source = await (0,
|
|
1654
|
+
const source = await (0, import_promises10.readFile)(metaPath, "utf8");
|
|
968
1655
|
return assertVaultMetadata(parseYaml(source), metaPath);
|
|
969
1656
|
} catch (error) {
|
|
970
1657
|
if (error.code === "ENOENT") {
|
|
@@ -974,11 +1661,11 @@ async function readVaultMetadata(storeRoot, vault = "default") {
|
|
|
974
1661
|
}
|
|
975
1662
|
}
|
|
976
1663
|
async function listSecretVaults(storeRoot) {
|
|
977
|
-
const vaultRoot =
|
|
1664
|
+
const vaultRoot = import_node_path11.default.join(storeRoot, "vaults");
|
|
978
1665
|
try {
|
|
979
|
-
const entries = await (0,
|
|
1666
|
+
const entries = await (0, import_promises10.readdir)(vaultRoot, { withFileTypes: true });
|
|
980
1667
|
const vaults = await Promise.all(
|
|
981
|
-
entries.filter((entry) => entry.isDirectory()).map(async (entry) => await exists3(
|
|
1668
|
+
entries.filter((entry) => entry.isDirectory()).map(async (entry) => await exists3(import_node_path11.default.join(vaultRoot, entry.name, META_FILENAME)) ? entry.name : void 0)
|
|
982
1669
|
);
|
|
983
1670
|
return vaults.filter((value) => Boolean(value)).sort((left, right) => left.localeCompare(right));
|
|
984
1671
|
} catch {
|
|
@@ -988,7 +1675,7 @@ async function listSecretVaults(storeRoot) {
|
|
|
988
1675
|
async function createSecretVault(storeRoot, vault, passphrase) {
|
|
989
1676
|
const normalizedVault = vault.trim() || "default";
|
|
990
1677
|
await assertNoLegacyVaultFormat(storeRoot, normalizedVault);
|
|
991
|
-
const salt = (0,
|
|
1678
|
+
const salt = (0, import_node_crypto2.randomBytes)(SALT_LENGTH);
|
|
992
1679
|
const key = deriveVaultKey(passphrase, salt, PBKDF2_ITERATIONS);
|
|
993
1680
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
994
1681
|
const meta = {
|
|
@@ -1067,7 +1754,7 @@ async function loadVaultPayload(storeRoot, vault, auth) {
|
|
|
1067
1754
|
if (!key) {
|
|
1068
1755
|
throw new CnosAuthenticationError(`Vault "${vault}" requires authentication before access.`);
|
|
1069
1756
|
}
|
|
1070
|
-
const buffer = await (0,
|
|
1757
|
+
const buffer = await (0, import_promises10.readFile)(buildKeystorePath(storeRoot, vault));
|
|
1071
1758
|
return {
|
|
1072
1759
|
meta,
|
|
1073
1760
|
payload: decryptPayload(buffer, key),
|
|
@@ -1140,14 +1827,14 @@ function resolveVaultDefinition(vaults, vault = "default") {
|
|
|
1140
1827
|
};
|
|
1141
1828
|
}
|
|
1142
1829
|
async function removeLocalVaultFiles(storeRoot, vault = "default") {
|
|
1143
|
-
await (0,
|
|
1830
|
+
await (0, import_promises10.rm)(import_node_path11.default.join(storeRoot, "vaults", vault), { recursive: true, force: true });
|
|
1144
1831
|
}
|
|
1145
1832
|
|
|
1146
1833
|
// ../core/src/secrets/auditLog.ts
|
|
1147
1834
|
async function appendAuditEvent(event, processEnv = process.env) {
|
|
1148
|
-
const auditFile = processEnv.CNOS_AUDIT_FILE ??
|
|
1149
|
-
await (0,
|
|
1150
|
-
await (0,
|
|
1835
|
+
const auditFile = processEnv.CNOS_AUDIT_FILE ?? import_node_path12.default.join(resolveSecretStoreRoot(processEnv), "audit", "access.log");
|
|
1836
|
+
await (0, import_promises11.mkdir)(import_node_path12.default.dirname(auditFile), { recursive: true });
|
|
1837
|
+
await (0, import_promises11.appendFile)(
|
|
1151
1838
|
auditFile,
|
|
1152
1839
|
`${JSON.stringify({
|
|
1153
1840
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -1414,11 +2101,11 @@ async function resolveVaultAuth(vaultId, definition, processEnv = process.env) {
|
|
|
1414
2101
|
}
|
|
1415
2102
|
|
|
1416
2103
|
// ../core/src/runtime/toServerProjection.ts
|
|
1417
|
-
var
|
|
2104
|
+
var import_node_crypto3 = require("crypto");
|
|
1418
2105
|
|
|
1419
2106
|
// ../core/src/runtime/dump.ts
|
|
1420
|
-
var
|
|
1421
|
-
var
|
|
2107
|
+
var import_promises12 = require("fs/promises");
|
|
2108
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
1422
2109
|
|
|
1423
2110
|
// ../core/src/utils/envNaming.ts
|
|
1424
2111
|
function normalizeMappingConfig(config = {}) {
|
|
@@ -1430,8 +2117,8 @@ function normalizeMappingConfig(config = {}) {
|
|
|
1430
2117
|
function toScreamingSnakeSegment(segment) {
|
|
1431
2118
|
return segment.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
|
|
1432
2119
|
}
|
|
1433
|
-
function toScreamingSnake(
|
|
1434
|
-
return
|
|
2120
|
+
function toScreamingSnake(path17) {
|
|
2121
|
+
return path17.split(".").map((segment) => toScreamingSnakeSegment(segment)).filter(Boolean).join("_");
|
|
1435
2122
|
}
|
|
1436
2123
|
function logicalKeyToEnvVar(key, config = {}) {
|
|
1437
2124
|
const normalized = normalizeMappingConfig(config);
|
|
@@ -1455,6 +2142,10 @@ function logicalKeyToEnvVar(key, config = {}) {
|
|
|
1455
2142
|
function flattenObject(value, prefix = "") {
|
|
1456
2143
|
return Object.entries(value).reduce((accumulator, [key, nestedValue]) => {
|
|
1457
2144
|
const nextKey = prefix ? `${prefix}.${key}` : key;
|
|
2145
|
+
if (isDerivedValue(nestedValue) || isSecretReference(nestedValue)) {
|
|
2146
|
+
accumulator[nextKey] = nestedValue;
|
|
2147
|
+
return accumulator;
|
|
2148
|
+
}
|
|
1458
2149
|
if (nestedValue && typeof nestedValue === "object" && !Array.isArray(nestedValue)) {
|
|
1459
2150
|
Object.assign(accumulator, flattenObject(nestedValue, nextKey));
|
|
1460
2151
|
return accumulator;
|
|
@@ -1564,7 +2255,7 @@ async function validateRuntime(runtime) {
|
|
|
1564
2255
|
}
|
|
1565
2256
|
|
|
1566
2257
|
// src/runtime/bootstrap.ts
|
|
1567
|
-
var
|
|
2258
|
+
var import_node_crypto4 = require("crypto");
|
|
1568
2259
|
var CNOS_GRAPH_ENV_VAR = "__CNOS_GRAPH__";
|
|
1569
2260
|
var CNOS_PROJECTION_ENV_VAR = "__CNOS_PROJECTION__";
|
|
1570
2261
|
var CNOS_SECRET_PAYLOAD_ENV_VAR = "__CNOS_SECRET_PAYLOAD__";
|
|
@@ -1577,7 +2268,11 @@ function deserializeServerProjection(source) {
|
|
|
1577
2268
|
if (!payload || payload.version !== 1 || typeof payload.workspace !== "string" || typeof payload.profile !== "string" || typeof payload.resolvedAt !== "string" || typeof payload.configHash !== "string" || !payload.values || typeof payload.values !== "object" || Array.isArray(payload.values) || !payload.secretRefs || typeof payload.secretRefs !== "object" || Array.isArray(payload.secretRefs) || !Array.isArray(payload.publicKeys) || !payload.meta || typeof payload.meta !== "object") {
|
|
1578
2269
|
throw new Error("Invalid CNOS server projection payload");
|
|
1579
2270
|
}
|
|
1580
|
-
return
|
|
2271
|
+
return {
|
|
2272
|
+
...payload,
|
|
2273
|
+
derived: payload.derived && typeof payload.derived === "object" && !Array.isArray(payload.derived) ? payload.derived : {},
|
|
2274
|
+
runtimeNamespaces: Array.isArray(payload.runtimeNamespaces) ? payload.runtimeNamespaces : []
|
|
2275
|
+
};
|
|
1581
2276
|
}
|
|
1582
2277
|
function serializeRuntimeGraph(graph) {
|
|
1583
2278
|
const payload = {
|
|
@@ -1622,15 +2317,15 @@ function decryptSecretPayload(serialized, sessionKey) {
|
|
|
1622
2317
|
const iv = Buffer.from(payload.iv, "base64");
|
|
1623
2318
|
const tag = Buffer.from(payload.tag, "base64");
|
|
1624
2319
|
const ciphertext = Buffer.from(payload.ciphertext, "base64");
|
|
1625
|
-
const decipher = (0,
|
|
2320
|
+
const decipher = (0, import_node_crypto4.createDecipheriv)("aes-256-gcm", key, iv);
|
|
1626
2321
|
decipher.setAuthTag(tag);
|
|
1627
2322
|
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
1628
2323
|
return JSON.parse(plaintext);
|
|
1629
2324
|
}
|
|
1630
2325
|
function serializeSecretPayload(values) {
|
|
1631
|
-
const key = (0,
|
|
1632
|
-
const iv = (0,
|
|
1633
|
-
const cipher = (0,
|
|
2326
|
+
const key = (0, import_node_crypto4.randomBytes)(32);
|
|
2327
|
+
const iv = (0, import_node_crypto4.randomBytes)(12);
|
|
2328
|
+
const cipher = (0, import_node_crypto4.createCipheriv)("aes-256-gcm", key, iv);
|
|
1634
2329
|
const ciphertext = Buffer.concat([cipher.update(JSON.stringify(values), "utf8"), cipher.final()]);
|
|
1635
2330
|
const tag = cipher.getAuthTag();
|
|
1636
2331
|
return {
|
|
@@ -1703,10 +2398,10 @@ function buildNamespaceInterfaces(schema) {
|
|
|
1703
2398
|
continue;
|
|
1704
2399
|
}
|
|
1705
2400
|
const namespace = logicalKey.slice(0, separatorIndex);
|
|
1706
|
-
const
|
|
2401
|
+
const path17 = logicalKey.slice(separatorIndex + 1);
|
|
1707
2402
|
const existing = namespaceGroups.get(namespace) ?? [];
|
|
1708
2403
|
existing.push({
|
|
1709
|
-
key:
|
|
2404
|
+
key: path17,
|
|
1710
2405
|
rule
|
|
1711
2406
|
});
|
|
1712
2407
|
namespaceGroups.set(namespace, existing);
|
|
@@ -1811,15 +2506,15 @@ function generateCodegenContent(manifest, sourcePath, typeModuleImport = "./cnos
|
|
|
1811
2506
|
}
|
|
1812
2507
|
|
|
1813
2508
|
// src/codegen/writeOutput.ts
|
|
1814
|
-
var
|
|
1815
|
-
var
|
|
2509
|
+
var import_promises13 = require("fs/promises");
|
|
2510
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
1816
2511
|
function stripTsExtension(filePath) {
|
|
1817
2512
|
return filePath.replace(/(\.d)?\.[cm]?tsx?$/i, "").replace(/\.[cm]?jsx?$/i, "");
|
|
1818
2513
|
}
|
|
1819
2514
|
function resolveCodegenPaths(repoRoot, out) {
|
|
1820
|
-
const typesPath = out ?
|
|
1821
|
-
const runtimePath =
|
|
1822
|
-
const typeImportPath = `./${
|
|
2515
|
+
const typesPath = out ? import_node_path14.default.resolve(repoRoot, out) : import_node_path14.default.join(repoRoot, ".cnos", "types", "cnos.d.ts");
|
|
2516
|
+
const runtimePath = import_node_path14.default.join(import_node_path14.default.dirname(typesPath), "runtime.ts");
|
|
2517
|
+
const typeImportPath = `./${import_node_path14.default.basename(stripTsExtension(typesPath))}`;
|
|
1823
2518
|
return {
|
|
1824
2519
|
typesPath,
|
|
1825
2520
|
runtimePath,
|
|
@@ -1828,12 +2523,13 @@ function resolveCodegenPaths(repoRoot, out) {
|
|
|
1828
2523
|
}
|
|
1829
2524
|
async function writeCodegenOutput(options = {}) {
|
|
1830
2525
|
const loadedManifest = await loadManifest(options.root ? { root: options.root } : {});
|
|
1831
|
-
const
|
|
2526
|
+
const outputRoot = loadedManifest.rootResolution.remote ? loadedManifest.consumerRoot : loadedManifest.repoRoot;
|
|
2527
|
+
const paths = resolveCodegenPaths(outputRoot, options.out);
|
|
1832
2528
|
const generated = generateCodegenContent(loadedManifest.manifest, loadedManifest.manifestPath, paths.typeImportPath);
|
|
1833
|
-
await (0,
|
|
1834
|
-
await (0,
|
|
1835
|
-
await (0,
|
|
1836
|
-
await (0,
|
|
2529
|
+
await (0, import_promises13.mkdir)(import_node_path14.default.dirname(paths.typesPath), { recursive: true });
|
|
2530
|
+
await (0, import_promises13.mkdir)(import_node_path14.default.dirname(paths.runtimePath), { recursive: true });
|
|
2531
|
+
await (0, import_promises13.writeFile)(paths.typesPath, generated.typesContent, "utf8");
|
|
2532
|
+
await (0, import_promises13.writeFile)(paths.runtimePath, generated.runtimeContent, "utf8");
|
|
1837
2533
|
return {
|
|
1838
2534
|
manifestPath: loadedManifest.manifestPath,
|
|
1839
2535
|
typesPath: paths.typesPath,
|
|
@@ -2019,7 +2715,7 @@ function formatDriftReport(report) {
|
|
|
2019
2715
|
}
|
|
2020
2716
|
|
|
2021
2717
|
// src/migrate/applyManifest.ts
|
|
2022
|
-
var
|
|
2718
|
+
var import_promises14 = require("fs/promises");
|
|
2023
2719
|
function sortRecord(record) {
|
|
2024
2720
|
return Object.fromEntries(Object.entries(record).sort(([left], [right]) => left.localeCompare(right)));
|
|
2025
2721
|
}
|
|
@@ -2054,7 +2750,7 @@ async function applyManifestMappings(proposals, root) {
|
|
|
2054
2750
|
promote: Array.from(promoted).sort((left, right) => left.localeCompare(right))
|
|
2055
2751
|
};
|
|
2056
2752
|
}
|
|
2057
|
-
await (0,
|
|
2753
|
+
await (0, import_promises14.writeFile)(loadedManifest.manifestPath, stringifyYaml(rawManifest), "utf8");
|
|
2058
2754
|
return {
|
|
2059
2755
|
manifestPath: loadedManifest.manifestPath,
|
|
2060
2756
|
appliedMappings,
|
|
@@ -2089,7 +2785,7 @@ function proposeMapping(envVar) {
|
|
|
2089
2785
|
}
|
|
2090
2786
|
|
|
2091
2787
|
// src/migrate/rewriteSource.ts
|
|
2092
|
-
var
|
|
2788
|
+
var import_promises15 = require("fs/promises");
|
|
2093
2789
|
function importStatementFor(kind) {
|
|
2094
2790
|
return kind === "import-meta-env" ? "import cnos from '@kitsy/cnos/browser';" : "import cnos from '@kitsy/cnos';";
|
|
2095
2791
|
}
|
|
@@ -2110,7 +2806,7 @@ async function rewriteSourceFiles(usages, proposals) {
|
|
|
2110
2806
|
const backupFiles = [];
|
|
2111
2807
|
const skippedUsages = [];
|
|
2112
2808
|
for (const [filePath, fileUsages] of fileGroups.entries()) {
|
|
2113
|
-
const original = await (0,
|
|
2809
|
+
const original = await (0, import_promises15.readFile)(filePath, "utf8");
|
|
2114
2810
|
let nextSource = original;
|
|
2115
2811
|
let changed = false;
|
|
2116
2812
|
const importKinds = /* @__PURE__ */ new Set();
|
|
@@ -2137,7 +2833,7 @@ async function rewriteSourceFiles(usages, proposals) {
|
|
|
2137
2833
|
continue;
|
|
2138
2834
|
}
|
|
2139
2835
|
const backupPath = `${filePath}.bak`;
|
|
2140
|
-
await (0,
|
|
2836
|
+
await (0, import_promises15.copyFile)(filePath, backupPath);
|
|
2141
2837
|
backupFiles.push(backupPath);
|
|
2142
2838
|
for (const kind of Array.from(importKinds)) {
|
|
2143
2839
|
const importStatement = importStatementFor(kind);
|
|
@@ -2146,7 +2842,7 @@ async function rewriteSourceFiles(usages, proposals) {
|
|
|
2146
2842
|
${nextSource}`;
|
|
2147
2843
|
}
|
|
2148
2844
|
}
|
|
2149
|
-
await (0,
|
|
2845
|
+
await (0, import_promises15.writeFile)(filePath, nextSource, "utf8");
|
|
2150
2846
|
rewrittenFiles.push(filePath);
|
|
2151
2847
|
}
|
|
2152
2848
|
return {
|
|
@@ -2157,18 +2853,18 @@ ${nextSource}`;
|
|
|
2157
2853
|
}
|
|
2158
2854
|
|
|
2159
2855
|
// src/migrate/scanEnvUsage.ts
|
|
2160
|
-
var
|
|
2161
|
-
var
|
|
2856
|
+
var import_promises16 = require("fs/promises");
|
|
2857
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
2162
2858
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", ".mjs", ".cjs"]);
|
|
2163
2859
|
var PROCESS_ENV_DOT = /process\.env\.([A-Z][A-Z0-9_]*)/g;
|
|
2164
2860
|
var PROCESS_ENV_BRACKET = /process\.env\[['"]([A-Z][A-Z0-9_]*)['"]\]/g;
|
|
2165
2861
|
var IMPORT_META_ENV_DOT = /import\.meta\.env\.([A-Z][A-Z0-9_]*)/g;
|
|
2166
2862
|
var IMPORT_META_ENV_BRACKET = /import\.meta\.env\[['"]([A-Z][A-Z0-9_]*)['"]\]/g;
|
|
2167
2863
|
async function collectFiles(root) {
|
|
2168
|
-
const entries = await (0,
|
|
2864
|
+
const entries = await (0, import_promises16.readdir)(root, { withFileTypes: true });
|
|
2169
2865
|
const files = [];
|
|
2170
2866
|
for (const entry of entries) {
|
|
2171
|
-
const filePath =
|
|
2867
|
+
const filePath = import_node_path15.default.join(root, entry.name);
|
|
2172
2868
|
if (entry.isDirectory()) {
|
|
2173
2869
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") {
|
|
2174
2870
|
continue;
|
|
@@ -2176,7 +2872,7 @@ async function collectFiles(root) {
|
|
|
2176
2872
|
files.push(...await collectFiles(filePath));
|
|
2177
2873
|
continue;
|
|
2178
2874
|
}
|
|
2179
|
-
if (SOURCE_EXTENSIONS.has(
|
|
2875
|
+
if (SOURCE_EXTENSIONS.has(import_node_path15.default.extname(entry.name))) {
|
|
2180
2876
|
files.push(filePath);
|
|
2181
2877
|
}
|
|
2182
2878
|
}
|
|
@@ -2202,7 +2898,7 @@ async function scanEnvUsage(scanRoot) {
|
|
|
2202
2898
|
const files = await collectFiles(scanRoot);
|
|
2203
2899
|
const usages = [];
|
|
2204
2900
|
for (const filePath of files) {
|
|
2205
|
-
const source = await (0,
|
|
2901
|
+
const source = await (0, import_promises16.readFile)(filePath, "utf8");
|
|
2206
2902
|
usages.push(...collectMatches(filePath, source, PROCESS_ENV_DOT, "process-env"));
|
|
2207
2903
|
usages.push(...collectMatches(filePath, source, PROCESS_ENV_BRACKET, "process-env"));
|
|
2208
2904
|
usages.push(...collectMatches(filePath, source, IMPORT_META_ENV_DOT, "import-meta-env"));
|
|
@@ -2243,7 +2939,7 @@ function diffGraphs(previous, next) {
|
|
|
2243
2939
|
}
|
|
2244
2940
|
|
|
2245
2941
|
// src/watch/watchFiles.ts
|
|
2246
|
-
var
|
|
2942
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
2247
2943
|
async function watchFiles(runtime, root) {
|
|
2248
2944
|
const manifest = await loadManifest(root ? { root } : {});
|
|
2249
2945
|
const roots = Array.from(
|
|
@@ -2251,7 +2947,7 @@ async function watchFiles(runtime, root) {
|
|
|
2251
2947
|
).sort((left, right) => left.localeCompare(right));
|
|
2252
2948
|
const files = Array.from(
|
|
2253
2949
|
new Set(
|
|
2254
|
-
Array.from(runtime.graph.entries.values()).map((entry) => entry.winner.origin?.file).filter((file) => Boolean(file)).map((file) =>
|
|
2950
|
+
Array.from(runtime.graph.entries.values()).map((entry) => entry.winner.origin?.file).filter((file) => Boolean(file)).map((file) => import_node_path16.default.resolve(manifest.repoRoot, file))
|
|
2255
2951
|
)
|
|
2256
2952
|
).sort((left, right) => left.localeCompare(right));
|
|
2257
2953
|
return {
|
|
@@ -2272,6 +2968,7 @@ async function watchFiles(runtime, root) {
|
|
|
2272
2968
|
clearAllVaultSessionKeys,
|
|
2273
2969
|
clearVaultSessionKey,
|
|
2274
2970
|
compareSchemaToGraph,
|
|
2971
|
+
createRemoteRootCacheKey,
|
|
2275
2972
|
createSecretVault,
|
|
2276
2973
|
createSecretVaultProvider,
|
|
2277
2974
|
deleteLocalSecret,
|
|
@@ -2288,23 +2985,32 @@ async function watchFiles(runtime, root) {
|
|
|
2288
2985
|
getVaultPassphraseEnvVar,
|
|
2289
2986
|
getVaultSessionKeyEnvVar,
|
|
2290
2987
|
graphRequiresSecretHydration,
|
|
2988
|
+
isDerivedValue,
|
|
2989
|
+
isImmutableGitRef,
|
|
2291
2990
|
isPassphraseEnvRef,
|
|
2292
2991
|
isSecretReference,
|
|
2293
2992
|
listLocalSecrets,
|
|
2294
2993
|
listSecretVaults,
|
|
2295
2994
|
loadManifest,
|
|
2995
|
+
normalizeDerivedValue,
|
|
2996
|
+
parseDerivation,
|
|
2997
|
+
parseGitUri,
|
|
2296
2998
|
parseYaml,
|
|
2297
2999
|
proposeMapping,
|
|
2298
3000
|
readKeychain,
|
|
2299
3001
|
readLocalSecret,
|
|
3002
|
+
readRemoteRootCacheMetadata,
|
|
2300
3003
|
readRuntimeGraphFromEnv,
|
|
2301
3004
|
readServerProjectionFromEnv,
|
|
2302
3005
|
readVaultMetadata,
|
|
2303
3006
|
removeLocalVaultFiles,
|
|
3007
|
+
resolveCnosCacheRoot,
|
|
2304
3008
|
resolveCodegenPaths,
|
|
2305
3009
|
resolveConfigDocumentPath,
|
|
2306
3010
|
resolveConfiguredVaultPassphrase,
|
|
2307
3011
|
resolveManifestRoot,
|
|
3012
|
+
resolveRemoteRootCachePaths,
|
|
3013
|
+
resolveRootUri,
|
|
2308
3014
|
resolveSecretPassphrase,
|
|
2309
3015
|
resolveSecretStoreRoot,
|
|
2310
3016
|
resolveSecretVaultFile,
|
|
@@ -2317,11 +3023,14 @@ async function watchFiles(runtime, root) {
|
|
|
2317
3023
|
serializeSecretPayload,
|
|
2318
3024
|
serializeServerProjection,
|
|
2319
3025
|
stringifyYaml,
|
|
3026
|
+
validateDerivedTargetNamespace,
|
|
3027
|
+
validateParsedDerivation,
|
|
2320
3028
|
validateRuntime,
|
|
2321
3029
|
watchFiles,
|
|
2322
3030
|
watchSchema,
|
|
2323
3031
|
writeCodegenOutput,
|
|
2324
3032
|
writeKeychain,
|
|
2325
3033
|
writeLocalSecret,
|
|
3034
|
+
writeRemoteRootCacheMetadata,
|
|
2326
3035
|
writeVaultSessionKey
|
|
2327
3036
|
});
|