@kitsy/cnos 1.9.2 → 1.10.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.
Files changed (57) hide show
  1. package/dist/build/index.cjs +193 -18
  2. package/dist/build/index.d.cts +1 -1
  3. package/dist/build/index.d.ts +1 -1
  4. package/dist/build/index.js +8 -8
  5. package/dist/{chunk-2JBA2LXU.js → chunk-3EZGPQCE.js} +35 -6
  6. package/dist/{chunk-6QQPHDUI.js → chunk-A5U7EZCJ.js} +1 -1
  7. package/dist/{chunk-CPGRRZLP.js → chunk-CSA4L64V.js} +10 -10
  8. package/dist/{chunk-QK7BMU47.js → chunk-EIK7OUFP.js} +3 -3
  9. package/dist/{chunk-A2WG3ZKW.js → chunk-ESBHCFC6.js} +1 -1
  10. package/dist/{chunk-7JZO6XN3.js → chunk-FHXLOWAB.js} +1 -1
  11. package/dist/{chunk-7KVM5PUW.js → chunk-MQ4WG3K6.js} +158 -12
  12. package/dist/{chunk-LURQ4LAK.js → chunk-RTHKUGJV.js} +1 -1
  13. package/dist/{chunk-L7JVECPE.js → chunk-UGLATJJD.js} +1 -1
  14. package/dist/{chunk-NVFACB64.js → chunk-UKNL2Y4N.js} +1 -1
  15. package/dist/configure/index.cjs +193 -18
  16. package/dist/configure/index.d.cts +3 -3
  17. package/dist/configure/index.d.ts +3 -3
  18. package/dist/configure/index.js +8 -8
  19. package/dist/{core-zDTUSVx9.d.cts → core-Ud1o2MBn.d.cts} +12 -5
  20. package/dist/{core-zDTUSVx9.d.ts → core-Ud1o2MBn.d.ts} +12 -5
  21. package/dist/{envNaming-BkorOKW_.d.ts → envNaming-CPwXl4I6.d.ts} +1 -1
  22. package/dist/{envNaming-EFzezmB3.d.cts → envNaming-DxxqiGKN.d.cts} +1 -1
  23. package/dist/index.cjs +193 -18
  24. package/dist/index.d.cts +1 -1
  25. package/dist/index.d.ts +1 -1
  26. package/dist/index.js +10 -10
  27. package/dist/internal.cjs +289 -31
  28. package/dist/internal.d.cts +31 -3
  29. package/dist/internal.d.ts +31 -3
  30. package/dist/internal.js +141 -23
  31. package/dist/plugin/basic-schema.cjs +9 -2
  32. package/dist/plugin/basic-schema.d.cts +1 -1
  33. package/dist/plugin/basic-schema.d.ts +1 -1
  34. package/dist/plugin/basic-schema.js +2 -2
  35. package/dist/plugin/cli-args.d.cts +1 -1
  36. package/dist/plugin/cli-args.d.ts +1 -1
  37. package/dist/plugin/cli-args.js +2 -2
  38. package/dist/plugin/dotenv.cjs +34 -5
  39. package/dist/plugin/dotenv.d.cts +2 -2
  40. package/dist/plugin/dotenv.d.ts +2 -2
  41. package/dist/plugin/dotenv.js +2 -2
  42. package/dist/plugin/env-export.d.cts +2 -2
  43. package/dist/plugin/env-export.d.ts +2 -2
  44. package/dist/plugin/env-export.js +2 -2
  45. package/dist/plugin/filesystem.d.cts +1 -1
  46. package/dist/plugin/filesystem.d.ts +1 -1
  47. package/dist/plugin/filesystem.js +2 -2
  48. package/dist/plugin/process-env.d.cts +2 -2
  49. package/dist/plugin/process-env.d.ts +2 -2
  50. package/dist/plugin/process-env.js +2 -2
  51. package/dist/runtime/index.cjs +193 -18
  52. package/dist/runtime/index.d.cts +1 -1
  53. package/dist/runtime/index.d.ts +1 -1
  54. package/dist/runtime/index.js +10 -10
  55. package/dist/{toPublicEnv-CT265rzS.d.ts → toPublicEnv-C9wPSpRo.d.ts} +1 -1
  56. package/dist/{toPublicEnv-Ds1DRwCX.d.cts → toPublicEnv-fUZMRUOz.d.cts} +1 -1
  57. package/package.json +1 -1
