@kitsy/cnos 1.10.0 → 1.11.1

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 (61) hide show
  1. package/dist/build/index.cjs +331 -63
  2. package/dist/build/index.d.cts +1 -1
  3. package/dist/build/index.d.ts +1 -1
  4. package/dist/build/index.js +13 -15
  5. package/dist/{chunk-A5U7EZCJ.js → chunk-2DMCB3PK.js} +1 -1
  6. package/dist/{chunk-RTHKUGJV.js → chunk-5JGNRADB.js} +1 -1
  7. package/dist/{chunk-3EZGPQCE.js → chunk-DPC2BV3S.js} +1 -1
  8. package/dist/{chunk-FHXLOWAB.js → chunk-KJ57PF47.js} +1 -1
  9. package/dist/{chunk-ESBHCFC6.js → chunk-NU25VFA2.js} +1 -1
  10. package/dist/{chunk-UGLATJJD.js → chunk-RNTTPI5S.js} +1 -1
  11. package/dist/{chunk-UKNL2Y4N.js → chunk-T3E57MSQ.js} +1 -1
  12. package/dist/{chunk-CSA4L64V.js → chunk-V3USPV5U.js} +8 -8
  13. package/dist/{chunk-MQ4WG3K6.js → chunk-WPB4HB2K.js} +320 -49
  14. package/dist/{chunk-EIK7OUFP.js → chunk-X4PBPUKL.js} +157 -37
  15. package/dist/configure/index.cjs +329 -59
  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-Ud1o2MBn.d.cts → core-CGJObpyy.d.cts} +40 -2
  20. package/dist/{core-Ud1o2MBn.d.ts → core-CGJObpyy.d.ts} +40 -2
  21. package/dist/{envNaming-DxxqiGKN.d.cts → envNaming-DIaBgT6E.d.cts} +1 -1
  22. package/dist/{envNaming-CPwXl4I6.d.ts → envNaming-_WD9sLZI.d.ts} +1 -1
  23. package/dist/index.cjs +480 -91
  24. package/dist/index.d.cts +2 -2
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.js +10 -10
  27. package/dist/internal.cjs +89 -23
  28. package/dist/internal.d.cts +3 -3
  29. package/dist/internal.d.ts +3 -3
  30. package/dist/internal.js +2 -2
  31. package/dist/plugin/basic-schema.cjs +4 -1
  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.cjs +4 -1
  36. package/dist/plugin/cli-args.d.cts +1 -1
  37. package/dist/plugin/cli-args.d.ts +1 -1
  38. package/dist/plugin/cli-args.js +2 -2
  39. package/dist/plugin/dotenv.cjs +6 -3
  40. package/dist/plugin/dotenv.d.cts +2 -2
  41. package/dist/plugin/dotenv.d.ts +2 -2
  42. package/dist/plugin/dotenv.js +2 -2
  43. package/dist/plugin/env-export.cjs +5 -2
  44. package/dist/plugin/env-export.d.cts +2 -2
  45. package/dist/plugin/env-export.d.ts +2 -2
  46. package/dist/plugin/env-export.js +2 -2
  47. package/dist/plugin/filesystem.cjs +13 -10
  48. package/dist/plugin/filesystem.d.cts +1 -1
  49. package/dist/plugin/filesystem.d.ts +1 -1
  50. package/dist/plugin/filesystem.js +2 -2
  51. package/dist/plugin/process-env.cjs +4 -1
  52. package/dist/plugin/process-env.d.cts +2 -2
  53. package/dist/plugin/process-env.d.ts +2 -2
  54. package/dist/plugin/process-env.js +2 -2
  55. package/dist/runtime/index.cjs +480 -91
  56. package/dist/runtime/index.d.cts +13 -6
  57. package/dist/runtime/index.d.ts +13 -6
  58. package/dist/runtime/index.js +10 -10
  59. package/dist/{toPublicEnv-fUZMRUOz.d.cts → toPublicEnv-C3A8aLjo.d.cts} +1 -1
  60. package/dist/{toPublicEnv-C9wPSpRo.d.ts → toPublicEnv-DLNNcEso.d.ts} +1 -1
  61. package/package.json +1 -1
