@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/runtime/index.cjs
CHANGED
|
@@ -34,7 +34,7 @@ __export(runtime_exports, {
|
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(runtime_exports);
|
|
36
36
|
var import_node_fs = require("fs");
|
|
37
|
-
var
|
|
37
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
38
38
|
|
|
39
39
|
// ../core/src/errors.ts
|
|
40
40
|
var CnosError = class extends Error {
|
|
@@ -72,16 +72,673 @@ var CnosKeyNotFoundError = class extends CnosError {
|
|
|
72
72
|
}
|
|
73
73
|
key;
|
|
74
74
|
};
|
|
75
|
+
var CnosDerivedExpressionError = class extends CnosError {
|
|
76
|
+
constructor(message, expression) {
|
|
77
|
+
super(expression ? `${message} (${expression})` : message);
|
|
78
|
+
this.expression = expression;
|
|
79
|
+
}
|
|
80
|
+
expression;
|
|
81
|
+
};
|
|
82
|
+
var CnosDerivedCycleError = class extends CnosError {
|
|
83
|
+
constructor(message) {
|
|
84
|
+
super(message);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var CnosDerivedResolutionError = class extends CnosError {
|
|
88
|
+
constructor(key, message) {
|
|
89
|
+
super(message);
|
|
90
|
+
this.key = key;
|
|
91
|
+
}
|
|
92
|
+
key;
|
|
93
|
+
};
|
|
94
|
+
var CnosRuntimeProviderError = class extends CnosError {
|
|
95
|
+
constructor(message) {
|
|
96
|
+
super(message);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// ../core/src/derive/builtins.ts
|
|
101
|
+
function stringify(value) {
|
|
102
|
+
if (value === void 0 || value === null) {
|
|
103
|
+
return "";
|
|
104
|
+
}
|
|
105
|
+
if (typeof value === "string") {
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
109
|
+
return String(value);
|
|
110
|
+
}
|
|
111
|
+
return JSON.stringify(value);
|
|
112
|
+
}
|
|
113
|
+
var DERIVE_BUILTINS = {
|
|
114
|
+
concat: (...args) => args.map((value) => stringify(value)).join(""),
|
|
115
|
+
coalesce: (...args) => args.find((value) => value !== void 0 && value !== null),
|
|
116
|
+
when: (condition, whenTrue, whenFalse) => condition ? whenTrue : whenFalse,
|
|
117
|
+
exists: (value) => value !== void 0 && value !== null,
|
|
118
|
+
eq: (left, right) => left === right,
|
|
119
|
+
ne: (left, right) => left !== right
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// ../core/src/derive/depGraph.ts
|
|
123
|
+
function detectDerivationCycles(dependencyMap) {
|
|
124
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
125
|
+
const visited = /* @__PURE__ */ new Set();
|
|
126
|
+
const stack = [];
|
|
127
|
+
const visit = (key) => {
|
|
128
|
+
if (visited.has(key)) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (visiting.has(key)) {
|
|
132
|
+
const start = stack.indexOf(key);
|
|
133
|
+
const cycle = [...stack.slice(start), key].join(" -> ");
|
|
134
|
+
throw new CnosDerivedCycleError(`Derivation cycle detected: ${cycle}`);
|
|
135
|
+
}
|
|
136
|
+
visiting.add(key);
|
|
137
|
+
stack.push(key);
|
|
138
|
+
for (const dependency of dependencyMap.get(key) ?? []) {
|
|
139
|
+
visit(dependency);
|
|
140
|
+
}
|
|
141
|
+
stack.pop();
|
|
142
|
+
visiting.delete(key);
|
|
143
|
+
visited.add(key);
|
|
144
|
+
};
|
|
145
|
+
for (const key of dependencyMap.keys()) {
|
|
146
|
+
visit(key);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ../core/src/derive/parser.ts
|
|
151
|
+
function isWhitespace(value) {
|
|
152
|
+
return value === " " || value === "\n" || value === "\r" || value === " ";
|
|
153
|
+
}
|
|
154
|
+
function skipWhitespace(state) {
|
|
155
|
+
while (isWhitespace(state.source[state.index])) {
|
|
156
|
+
state.index += 1;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function isIdentifierStart(value) {
|
|
160
|
+
return typeof value === "string" && /[A-Za-z_]/.test(value);
|
|
161
|
+
}
|
|
162
|
+
function isIdentifierPart(value) {
|
|
163
|
+
return typeof value === "string" && /[A-Za-z0-9_.-]/.test(value);
|
|
164
|
+
}
|
|
165
|
+
function errorAt(state, message) {
|
|
166
|
+
throw new CnosDerivedExpressionError(`${message} at position ${state.index + 1}`, state.source);
|
|
167
|
+
}
|
|
168
|
+
function parseStringLiteral(state) {
|
|
169
|
+
const quote = state.source[state.index];
|
|
170
|
+
if (quote !== "'") {
|
|
171
|
+
errorAt(state, "Expected string literal");
|
|
172
|
+
}
|
|
173
|
+
state.index += 1;
|
|
174
|
+
let value = "";
|
|
175
|
+
while (state.index < state.source.length) {
|
|
176
|
+
const current = state.source[state.index];
|
|
177
|
+
if (current === "\\") {
|
|
178
|
+
const next = state.source[state.index + 1];
|
|
179
|
+
if (next === void 0) {
|
|
180
|
+
errorAt(state, "Unterminated escape sequence");
|
|
181
|
+
}
|
|
182
|
+
value += next;
|
|
183
|
+
state.index += 2;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (current === "'") {
|
|
187
|
+
state.index += 1;
|
|
188
|
+
return {
|
|
189
|
+
type: "literal",
|
|
190
|
+
value
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
value += current;
|
|
194
|
+
state.index += 1;
|
|
195
|
+
}
|
|
196
|
+
errorAt(state, "Unterminated string literal");
|
|
197
|
+
}
|
|
198
|
+
function parseNumberLiteral(state) {
|
|
199
|
+
const start = state.index;
|
|
200
|
+
while (/[0-9]/.test(state.source[state.index] ?? "")) {
|
|
201
|
+
state.index += 1;
|
|
202
|
+
}
|
|
203
|
+
if (state.source[state.index] === ".") {
|
|
204
|
+
state.index += 1;
|
|
205
|
+
while (/[0-9]/.test(state.source[state.index] ?? "")) {
|
|
206
|
+
state.index += 1;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
type: "literal",
|
|
211
|
+
value: Number(state.source.slice(start, state.index))
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function parseIdentifier(state) {
|
|
215
|
+
if (!isIdentifierStart(state.source[state.index])) {
|
|
216
|
+
errorAt(state, "Expected identifier");
|
|
217
|
+
}
|
|
218
|
+
const start = state.index;
|
|
219
|
+
state.index += 1;
|
|
220
|
+
while (isIdentifierPart(state.source[state.index])) {
|
|
221
|
+
state.index += 1;
|
|
222
|
+
}
|
|
223
|
+
return state.source.slice(start, state.index);
|
|
224
|
+
}
|
|
225
|
+
function parseArguments(state) {
|
|
226
|
+
const args = [];
|
|
227
|
+
skipWhitespace(state);
|
|
228
|
+
if (state.source[state.index] === ")") {
|
|
229
|
+
state.index += 1;
|
|
230
|
+
return args;
|
|
231
|
+
}
|
|
232
|
+
while (state.index < state.source.length) {
|
|
233
|
+
args.push(parseExpressionNode(state));
|
|
234
|
+
skipWhitespace(state);
|
|
235
|
+
const current = state.source[state.index];
|
|
236
|
+
if (current === ",") {
|
|
237
|
+
state.index += 1;
|
|
238
|
+
skipWhitespace(state);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (current === ")") {
|
|
242
|
+
state.index += 1;
|
|
243
|
+
return args;
|
|
244
|
+
}
|
|
245
|
+
errorAt(state, 'Expected "," or ")"');
|
|
246
|
+
}
|
|
247
|
+
errorAt(state, "Unterminated function call");
|
|
248
|
+
}
|
|
249
|
+
function parseIdentifierOrCall(state) {
|
|
250
|
+
const identifier = parseIdentifier(state);
|
|
251
|
+
skipWhitespace(state);
|
|
252
|
+
if (state.source[state.index] === "(") {
|
|
253
|
+
if (!(identifier in DERIVE_BUILTINS)) {
|
|
254
|
+
throw new CnosDerivedExpressionError(`Unknown derive function: ${identifier}`, state.source);
|
|
255
|
+
}
|
|
256
|
+
state.index += 1;
|
|
257
|
+
return {
|
|
258
|
+
type: "call",
|
|
259
|
+
name: identifier,
|
|
260
|
+
args: parseArguments(state)
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
if (identifier === "true" || identifier === "false") {
|
|
264
|
+
return {
|
|
265
|
+
type: "literal",
|
|
266
|
+
value: identifier === "true"
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
if (identifier === "null") {
|
|
270
|
+
return {
|
|
271
|
+
type: "literal",
|
|
272
|
+
value: null
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
type: "ref",
|
|
277
|
+
path: identifier
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function parseExpressionNode(state) {
|
|
281
|
+
skipWhitespace(state);
|
|
282
|
+
const current = state.source[state.index];
|
|
283
|
+
if (current === "'") {
|
|
284
|
+
return parseStringLiteral(state);
|
|
285
|
+
}
|
|
286
|
+
if (/[0-9]/.test(current ?? "")) {
|
|
287
|
+
return parseNumberLiteral(state);
|
|
288
|
+
}
|
|
289
|
+
if (isIdentifierStart(current)) {
|
|
290
|
+
return parseIdentifierOrCall(state);
|
|
291
|
+
}
|
|
292
|
+
errorAt(state, "Unexpected token");
|
|
293
|
+
}
|
|
294
|
+
function parseExpression(source) {
|
|
295
|
+
const state = {
|
|
296
|
+
source,
|
|
297
|
+
index: 0
|
|
298
|
+
};
|
|
299
|
+
const ast = parseExpressionNode(state);
|
|
300
|
+
skipWhitespace(state);
|
|
301
|
+
if (state.index !== source.length) {
|
|
302
|
+
errorAt(state, "Unexpected trailing input");
|
|
303
|
+
}
|
|
304
|
+
return ast;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// ../core/src/derive/templateParser.ts
|
|
308
|
+
function toLiteral(value) {
|
|
309
|
+
return {
|
|
310
|
+
type: "literal",
|
|
311
|
+
value
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function toRef(path17) {
|
|
315
|
+
return {
|
|
316
|
+
type: "ref",
|
|
317
|
+
path: path17
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
function parseTemplate(source) {
|
|
321
|
+
const parts = [];
|
|
322
|
+
let cursor = 0;
|
|
323
|
+
while (cursor < source.length) {
|
|
324
|
+
const start = source.indexOf("${", cursor);
|
|
325
|
+
if (start < 0) {
|
|
326
|
+
if (cursor < source.length) {
|
|
327
|
+
parts.push(toLiteral(source.slice(cursor)));
|
|
328
|
+
}
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
if (start > cursor) {
|
|
332
|
+
parts.push(toLiteral(source.slice(cursor, start)));
|
|
333
|
+
}
|
|
334
|
+
const end = source.indexOf("}", start + 2);
|
|
335
|
+
if (end < 0) {
|
|
336
|
+
throw new CnosDerivedExpressionError(`Invalid derivation template: unclosed \${...} at position ${start + 1}`, source);
|
|
337
|
+
}
|
|
338
|
+
const ref = source.slice(start + 2, end).trim();
|
|
339
|
+
if (!ref) {
|
|
340
|
+
throw new CnosDerivedExpressionError(`Invalid derivation template: empty reference at position ${start + 1}`, source);
|
|
341
|
+
}
|
|
342
|
+
if (!/^[A-Za-z_][A-Za-z0-9_.-]*$/.test(ref)) {
|
|
343
|
+
throw new CnosDerivedExpressionError(`Invalid derivation template reference "${ref}"`, source);
|
|
344
|
+
}
|
|
345
|
+
parts.push(toRef(ref));
|
|
346
|
+
cursor = end + 1;
|
|
347
|
+
}
|
|
348
|
+
if (parts.length === 0) {
|
|
349
|
+
return toLiteral("");
|
|
350
|
+
}
|
|
351
|
+
if (parts.length === 1) {
|
|
352
|
+
return parts[0];
|
|
353
|
+
}
|
|
354
|
+
return {
|
|
355
|
+
type: "call",
|
|
356
|
+
name: "concat",
|
|
357
|
+
args: parts
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// ../core/src/derive/evaluator.ts
|
|
362
|
+
function isDerivedValue(value) {
|
|
363
|
+
return Boolean(
|
|
364
|
+
value && typeof value === "object" && !Array.isArray(value) && "$derive" in value
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
function extractRefs(node, refs = /* @__PURE__ */ new Set()) {
|
|
368
|
+
if (node.type === "ref") {
|
|
369
|
+
refs.add(node.path);
|
|
370
|
+
return refs;
|
|
371
|
+
}
|
|
372
|
+
if (node.type === "call") {
|
|
373
|
+
for (const arg of node.args) {
|
|
374
|
+
extractRefs(arg, refs);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return refs;
|
|
378
|
+
}
|
|
379
|
+
function parseDerivation(value) {
|
|
380
|
+
const source = typeof value.$derive === "string" ? value.$derive : value.$derive?.expr;
|
|
381
|
+
if (typeof source !== "string") {
|
|
382
|
+
throw new CnosDerivedExpressionError("Derived value requires either a template string or { expr } object");
|
|
383
|
+
}
|
|
384
|
+
const type = typeof value.$derive === "string" ? "template" : "expression";
|
|
385
|
+
const ast = type === "template" ? parseTemplate(source) : parseExpression(source);
|
|
386
|
+
const refs = Array.from(extractRefs(ast)).sort((left, right) => left.localeCompare(right));
|
|
387
|
+
return {
|
|
388
|
+
type,
|
|
389
|
+
raw: source,
|
|
390
|
+
ast,
|
|
391
|
+
refs,
|
|
392
|
+
runtimeRefs: [],
|
|
393
|
+
isRuntimeDependent: false
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
function normalizeConcatValue(value) {
|
|
397
|
+
if (value === void 0 || value === null) {
|
|
398
|
+
return "";
|
|
399
|
+
}
|
|
400
|
+
if (typeof value === "string") {
|
|
401
|
+
return value;
|
|
402
|
+
}
|
|
403
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
404
|
+
return String(value);
|
|
405
|
+
}
|
|
406
|
+
return JSON.stringify(value);
|
|
407
|
+
}
|
|
408
|
+
function evaluateNode(node, resolveRef) {
|
|
409
|
+
switch (node.type) {
|
|
410
|
+
case "literal":
|
|
411
|
+
return node.value;
|
|
412
|
+
case "ref":
|
|
413
|
+
return resolveRef(node.path);
|
|
414
|
+
case "call": {
|
|
415
|
+
const args = node.args.map((arg) => evaluateNode(arg, resolveRef));
|
|
416
|
+
switch (node.name) {
|
|
417
|
+
case "concat":
|
|
418
|
+
return args.map((value) => normalizeConcatValue(value)).join("");
|
|
419
|
+
case "coalesce":
|
|
420
|
+
return DERIVE_BUILTINS.coalesce(...args);
|
|
421
|
+
case "when":
|
|
422
|
+
return DERIVE_BUILTINS.when(args[0], args[1], args[2]);
|
|
423
|
+
case "exists":
|
|
424
|
+
return DERIVE_BUILTINS.exists(args[0]);
|
|
425
|
+
case "eq":
|
|
426
|
+
return DERIVE_BUILTINS.eq(args[0], args[1]);
|
|
427
|
+
case "ne":
|
|
428
|
+
return DERIVE_BUILTINS.ne(args[0], args[1]);
|
|
429
|
+
default:
|
|
430
|
+
throw new CnosDerivedExpressionError(`Unknown derive function: ${String(node.name)}`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
default:
|
|
434
|
+
throw new CnosDerivedExpressionError(`Unsupported derive AST node ${node.type ?? "unknown"}`);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function evaluateDerivation(options) {
|
|
438
|
+
const missingRefs = /* @__PURE__ */ new Set();
|
|
439
|
+
const value = evaluateNode(options.parsed.ast, (ref) => {
|
|
440
|
+
const resolved = options.resolveRef(ref);
|
|
441
|
+
if (resolved === void 0) {
|
|
442
|
+
missingRefs.add(ref);
|
|
443
|
+
options.onMissing?.(ref);
|
|
444
|
+
}
|
|
445
|
+
return resolved;
|
|
446
|
+
});
|
|
447
|
+
if (missingRefs.size > 0 && options.parsed.ast.type === "ref") {
|
|
448
|
+
throw new CnosDerivedResolutionError(
|
|
449
|
+
options.key,
|
|
450
|
+
`Unable to resolve derived config key ${options.key} because ${Array.from(missingRefs).join(", ")} is missing.`
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
return value;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// ../core/src/derive/validate.ts
|
|
457
|
+
var FORBIDDEN_TARGET_NAMESPACES = /* @__PURE__ */ new Set(["public", "meta", "secret"]);
|
|
458
|
+
var FORBIDDEN_REF_NAMESPACES = /* @__PURE__ */ new Set(["public", "secret"]);
|
|
459
|
+
function validateDerivedTargetNamespace(manifest, namespace) {
|
|
460
|
+
if (FORBIDDEN_TARGET_NAMESPACES.has(namespace)) {
|
|
461
|
+
throw new CnosManifestError(`Cannot define derived values under namespace "${namespace}".`);
|
|
462
|
+
}
|
|
463
|
+
if (manifest.runtimeNamespaces[namespace]) {
|
|
464
|
+
throw new CnosManifestError(`Cannot define derived values under runtime namespace "${namespace}".`);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
function validateParsedDerivation(manifest, parsed) {
|
|
468
|
+
for (const ref of parsed.refs) {
|
|
469
|
+
const namespace = ref.split(".")[0] ?? "";
|
|
470
|
+
if (FORBIDDEN_REF_NAMESPACES.has(namespace)) {
|
|
471
|
+
throw new CnosDerivedExpressionError(`Derived expressions cannot reference ${namespace}.* keys.`, parsed.raw);
|
|
472
|
+
}
|
|
473
|
+
if (manifest.runtimeNamespaces[namespace]) {
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
if (!manifest.namespaces[namespace] && namespace !== "value" && namespace !== "meta") {
|
|
477
|
+
throw new CnosDerivedExpressionError(`Unknown derive reference namespace: ${namespace}`, parsed.raw);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// ../core/src/derive/runtime.ts
|
|
483
|
+
function namespaceForKey(key) {
|
|
484
|
+
return key.split(".")[0] ?? "";
|
|
485
|
+
}
|
|
486
|
+
function dependencyNamespaces(key, entries, memo) {
|
|
487
|
+
if (memo.has(key)) {
|
|
488
|
+
return memo.get(key);
|
|
489
|
+
}
|
|
490
|
+
const entry = entries.get(key);
|
|
491
|
+
if (!entry) {
|
|
492
|
+
memo.set(key, []);
|
|
493
|
+
return [];
|
|
494
|
+
}
|
|
495
|
+
const namespaces = /* @__PURE__ */ new Set();
|
|
496
|
+
for (const ref of entry.parsed.refs) {
|
|
497
|
+
const namespace = namespaceForKey(ref);
|
|
498
|
+
if (!entries.has(ref)) {
|
|
499
|
+
namespaces.add(namespace);
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
for (const dependencyNamespace of dependencyNamespaces(ref, entries, memo)) {
|
|
503
|
+
namespaces.add(dependencyNamespace);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
const result = Array.from(namespaces).sort((left, right) => left.localeCompare(right));
|
|
507
|
+
memo.set(key, result);
|
|
508
|
+
return result;
|
|
509
|
+
}
|
|
510
|
+
function isRuntimeDependentKey(key, entries, manifest, memo) {
|
|
511
|
+
if (memo.has(key)) {
|
|
512
|
+
return memo.get(key);
|
|
513
|
+
}
|
|
514
|
+
const entry = entries.get(key);
|
|
515
|
+
if (!entry) {
|
|
516
|
+
memo.set(key, false);
|
|
517
|
+
return false;
|
|
518
|
+
}
|
|
519
|
+
for (const ref of entry.parsed.refs) {
|
|
520
|
+
const namespace = namespaceForKey(ref);
|
|
521
|
+
if (manifest.runtimeNamespaces[namespace]) {
|
|
522
|
+
memo.set(key, true);
|
|
523
|
+
return true;
|
|
524
|
+
}
|
|
525
|
+
if (entries.has(ref) && isRuntimeDependentKey(ref, entries, manifest, memo)) {
|
|
526
|
+
memo.set(key, true);
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
memo.set(key, false);
|
|
531
|
+
return false;
|
|
532
|
+
}
|
|
533
|
+
function prepareEntries(graph, manifest) {
|
|
534
|
+
const entries = /* @__PURE__ */ new Map();
|
|
535
|
+
for (const [key, entry] of graph.entries) {
|
|
536
|
+
if (!isDerivedValue(entry.value)) {
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
const namespaceDefinition = manifest.namespaces[entry.namespace];
|
|
540
|
+
if (!namespaceDefinition || namespaceDefinition.kind === "data") {
|
|
541
|
+
validateDerivedTargetNamespace(manifest, entry.namespace);
|
|
542
|
+
}
|
|
543
|
+
const parsed = parseDerivation(entry.value);
|
|
544
|
+
validateParsedDerivation(manifest, parsed);
|
|
545
|
+
entries.set(key, {
|
|
546
|
+
key,
|
|
547
|
+
namespace: entry.namespace,
|
|
548
|
+
value: entry.value,
|
|
549
|
+
parsed
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
detectDerivationCycles(
|
|
553
|
+
new Map(
|
|
554
|
+
Array.from(entries.values()).map((entry) => [
|
|
555
|
+
entry.key,
|
|
556
|
+
entry.parsed.refs.filter((ref) => entries.has(ref))
|
|
557
|
+
])
|
|
558
|
+
)
|
|
559
|
+
);
|
|
560
|
+
const runtimeMemo = /* @__PURE__ */ new Map();
|
|
561
|
+
const namespaceMemo = /* @__PURE__ */ new Map();
|
|
562
|
+
for (const entry of entries.values()) {
|
|
563
|
+
entry.parsed.isRuntimeDependent = isRuntimeDependentKey(entry.key, entries, manifest, runtimeMemo);
|
|
564
|
+
entry.parsed.runtimeRefs = entry.parsed.refs.filter((ref) => manifest.runtimeNamespaces[namespaceForKey(ref)]);
|
|
565
|
+
if (entry.parsed.runtimeRefs.length === 0 && entry.parsed.isRuntimeDependent) {
|
|
566
|
+
entry.parsed.runtimeRefs = dependencyNamespaces(entry.key, entries, namespaceMemo).filter((namespace) => manifest.runtimeNamespaces[namespace]).map((namespace) => `${namespace}.*`);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
return entries;
|
|
570
|
+
}
|
|
571
|
+
function createDerivedRuntimeSupport(graph, manifest, runtimeProviders) {
|
|
572
|
+
const entries = prepareEntries(graph, manifest);
|
|
573
|
+
const configCache = /* @__PURE__ */ new Map();
|
|
574
|
+
const runtimeDependencyMemo = /* @__PURE__ */ new Map();
|
|
575
|
+
const support = {};
|
|
576
|
+
Object.assign(support, {
|
|
577
|
+
runtimeProviders,
|
|
578
|
+
read(key, readBase) {
|
|
579
|
+
const namespace = namespaceForKey(key);
|
|
580
|
+
if (runtimeProviders.has(namespace)) {
|
|
581
|
+
const provider = runtimeProviders.get(namespace);
|
|
582
|
+
return provider(key.slice(namespace.length + 1));
|
|
583
|
+
}
|
|
584
|
+
if (entries.has(key)) {
|
|
585
|
+
return readDerived(key, readBase);
|
|
586
|
+
}
|
|
587
|
+
return readBase(key);
|
|
588
|
+
},
|
|
589
|
+
describe(key, readBase) {
|
|
590
|
+
const entry = entries.get(key);
|
|
591
|
+
if (!entry) {
|
|
592
|
+
return void 0;
|
|
593
|
+
}
|
|
594
|
+
const runtimeNamespaces = Array.from(
|
|
595
|
+
new Set(
|
|
596
|
+
entry.parsed.refs.map((ref) => namespaceForKey(ref)).filter((namespace) => manifest.runtimeNamespaces[namespace])
|
|
597
|
+
)
|
|
598
|
+
).sort((left, right) => left.localeCompare(right));
|
|
599
|
+
return {
|
|
600
|
+
key,
|
|
601
|
+
type: entry.parsed.type,
|
|
602
|
+
expression: entry.parsed.raw,
|
|
603
|
+
dependencies: entry.parsed.refs.map((ref) => {
|
|
604
|
+
const namespace = namespaceForKey(ref);
|
|
605
|
+
return {
|
|
606
|
+
key: ref,
|
|
607
|
+
value: support.read(ref, readBase),
|
|
608
|
+
...manifest.runtimeNamespaces[namespace] ? {
|
|
609
|
+
runtimeNamespace: namespace
|
|
610
|
+
} : {}
|
|
611
|
+
};
|
|
612
|
+
}),
|
|
613
|
+
runtimeDependent: entry.parsed.isRuntimeDependent,
|
|
614
|
+
runtimeNamespaces,
|
|
615
|
+
...entry.parsed.isRuntimeDependent ? {
|
|
616
|
+
promotionWarning: "Cannot be promoted to browser/public."
|
|
617
|
+
} : {}
|
|
618
|
+
};
|
|
619
|
+
},
|
|
620
|
+
isDerivedKey(key) {
|
|
621
|
+
return entries.has(key);
|
|
622
|
+
},
|
|
623
|
+
isRuntimeDependentKey(key) {
|
|
624
|
+
if (runtimeDependencyMemo.has(key)) {
|
|
625
|
+
return runtimeDependencyMemo.get(key);
|
|
626
|
+
}
|
|
627
|
+
const value = entries.get(key)?.parsed.isRuntimeDependent ?? false;
|
|
628
|
+
runtimeDependencyMemo.set(key, value);
|
|
629
|
+
return value;
|
|
630
|
+
},
|
|
631
|
+
toConcreteValue(key, readBase, mode) {
|
|
632
|
+
const entry = entries.get(key);
|
|
633
|
+
if (!entry) {
|
|
634
|
+
return support.read(key, readBase);
|
|
635
|
+
}
|
|
636
|
+
if (!entry.parsed.isRuntimeDependent) {
|
|
637
|
+
return support.read(key, readBase);
|
|
638
|
+
}
|
|
639
|
+
if (mode === "server" || mode === "runtime") {
|
|
640
|
+
return support.read(key, readBase);
|
|
641
|
+
}
|
|
642
|
+
for (const ref of entry.parsed.refs) {
|
|
643
|
+
const namespace = namespaceForKey(ref);
|
|
644
|
+
const runtimeNamespace = manifest.runtimeNamespaces[namespace];
|
|
645
|
+
if (!runtimeNamespace) {
|
|
646
|
+
continue;
|
|
647
|
+
}
|
|
648
|
+
if (runtimeNamespace.serverOnly) {
|
|
649
|
+
throw new CnosDerivedResolutionError(
|
|
650
|
+
key,
|
|
651
|
+
`Cannot resolve ${key} for ${mode} output because it depends on runtime namespace ${namespace}.`
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
if (!runtimeProviders.has(namespace)) {
|
|
655
|
+
if (mode === "env") {
|
|
656
|
+
return void 0;
|
|
657
|
+
}
|
|
658
|
+
throw new CnosDerivedResolutionError(
|
|
659
|
+
key,
|
|
660
|
+
`Cannot resolve ${key} for ${mode} output because runtime namespace ${namespace} has no registered provider.`
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return support.read(key, readBase);
|
|
665
|
+
},
|
|
666
|
+
toServerFormula(key) {
|
|
667
|
+
const entry = entries.get(key);
|
|
668
|
+
if (!entry || !entry.parsed.isRuntimeDependent) {
|
|
669
|
+
return void 0;
|
|
670
|
+
}
|
|
671
|
+
return {
|
|
672
|
+
expr: entry.parsed.raw,
|
|
673
|
+
deps: entry.parsed.refs.filter((ref) => !manifest.runtimeNamespaces[namespaceForKey(ref)]),
|
|
674
|
+
runtimeRefs: entry.parsed.refs.filter((ref) => manifest.runtimeNamespaces[namespaceForKey(ref)])
|
|
675
|
+
};
|
|
676
|
+
},
|
|
677
|
+
derivedKeys: Array.from(entries.keys()).sort((left, right) => left.localeCompare(right))
|
|
678
|
+
});
|
|
679
|
+
const readDerived = (key, readBase, evaluationStack = /* @__PURE__ */ new Set()) => {
|
|
680
|
+
const entry = entries.get(key);
|
|
681
|
+
if (!entry) {
|
|
682
|
+
return readBase(key);
|
|
683
|
+
}
|
|
684
|
+
if (!entry.parsed.isRuntimeDependent && configCache.has(key)) {
|
|
685
|
+
return configCache.get(key);
|
|
686
|
+
}
|
|
687
|
+
const value = evaluateDerivation({
|
|
688
|
+
key,
|
|
689
|
+
parsed: entry.parsed,
|
|
690
|
+
resolveRef: (ref) => {
|
|
691
|
+
const namespace = namespaceForKey(ref);
|
|
692
|
+
if (runtimeProviders.has(namespace)) {
|
|
693
|
+
const provider = runtimeProviders.get(namespace);
|
|
694
|
+
return provider(ref.slice(namespace.length + 1));
|
|
695
|
+
}
|
|
696
|
+
if (entries.has(ref)) {
|
|
697
|
+
if (evaluationStack.has(ref)) {
|
|
698
|
+
throw new CnosDerivedResolutionError(key, `Unable to resolve derived config key ${key} because of a recursive dependency on ${ref}.`);
|
|
699
|
+
}
|
|
700
|
+
evaluationStack.add(ref);
|
|
701
|
+
const resolved = readDerived(ref, readBase, evaluationStack);
|
|
702
|
+
evaluationStack.delete(ref);
|
|
703
|
+
return resolved;
|
|
704
|
+
}
|
|
705
|
+
return readBase(ref);
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
if (!entry.parsed.isRuntimeDependent) {
|
|
709
|
+
configCache.set(key, value);
|
|
710
|
+
}
|
|
711
|
+
return value;
|
|
712
|
+
};
|
|
713
|
+
for (const key of Array.from(entries.keys()).sort((left, right) => left.localeCompare(right))) {
|
|
714
|
+
const entry = entries.get(key);
|
|
715
|
+
if (!entry.parsed.isRuntimeDependent) {
|
|
716
|
+
readDerived(key, (ref) => graph.entries.get(ref)?.value);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
return support;
|
|
720
|
+
}
|
|
721
|
+
function registerRuntimeProvider(manifest, runtimeProviders, namespace, provider) {
|
|
722
|
+
const definition = manifest.runtimeNamespaces[namespace];
|
|
723
|
+
if (!definition) {
|
|
724
|
+
throw new CnosRuntimeProviderError(`Cannot register runtime provider for undeclared namespace "${namespace}".`);
|
|
725
|
+
}
|
|
726
|
+
if (definition.builtIn) {
|
|
727
|
+
throw new CnosRuntimeProviderError(`Cannot override built-in runtime namespace "${namespace}".`);
|
|
728
|
+
}
|
|
729
|
+
runtimeProviders.set(namespace, provider);
|
|
730
|
+
}
|
|
75
731
|
|
|
76
732
|
// ../core/src/runtime/inspect.ts
|
|
77
|
-
function inspectValue(graph, key) {
|
|
733
|
+
function inspectValue(graph, key, helpers = {}) {
|
|
78
734
|
const entry = graph.entries.get(key);
|
|
79
735
|
if (!entry) {
|
|
80
736
|
throw new CnosKeyNotFoundError(key);
|
|
81
737
|
}
|
|
738
|
+
const derived = helpers.describeDerived?.(key);
|
|
82
739
|
return {
|
|
83
740
|
key: entry.key,
|
|
84
|
-
value: entry.value,
|
|
741
|
+
value: helpers.read ? helpers.read(entry.key) : entry.value,
|
|
85
742
|
namespace: entry.namespace,
|
|
86
743
|
profile: graph.profile,
|
|
87
744
|
profileSource: graph.profileSource,
|
|
@@ -102,7 +759,10 @@ function inspectValue(graph, key) {
|
|
|
102
759
|
workspaceId: override.workspaceId,
|
|
103
760
|
value: override.value,
|
|
104
761
|
...override.origin ? { origin: override.origin } : {}
|
|
105
|
-
}))
|
|
762
|
+
})),
|
|
763
|
+
...derived ? {
|
|
764
|
+
derived
|
|
765
|
+
} : {}
|
|
106
766
|
};
|
|
107
767
|
}
|
|
108
768
|
|
|
@@ -152,59 +812,364 @@ var execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process3
|
|
|
152
812
|
function wrap(script) {
|
|
153
813
|
return ["-NoProfile", "-Command", script];
|
|
154
814
|
}
|
|
155
|
-
async function readWindowsKeychain(entry) {
|
|
156
|
-
try {
|
|
157
|
-
const { stdout } = await execFileAsync3(
|
|
158
|
-
"powershell",
|
|
159
|
-
wrap(`Add-Type -AssemblyName System.Runtime.WindowsRuntime; [Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime] > $null; $vault = New-Object Windows.Security.Credentials.PasswordVault; $credential = $vault.Retrieve('cnos','${entry}'); $credential.RetrievePassword(); Write-Output $credential.Password`)
|
|
815
|
+
async function readWindowsKeychain(entry) {
|
|
816
|
+
try {
|
|
817
|
+
const { stdout } = await execFileAsync3(
|
|
818
|
+
"powershell",
|
|
819
|
+
wrap(`Add-Type -AssemblyName System.Runtime.WindowsRuntime; [Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime] > $null; $vault = New-Object Windows.Security.Credentials.PasswordVault; $credential = $vault.Retrieve('cnos','${entry}'); $credential.RetrievePassword(); Write-Output $credential.Password`)
|
|
820
|
+
);
|
|
821
|
+
const value = stdout.trim();
|
|
822
|
+
return value.length > 0 ? value : void 0;
|
|
823
|
+
} catch {
|
|
824
|
+
return void 0;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// ../core/src/keychain/index.ts
|
|
829
|
+
async function readKeychain(entry) {
|
|
830
|
+
if (process.platform === "win32") {
|
|
831
|
+
return readWindowsKeychain(entry);
|
|
832
|
+
}
|
|
833
|
+
if (process.platform === "darwin") {
|
|
834
|
+
return readMacosKeychain(entry);
|
|
835
|
+
}
|
|
836
|
+
if (process.platform === "linux") {
|
|
837
|
+
return readLinuxKeychain(entry);
|
|
838
|
+
}
|
|
839
|
+
return void 0;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// ../core/src/manifest/loadManifest.ts
|
|
843
|
+
var import_promises5 = require("fs/promises");
|
|
844
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
845
|
+
|
|
846
|
+
// ../core/src/utils/path.ts
|
|
847
|
+
var import_promises4 = require("fs/promises");
|
|
848
|
+
var import_node_os3 = __toESM(require("os"), 1);
|
|
849
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
850
|
+
|
|
851
|
+
// ../core/src/discovery/findCnosrc.ts
|
|
852
|
+
var import_promises3 = require("fs/promises");
|
|
853
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
854
|
+
|
|
855
|
+
// ../core/src/utils/yaml.ts
|
|
856
|
+
var import_yaml = require("yaml");
|
|
857
|
+
function parseYaml(source) {
|
|
858
|
+
return (0, import_yaml.parse)(source);
|
|
859
|
+
}
|
|
860
|
+
function stringifyYaml(value) {
|
|
861
|
+
return (0, import_yaml.stringify)(value);
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
// ../core/src/discovery/resolveRoot.ts
|
|
865
|
+
var import_promises2 = require("fs/promises");
|
|
866
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
867
|
+
var import_node_child_process4 = require("child_process");
|
|
868
|
+
var import_node_os2 = __toESM(require("os"), 1);
|
|
869
|
+
|
|
870
|
+
// ../core/src/discovery/parseGitUri.ts
|
|
871
|
+
function isGitRootUri(uri) {
|
|
872
|
+
return /^git\+[a-z]+:\/\//i.test(uri);
|
|
873
|
+
}
|
|
874
|
+
function parseGitUri(uri) {
|
|
875
|
+
if (!isGitRootUri(uri)) {
|
|
876
|
+
throw new CnosDiscoveryError(`Unsupported git root URI: ${uri}`);
|
|
877
|
+
}
|
|
878
|
+
const withoutPrefix = uri.slice("git+".length);
|
|
879
|
+
const hashIndex = withoutPrefix.indexOf("#");
|
|
880
|
+
if (hashIndex < 0) {
|
|
881
|
+
throw new CnosDiscoveryError(
|
|
882
|
+
`Git root URI must include a #ref (tag, branch, or commit). Got: ${uri}`
|
|
883
|
+
);
|
|
884
|
+
}
|
|
885
|
+
const cloneUrl = withoutPrefix.slice(0, hashIndex);
|
|
886
|
+
const fragment = withoutPrefix.slice(hashIndex + 1);
|
|
887
|
+
const separatorIndex = fragment.indexOf(":");
|
|
888
|
+
const ref = (separatorIndex >= 0 ? fragment.slice(0, separatorIndex) : fragment).trim();
|
|
889
|
+
const subpath = (separatorIndex >= 0 ? fragment.slice(separatorIndex + 1) : ".cnos").trim() || ".cnos";
|
|
890
|
+
const protocol = cloneUrl.slice(0, cloneUrl.indexOf("://"));
|
|
891
|
+
if (!cloneUrl || !ref) {
|
|
892
|
+
throw new CnosDiscoveryError(
|
|
893
|
+
`Git root URI must include both a clone URL and #ref. Got: ${uri}`
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
return {
|
|
897
|
+
uri,
|
|
898
|
+
cloneUrl,
|
|
899
|
+
ref,
|
|
900
|
+
subpath,
|
|
901
|
+
transport: protocol === "https" ? "https" : protocol === "ssh" ? "ssh" : protocol === "file" ? "file" : "custom"
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// ../core/src/discovery/cache/cacheManager.ts
|
|
906
|
+
var SEMVER_TAG_RE = /^v?\d+\.\d+(?:\.\d+)?(?:[-+][A-Za-z0-9.-]+)?$/;
|
|
907
|
+
var COMMIT_SHA_RE = /^[0-9a-f]{40}$/i;
|
|
908
|
+
function isImmutableGitRef(ref) {
|
|
909
|
+
return SEMVER_TAG_RE.test(ref) || COMMIT_SHA_RE.test(ref);
|
|
910
|
+
}
|
|
911
|
+
function resolveRemoteRootCacheTtlSeconds(mode = "runtime", processEnv = process.env, override) {
|
|
912
|
+
if (typeof override === "number" && Number.isFinite(override) && override >= 0) {
|
|
913
|
+
return override;
|
|
914
|
+
}
|
|
915
|
+
const fromEnv = Number(processEnv.CNOS_CACHE_TTL ?? "");
|
|
916
|
+
if (Number.isFinite(fromEnv) && fromEnv >= 0) {
|
|
917
|
+
return fromEnv;
|
|
918
|
+
}
|
|
919
|
+
switch (mode) {
|
|
920
|
+
case "build":
|
|
921
|
+
return 0;
|
|
922
|
+
case "dev":
|
|
923
|
+
return 30;
|
|
924
|
+
case "runtime":
|
|
925
|
+
default:
|
|
926
|
+
return 300;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
function isRemoteRootCacheFresh(metadata, options) {
|
|
930
|
+
if (!metadata || options.forceRefresh) {
|
|
931
|
+
return false;
|
|
932
|
+
}
|
|
933
|
+
if (metadata.uri !== options.uri || metadata.ref !== options.ref) {
|
|
934
|
+
return false;
|
|
935
|
+
}
|
|
936
|
+
if (metadata.isImmutable) {
|
|
937
|
+
return true;
|
|
938
|
+
}
|
|
939
|
+
const ttlSeconds = resolveRemoteRootCacheTtlSeconds(
|
|
940
|
+
options.mode,
|
|
941
|
+
options.processEnv,
|
|
942
|
+
options.ttlSeconds
|
|
943
|
+
);
|
|
944
|
+
if (ttlSeconds <= 0) {
|
|
945
|
+
return false;
|
|
946
|
+
}
|
|
947
|
+
const cachedAtMs = Date.parse(metadata.cachedAt);
|
|
948
|
+
if (Number.isNaN(cachedAtMs)) {
|
|
949
|
+
return false;
|
|
950
|
+
}
|
|
951
|
+
return Date.now() - cachedAtMs <= ttlSeconds * 1e3;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// ../core/src/discovery/cache/cacheMetadata.ts
|
|
955
|
+
var import_promises = require("fs/promises");
|
|
956
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
957
|
+
async function readRemoteRootCacheMetadata(metaPath) {
|
|
958
|
+
try {
|
|
959
|
+
const source = await (0, import_promises.readFile)(metaPath, "utf8");
|
|
960
|
+
const parsed = JSON.parse(source);
|
|
961
|
+
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") {
|
|
962
|
+
return void 0;
|
|
963
|
+
}
|
|
964
|
+
return parsed;
|
|
965
|
+
} catch {
|
|
966
|
+
return void 0;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
async function writeRemoteRootCacheMetadata(metaPath, metadata) {
|
|
970
|
+
await (0, import_promises.mkdir)(import_node_path.default.dirname(metaPath), { recursive: true });
|
|
971
|
+
await (0, import_promises.writeFile)(metaPath, `${JSON.stringify(metadata, null, 2)}
|
|
972
|
+
`, "utf8");
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
// ../core/src/discovery/cache/cachePaths.ts
|
|
976
|
+
var import_node_crypto = require("crypto");
|
|
977
|
+
var import_node_os = __toESM(require("os"), 1);
|
|
978
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
979
|
+
function resolveCnosCacheRoot(processEnv = process.env) {
|
|
980
|
+
return import_node_path2.default.resolve(
|
|
981
|
+
expandHomePath(processEnv.CNOS_CACHE_DIR ?? import_node_path2.default.join(import_node_os.default.homedir(), ".cnos", "cache"))
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
function createRemoteRootCacheKey(uri) {
|
|
985
|
+
return (0, import_node_crypto.createHash)("sha256").update(uri).digest("hex");
|
|
986
|
+
}
|
|
987
|
+
function resolveRemoteRootCachePaths(uri, processEnv = process.env) {
|
|
988
|
+
const cacheRoot = resolveCnosCacheRoot(processEnv);
|
|
989
|
+
const cacheDir = import_node_path2.default.join(cacheRoot, "roots", createRemoteRootCacheKey(uri));
|
|
990
|
+
return {
|
|
991
|
+
cacheRoot,
|
|
992
|
+
cacheDir,
|
|
993
|
+
repoDir: import_node_path2.default.join(cacheDir, "repo"),
|
|
994
|
+
metaPath: import_node_path2.default.join(cacheDir, ".cnos-cache-meta.json")
|
|
995
|
+
};
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
// ../core/src/discovery/resolveRoot.ts
|
|
999
|
+
async function pathExists(targetPath) {
|
|
1000
|
+
try {
|
|
1001
|
+
await (0, import_promises2.access)(targetPath);
|
|
1002
|
+
return true;
|
|
1003
|
+
} catch {
|
|
1004
|
+
return false;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
function expandHomePath2(targetPath) {
|
|
1008
|
+
if (targetPath === "~") {
|
|
1009
|
+
return import_node_os2.default.homedir();
|
|
1010
|
+
}
|
|
1011
|
+
if (targetPath.startsWith("~/") || targetPath.startsWith("~\\")) {
|
|
1012
|
+
return import_node_path3.default.join(import_node_os2.default.homedir(), targetPath.slice(2));
|
|
1013
|
+
}
|
|
1014
|
+
return targetPath;
|
|
1015
|
+
}
|
|
1016
|
+
function isLocalRootUri(rootUri) {
|
|
1017
|
+
return !isGitRootUri2(rootUri) && !isCnosHostedRootUri(rootUri);
|
|
1018
|
+
}
|
|
1019
|
+
function isCnosHostedRootUri(rootUri) {
|
|
1020
|
+
return rootUri.startsWith("cnos://");
|
|
1021
|
+
}
|
|
1022
|
+
function isGitRootUri2(rootUri) {
|
|
1023
|
+
return rootUri.startsWith("git+");
|
|
1024
|
+
}
|
|
1025
|
+
async function runGitCommand(args, options = {}) {
|
|
1026
|
+
return new Promise((resolve, reject) => {
|
|
1027
|
+
const child = (0, import_node_child_process4.spawn)("git", args, {
|
|
1028
|
+
cwd: options.cwd,
|
|
1029
|
+
env: options.processEnv ?? process.env,
|
|
1030
|
+
shell: process.platform === "win32",
|
|
1031
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
1032
|
+
});
|
|
1033
|
+
let stdout = "";
|
|
1034
|
+
let stderr = "";
|
|
1035
|
+
child.stdout.on("data", (chunk) => {
|
|
1036
|
+
stdout += chunk.toString();
|
|
1037
|
+
});
|
|
1038
|
+
child.stderr.on("data", (chunk) => {
|
|
1039
|
+
stderr += chunk.toString();
|
|
1040
|
+
});
|
|
1041
|
+
child.on("error", (error) => {
|
|
1042
|
+
reject(
|
|
1043
|
+
new CnosDiscoveryError(
|
|
1044
|
+
`Failed to run git. Make sure git is installed and available on PATH. ${error.message}`
|
|
1045
|
+
)
|
|
1046
|
+
);
|
|
1047
|
+
});
|
|
1048
|
+
child.on("close", (code) => {
|
|
1049
|
+
if (code === 0) {
|
|
1050
|
+
resolve(stdout.trim());
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
const details = stderr.trim() || stdout.trim();
|
|
1054
|
+
reject(
|
|
1055
|
+
new CnosDiscoveryError(
|
|
1056
|
+
details ? `Git command failed: ${details}` : `Git command failed with exit code ${code ?? 1}`
|
|
1057
|
+
)
|
|
1058
|
+
);
|
|
1059
|
+
});
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
async function resolveLocalRoot(rootUri, cnosrcDir) {
|
|
1063
|
+
const candidateRoot = rootUri.startsWith("~") ? expandHomePath2(rootUri) : rootUri;
|
|
1064
|
+
const manifestRoot = import_node_path3.default.resolve(cnosrcDir, candidateRoot);
|
|
1065
|
+
const manifestPath = import_node_path3.default.join(manifestRoot, "cnos.yml");
|
|
1066
|
+
if (!await pathExists(manifestPath)) {
|
|
1067
|
+
throw new CnosDiscoveryError(`.cnosrc.yml points to ${manifestRoot} but no cnos.yml found there.`);
|
|
1068
|
+
}
|
|
1069
|
+
return {
|
|
1070
|
+
manifestRoot,
|
|
1071
|
+
resolution: {
|
|
1072
|
+
rootUri,
|
|
1073
|
+
protocol: "local",
|
|
1074
|
+
remote: false,
|
|
1075
|
+
readOnly: false
|
|
1076
|
+
}
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
async function ensureGitCheckout(parsed, repoDir, processEnv) {
|
|
1080
|
+
const hasRepo = await pathExists(import_node_path3.default.join(repoDir, ".git"));
|
|
1081
|
+
if (!hasRepo) {
|
|
1082
|
+
await (0, import_promises2.mkdir)(import_node_path3.default.dirname(repoDir), { recursive: true });
|
|
1083
|
+
await runGitCommand(["clone", "--no-checkout", parsed.cloneUrl, repoDir], { processEnv });
|
|
1084
|
+
} else {
|
|
1085
|
+
await runGitCommand(["-C", repoDir, "remote", "set-url", "origin", parsed.cloneUrl], {
|
|
1086
|
+
processEnv
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
await runGitCommand(["-C", repoDir, "fetch", "--tags", "--force", "origin"], { processEnv });
|
|
1090
|
+
await runGitCommand(["-C", repoDir, "checkout", "--force", parsed.ref], { processEnv });
|
|
1091
|
+
await runGitCommand(["-C", repoDir, "clean", "-fdx"], { processEnv });
|
|
1092
|
+
}
|
|
1093
|
+
async function resolveGitRoot(rootUri, options = {}) {
|
|
1094
|
+
const processEnv = options.processEnv ?? process.env;
|
|
1095
|
+
const parsed = parseGitUri(rootUri);
|
|
1096
|
+
const cachePaths = resolveRemoteRootCachePaths(rootUri, processEnv);
|
|
1097
|
+
const metadata = await readRemoteRootCacheMetadata(cachePaths.metaPath);
|
|
1098
|
+
const immutable = isImmutableGitRef(parsed.ref);
|
|
1099
|
+
const cacheFresh = isRemoteRootCacheFresh(metadata, {
|
|
1100
|
+
uri: rootUri,
|
|
1101
|
+
ref: parsed.ref,
|
|
1102
|
+
...options.cacheMode ? { mode: options.cacheMode } : {},
|
|
1103
|
+
processEnv,
|
|
1104
|
+
...typeof options.cacheTtlSeconds === "number" ? { ttlSeconds: options.cacheTtlSeconds } : {},
|
|
1105
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
1106
|
+
});
|
|
1107
|
+
if (!cacheFresh) {
|
|
1108
|
+
try {
|
|
1109
|
+
await ensureGitCheckout(parsed, cachePaths.repoDir, processEnv);
|
|
1110
|
+
} catch (error) {
|
|
1111
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1112
|
+
const authHint = parsed.transport === "ssh" ? " Check your SSH key and git access." : " Check the URL and your git credential helper or token setup.";
|
|
1113
|
+
throw new CnosDiscoveryError(`Failed to resolve remote git root ${rootUri}. ${message}${authHint}`);
|
|
1114
|
+
}
|
|
1115
|
+
const resolvedCommit = await runGitCommand(["-C", cachePaths.repoDir, "rev-parse", "HEAD"], {
|
|
1116
|
+
processEnv
|
|
1117
|
+
});
|
|
1118
|
+
await writeRemoteRootCacheMetadata(cachePaths.metaPath, {
|
|
1119
|
+
uri: rootUri,
|
|
1120
|
+
cloneUrl: parsed.cloneUrl,
|
|
1121
|
+
ref: parsed.ref,
|
|
1122
|
+
subpath: parsed.subpath,
|
|
1123
|
+
resolvedCommit,
|
|
1124
|
+
cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1125
|
+
isImmutable: immutable
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
const nextMetadata = metadata && cacheFresh ? metadata : await readRemoteRootCacheMetadata(cachePaths.metaPath);
|
|
1129
|
+
const manifestRoot = import_node_path3.default.join(cachePaths.repoDir, parsed.subpath);
|
|
1130
|
+
if (!await pathExists(import_node_path3.default.join(manifestRoot, "cnos.yml"))) {
|
|
1131
|
+
throw new CnosDiscoveryError(
|
|
1132
|
+
`Git root ${rootUri} resolved to ${manifestRoot} but no cnos.yml was found there. Check the :subpath segment.`
|
|
160
1133
|
);
|
|
161
|
-
const value = stdout.trim();
|
|
162
|
-
return value.length > 0 ? value : void 0;
|
|
163
|
-
} catch {
|
|
164
|
-
return void 0;
|
|
165
1134
|
}
|
|
1135
|
+
return {
|
|
1136
|
+
manifestRoot,
|
|
1137
|
+
resolution: {
|
|
1138
|
+
rootUri,
|
|
1139
|
+
protocol: "git",
|
|
1140
|
+
remote: true,
|
|
1141
|
+
readOnly: true,
|
|
1142
|
+
cacheDir: cachePaths.cacheDir,
|
|
1143
|
+
cacheMetaPath: cachePaths.metaPath,
|
|
1144
|
+
ref: parsed.ref,
|
|
1145
|
+
subpath: parsed.subpath,
|
|
1146
|
+
immutable,
|
|
1147
|
+
...nextMetadata?.resolvedCommit ? { resolvedCommit: nextMetadata.resolvedCommit } : {},
|
|
1148
|
+
...nextMetadata?.cachedAt ? { cachedAt: nextMetadata.cachedAt } : {}
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
166
1151
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (process.platform === "win32") {
|
|
171
|
-
return readWindowsKeychain(entry);
|
|
1152
|
+
async function resolveRootUri(rootUri, cnosrcDir, options = {}) {
|
|
1153
|
+
if (isLocalRootUri(rootUri)) {
|
|
1154
|
+
return resolveLocalRoot(rootUri, cnosrcDir);
|
|
172
1155
|
}
|
|
173
|
-
if (
|
|
174
|
-
return
|
|
1156
|
+
if (isGitRootUri2(rootUri)) {
|
|
1157
|
+
return resolveGitRoot(rootUri, options);
|
|
175
1158
|
}
|
|
176
|
-
if (
|
|
177
|
-
|
|
1159
|
+
if (isCnosHostedRootUri(rootUri)) {
|
|
1160
|
+
throw new CnosDiscoveryError(
|
|
1161
|
+
`The cnos:// remote root protocol is reserved but not implemented yet. Use git+https:// or git+ssh:// for now.`
|
|
1162
|
+
);
|
|
178
1163
|
}
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// ../core/src/manifest/loadManifest.ts
|
|
183
|
-
var import_promises3 = require("fs/promises");
|
|
184
|
-
var import_node_path3 = __toESM(require("path"), 1);
|
|
185
|
-
|
|
186
|
-
// ../core/src/utils/path.ts
|
|
187
|
-
var import_promises2 = require("fs/promises");
|
|
188
|
-
var import_node_os = __toESM(require("os"), 1);
|
|
189
|
-
var import_node_path2 = __toESM(require("path"), 1);
|
|
190
|
-
|
|
191
|
-
// ../core/src/discovery/findCnosrc.ts
|
|
192
|
-
var import_promises = require("fs/promises");
|
|
193
|
-
var import_node_path = __toESM(require("path"), 1);
|
|
194
|
-
|
|
195
|
-
// ../core/src/utils/yaml.ts
|
|
196
|
-
var import_yaml = require("yaml");
|
|
197
|
-
function parseYaml(source) {
|
|
198
|
-
return (0, import_yaml.parse)(source);
|
|
199
|
-
}
|
|
200
|
-
function stringifyYaml(value) {
|
|
201
|
-
return (0, import_yaml.stringify)(value);
|
|
1164
|
+
throw new CnosDiscoveryError(
|
|
1165
|
+
`Unknown root protocol: ${rootUri}. Supported root protocols are local paths, git+https://..., and git+ssh://....`
|
|
1166
|
+
);
|
|
202
1167
|
}
|
|
203
1168
|
|
|
204
1169
|
// ../core/src/discovery/findCnosrc.ts
|
|
205
1170
|
async function exists(targetPath) {
|
|
206
1171
|
try {
|
|
207
|
-
await (0,
|
|
1172
|
+
await (0, import_promises3.access)(targetPath);
|
|
208
1173
|
return true;
|
|
209
1174
|
} catch {
|
|
210
1175
|
return false;
|
|
@@ -225,13 +1190,13 @@ function validateCnosrc(value, filePath) {
|
|
|
225
1190
|
};
|
|
226
1191
|
}
|
|
227
1192
|
async function findCnosrc(startDir = process.cwd(), maxLevels = 3) {
|
|
228
|
-
let current =
|
|
1193
|
+
let current = import_node_path4.default.resolve(startDir);
|
|
229
1194
|
for (let depth = 0; depth <= maxLevels; depth += 1) {
|
|
230
|
-
const candidate =
|
|
1195
|
+
const candidate = import_node_path4.default.join(current, ".cnosrc.yml");
|
|
231
1196
|
if (await exists(candidate)) {
|
|
232
1197
|
return candidate;
|
|
233
1198
|
}
|
|
234
|
-
const parent =
|
|
1199
|
+
const parent = import_node_path4.default.dirname(current);
|
|
235
1200
|
if (parent === current) {
|
|
236
1201
|
break;
|
|
237
1202
|
}
|
|
@@ -239,27 +1204,22 @@ async function findCnosrc(startDir = process.cwd(), maxLevels = 3) {
|
|
|
239
1204
|
}
|
|
240
1205
|
return void 0;
|
|
241
1206
|
}
|
|
242
|
-
async function discoverCnosAnchor(startDir = process.cwd(), maxLevels = 3) {
|
|
1207
|
+
async function discoverCnosAnchor(startDir = process.cwd(), maxLevels = 3, options = {}) {
|
|
243
1208
|
const anchorPath = await findCnosrc(startDir, maxLevels);
|
|
244
1209
|
if (!anchorPath) {
|
|
245
1210
|
throw new CnosDiscoveryError(
|
|
246
1211
|
"No .cnosrc.yml found. Run cnos init or create .cnosrc.yml in your package root."
|
|
247
1212
|
);
|
|
248
1213
|
}
|
|
249
|
-
const source = await (0,
|
|
1214
|
+
const source = await (0, import_promises3.readFile)(anchorPath, "utf8");
|
|
250
1215
|
const parsed = validateCnosrc(parseYaml(source), anchorPath);
|
|
251
|
-
const consumerRoot =
|
|
252
|
-
const
|
|
253
|
-
const manifestPath = import_node_path.default.join(manifestRoot, "cnos.yml");
|
|
254
|
-
if (!await exists(manifestPath)) {
|
|
255
|
-
throw new CnosDiscoveryError(
|
|
256
|
-
`.cnosrc.yml points to ${manifestRoot} but no cnos.yml found there.`
|
|
257
|
-
);
|
|
258
|
-
}
|
|
1216
|
+
const consumerRoot = import_node_path4.default.dirname(anchorPath);
|
|
1217
|
+
const resolvedRoot = await resolveRootUri(parsed.root, consumerRoot, options);
|
|
259
1218
|
return {
|
|
260
1219
|
anchorPath,
|
|
261
1220
|
consumerRoot,
|
|
262
|
-
manifestRoot,
|
|
1221
|
+
manifestRoot: resolvedRoot.manifestRoot,
|
|
1222
|
+
rootResolution: resolvedRoot.resolution,
|
|
263
1223
|
...parsed.workspace ? { workspace: parsed.workspace } : {}
|
|
264
1224
|
};
|
|
265
1225
|
}
|
|
@@ -269,21 +1229,21 @@ var PRIMARY_CNOS_DIR = ".cnos";
|
|
|
269
1229
|
var LEGACY_CNOS_DIR = "cnos";
|
|
270
1230
|
async function exists2(filePath) {
|
|
271
1231
|
try {
|
|
272
|
-
await (0,
|
|
1232
|
+
await (0, import_promises4.access)(filePath);
|
|
273
1233
|
return true;
|
|
274
1234
|
} catch {
|
|
275
1235
|
return false;
|
|
276
1236
|
}
|
|
277
1237
|
}
|
|
278
1238
|
async function resolveCnosRoot(root = process.cwd()) {
|
|
279
|
-
const basePath =
|
|
1239
|
+
const basePath = import_node_path5.default.resolve(root);
|
|
280
1240
|
const candidates = [
|
|
281
|
-
|
|
282
|
-
|
|
1241
|
+
import_node_path5.default.join(basePath, PRIMARY_CNOS_DIR),
|
|
1242
|
+
import_node_path5.default.join(basePath, LEGACY_CNOS_DIR),
|
|
283
1243
|
basePath
|
|
284
1244
|
];
|
|
285
1245
|
for (const candidate of candidates) {
|
|
286
|
-
if (await exists2(
|
|
1246
|
+
if (await exists2(import_node_path5.default.join(candidate, "cnos.yml"))) {
|
|
287
1247
|
return candidate;
|
|
288
1248
|
}
|
|
289
1249
|
}
|
|
@@ -293,18 +1253,44 @@ async function resolveCnosRoot(root = process.cwd()) {
|
|
|
293
1253
|
}
|
|
294
1254
|
async function resolveManifestRoot(options = {}) {
|
|
295
1255
|
if (options.root) {
|
|
1256
|
+
if (options.root.startsWith("git+") || options.root.startsWith("cnos://")) {
|
|
1257
|
+
const consumerRoot2 = import_node_path5.default.resolve(options.cwd ?? process.cwd());
|
|
1258
|
+
const resolvedRoot2 = await resolveRootUri(options.root, consumerRoot2, {
|
|
1259
|
+
...options.processEnv ? { processEnv: options.processEnv } : {},
|
|
1260
|
+
...options.cacheMode ? { cacheMode: options.cacheMode } : {},
|
|
1261
|
+
...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
|
|
1262
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
1263
|
+
});
|
|
1264
|
+
return {
|
|
1265
|
+
manifestRoot: resolvedRoot2.manifestRoot,
|
|
1266
|
+
consumerRoot: consumerRoot2,
|
|
1267
|
+
rootResolution: resolvedRoot2.resolution
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
296
1270
|
const manifestRoot = await resolveCnosRoot(options.root);
|
|
297
|
-
const resolvedRoot =
|
|
298
|
-
const consumerRoot =
|
|
1271
|
+
const resolvedRoot = import_node_path5.default.resolve(options.root);
|
|
1272
|
+
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;
|
|
299
1273
|
return {
|
|
300
1274
|
manifestRoot,
|
|
301
|
-
consumerRoot
|
|
1275
|
+
consumerRoot,
|
|
1276
|
+
rootResolution: {
|
|
1277
|
+
rootUri: manifestRoot,
|
|
1278
|
+
protocol: "local",
|
|
1279
|
+
remote: false,
|
|
1280
|
+
readOnly: false
|
|
1281
|
+
}
|
|
302
1282
|
};
|
|
303
1283
|
}
|
|
304
|
-
const discovered = await discoverCnosAnchor(options.cwd ?? process.cwd()
|
|
1284
|
+
const discovered = await discoverCnosAnchor(options.cwd ?? process.cwd(), 3, {
|
|
1285
|
+
...options.processEnv ? { processEnv: options.processEnv } : {},
|
|
1286
|
+
...options.cacheMode ? { cacheMode: options.cacheMode } : {},
|
|
1287
|
+
...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
|
|
1288
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
1289
|
+
});
|
|
305
1290
|
return {
|
|
306
1291
|
manifestRoot: discovered.manifestRoot,
|
|
307
1292
|
consumerRoot: discovered.consumerRoot,
|
|
1293
|
+
rootResolution: discovered.rootResolution,
|
|
308
1294
|
anchorPath: discovered.anchorPath,
|
|
309
1295
|
...discovered.workspace ? { workspace: discovered.workspace } : {}
|
|
310
1296
|
};
|
|
@@ -317,10 +1303,10 @@ function interpolatePathTemplate(template, tokens) {
|
|
|
317
1303
|
}
|
|
318
1304
|
function expandHomePath(targetPath) {
|
|
319
1305
|
if (targetPath === "~") {
|
|
320
|
-
return
|
|
1306
|
+
return import_node_os3.default.homedir();
|
|
321
1307
|
}
|
|
322
1308
|
if (targetPath.startsWith("~/") || targetPath.startsWith("~\\")) {
|
|
323
|
-
return
|
|
1309
|
+
return import_node_path5.default.join(import_node_os3.default.homedir(), targetPath.slice(2));
|
|
324
1310
|
}
|
|
325
1311
|
return targetPath;
|
|
326
1312
|
}
|
|
@@ -338,7 +1324,7 @@ function stripWorkspaceTemplatePrefix(template) {
|
|
|
338
1324
|
function resolveWorkspaceScopedPath(workspaceRoot, template, tokens) {
|
|
339
1325
|
const relativeTemplate = stripWorkspaceTemplatePrefix(template);
|
|
340
1326
|
const interpolated = interpolatePathTemplate(relativeTemplate, tokens);
|
|
341
|
-
return
|
|
1327
|
+
return import_node_path5.default.resolve(workspaceRoot, interpolated);
|
|
342
1328
|
}
|
|
343
1329
|
function toPortablePath(targetPath) {
|
|
344
1330
|
return targetPath.replace(/\\/g, "/");
|
|
@@ -404,6 +1390,13 @@ var DEFAULT_NAMESPACES = {
|
|
|
404
1390
|
readonly: true
|
|
405
1391
|
}
|
|
406
1392
|
};
|
|
1393
|
+
var DEFAULT_RUNTIME_NAMESPACES = {
|
|
1394
|
+
process: {
|
|
1395
|
+
description: "Live process runtime values.",
|
|
1396
|
+
serverOnly: true,
|
|
1397
|
+
builtIn: true
|
|
1398
|
+
}
|
|
1399
|
+
};
|
|
407
1400
|
function validateResolveFrom(resolveFrom) {
|
|
408
1401
|
const validValues = ["cli.profile", "env.CNOS_PROFILE", "default"];
|
|
409
1402
|
for (const entry of resolveFrom) {
|
|
@@ -426,7 +1419,7 @@ function normalizeWorkspaceItems(items) {
|
|
|
426
1419
|
}
|
|
427
1420
|
function normalizeNamespaces(namespaces) {
|
|
428
1421
|
const normalized = Object.fromEntries(
|
|
429
|
-
Object.entries(namespaces ?? {}).map(([namespace, definition]) => [
|
|
1422
|
+
Object.entries(namespaces ?? {}).filter(([namespace]) => namespace !== "runtime").map(([namespace, definition]) => [
|
|
430
1423
|
namespace,
|
|
431
1424
|
{
|
|
432
1425
|
kind: definition.kind ?? "data",
|
|
@@ -442,6 +1435,29 @@ function normalizeNamespaces(namespaces) {
|
|
|
442
1435
|
...normalized
|
|
443
1436
|
};
|
|
444
1437
|
}
|
|
1438
|
+
function normalizeRuntimeNamespaces(namespaces) {
|
|
1439
|
+
const runtimeEntries = namespaces?.runtime ?? {};
|
|
1440
|
+
const normalized = Object.fromEntries(
|
|
1441
|
+
Object.entries(runtimeEntries).map(([namespace, definition]) => [
|
|
1442
|
+
namespace,
|
|
1443
|
+
{
|
|
1444
|
+
...definition.description?.trim() ? {
|
|
1445
|
+
description: definition.description.trim()
|
|
1446
|
+
} : {},
|
|
1447
|
+
serverOnly: definition.server_only ?? true
|
|
1448
|
+
}
|
|
1449
|
+
])
|
|
1450
|
+
);
|
|
1451
|
+
for (const namespace of Object.keys(normalized)) {
|
|
1452
|
+
if (DEFAULT_NAMESPACES[namespace] || namespace === "runtime") {
|
|
1453
|
+
throw new CnosManifestError(`Runtime namespace "${namespace}" conflicts with a built-in or reserved namespace.`);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
return {
|
|
1457
|
+
...DEFAULT_RUNTIME_NAMESPACES,
|
|
1458
|
+
...normalized
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
445
1461
|
function normalizeVaults(vaults) {
|
|
446
1462
|
return Object.fromEntries(
|
|
447
1463
|
Object.entries(vaults ?? {}).map(([name, definition]) => {
|
|
@@ -533,6 +1549,7 @@ function normalizeManifest(manifest) {
|
|
|
533
1549
|
const defaultProfile = manifest.profiles?.default?.trim() || "base";
|
|
534
1550
|
const workspaceItems = normalizeWorkspaceItems(manifest.workspaces?.items);
|
|
535
1551
|
const resolveFrom = validateResolveFrom(manifest.profiles?.resolveFrom ?? DEFAULT_RESOLVE_FROM);
|
|
1552
|
+
const runtimeNamespaces = normalizeRuntimeNamespaces(manifest.namespaces);
|
|
536
1553
|
const filesystemValues = {
|
|
537
1554
|
root: "./",
|
|
538
1555
|
format: "yaml",
|
|
@@ -606,6 +1623,7 @@ function normalizeManifest(manifest) {
|
|
|
606
1623
|
}
|
|
607
1624
|
},
|
|
608
1625
|
namespaces: normalizeNamespaces(manifest.namespaces),
|
|
1626
|
+
runtimeNamespaces,
|
|
609
1627
|
vaults: normalizeVaults(manifest.vaults),
|
|
610
1628
|
writePolicy: {
|
|
611
1629
|
define: {
|
|
@@ -624,13 +1642,17 @@ function normalizeManifest(manifest) {
|
|
|
624
1642
|
async function loadManifest(options = {}) {
|
|
625
1643
|
const resolved = await resolveManifestRoot({
|
|
626
1644
|
...options.root ? { root: options.root } : {},
|
|
627
|
-
...options.cwd ? { cwd: options.cwd } : {}
|
|
1645
|
+
...options.cwd ? { cwd: options.cwd } : {},
|
|
1646
|
+
...options.processEnv ? { processEnv: options.processEnv } : {},
|
|
1647
|
+
...options.cacheMode ? { cacheMode: options.cacheMode } : {},
|
|
1648
|
+
...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
|
|
1649
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
628
1650
|
});
|
|
629
1651
|
const manifestRoot = resolved.manifestRoot;
|
|
630
|
-
const manifestPath =
|
|
1652
|
+
const manifestPath = import_node_path6.default.join(manifestRoot, "cnos.yml");
|
|
631
1653
|
let source;
|
|
632
1654
|
try {
|
|
633
|
-
source = await (0,
|
|
1655
|
+
source = await (0, import_promises5.readFile)(manifestPath, "utf8");
|
|
634
1656
|
} catch {
|
|
635
1657
|
throw new CnosManifestError("Unable to read CNOS manifest", manifestPath);
|
|
636
1658
|
}
|
|
@@ -640,10 +1662,11 @@ async function loadManifest(options = {}) {
|
|
|
640
1662
|
}
|
|
641
1663
|
return {
|
|
642
1664
|
manifestRoot,
|
|
643
|
-
repoRoot:
|
|
1665
|
+
repoRoot: import_node_path6.default.dirname(manifestRoot),
|
|
644
1666
|
consumerRoot: resolved.consumerRoot,
|
|
645
1667
|
...resolved.anchorPath ? { anchorPath: resolved.anchorPath } : {},
|
|
646
1668
|
...resolved.workspace ? { anchoredWorkspace: resolved.workspace } : {},
|
|
1669
|
+
rootResolution: resolved.rootResolution,
|
|
647
1670
|
manifestPath,
|
|
648
1671
|
manifest: normalizeManifest(rawManifest),
|
|
649
1672
|
rawManifest
|
|
@@ -651,12 +1674,12 @@ async function loadManifest(options = {}) {
|
|
|
651
1674
|
}
|
|
652
1675
|
|
|
653
1676
|
// ../core/src/manifest/loadWorkspaceFile.ts
|
|
654
|
-
var
|
|
655
|
-
var
|
|
1677
|
+
var import_promises6 = require("fs/promises");
|
|
1678
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
656
1679
|
async function loadWorkspaceFile(repoRoot) {
|
|
657
|
-
const workspaceFilePath =
|
|
1680
|
+
const workspaceFilePath = import_node_path7.default.join(repoRoot, ".cnos-workspace.yml");
|
|
658
1681
|
try {
|
|
659
|
-
const source = await (0,
|
|
1682
|
+
const source = await (0, import_promises6.readFile)(workspaceFilePath, "utf8");
|
|
660
1683
|
const parsed = parseYaml(source);
|
|
661
1684
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
662
1685
|
throw new CnosManifestError(".cnos-workspace.yml must be a YAML object", workspaceFilePath);
|
|
@@ -679,11 +1702,11 @@ async function loadWorkspaceFile(repoRoot) {
|
|
|
679
1702
|
}
|
|
680
1703
|
|
|
681
1704
|
// ../core/src/profiles/expandProfileChain.ts
|
|
682
|
-
var
|
|
683
|
-
var
|
|
1705
|
+
var import_promises7 = require("fs/promises");
|
|
1706
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
684
1707
|
async function fileExists(targetPath) {
|
|
685
1708
|
try {
|
|
686
|
-
await (0,
|
|
1709
|
+
await (0, import_promises7.access)(targetPath);
|
|
687
1710
|
return true;
|
|
688
1711
|
} catch {
|
|
689
1712
|
return false;
|
|
@@ -717,11 +1740,11 @@ async function loadProfileDefinition(profileName, options) {
|
|
|
717
1740
|
return normalizeProfileDefinition(profileName, void 0);
|
|
718
1741
|
}
|
|
719
1742
|
for (const workspaceRoot of [...workspaceRoots].reverse()) {
|
|
720
|
-
const profilePath =
|
|
1743
|
+
const profilePath = import_node_path8.default.join(workspaceRoot.path, "profiles", `${profileName}.yml`);
|
|
721
1744
|
if (!await fileExists(profilePath)) {
|
|
722
1745
|
continue;
|
|
723
1746
|
}
|
|
724
|
-
const document = await (0,
|
|
1747
|
+
const document = await (0, import_promises7.readFile)(profilePath, "utf8");
|
|
725
1748
|
const parsed = parseYaml(document);
|
|
726
1749
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
727
1750
|
throw new CnosManifestError("Profile definition must be a YAML object", profilePath);
|
|
@@ -729,7 +1752,7 @@ async function loadProfileDefinition(profileName, options) {
|
|
|
729
1752
|
const definition = normalizeProfileDefinition(
|
|
730
1753
|
profileName,
|
|
731
1754
|
parsed,
|
|
732
|
-
options.manifestRoot ? toPortablePath(
|
|
1755
|
+
options.manifestRoot ? toPortablePath(import_node_path8.default.relative(import_node_path8.default.dirname(options.manifestRoot), profilePath)) : toPortablePath(profilePath)
|
|
733
1756
|
);
|
|
734
1757
|
if (definition.name !== profileName) {
|
|
735
1758
|
throw new CnosManifestError(
|
|
@@ -1011,8 +2034,8 @@ function createProfileAwareResolver() {
|
|
|
1011
2034
|
}
|
|
1012
2035
|
|
|
1013
2036
|
// ../core/src/workspaces/resolveWorkspaceContext.ts
|
|
1014
|
-
var
|
|
1015
|
-
var
|
|
2037
|
+
var import_promises8 = require("fs/promises");
|
|
2038
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
1016
2039
|
|
|
1017
2040
|
// ../core/src/workspaces/expandWorkspaceChain.ts
|
|
1018
2041
|
function expandWorkspaceChain(workspaceId, items) {
|
|
@@ -1051,14 +2074,14 @@ function expandWorkspaceChain(workspaceId, items) {
|
|
|
1051
2074
|
// ../core/src/workspaces/resolveWorkspaceContext.ts
|
|
1052
2075
|
async function exists3(targetPath) {
|
|
1053
2076
|
try {
|
|
1054
|
-
await (0,
|
|
2077
|
+
await (0, import_promises8.access)(targetPath);
|
|
1055
2078
|
return true;
|
|
1056
2079
|
} catch {
|
|
1057
2080
|
return false;
|
|
1058
2081
|
}
|
|
1059
2082
|
}
|
|
1060
2083
|
async function resolveLocalWorkspaceRoot(manifestRoot, workspaceId, manifest) {
|
|
1061
|
-
const workspaceRoot =
|
|
2084
|
+
const workspaceRoot = import_node_path9.default.join(manifestRoot, "workspaces", workspaceId);
|
|
1062
2085
|
if (await exists3(workspaceRoot)) {
|
|
1063
2086
|
return workspaceRoot;
|
|
1064
2087
|
}
|
|
@@ -1066,7 +2089,7 @@ async function resolveLocalWorkspaceRoot(manifestRoot, workspaceId, manifest) {
|
|
|
1066
2089
|
([namespace, definition]) => namespace !== "value" && namespace !== "secret" && definition.kind === "data" && !definition.sensitive
|
|
1067
2090
|
).map(([namespace]) => namespace);
|
|
1068
2091
|
const legacyMarkers = ["values", "secrets", "env", "profiles", ...customDataNamespaceRoots].map(
|
|
1069
|
-
(segment) =>
|
|
2092
|
+
(segment) => import_node_path9.default.join(manifestRoot, segment)
|
|
1070
2093
|
);
|
|
1071
2094
|
if ((await Promise.all(legacyMarkers.map((marker) => exists3(marker)))).some(Boolean)) {
|
|
1072
2095
|
return manifestRoot;
|
|
@@ -1114,26 +2137,26 @@ function resolveGlobalRoot(manifest, workspaceFile, options) {
|
|
|
1114
2137
|
}
|
|
1115
2138
|
if (options.globalRoot) {
|
|
1116
2139
|
return {
|
|
1117
|
-
value:
|
|
2140
|
+
value: import_node_path9.default.resolve(expandHomePath(options.globalRoot)),
|
|
1118
2141
|
source: "cli"
|
|
1119
2142
|
};
|
|
1120
2143
|
}
|
|
1121
2144
|
if (workspaceFile?.globalRoot) {
|
|
1122
2145
|
return {
|
|
1123
|
-
value:
|
|
2146
|
+
value: import_node_path9.default.resolve(expandHomePath(workspaceFile.globalRoot)),
|
|
1124
2147
|
source: "workspace-file"
|
|
1125
2148
|
};
|
|
1126
2149
|
}
|
|
1127
2150
|
if (manifest.workspaces.global.root) {
|
|
1128
2151
|
return {
|
|
1129
|
-
value:
|
|
2152
|
+
value: import_node_path9.default.resolve(expandHomePath(manifest.workspaces.global.root)),
|
|
1130
2153
|
source: "manifest"
|
|
1131
2154
|
};
|
|
1132
2155
|
}
|
|
1133
2156
|
const cnosHome = options.processEnv?.CNOS_HOME;
|
|
1134
2157
|
if (cnosHome) {
|
|
1135
2158
|
return {
|
|
1136
|
-
value:
|
|
2159
|
+
value: import_node_path9.default.resolve(expandHomePath(cnosHome)),
|
|
1137
2160
|
source: "CNOS_HOME"
|
|
1138
2161
|
};
|
|
1139
2162
|
}
|
|
@@ -1155,7 +2178,7 @@ async function resolveWorkspaceContext(manifest, options) {
|
|
|
1155
2178
|
workspaceRoots.push({
|
|
1156
2179
|
scope: "global",
|
|
1157
2180
|
workspaceId: chainWorkspaceId,
|
|
1158
|
-
path:
|
|
2181
|
+
path: import_node_path9.default.join(globalRoot.value, "workspaces", globalWorkspaceId)
|
|
1159
2182
|
});
|
|
1160
2183
|
}
|
|
1161
2184
|
}
|
|
@@ -1278,6 +2301,10 @@ function applySchemaRules(graph, schema) {
|
|
|
1278
2301
|
}
|
|
1279
2302
|
continue;
|
|
1280
2303
|
}
|
|
2304
|
+
if (isDerivedValue(resolvedEntry.value)) {
|
|
2305
|
+
nextEntries.set(key, resolvedEntry);
|
|
2306
|
+
continue;
|
|
2307
|
+
}
|
|
1281
2308
|
const coercedValue = coerceValue(resolvedEntry.value, rule);
|
|
1282
2309
|
const nextResolvedEntry = coercedValue === resolvedEntry.value ? resolvedEntry : {
|
|
1283
2310
|
...resolvedEntry,
|
|
@@ -1347,26 +2374,26 @@ async function runPipeline(options) {
|
|
|
1347
2374
|
}
|
|
1348
2375
|
|
|
1349
2376
|
// ../core/src/secrets/auditLog.ts
|
|
1350
|
-
var
|
|
1351
|
-
var
|
|
2377
|
+
var import_promises11 = require("fs/promises");
|
|
2378
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
1352
2379
|
|
|
1353
2380
|
// ../core/src/utils/secretStore.ts
|
|
1354
|
-
var
|
|
1355
|
-
var
|
|
1356
|
-
var
|
|
2381
|
+
var import_node_crypto2 = require("crypto");
|
|
2382
|
+
var import_promises10 = require("fs/promises");
|
|
2383
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
1357
2384
|
|
|
1358
2385
|
// ../core/src/secrets/sessionStore.ts
|
|
1359
|
-
var
|
|
1360
|
-
var
|
|
2386
|
+
var import_promises9 = require("fs/promises");
|
|
2387
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
1361
2388
|
function buildSessionRoot(processEnv = process.env) {
|
|
1362
|
-
return
|
|
2389
|
+
return import_node_path10.default.join(import_node_path10.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets")), "sessions");
|
|
1363
2390
|
}
|
|
1364
2391
|
function buildSessionPath(vault, processEnv) {
|
|
1365
|
-
return
|
|
2392
|
+
return import_node_path10.default.join(buildSessionRoot(processEnv), `${vault}.json`);
|
|
1366
2393
|
}
|
|
1367
2394
|
async function readVaultSessionKey(vault, processEnv) {
|
|
1368
2395
|
try {
|
|
1369
|
-
const source = await (0,
|
|
2396
|
+
const source = await (0, import_promises9.readFile)(buildSessionPath(vault, processEnv), "utf8");
|
|
1370
2397
|
const document = JSON.parse(source);
|
|
1371
2398
|
if (document.version !== 1 || typeof document.derivedKey !== "string") {
|
|
1372
2399
|
return void 0;
|
|
@@ -1395,7 +2422,7 @@ function isSecretReference(value) {
|
|
|
1395
2422
|
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));
|
|
1396
2423
|
}
|
|
1397
2424
|
function resolveSecretStoreRoot(processEnv = process.env) {
|
|
1398
|
-
return
|
|
2425
|
+
return import_node_path11.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
|
|
1399
2426
|
}
|
|
1400
2427
|
function normalizeVaultToken(vault = "default") {
|
|
1401
2428
|
return vault.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
|
|
@@ -1424,19 +2451,19 @@ function resolveVaultSessionKey(vault = "default", processEnv = process.env) {
|
|
|
1424
2451
|
}
|
|
1425
2452
|
}
|
|
1426
2453
|
function deriveVaultKey(passphrase, salt, iterations = PBKDF2_ITERATIONS) {
|
|
1427
|
-
return (0,
|
|
2454
|
+
return (0, import_node_crypto2.pbkdf2Sync)(passphrase, salt, iterations, KEY_LENGTH, "sha512");
|
|
1428
2455
|
}
|
|
1429
2456
|
function buildMetaPath(storeRoot, vault = "default") {
|
|
1430
|
-
return
|
|
2457
|
+
return import_node_path11.default.join(storeRoot, "vaults", vault, META_FILENAME);
|
|
1431
2458
|
}
|
|
1432
2459
|
function buildKeystorePath(storeRoot, vault = "default") {
|
|
1433
|
-
return
|
|
2460
|
+
return import_node_path11.default.join(storeRoot, "vaults", vault, KEYSTORE_FILENAME);
|
|
1434
2461
|
}
|
|
1435
2462
|
function buildLegacyVaultFile(storeRoot, vault = "default") {
|
|
1436
|
-
return
|
|
2463
|
+
return import_node_path11.default.join(storeRoot, "vaults", `${vault}.json`);
|
|
1437
2464
|
}
|
|
1438
2465
|
function buildLegacyVaultStoreRoot(storeRoot, vault = "default") {
|
|
1439
|
-
return
|
|
2466
|
+
return import_node_path11.default.join(storeRoot, "vaults", vault, "store");
|
|
1440
2467
|
}
|
|
1441
2468
|
function assertVaultMetadata(value, filePath) {
|
|
1442
2469
|
if (!isObject(value)) {
|
|
@@ -1449,7 +2476,7 @@ function assertVaultMetadata(value, filePath) {
|
|
|
1449
2476
|
}
|
|
1450
2477
|
async function exists4(targetPath) {
|
|
1451
2478
|
try {
|
|
1452
|
-
await (0,
|
|
2479
|
+
await (0, import_promises10.stat)(targetPath);
|
|
1453
2480
|
return true;
|
|
1454
2481
|
} catch {
|
|
1455
2482
|
return false;
|
|
@@ -1476,8 +2503,8 @@ async function assertNoLegacyVaultFormat(storeRoot, vault = "default") {
|
|
|
1476
2503
|
);
|
|
1477
2504
|
}
|
|
1478
2505
|
function encryptPayload(payload, key) {
|
|
1479
|
-
const iv = (0,
|
|
1480
|
-
const cipher = (0,
|
|
2506
|
+
const iv = (0, import_node_crypto2.randomBytes)(IV_LENGTH);
|
|
2507
|
+
const cipher = (0, import_node_crypto2.createCipheriv)("aes-256-gcm", key, iv);
|
|
1481
2508
|
const plaintext = Buffer.from(JSON.stringify(payload), "utf8");
|
|
1482
2509
|
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
1483
2510
|
const tag = cipher.getAuthTag();
|
|
@@ -1502,7 +2529,7 @@ function decryptPayload(buffer, key) {
|
|
|
1502
2529
|
const iv = buffer.subarray(ivOffset, tagOffset);
|
|
1503
2530
|
const tag = buffer.subarray(tagOffset, cipherOffset);
|
|
1504
2531
|
const ciphertext = buffer.subarray(cipherOffset);
|
|
1505
|
-
const decipher = (0,
|
|
2532
|
+
const decipher = (0, import_node_crypto2.createDecipheriv)("aes-256-gcm", key, iv);
|
|
1506
2533
|
decipher.setAuthTag(tag);
|
|
1507
2534
|
try {
|
|
1508
2535
|
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
@@ -1533,15 +2560,15 @@ function buildInitialPayload() {
|
|
|
1533
2560
|
async function writeVaultFiles(storeRoot, vault, meta, payload, key) {
|
|
1534
2561
|
const metaPath = buildMetaPath(storeRoot, vault);
|
|
1535
2562
|
const keystorePath = buildKeystorePath(storeRoot, vault);
|
|
1536
|
-
await (0,
|
|
1537
|
-
await (0,
|
|
1538
|
-
await (0,
|
|
2563
|
+
await (0, import_promises10.mkdir)(import_node_path11.default.dirname(metaPath), { recursive: true });
|
|
2564
|
+
await (0, import_promises10.writeFile)(metaPath, stringifyYaml(meta), "utf8");
|
|
2565
|
+
await (0, import_promises10.writeFile)(keystorePath, encryptPayload(payload, key));
|
|
1539
2566
|
}
|
|
1540
2567
|
async function readVaultMetadata(storeRoot, vault = "default") {
|
|
1541
2568
|
await assertNoLegacyVaultFormat(storeRoot, vault);
|
|
1542
2569
|
const metaPath = buildMetaPath(storeRoot, vault);
|
|
1543
2570
|
try {
|
|
1544
|
-
const source = await (0,
|
|
2571
|
+
const source = await (0, import_promises10.readFile)(metaPath, "utf8");
|
|
1545
2572
|
return assertVaultMetadata(parseYaml(source), metaPath);
|
|
1546
2573
|
} catch (error) {
|
|
1547
2574
|
if (error.code === "ENOENT") {
|
|
@@ -1553,7 +2580,7 @@ async function readVaultMetadata(storeRoot, vault = "default") {
|
|
|
1553
2580
|
async function createSecretVault(storeRoot, vault, passphrase) {
|
|
1554
2581
|
const normalizedVault = vault.trim() || "default";
|
|
1555
2582
|
await assertNoLegacyVaultFormat(storeRoot, normalizedVault);
|
|
1556
|
-
const salt = (0,
|
|
2583
|
+
const salt = (0, import_node_crypto2.randomBytes)(SALT_LENGTH);
|
|
1557
2584
|
const key = deriveVaultKey(passphrase, salt, PBKDF2_ITERATIONS);
|
|
1558
2585
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1559
2586
|
const meta = {
|
|
@@ -1632,7 +2659,7 @@ async function loadVaultPayload(storeRoot, vault, auth) {
|
|
|
1632
2659
|
if (!key) {
|
|
1633
2660
|
throw new CnosAuthenticationError(`Vault "${vault}" requires authentication before access.`);
|
|
1634
2661
|
}
|
|
1635
|
-
const buffer = await (0,
|
|
2662
|
+
const buffer = await (0, import_promises10.readFile)(buildKeystorePath(storeRoot, vault));
|
|
1636
2663
|
return {
|
|
1637
2664
|
meta,
|
|
1638
2665
|
payload: decryptPayload(buffer, key),
|
|
@@ -1707,9 +2734,9 @@ function resolveVaultDefinition(vaults, vault = "default") {
|
|
|
1707
2734
|
|
|
1708
2735
|
// ../core/src/secrets/auditLog.ts
|
|
1709
2736
|
async function appendAuditEvent(event, processEnv = process.env) {
|
|
1710
|
-
const auditFile = processEnv.CNOS_AUDIT_FILE ??
|
|
1711
|
-
await (0,
|
|
1712
|
-
await (0,
|
|
2737
|
+
const auditFile = processEnv.CNOS_AUDIT_FILE ?? import_node_path12.default.join(resolveSecretStoreRoot(processEnv), "audit", "access.log");
|
|
2738
|
+
await (0, import_promises11.mkdir)(import_node_path12.default.dirname(auditFile), { recursive: true });
|
|
2739
|
+
await (0, import_promises11.appendFile)(
|
|
1713
2740
|
auditFile,
|
|
1714
2741
|
`${JSON.stringify({
|
|
1715
2742
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -2067,7 +3094,7 @@ function setNestedValue(target, pathSegments, value) {
|
|
|
2067
3094
|
target[head] = nextTarget;
|
|
2068
3095
|
setNestedValue(nextTarget, tail, value);
|
|
2069
3096
|
}
|
|
2070
|
-
function toNamespaceObject(graph, namespace) {
|
|
3097
|
+
function toNamespaceObject(graph, namespace, readValueForKey = (key) => graph.entries.get(key)?.value) {
|
|
2071
3098
|
const output = {};
|
|
2072
3099
|
const resolvedEntries = Array.from(graph.entries.values()).sort(
|
|
2073
3100
|
(left, right) => left.key.localeCompare(right.key)
|
|
@@ -2077,7 +3104,11 @@ function toNamespaceObject(graph, namespace) {
|
|
|
2077
3104
|
continue;
|
|
2078
3105
|
}
|
|
2079
3106
|
const valuePath = namespace ? stripNamespace(entry.key) : entry.key;
|
|
2080
|
-
|
|
3107
|
+
const value = readValueForKey(entry.key);
|
|
3108
|
+
if (value === void 0) {
|
|
3109
|
+
continue;
|
|
3110
|
+
}
|
|
3111
|
+
setNestedValue(output, valuePath.split("."), value);
|
|
2081
3112
|
}
|
|
2082
3113
|
return output;
|
|
2083
3114
|
}
|
|
@@ -2087,12 +3118,6 @@ function readValue(graph, key) {
|
|
|
2087
3118
|
return graph.entries.get(key)?.value;
|
|
2088
3119
|
}
|
|
2089
3120
|
|
|
2090
|
-
// ../core/src/runtime/readOr.ts
|
|
2091
|
-
function readOrValue(graph, key, fallback) {
|
|
2092
|
-
const value = readValue(graph, key);
|
|
2093
|
-
return value === void 0 ? fallback : value;
|
|
2094
|
-
}
|
|
2095
|
-
|
|
2096
3121
|
// ../core/src/runtime/require.ts
|
|
2097
3122
|
function requireValue(graph, key) {
|
|
2098
3123
|
const value = readValue(graph, key);
|
|
@@ -2102,8 +3127,38 @@ function requireValue(graph, key) {
|
|
|
2102
3127
|
return value;
|
|
2103
3128
|
}
|
|
2104
3129
|
|
|
3130
|
+
// ../core/src/runtime/runtimeProviders.ts
|
|
3131
|
+
function createDefaultRuntimeProviders(manifest, processEnv) {
|
|
3132
|
+
const providers = /* @__PURE__ */ new Map();
|
|
3133
|
+
if (manifest.runtimeNamespaces.process) {
|
|
3134
|
+
providers.set("process", (key) => {
|
|
3135
|
+
const segments = key.split(".");
|
|
3136
|
+
if (segments[0] === "env") {
|
|
3137
|
+
return processEnv[segments.slice(1).join(".")];
|
|
3138
|
+
}
|
|
3139
|
+
if (key === "cwd") {
|
|
3140
|
+
return process.cwd();
|
|
3141
|
+
}
|
|
3142
|
+
if (key === "platform") {
|
|
3143
|
+
return process.platform;
|
|
3144
|
+
}
|
|
3145
|
+
if (key === "arch") {
|
|
3146
|
+
return process.arch;
|
|
3147
|
+
}
|
|
3148
|
+
if (key === "pid") {
|
|
3149
|
+
return process.pid;
|
|
3150
|
+
}
|
|
3151
|
+
if (key === "node.version") {
|
|
3152
|
+
return process.version;
|
|
3153
|
+
}
|
|
3154
|
+
return void 0;
|
|
3155
|
+
});
|
|
3156
|
+
}
|
|
3157
|
+
return providers;
|
|
3158
|
+
}
|
|
3159
|
+
|
|
2105
3160
|
// ../core/src/runtime/toServerProjection.ts
|
|
2106
|
-
var
|
|
3161
|
+
var import_node_crypto3 = require("crypto");
|
|
2107
3162
|
function stableSortObject(value) {
|
|
2108
3163
|
return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)));
|
|
2109
3164
|
}
|
|
@@ -2112,12 +3167,14 @@ function stripValuePrefix(key) {
|
|
|
2112
3167
|
}
|
|
2113
3168
|
function configHash(values) {
|
|
2114
3169
|
const serialized = JSON.stringify(stableSortObject(values));
|
|
2115
|
-
return (0,
|
|
3170
|
+
return (0, import_node_crypto3.createHash)("sha256").update(serialized).digest("hex");
|
|
2116
3171
|
}
|
|
2117
|
-
function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev") {
|
|
3172
|
+
function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev", helpers = {}) {
|
|
2118
3173
|
const values = {};
|
|
3174
|
+
const derived = {};
|
|
2119
3175
|
const secretRefs = {};
|
|
2120
3176
|
const namespaces = /* @__PURE__ */ new Set();
|
|
3177
|
+
const runtimeNamespaces = /* @__PURE__ */ new Set();
|
|
2121
3178
|
const publicKeys = Array.from(graph.entries.values()).filter((entry) => entry.namespace === "public").map((entry) => entry.key.slice("public.".length)).sort((left, right) => left.localeCompare(right));
|
|
2122
3179
|
for (const [key, entry] of graph.entries) {
|
|
2123
3180
|
if (entry.namespace === "secret" && isSecretReference(entry.value)) {
|
|
@@ -2129,12 +3186,33 @@ function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev") {
|
|
|
2129
3186
|
continue;
|
|
2130
3187
|
}
|
|
2131
3188
|
if (entry.namespace === "value") {
|
|
2132
|
-
|
|
3189
|
+
if (helpers.isRuntimeDependent?.(key)) {
|
|
3190
|
+
const formula = helpers.toServerFormula?.(key);
|
|
3191
|
+
if (formula) {
|
|
3192
|
+
derived[stripValuePrefix(key)] = formula;
|
|
3193
|
+
for (const ref of formula.runtimeRefs) {
|
|
3194
|
+
runtimeNamespaces.add(ref.split(".")[0] ?? "");
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
continue;
|
|
3198
|
+
}
|
|
3199
|
+
const value = helpers.read ? helpers.read(key) : entry.value;
|
|
3200
|
+
values[stripValuePrefix(key)] = value;
|
|
2133
3201
|
continue;
|
|
2134
3202
|
}
|
|
2135
3203
|
const namespaceDefinition = manifest.namespaces[entry.namespace];
|
|
2136
3204
|
if (namespaceDefinition && namespaceDefinition.kind === "data" && !namespaceDefinition.sensitive && entry.namespace !== "public") {
|
|
2137
|
-
|
|
3205
|
+
if (helpers.isRuntimeDependent?.(key)) {
|
|
3206
|
+
const formula = helpers.toServerFormula?.(key);
|
|
3207
|
+
if (formula) {
|
|
3208
|
+
derived[key] = formula;
|
|
3209
|
+
for (const ref of formula.runtimeRefs) {
|
|
3210
|
+
runtimeNamespaces.add(ref.split(".")[0] ?? "");
|
|
3211
|
+
}
|
|
3212
|
+
}
|
|
3213
|
+
continue;
|
|
3214
|
+
}
|
|
3215
|
+
values[key] = helpers.read ? helpers.read(key) : entry.value;
|
|
2138
3216
|
namespaces.add(entry.namespace);
|
|
2139
3217
|
}
|
|
2140
3218
|
}
|
|
@@ -2145,8 +3223,10 @@ function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev") {
|
|
|
2145
3223
|
resolvedAt: graph.resolvedAt,
|
|
2146
3224
|
configHash: configHash(values),
|
|
2147
3225
|
values: stableSortObject(values),
|
|
3226
|
+
derived: stableSortObject(derived),
|
|
2148
3227
|
secretRefs: stableSortObject(secretRefs),
|
|
2149
3228
|
publicKeys,
|
|
3229
|
+
runtimeNamespaces: Array.from(runtimeNamespaces).sort((left, right) => left.localeCompare(right)),
|
|
2150
3230
|
meta: {
|
|
2151
3231
|
workspace: graph.workspace.workspaceId,
|
|
2152
3232
|
profile: graph.profile,
|
|
@@ -2169,7 +3249,7 @@ function normalizeEnvValue(value) {
|
|
|
2169
3249
|
}
|
|
2170
3250
|
return JSON.stringify(value);
|
|
2171
3251
|
}
|
|
2172
|
-
function toEnv(graph, manifest, options = {}) {
|
|
3252
|
+
function toEnv(graph, manifest, options = {}, helpers = {}) {
|
|
2173
3253
|
const includeSecrets = options.includeSecrets ?? true;
|
|
2174
3254
|
const output = {};
|
|
2175
3255
|
const mappedEntries = Object.entries(manifest.envMapping.explicit).sort(
|
|
@@ -2190,7 +3270,11 @@ function toEnv(graph, manifest, options = {}) {
|
|
|
2190
3270
|
if (isSecretReference(entry.value)) {
|
|
2191
3271
|
continue;
|
|
2192
3272
|
}
|
|
2193
|
-
|
|
3273
|
+
const value = helpers.read ? helpers.read(logicalKey) : entry.value;
|
|
3274
|
+
if (value === void 0) {
|
|
3275
|
+
continue;
|
|
3276
|
+
}
|
|
3277
|
+
output[envVar] = normalizeEnvValue(value);
|
|
2194
3278
|
}
|
|
2195
3279
|
return output;
|
|
2196
3280
|
}
|
|
@@ -2227,20 +3311,43 @@ function resolvePublicPrefix(manifest, options) {
|
|
|
2227
3311
|
}
|
|
2228
3312
|
return manifest.public.frameworks[options.framework] ?? "";
|
|
2229
3313
|
}
|
|
2230
|
-
function toPublicEnv(graph, manifest, options = {}) {
|
|
3314
|
+
function toPublicEnv(graph, manifest, options = {}, helpers = {}) {
|
|
2231
3315
|
const prefix = resolvePublicPrefix(manifest, options);
|
|
2232
3316
|
const output = {};
|
|
2233
3317
|
const promotions = Array.from(graph.entries.values()).filter((entry) => entry.namespace === "public").sort((left, right) => left.key.localeCompare(right.key));
|
|
2234
3318
|
for (const resolved of promotions) {
|
|
3319
|
+
if (helpers.isRuntimeDependent?.(resolved.key)) {
|
|
3320
|
+
const value2 = helpers.read?.(resolved.key);
|
|
3321
|
+
if (value2 === void 0) {
|
|
3322
|
+
throw new CnosManifestError(`Cannot build public output for ${resolved.key} because it depends on runtime-only values.`);
|
|
3323
|
+
}
|
|
3324
|
+
}
|
|
2235
3325
|
const baseEnvVar = fallbackPublicEnvVar(stripNamespace(resolved.key));
|
|
2236
3326
|
const envVar = prefix && !baseEnvVar.startsWith(prefix) ? `${prefix}${baseEnvVar}` : baseEnvVar;
|
|
2237
|
-
|
|
3327
|
+
const value = helpers.read ? helpers.read(resolved.key) : resolved.value;
|
|
3328
|
+
if (value === void 0) {
|
|
3329
|
+
continue;
|
|
3330
|
+
}
|
|
3331
|
+
output[envVar] = normalizeEnvValue2(value);
|
|
2238
3332
|
}
|
|
2239
3333
|
return output;
|
|
2240
3334
|
}
|
|
2241
3335
|
|
|
2242
3336
|
// ../core/src/orchestrator/runtime.ts
|
|
2243
3337
|
function createRuntime(manifest, graph, plugins = [], secretCache, processEnv = process.env, cnosVersion = "0.0.0-dev") {
|
|
3338
|
+
const runtimeProviders = createDefaultRuntimeProviders(manifest, processEnv);
|
|
3339
|
+
const derivedSupport = createDerivedRuntimeSupport(graph, manifest, runtimeProviders);
|
|
3340
|
+
function resolveProjectedSourceKey(key) {
|
|
3341
|
+
if (!key.startsWith("public.")) {
|
|
3342
|
+
return key;
|
|
3343
|
+
}
|
|
3344
|
+
const promotedFrom = graph.entries.get(key)?.winner.metadata?.promotedFrom;
|
|
3345
|
+
if (typeof promotedFrom === "string") {
|
|
3346
|
+
return promotedFrom;
|
|
3347
|
+
}
|
|
3348
|
+
const fallback = `value.${key.slice("public.".length)}`;
|
|
3349
|
+
return graph.entries.has(fallback) ? fallback : key;
|
|
3350
|
+
}
|
|
2244
3351
|
async function refreshSecretEntry(key) {
|
|
2245
3352
|
const entry = graph.entries.get(key);
|
|
2246
3353
|
if (!entry || entry.namespace !== "secret" || !isSecretReference(entry.value)) {
|
|
@@ -2272,6 +3379,19 @@ function createRuntime(manifest, graph, plugins = [], secretCache, processEnv =
|
|
|
2272
3379
|
}
|
|
2273
3380
|
}
|
|
2274
3381
|
function readLogicalKey2(key) {
|
|
3382
|
+
const resolved = derivedSupport.read(key, (ref) => {
|
|
3383
|
+
const entry2 = graph.entries.get(ref);
|
|
3384
|
+
if (!entry2) {
|
|
3385
|
+
return void 0;
|
|
3386
|
+
}
|
|
3387
|
+
if (!secretCache) {
|
|
3388
|
+
return entry2.value;
|
|
3389
|
+
}
|
|
3390
|
+
return resolveSecretEntryValue(ref, entry2.value, secretCache);
|
|
3391
|
+
});
|
|
3392
|
+
if (resolved !== void 0 || graph.entries.has(key) || manifest.runtimeNamespaces[key.split(".")[0] ?? ""]) {
|
|
3393
|
+
return resolved;
|
|
3394
|
+
}
|
|
2275
3395
|
const entry = graph.entries.get(key);
|
|
2276
3396
|
if (!entry) {
|
|
2277
3397
|
return void 0;
|
|
@@ -2296,34 +3416,64 @@ function createRuntime(manifest, graph, plugins = [], secretCache, processEnv =
|
|
|
2296
3416
|
return value;
|
|
2297
3417
|
},
|
|
2298
3418
|
readOr(key, fallback) {
|
|
2299
|
-
|
|
3419
|
+
const value = readLogicalKey2(key);
|
|
3420
|
+
return value === void 0 ? fallback : value;
|
|
2300
3421
|
},
|
|
2301
|
-
value(
|
|
2302
|
-
return readLogicalKey2(toLogicalKey("value",
|
|
3422
|
+
value(path17) {
|
|
3423
|
+
return readLogicalKey2(toLogicalKey("value", path17));
|
|
2303
3424
|
},
|
|
2304
|
-
secret(
|
|
2305
|
-
return readLogicalKey2(toLogicalKey("secret",
|
|
3425
|
+
secret(path17) {
|
|
3426
|
+
return readLogicalKey2(toLogicalKey("secret", path17));
|
|
2306
3427
|
},
|
|
2307
|
-
meta(
|
|
2308
|
-
return readLogicalKey2(toLogicalKey("meta",
|
|
3428
|
+
meta(path17) {
|
|
3429
|
+
return readLogicalKey2(toLogicalKey("meta", path17));
|
|
2309
3430
|
},
|
|
2310
3431
|
inspect(key) {
|
|
2311
|
-
return inspectValue(graph, key
|
|
3432
|
+
return inspectValue(graph, key, {
|
|
3433
|
+
read: (ref) => readLogicalKey2(ref),
|
|
3434
|
+
describeDerived: (ref) => derivedSupport.describe(ref, (candidate) => {
|
|
3435
|
+
const entry = graph.entries.get(candidate);
|
|
3436
|
+
if (!entry) {
|
|
3437
|
+
return void 0;
|
|
3438
|
+
}
|
|
3439
|
+
if (!secretCache) {
|
|
3440
|
+
return entry.value;
|
|
3441
|
+
}
|
|
3442
|
+
return resolveSecretEntryValue(candidate, entry.value, secretCache);
|
|
3443
|
+
})
|
|
3444
|
+
});
|
|
2312
3445
|
},
|
|
2313
3446
|
toObject() {
|
|
2314
|
-
return toNamespaceObject(graph);
|
|
3447
|
+
return toNamespaceObject(graph, void 0, (key) => readLogicalKey2(key));
|
|
2315
3448
|
},
|
|
2316
3449
|
toNamespace(namespace) {
|
|
2317
|
-
return toNamespaceObject(graph, namespace);
|
|
3450
|
+
return toNamespaceObject(graph, namespace, (key) => readLogicalKey2(key));
|
|
2318
3451
|
},
|
|
2319
3452
|
toEnv(options) {
|
|
2320
|
-
return toEnv(graph, manifest, options
|
|
3453
|
+
return toEnv(graph, manifest, options, {
|
|
3454
|
+
read: (key) => readLogicalKey2(key),
|
|
3455
|
+
isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(key)
|
|
3456
|
+
});
|
|
2321
3457
|
},
|
|
2322
3458
|
toPublicEnv(options) {
|
|
2323
|
-
return toPublicEnv(graph, manifest, options
|
|
3459
|
+
return toPublicEnv(graph, manifest, options, {
|
|
3460
|
+
read: (key) => derivedSupport.toConcreteValue(
|
|
3461
|
+
resolveProjectedSourceKey(key),
|
|
3462
|
+
(candidate) => readLogicalKey2(candidate),
|
|
3463
|
+
"public"
|
|
3464
|
+
),
|
|
3465
|
+
isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(resolveProjectedSourceKey(key))
|
|
3466
|
+
});
|
|
2324
3467
|
},
|
|
2325
3468
|
toServerProjection() {
|
|
2326
|
-
return toServerProjection(graph, manifest, cnosVersion
|
|
3469
|
+
return toServerProjection(graph, manifest, cnosVersion, {
|
|
3470
|
+
read: (key) => derivedSupport.toConcreteValue(key, (candidate) => readLogicalKey2(candidate), "server"),
|
|
3471
|
+
isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(key),
|
|
3472
|
+
toServerFormula: (key) => derivedSupport.toServerFormula(key)
|
|
3473
|
+
});
|
|
3474
|
+
},
|
|
3475
|
+
registerRuntimeProvider(namespace, provider) {
|
|
3476
|
+
registerRuntimeProvider(manifest, runtimeProviders, namespace, provider);
|
|
2327
3477
|
},
|
|
2328
3478
|
async refreshSecrets() {
|
|
2329
3479
|
await refreshAllSecrets();
|
|
@@ -2430,7 +3580,11 @@ function appendMetaEntries(graph, cnosVersion) {
|
|
|
2430
3580
|
async function createCnos(options = {}) {
|
|
2431
3581
|
const loadedManifest = await loadManifest({
|
|
2432
3582
|
...options.root ? { root: options.root } : {},
|
|
2433
|
-
...options.cwd ? { cwd: options.cwd } : {}
|
|
3583
|
+
...options.cwd ? { cwd: options.cwd } : {},
|
|
3584
|
+
...options.processEnv ? { processEnv: options.processEnv } : {},
|
|
3585
|
+
...options.cacheMode ? { cacheMode: options.cacheMode } : {},
|
|
3586
|
+
...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
|
|
3587
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
2434
3588
|
});
|
|
2435
3589
|
for (const key of loadedManifest.manifest.public.promote) {
|
|
2436
3590
|
ensureProjectionAllowed(loadedManifest.manifest, key, "public");
|
|
@@ -2491,8 +3645,8 @@ async function createCnos(options = {}) {
|
|
|
2491
3645
|
}
|
|
2492
3646
|
|
|
2493
3647
|
// ../core/src/runtime/dump.ts
|
|
2494
|
-
var
|
|
2495
|
-
var
|
|
3648
|
+
var import_promises12 = require("fs/promises");
|
|
3649
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
2496
3650
|
|
|
2497
3651
|
// ../core/src/utils/envNaming.ts
|
|
2498
3652
|
function normalizeMappingConfig(config = {}) {
|
|
@@ -2501,8 +3655,8 @@ function normalizeMappingConfig(config = {}) {
|
|
|
2501
3655
|
explicit: config.explicit ?? {}
|
|
2502
3656
|
};
|
|
2503
3657
|
}
|
|
2504
|
-
function fromScreamingSnake(
|
|
2505
|
-
return
|
|
3658
|
+
function fromScreamingSnake(path17) {
|
|
3659
|
+
return path17.split("_").map((segment) => segment.trim().toLowerCase()).filter(Boolean).join(".");
|
|
2506
3660
|
}
|
|
2507
3661
|
function envVarToLogicalKey(envVar, config = {}) {
|
|
2508
3662
|
const normalized = normalizeMappingConfig(config);
|
|
@@ -2529,7 +3683,7 @@ function envVarToLogicalKey(envVar, config = {}) {
|
|
|
2529
3683
|
// package.json
|
|
2530
3684
|
var package_default = {
|
|
2531
3685
|
name: "@kitsy/cnos",
|
|
2532
|
-
version: "1.
|
|
3686
|
+
version: "1.7.0",
|
|
2533
3687
|
description: "Batteries-included CNOS runtime package wired with the official plugins.",
|
|
2534
3688
|
type: "module",
|
|
2535
3689
|
main: "./dist/index.cjs",
|
|
@@ -2728,8 +3882,8 @@ function createCliArgsPlugin() {
|
|
|
2728
3882
|
}
|
|
2729
3883
|
|
|
2730
3884
|
// ../../plugins/dotenv/src/index.ts
|
|
2731
|
-
var
|
|
2732
|
-
var
|
|
3885
|
+
var import_promises13 = require("fs/promises");
|
|
3886
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
2733
3887
|
var DOTENV_PLUGIN_ID = "@kitsy/cnos/plugins/dotenv";
|
|
2734
3888
|
function parseDoubleQuoted(value) {
|
|
2735
3889
|
return value.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
@@ -2786,7 +3940,7 @@ function dotenvEntriesFromObject(values, mapping = {}, originFile, workspaceId =
|
|
|
2786
3940
|
}
|
|
2787
3941
|
async function readIfPresent(filePath) {
|
|
2788
3942
|
try {
|
|
2789
|
-
return await (0,
|
|
3943
|
+
return await (0, import_promises13.readFile)(filePath, "utf8");
|
|
2790
3944
|
} catch {
|
|
2791
3945
|
return void 0;
|
|
2792
3946
|
}
|
|
@@ -2805,7 +3959,7 @@ function createDotenvPlugin() {
|
|
|
2805
3959
|
workspace: workspaceRoot.workspaceId
|
|
2806
3960
|
});
|
|
2807
3961
|
for (const fileName of fileNames) {
|
|
2808
|
-
const absolutePath =
|
|
3962
|
+
const absolutePath = import_node_path14.default.join(envRoot, fileName);
|
|
2809
3963
|
const document = await readIfPresent(absolutePath);
|
|
2810
3964
|
if (!document) {
|
|
2811
3965
|
continue;
|
|
@@ -2814,7 +3968,7 @@ function createDotenvPlugin() {
|
|
|
2814
3968
|
...dotenvEntriesFromObject(
|
|
2815
3969
|
parseDotenv(document),
|
|
2816
3970
|
config.envMapping,
|
|
2817
|
-
toPortablePath(
|
|
3971
|
+
toPortablePath(import_node_path14.default.relative(import_node_path14.default.dirname(context.manifestRoot), absolutePath)),
|
|
2818
3972
|
workspaceRoot.workspaceId
|
|
2819
3973
|
)
|
|
2820
3974
|
);
|
|
@@ -2852,16 +4006,16 @@ function createPublicEnvExportPlugin() {
|
|
|
2852
4006
|
}
|
|
2853
4007
|
|
|
2854
4008
|
// ../../plugins/filesystem/src/filesystemSecretsReader.ts
|
|
2855
|
-
var
|
|
4009
|
+
var import_promises15 = require("fs/promises");
|
|
2856
4010
|
|
|
2857
4011
|
// ../../plugins/filesystem/src/helpers.ts
|
|
2858
|
-
var
|
|
2859
|
-
var
|
|
4012
|
+
var import_promises14 = require("fs/promises");
|
|
4013
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
2860
4014
|
var YAML_EXTENSIONS = /* @__PURE__ */ new Set([".yml", ".yaml"]);
|
|
2861
4015
|
var FILESYSTEM_PLUGIN_ID = "@kitsy/cnos/plugins/filesystem";
|
|
2862
4016
|
async function existsDirectory(targetPath) {
|
|
2863
4017
|
try {
|
|
2864
|
-
const stat2 = await (0,
|
|
4018
|
+
const stat2 = await (0, import_promises14.readdir)(targetPath);
|
|
2865
4019
|
void stat2;
|
|
2866
4020
|
return true;
|
|
2867
4021
|
} catch {
|
|
@@ -2869,15 +4023,15 @@ async function existsDirectory(targetPath) {
|
|
|
2869
4023
|
}
|
|
2870
4024
|
}
|
|
2871
4025
|
async function collectYamlFiles(root) {
|
|
2872
|
-
const entries = await (0,
|
|
4026
|
+
const entries = await (0, import_promises14.readdir)(root, { withFileTypes: true });
|
|
2873
4027
|
const results = [];
|
|
2874
4028
|
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
2875
|
-
const absolutePath =
|
|
4029
|
+
const absolutePath = import_node_path15.default.join(root, entry.name);
|
|
2876
4030
|
if (entry.isDirectory()) {
|
|
2877
4031
|
results.push(...await collectYamlFiles(absolutePath));
|
|
2878
4032
|
continue;
|
|
2879
4033
|
}
|
|
2880
|
-
if (entry.isFile() && YAML_EXTENSIONS.has(
|
|
4034
|
+
if (entry.isFile() && YAML_EXTENSIONS.has(import_node_path15.default.extname(entry.name).toLowerCase())) {
|
|
2881
4035
|
results.push(absolutePath);
|
|
2882
4036
|
}
|
|
2883
4037
|
}
|
|
@@ -2885,16 +4039,16 @@ async function collectYamlFiles(root) {
|
|
|
2885
4039
|
}
|
|
2886
4040
|
async function collectFilesystemLayerFiles(manifestRoot, workspaceRoots, sourceRoot, activeLayers) {
|
|
2887
4041
|
const files = [];
|
|
2888
|
-
const repoRoot =
|
|
4042
|
+
const repoRoot = import_node_path15.default.dirname(manifestRoot);
|
|
2889
4043
|
for (const workspaceRoot of workspaceRoots) {
|
|
2890
|
-
const resolvedRoot =
|
|
4044
|
+
const resolvedRoot = import_node_path15.default.resolve(workspaceRoot.path, sourceRoot);
|
|
2891
4045
|
for (const layer of activeLayers) {
|
|
2892
|
-
const layerRoot =
|
|
4046
|
+
const layerRoot = import_node_path15.default.join(resolvedRoot, layer);
|
|
2893
4047
|
if (!await existsDirectory(layerRoot)) {
|
|
2894
4048
|
continue;
|
|
2895
4049
|
}
|
|
2896
4050
|
for (const absolutePath of await collectYamlFiles(layerRoot)) {
|
|
2897
|
-
const relativePath =
|
|
4051
|
+
const relativePath = import_node_path15.default.relative(repoRoot, absolutePath);
|
|
2898
4052
|
files.push({
|
|
2899
4053
|
absolutePath,
|
|
2900
4054
|
relativePath: toPortablePath(relativePath.startsWith("..") ? absolutePath : relativePath),
|
|
@@ -2914,7 +4068,7 @@ function assertObjectDocument(value, filePath) {
|
|
|
2914
4068
|
function flattenConfigObject(value, options = {}, prefix = "") {
|
|
2915
4069
|
return Object.entries(value).reduce((accumulator, [key, nestedValue]) => {
|
|
2916
4070
|
const nextKey = prefix ? `${prefix}.${key}` : key;
|
|
2917
|
-
if (nestedValue && typeof nestedValue === "object" && !Array.isArray(nestedValue) && !options.stopAtLeaf?.(nestedValue)) {
|
|
4071
|
+
if (nestedValue && typeof nestedValue === "object" && !Array.isArray(nestedValue) && !isDerivedValue(nestedValue) && !options.stopAtLeaf?.(nestedValue)) {
|
|
2918
4072
|
Object.assign(
|
|
2919
4073
|
accumulator,
|
|
2920
4074
|
flattenConfigObject(nestedValue, options, nextKey)
|
|
@@ -2971,7 +4125,7 @@ function createFilesystemSecretsPlugin() {
|
|
|
2971
4125
|
);
|
|
2972
4126
|
const entries = [];
|
|
2973
4127
|
for (const file of files) {
|
|
2974
|
-
const document = await (0,
|
|
4128
|
+
const document = await (0, import_promises15.readFile)(file.absolutePath, "utf8");
|
|
2975
4129
|
const fileEntries = filesystemSecretsReader(file.relativePath, document, file.workspaceId);
|
|
2976
4130
|
for (const entry of fileEntries) {
|
|
2977
4131
|
const metadata = toSecretReferenceMetadata(entry.value);
|
|
@@ -2987,7 +4141,7 @@ function createFilesystemSecretsPlugin() {
|
|
|
2987
4141
|
}
|
|
2988
4142
|
|
|
2989
4143
|
// ../../plugins/filesystem/src/filesystemValuesReader.ts
|
|
2990
|
-
var
|
|
4144
|
+
var import_promises16 = require("fs/promises");
|
|
2991
4145
|
function filesystemValuesReader(filePath, document, workspaceId = "default") {
|
|
2992
4146
|
return yamlObjectToEntries(document, filePath, "value", "filesystem-values", workspaceId);
|
|
2993
4147
|
}
|
|
@@ -3008,7 +4162,7 @@ function createFilesystemValuesPlugin() {
|
|
|
3008
4162
|
).map(([namespace]) => namespace);
|
|
3009
4163
|
const entries = [];
|
|
3010
4164
|
for (const file of files) {
|
|
3011
|
-
const document = await (0,
|
|
4165
|
+
const document = await (0, import_promises16.readFile)(file.absolutePath, "utf8");
|
|
3012
4166
|
entries.push(...filesystemValuesReader(file.relativePath, document, file.workspaceId));
|
|
3013
4167
|
}
|
|
3014
4168
|
for (const namespace of customNamespaces) {
|
|
@@ -3023,7 +4177,7 @@ function createFilesystemValuesPlugin() {
|
|
|
3023
4177
|
layers
|
|
3024
4178
|
);
|
|
3025
4179
|
for (const file of namespaceFiles) {
|
|
3026
|
-
const document = await (0,
|
|
4180
|
+
const document = await (0, import_promises16.readFile)(file.absolutePath, "utf8");
|
|
3027
4181
|
entries.push(...yamlObjectToEntries(document, file.relativePath, namespace, "filesystem-values", file.workspaceId));
|
|
3028
4182
|
}
|
|
3029
4183
|
}
|
|
@@ -3193,7 +4347,7 @@ async function createCnos2(options = {}) {
|
|
|
3193
4347
|
}
|
|
3194
4348
|
|
|
3195
4349
|
// src/runtime/bootstrap.ts
|
|
3196
|
-
var
|
|
4350
|
+
var import_node_crypto4 = require("crypto");
|
|
3197
4351
|
var CNOS_GRAPH_ENV_VAR = "__CNOS_GRAPH__";
|
|
3198
4352
|
var CNOS_PROJECTION_ENV_VAR = "__CNOS_PROJECTION__";
|
|
3199
4353
|
var CNOS_SECRET_PAYLOAD_ENV_VAR = "__CNOS_SECRET_PAYLOAD__";
|
|
@@ -3203,7 +4357,11 @@ function deserializeServerProjection(source) {
|
|
|
3203
4357
|
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") {
|
|
3204
4358
|
throw new Error("Invalid CNOS server projection payload");
|
|
3205
4359
|
}
|
|
3206
|
-
return
|
|
4360
|
+
return {
|
|
4361
|
+
...payload,
|
|
4362
|
+
derived: payload.derived && typeof payload.derived === "object" && !Array.isArray(payload.derived) ? payload.derived : {},
|
|
4363
|
+
runtimeNamespaces: Array.isArray(payload.runtimeNamespaces) ? payload.runtimeNamespaces : []
|
|
4364
|
+
};
|
|
3207
4365
|
}
|
|
3208
4366
|
function deserializeRuntimeGraph(source) {
|
|
3209
4367
|
const payload = JSON.parse(source);
|
|
@@ -3238,7 +4396,7 @@ function decryptSecretPayload(serialized, sessionKey) {
|
|
|
3238
4396
|
const iv = Buffer.from(payload.iv, "base64");
|
|
3239
4397
|
const tag = Buffer.from(payload.tag, "base64");
|
|
3240
4398
|
const ciphertext = Buffer.from(payload.ciphertext, "base64");
|
|
3241
|
-
const decipher = (0,
|
|
4399
|
+
const decipher = (0, import_node_crypto4.createDecipheriv)("aes-256-gcm", key, iv);
|
|
3242
4400
|
decipher.setAuthTag(tag);
|
|
3243
4401
|
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
3244
4402
|
return JSON.parse(plaintext);
|
|
@@ -3313,6 +4471,27 @@ function formatMessage(runtime, message) {
|
|
|
3313
4471
|
return value === void 0 ? match : stringifyLogValue(value);
|
|
3314
4472
|
});
|
|
3315
4473
|
}
|
|
4474
|
+
function discoverRuntimeNamespacesFromGraph(graph) {
|
|
4475
|
+
const configNamespaces = /* @__PURE__ */ new Set(["value", "secret", "meta", "public"]);
|
|
4476
|
+
for (const entry of graph.entries.values()) {
|
|
4477
|
+
configNamespaces.add(entry.namespace);
|
|
4478
|
+
}
|
|
4479
|
+
const runtimeNamespaces = /* @__PURE__ */ new Set();
|
|
4480
|
+
for (const entry of graph.entries.values()) {
|
|
4481
|
+
if (!isDerivedValue(entry.value)) {
|
|
4482
|
+
continue;
|
|
4483
|
+
}
|
|
4484
|
+
const parsed = parseDerivation(entry.value);
|
|
4485
|
+
for (const ref of parsed.refs) {
|
|
4486
|
+
const namespace = ref.split(".")[0] ?? "";
|
|
4487
|
+
if (!namespace || configNamespaces.has(namespace)) {
|
|
4488
|
+
continue;
|
|
4489
|
+
}
|
|
4490
|
+
runtimeNamespaces.add(namespace);
|
|
4491
|
+
}
|
|
4492
|
+
}
|
|
4493
|
+
return Array.from(runtimeNamespaces).sort((left, right) => left.localeCompare(right));
|
|
4494
|
+
}
|
|
3316
4495
|
function attachBootstrappedGraph(graph) {
|
|
3317
4496
|
if (getSingletonRuntime()) {
|
|
3318
4497
|
return;
|
|
@@ -3359,6 +4538,21 @@ function attachBootstrappedGraph(graph) {
|
|
|
3359
4538
|
frameworks: {}
|
|
3360
4539
|
},
|
|
3361
4540
|
namespaces: {},
|
|
4541
|
+
runtimeNamespaces: {
|
|
4542
|
+
process: {
|
|
4543
|
+
description: "Live process runtime values.",
|
|
4544
|
+
serverOnly: true,
|
|
4545
|
+
builtIn: true
|
|
4546
|
+
},
|
|
4547
|
+
...Object.fromEntries(
|
|
4548
|
+
discoverRuntimeNamespacesFromGraph(graph).map((namespace) => [
|
|
4549
|
+
namespace,
|
|
4550
|
+
{
|
|
4551
|
+
serverOnly: true
|
|
4552
|
+
}
|
|
4553
|
+
])
|
|
4554
|
+
)
|
|
4555
|
+
},
|
|
3362
4556
|
vaults: {},
|
|
3363
4557
|
writePolicy: {
|
|
3364
4558
|
define: {
|
|
@@ -3371,46 +4565,76 @@ function attachBootstrappedGraph(graph) {
|
|
|
3371
4565
|
},
|
|
3372
4566
|
schema: {}
|
|
3373
4567
|
};
|
|
4568
|
+
const runtimeProviders = createDefaultRuntimeProviders(bootstrappedManifest, process.env);
|
|
4569
|
+
const derivedSupport = createDerivedRuntimeSupport(graph, bootstrappedManifest, runtimeProviders);
|
|
4570
|
+
const resolveProjectedSourceKey = (key) => {
|
|
4571
|
+
if (!key.startsWith("public.")) {
|
|
4572
|
+
return key;
|
|
4573
|
+
}
|
|
4574
|
+
const promotedFrom = graph.entries.get(key)?.winner.metadata?.promotedFrom;
|
|
4575
|
+
if (typeof promotedFrom === "string") {
|
|
4576
|
+
return promotedFrom;
|
|
4577
|
+
}
|
|
4578
|
+
const fallback = `value.${key.slice("public.".length)}`;
|
|
4579
|
+
return graph.entries.has(fallback) ? fallback : key;
|
|
4580
|
+
};
|
|
3374
4581
|
const runtime = {
|
|
3375
4582
|
manifest: bootstrappedManifest,
|
|
3376
4583
|
plugins: [],
|
|
3377
4584
|
graph,
|
|
3378
4585
|
read(key) {
|
|
3379
|
-
return readValue(graph,
|
|
4586
|
+
return derivedSupport.read(key, (ref) => readValue(graph, ref));
|
|
3380
4587
|
},
|
|
3381
4588
|
require(key) {
|
|
3382
|
-
|
|
4589
|
+
const value = this.read(key);
|
|
4590
|
+
if (value === void 0) {
|
|
4591
|
+
return requireValue(graph, key);
|
|
4592
|
+
}
|
|
4593
|
+
return value;
|
|
3383
4594
|
},
|
|
3384
4595
|
readOr(key, fallback) {
|
|
3385
|
-
|
|
4596
|
+
const value = this.read(key);
|
|
4597
|
+
return value === void 0 ? fallback : value;
|
|
3386
4598
|
},
|
|
3387
|
-
value(
|
|
3388
|
-
return readValue(graph, toLogicalKey("value",
|
|
4599
|
+
value(path17) {
|
|
4600
|
+
return readValue(graph, toLogicalKey("value", path17));
|
|
3389
4601
|
},
|
|
3390
|
-
secret(
|
|
3391
|
-
return readValue(graph, toLogicalKey("secret",
|
|
4602
|
+
secret(path17) {
|
|
4603
|
+
return readValue(graph, toLogicalKey("secret", path17));
|
|
3392
4604
|
},
|
|
3393
|
-
meta(
|
|
3394
|
-
return readValue(graph, toLogicalKey("meta",
|
|
4605
|
+
meta(path17) {
|
|
4606
|
+
return readValue(graph, toLogicalKey("meta", path17));
|
|
3395
4607
|
},
|
|
3396
4608
|
toNamespace(namespace) {
|
|
3397
|
-
return toNamespaceObject(graph, namespace);
|
|
4609
|
+
return toNamespaceObject(graph, namespace, (key) => this.read(key));
|
|
3398
4610
|
},
|
|
3399
4611
|
toEnv(options) {
|
|
3400
|
-
return toEnv(graph, bootstrappedManifest, options
|
|
4612
|
+
return toEnv(graph, bootstrappedManifest, options, {
|
|
4613
|
+
read: (key) => this.read(key),
|
|
4614
|
+
isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(key)
|
|
4615
|
+
});
|
|
3401
4616
|
},
|
|
3402
4617
|
toPublicEnv(options) {
|
|
3403
|
-
return toPublicEnv(graph, bootstrappedManifest, options
|
|
4618
|
+
return toPublicEnv(graph, bootstrappedManifest, options, {
|
|
4619
|
+
read: (key) => derivedSupport.toConcreteValue(resolveProjectedSourceKey(key), (ref) => readValue(graph, ref), "public"),
|
|
4620
|
+
isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(resolveProjectedSourceKey(key))
|
|
4621
|
+
});
|
|
3404
4622
|
},
|
|
3405
4623
|
inspect(key) {
|
|
3406
|
-
return inspectValue(graph, key
|
|
4624
|
+
return inspectValue(graph, key, {
|
|
4625
|
+
read: (ref) => this.read(ref),
|
|
4626
|
+
describeDerived: (ref) => derivedSupport.describe(ref, (candidate) => readValue(graph, candidate))
|
|
4627
|
+
});
|
|
3407
4628
|
},
|
|
3408
4629
|
toObject() {
|
|
3409
|
-
return toNamespaceObject(graph);
|
|
4630
|
+
return toNamespaceObject(graph, void 0, (key) => this.read(key));
|
|
3410
4631
|
},
|
|
3411
4632
|
toServerProjection() {
|
|
3412
4633
|
throw new Error("CNOS graph bootstrap payload does not support server projection export.");
|
|
3413
4634
|
},
|
|
4635
|
+
registerRuntimeProvider(namespace, provider) {
|
|
4636
|
+
registerRuntimeProvider(bootstrappedManifest, runtimeProviders, namespace, provider);
|
|
4637
|
+
},
|
|
3414
4638
|
async refreshSecrets() {
|
|
3415
4639
|
return;
|
|
3416
4640
|
},
|
|
@@ -3421,7 +4645,7 @@ function attachBootstrappedGraph(graph) {
|
|
|
3421
4645
|
setSingletonRuntime(runtime);
|
|
3422
4646
|
setBootstrappedSecretHydrationRequired(graphRequiresSecretHydration(graph));
|
|
3423
4647
|
}
|
|
3424
|
-
function toBootstrappedManifest(graph) {
|
|
4648
|
+
function toBootstrappedManifest(graph, runtimeNamespaces = []) {
|
|
3425
4649
|
return {
|
|
3426
4650
|
version: 1,
|
|
3427
4651
|
project: {
|
|
@@ -3464,8 +4688,24 @@ function toBootstrappedManifest(graph) {
|
|
|
3464
4688
|
value: { kind: "data", shareable: true },
|
|
3465
4689
|
secret: { kind: "data", shareable: false, sensitive: true },
|
|
3466
4690
|
meta: { kind: "system", shareable: false, readonly: true },
|
|
4691
|
+
process: { kind: "system", shareable: false, readonly: true },
|
|
3467
4692
|
public: { kind: "projection", shareable: true, readonly: true, source: "promote" }
|
|
3468
4693
|
},
|
|
4694
|
+
runtimeNamespaces: {
|
|
4695
|
+
process: {
|
|
4696
|
+
description: "Live process runtime values.",
|
|
4697
|
+
serverOnly: true,
|
|
4698
|
+
builtIn: true
|
|
4699
|
+
},
|
|
4700
|
+
...Object.fromEntries(
|
|
4701
|
+
runtimeNamespaces.filter((namespace) => namespace !== "process").map((namespace) => [
|
|
4702
|
+
namespace,
|
|
4703
|
+
{
|
|
4704
|
+
serverOnly: true
|
|
4705
|
+
}
|
|
4706
|
+
])
|
|
4707
|
+
)
|
|
4708
|
+
},
|
|
3469
4709
|
vaults: {},
|
|
3470
4710
|
writePolicy: {
|
|
3471
4711
|
define: {
|
|
@@ -3504,6 +4744,31 @@ function graphFromProjection(projection) {
|
|
|
3504
4744
|
overridden: []
|
|
3505
4745
|
});
|
|
3506
4746
|
}
|
|
4747
|
+
for (const [key, formula] of Object.entries(projection.derived)) {
|
|
4748
|
+
const firstSegment = key.split(".")[0] ?? "";
|
|
4749
|
+
const logicalKey = key.startsWith("value.") || key.startsWith("public.") || explicitNamespaces.has(firstSegment) ? key : `value.${key}`;
|
|
4750
|
+
const namespace = logicalKey.slice(0, logicalKey.indexOf("."));
|
|
4751
|
+
const winner = {
|
|
4752
|
+
key: logicalKey,
|
|
4753
|
+
value: {
|
|
4754
|
+
$derive: {
|
|
4755
|
+
expr: formula.expr
|
|
4756
|
+
}
|
|
4757
|
+
},
|
|
4758
|
+
namespace,
|
|
4759
|
+
sourceId: "server-projection",
|
|
4760
|
+
pluginId: "cnos",
|
|
4761
|
+
workspaceId: projection.workspace,
|
|
4762
|
+
profile: projection.profile
|
|
4763
|
+
};
|
|
4764
|
+
entries.set(logicalKey, {
|
|
4765
|
+
key: logicalKey,
|
|
4766
|
+
value: winner.value,
|
|
4767
|
+
namespace,
|
|
4768
|
+
winner,
|
|
4769
|
+
overridden: []
|
|
4770
|
+
});
|
|
4771
|
+
}
|
|
3507
4772
|
for (const [key, ref] of Object.entries(projection.secretRefs)) {
|
|
3508
4773
|
const logicalKey = `secret.${key}`;
|
|
3509
4774
|
entries.set(logicalKey, {
|
|
@@ -3540,7 +4805,10 @@ function graphFromProjection(projection) {
|
|
|
3540
4805
|
sourceId: "server-projection",
|
|
3541
4806
|
pluginId: "cnos",
|
|
3542
4807
|
workspaceId: projection.workspace,
|
|
3543
|
-
profile: projection.profile
|
|
4808
|
+
profile: projection.profile,
|
|
4809
|
+
metadata: {
|
|
4810
|
+
promotedFrom: valueKey
|
|
4811
|
+
}
|
|
3544
4812
|
},
|
|
3545
4813
|
overridden: []
|
|
3546
4814
|
});
|
|
@@ -3578,8 +4846,21 @@ function attachBootstrappedProjection(projection, force = false) {
|
|
|
3578
4846
|
return;
|
|
3579
4847
|
}
|
|
3580
4848
|
const graph = graphFromProjection(projection);
|
|
3581
|
-
const manifest = toBootstrappedManifest(graph);
|
|
4849
|
+
const manifest = toBootstrappedManifest(graph, projection.runtimeNamespaces);
|
|
3582
4850
|
const hydratedSecrets = /* @__PURE__ */ new Map();
|
|
4851
|
+
const runtimeProviders = createDefaultRuntimeProviders(manifest, process.env);
|
|
4852
|
+
const derivedSupport = createDerivedRuntimeSupport(graph, manifest, runtimeProviders);
|
|
4853
|
+
const resolveProjectedSourceKey = (key) => {
|
|
4854
|
+
if (!key.startsWith("public.")) {
|
|
4855
|
+
return key;
|
|
4856
|
+
}
|
|
4857
|
+
const promotedFrom = graph.entries.get(key)?.winner.metadata?.promotedFrom;
|
|
4858
|
+
if (typeof promotedFrom === "string") {
|
|
4859
|
+
return promotedFrom;
|
|
4860
|
+
}
|
|
4861
|
+
const fallback = `value.${key.slice("public.".length)}`;
|
|
4862
|
+
return graph.entries.has(fallback) ? fallback : key;
|
|
4863
|
+
};
|
|
3583
4864
|
const resolveSecretValue = async (key) => {
|
|
3584
4865
|
const entry = graph.entries.get(key);
|
|
3585
4866
|
if (!entry || entry.namespace !== "secret") {
|
|
@@ -3605,14 +4886,16 @@ function attachBootstrappedProjection(projection, force = false) {
|
|
|
3605
4886
|
plugins: [],
|
|
3606
4887
|
graph,
|
|
3607
4888
|
read(key) {
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
4889
|
+
return derivedSupport.read(key, (ref) => {
|
|
4890
|
+
const entry = graph.entries.get(ref);
|
|
4891
|
+
if (!entry) {
|
|
4892
|
+
return void 0;
|
|
4893
|
+
}
|
|
4894
|
+
if (entry.namespace === "secret") {
|
|
4895
|
+
return hydratedSecrets.get(ref);
|
|
4896
|
+
}
|
|
4897
|
+
return entry.value;
|
|
4898
|
+
});
|
|
3616
4899
|
},
|
|
3617
4900
|
require(key) {
|
|
3618
4901
|
const value = this.read(key);
|
|
@@ -3644,24 +4927,59 @@ function attachBootstrappedProjection(projection, force = false) {
|
|
|
3644
4927
|
])
|
|
3645
4928
|
)
|
|
3646
4929
|
},
|
|
3647
|
-
key
|
|
4930
|
+
key,
|
|
4931
|
+
{
|
|
4932
|
+
read: (ref) => this.read(ref),
|
|
4933
|
+
describeDerived: (ref) => derivedSupport.describe(ref, (candidate) => {
|
|
4934
|
+
const entry = graph.entries.get(candidate);
|
|
4935
|
+
if (!entry) {
|
|
4936
|
+
return void 0;
|
|
4937
|
+
}
|
|
4938
|
+
if (entry.namespace === "secret") {
|
|
4939
|
+
return hydratedSecrets.get(candidate);
|
|
4940
|
+
}
|
|
4941
|
+
return entry.value;
|
|
4942
|
+
})
|
|
4943
|
+
}
|
|
3648
4944
|
);
|
|
3649
4945
|
},
|
|
3650
4946
|
toObject() {
|
|
3651
|
-
return toNamespaceObject(graph);
|
|
4947
|
+
return toNamespaceObject(graph, void 0, (key) => this.read(key));
|
|
3652
4948
|
},
|
|
3653
4949
|
toNamespace(namespace) {
|
|
3654
|
-
return toNamespaceObject(graph, namespace);
|
|
4950
|
+
return toNamespaceObject(graph, namespace, (key) => this.read(key));
|
|
3655
4951
|
},
|
|
3656
4952
|
toEnv(options) {
|
|
3657
|
-
return toEnv(graph, manifest, options
|
|
4953
|
+
return toEnv(graph, manifest, options, {
|
|
4954
|
+
read: (key) => this.read(key),
|
|
4955
|
+
isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(key)
|
|
4956
|
+
});
|
|
3658
4957
|
},
|
|
3659
4958
|
toPublicEnv(options) {
|
|
3660
|
-
return toPublicEnv(graph, manifest, options
|
|
4959
|
+
return toPublicEnv(graph, manifest, options, {
|
|
4960
|
+
read: (key) => derivedSupport.toConcreteValue(
|
|
4961
|
+
resolveProjectedSourceKey(key),
|
|
4962
|
+
(ref) => {
|
|
4963
|
+
const entry = graph.entries.get(ref);
|
|
4964
|
+
if (!entry) {
|
|
4965
|
+
return void 0;
|
|
4966
|
+
}
|
|
4967
|
+
if (entry.namespace === "secret") {
|
|
4968
|
+
return hydratedSecrets.get(ref);
|
|
4969
|
+
}
|
|
4970
|
+
return entry.value;
|
|
4971
|
+
},
|
|
4972
|
+
"public"
|
|
4973
|
+
),
|
|
4974
|
+
isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(resolveProjectedSourceKey(key))
|
|
4975
|
+
});
|
|
3661
4976
|
},
|
|
3662
4977
|
toServerProjection() {
|
|
3663
4978
|
return projection;
|
|
3664
4979
|
},
|
|
4980
|
+
registerRuntimeProvider(namespace, provider) {
|
|
4981
|
+
registerRuntimeProvider(manifest, runtimeProviders, namespace, provider);
|
|
4982
|
+
},
|
|
3665
4983
|
async refreshSecrets() {
|
|
3666
4984
|
for (const key of Object.keys(projection.secretRefs).map((segment) => `secret.${segment}`)) {
|
|
3667
4985
|
hydratedSecrets.delete(key);
|
|
@@ -3696,7 +5014,7 @@ function bootstrapFromProcessEnv() {
|
|
|
3696
5014
|
function discoverProjectionPathSync() {
|
|
3697
5015
|
const cwd = process.cwd();
|
|
3698
5016
|
const directCandidates = [
|
|
3699
|
-
|
|
5017
|
+
import_node_path16.default.join(cwd, ".cnos-server.json")
|
|
3700
5018
|
];
|
|
3701
5019
|
for (const candidate of directCandidates) {
|
|
3702
5020
|
if ((0, import_node_fs.existsSync)(candidate)) {
|
|
@@ -3705,14 +5023,14 @@ function discoverProjectionPathSync() {
|
|
|
3705
5023
|
}
|
|
3706
5024
|
let current = cwd;
|
|
3707
5025
|
for (let depth = 0; depth <= 3; depth += 1) {
|
|
3708
|
-
const rcCandidate =
|
|
5026
|
+
const rcCandidate = import_node_path16.default.join(current, ".cnosrc.yml");
|
|
3709
5027
|
if ((0, import_node_fs.existsSync)(rcCandidate)) {
|
|
3710
|
-
const projectionCandidate =
|
|
5028
|
+
const projectionCandidate = import_node_path16.default.join(current, ".cnos-server.json");
|
|
3711
5029
|
if ((0, import_node_fs.existsSync)(projectionCandidate)) {
|
|
3712
5030
|
return projectionCandidate;
|
|
3713
5031
|
}
|
|
3714
5032
|
}
|
|
3715
|
-
const parent =
|
|
5033
|
+
const parent = import_node_path16.default.dirname(current);
|
|
3716
5034
|
if (parent === current) {
|
|
3717
5035
|
break;
|
|
3718
5036
|
}
|
|
@@ -3748,14 +5066,14 @@ var cnos = Object.assign(
|
|
|
3748
5066
|
readOr(key, fallback) {
|
|
3749
5067
|
return getRuntimeOrThrow().readOr(key, fallback);
|
|
3750
5068
|
},
|
|
3751
|
-
value(
|
|
3752
|
-
return getRuntimeOrThrow().value(
|
|
5069
|
+
value(path17) {
|
|
5070
|
+
return getRuntimeOrThrow().value(path17);
|
|
3753
5071
|
},
|
|
3754
|
-
secret(
|
|
3755
|
-
return getRuntimeOrThrow().secret(
|
|
5072
|
+
secret(path17) {
|
|
5073
|
+
return getRuntimeOrThrow().secret(path17);
|
|
3756
5074
|
},
|
|
3757
|
-
meta(
|
|
3758
|
-
return getRuntimeOrThrow().meta(
|
|
5075
|
+
meta(path17) {
|
|
5076
|
+
return getRuntimeOrThrow().meta(path17);
|
|
3759
5077
|
},
|
|
3760
5078
|
inspect(key) {
|
|
3761
5079
|
return getRuntimeOrThrow().inspect(key);
|
|
@@ -3778,11 +5096,14 @@ var cnos = Object.assign(
|
|
|
3778
5096
|
return formatted;
|
|
3779
5097
|
},
|
|
3780
5098
|
async loadProjection(source) {
|
|
3781
|
-
const resolvedSource =
|
|
5099
|
+
const resolvedSource = import_node_path16.default.resolve(source);
|
|
3782
5100
|
const projection = deserializeServerProjection((0, import_node_fs.readFileSync)(resolvedSource, "utf8"));
|
|
3783
5101
|
attachBootstrappedProjection(projection, true);
|
|
3784
5102
|
setBootstrappedSecretHydrationRequired(Object.keys(projection.secretRefs).length > 0);
|
|
3785
5103
|
},
|
|
5104
|
+
registerRuntimeProvider(namespace, provider) {
|
|
5105
|
+
getRuntimeOrThrow().registerRuntimeProvider(namespace, provider);
|
|
5106
|
+
},
|
|
3786
5107
|
async refreshSecrets() {
|
|
3787
5108
|
await getRuntimeOrThrow().refreshSecrets();
|
|
3788
5109
|
setBootstrappedSecretHydrationRequired(false);
|