@@ -1339,6 +1339,134 @@ function stripNamespace(key) {
1339
1339
  return key.split(".").slice(1).join(".");
1340
1340
  }
1341
1341
 
1342
+ // ../core/src/spec/normalizeSpecRule.ts
1343
+ var ALLOWED_TYPES = /* @__PURE__ */ new Set(["string", "number", "boolean", "object", "array"]);
1344
+ var SECRET_FORBIDDEN_FIELDS = ["default", "examples", "enum"];
1345
+ function hasOwn(target, key) {
1346
+ return Object.prototype.hasOwnProperty.call(target, key);
1347
+ }
1348
+ function normalizeOptionalString(value, fieldName, logicalKey) {
1349
+ if (value === void 0) {
1350
+ return void 0;
1351
+ }
1352
+ if (typeof value !== "string") {
1353
+ throw new CnosManifestError(`Invalid schema rule for ${logicalKey}: "${fieldName}" must be a string.`);
1354
+ }
1355
+ const nextValue = value.trim();
1356
+ return nextValue.length > 0 ? nextValue : void 0;
1357
+ }
1358
+ function normalizeStringArray(value, fieldName, logicalKey) {
1359
+ if (value === void 0) {
1360
+ return void 0;
1361
+ }
1362
+ if (!Array.isArray(value)) {
1363
+ throw new CnosManifestError(`Invalid schema rule for ${logicalKey}: "${fieldName}" must be an array.`);
1364
+ }
1365
+ const nextValue = value.map((entry) => {
1366
+ if (typeof entry !== "string") {
1367
+ throw new CnosManifestError(
1368
+ `Invalid schema rule for ${logicalKey}: "${fieldName}" entries must be strings.`
1369
+ );
1370
+ }
1371
+ return entry.trim();
1372
+ }).filter(Boolean);
1373
+ return nextValue.length > 0 ? nextValue : void 0;
1374
+ }
1375
+ function normalizeUnknownArray(value, fieldName, logicalKey) {
1376
+ if (value === void 0) {
1377
+ return void 0;
1378
+ }
1379
+ if (!Array.isArray(value)) {
1380
+ throw new CnosManifestError(`Invalid schema rule for ${logicalKey}: "${fieldName}" must be an array.`);
1381
+ }
1382
+ return value.length > 0 ? value : void 0;
1383
+ }
1384
+ function assertValidPatternRegex(pattern, logicalKey) {
1385
+ try {
1386
+ void new RegExp(pattern);
1387
+ } catch (error) {
1388
+ const reason = error instanceof Error ? error.message : String(error);
1389
+ throw new CnosManifestError(
1390
+ `Invalid schema rule for ${logicalKey}: "pattern" must be a valid regex (${reason}).`
1391
+ );
1392
+ }
1393
+ }
1394
+ function assertSecretRuleSafety(logicalKey, rule) {
1395
+ if (!logicalKey.startsWith("secret.")) {
1396
+ return;
1397
+ }
1398
+ const offendingFields = SECRET_FORBIDDEN_FIELDS.filter((field) => hasOwn(rule, field));
1399
+ if (offendingFields.length === 0) {
1400
+ return;
1401
+ }
1402
+ throw new CnosManifestError(
1403
+ `Invalid schema rule for ${logicalKey}: secret specs cannot include ${offendingFields.join(", ")}. Store secret values in the vault, not schema metadata. Remove ${offendingFields.map((field) => `schema.${logicalKey}.${field}`).join(", ")} to continue.`
1404
+ );
1405
+ }
1406
+ function normalizeSpecRule(logicalKey, rule) {
1407
+ if (!rule || typeof rule !== "object" || Array.isArray(rule)) {
1408
+ throw new CnosManifestError(`Invalid schema rule for ${logicalKey}: expected an object.`);
1409
+ }
1410
+ const candidate = rule;
1411
+ assertSecretRuleSafety(logicalKey, candidate);
1412
+ const normalized = {};
1413
+ if (candidate.type !== void 0) {
1414
+ if (typeof candidate.type !== "string" || !ALLOWED_TYPES.has(candidate.type)) {
1415
+ throw new CnosManifestError(`Invalid schema rule for ${logicalKey}: unsupported type "${String(candidate.type)}".`);
1416
+ }
1417
+ normalized.type = candidate.type;
1418
+ }
1419
+ if (candidate.required !== void 0) {
1420
+ if (typeof candidate.required !== "boolean") {
1421
+ throw new CnosManifestError(`Invalid schema rule for ${logicalKey}: "required" must be a boolean.`);
1422
+ }
1423
+ normalized.required = candidate.required;
1424
+ }
1425
+ if (hasOwn(candidate, "default")) {
1426
+ normalized.default = candidate.default;
1427
+ }
1428
+ const normalizedEnum = normalizeUnknownArray(candidate.enum, "enum", logicalKey);
1429
+ if (normalizedEnum !== void 0) {
1430
+ normalized.enum = normalizedEnum;
1431
+ }
1432
+ const normalizedPattern = normalizeOptionalString(candidate.pattern, "pattern", logicalKey);
1433
+ if (normalizedPattern !== void 0) {
1434
+ assertValidPatternRegex(normalizedPattern, logicalKey);
1435
+ normalized.pattern = normalizedPattern;
1436
+ }
1437
+ const normalizedSummary = normalizeOptionalString(candidate.summary, "summary", logicalKey);
1438
+ if (normalizedSummary !== void 0) {
1439
+ normalized.summary = normalizedSummary;
1440
+ }
1441
+ const normalizedDescription = normalizeOptionalString(candidate.description, "description", logicalKey);
1442
+ if (normalizedDescription !== void 0) {
1443
+ normalized.description = normalizedDescription;
1444
+ }
1445
+ const normalizedExamples = normalizeUnknownArray(candidate.examples, "examples", logicalKey);
1446
+ if (normalizedExamples !== void 0) {
1447
+ normalized.examples = normalizedExamples;
1448
+ }
1449
+ const normalizedUsedBy = normalizeStringArray(candidate.usedBy, "usedBy", logicalKey);
1450
+ if (normalizedUsedBy !== void 0) {
1451
+ normalized.usedBy = normalizedUsedBy;
1452
+ }
1453
+ if (candidate.deprecated !== void 0) {
1454
+ if (typeof candidate.deprecated !== "boolean") {
1455
+ throw new CnosManifestError(`Invalid schema rule for ${logicalKey}: "deprecated" must be a boolean.`);
1456
+ }
1457
+ normalized.deprecated = candidate.deprecated;
1458
+ }
1459
+ const normalizedDeprecationMessage = normalizeOptionalString(
1460
+ candidate.deprecationMessage,
1461
+ "deprecationMessage",
1462
+ logicalKey
1463
+ );
1464
+ if (normalizedDeprecationMessage !== void 0) {
1465
+ normalized.deprecationMessage = normalizedDeprecationMessage;
1466
+ }
1467
+ return normalized;
1468
+ }
1469
+
1342
1470
  // ../core/src/manifest/normalizeManifest.ts