@@ -3,7 +3,7 @@ import {
3
3
  graphRequiresSecretHydration,
4
4
  readRuntimeGraphFromEnv,
5
5
  readServerProjectionFromEnv
6
- } from "./chunk-UKNL2Y4N.js";
6
+ } from "./chunk-T3E57MSQ.js";
7
7
  import {
8
8
  createCnos,
9
9
  getBootstrappedSecretHydrationRequired,
@@ -12,8 +12,9 @@ import {
12
12
  setBootstrappedSecretHydrationRequired,
13
13
  setSingletonReady,
14
14
  setSingletonRuntime
15
- } from "./chunk-CSA4L64V.js";
15
+ } from "./chunk-V3USPV5U.js";
16
16
  import {
17
+ assertSecretRefVaultProviderCompatible,
17
18
  createDefaultRuntimeProviders,
18
19
  createDerivedRuntimeSupport,
19
20
  createSecretVaultProvider,
@@ -28,12 +29,25 @@ import {
28
29
  toLogicalKey,
29
30
  toNamespaceObject,
30
31
  toPublicEnv
31
- } from "./chunk-MQ4WG3K6.js";
32
+ } from "./chunk-WPB4HB2K.js";
32
33
 
33
34
  // src/runtime/index.ts
34
35
  import { existsSync, readFileSync } from "fs";
35
36
  import path from "path";
36
37
  var NOT_READY_MESSAGE = "CNOS not initialized. Call await cnos.ready() or use cnos run.";
