@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/build/index.cjs
CHANGED
|
@@ -73,16 +73,673 @@ var CnosKeyNotFoundError = class extends CnosError {
|
|
|
73
73
|
}
|
|
74
74
|
key;
|
|
75
75
|
};
|
|
76
|
+
var CnosDerivedExpressionError = class extends CnosError {
|
|
77
|
+
constructor(message, expression) {
|
|
78
|
+
super(expression ? `${message} (${expression})` : message);
|
|
79
|
+
this.expression = expression;
|
|
80
|
+
}
|
|
81
|
+
expression;
|
|
82
|
+
};
|
|
83
|
+
var CnosDerivedCycleError = class extends CnosError {
|
|
84
|
+
constructor(message) {
|
|
85
|
+
super(message);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
var CnosDerivedResolutionError = class extends CnosError {
|
|
89
|
+
constructor(key, message) {
|
|
90
|
+
super(message);
|
|
91
|
+
this.key = key;
|
|
92
|
+
}
|
|
93
|
+
key;
|
|
94
|
+
};
|
|
95
|
+
var CnosRuntimeProviderError = class extends CnosError {
|
|
96
|
+
constructor(message) {
|
|
97
|
+
super(message);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// ../core/src/derive/builtins.ts
|
|
102
|
+
function stringify(value) {
|
|
103
|
+
if (value === void 0 || value === null) {
|
|
104
|
+
return "";
|
|
105
|
+
}
|
|
106
|
+
if (typeof value === "string") {
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
109
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
110
|
+
return String(value);
|
|
111
|
+
}
|
|
112
|
+
return JSON.stringify(value);
|
|
113
|
+
}
|
|
114
|
+
var DERIVE_BUILTINS = {
|
|
115
|
+
concat: (...args) => args.map((value) => stringify(value)).join(""),
|
|
116
|
+
coalesce: (...args) => args.find((value) => value !== void 0 && value !== null),
|
|
117
|
+
when: (condition, whenTrue, whenFalse) => condition ? whenTrue : whenFalse,
|
|
118
|
+
exists: (value) => value !== void 0 && value !== null,
|
|
119
|
+
eq: (left, right) => left === right,
|
|
120
|
+
ne: (left, right) => left !== right
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// ../core/src/derive/depGraph.ts
|
|
124
|
+
function detectDerivationCycles(dependencyMap) {
|
|
125
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
126
|
+
const visited = /* @__PURE__ */ new Set();
|
|
127
|
+
const stack = [];
|
|
128
|
+
const visit = (key) => {
|
|
129
|
+
if (visited.has(key)) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (visiting.has(key)) {
|
|
133
|
+
const start = stack.indexOf(key);
|
|
134
|
+
const cycle = [...stack.slice(start), key].join(" -> ");
|
|
135
|
+
throw new CnosDerivedCycleError(`Derivation cycle detected: ${cycle}`);
|
|
136
|
+
}
|
|
137
|
+
visiting.add(key);
|
|
138
|
+
stack.push(key);
|
|
139
|
+
for (const dependency of dependencyMap.get(key) ?? []) {
|
|
140
|
+
visit(dependency);
|
|
141
|
+
}
|
|
142
|
+
stack.pop();
|
|
143
|
+
visiting.delete(key);
|
|
144
|
+
visited.add(key);
|
|
145
|
+
};
|
|
146
|
+
for (const key of dependencyMap.keys()) {
|
|
147
|
+
visit(key);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ../core/src/derive/parser.ts
|
|
152
|
+
function isWhitespace(value) {
|
|
153
|
+
return value === " " || value === "\n" || value === "\r" || value === " ";
|
|
154
|
+
}
|
|
155
|
+
function skipWhitespace(state) {
|
|
156
|
+
while (isWhitespace(state.source[state.index])) {
|
|
157
|
+
state.index += 1;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function isIdentifierStart(value) {
|
|
161
|
+
return typeof value === "string" && /[A-Za-z_]/.test(value);
|
|
162
|
+
}
|
|
163
|
+
function isIdentifierPart(value) {
|
|
164
|
+
return typeof value === "string" && /[A-Za-z0-9_.-]/.test(value);
|
|
165
|
+
}
|
|
166
|
+
function errorAt(state, message) {
|
|
167
|
+
throw new CnosDerivedExpressionError(`${message} at position ${state.index + 1}`, state.source);
|
|
168
|
+
}
|
|
169
|
+
function parseStringLiteral(state) {
|
|
170
|
+
const quote = state.source[state.index];
|
|
171
|
+
if (quote !== "'") {
|
|
172
|
+
errorAt(state, "Expected string literal");
|
|
173
|
+
}
|
|
174
|
+
state.index += 1;
|
|
175
|
+
let value = "";
|
|
176
|
+
while (state.index < state.source.length) {
|
|
177
|
+
const current = state.source[state.index];
|
|
178
|
+
if (current === "\\") {
|
|
179
|
+
const next = state.source[state.index + 1];
|
|
180
|
+
if (next === void 0) {
|
|
181
|
+
errorAt(state, "Unterminated escape sequence");
|
|
182
|
+
}
|
|
183
|
+
value += next;
|
|
184
|
+
state.index += 2;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
if (current === "'") {
|
|
188
|
+
state.index += 1;
|
|
189
|
+
return {
|
|
190
|
+
type: "literal",
|
|
191
|
+
value
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
value += current;
|
|
195
|
+
state.index += 1;
|
|
196
|
+
}
|
|
197
|
+
errorAt(state, "Unterminated string literal");
|
|
198
|
+
}
|
|
199
|
+
function parseNumberLiteral(state) {
|
|
200
|
+
const start = state.index;
|
|
201
|
+
while (/[0-9]/.test(state.source[state.index] ?? "")) {
|
|
202
|
+
state.index += 1;
|
|
203
|
+
}
|
|
204
|
+
if (state.source[state.index] === ".") {
|
|
205
|
+
state.index += 1;
|
|
206
|
+
while (/[0-9]/.test(state.source[state.index] ?? "")) {
|
|
207
|
+
state.index += 1;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
type: "literal",
|
|
212
|
+
value: Number(state.source.slice(start, state.index))
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function parseIdentifier(state) {
|
|
216
|
+
if (!isIdentifierStart(state.source[state.index])) {
|
|
217
|
+
errorAt(state, "Expected identifier");
|
|
218
|
+
}
|
|
219
|
+
const start = state.index;
|
|
220
|
+
state.index += 1;
|
|
221
|
+
while (isIdentifierPart(state.source[state.index])) {
|
|
222
|
+
state.index += 1;
|
|
223
|
+
}
|
|
224
|
+
return state.source.slice(start, state.index);
|
|
225
|
+
}
|
|
226
|
+
function parseArguments(state) {
|
|
227
|
+
const args = [];
|
|
228
|
+
skipWhitespace(state);
|
|
229
|
+
if (state.source[state.index] === ")") {
|
|
230
|
+
state.index += 1;
|
|
231
|
+
return args;
|
|
232
|
+
}
|
|
233
|
+
while (state.index < state.source.length) {
|
|
234
|
+
args.push(parseExpressionNode(state));
|
|
235
|
+
skipWhitespace(state);
|
|
236
|
+
const current = state.source[state.index];
|
|
237
|
+
if (current === ",") {
|
|
238
|
+
state.index += 1;
|
|
239
|
+
skipWhitespace(state);
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
if (current === ")") {
|
|
243
|
+
state.index += 1;
|
|
244
|
+
return args;
|
|
245
|
+
}
|
|
246
|
+
errorAt(state, 'Expected "," or ")"');
|
|
247
|
+
}
|
|
248
|
+
errorAt(state, "Unterminated function call");
|
|
249
|
+
}
|
|
250
|
+
function parseIdentifierOrCall(state) {
|
|
251
|
+
const identifier = parseIdentifier(state);
|
|
252
|
+
skipWhitespace(state);
|
|
253
|
+
if (state.source[state.index] === "(") {
|
|
254
|
+
if (!(identifier in DERIVE_BUILTINS)) {
|
|
255
|
+
throw new CnosDerivedExpressionError(`Unknown derive function: ${identifier}`, state.source);
|
|
256
|
+
}
|
|
257
|
+
state.index += 1;
|
|
258
|
+
return {
|
|
259
|
+
type: "call",
|
|
260
|
+
name: identifier,
|
|
261
|
+
args: parseArguments(state)
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
if (identifier === "true" || identifier === "false") {
|
|
265
|
+
return {
|
|
266
|
+
type: "literal",
|
|
267
|
+
value: identifier === "true"
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
if (identifier === "null") {
|
|
271
|
+
return {
|
|
272
|
+
type: "literal",
|
|
273
|
+
value: null
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
type: "ref",
|
|
278
|
+
path: identifier
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function parseExpressionNode(state) {
|
|
282
|
+
skipWhitespace(state);
|
|
283
|
+
const current = state.source[state.index];
|
|
284
|
+
if (current === "'") {
|
|
285
|
+
return parseStringLiteral(state);
|
|
286
|
+
}
|
|
287
|
+
if (/[0-9]/.test(current ?? "")) {
|
|
288
|
+
return parseNumberLiteral(state);
|
|
289
|
+
}
|
|
290
|
+
if (isIdentifierStart(current)) {
|
|
291
|
+
return parseIdentifierOrCall(state);
|
|
292
|
+
}
|
|
293
|
+
errorAt(state, "Unexpected token");
|
|
294
|
+
}
|
|
295
|
+
function parseExpression(source) {
|
|
296
|
+
const state = {
|
|
297
|
+
source,
|
|
298
|
+
index: 0
|
|
299
|
+
};
|
|
300
|
+
const ast = parseExpressionNode(state);
|
|
301
|
+
skipWhitespace(state);
|
|
302
|
+
if (state.index !== source.length) {
|
|
303
|
+
errorAt(state, "Unexpected trailing input");
|
|
304
|
+
}
|
|
305
|
+
return ast;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ../core/src/derive/templateParser.ts
|
|
309
|
+
function toLiteral(value) {
|
|
310
|
+
return {
|
|
311
|
+
type: "literal",
|
|
312
|
+
value
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
function toRef(path16) {
|
|
316
|
+
return {
|
|
317
|
+
type: "ref",
|
|
318
|
+
path: path16
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
function parseTemplate(source) {
|
|
322
|
+
const parts = [];
|
|
323
|
+
let cursor = 0;
|
|
324
|
+
while (cursor < source.length) {
|
|
325
|
+
const start = source.indexOf("${", cursor);
|
|
326
|
+
if (start < 0) {
|
|
327
|
+
if (cursor < source.length) {
|
|
328
|
+
parts.push(toLiteral(source.slice(cursor)));
|
|
329
|
+
}
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
if (start > cursor) {
|
|
333
|
+
parts.push(toLiteral(source.slice(cursor, start)));
|
|
334
|
+
}
|
|
335
|
+
const end = source.indexOf("}", start + 2);
|
|
336
|
+
if (end < 0) {
|
|
337
|
+
throw new CnosDerivedExpressionError(`Invalid derivation template: unclosed \${...} at position ${start + 1}`, source);
|
|
338
|
+
}
|
|
339
|
+
const ref = source.slice(start + 2, end).trim();
|
|
340
|
+
if (!ref) {
|
|
341
|
+
throw new CnosDerivedExpressionError(`Invalid derivation template: empty reference at position ${start + 1}`, source);
|
|
342
|
+
}
|
|
343
|
+
if (!/^[A-Za-z_][A-Za-z0-9_.-]*$/.test(ref)) {
|
|
344
|
+
throw new CnosDerivedExpressionError(`Invalid derivation template reference "${ref}"`, source);
|
|
345
|
+
}
|
|
346
|
+
parts.push(toRef(ref));
|
|
347
|
+
cursor = end + 1;
|
|
348
|
+
}
|
|
349
|
+
if (parts.length === 0) {
|
|
350
|
+
return toLiteral("");
|
|
351
|
+
}
|
|
352
|
+
if (parts.length === 1) {
|
|
353
|
+
return parts[0];
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
type: "call",
|
|
357
|
+
name: "concat",
|
|
358
|
+
args: parts
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// ../core/src/derive/evaluator.ts
|
|
363
|
+
function isDerivedValue(value) {
|
|
364
|
+
return Boolean(
|
|
365
|
+
value && typeof value === "object" && !Array.isArray(value) && "$derive" in value
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
function extractRefs(node, refs = /* @__PURE__ */ new Set()) {
|
|
369
|
+
if (node.type === "ref") {
|
|
370
|
+
refs.add(node.path);
|
|
371
|
+
return refs;
|
|
372
|
+
}
|
|
373
|
+
if (node.type === "call") {
|
|
374
|
+
for (const arg of node.args) {
|
|
375
|
+
extractRefs(arg, refs);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return refs;
|
|
379
|
+
}
|
|
380
|
+
function parseDerivation(value) {
|
|
381
|
+
const source = typeof value.$derive === "string" ? value.$derive : value.$derive?.expr;
|
|
382
|
+
if (typeof source !== "string") {
|
|
383
|
+
throw new CnosDerivedExpressionError("Derived value requires either a template string or { expr } object");
|
|
384
|
+
}
|
|
385
|
+
const type = typeof value.$derive === "string" ? "template" : "expression";
|
|
386
|
+
const ast = type === "template" ? parseTemplate(source) : parseExpression(source);
|
|
387
|
+
const refs = Array.from(extractRefs(ast)).sort((left, right) => left.localeCompare(right));
|
|
388
|
+
return {
|
|
389
|
+
type,
|
|
390
|
+
raw: source,
|
|
391
|
+
ast,
|
|
392
|
+
refs,
|
|
393
|
+
runtimeRefs: [],
|
|
394
|
+
isRuntimeDependent: false
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function normalizeConcatValue(value) {
|
|
398
|
+
if (value === void 0 || value === null) {
|
|
399
|
+
return "";
|
|
400
|
+
}
|
|
401
|
+
if (typeof value === "string") {
|
|
402
|
+
return value;
|
|
403
|
+
}
|
|
404
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
405
|
+
return String(value);
|
|
406
|
+
}
|
|
407
|
+
return JSON.stringify(value);
|
|
408
|
+
}
|
|
409
|
+
function evaluateNode(node, resolveRef) {
|
|
410
|
+
switch (node.type) {
|
|
411
|
+
case "literal":
|
|
412
|
+
return node.value;
|
|
413
|
+
case "ref":
|
|
414
|
+
return resolveRef(node.path);
|
|
415
|
+
case "call": {
|
|
416
|
+
const args = node.args.map((arg) => evaluateNode(arg, resolveRef));
|
|
417
|
+
switch (node.name) {
|
|
418
|
+
case "concat":
|
|
419
|
+
return args.map((value) => normalizeConcatValue(value)).join("");
|
|
420
|
+
case "coalesce":
|
|
421
|
+
return DERIVE_BUILTINS.coalesce(...args);
|
|
422
|
+
case "when":
|
|
423
|
+
return DERIVE_BUILTINS.when(args[0], args[1], args[2]);
|
|
424
|
+
case "exists":
|
|
425
|
+
return DERIVE_BUILTINS.exists(args[0]);
|
|
426
|
+
case "eq":
|
|
427
|
+
return DERIVE_BUILTINS.eq(args[0], args[1]);
|
|
428
|
+
case "ne":
|
|
429
|
+
return DERIVE_BUILTINS.ne(args[0], args[1]);
|
|
430
|
+
default:
|
|
431
|
+
throw new CnosDerivedExpressionError(`Unknown derive function: ${String(node.name)}`);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
default:
|
|
435
|
+
throw new CnosDerivedExpressionError(`Unsupported derive AST node ${node.type ?? "unknown"}`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
function evaluateDerivation(options) {
|
|
439
|
+
const missingRefs = /* @__PURE__ */ new Set();
|
|
440
|
+
const value = evaluateNode(options.parsed.ast, (ref) => {
|
|
441
|
+
const resolved = options.resolveRef(ref);
|
|
442
|
+
if (resolved === void 0) {
|
|
443
|
+
missingRefs.add(ref);
|
|
444
|
+
options.onMissing?.(ref);
|
|
445
|
+
}
|
|
446
|
+
return resolved;
|
|
447
|
+
});
|
|
448
|
+
if (missingRefs.size > 0 && options.parsed.ast.type === "ref") {
|
|
449
|
+
throw new CnosDerivedResolutionError(
|
|
450
|
+
options.key,
|
|
451
|
+
`Unable to resolve derived config key ${options.key} because ${Array.from(missingRefs).join(", ")} is missing.`
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
return value;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// ../core/src/derive/validate.ts
|
|
458
|
+
var FORBIDDEN_TARGET_NAMESPACES = /* @__PURE__ */ new Set(["public", "meta", "secret"]);
|
|
459
|
+
var FORBIDDEN_REF_NAMESPACES = /* @__PURE__ */ new Set(["public", "secret"]);
|
|
460
|
+
function validateDerivedTargetNamespace(manifest, namespace) {
|
|
461
|
+
if (FORBIDDEN_TARGET_NAMESPACES.has(namespace)) {
|
|
462
|
+
throw new CnosManifestError(`Cannot define derived values under namespace "${namespace}".`);
|
|
463
|
+
}
|
|
464
|
+
if (manifest.runtimeNamespaces[namespace]) {
|
|
465
|
+
throw new CnosManifestError(`Cannot define derived values under runtime namespace "${namespace}".`);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
function validateParsedDerivation(manifest, parsed) {
|
|
469
|
+
for (const ref of parsed.refs) {
|
|
470
|
+
const namespace = ref.split(".")[0] ?? "";
|
|
471
|
+
if (FORBIDDEN_REF_NAMESPACES.has(namespace)) {
|
|
472
|
+
throw new CnosDerivedExpressionError(`Derived expressions cannot reference ${namespace}.* keys.`, parsed.raw);
|
|
473
|
+
}
|
|
474
|
+
if (manifest.runtimeNamespaces[namespace]) {
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
if (!manifest.namespaces[namespace] && namespace !== "value" && namespace !== "meta") {
|
|
478
|
+
throw new CnosDerivedExpressionError(`Unknown derive reference namespace: ${namespace}`, parsed.raw);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// ../core/src/derive/runtime.ts
|
|
484
|
+
function namespaceForKey(key) {
|
|
485
|
+
return key.split(".")[0] ?? "";
|
|
486
|
+
}
|
|
487
|
+
function dependencyNamespaces(key, entries, memo) {
|
|
488
|
+
if (memo.has(key)) {
|
|
489
|
+
return memo.get(key);
|
|
490
|
+
}
|
|
491
|
+
const entry = entries.get(key);
|
|
492
|
+
if (!entry) {
|
|
493
|
+
memo.set(key, []);
|
|
494
|
+
return [];
|
|
495
|
+
}
|
|
496
|
+
const namespaces = /* @__PURE__ */ new Set();
|
|
497
|
+
for (const ref of entry.parsed.refs) {
|
|
498
|
+
const namespace = namespaceForKey(ref);
|
|
499
|
+
if (!entries.has(ref)) {
|
|
500
|
+
namespaces.add(namespace);
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
for (const dependencyNamespace of dependencyNamespaces(ref, entries, memo)) {
|
|
504
|
+
namespaces.add(dependencyNamespace);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
const result = Array.from(namespaces).sort((left, right) => left.localeCompare(right));
|
|
508
|
+
memo.set(key, result);
|
|
509
|
+
return result;
|
|
510
|
+
}
|
|
511
|
+
function isRuntimeDependentKey(key, entries, manifest, memo) {
|
|
512
|
+
if (memo.has(key)) {
|
|
513
|
+
return memo.get(key);
|
|
514
|
+
}
|
|
515
|
+
const entry = entries.get(key);
|
|
516
|
+
if (!entry) {
|
|
517
|
+
memo.set(key, false);
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
for (const ref of entry.parsed.refs) {
|
|
521
|
+
const namespace = namespaceForKey(ref);
|
|
522
|
+
if (manifest.runtimeNamespaces[namespace]) {
|
|
523
|
+
memo.set(key, true);
|
|
524
|
+
return true;
|
|
525
|
+
}
|
|
526
|
+
if (entries.has(ref) && isRuntimeDependentKey(ref, entries, manifest, memo)) {
|
|
527
|
+
memo.set(key, true);
|
|
528
|
+
return true;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
memo.set(key, false);
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
function prepareEntries(graph, manifest) {
|
|
535
|
+
const entries = /* @__PURE__ */ new Map();
|
|
536
|
+
for (const [key, entry] of graph.entries) {
|
|
537
|
+
if (!isDerivedValue(entry.value)) {
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
const namespaceDefinition = manifest.namespaces[entry.namespace];
|
|
541
|
+
if (!namespaceDefinition || namespaceDefinition.kind === "data") {
|
|
542
|
+
validateDerivedTargetNamespace(manifest, entry.namespace);
|
|
543
|
+
}
|
|
544
|
+
const parsed = parseDerivation(entry.value);
|
|
545
|
+
validateParsedDerivation(manifest, parsed);
|
|
546
|
+
entries.set(key, {
|
|
547
|
+
key,
|
|
548
|
+
namespace: entry.namespace,
|
|
549
|
+
value: entry.value,
|
|
550
|
+
parsed
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
detectDerivationCycles(
|
|
554
|
+
new Map(
|
|
555
|
+
Array.from(entries.values()).map((entry) => [
|
|
556
|
+
entry.key,
|
|
557
|
+
entry.parsed.refs.filter((ref) => entries.has(ref))
|
|
558
|
+
])
|
|
559
|
+
)
|
|
560
|
+
);
|
|
561
|
+
const runtimeMemo = /* @__PURE__ */ new Map();
|
|
562
|
+
const namespaceMemo = /* @__PURE__ */ new Map();
|
|
563
|
+
for (const entry of entries.values()) {
|
|
564
|
+
entry.parsed.isRuntimeDependent = isRuntimeDependentKey(entry.key, entries, manifest, runtimeMemo);
|
|
565
|
+
entry.parsed.runtimeRefs = entry.parsed.refs.filter((ref) => manifest.runtimeNamespaces[namespaceForKey(ref)]);
|
|
566
|
+
if (entry.parsed.runtimeRefs.length === 0 && entry.parsed.isRuntimeDependent) {
|
|
567
|
+
entry.parsed.runtimeRefs = dependencyNamespaces(entry.key, entries, namespaceMemo).filter((namespace) => manifest.runtimeNamespaces[namespace]).map((namespace) => `${namespace}.*`);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return entries;
|
|
571
|
+
}
|
|
572
|
+
function createDerivedRuntimeSupport(graph, manifest, runtimeProviders) {
|
|
573
|
+
const entries = prepareEntries(graph, manifest);
|
|
574
|
+
const configCache = /* @__PURE__ */ new Map();
|
|
575
|
+
const runtimeDependencyMemo = /* @__PURE__ */ new Map();
|
|
576
|
+
const support = {};
|
|
577
|
+
Object.assign(support, {
|
|
578
|
+
runtimeProviders,
|
|
579
|
+
read(key, readBase) {
|
|
580
|
+
const namespace = namespaceForKey(key);
|
|
581
|
+
if (runtimeProviders.has(namespace)) {
|
|
582
|
+
const provider = runtimeProviders.get(namespace);
|
|
583
|
+
return provider(key.slice(namespace.length + 1));
|
|
584
|
+
}
|
|
585
|
+
if (entries.has(key)) {
|
|
586
|
+
return readDerived(key, readBase);
|
|
587
|
+
}
|
|
588
|
+
return readBase(key);
|
|
589
|
+
},
|
|
590
|
+
describe(key, readBase) {
|
|
591
|
+
const entry = entries.get(key);
|
|
592
|
+
if (!entry) {
|
|
593
|
+
return void 0;
|
|
594
|
+
}
|
|
595
|
+
const runtimeNamespaces = Array.from(
|
|
596
|
+
new Set(
|
|
597
|
+
entry.parsed.refs.map((ref) => namespaceForKey(ref)).filter((namespace) => manifest.runtimeNamespaces[namespace])
|
|
598
|
+
)
|
|
599
|
+
).sort((left, right) => left.localeCompare(right));
|
|
600
|
+
return {
|
|
601
|
+
key,
|
|
602
|
+
type: entry.parsed.type,
|
|
603
|
+
expression: entry.parsed.raw,
|
|
604
|
+
dependencies: entry.parsed.refs.map((ref) => {
|
|
605
|
+
const namespace = namespaceForKey(ref);
|
|
606
|
+
return {
|
|
607
|
+
key: ref,
|
|
608
|
+
value: support.read(ref, readBase),
|
|
609
|
+
...manifest.runtimeNamespaces[namespace] ? {
|
|
610
|
+
runtimeNamespace: namespace
|
|
611
|
+
} : {}
|
|
612
|
+
};
|
|
613
|
+
}),
|
|
614
|
+
runtimeDependent: entry.parsed.isRuntimeDependent,
|
|
615
|
+
runtimeNamespaces,
|
|
616
|
+
...entry.parsed.isRuntimeDependent ? {
|
|
617
|
+
promotionWarning: "Cannot be promoted to browser/public."
|
|
618
|
+
} : {}
|
|
619
|
+
};
|
|
620
|
+
},
|
|
621
|
+
isDerivedKey(key) {
|
|
622
|
+
return entries.has(key);
|
|
623
|
+
},
|
|
624
|
+
isRuntimeDependentKey(key) {
|
|
625
|
+
if (runtimeDependencyMemo.has(key)) {
|
|
626
|
+
return runtimeDependencyMemo.get(key);
|
|
627
|
+
}
|
|
628
|
+
const value = entries.get(key)?.parsed.isRuntimeDependent ?? false;
|
|
629
|
+
runtimeDependencyMemo.set(key, value);
|
|
630
|
+
return value;
|
|
631
|
+
},
|
|
632
|
+
toConcreteValue(key, readBase, mode) {
|
|
633
|
+
const entry = entries.get(key);
|
|
634
|
+
if (!entry) {
|
|
635
|
+
return support.read(key, readBase);
|
|
636
|
+
}
|
|
637
|
+
if (!entry.parsed.isRuntimeDependent) {
|
|
638
|
+
return support.read(key, readBase);
|
|
639
|
+
}
|
|
640
|
+
if (mode === "server" || mode === "runtime") {
|
|
641
|
+
return support.read(key, readBase);
|
|
642
|
+
}
|
|
643
|
+
for (const ref of entry.parsed.refs) {
|
|
644
|
+
const namespace = namespaceForKey(ref);
|
|
645
|
+
const runtimeNamespace = manifest.runtimeNamespaces[namespace];
|
|
646
|
+
if (!runtimeNamespace) {
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
if (runtimeNamespace.serverOnly) {
|
|
650
|
+
throw new CnosDerivedResolutionError(
|
|
651
|
+
key,
|
|
652
|
+
`Cannot resolve ${key} for ${mode} output because it depends on runtime namespace ${namespace}.`
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
if (!runtimeProviders.has(namespace)) {
|
|
656
|
+
if (mode === "env") {
|
|
657
|
+
return void 0;
|
|
658
|
+
}
|
|
659
|
+
throw new CnosDerivedResolutionError(
|
|
660
|
+
key,
|
|
661
|
+
`Cannot resolve ${key} for ${mode} output because runtime namespace ${namespace} has no registered provider.`
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
return support.read(key, readBase);
|
|
666
|
+
},
|
|
667
|
+
toServerFormula(key) {
|
|
668
|
+
const entry = entries.get(key);
|
|
669
|
+
if (!entry || !entry.parsed.isRuntimeDependent) {
|
|
670
|
+
return void 0;
|
|
671
|
+
}
|
|
672
|
+
return {
|
|
673
|
+
expr: entry.parsed.raw,
|
|
674
|
+
deps: entry.parsed.refs.filter((ref) => !manifest.runtimeNamespaces[namespaceForKey(ref)]),
|
|
675
|
+
runtimeRefs: entry.parsed.refs.filter((ref) => manifest.runtimeNamespaces[namespaceForKey(ref)])
|
|
676
|
+
};
|
|
677
|
+
},
|
|
678
|
+
derivedKeys: Array.from(entries.keys()).sort((left, right) => left.localeCompare(right))
|
|
679
|
+
});
|
|
680
|
+
const readDerived = (key, readBase, evaluationStack = /* @__PURE__ */ new Set()) => {
|
|
681
|
+
const entry = entries.get(key);
|
|
682
|
+
if (!entry) {
|
|
683
|
+
return readBase(key);
|
|
684
|
+
}
|
|
685
|
+
if (!entry.parsed.isRuntimeDependent && configCache.has(key)) {
|
|
686
|
+
return configCache.get(key);
|
|
687
|
+
}
|
|
688
|
+
const value = evaluateDerivation({
|
|
689
|
+
key,
|
|
690
|
+
parsed: entry.parsed,
|
|
691
|
+
resolveRef: (ref) => {
|
|
692
|
+
const namespace = namespaceForKey(ref);
|
|
693
|
+
if (runtimeProviders.has(namespace)) {
|
|
694
|
+
const provider = runtimeProviders.get(namespace);
|
|
695
|
+
return provider(ref.slice(namespace.length + 1));
|
|
696
|
+
}
|
|
697
|
+
if (entries.has(ref)) {
|
|
698
|
+
if (evaluationStack.has(ref)) {
|
|
699
|
+
throw new CnosDerivedResolutionError(key, `Unable to resolve derived config key ${key} because of a recursive dependency on ${ref}.`);
|
|
700
|
+
}
|
|
701
|
+
evaluationStack.add(ref);
|
|
702
|
+
const resolved = readDerived(ref, readBase, evaluationStack);
|
|
703
|
+
evaluationStack.delete(ref);
|
|
704
|
+
return resolved;
|
|
705
|
+
}
|
|
706
|
+
return readBase(ref);
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
if (!entry.parsed.isRuntimeDependent) {
|
|
710
|
+
configCache.set(key, value);
|
|
711
|
+
}
|
|
712
|
+
return value;
|
|
713
|
+
};
|
|
714
|
+
for (const key of Array.from(entries.keys()).sort((left, right) => left.localeCompare(right))) {
|
|
715
|
+
const entry = entries.get(key);
|
|
716
|
+
if (!entry.parsed.isRuntimeDependent) {
|
|
717
|
+
readDerived(key, (ref) => graph.entries.get(ref)?.value);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return support;
|
|
721
|
+
}
|
|
722
|
+
function registerRuntimeProvider(manifest, runtimeProviders, namespace, provider) {
|
|
723
|
+
const definition = manifest.runtimeNamespaces[namespace];
|
|
724
|
+
if (!definition) {
|
|
725
|
+
throw new CnosRuntimeProviderError(`Cannot register runtime provider for undeclared namespace "${namespace}".`);
|
|
726
|
+
}
|
|
727
|
+
if (definition.builtIn) {
|
|
728
|
+
throw new CnosRuntimeProviderError(`Cannot override built-in runtime namespace "${namespace}".`);
|
|
729
|
+
}
|
|
730
|
+
runtimeProviders.set(namespace, provider);
|
|
731
|
+
}
|
|
76
732
|
|
|
77
733
|
// ../core/src/runtime/inspect.ts
|
|
78
|
-
function inspectValue(graph, key) {
|
|
734
|
+
function inspectValue(graph, key, helpers = {}) {
|
|
79
735
|
const entry = graph.entries.get(key);
|
|
80
736
|
if (!entry) {
|
|
81
737
|
throw new CnosKeyNotFoundError(key);
|
|
82
738
|
}
|
|
739
|
+
const derived = helpers.describeDerived?.(key);
|
|
83
740
|
return {
|
|
84
741
|
key: entry.key,
|
|
85
|
-
value: entry.value,
|
|
742
|
+
value: helpers.read ? helpers.read(entry.key) : entry.value,
|
|
86
743
|
namespace: entry.namespace,
|
|
87
744
|
profile: graph.profile,
|
|
88
745
|
profileSource: graph.profileSource,
|
|
@@ -103,7 +760,10 @@ function inspectValue(graph, key) {
|
|
|
103
760
|
workspaceId: override.workspaceId,
|
|
104
761
|
value: override.value,
|
|
105
762
|
...override.origin ? { origin: override.origin } : {}
|
|
106
|
-
}))
|
|
763
|
+
})),
|
|
764
|
+
...derived ? {
|
|
765
|
+
derived
|
|
766
|
+
} : {}
|
|
107
767
|
};
|
|
108
768
|
}
|
|
109
769
|
|
|
@@ -181,17 +841,17 @@ async function readKeychain(entry) {
|
|
|
181
841
|
}
|
|
182
842
|
|
|
183
843
|
// ../core/src/manifest/loadManifest.ts
|
|
184
|
-
var
|
|
185
|
-
var
|
|
844
|
+
var import_promises5 = require("fs/promises");
|
|
845
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
186
846
|
|
|
187
847
|
// ../core/src/utils/path.ts
|
|
188
|
-
var
|
|
189
|
-
var
|
|
190
|
-
var
|
|
848
|
+
var import_promises4 = require("fs/promises");
|
|
849
|
+
var import_node_os3 = __toESM(require("os"), 1);
|
|
850
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
191
851
|
|
|
192
852
|
// ../core/src/discovery/findCnosrc.ts
|
|
193
|
-
var
|
|
194
|
-
var
|
|
853
|
+
var import_promises3 = require("fs/promises");
|
|
854
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
195
855
|
|
|
196
856
|
// ../core/src/utils/yaml.ts
|
|
197
857
|
var import_yaml = require("yaml");
|
|
@@ -202,10 +862,315 @@ function stringifyYaml(value) {
|
|
|
202
862
|
return (0, import_yaml.stringify)(value);
|
|
203
863
|
}
|
|
204
864
|
|
|
865
|
+
// ../core/src/discovery/resolveRoot.ts
|
|
866
|
+
var import_promises2 = require("fs/promises");
|
|
867
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
868
|
+
var import_node_child_process4 = require("child_process");
|
|
869
|
+
var import_node_os2 = __toESM(require("os"), 1);
|
|
870
|
+
|
|
871
|
+
// ../core/src/discovery/parseGitUri.ts
|
|
872
|
+
function isGitRootUri(uri) {
|
|
873
|
+
return /^git\+[a-z]+:\/\//i.test(uri);
|
|
874
|
+
}
|
|
875
|
+
function parseGitUri(uri) {
|
|
876
|
+
if (!isGitRootUri(uri)) {
|
|
877
|
+
throw new CnosDiscoveryError(`Unsupported git root URI: ${uri}`);
|
|
878
|
+
}
|
|
879
|
+
const withoutPrefix = uri.slice("git+".length);
|
|
880
|
+
const hashIndex = withoutPrefix.indexOf("#");
|
|
881
|
+
if (hashIndex < 0) {
|
|
882
|
+
throw new CnosDiscoveryError(
|
|
883
|
+
`Git root URI must include a #ref (tag, branch, or commit). Got: ${uri}`
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
const cloneUrl = withoutPrefix.slice(0, hashIndex);
|
|
887
|
+
const fragment = withoutPrefix.slice(hashIndex + 1);
|
|
888
|
+
const separatorIndex = fragment.indexOf(":");
|
|
889
|
+
const ref = (separatorIndex >= 0 ? fragment.slice(0, separatorIndex) : fragment).trim();
|
|
890
|
+
const subpath = (separatorIndex >= 0 ? fragment.slice(separatorIndex + 1) : ".cnos").trim() || ".cnos";
|
|
891
|
+
const protocol = cloneUrl.slice(0, cloneUrl.indexOf("://"));
|
|
892
|
+
if (!cloneUrl || !ref) {
|
|
893
|
+
throw new CnosDiscoveryError(
|
|
894
|
+
`Git root URI must include both a clone URL and #ref. Got: ${uri}`
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
return {
|
|
898
|
+
uri,
|
|
899
|
+
cloneUrl,
|
|
900
|
+
ref,
|
|
901
|
+
subpath,
|
|
902
|
+
transport: protocol === "https" ? "https" : protocol === "ssh" ? "ssh" : protocol === "file" ? "file" : "custom"
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// ../core/src/discovery/cache/cacheManager.ts
|
|
907
|
+
var SEMVER_TAG_RE = /^v?\d+\.\d+(?:\.\d+)?(?:[-+][A-Za-z0-9.-]+)?$/;
|
|
908
|
+
var COMMIT_SHA_RE = /^[0-9a-f]{40}$/i;
|
|
909
|
+
function isImmutableGitRef(ref) {
|
|
910
|
+
return SEMVER_TAG_RE.test(ref) || COMMIT_SHA_RE.test(ref);
|
|
911
|
+
}
|
|
912
|
+
function resolveRemoteRootCacheTtlSeconds(mode = "runtime", processEnv = process.env, override) {
|
|
913
|
+
if (typeof override === "number" && Number.isFinite(override) && override >= 0) {
|
|
914
|
+
return override;
|
|
915
|
+
}
|
|
916
|
+
const fromEnv = Number(processEnv.CNOS_CACHE_TTL ?? "");
|
|
917
|
+
if (Number.isFinite(fromEnv) && fromEnv >= 0) {
|
|
918
|
+
return fromEnv;
|
|
919
|
+
}
|
|
920
|
+
switch (mode) {
|
|
921
|
+
case "build":
|
|
922
|
+
return 0;
|
|
923
|
+
case "dev":
|
|
924
|
+
return 30;
|
|
925
|
+
case "runtime":
|
|
926
|
+
default:
|
|
927
|
+
return 300;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
function isRemoteRootCacheFresh(metadata, options) {
|
|
931
|
+
if (!metadata || options.forceRefresh) {
|
|
932
|
+
return false;
|
|
933
|
+
}
|
|
934
|
+
if (metadata.uri !== options.uri || metadata.ref !== options.ref) {
|
|
935
|
+
return false;
|
|
936
|
+
}
|
|
937
|
+
if (metadata.isImmutable) {
|
|
938
|
+
return true;
|
|
939
|
+
}
|
|
940
|
+
const ttlSeconds = resolveRemoteRootCacheTtlSeconds(
|
|
941
|
+
options.mode,
|
|
942
|
+
options.processEnv,
|
|
943
|
+
options.ttlSeconds
|
|
944
|
+
);
|
|
945
|
+
if (ttlSeconds <= 0) {
|
|
946
|
+
return false;
|
|
947
|
+
}
|
|
948
|
+
const cachedAtMs = Date.parse(metadata.cachedAt);
|
|
949
|
+
if (Number.isNaN(cachedAtMs)) {
|
|
950
|
+
return false;
|
|
951
|
+
}
|
|
952
|
+
return Date.now() - cachedAtMs <= ttlSeconds * 1e3;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
// ../core/src/discovery/cache/cacheMetadata.ts
|
|
956
|
+
var import_promises = require("fs/promises");
|
|
957
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
958
|
+
async function readRemoteRootCacheMetadata(metaPath) {
|
|
959
|
+
try {
|
|
960
|
+
const source = await (0, import_promises.readFile)(metaPath, "utf8");
|
|
961
|
+
const parsed = JSON.parse(source);
|
|
962
|
+
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") {
|
|
963
|
+
return void 0;
|
|
964
|
+
}
|
|
965
|
+
return parsed;
|
|
966
|
+
} catch {
|
|
967
|
+
return void 0;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
async function writeRemoteRootCacheMetadata(metaPath, metadata) {
|
|
971
|
+
await (0, import_promises.mkdir)(import_node_path.default.dirname(metaPath), { recursive: true });
|
|
972
|
+
await (0, import_promises.writeFile)(metaPath, `${JSON.stringify(metadata, null, 2)}
|
|
973
|
+
`, "utf8");
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// ../core/src/discovery/cache/cachePaths.ts
|
|
977
|
+
var import_node_crypto = require("crypto");
|
|
978
|
+
var import_node_os = __toESM(require("os"), 1);
|
|
979
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
980
|
+
function resolveCnosCacheRoot(processEnv = process.env) {
|
|
981
|
+
return import_node_path2.default.resolve(
|
|
982
|
+
expandHomePath(processEnv.CNOS_CACHE_DIR ?? import_node_path2.default.join(import_node_os.default.homedir(), ".cnos", "cache"))
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
function createRemoteRootCacheKey(uri) {
|
|
986
|
+
return (0, import_node_crypto.createHash)("sha256").update(uri).digest("hex");
|
|
987
|
+
}
|
|
988
|
+
function resolveRemoteRootCachePaths(uri, processEnv = process.env) {
|
|
989
|
+
const cacheRoot = resolveCnosCacheRoot(processEnv);
|
|
990
|
+
const cacheDir = import_node_path2.default.join(cacheRoot, "roots", createRemoteRootCacheKey(uri));
|
|
991
|
+
return {
|
|
992
|
+
cacheRoot,
|
|
993
|
+
cacheDir,
|
|
994
|
+
repoDir: import_node_path2.default.join(cacheDir, "repo"),
|
|
995
|
+
metaPath: import_node_path2.default.join(cacheDir, ".cnos-cache-meta.json")
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// ../core/src/discovery/resolveRoot.ts
|
|
1000
|
+
async function pathExists(targetPath) {
|
|
1001
|
+
try {
|
|
1002
|
+
await (0, import_promises2.access)(targetPath);
|
|
1003
|
+
return true;
|
|
1004
|
+
} catch {
|
|
1005
|
+
return false;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
function expandHomePath2(targetPath) {
|
|
1009
|
+
if (targetPath === "~") {
|
|
1010
|
+
return import_node_os2.default.homedir();
|
|
1011
|
+
}
|
|
1012
|
+
if (targetPath.startsWith("~/") || targetPath.startsWith("~\\")) {
|
|
1013
|
+
return import_node_path3.default.join(import_node_os2.default.homedir(), targetPath.slice(2));
|
|
1014
|
+
}
|
|
1015
|
+
return targetPath;
|
|
1016
|
+
}
|
|
1017
|
+
function isLocalRootUri(rootUri) {
|
|
1018
|
+
return !isGitRootUri2(rootUri) && !isCnosHostedRootUri(rootUri);
|
|
1019
|
+
}
|
|
1020
|
+
function isCnosHostedRootUri(rootUri) {
|
|
1021
|
+
return rootUri.startsWith("cnos://");
|
|
1022
|
+
}
|
|
1023
|
+
function isGitRootUri2(rootUri) {
|
|
1024
|
+
return rootUri.startsWith("git+");
|
|
1025
|
+
}
|
|
1026
|
+
async function runGitCommand(args, options = {}) {
|
|
1027
|
+
return new Promise((resolve, reject) => {
|
|
1028
|
+
const child = (0, import_node_child_process4.spawn)("git", args, {
|
|
1029
|
+
cwd: options.cwd,
|
|
1030
|
+
env: options.processEnv ?? process.env,
|
|
1031
|
+
shell: process.platform === "win32",
|
|
1032
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
1033
|
+
});
|
|
1034
|
+
let stdout = "";
|
|
1035
|
+
let stderr = "";
|
|
1036
|
+
child.stdout.on("data", (chunk) => {
|
|
1037
|
+
stdout += chunk.toString();
|
|
1038
|
+
});
|
|
1039
|
+
child.stderr.on("data", (chunk) => {
|
|
1040
|
+
stderr += chunk.toString();
|
|
1041
|
+
});
|
|
1042
|
+
child.on("error", (error) => {
|
|
1043
|
+
reject(
|
|
1044
|
+
new CnosDiscoveryError(
|
|
1045
|
+
`Failed to run git. Make sure git is installed and available on PATH. ${error.message}`
|
|
1046
|
+
)
|
|
1047
|
+
);
|
|
1048
|
+
});
|
|
1049
|
+
child.on("close", (code) => {
|
|
1050
|
+
if (code === 0) {
|
|
1051
|
+
resolve(stdout.trim());
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
const details = stderr.trim() || stdout.trim();
|
|
1055
|
+
reject(
|
|
1056
|
+
new CnosDiscoveryError(
|
|
1057
|
+
details ? `Git command failed: ${details}` : `Git command failed with exit code ${code ?? 1}`
|
|
1058
|
+
)
|
|
1059
|
+
);
|
|
1060
|
+
});
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
async function resolveLocalRoot(rootUri, cnosrcDir) {
|
|
1064
|
+
const candidateRoot = rootUri.startsWith("~") ? expandHomePath2(rootUri) : rootUri;
|
|
1065
|
+
const manifestRoot = import_node_path3.default.resolve(cnosrcDir, candidateRoot);
|
|
1066
|
+
const manifestPath = import_node_path3.default.join(manifestRoot, "cnos.yml");
|
|
1067
|
+
if (!await pathExists(manifestPath)) {
|
|
1068
|
+
throw new CnosDiscoveryError(`.cnosrc.yml points to ${manifestRoot} but no cnos.yml found there.`);
|
|
1069
|
+
}
|
|
1070
|
+
return {
|
|
1071
|
+
manifestRoot,
|
|
1072
|
+
resolution: {
|
|
1073
|
+
rootUri,
|
|
1074
|
+
protocol: "local",
|
|
1075
|
+
remote: false,
|
|
1076
|
+
readOnly: false
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
async function ensureGitCheckout(parsed, repoDir, processEnv) {
|
|
1081
|
+
const hasRepo = await pathExists(import_node_path3.default.join(repoDir, ".git"));
|
|
1082
|
+
if (!hasRepo) {
|
|
1083
|
+
await (0, import_promises2.mkdir)(import_node_path3.default.dirname(repoDir), { recursive: true });
|
|
1084
|
+
await runGitCommand(["clone", "--no-checkout", parsed.cloneUrl, repoDir], { processEnv });
|
|
1085
|
+
} else {
|
|
1086
|
+
await runGitCommand(["-C", repoDir, "remote", "set-url", "origin", parsed.cloneUrl], {
|
|
1087
|
+
processEnv
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
await runGitCommand(["-C", repoDir, "fetch", "--tags", "--force", "origin"], { processEnv });
|
|
1091
|
+
await runGitCommand(["-C", repoDir, "checkout", "--force", parsed.ref], { processEnv });
|
|
1092
|
+
await runGitCommand(["-C", repoDir, "clean", "-fdx"], { processEnv });
|
|
1093
|
+
}
|
|
1094
|
+
async function resolveGitRoot(rootUri, options = {}) {
|
|
1095
|
+
const processEnv = options.processEnv ?? process.env;
|
|
1096
|
+
const parsed = parseGitUri(rootUri);
|
|
1097
|
+
const cachePaths = resolveRemoteRootCachePaths(rootUri, processEnv);
|
|
1098
|
+
const metadata = await readRemoteRootCacheMetadata(cachePaths.metaPath);
|
|
1099
|
+
const immutable = isImmutableGitRef(parsed.ref);
|
|
1100
|
+
const cacheFresh = isRemoteRootCacheFresh(metadata, {
|
|
1101
|
+
uri: rootUri,
|
|
1102
|
+
ref: parsed.ref,
|
|
1103
|
+
...options.cacheMode ? { mode: options.cacheMode } : {},
|
|
1104
|
+
processEnv,
|
|
1105
|
+
...typeof options.cacheTtlSeconds === "number" ? { ttlSeconds: options.cacheTtlSeconds } : {},
|
|
1106
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
1107
|
+
});
|
|
1108
|
+
if (!cacheFresh) {
|
|
1109
|
+
try {
|
|
1110
|
+
await ensureGitCheckout(parsed, cachePaths.repoDir, processEnv);
|
|
1111
|
+
} catch (error) {
|
|
1112
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1113
|
+
const authHint = parsed.transport === "ssh" ? " Check your SSH key and git access." : " Check the URL and your git credential helper or token setup.";
|
|
1114
|
+
throw new CnosDiscoveryError(`Failed to resolve remote git root ${rootUri}. ${message}${authHint}`);
|
|
1115
|
+
}
|
|
1116
|
+
const resolvedCommit = await runGitCommand(["-C", cachePaths.repoDir, "rev-parse", "HEAD"], {
|
|
1117
|
+
processEnv
|
|
1118
|
+
});
|
|
1119
|
+
await writeRemoteRootCacheMetadata(cachePaths.metaPath, {
|
|
1120
|
+
uri: rootUri,
|
|
1121
|
+
cloneUrl: parsed.cloneUrl,
|
|
1122
|
+
ref: parsed.ref,
|
|
1123
|
+
subpath: parsed.subpath,
|
|
1124
|
+
resolvedCommit,
|
|
1125
|
+
cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1126
|
+
isImmutable: immutable
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1129
|
+
const nextMetadata = metadata && cacheFresh ? metadata : await readRemoteRootCacheMetadata(cachePaths.metaPath);
|
|
1130
|
+
const manifestRoot = import_node_path3.default.join(cachePaths.repoDir, parsed.subpath);
|
|
1131
|
+
if (!await pathExists(import_node_path3.default.join(manifestRoot, "cnos.yml"))) {
|
|
1132
|
+
throw new CnosDiscoveryError(
|
|
1133
|
+
`Git root ${rootUri} resolved to ${manifestRoot} but no cnos.yml was found there. Check the :subpath segment.`
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
1136
|
+
return {
|
|
1137
|
+
manifestRoot,
|
|
1138
|
+
resolution: {
|
|
1139
|
+
rootUri,
|
|
1140
|
+
protocol: "git",
|
|
1141
|
+
remote: true,
|
|
1142
|
+
readOnly: true,
|
|
1143
|
+
cacheDir: cachePaths.cacheDir,
|
|
1144
|
+
cacheMetaPath: cachePaths.metaPath,
|
|
1145
|
+
ref: parsed.ref,
|
|
1146
|
+
subpath: parsed.subpath,
|
|
1147
|
+
immutable,
|
|
1148
|
+
...nextMetadata?.resolvedCommit ? { resolvedCommit: nextMetadata.resolvedCommit } : {},
|
|
1149
|
+
...nextMetadata?.cachedAt ? { cachedAt: nextMetadata.cachedAt } : {}
|
|
1150
|
+
}
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
async function resolveRootUri(rootUri, cnosrcDir, options = {}) {
|
|
1154
|
+
if (isLocalRootUri(rootUri)) {
|
|
1155
|
+
return resolveLocalRoot(rootUri, cnosrcDir);
|
|
1156
|
+
}
|
|
1157
|
+
if (isGitRootUri2(rootUri)) {
|
|
1158
|
+
return resolveGitRoot(rootUri, options);
|
|
1159
|
+
}
|
|
1160
|
+
if (isCnosHostedRootUri(rootUri)) {
|
|
1161
|
+
throw new CnosDiscoveryError(
|
|
1162
|
+
`The cnos:// remote root protocol is reserved but not implemented yet. Use git+https:// or git+ssh:// for now.`
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
throw new CnosDiscoveryError(
|
|
1166
|
+
`Unknown root protocol: ${rootUri}. Supported root protocols are local paths, git+https://..., and git+ssh://....`
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
205
1170
|
// ../core/src/discovery/findCnosrc.ts
|
|
206
1171
|
async function exists(targetPath) {
|
|
207
1172
|
try {
|
|
208
|
-
await (0,
|
|
1173
|
+
await (0, import_promises3.access)(targetPath);
|
|
209
1174
|
return true;
|
|
210
1175
|
} catch {
|
|
211
1176
|
return false;
|
|
@@ -226,13 +1191,13 @@ function validateCnosrc(value, filePath) {
|
|
|
226
1191
|
};
|
|
227
1192
|
}
|
|
228
1193
|
async function findCnosrc(startDir = process.cwd(), maxLevels = 3) {
|
|
229
|
-
let current =
|
|
1194
|
+
let current = import_node_path4.default.resolve(startDir);
|
|
230
1195
|
for (let depth = 0; depth <= maxLevels; depth += 1) {
|
|
231
|
-
const candidate =
|
|
1196
|
+
const candidate = import_node_path4.default.join(current, ".cnosrc.yml");
|
|
232
1197
|
if (await exists(candidate)) {
|
|
233
1198
|
return candidate;
|
|
234
1199
|
}
|
|
235
|
-
const parent =
|
|
1200
|
+
const parent = import_node_path4.default.dirname(current);
|
|
236
1201
|
if (parent === current) {
|
|
237
1202
|
break;
|
|
238
1203
|
}
|
|
@@ -240,27 +1205,22 @@ async function findCnosrc(startDir = process.cwd(), maxLevels = 3) {
|
|
|
240
1205
|
}
|
|
241
1206
|
return void 0;
|
|
242
1207
|
}
|
|
243
|
-
async function discoverCnosAnchor(startDir = process.cwd(), maxLevels = 3) {
|
|
1208
|
+
async function discoverCnosAnchor(startDir = process.cwd(), maxLevels = 3, options = {}) {
|
|
244
1209
|
const anchorPath = await findCnosrc(startDir, maxLevels);
|
|
245
1210
|
if (!anchorPath) {
|
|
246
1211
|
throw new CnosDiscoveryError(
|
|
247
1212
|
"No .cnosrc.yml found. Run cnos init or create .cnosrc.yml in your package root."
|
|
248
1213
|
);
|
|
249
1214
|
}
|
|
250
|
-
const source = await (0,
|
|
1215
|
+
const source = await (0, import_promises3.readFile)(anchorPath, "utf8");
|
|
251
1216
|
const parsed = validateCnosrc(parseYaml(source), anchorPath);
|
|
252
|
-
const consumerRoot =
|
|
253
|
-
const
|
|
254
|
-
const manifestPath = import_node_path.default.join(manifestRoot, "cnos.yml");
|
|
255
|
-
if (!await exists(manifestPath)) {
|
|
256
|
-
throw new CnosDiscoveryError(
|
|
257
|
-
`.cnosrc.yml points to ${manifestRoot} but no cnos.yml found there.`
|
|
258
|
-
);
|
|
259
|
-
}
|
|
1217
|
+
const consumerRoot = import_node_path4.default.dirname(anchorPath);
|
|
1218
|
+
const resolvedRoot = await resolveRootUri(parsed.root, consumerRoot, options);
|
|
260
1219
|
return {
|
|
261
1220
|
anchorPath,
|
|
262
1221
|
consumerRoot,
|
|
263
|
-
manifestRoot,
|
|
1222
|
+
manifestRoot: resolvedRoot.manifestRoot,
|
|
1223
|
+
rootResolution: resolvedRoot.resolution,
|
|
264
1224
|
...parsed.workspace ? { workspace: parsed.workspace } : {}
|
|
265
1225
|
};
|
|
266
1226
|
}
|
|
@@ -270,21 +1230,21 @@ var PRIMARY_CNOS_DIR = ".cnos";
|
|
|
270
1230
|
var LEGACY_CNOS_DIR = "cnos";
|
|
271
1231
|
async function exists2(filePath) {
|
|
272
1232
|
try {
|
|
273
|
-
await (0,
|
|
1233
|
+
await (0, import_promises4.access)(filePath);
|
|
274
1234
|
return true;
|
|
275
1235
|
} catch {
|
|
276
1236
|
return false;
|
|
277
1237
|
}
|
|
278
1238
|
}
|
|
279
1239
|
async function resolveCnosRoot(root = process.cwd()) {
|
|
280
|
-
const basePath =
|
|
1240
|
+
const basePath = import_node_path5.default.resolve(root);
|
|
281
1241
|
const candidates = [
|
|
282
|
-
|
|
283
|
-
|
|
1242
|
+
import_node_path5.default.join(basePath, PRIMARY_CNOS_DIR),
|
|
1243
|
+
import_node_path5.default.join(basePath, LEGACY_CNOS_DIR),
|
|
284
1244
|
basePath
|
|
285
1245
|
];
|
|
286
1246
|
for (const candidate of candidates) {
|
|
287
|
-
if (await exists2(
|
|
1247
|
+
if (await exists2(import_node_path5.default.join(candidate, "cnos.yml"))) {
|
|
288
1248
|
return candidate;
|
|
289
1249
|
}
|
|
290
1250
|
}
|
|
@@ -294,18 +1254,44 @@ async function resolveCnosRoot(root = process.cwd()) {
|
|
|
294
1254
|
}
|
|
295
1255
|
async function resolveManifestRoot(options = {}) {
|
|
296
1256
|
if (options.root) {
|
|
1257
|
+
if (options.root.startsWith("git+") || options.root.startsWith("cnos://")) {
|
|
1258
|
+
const consumerRoot2 = import_node_path5.default.resolve(options.cwd ?? process.cwd());
|
|
1259
|
+
const resolvedRoot2 = await resolveRootUri(options.root, consumerRoot2, {
|
|
1260
|
+
...options.processEnv ? { processEnv: options.processEnv } : {},
|
|
1261
|
+
...options.cacheMode ? { cacheMode: options.cacheMode } : {},
|
|
1262
|
+
...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
|
|
1263
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
1264
|
+
});
|
|
1265
|
+
return {
|
|
1266
|
+
manifestRoot: resolvedRoot2.manifestRoot,
|
|
1267
|
+
consumerRoot: consumerRoot2,
|
|
1268
|
+
rootResolution: resolvedRoot2.resolution
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
297
1271
|
const manifestRoot = await resolveCnosRoot(options.root);
|
|
298
|
-
const resolvedRoot =
|
|
299
|
-
const consumerRoot =
|
|
1272
|
+
const resolvedRoot = import_node_path5.default.resolve(options.root);
|
|
1273
|
+
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;
|
|
300
1274
|
return {
|
|
301
1275
|
manifestRoot,
|
|
302
|
-
consumerRoot
|
|
1276
|
+
consumerRoot,
|
|
1277
|
+
rootResolution: {
|
|
1278
|
+
rootUri: manifestRoot,
|
|
1279
|
+
protocol: "local",
|
|
1280
|
+
remote: false,
|
|
1281
|
+
readOnly: false
|
|
1282
|
+
}
|
|
303
1283
|
};
|
|
304
1284
|
}
|
|
305
|
-
const discovered = await discoverCnosAnchor(options.cwd ?? process.cwd()
|
|
1285
|
+
const discovered = await discoverCnosAnchor(options.cwd ?? process.cwd(), 3, {
|
|
1286
|
+
...options.processEnv ? { processEnv: options.processEnv } : {},
|
|
1287
|
+
...options.cacheMode ? { cacheMode: options.cacheMode } : {},
|
|
1288
|
+
...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
|
|
1289
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
1290
|
+
});
|
|
306
1291
|
return {
|
|
307
1292
|
manifestRoot: discovered.manifestRoot,
|
|
308
1293
|
consumerRoot: discovered.consumerRoot,
|
|
1294
|
+
rootResolution: discovered.rootResolution,
|
|
309
1295
|
anchorPath: discovered.anchorPath,
|
|
310
1296
|
...discovered.workspace ? { workspace: discovered.workspace } : {}
|
|
311
1297
|
};
|
|
@@ -318,10 +1304,10 @@ function interpolatePathTemplate(template, tokens) {
|
|
|
318
1304
|
}
|
|
319
1305
|
function expandHomePath(targetPath) {
|
|
320
1306
|
if (targetPath === "~") {
|
|
321
|
-
return
|
|
1307
|
+
return import_node_os3.default.homedir();
|
|
322
1308
|
}
|
|
323
1309
|
if (targetPath.startsWith("~/") || targetPath.startsWith("~\\")) {
|
|
324
|
-
return
|
|
1310
|
+
return import_node_path5.default.join(import_node_os3.default.homedir(), targetPath.slice(2));
|
|
325
1311
|
}
|
|
326
1312
|
return targetPath;
|
|
327
1313
|
}
|
|
@@ -339,7 +1325,7 @@ function stripWorkspaceTemplatePrefix(template) {
|
|
|
339
1325
|
function resolveWorkspaceScopedPath(workspaceRoot, template, tokens) {
|
|
340
1326
|
const relativeTemplate = stripWorkspaceTemplatePrefix(template);
|
|
341
1327
|
const interpolated = interpolatePathTemplate(relativeTemplate, tokens);
|
|
342
|
-
return
|
|
1328
|
+
return import_node_path5.default.resolve(workspaceRoot, interpolated);
|
|
343
1329
|
}
|
|
344
1330
|
function toPortablePath(targetPath) {
|
|
345
1331
|
return targetPath.replace(/\\/g, "/");
|
|
@@ -405,6 +1391,13 @@ var DEFAULT_NAMESPACES = {
|
|
|
405
1391
|
readonly: true
|
|
406
1392
|
}
|
|
407
1393
|
};
|
|
1394
|
+
var DEFAULT_RUNTIME_NAMESPACES = {
|
|
1395
|
+
process: {
|
|
1396
|
+
description: "Live process runtime values.",
|
|
1397
|
+
serverOnly: true,
|
|
1398
|
+
builtIn: true
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
408
1401
|
function validateResolveFrom(resolveFrom) {
|
|
409
1402
|
const validValues = ["cli.profile", "env.CNOS_PROFILE", "default"];
|
|
410
1403
|
for (const entry of resolveFrom) {
|
|
@@ -427,7 +1420,7 @@ function normalizeWorkspaceItems(items) {
|
|
|
427
1420
|
}
|
|
428
1421
|
function normalizeNamespaces(namespaces) {
|
|
429
1422
|
const normalized = Object.fromEntries(
|
|
430
|
-
Object.entries(namespaces ?? {}).map(([namespace, definition]) => [
|
|
1423
|
+
Object.entries(namespaces ?? {}).filter(([namespace]) => namespace !== "runtime").map(([namespace, definition]) => [
|
|
431
1424
|
namespace,
|
|
432
1425
|
{
|
|
433
1426
|
kind: definition.kind ?? "data",
|
|
@@ -443,6 +1436,29 @@ function normalizeNamespaces(namespaces) {
|
|
|
443
1436
|
...normalized
|
|
444
1437
|
};
|
|
445
1438
|
}
|
|
1439
|
+
function normalizeRuntimeNamespaces(namespaces) {
|
|
1440
|
+
const runtimeEntries = namespaces?.runtime ?? {};
|
|
1441
|
+
const normalized = Object.fromEntries(
|
|
1442
|
+
Object.entries(runtimeEntries).map(([namespace, definition]) => [
|
|
1443
|
+
namespace,
|
|
1444
|
+
{
|
|
1445
|
+
...definition.description?.trim() ? {
|
|
1446
|
+
description: definition.description.trim()
|
|
1447
|
+
} : {},
|
|
1448
|
+
serverOnly: definition.server_only ?? true
|
|
1449
|
+
}
|
|
1450
|
+
])
|
|
1451
|
+
);
|
|
1452
|
+
for (const namespace of Object.keys(normalized)) {
|
|
1453
|
+
if (DEFAULT_NAMESPACES[namespace] || namespace === "runtime") {
|
|
1454
|
+
throw new CnosManifestError(`Runtime namespace "${namespace}" conflicts with a built-in or reserved namespace.`);
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
return {
|
|
1458
|
+
...DEFAULT_RUNTIME_NAMESPACES,
|
|
1459
|
+
...normalized
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
446
1462
|
function normalizeVaults(vaults) {
|
|
447
1463
|
return Object.fromEntries(
|
|
448
1464
|
Object.entries(vaults ?? {}).map(([name, definition]) => {
|
|
@@ -534,6 +1550,7 @@ function normalizeManifest(manifest) {
|
|
|
534
1550
|
const defaultProfile = manifest.profiles?.default?.trim() || "base";
|
|
535
1551
|
const workspaceItems = normalizeWorkspaceItems(manifest.workspaces?.items);
|
|
536
1552
|
const resolveFrom = validateResolveFrom(manifest.profiles?.resolveFrom ?? DEFAULT_RESOLVE_FROM);
|
|
1553
|
+
const runtimeNamespaces = normalizeRuntimeNamespaces(manifest.namespaces);
|
|
537
1554
|
const filesystemValues = {
|
|
538
1555
|
root: "./",
|
|
539
1556
|
format: "yaml",
|
|
@@ -607,6 +1624,7 @@ function normalizeManifest(manifest) {
|
|
|
607
1624
|
}
|
|
608
1625
|
},
|
|
609
1626
|
namespaces: normalizeNamespaces(manifest.namespaces),
|
|
1627
|
+
runtimeNamespaces,
|
|
610
1628
|
vaults: normalizeVaults(manifest.vaults),
|
|
611
1629
|
writePolicy: {
|
|
612
1630
|
define: {
|
|
@@ -625,13 +1643,17 @@ function normalizeManifest(manifest) {
|
|
|
625
1643
|
async function loadManifest(options = {}) {
|
|
626
1644
|
const resolved = await resolveManifestRoot({
|
|
627
1645
|
...options.root ? { root: options.root } : {},
|
|
628
|
-
...options.cwd ? { cwd: options.cwd } : {}
|
|
1646
|
+
...options.cwd ? { cwd: options.cwd } : {},
|
|
1647
|
+
...options.processEnv ? { processEnv: options.processEnv } : {},
|
|
1648
|
+
...options.cacheMode ? { cacheMode: options.cacheMode } : {},
|
|
1649
|
+
...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
|
|
1650
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
629
1651
|
});
|
|
630
1652
|
const manifestRoot = resolved.manifestRoot;
|
|
631
|
-
const manifestPath =
|
|
1653
|
+
const manifestPath = import_node_path6.default.join(manifestRoot, "cnos.yml");
|
|
632
1654
|
let source;
|
|
633
1655
|
try {
|
|
634
|
-
source = await (0,
|
|
1656
|
+
source = await (0, import_promises5.readFile)(manifestPath, "utf8");
|
|
635
1657
|
} catch {
|
|
636
1658
|
throw new CnosManifestError("Unable to read CNOS manifest", manifestPath);
|
|
637
1659
|
}
|
|
@@ -641,10 +1663,11 @@ async function loadManifest(options = {}) {
|
|
|
641
1663
|
}
|
|
642
1664
|
return {
|
|
643
1665
|
manifestRoot,
|
|
644
|
-
repoRoot:
|
|
1666
|
+
repoRoot: import_node_path6.default.dirname(manifestRoot),
|
|
645
1667
|
consumerRoot: resolved.consumerRoot,
|
|
646
1668
|
...resolved.anchorPath ? { anchorPath: resolved.anchorPath } : {},
|
|
647
1669
|
...resolved.workspace ? { anchoredWorkspace: resolved.workspace } : {},
|
|
1670
|
+
rootResolution: resolved.rootResolution,
|
|
648
1671
|
manifestPath,
|
|
649
1672
|
manifest: normalizeManifest(rawManifest),
|
|
650
1673
|
rawManifest
|
|
@@ -652,12 +1675,12 @@ async function loadManifest(options = {}) {
|
|
|
652
1675
|
}
|
|
653
1676
|
|
|
654
1677
|
// ../core/src/manifest/loadWorkspaceFile.ts
|
|
655
|
-
var
|
|
656
|
-
var
|
|
1678
|
+
var import_promises6 = require("fs/promises");
|
|
1679
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
657
1680
|
async function loadWorkspaceFile(repoRoot) {
|
|
658
|
-
const workspaceFilePath =
|
|
1681
|
+
const workspaceFilePath = import_node_path7.default.join(repoRoot, ".cnos-workspace.yml");
|
|
659
1682
|
try {
|
|
660
|
-
const source = await (0,
|
|
1683
|
+
const source = await (0, import_promises6.readFile)(workspaceFilePath, "utf8");
|
|
661
1684
|
const parsed = parseYaml(source);
|
|
662
1685
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
663
1686
|
throw new CnosManifestError(".cnos-workspace.yml must be a YAML object", workspaceFilePath);
|
|
@@ -680,11 +1703,11 @@ async function loadWorkspaceFile(repoRoot) {
|
|
|
680
1703
|
}
|
|
681
1704
|
|
|
682
1705
|
// ../core/src/profiles/expandProfileChain.ts
|
|
683
|
-
var
|
|
684
|
-
var
|
|
1706
|
+
var import_promises7 = require("fs/promises");
|
|
1707
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
685
1708
|
async function fileExists(targetPath) {
|
|
686
1709
|
try {
|
|
687
|
-
await (0,
|
|
1710
|
+
await (0, import_promises7.access)(targetPath);
|
|
688
1711
|
return true;
|
|
689
1712
|
} catch {
|
|
690
1713
|
return false;
|
|
@@ -718,11 +1741,11 @@ async function loadProfileDefinition(profileName, options) {
|
|
|
718
1741
|
return normalizeProfileDefinition(profileName, void 0);
|
|
719
1742
|
}
|
|
720
1743
|
for (const workspaceRoot of [...workspaceRoots].reverse()) {
|
|
721
|
-
const profilePath =
|
|
1744
|
+
const profilePath = import_node_path8.default.join(workspaceRoot.path, "profiles", `${profileName}.yml`);
|
|
722
1745
|
if (!await fileExists(profilePath)) {
|
|
723
1746
|
continue;
|
|
724
1747
|
}
|
|
725
|
-
const document = await (0,
|
|
1748
|
+
const document = await (0, import_promises7.readFile)(profilePath, "utf8");
|
|
726
1749
|
const parsed = parseYaml(document);
|
|
727
1750
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
728
1751
|
throw new CnosManifestError("Profile definition must be a YAML object", profilePath);
|
|
@@ -730,7 +1753,7 @@ async function loadProfileDefinition(profileName, options) {
|
|
|
730
1753
|
const definition = normalizeProfileDefinition(
|
|
731
1754
|
profileName,
|
|
732
1755
|
parsed,
|
|
733
|
-
options.manifestRoot ? toPortablePath(
|
|
1756
|
+
options.manifestRoot ? toPortablePath(import_node_path8.default.relative(import_node_path8.default.dirname(options.manifestRoot), profilePath)) : toPortablePath(profilePath)
|
|
734
1757
|
);
|
|
735
1758
|
if (definition.name !== profileName) {
|
|
736
1759
|
throw new CnosManifestError(
|
|
@@ -1012,8 +2035,8 @@ function createProfileAwareResolver() {
|
|
|
1012
2035
|
}
|
|
1013
2036
|
|
|
1014
2037
|
// ../core/src/workspaces/resolveWorkspaceContext.ts
|
|
1015
|
-
var
|
|
1016
|
-
var
|
|
2038
|
+
var import_promises8 = require("fs/promises");
|
|
2039
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
1017
2040
|
|
|
1018
2041
|
// ../core/src/workspaces/expandWorkspaceChain.ts
|
|
1019
2042
|
function expandWorkspaceChain(workspaceId, items) {
|
|
@@ -1052,14 +2075,14 @@ function expandWorkspaceChain(workspaceId, items) {
|
|
|
1052
2075
|
// ../core/src/workspaces/resolveWorkspaceContext.ts
|
|
1053
2076
|
async function exists3(targetPath) {
|
|
1054
2077
|
try {
|
|
1055
|
-
await (0,
|
|
2078
|
+
await (0, import_promises8.access)(targetPath);
|
|
1056
2079
|
return true;
|
|
1057
2080
|
} catch {
|
|
1058
2081
|
return false;
|
|
1059
2082
|
}
|
|
1060
2083
|
}
|
|
1061
2084
|
async function resolveLocalWorkspaceRoot(manifestRoot, workspaceId, manifest) {
|
|
1062
|
-
const workspaceRoot =
|
|
2085
|
+
const workspaceRoot = import_node_path9.default.join(manifestRoot, "workspaces", workspaceId);
|
|
1063
2086
|
if (await exists3(workspaceRoot)) {
|
|
1064
2087
|
return workspaceRoot;
|
|
1065
2088
|
}
|
|
@@ -1067,7 +2090,7 @@ async function resolveLocalWorkspaceRoot(manifestRoot, workspaceId, manifest) {
|
|
|
1067
2090
|
([namespace, definition]) => namespace !== "value" && namespace !== "secret" && definition.kind === "data" && !definition.sensitive
|
|
1068
2091
|
).map(([namespace]) => namespace);
|
|
1069
2092
|
const legacyMarkers = ["values", "secrets", "env", "profiles", ...customDataNamespaceRoots].map(
|
|
1070
|
-
(segment) =>
|
|
2093
|
+
(segment) => import_node_path9.default.join(manifestRoot, segment)
|
|
1071
2094
|
);
|
|
1072
2095
|
if ((await Promise.all(legacyMarkers.map((marker) => exists3(marker)))).some(Boolean)) {
|
|
1073
2096
|
return manifestRoot;
|
|
@@ -1115,26 +2138,26 @@ function resolveGlobalRoot(manifest, workspaceFile, options) {
|
|
|
1115
2138
|
}
|
|
1116
2139
|
if (options.globalRoot) {
|
|
1117
2140
|
return {
|
|
1118
|
-
value:
|
|
2141
|
+
value: import_node_path9.default.resolve(expandHomePath(options.globalRoot)),
|
|
1119
2142
|
source: "cli"
|
|
1120
2143
|
};
|
|
1121
2144
|
}
|
|
1122
2145
|
if (workspaceFile?.globalRoot) {
|
|
1123
2146
|
return {
|
|
1124
|
-
value:
|
|
2147
|
+
value: import_node_path9.default.resolve(expandHomePath(workspaceFile.globalRoot)),
|
|
1125
2148
|
source: "workspace-file"
|
|
1126
2149
|
};
|
|
1127
2150
|
}
|
|
1128
2151
|
if (manifest.workspaces.global.root) {
|
|
1129
2152
|
return {
|
|
1130
|
-
value:
|
|
2153
|
+
value: import_node_path9.default.resolve(expandHomePath(manifest.workspaces.global.root)),
|
|
1131
2154
|
source: "manifest"
|
|
1132
2155
|
};
|
|
1133
2156
|
}
|
|
1134
2157
|
const cnosHome = options.processEnv?.CNOS_HOME;
|
|
1135
2158
|
if (cnosHome) {
|
|
1136
2159
|
return {
|
|
1137
|
-
value:
|
|
2160
|
+
value: import_node_path9.default.resolve(expandHomePath(cnosHome)),
|
|
1138
2161
|
source: "CNOS_HOME"
|
|
1139
2162
|
};
|
|
1140
2163
|
}
|
|
@@ -1156,7 +2179,7 @@ async function resolveWorkspaceContext(manifest, options) {
|
|
|
1156
2179
|
workspaceRoots.push({
|
|
1157
2180
|
scope: "global",
|
|
1158
2181
|
workspaceId: chainWorkspaceId,
|
|
1159
|
-
path:
|
|
2182
|
+
path: import_node_path9.default.join(globalRoot.value, "workspaces", globalWorkspaceId)
|
|
1160
2183
|
});
|
|
1161
2184
|
}
|
|
1162
2185
|
}
|
|
@@ -1279,6 +2302,10 @@ function applySchemaRules(graph, schema) {
|
|
|
1279
2302
|
}
|
|
1280
2303
|
continue;
|
|
1281
2304
|
}
|
|
2305
|
+
if (isDerivedValue(resolvedEntry.value)) {
|
|
2306
|
+
nextEntries.set(key, resolvedEntry);
|
|
2307
|
+
continue;
|
|
2308
|
+
}
|
|
1282
2309
|
const coercedValue = coerceValue(resolvedEntry.value, rule);
|
|
1283
2310
|
const nextResolvedEntry = coercedValue === resolvedEntry.value ? resolvedEntry : {
|
|
1284
2311
|
...resolvedEntry,
|
|
@@ -1348,26 +2375,26 @@ async function runPipeline(options) {
|
|
|
1348
2375
|
}
|
|
1349
2376
|
|
|
1350
2377
|
// ../core/src/secrets/auditLog.ts
|
|
1351
|
-
var
|
|
1352
|
-
var
|
|
2378
|
+
var import_promises11 = require("fs/promises");
|
|
2379
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
1353
2380
|
|
|
1354
2381
|
// ../core/src/utils/secretStore.ts
|
|
1355
|
-
var
|
|
1356
|
-
var
|
|
1357
|
-
var
|
|
2382
|
+
var import_node_crypto2 = require("crypto");
|
|
2383
|
+
var import_promises10 = require("fs/promises");
|
|
2384
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
1358
2385
|
|
|
1359
2386
|
// ../core/src/secrets/sessionStore.ts
|
|
1360
|
-
var
|
|
1361
|
-
var
|
|
2387
|
+
var import_promises9 = require("fs/promises");
|
|
2388
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
1362
2389
|
function buildSessionRoot(processEnv = process.env) {
|
|
1363
|
-
return
|
|
2390
|
+
return import_node_path10.default.join(import_node_path10.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets")), "sessions");
|
|
1364
2391
|
}
|
|
1365
2392
|
function buildSessionPath(vault, processEnv) {
|
|
1366
|
-
return
|
|
2393
|
+
return import_node_path10.default.join(buildSessionRoot(processEnv), `${vault}.json`);
|
|
1367
2394
|
}
|
|
1368
2395
|
async function readVaultSessionKey(vault, processEnv) {
|
|
1369
2396
|
try {
|
|
1370
|
-
const source = await (0,
|
|
2397
|
+
const source = await (0, import_promises9.readFile)(buildSessionPath(vault, processEnv), "utf8");
|
|
1371
2398
|
const document = JSON.parse(source);
|
|
1372
2399
|
if (document.version !== 1 || typeof document.derivedKey !== "string") {
|
|
1373
2400
|
return void 0;
|
|
@@ -1396,7 +2423,7 @@ function isSecretReference(value) {
|
|
|
1396
2423
|
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));
|
|
1397
2424
|
}
|
|
1398
2425
|
function resolveSecretStoreRoot(processEnv = process.env) {
|
|
1399
|
-
return
|
|
2426
|
+
return import_node_path11.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
|
|
1400
2427
|
}
|
|
1401
2428
|
function normalizeVaultToken(vault = "default") {
|
|
1402
2429
|
return vault.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
|
|
@@ -1425,19 +2452,19 @@ function resolveVaultSessionKey(vault = "default", processEnv = process.env) {
|
|
|
1425
2452
|
}
|
|
1426
2453
|
}
|
|
1427
2454
|
function deriveVaultKey(passphrase, salt, iterations = PBKDF2_ITERATIONS) {
|
|
1428
|
-
return (0,
|
|
2455
|
+
return (0, import_node_crypto2.pbkdf2Sync)(passphrase, salt, iterations, KEY_LENGTH, "sha512");
|
|
1429
2456
|
}
|
|
1430
2457
|
function buildMetaPath(storeRoot, vault = "default") {
|
|
1431
|
-
return
|
|
2458
|
+
return import_node_path11.default.join(storeRoot, "vaults", vault, META_FILENAME);
|
|
1432
2459
|
}
|
|
1433
2460
|
function buildKeystorePath(storeRoot, vault = "default") {
|
|
1434
|
-
return
|
|
2461
|
+
return import_node_path11.default.join(storeRoot, "vaults", vault, KEYSTORE_FILENAME);
|
|
1435
2462
|
}
|
|
1436
2463
|
function buildLegacyVaultFile(storeRoot, vault = "default") {
|
|
1437
|
-
return
|
|
2464
|
+
return import_node_path11.default.join(storeRoot, "vaults", `${vault}.json`);
|
|
1438
2465
|
}
|
|
1439
2466
|
function buildLegacyVaultStoreRoot(storeRoot, vault = "default") {
|
|
1440
|
-
return
|
|
2467
|
+
return import_node_path11.default.join(storeRoot, "vaults", vault, "store");
|
|
1441
2468
|
}
|
|
1442
2469
|
function assertVaultMetadata(value, filePath) {
|
|
1443
2470
|
if (!isObject(value)) {
|
|
@@ -1450,7 +2477,7 @@ function assertVaultMetadata(value, filePath) {
|
|
|
1450
2477
|
}
|
|
1451
2478
|
async function exists4(targetPath) {
|
|
1452
2479
|
try {
|
|
1453
|
-
await (0,
|
|
2480
|
+
await (0, import_promises10.stat)(targetPath);
|
|
1454
2481
|
return true;
|
|
1455
2482
|
} catch {
|
|
1456
2483
|
return false;
|
|
@@ -1477,8 +2504,8 @@ async function assertNoLegacyVaultFormat(storeRoot, vault = "default") {
|
|
|
1477
2504
|
);
|
|
1478
2505
|
}
|
|
1479
2506
|
function encryptPayload(payload, key) {
|
|
1480
|
-
const iv = (0,
|
|
1481
|
-
const cipher = (0,
|
|
2507
|
+
const iv = (0, import_node_crypto2.randomBytes)(IV_LENGTH);
|
|
2508
|
+
const cipher = (0, import_node_crypto2.createCipheriv)("aes-256-gcm", key, iv);
|
|
1482
2509
|
const plaintext = Buffer.from(JSON.stringify(payload), "utf8");
|
|
1483
2510
|
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
1484
2511
|
const tag = cipher.getAuthTag();
|
|
@@ -1503,7 +2530,7 @@ function decryptPayload(buffer, key) {
|
|
|
1503
2530
|
const iv = buffer.subarray(ivOffset, tagOffset);
|
|
1504
2531
|
const tag = buffer.subarray(tagOffset, cipherOffset);
|
|
1505
2532
|
const ciphertext = buffer.subarray(cipherOffset);
|
|
1506
|
-
const decipher = (0,
|
|
2533
|
+
const decipher = (0, import_node_crypto2.createDecipheriv)("aes-256-gcm", key, iv);
|
|
1507
2534
|
decipher.setAuthTag(tag);
|
|
1508
2535
|
try {
|
|
1509
2536
|
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
@@ -1534,15 +2561,15 @@ function buildInitialPayload() {
|
|
|
1534
2561
|
async function writeVaultFiles(storeRoot, vault, meta, payload, key) {
|
|
1535
2562
|
const metaPath = buildMetaPath(storeRoot, vault);
|
|
1536
2563
|
const keystorePath = buildKeystorePath(storeRoot, vault);
|
|
1537
|
-
await (0,
|
|
1538
|
-
await (0,
|
|
1539
|
-
await (0,
|
|
2564
|
+
await (0, import_promises10.mkdir)(import_node_path11.default.dirname(metaPath), { recursive: true });
|
|
2565
|
+
await (0, import_promises10.writeFile)(metaPath, stringifyYaml(meta), "utf8");
|
|
2566
|
+
await (0, import_promises10.writeFile)(keystorePath, encryptPayload(payload, key));
|
|
1540
2567
|
}
|
|
1541
2568
|
async function readVaultMetadata(storeRoot, vault = "default") {
|
|
1542
2569
|
await assertNoLegacyVaultFormat(storeRoot, vault);
|
|
1543
2570
|
const metaPath = buildMetaPath(storeRoot, vault);
|
|
1544
2571
|
try {
|
|
1545
|
-
const source = await (0,
|
|
2572
|
+
const source = await (0, import_promises10.readFile)(metaPath, "utf8");
|
|
1546
2573
|
return assertVaultMetadata(parseYaml(source), metaPath);
|
|
1547
2574
|
} catch (error) {
|
|
1548
2575
|
if (error.code === "ENOENT") {
|
|
@@ -1554,7 +2581,7 @@ async function readVaultMetadata(storeRoot, vault = "default") {
|
|
|
1554
2581
|
async function createSecretVault(storeRoot, vault, passphrase) {
|
|
1555
2582
|
const normalizedVault = vault.trim() || "default";
|
|
1556
2583
|
await assertNoLegacyVaultFormat(storeRoot, normalizedVault);
|
|
1557
|
-
const salt = (0,
|
|
2584
|
+
const salt = (0, import_node_crypto2.randomBytes)(SALT_LENGTH);
|
|
1558
2585
|
const key = deriveVaultKey(passphrase, salt, PBKDF2_ITERATIONS);
|
|
1559
2586
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1560
2587
|
const meta = {
|
|
@@ -1633,7 +2660,7 @@ async function loadVaultPayload(storeRoot, vault, auth) {
|
|
|
1633
2660
|
if (!key) {
|
|
1634
2661
|
throw new CnosAuthenticationError(`Vault "${vault}" requires authentication before access.`);
|
|
1635
2662
|
}
|
|
1636
|
-
const buffer = await (0,
|
|
2663
|
+
const buffer = await (0, import_promises10.readFile)(buildKeystorePath(storeRoot, vault));
|
|
1637
2664
|
return {
|
|
1638
2665
|
meta,
|
|
1639
2666
|
payload: decryptPayload(buffer, key),
|
|
@@ -1708,9 +2735,9 @@ function resolveVaultDefinition(vaults, vault = "default") {
|
|
|
1708
2735
|
|
|
1709
2736
|
// ../core/src/secrets/auditLog.ts
|
|
1710
2737
|
async function appendAuditEvent(event, processEnv = process.env) {
|
|
1711
|
-
const auditFile = processEnv.CNOS_AUDIT_FILE ??
|
|
1712
|
-
await (0,
|
|
1713
|
-
await (0,
|
|
2738
|
+
const auditFile = processEnv.CNOS_AUDIT_FILE ?? import_node_path12.default.join(resolveSecretStoreRoot(processEnv), "audit", "access.log");
|
|
2739
|
+
await (0, import_promises11.mkdir)(import_node_path12.default.dirname(auditFile), { recursive: true });
|
|
2740
|
+
await (0, import_promises11.appendFile)(
|
|
1714
2741
|
auditFile,
|
|
1715
2742
|
`${JSON.stringify({
|
|
1716
2743
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -2068,7 +3095,7 @@ function setNestedValue(target, pathSegments, value) {
|
|
|
2068
3095
|
target[head] = nextTarget;
|
|
2069
3096
|
setNestedValue(nextTarget, tail, value);
|
|
2070
3097
|
}
|
|
2071
|
-
function toNamespaceObject(graph, namespace) {
|
|
3098
|
+
function toNamespaceObject(graph, namespace, readValueForKey = (key) => graph.entries.get(key)?.value) {
|
|
2072
3099
|
const output = {};
|
|
2073
3100
|
const resolvedEntries = Array.from(graph.entries.values()).sort(
|
|
2074
3101
|
(left, right) => left.key.localeCompare(right.key)
|
|
@@ -2078,7 +3105,11 @@ function toNamespaceObject(graph, namespace) {
|
|
|
2078
3105
|
continue;
|
|
2079
3106
|
}
|
|
2080
3107
|
const valuePath = namespace ? stripNamespace(entry.key) : entry.key;
|
|
2081
|
-
|
|
3108
|
+
const value = readValueForKey(entry.key);
|
|
3109
|
+
if (value === void 0) {
|
|
3110
|
+
continue;
|
|
3111
|
+
}
|
|
3112
|
+
setNestedValue(output, valuePath.split("."), value);
|
|
2082
3113
|
}
|
|
2083
3114
|
return output;
|
|
2084
3115
|
}
|
|
@@ -2088,12 +3119,6 @@ function readValue(graph, key) {
|
|
|
2088
3119
|
return graph.entries.get(key)?.value;
|
|
2089
3120
|
}
|
|
2090
3121
|
|
|
2091
|
-
// ../core/src/runtime/readOr.ts
|
|
2092
|
-
function readOrValue(graph, key, fallback) {
|
|
2093
|
-
const value = readValue(graph, key);
|
|
2094
|
-
return value === void 0 ? fallback : value;
|
|
2095
|
-
}
|
|
2096
|
-
|
|
2097
3122
|
// ../core/src/runtime/require.ts
|
|
2098
3123
|
function requireValue(graph, key) {
|
|
2099
3124
|
const value = readValue(graph, key);
|
|
@@ -2103,8 +3128,38 @@ function requireValue(graph, key) {
|
|
|
2103
3128
|
return value;
|
|
2104
3129
|
}
|
|
2105
3130
|
|
|
3131
|
+
// ../core/src/runtime/runtimeProviders.ts
|
|
3132
|
+
function createDefaultRuntimeProviders(manifest, processEnv) {
|
|
3133
|
+
const providers = /* @__PURE__ */ new Map();
|
|
3134
|
+
if (manifest.runtimeNamespaces.process) {
|
|
3135
|
+
providers.set("process", (key) => {
|
|
3136
|
+
const segments = key.split(".");
|
|
3137
|
+
if (segments[0] === "env") {
|
|
3138
|
+
return processEnv[segments.slice(1).join(".")];
|
|
3139
|
+
}
|
|
3140
|
+
if (key === "cwd") {
|
|
3141
|
+
return process.cwd();
|
|
3142
|
+
}
|
|
3143
|
+
if (key === "platform") {
|
|
3144
|
+
return process.platform;
|
|
3145
|
+
}
|
|
3146
|
+
if (key === "arch") {
|
|
3147
|
+
return process.arch;
|
|
3148
|
+
}
|
|
3149
|
+
if (key === "pid") {
|
|
3150
|
+
return process.pid;
|
|
3151
|
+
}
|
|
3152
|
+
if (key === "node.version") {
|
|
3153
|
+
return process.version;
|
|
3154
|
+
}
|
|
3155
|
+
return void 0;
|
|
3156
|
+
});
|
|
3157
|
+
}
|
|
3158
|
+
return providers;
|
|
3159
|
+
}
|
|
3160
|
+
|
|
2106
3161
|
// ../core/src/runtime/toServerProjection.ts
|
|
2107
|
-
var
|
|
3162
|
+
var import_node_crypto3 = require("crypto");
|
|
2108
3163
|
function stableSortObject(value) {
|
|
2109
3164
|
return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)));
|
|
2110
3165
|
}
|
|
@@ -2113,12 +3168,14 @@ function stripValuePrefix(key) {
|
|
|
2113
3168
|
}
|
|
2114
3169
|
function configHash(values) {
|
|
2115
3170
|
const serialized = JSON.stringify(stableSortObject(values));
|
|
2116
|
-
return (0,
|
|
3171
|
+
return (0, import_node_crypto3.createHash)("sha256").update(serialized).digest("hex");
|
|
2117
3172
|
}
|
|
2118
|
-
function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev") {
|
|
3173
|
+
function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev", helpers = {}) {
|
|
2119
3174
|
const values = {};
|
|
3175
|
+
const derived = {};
|
|
2120
3176
|
const secretRefs = {};
|
|
2121
3177
|
const namespaces = /* @__PURE__ */ new Set();
|
|
3178
|
+
const runtimeNamespaces = /* @__PURE__ */ new Set();
|
|
2122
3179
|
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));
|
|
2123
3180
|
for (const [key, entry] of graph.entries) {
|
|
2124
3181
|
if (entry.namespace === "secret" && isSecretReference(entry.value)) {
|
|
@@ -2130,12 +3187,33 @@ function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev") {
|
|
|
2130
3187
|
continue;
|
|
2131
3188
|
}
|
|
2132
3189
|
if (entry.namespace === "value") {
|
|
2133
|
-
|
|
3190
|
+
if (helpers.isRuntimeDependent?.(key)) {
|
|
3191
|
+
const formula = helpers.toServerFormula?.(key);
|
|
3192
|
+
if (formula) {
|
|
3193
|
+
derived[stripValuePrefix(key)] = formula;
|
|
3194
|
+
for (const ref of formula.runtimeRefs) {
|
|
3195
|
+
runtimeNamespaces.add(ref.split(".")[0] ?? "");
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
continue;
|
|
3199
|
+
}
|
|
3200
|
+
const value = helpers.read ? helpers.read(key) : entry.value;
|
|
3201
|
+
values[stripValuePrefix(key)] = value;
|
|
2134
3202
|
continue;
|
|
2135
3203
|
}
|
|
2136
3204
|
const namespaceDefinition = manifest.namespaces[entry.namespace];
|
|
2137
3205
|
if (namespaceDefinition && namespaceDefinition.kind === "data" && !namespaceDefinition.sensitive && entry.namespace !== "public") {
|
|
2138
|
-
|
|
3206
|
+
if (helpers.isRuntimeDependent?.(key)) {
|
|
3207
|
+
const formula = helpers.toServerFormula?.(key);
|
|
3208
|
+
if (formula) {
|
|
3209
|
+
derived[key] = formula;
|
|
3210
|
+
for (const ref of formula.runtimeRefs) {
|
|
3211
|
+
runtimeNamespaces.add(ref.split(".")[0] ?? "");
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
continue;
|
|
3215
|
+
}
|
|
3216
|
+
values[key] = helpers.read ? helpers.read(key) : entry.value;
|
|
2139
3217
|
namespaces.add(entry.namespace);
|
|
2140
3218
|
}
|
|
2141
3219
|
}
|
|
@@ -2146,8 +3224,10 @@ function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev") {
|
|
|
2146
3224
|
resolvedAt: graph.resolvedAt,
|
|
2147
3225
|
configHash: configHash(values),
|
|
2148
3226
|
values: stableSortObject(values),
|
|
3227
|
+
derived: stableSortObject(derived),
|
|
2149
3228
|
secretRefs: stableSortObject(secretRefs),
|
|
2150
3229
|
publicKeys,
|
|
3230
|
+
runtimeNamespaces: Array.from(runtimeNamespaces).sort((left, right) => left.localeCompare(right)),
|
|
2151
3231
|
meta: {
|
|
2152
3232
|
workspace: graph.workspace.workspaceId,
|
|
2153
3233
|
profile: graph.profile,
|
|
@@ -2170,7 +3250,7 @@ function normalizeEnvValue(value) {
|
|
|
2170
3250
|
}
|
|
2171
3251
|
return JSON.stringify(value);
|
|
2172
3252
|
}
|
|
2173
|
-
function toEnv(graph, manifest, options = {}) {
|
|
3253
|
+
function toEnv(graph, manifest, options = {}, helpers = {}) {
|
|
2174
3254
|
const includeSecrets = options.includeSecrets ?? true;
|
|
2175
3255
|
const output = {};
|
|
2176
3256
|
const mappedEntries = Object.entries(manifest.envMapping.explicit).sort(
|
|
@@ -2191,7 +3271,11 @@ function toEnv(graph, manifest, options = {}) {
|
|
|
2191
3271
|
if (isSecretReference(entry.value)) {
|
|
2192
3272
|
continue;
|
|
2193
3273
|
}
|
|
2194
|
-
|
|
3274
|
+
const value = helpers.read ? helpers.read(logicalKey) : entry.value;
|
|
3275
|
+
if (value === void 0) {
|
|
3276
|
+
continue;
|
|
3277
|
+
}
|
|
3278
|
+
output[envVar] = normalizeEnvValue(value);
|
|
2195
3279
|
}
|
|
2196
3280
|
return output;
|
|
2197
3281
|
}
|
|
@@ -2228,20 +3312,43 @@ function resolvePublicPrefix(manifest, options) {
|
|
|
2228
3312
|
}
|
|
2229
3313
|
return manifest.public.frameworks[options.framework] ?? "";
|
|
2230
3314
|
}
|
|
2231
|
-
function toPublicEnv(graph, manifest, options = {}) {
|
|
3315
|
+
function toPublicEnv(graph, manifest, options = {}, helpers = {}) {
|
|
2232
3316
|
const prefix = resolvePublicPrefix(manifest, options);
|
|
2233
3317
|
const output = {};
|
|
2234
3318
|
const promotions = Array.from(graph.entries.values()).filter((entry) => entry.namespace === "public").sort((left, right) => left.key.localeCompare(right.key));
|
|
2235
3319
|
for (const resolved of promotions) {
|
|
3320
|
+
if (helpers.isRuntimeDependent?.(resolved.key)) {
|
|
3321
|
+
const value2 = helpers.read?.(resolved.key);
|
|
3322
|
+
if (value2 === void 0) {
|
|
3323
|
+
throw new CnosManifestError(`Cannot build public output for ${resolved.key} because it depends on runtime-only values.`);
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
2236
3326
|
const baseEnvVar = fallbackPublicEnvVar(stripNamespace(resolved.key));
|
|
2237
3327
|
const envVar = prefix && !baseEnvVar.startsWith(prefix) ? `${prefix}${baseEnvVar}` : baseEnvVar;
|
|
2238
|
-
|
|
3328
|
+
const value = helpers.read ? helpers.read(resolved.key) : resolved.value;
|
|
3329
|
+
if (value === void 0) {
|
|
3330
|
+
continue;
|
|
3331
|
+
}
|
|
3332
|
+
output[envVar] = normalizeEnvValue2(value);
|
|
2239
3333
|
}
|
|
2240
3334
|
return output;
|
|
2241
3335
|
}
|
|
2242
3336
|
|
|
2243
3337
|
// ../core/src/orchestrator/runtime.ts
|
|
2244
3338
|
function createRuntime(manifest, graph, plugins = [], secretCache, processEnv = process.env, cnosVersion = "0.0.0-dev") {
|
|
3339
|
+
const runtimeProviders = createDefaultRuntimeProviders(manifest, processEnv);
|
|
3340
|
+
const derivedSupport = createDerivedRuntimeSupport(graph, manifest, runtimeProviders);
|
|
3341
|
+
function resolveProjectedSourceKey(key) {
|
|
3342
|
+
if (!key.startsWith("public.")) {
|
|
3343
|
+
return key;
|
|
3344
|
+
}
|
|
3345
|
+
const promotedFrom = graph.entries.get(key)?.winner.metadata?.promotedFrom;
|
|
3346
|
+
if (typeof promotedFrom === "string") {
|
|
3347
|
+
return promotedFrom;
|
|
3348
|
+
}
|
|
3349
|
+
const fallback = `value.${key.slice("public.".length)}`;
|
|
3350
|
+
return graph.entries.has(fallback) ? fallback : key;
|
|
3351
|
+
}
|
|
2245
3352
|
async function refreshSecretEntry(key) {
|
|
2246
3353
|
const entry = graph.entries.get(key);
|
|
2247
3354
|
if (!entry || entry.namespace !== "secret" || !isSecretReference(entry.value)) {
|
|
@@ -2273,6 +3380,19 @@ function createRuntime(manifest, graph, plugins = [], secretCache, processEnv =
|
|
|
2273
3380
|
}
|
|
2274
3381
|
}
|
|
2275
3382
|
function readLogicalKey(key) {
|
|
3383
|
+
const resolved = derivedSupport.read(key, (ref) => {
|
|
3384
|
+
const entry2 = graph.entries.get(ref);
|
|
3385
|
+
if (!entry2) {
|
|
3386
|
+
return void 0;
|
|
3387
|
+
}
|
|
3388
|
+
if (!secretCache) {
|
|
3389
|
+
return entry2.value;
|
|
3390
|
+
}
|
|
3391
|
+
return resolveSecretEntryValue(ref, entry2.value, secretCache);
|
|
3392
|
+
});
|
|
3393
|
+
if (resolved !== void 0 || graph.entries.has(key) || manifest.runtimeNamespaces[key.split(".")[0] ?? ""]) {
|
|
3394
|
+
return resolved;
|
|
3395
|
+
}
|
|
2276
3396
|
const entry = graph.entries.get(key);
|
|
2277
3397
|
if (!entry) {
|
|
2278
3398
|
return void 0;
|
|
@@ -2297,34 +3417,64 @@ function createRuntime(manifest, graph, plugins = [], secretCache, processEnv =
|
|
|
2297
3417
|
return value;
|
|
2298
3418
|
},
|
|
2299
3419
|
readOr(key, fallback) {
|
|
2300
|
-
|
|
3420
|
+
const value = readLogicalKey(key);
|
|
3421
|
+
return value === void 0 ? fallback : value;
|
|
2301
3422
|
},
|
|
2302
|
-
value(
|
|
2303
|
-
return readLogicalKey(toLogicalKey("value",
|
|
3423
|
+
value(path16) {
|
|
3424
|
+
return readLogicalKey(toLogicalKey("value", path16));
|
|
2304
3425
|
},
|
|
2305
|
-
secret(
|
|
2306
|
-
return readLogicalKey(toLogicalKey("secret",
|
|
3426
|
+
secret(path16) {
|
|
3427
|
+
return readLogicalKey(toLogicalKey("secret", path16));
|
|
2307
3428
|
},
|
|
2308
|
-
meta(
|
|
2309
|
-
return readLogicalKey(toLogicalKey("meta",
|
|
3429
|
+
meta(path16) {
|
|
3430
|
+
return readLogicalKey(toLogicalKey("meta", path16));
|
|
2310
3431
|
},
|
|
2311
3432
|
inspect(key) {
|
|
2312
|
-
return inspectValue(graph, key
|
|
3433
|
+
return inspectValue(graph, key, {
|
|
3434
|
+
read: (ref) => readLogicalKey(ref),
|
|
3435
|
+
describeDerived: (ref) => derivedSupport.describe(ref, (candidate) => {
|
|
3436
|
+
const entry = graph.entries.get(candidate);
|
|
3437
|
+
if (!entry) {
|
|
3438
|
+
return void 0;
|
|
3439
|
+
}
|
|
3440
|
+
if (!secretCache) {
|
|
3441
|
+
return entry.value;
|
|
3442
|
+
}
|
|
3443
|
+
return resolveSecretEntryValue(candidate, entry.value, secretCache);
|
|
3444
|
+
})
|
|
3445
|
+
});
|
|
2313
3446
|
},
|
|
2314
3447
|
toObject() {
|
|
2315
|
-
return toNamespaceObject(graph);
|
|
3448
|
+
return toNamespaceObject(graph, void 0, (key) => readLogicalKey(key));
|
|
2316
3449
|
},
|
|
2317
3450
|
toNamespace(namespace) {
|
|
2318
|
-
return toNamespaceObject(graph, namespace);
|
|
3451
|
+
return toNamespaceObject(graph, namespace, (key) => readLogicalKey(key));
|
|
2319
3452
|
},
|
|
2320
3453
|
toEnv(options) {
|
|
2321
|
-
return toEnv(graph, manifest, options
|
|
3454
|
+
return toEnv(graph, manifest, options, {
|
|
3455
|
+
read: (key) => readLogicalKey(key),
|
|
3456
|
+
isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(key)
|
|
3457
|
+
});
|
|
2322
3458
|
},
|
|
2323
3459
|
toPublicEnv(options) {
|
|
2324
|
-
return toPublicEnv(graph, manifest, options
|
|
3460
|
+
return toPublicEnv(graph, manifest, options, {
|
|
3461
|
+
read: (key) => derivedSupport.toConcreteValue(
|
|
3462
|
+
resolveProjectedSourceKey(key),
|
|
3463
|
+
(candidate) => readLogicalKey(candidate),
|
|
3464
|
+
"public"
|
|
3465
|
+
),
|
|
3466
|
+
isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(resolveProjectedSourceKey(key))
|
|
3467
|
+
});
|
|
2325
3468
|
},
|
|
2326
3469
|
toServerProjection() {
|
|
2327
|
-
return toServerProjection(graph, manifest, cnosVersion
|
|
3470
|
+
return toServerProjection(graph, manifest, cnosVersion, {
|
|
3471
|
+
read: (key) => derivedSupport.toConcreteValue(key, (candidate) => readLogicalKey(candidate), "server"),
|
|
3472
|
+
isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(key),
|
|
3473
|
+
toServerFormula: (key) => derivedSupport.toServerFormula(key)
|
|
3474
|
+
});
|
|
3475
|
+
},
|
|
3476
|
+
registerRuntimeProvider(namespace, provider) {
|
|
3477
|
+
registerRuntimeProvider(manifest, runtimeProviders, namespace, provider);
|
|
2328
3478
|
},
|
|
2329
3479
|
async refreshSecrets() {
|
|
2330
3480
|
await refreshAllSecrets();
|
|
@@ -2431,7 +3581,11 @@ function appendMetaEntries(graph, cnosVersion) {
|
|
|
2431
3581
|
async function createCnos(options = {}) {
|
|
2432
3582
|
const loadedManifest = await loadManifest({
|
|
2433
3583
|
...options.root ? { root: options.root } : {},
|
|
2434
|
-
...options.cwd ? { cwd: options.cwd } : {}
|
|
3584
|
+
...options.cwd ? { cwd: options.cwd } : {},
|
|
3585
|
+
...options.processEnv ? { processEnv: options.processEnv } : {},
|
|
3586
|
+
...options.cacheMode ? { cacheMode: options.cacheMode } : {},
|
|
3587
|
+
...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
|
|
3588
|
+
...options.forceRefresh ? { forceRefresh: true } : {}
|
|
2435
3589
|
});
|
|
2436
3590
|
for (const key of loadedManifest.manifest.public.promote) {
|
|
2437
3591
|
ensureProjectionAllowed(loadedManifest.manifest, key, "public");
|
|
@@ -2492,8 +3646,8 @@ async function createCnos(options = {}) {
|
|
|
2492
3646
|
}
|
|
2493
3647
|
|
|
2494
3648
|
// ../core/src/runtime/dump.ts
|
|
2495
|
-
var
|
|
2496
|
-
var
|
|
3649
|
+
var import_promises12 = require("fs/promises");
|
|
3650
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
2497
3651
|
|
|
2498
3652
|
// ../core/src/utils/envNaming.ts
|
|
2499
3653
|
function normalizeMappingConfig(config = {}) {
|
|
@@ -2502,8 +3656,8 @@ function normalizeMappingConfig(config = {}) {
|
|
|
2502
3656
|
explicit: config.explicit ?? {}
|
|
2503
3657
|
};
|
|
2504
3658
|
}
|
|
2505
|
-
function fromScreamingSnake(
|
|
2506
|
-
return
|
|
3659
|
+
function fromScreamingSnake(path16) {
|
|
3660
|
+
return path16.split("_").map((segment) => segment.trim().toLowerCase()).filter(Boolean).join(".");
|
|
2507
3661
|
}
|
|
2508
3662
|
function envVarToLogicalKey(envVar, config = {}) {
|
|
2509
3663
|
const normalized = normalizeMappingConfig(config);
|
|
@@ -2530,7 +3684,7 @@ function envVarToLogicalKey(envVar, config = {}) {
|
|
|
2530
3684
|
// package.json
|
|
2531
3685
|
var package_default = {
|
|
2532
3686
|
name: "@kitsy/cnos",
|
|
2533
|
-
version: "1.
|
|
3687
|
+
version: "1.7.0",
|
|
2534
3688
|
description: "Batteries-included CNOS runtime package wired with the official plugins.",
|
|
2535
3689
|
type: "module",
|
|
2536
3690
|
main: "./dist/index.cjs",
|
|
@@ -2729,8 +3883,8 @@ function createCliArgsPlugin() {
|
|
|
2729
3883
|
}
|
|
2730
3884
|
|
|
2731
3885
|
// ../../plugins/dotenv/src/index.ts
|
|
2732
|
-
var
|
|
2733
|
-
var
|
|
3886
|
+
var import_promises13 = require("fs/promises");
|
|
3887
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
2734
3888
|
var DOTENV_PLUGIN_ID = "@kitsy/cnos/plugins/dotenv";
|
|
2735
3889
|
function parseDoubleQuoted(value) {
|
|
2736
3890
|
return value.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
@@ -2787,7 +3941,7 @@ function dotenvEntriesFromObject(values, mapping = {}, originFile, workspaceId =
|
|
|
2787
3941
|
}
|
|
2788
3942
|
async function readIfPresent(filePath) {
|
|
2789
3943
|
try {
|
|
2790
|
-
return await (0,
|
|
3944
|
+
return await (0, import_promises13.readFile)(filePath, "utf8");
|
|
2791
3945
|
} catch {
|
|
2792
3946
|
return void 0;
|
|
2793
3947
|
}
|
|
@@ -2806,7 +3960,7 @@ function createDotenvPlugin() {
|
|
|
2806
3960
|
workspace: workspaceRoot.workspaceId
|
|
2807
3961
|
});
|
|
2808
3962
|
for (const fileName of fileNames) {
|
|
2809
|
-
const absolutePath =
|
|
3963
|
+
const absolutePath = import_node_path14.default.join(envRoot, fileName);
|
|
2810
3964
|
const document = await readIfPresent(absolutePath);
|
|
2811
3965
|
if (!document) {
|
|
2812
3966
|
continue;
|
|
@@ -2815,7 +3969,7 @@ function createDotenvPlugin() {
|
|
|
2815
3969
|
...dotenvEntriesFromObject(
|
|
2816
3970
|
parseDotenv(document),
|
|
2817
3971
|
config.envMapping,
|
|
2818
|
-
toPortablePath(
|
|
3972
|
+
toPortablePath(import_node_path14.default.relative(import_node_path14.default.dirname(context.manifestRoot), absolutePath)),
|
|
2819
3973
|
workspaceRoot.workspaceId
|
|
2820
3974
|
)
|
|
2821
3975
|
);
|
|
@@ -2853,16 +4007,16 @@ function createPublicEnvExportPlugin() {
|
|
|
2853
4007
|
}
|
|
2854
4008
|
|
|
2855
4009
|
// ../../plugins/filesystem/src/filesystemSecretsReader.ts
|
|
2856
|
-
var
|
|
4010
|
+
var import_promises15 = require("fs/promises");
|
|
2857
4011
|
|
|
2858
4012
|
// ../../plugins/filesystem/src/helpers.ts
|
|
2859
|
-
var
|
|
2860
|
-
var
|
|
4013
|
+
var import_promises14 = require("fs/promises");
|
|
4014
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
2861
4015
|
var YAML_EXTENSIONS = /* @__PURE__ */ new Set([".yml", ".yaml"]);
|
|
2862
4016
|
var FILESYSTEM_PLUGIN_ID = "@kitsy/cnos/plugins/filesystem";
|
|
2863
4017
|
async function existsDirectory(targetPath) {
|
|
2864
4018
|
try {
|
|
2865
|
-
const stat2 = await (0,
|
|
4019
|
+
const stat2 = await (0, import_promises14.readdir)(targetPath);
|
|
2866
4020
|
void stat2;
|
|
2867
4021
|
return true;
|
|
2868
4022
|
} catch {
|
|
@@ -2870,15 +4024,15 @@ async function existsDirectory(targetPath) {
|
|
|
2870
4024
|
}
|
|
2871
4025
|
}
|
|
2872
4026
|
async function collectYamlFiles(root) {
|
|
2873
|
-
const entries = await (0,
|
|
4027
|
+
const entries = await (0, import_promises14.readdir)(root, { withFileTypes: true });
|
|
2874
4028
|
const results = [];
|
|
2875
4029
|
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
2876
|
-
const absolutePath =
|
|
4030
|
+
const absolutePath = import_node_path15.default.join(root, entry.name);
|
|
2877
4031
|
if (entry.isDirectory()) {
|
|
2878
4032
|
results.push(...await collectYamlFiles(absolutePath));
|
|
2879
4033
|
continue;
|
|
2880
4034
|
}
|
|
2881
|
-
if (entry.isFile() && YAML_EXTENSIONS.has(
|
|
4035
|
+
if (entry.isFile() && YAML_EXTENSIONS.has(import_node_path15.default.extname(entry.name).toLowerCase())) {
|
|
2882
4036
|
results.push(absolutePath);
|
|
2883
4037
|
}
|
|
2884
4038
|
}
|
|
@@ -2886,16 +4040,16 @@ async function collectYamlFiles(root) {
|
|
|
2886
4040
|
}
|
|
2887
4041
|
async function collectFilesystemLayerFiles(manifestRoot, workspaceRoots, sourceRoot, activeLayers) {
|
|
2888
4042
|
const files = [];
|
|
2889
|
-
const repoRoot =
|
|
4043
|
+
const repoRoot = import_node_path15.default.dirname(manifestRoot);
|
|
2890
4044
|
for (const workspaceRoot of workspaceRoots) {
|
|
2891
|
-
const resolvedRoot =
|
|
4045
|
+
const resolvedRoot = import_node_path15.default.resolve(workspaceRoot.path, sourceRoot);
|
|
2892
4046
|
for (const layer of activeLayers) {
|
|
2893
|
-
const layerRoot =
|
|
4047
|
+
const layerRoot = import_node_path15.default.join(resolvedRoot, layer);
|
|
2894
4048
|
if (!await existsDirectory(layerRoot)) {
|
|
2895
4049
|
continue;
|
|
2896
4050
|
}
|
|
2897
4051
|
for (const absolutePath of await collectYamlFiles(layerRoot)) {
|
|
2898
|
-
const relativePath =
|
|
4052
|
+
const relativePath = import_node_path15.default.relative(repoRoot, absolutePath);
|
|
2899
4053
|
files.push({
|
|
2900
4054
|
absolutePath,
|
|
2901
4055
|
relativePath: toPortablePath(relativePath.startsWith("..") ? absolutePath : relativePath),
|
|
@@ -2915,7 +4069,7 @@ function assertObjectDocument(value, filePath) {
|
|
|
2915
4069
|
function flattenConfigObject(value, options = {}, prefix = "") {
|
|
2916
4070
|
return Object.entries(value).reduce((accumulator, [key, nestedValue]) => {
|
|
2917
4071
|
const nextKey = prefix ? `${prefix}.${key}` : key;
|
|
2918
|
-
if (nestedValue && typeof nestedValue === "object" && !Array.isArray(nestedValue) && !options.stopAtLeaf?.(nestedValue)) {
|
|
4072
|
+
if (nestedValue && typeof nestedValue === "object" && !Array.isArray(nestedValue) && !isDerivedValue(nestedValue) && !options.stopAtLeaf?.(nestedValue)) {
|
|
2919
4073
|
Object.assign(
|
|
2920
4074
|
accumulator,
|
|
2921
4075
|
flattenConfigObject(nestedValue, options, nextKey)
|
|
@@ -2972,7 +4126,7 @@ function createFilesystemSecretsPlugin() {
|
|
|
2972
4126
|
);
|
|
2973
4127
|
const entries = [];
|
|
2974
4128
|
for (const file of files) {
|
|
2975
|
-
const document = await (0,
|
|
4129
|
+
const document = await (0, import_promises15.readFile)(file.absolutePath, "utf8");
|
|
2976
4130
|
const fileEntries = filesystemSecretsReader(file.relativePath, document, file.workspaceId);
|
|
2977
4131
|
for (const entry of fileEntries) {
|
|
2978
4132
|
const metadata = toSecretReferenceMetadata(entry.value);
|
|
@@ -2988,7 +4142,7 @@ function createFilesystemSecretsPlugin() {
|
|
|
2988
4142
|
}
|
|
2989
4143
|
|
|
2990
4144
|
// ../../plugins/filesystem/src/filesystemValuesReader.ts
|
|
2991
|
-
var
|
|
4145
|
+
var import_promises16 = require("fs/promises");
|
|
2992
4146
|
function filesystemValuesReader(filePath, document, workspaceId = "default") {
|
|
2993
4147
|
return yamlObjectToEntries(document, filePath, "value", "filesystem-values", workspaceId);
|
|
2994
4148
|
}
|
|
@@ -3009,7 +4163,7 @@ function createFilesystemValuesPlugin() {
|
|
|
3009
4163
|
).map(([namespace]) => namespace);
|
|
3010
4164
|
const entries = [];
|
|
3011
4165
|
for (const file of files) {
|
|
3012
|
-
const document = await (0,
|
|
4166
|
+
const document = await (0, import_promises16.readFile)(file.absolutePath, "utf8");
|
|
3013
4167
|
entries.push(...filesystemValuesReader(file.relativePath, document, file.workspaceId));
|
|
3014
4168
|
}
|
|
3015
4169
|
for (const namespace of customNamespaces) {
|
|
@@ -3024,7 +4178,7 @@ function createFilesystemValuesPlugin() {
|
|
|
3024
4178
|
layers
|
|
3025
4179
|
);
|
|
3026
4180
|
for (const file of namespaceFiles) {
|
|
3027
|
-
const document = await (0,
|
|
4181
|
+
const document = await (0, import_promises16.readFile)(file.absolutePath, "utf8");
|
|
3028
4182
|
entries.push(...yamlObjectToEntries(document, file.relativePath, namespace, "filesystem-values", file.workspaceId));
|
|
3029
4183
|
}
|
|
3030
4184
|
}
|
|
@@ -3179,21 +4333,34 @@ async function createCnos2(options = {}) {
|
|
|
3179
4333
|
|
|
3180
4334
|
// src/build/index.ts
|
|
3181
4335
|
async function resolveBrowserData(options = {}) {
|
|
3182
|
-
const runtime = await createCnos2(
|
|
4336
|
+
const runtime = await createCnos2({
|
|
4337
|
+
...options,
|
|
4338
|
+
cacheMode: options.cacheMode ?? "build"
|
|
4339
|
+
});
|
|
3183
4340
|
const browserData = {};
|
|
3184
|
-
for (const [key
|
|
4341
|
+
for (const [key] of runtime.graph.entries) {
|
|
3185
4342
|
if (!key.startsWith("public.")) {
|
|
3186
4343
|
continue;
|
|
3187
4344
|
}
|
|
3188
|
-
|
|
4345
|
+
const inspect = runtime.inspect(key);
|
|
4346
|
+
if (inspect.derived?.runtimeDependent) {
|
|
4347
|
+
throw new Error(
|
|
4348
|
+
`Cannot build browser projection: ${key} depends on runtime namespaces ${inspect.derived.runtimeNamespaces.join(", ") || "runtime"}.`
|
|
4349
|
+
);
|
|
4350
|
+
}
|
|
4351
|
+
const value = runtime.read(key);
|
|
4352
|
+
if (value === void 0) {
|
|
4353
|
+
continue;
|
|
4354
|
+
}
|
|
4355
|
+
browserData[key] = value;
|
|
3189
4356
|
}
|
|
3190
4357
|
return browserData;
|
|
3191
4358
|
}
|
|
3192
4359
|
function toScreamingSnakeSegment(segment) {
|
|
3193
4360
|
return segment.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
|
|
3194
4361
|
}
|
|
3195
|
-
function toScreamingSnake(
|
|
3196
|
-
return
|
|
4362
|
+
function toScreamingSnake(path16) {
|
|
4363
|
+
return path16.split(".").map((segment) => toScreamingSnakeSegment(segment)).filter(Boolean).join("_");
|
|
3197
4364
|
}
|
|
3198
4365
|
function stripPublicNamespace(key) {
|
|
3199
4366
|
return key.startsWith("public.") ? key.slice("public.".length) : key;
|
|
@@ -3225,17 +4392,26 @@ function toFrameworkEnv(browserData, framework = "generic", options = {}) {
|
|
|
3225
4392
|
}
|
|
3226
4393
|
async function resolveFrameworkEnv(options = {}, framework = "generic", envOptions = {}) {
|
|
3227
4394
|
if (framework === "generic") {
|
|
3228
|
-
const browserData = await resolveBrowserData(
|
|
4395
|
+
const browserData = await resolveBrowserData({
|
|
4396
|
+
...options,
|
|
4397
|
+
cacheMode: options.cacheMode ?? "build"
|
|
4398
|
+
});
|
|
3229
4399
|
return toFrameworkEnv(browserData, framework, envOptions);
|
|
3230
4400
|
}
|
|
3231
|
-
const runtime = await createCnos2(
|
|
4401
|
+
const runtime = await createCnos2({
|
|
4402
|
+
...options,
|
|
4403
|
+
cacheMode: options.cacheMode ?? "build"
|
|
4404
|
+
});
|
|
3232
4405
|
return runtime.toPublicEnv({
|
|
3233
4406
|
framework,
|
|
3234
4407
|
...envOptions.prefix ? { prefix: envOptions.prefix } : {}
|
|
3235
4408
|
});
|
|
3236
4409
|
}
|
|
3237
4410
|
async function resolveServerProjection(options = {}) {
|
|
3238
|
-
const runtime = await createCnos2(
|
|
4411
|
+
const runtime = await createCnos2({
|
|
4412
|
+
...options,
|
|
4413
|
+
cacheMode: options.cacheMode ?? "build"
|
|
4414
|
+
});
|
|
3239
4415
|
return runtime.toServerProjection();
|
|
3240
4416
|
}
|
|
3241
4417
|
// Annotate the CommonJS export names for ESM import in node:
|