1343
1471
  var DEFAULT_RESOLVE_FROM = ["cli.profile", "env.CNOS_PROFILE", "default"];
1344
1472
  var DEFAULT_LOADERS = [
@@ -1537,6 +1665,14 @@ function normalizeVaultAuth(vaultName, provider, auth) {
1537
1665
  ...auth?.config ? { config: auth.config } : {}
1538
1666
  };
1539
1667
  }
1668
+ function normalizeSchema(schema) {
1669
+ return Object.fromEntries(
1670
+ Object.entries(schema ?? {}).map(([logicalKey, rule]) => [
1671
+ logicalKey,
1672
+ normalizeSpecRule(logicalKey, rule)
1673
+ ])
1674
+ );
1675
+ }
1540
1676
  function normalizeManifest(manifest) {
1541
1677
  const version = manifest.version ?? 1;
1542
1678
  if (version !== 1) {
@@ -1634,7 +1770,7 @@ function normalizeManifest(manifest) {
1634
1770
  }
1635
1771
  }
1636
1772
  },
1637
- schema: manifest.schema ?? {}
1773
+ schema: normalizeSchema(manifest.schema)
1638
1774
  };
1639
1775
  }
1640
1776
 
@@ -2268,6 +2404,13 @@ function enumMatches(value, allowed) {
2268
2404
  const serialized = JSON.stringify(value);
2269
2405
  return allowed.some((candidate) => JSON.stringify(candidate) === serialized);
2270
2406
  }