38
+ var bootstrappedProjection;
39
+ var singletonRuntimeProviders = /* @__PURE__ */ new Map();
40
+ var singletonSecretVaultProviders = /* @__PURE__ */ new Map();
41
+ function registerSingletonSecretVaultProvider(factory) {
42
+ singletonSecretVaultProviders.set(factory.provider, factory);
43
+ }
44
+ function mergeSecretVaultProviders(factories = []) {
45
+ const merged = new Map(singletonSecretVaultProviders);
46
+ for (const factory of factories) {
47
+ merged.set(factory.provider, factory);
48
+ }
49
+ return Array.from(merged.values());
50
+ }
37
51
  function getRuntimeOrThrow() {
38
52
  const runtime = getSingletonRuntime();
39
53
  if (!runtime) {
@@ -97,6 +111,7 @@ function attachBootstrappedGraph(graph) {
97
111
  if (getSingletonRuntime()) {
98
112
  return;
99
113
  }
114
+ bootstrappedProjection = void 0;
100
115
  const bootstrappedManifest = {
101
116
  version: 1,
102
117
  project: {
@@ -167,6 +182,9 @@ function attachBootstrappedGraph(graph) {
167
182
  schema: {}
168
183
  };
169
184
  const runtimeProviders = createDefaultRuntimeProviders(bootstrappedManifest, process.env);
185
+ for (const [namespace, provider] of singletonRuntimeProviders) {
186
+ registerRuntimeProvider(bootstrappedManifest, runtimeProviders, namespace, provider);
187
+ }
170
188
  const derivedSupport = createDerivedRuntimeSupport(graph, bootstrappedManifest, runtimeProviders);
171
189
  const resolveProjectedSourceKey = (key) => {
172
190
  if (!key.startsWith("public.")) {
@@ -235,6 +253,7 @@ function attachBootstrappedGraph(graph) {
235
253
  },
236
254
  registerRuntimeProvider(namespace, provider) {
237
255
  registerRuntimeProvider(bootstrappedManifest, runtimeProviders, namespace, provider);
256
+ singletonRuntimeProviders.set(namespace, provider);
238
257
  },
239
258
  async refreshSecrets() {
240
259
  return;
@@ -246,7 +265,7 @@ function attachBootstrappedGraph(graph) {
246
265
  setSingletonRuntime(runtime);
247
266
  setBootstrappedSecretHydrationRequired(graphRequiresSecretHydration(graph));
248
267
  }
249
- function toBootstrappedManifest(graph, runtimeNamespaces = []) {
268
+ function toBootstrappedManifest(graph, runtimeNamespaces = [], vaults = {}) {
250
269
  return {
251
270
  version: 1,
252
271
  project: {
@@ -307,7 +326,7 @@ function toBootstrappedManifest(graph, runtimeNamespaces = []) {
307
326
  ])
308
327
  )
309
328
  },
310
- vaults: {},
329
+ vaults,
311
330
  writePolicy: {
312
331
  define: {
313
332
  defaultProfile: graph.profile,
@@ -442,14 +461,34 @@ function graphFromProjection(projection) {
442
461
  }
443
462
  };
444
463
  }
445
- function attachBootstrappedProjection(projection, force = false) {
464
+ function vaultDefinitionFromProjection(manifest, projection, key, ref) {
465
+ assertSecretRefVaultProviderCompatible(manifest, ref, key);
466
+ const vaultId = ref.vault ?? "default";
467
+ const projected = projection.vaults?.[vaultId];
468
+ const mapping = {
469
+ ...projected?.mapping ?? {},
470
+ ...ref.envVar ? { [ref.envVar]: ref.ref } : {}
471
+ };
472
+ return {
473
+ provider: projected?.provider ?? ref.provider ?? "local",
474
+ ...projected?.auth ? { auth: projected.auth } : {},
475
+ ...Object.keys(mapping).length > 0 ? { mapping } : {},
476
+ ...projected?.fallback ? { fallback: projected.fallback } : {}
477
+ };
478
+ }
479
+ function attachBootstrappedProjection(projection, force = false, options = {}) {
446
480
  if (getSingletonRuntime() && !force) {
447
481
  return;
448
482
  }
483
+ bootstrappedProjection = projection;
449
484
  const graph = graphFromProjection(projection);
450
- const manifest = toBootstrappedManifest(graph, projection.runtimeNamespaces);
485
+ const manifest = toBootstrappedManifest(graph, projection.runtimeNamespaces, projection.vaults ?? {});
451
486
  const hydratedSecrets = /* @__PURE__ */ new Map();
487
+ const secretVaultProviders = mergeSecretVaultProviders(options.secretVaultProviders);
452
488
  const runtimeProviders = createDefaultRuntimeProviders(manifest, process.env);
489
+ for (const [namespace, provider] of singletonRuntimeProviders) {
490
+ registerRuntimeProvider(manifest, runtimeProviders, namespace, provider);
491
+ }
453
492
  const derivedSupport = createDerivedRuntimeSupport(graph, manifest, runtimeProviders);
454
493
  const resolveProjectedSourceKey = (key) => {
455
494
  if (!key.startsWith("public.")) {
@@ -462,32 +501,95 @@ function attachBootstrappedProjection(projection, force = false) {
462
501
  const fallback = `value.${key.slice("public.".length)}`;
463
502
  return graph.entries.has(fallback) ? fallback : key;
464
503
  };
465
- const resolveSecretValue = async (key) => {
504
+ const projectedDescriptorForKey = (key) => {
466
505
  const entry = graph.entries.get(key);
467
506
  if (!entry || entry.namespace !== "secret") {
468
- return entry?.value;
469
- }
470
- if (hydratedSecrets.has(key)) {
471
- return hydratedSecrets.get(key);
507
+ return void 0;
472
508
  }
473
509
  const ref = projection.secretRefs[key.slice("secret.".length)];
474
510
  if (!ref) {
475
511
  return void 0;
476
512
  }
477
- const definition = {
478
- provider: ref.provider,
479
- ...ref.envVar ? {
480
- mapping: {
481
- [ref.envVar]: ref.ref
482
- }
483
- } : {}
513
+ const definition = vaultDefinitionFromProjection(manifest, projection, key, ref);
514
+ return {
515
+ key,
516
+ ref,
517
+ vaultId: ref.vault ?? "default",
518
+ definitions: [definition, ...definition.fallback ?? []]
484
519
  };
485
- const provider = createSecretVaultProvider(ref.vault ?? "default", definition, process.env);
486
- const auth = await resolveVaultAuth(ref.vault ?? "default", definition, process.env);
487
- await provider.authenticate(auth);
488
- const value = await provider.get(ref.ref);
489
- hydratedSecrets.set(key, value);
490
- return value;
520
+ };
521
+ const runtimeDefinitionForCandidate = (candidate) => ({
522
+ provider: candidate.provider,
523
+ ...candidate.auth ? { auth: candidate.auth } : {},
524
+ ...candidate.mapping ? { mapping: candidate.mapping } : {}
525
+ });
526
+ const hydrateProjectedSecrets = async (keys) => {
527
+ const requestedKeys = keys ?? Object.keys(projection.secretRefs).map((segment) => `secret.${segment}`);
528
+ let remaining = requestedKeys.filter((key) => !hydratedSecrets.has(key)).map((key) => projectedDescriptorForKey(key)).filter((descriptor) => Boolean(descriptor));
529
+ const lastErrors = /* @__PURE__ */ new Map();
530
+ let candidateIndex = 0;
531
+ while (remaining.length > 0) {
532
+ const grouped = /* @__PURE__ */ new Map();
533
+ const exhausted = [];
534
+ for (const descriptor of remaining) {
535
+ const candidate = descriptor.definitions[candidateIndex];
536
+ if (!candidate) {
537
+ exhausted.push(descriptor);
538
+ continue;
539
+ }
540
+ const groupKey = `${descriptor.vaultId}\0${candidate.provider}`;
541
+ const group = grouped.get(groupKey) ?? {
542
+ vaultId: descriptor.vaultId,
543
+ definition: candidate,
544
+ descriptors: []
545
+ };
546
+ group.descriptors.push(descriptor);
547
+ grouped.set(groupKey, group);
548
+ }
549
+ if (grouped.size === 0) {
550
+ remaining = exhausted;
551
+ break;
552
+ }
553
+ const unresolved = [...exhausted];
554
+ for (const group of grouped.values()) {
555
+ const runtimeDefinition = runtimeDefinitionForCandidate(group.definition);
556
+ try {
557
+ const provider = createSecretVaultProvider(
558
+ group.vaultId,
559
+ runtimeDefinition,
560
+ process.env,
561
+ secretVaultProviders
562
+ );
563
+ const auth = await resolveVaultAuth(group.vaultId, runtimeDefinition, process.env);
564
+ await provider.authenticate(auth);
565
+ const refs = Array.from(new Set(group.descriptors.map((descriptor) => descriptor.ref.ref))).sort((left, right) => left.localeCompare(right));
566
+ const values = await provider.batchGet(refs);
567
+ for (const descriptor of group.descriptors) {
568
+ const value = values.get(descriptor.ref.ref);
569
+ if (value !== void 0) {
570
+ hydratedSecrets.set(descriptor.key, value);
571
+ lastErrors.delete(descriptor.key);
572
+ } else {
573
+ unresolved.push(descriptor);
574
+ }
575
+ }
576
+ } catch (error) {
577
+ for (const descriptor of group.descriptors) {
578
+ lastErrors.set(descriptor.key, error);
579
+ unresolved.push(descriptor);
580
+ }
581
+ }
582
+ }
583
+ remaining = unresolved.filter((descriptor) => !hydratedSecrets.has(descriptor.key));
584
+ candidateIndex += 1;
585
+ }
586
+ for (const descriptor of remaining) {
587
+ const error = lastErrors.get(descriptor.key);
588
+ if (error) {
589
+ throw error;
590
+ }
591
+ hydratedSecrets.set(descriptor.key, void 0);
592
+ }
491
593
  };
492
594
  const runtime = {
493
595
  manifest,
@@ -557,14 +659,14 @@ function attachBootstrappedProjection(projection, force = false) {
557
659
  toNamespace(namespace) {
558
660
  return toNamespaceObject(graph, namespace, (key) => this.read(key));
559
661
  },
560
- toEnv(options) {
561
- return toEnv(graph, manifest, options, {
662
+ toEnv(options2) {
663
+ return toEnv(graph, manifest, options2, {
562
664
  read: (key) => this.read(key),
563
665
  isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(key)
564
666
  });
565
667
  },
566
- toPublicEnv(options) {
567
- return toPublicEnv(graph, manifest, options, {
668
+ toPublicEnv(options2) {
669
+ return toPublicEnv(graph, manifest, options2, {
568
670
  read: (key) => derivedSupport.toConcreteValue(
569
671
  resolveProjectedSourceKey(key),
570
672
  (ref) => {
@@ -587,16 +689,18 @@ function attachBootstrappedProjection(projection, force = false) {
587
689
  },
588
690
  registerRuntimeProvider(namespace, provider) {
589
691
  registerRuntimeProvider(manifest, runtimeProviders, namespace, provider);
692
+ singletonRuntimeProviders.set(namespace, provider);
590
693
  },
591
694
  async refreshSecrets() {
592
- for (const key of Object.keys(projection.secretRefs).map((segment) => `secret.${segment}`)) {
695
+ const keys = Object.keys(projection.secretRefs).map((segment) => `secret.${segment}`);
696
+ for (const key of keys) {
593
697
  hydratedSecrets.delete(key);
594
- await resolveSecretValue(key);
595
698
  }
699
+ await hydrateProjectedSecrets(keys);
596
700
  },
597
701
  async refreshSecret(key) {
598
702
  hydratedSecrets.delete(key);
599
- await resolveSecretValue(key);
703
+ await hydrateProjectedSecrets([key]);
600
704
  }
601
705
  };
602
706
  setSingletonRuntime(runtime);
@@ -703,14 +807,23 @@ var cnos = Object.assign(
703
807
  console.log(formatted);
704
808
  return formatted;
705
809
  },
706
- async loadProjection(source) {
810
+ async loadProjection(source, options = {}) {
707
811
  const resolvedSource = path.resolve(source);
708
812
  const projection = deserializeServerProjection(readFileSync(resolvedSource, "utf8"));
709
- attachBootstrappedProjection(projection, true);
813
+ attachBootstrappedProjection(projection, true, options);
710
814
  setBootstrappedSecretHydrationRequired(Object.keys(projection.secretRefs).length > 0);
711
815
  },
712
816
  registerRuntimeProvider(namespace, provider) {
713
817
  getRuntimeOrThrow().registerRuntimeProvider(namespace, provider);
818
+ singletonRuntimeProviders.set(namespace, provider);
819
+ },
820
+ registerSecretVaultProvider(factory) {
821
+ registerSingletonSecretVaultProvider(factory);
822
+ },
823
+ registerSecretVaultProviders(factories) {
824
+ for (const factory of factories) {
825
+ registerSingletonSecretVaultProvider(factory);
826
+ }
714
827
  },
715
828
  async refreshSecrets() {
716
829
  await getRuntimeOrThrow().refreshSecrets();
@@ -719,10 +832,14 @@ var cnos = Object.assign(
719
832
  async refreshSecret(key) {
720
833
  await getRuntimeOrThrow().refreshSecret(key);
721
834
  },
722
- async ready() {
835
+ async ready(options = {}) {
723
836
  const runtime = getSingletonRuntime();
837
+ const secretVaultProviders = mergeSecretVaultProviders(options.secretVaultProviders);
724
838
  if (runtime && getBootstrappedSecretHydrationRequired()) {
725
- await runtime.refreshSecrets();
839
+ const runtimeToHydrate = bootstrappedProjection && secretVaultProviders.length > 0 ? (attachBootstrappedProjection(bootstrappedProjection, true, {
840
+ secretVaultProviders
841
+ }), getRuntimeOrThrow()) : runtime;
842
+ await runtimeToHydrate.refreshSecrets();
726
843
  setBootstrappedSecretHydrationRequired(false);
727
844
  return;
728
845
  }
@@ -734,7 +851,10 @@ var cnos = Object.assign(
734
851
  await existing;
735
852
  return;
736
853
  }
737
- const readyPromise = createCnos().then((runtime2) => {
854
+ const readyPromise = createCnos({
855
+ ...options,
856
+ secretVaultProviders
857
+ }).then((runtime2) => {
738
858
  setSingletonRuntime(runtime2);
739
859
  setBootstrappedSecretHydrationRequired(false);
740
860
  return runtime2;