2407
+ function testPattern(pattern, value) {
2408
+ try {
2409
+ return new RegExp(pattern).test(value);
2410
+ } catch {
2411
+ return false;
2412
+ }
2413
+ }
2271
2414
  function applySchemaRules(graph, schema) {
2272
2415
  const nextEntries = new Map(graph.entries);
2273
2416
  const issues = [];
@@ -2334,11 +2477,11 @@ function applySchemaRules(graph, schema) {
2334
2477
  key,
2335
2478
  message: `Config key ${key} must be a string to match pattern ${rule.pattern}`
2336
2479
  });
2337
- } else if (!new RegExp(rule.pattern).test(coercedValue)) {
2480
+ } else if (!testPattern(rule.pattern, coercedValue)) {
2338
2481
  issues.push({
2339
2482
  code: "schema.pattern",
2340
2483
  key,
2341
- message: `Config key ${key} does not match pattern ${rule.pattern}`
2484
+ message: `Config key ${key} does not match pattern ${rule.pattern} (or the pattern is invalid).`
2342
2485
  });
2343
2486
  }
2344
2487
  }
@@ -2738,16 +2881,19 @@ function resolveVaultDefinition(vaults, vault = "default") {
2738
2881
  // ../core/src/secrets/auditLog.ts
2739
2882
  async function appendAuditEvent(event, processEnv = process.env) {
2740
2883
  const auditFile = processEnv.CNOS_AUDIT_FILE ?? import_node_path12.default.join(resolveSecretStoreRoot(processEnv), "audit", "access.log");
2741
- await (0, import_promises11.mkdir)(import_node_path12.default.dirname(auditFile), { recursive: true });
2742
- await (0, import_promises11.appendFile)(
2743
- auditFile,
2744
- `${JSON.stringify({
2745
- ts: (/* @__PURE__ */ new Date()).toISOString(),
2746
- ...event
2747
- })}
2884
+ try {
2885
+ await (0, import_promises11.mkdir)(import_node_path12.default.dirname(auditFile), { recursive: true });
2886
+ await (0, import_promises11.appendFile)(
2887
+ auditFile,
2888
+ `${JSON.stringify({
2889
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
2890
+ ...event
2891
+ })}
2748
2892
  `,
2749
- "utf8"
2750
- );
2893
+ "utf8"
2894
+ );
2895
+ } catch {
2896
+ }
2751
2897
  }
2752
2898
 
2753
2899
  // ../core/src/secrets/secretCache.ts
@@ -3719,7 +3865,7 @@ function envVarToLogicalKey(envVar, config = {}) {
3719
3865
  // package.json
3720
3866
  var package_default = {
3721
3867
  name: "@kitsy/cnos",
3722
- version: "1.9.2",
3868
+ version: "1.10.0",
3723
3869
  description: "Batteries-included CNOS runtime package wired with the official plugins.",
3724
3870
  type: "module",
3725
3871
  main: "./dist/index.cjs",
@@ -3924,9 +4070,30 @@ var DOTENV_PLUGIN_ID = "@kitsy/cnos/plugins/dotenv";
3924
4070
  function parseDoubleQuoted(value) {
3925
4071
  return value.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
3926
4072
  }
4073
+ function isEscapedCharacter(value, index) {
4074
+ let slashCount = 0;
4075
+ for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
4076
+ slashCount += 1;
4077
+ }
4078
+ return slashCount % 2 === 1;
4079
+ }
4080
+ function findClosingQuote(value, quote) {
4081
+ for (let index = 0; index < value.length; index += 1) {
4082
+ if (value[index] !== quote) {
4083
+ continue;
4084
+ }
4085
+ if (quote === '"' && isEscapedCharacter(value, index)) {
4086
+ continue;
4087
+ }
4088
+ return index;
4089
+ }
4090
+ return -1;
4091
+ }
3927
4092
  function parseDotenv(document) {
3928
4093
  const parsed = {};
3929
- for (const rawLine of document.split(/\r?\n/)) {
4094
+ const lines = document.split(/\r?\n/);
4095
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
4096
+ const rawLine = lines[lineIndex] ?? "";
3930
4097
  const line = rawLine.trim();
3931
4098
  if (!line || line.startsWith("#")) {
3932
4099
  continue;
@@ -3941,10 +4108,18 @@ function parseDotenv(document) {
3941
4108
  if (!envVar) {
3942
4109
  continue;
3943
4110
  }
3944
- if (value.startsWith('"') && value.endsWith('"')) {
3945
- value = parseDoubleQuoted(value.slice(1, -1));
3946
- } else if (value.startsWith("'") && value.endsWith("'")) {
3947
- value = value.slice(1, -1);
4111
+ if (value.startsWith('"') || value.startsWith("'")) {
4112
+ const quote = value.startsWith('"') ? '"' : "'";
4113
+ let quotedContent = value.slice(1);
4114
+ let closingIndex = findClosingQuote(quotedContent, quote);
4115
+ while (closingIndex === -1 && lineIndex < lines.length - 1) {
4116
+ lineIndex += 1;
4117
+ quotedContent = `${quotedContent}
4118
+ ${lines[lineIndex] ?? ""}`;
4119
+ closingIndex = findClosingQuote(quotedContent, quote);
4120
+ }
4121
+ const rawQuotedValue = closingIndex === -1 ? quotedContent : quotedContent.slice(0, closingIndex);
4122
+ value = quote === '"' ? parseDoubleQuoted(rawQuotedValue) : rawQuotedValue;
3948
4123
  } else {
3949
4124
  value = value.replace(/\s+#.*$/, "").trim();
3950
4125
  }
@@ -1,4 +1,4 @@
1
- import { b as LogicalKey, g as CnosRuntime, I as InspectResult } from '../core-zDTUSVx9.cjs';
1
+ import { b as LogicalKey, g as CnosRuntime, I as InspectResult } from '../core-Ud1o2MBn.cjs';
2
2
 
3
3
  interface CnosSingleton {
4
4
  <T = unknown>(key: LogicalKey): T | undefined;
@@ -1,4 +1,4 @@
1
- import { b as LogicalKey, g as CnosRuntime, I as InspectResult } from '../core-zDTUSVx9.js';
1
+ import { b as LogicalKey, g as CnosRuntime, I as InspectResult } from '../core-Ud1o2MBn.js';
2
2
 
3
3
  interface CnosSingleton {
4
4
  <T = unknown>(key: LogicalKey): T | undefined;
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  runtime_default
3
- } from "../chunk-QK7BMU47.js";
4
- import "../chunk-NVFACB64.js";
5
- import "../chunk-CPGRRZLP.js";
6
- import "../chunk-LURQ4LAK.js";
7
- import "../chunk-A2WG3ZKW.js";
8
- import "../chunk-L7JVECPE.js";
9
- import "../chunk-6QQPHDUI.js";
10
- import "../chunk-7JZO6XN3.js";
11
- import "../chunk-2JBA2LXU.js";
12
- import "../chunk-7KVM5PUW.js";
3
+ } from "../chunk-EIK7OUFP.js";
4
+ import "../chunk-UKNL2Y4N.js";
5
+ import "../chunk-CSA4L64V.js";
6
+ import "../chunk-3EZGPQCE.js";
7
+ import "../chunk-RTHKUGJV.js";
8
+ import "../chunk-ESBHCFC6.js";
9
+ import "../chunk-UGLATJJD.js";
10
+ import "../chunk-A5U7EZCJ.js";
11
+ import "../chunk-FHXLOWAB.js";
12
+ import "../chunk-MQ4WG3K6.js";
13
13
  export {
14
14
  runtime_default as default
15
15
  };
@@ -1,4 +1,4 @@
1
- import { R as ResolvedGraph, N as NormalizedManifest, T as ToEnvOptions, c as ToPublicEnvOptions } from './core-zDTUSVx9.js';
1
+ import { R as ResolvedGraph, N as NormalizedManifest, T as ToEnvOptions, c as ToPublicEnvOptions } from './core-Ud1o2MBn.js';
2
2
 
3
3
  declare function toEnv(graph: ResolvedGraph, manifest: NormalizedManifest, options?: ToEnvOptions, helpers?: {
4
4
  read?: (key: string) => unknown;
@@ -1,4 +1,4 @@
1
- import { R as ResolvedGraph, N as NormalizedManifest, T as ToEnvOptions, c as ToPublicEnvOptions } from './core-zDTUSVx9.cjs';
1
+ import { R as ResolvedGraph, N as NormalizedManifest, T as ToEnvOptions, c as ToPublicEnvOptions } from './core-Ud1o2MBn.cjs';
2
2
 
3
3
  declare function toEnv(graph: ResolvedGraph, manifest: NormalizedManifest, options?: ToEnvOptions, helpers?: {
4
4
  read?: (key: string) => unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitsy/cnos",
3
- "version": "1.9.2",
3
+ "version": "1.10.0",
4
4
  "description": "Batteries-included CNOS runtime package wired with the official plugins.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",