@super-repo/envx 0.4.0 → 0.4.1-b.2

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 (106) hide show
  1. package/README.md +2 -2
  2. package/dist/auto.js +1 -1
  3. package/dist/chunks/auto-preload-CrSuZDg1.js +75 -0
  4. package/dist/chunks/auto-preload-CrSuZDg1.js.map +1 -0
  5. package/dist/chunks/aws-DgcXfw-Y.js +54 -0
  6. package/dist/chunks/aws-DgcXfw-Y.js.map +1 -0
  7. package/dist/chunks/azure-Cmh5-dPn.js +62 -0
  8. package/dist/chunks/azure-Cmh5-dPn.js.map +1 -0
  9. package/dist/chunks/{commands-KUyDszno.js → commands-Br0Z7uUF.js} +2 -2
  10. package/dist/chunks/commands-Br0Z7uUF.js.map +1 -0
  11. package/dist/chunks/doppler-BkQsajIp.js +50 -0
  12. package/dist/chunks/doppler-BkQsajIp.js.map +1 -0
  13. package/dist/chunks/gcp-Dq7QncPS.js +53 -0
  14. package/dist/chunks/gcp-Dq7QncPS.js.map +1 -0
  15. package/dist/chunks/infisical-CO073rdx.js +57 -0
  16. package/dist/chunks/infisical-CO073rdx.js.map +1 -0
  17. package/dist/chunks/{src-Ln2uXfYC.js → libs-CqVa6LY9.js} +0 -0
  18. package/dist/chunks/libs-CqVa6LY9.js.map +1 -0
  19. package/dist/chunks/op-CG9UWJIj.js +76 -0
  20. package/dist/chunks/op-CG9UWJIj.js.map +1 -0
  21. package/dist/chunks/runtime-BIEf_Dgo.js +102 -0
  22. package/dist/chunks/runtime-BIEf_Dgo.js.map +1 -0
  23. package/dist/chunks/{src-BM4EdT3z.js → src-ke3h417V.js} +2 -2
  24. package/dist/chunks/src-ke3h417V.js.map +1 -0
  25. package/dist/chunks/types-COrFYR0z.js +62 -0
  26. package/dist/chunks/types-COrFYR0z.js.map +1 -0
  27. package/dist/chunks/vault-BWdO9DFO.js +54 -0
  28. package/dist/chunks/vault-BWdO9DFO.js.map +1 -0
  29. package/dist/cli.js +1 -1
  30. package/dist/commands/index.js +1 -1
  31. package/dist/index.d.ts +3 -3
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +2 -2
  34. package/dist/libs/audit.d.ts +62 -0
  35. package/dist/libs/audit.d.ts.map +1 -0
  36. package/dist/libs/config.d.ts +185 -0
  37. package/dist/libs/config.d.ts.map +1 -0
  38. package/dist/libs/crypto.d.ts +34 -0
  39. package/dist/libs/crypto.d.ts.map +1 -0
  40. package/dist/libs/decrypt.d.ts +10 -0
  41. package/dist/libs/decrypt.d.ts.map +1 -0
  42. package/dist/libs/encrypt.d.ts +21 -0
  43. package/dist/libs/encrypt.d.ts.map +1 -0
  44. package/dist/libs/env.d.ts +178 -0
  45. package/dist/libs/env.d.ts.map +1 -0
  46. package/dist/libs/expand.d.ts +51 -0
  47. package/dist/libs/expand.d.ts.map +1 -0
  48. package/dist/libs/index.d.ts +22 -0
  49. package/dist/libs/index.d.ts.map +1 -0
  50. package/dist/libs/index.js +2 -0
  51. package/dist/libs/keys.d.ts +92 -0
  52. package/dist/libs/keys.d.ts.map +1 -0
  53. package/dist/libs/match.d.ts +7 -0
  54. package/dist/libs/match.d.ts.map +1 -0
  55. package/dist/libs/parser.d.ts +33 -0
  56. package/dist/libs/parser.d.ts.map +1 -0
  57. package/dist/libs/rotate.d.ts +24 -0
  58. package/dist/libs/rotate.d.ts.map +1 -0
  59. package/dist/libs/types.d.ts +42 -0
  60. package/dist/libs/types.d.ts.map +1 -0
  61. package/dist/plugins/auto-preload.d.ts +50 -0
  62. package/dist/plugins/auto-preload.d.ts.map +1 -0
  63. package/dist/plugins/auto-preload.js +2 -0
  64. package/dist/plugins/aws.d.ts +52 -0
  65. package/dist/plugins/aws.d.ts.map +1 -0
  66. package/dist/plugins/aws.js +2 -0
  67. package/dist/plugins/azure.d.ts +46 -0
  68. package/dist/plugins/azure.d.ts.map +1 -0
  69. package/dist/plugins/azure.js +2 -0
  70. package/dist/plugins/doppler.d.ts +36 -0
  71. package/dist/plugins/doppler.d.ts.map +1 -0
  72. package/dist/plugins/doppler.js +2 -0
  73. package/dist/plugins/gcp.d.ts +48 -0
  74. package/dist/plugins/gcp.d.ts.map +1 -0
  75. package/dist/plugins/gcp.js +2 -0
  76. package/dist/plugins/index.d.ts +11 -0
  77. package/dist/plugins/index.d.ts.map +1 -0
  78. package/dist/plugins/index.js +11 -0
  79. package/dist/plugins/infisical.d.ts +51 -0
  80. package/dist/plugins/infisical.d.ts.map +1 -0
  81. package/dist/plugins/infisical.js +2 -0
  82. package/dist/plugins/op.d.ts +52 -0
  83. package/dist/plugins/op.d.ts.map +1 -0
  84. package/dist/plugins/op.js +2 -0
  85. package/dist/plugins/runtime.d.ts +95 -0
  86. package/dist/plugins/runtime.d.ts.map +1 -0
  87. package/dist/plugins/runtime.js +2 -0
  88. package/dist/plugins/types.d.ts +54 -0
  89. package/dist/plugins/types.d.ts.map +1 -0
  90. package/dist/plugins/vault.d.ts +47 -0
  91. package/dist/plugins/vault.d.ts.map +1 -0
  92. package/dist/plugins/vault.js +2 -0
  93. package/docs/plugins/custom-providers.md +26 -0
  94. package/docs/plugins/library-api.md +52 -0
  95. package/docs/plugins/overview.md +96 -0
  96. package/docs/plugins/providers.md +149 -0
  97. package/docs/plugins/recipes.md +77 -0
  98. package/docs/plugins/runtime.md +88 -0
  99. package/docs/security-models.md +3 -3
  100. package/package.json +51 -11
  101. package/dist/bin/dotenvx.d.ts +0 -1
  102. package/dist/bin/dotenvx.d.ts.map +0 -1
  103. package/dist/bin/dotenvx.js +0 -2
  104. package/dist/chunks/commands-KUyDszno.js.map +0 -1
  105. package/dist/chunks/src-BM4EdT3z.js.map +0 -1
  106. package/dist/chunks/src-Ln2uXfYC.js.map +0 -1
package/README.md CHANGED
@@ -86,7 +86,7 @@ Full subcommand and flag reference: [docs/cli.md](./docs/cli.md). Full schema fo
86
86
  | **`.env.keys` location** | alongside the env file | one shared file at the workspace root |
87
87
  | **Cascade discovery** | from cwd | from workspace root, layered with package overrides |
88
88
  | **`rotate`** | per-file | walks every encrypted file the resolver picks up |
89
- | **Secret-provider plugins** | not built in | `@super-repo/envx-plugins` (AWS, GCP, Azure, Vault, …) |
89
+ | **Secret-provider plugins** | not built in | `@super-repo/envx/plugins` (AWS, GCP, Azure, Vault, …) |
90
90
  | **Schema validation / profiles / audit / doctor / template / diff / hook / types / watch / bake** | not built in | first-class |
91
91
  | **Encryption (wire format)** | ECIES via `eciesjs` | **identical** — interoperable |
92
92
  | **License** | BSD-3-Clause | MIT |
@@ -131,7 +131,7 @@ Deep references and worked examples live alongside this package in [./docs/](./d
131
131
  ## References
132
132
 
133
133
  - [`@dotenvx/dotenvx`](https://dotenvx.com) — the upstream package envx builds on. Use it directly for single-app projects.
134
- - [`@super-repo/envx-plugins`](../plugins) — secret-provider plugins (AWS, GCP, Azure, Vault, 1Password, Doppler, Infisical) consumed via `resolvers:`.
134
+ - [`@super-repo/envx/plugins`](./docs/plugins/overview.md) — secret-provider plugins (AWS, GCP, Azure, Vault, 1Password, Doppler, Infisical) consumed via `resolvers:`.
135
135
  - [`eciesjs`](https://www.npmjs.com/package/eciesjs) — the secp256k1 + AES-256-GCM library used for encryption.
136
136
 
137
137
  ## License
package/dist/auto.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as envx } from "./chunks/src-BM4EdT3z.js";
1
+ import { t as envx } from "./chunks/src-ke3h417V.js";
2
2
  //#region src/auto.ts
3
3
  envx();
4
4
  //#endregion
@@ -0,0 +1,75 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ //#region src/plugins/auto-preload.ts
4
+ var REF_RE = /\$\{\{([a-zA-Z][\w-]*):([^}]+)\}\}/g;
5
+ /**
6
+ * Scan a set of env files for `${provider:id}` references and call
7
+ * `preload()` on every plugin whose `name` matches a found provider.
8
+ * Plugins whose names don't appear in any reference are skipped (no
9
+ * round-trip, no SDK warm-up, no surprise charges).
10
+ *
11
+ * Composes with the rest of envx like this:
12
+ *
13
+ * ```ts
14
+ * import envx from "@super-repo/envx";
15
+ * import { awsSecrets } from "@super-repo/envx/plugins/aws";
16
+ * import { gcpSecrets } from "@super-repo/envx/plugins/gcp";
17
+ * import { autoPreload } from "@super-repo/envx/plugins";
18
+ *
19
+ * const aws = awsSecrets({ region: "us-east-1" });
20
+ * const gcp = gcpSecrets({ projectId: "acme-prod" });
21
+ *
22
+ * await autoPreload([aws, gcp], { envFiles: [".env", "vault/.env.prod"] });
23
+ *
24
+ * envx({
25
+ * resolvers: {
26
+ * [aws.name]: aws.resolve,
27
+ * [gcp.name]: gcp.resolve,
28
+ * },
29
+ * });
30
+ * ```
31
+ */
32
+ async function autoPreload(providers, opts) {
33
+ const cwd = opts.cwd ?? process.cwd();
34
+ const byProvider = /* @__PURE__ */ new Map();
35
+ for (const p of providers) byProvider.set(p.name, /* @__PURE__ */ new Set());
36
+ for (const file of opts.envFiles) {
37
+ const abs = path.isAbsolute(file) ? file : path.resolve(cwd, file);
38
+ if (!fs.existsSync(abs)) continue;
39
+ const content = fs.readFileSync(abs, "utf8");
40
+ let m;
41
+ REF_RE.lastIndex = 0;
42
+ while ((m = REF_RE.exec(content)) !== null) {
43
+ const provider = m[1];
44
+ const id = m[2];
45
+ if (provider === void 0 || id === void 0) continue;
46
+ const set = byProvider.get(provider);
47
+ if (set) set.add(id);
48
+ }
49
+ }
50
+ const preloaded = {};
51
+ await Promise.all(providers.map(async (p) => {
52
+ const ids = [...byProvider.get(p.name) ?? []];
53
+ if (ids.length === 0) {
54
+ preloaded[p.name] = [];
55
+ return;
56
+ }
57
+ await p.preload(ids);
58
+ preloaded[p.name] = ids;
59
+ }));
60
+ return { preloaded };
61
+ }
62
+ /**
63
+ * Build a `resolvers:` map from a list of providers — the shape envx's
64
+ * `resolvers` config expects. Saves you from repeating
65
+ * `{ [p.name]: p.resolve }` for every provider.
66
+ */
67
+ function asResolvers(providers) {
68
+ const out = {};
69
+ for (const p of providers) out[p.name] = (id) => p.resolve(id);
70
+ return out;
71
+ }
72
+ //#endregion
73
+ export { autoPreload as n, asResolvers as t };
74
+
75
+ //# sourceMappingURL=auto-preload-CrSuZDg1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-preload-CrSuZDg1.js","names":[],"sources":["../../src/plugins/auto-preload.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\n\nimport type { SecretProvider } from \"./types.js\";\n\n// #region -- autoPreload -----------------------------------\n\n// Matches `${{provider:id}}` references — see env.ts for the dotenvx-conflict reasoning.\nconst REF_RE = /\\$\\{\\{([a-zA-Z][\\w-]*):([^}]+)\\}\\}/g;\n\nexport interface AutoPreloadOptions {\n /**\n * Env files to scan for `${provider:id}` references. Paths are\n * resolved against `cwd` (which defaults to `process.cwd()`).\n * Missing files are silently skipped — the helper assumes you\n * already know which files will load and just need the references\n * pre-resolved.\n */\n readonly envFiles: readonly string[];\n /** Defaults to `process.cwd()`. */\n readonly cwd?: string;\n}\n\n/**\n * Scan a set of env files for `${provider:id}` references and call\n * `preload()` on every plugin whose `name` matches a found provider.\n * Plugins whose names don't appear in any reference are skipped (no\n * round-trip, no SDK warm-up, no surprise charges).\n *\n * Composes with the rest of envx like this:\n *\n * ```ts\n * import envx from \"@super-repo/envx\";\n * import { awsSecrets } from \"@super-repo/envx/plugins/aws\";\n * import { gcpSecrets } from \"@super-repo/envx/plugins/gcp\";\n * import { autoPreload } from \"@super-repo/envx/plugins\";\n *\n * const aws = awsSecrets({ region: \"us-east-1\" });\n * const gcp = gcpSecrets({ projectId: \"acme-prod\" });\n *\n * await autoPreload([aws, gcp], { envFiles: [\".env\", \"vault/.env.prod\"] });\n *\n * envx({\n * resolvers: {\n * [aws.name]: aws.resolve,\n * [gcp.name]: gcp.resolve,\n * },\n * });\n * ```\n */\nexport async function autoPreload(\n providers: readonly SecretProvider[],\n opts: AutoPreloadOptions,\n): Promise<{ readonly preloaded: Record<string, string[]> }> {\n const cwd = opts.cwd ?? process.cwd();\n const byProvider: Map<string, Set<string>> = new Map();\n for (const p of providers) byProvider.set(p.name, new Set());\n\n for (const file of opts.envFiles) {\n const abs = path.isAbsolute(file) ? file : path.resolve(cwd, file);\n if (!fs.existsSync(abs)) continue;\n const content = fs.readFileSync(abs, \"utf8\");\n let m: RegExpExecArray | null;\n REF_RE.lastIndex = 0;\n while ((m = REF_RE.exec(content)) !== null) {\n const provider = m[1];\n const id = m[2];\n if (provider === undefined || id === undefined) continue;\n const set = byProvider.get(provider);\n if (set) set.add(id);\n }\n }\n\n const preloaded: Record<string, string[]> = {};\n await Promise.all(\n providers.map(async (p) => {\n const ids = [...(byProvider.get(p.name) ?? [])];\n if (ids.length === 0) {\n preloaded[p.name] = [];\n return;\n }\n await p.preload(ids);\n preloaded[p.name] = ids;\n }),\n );\n return { preloaded };\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- Convenience ---------------------------------\n\n/**\n * Build a `resolvers:` map from a list of providers — the shape envx's\n * `resolvers` config expects. Saves you from repeating\n * `{ [p.name]: p.resolve }` for every provider.\n */\nexport function asResolvers(\n providers: readonly SecretProvider[],\n): Record<string, (id: string) => string | undefined> {\n const out: Record<string, (id: string) => string | undefined> = {};\n for (const p of providers) out[p.name] = (id) => p.resolve(id);\n return out;\n}\n\n// #endregion -----------------------------------------------\n"],"mappings":";;;AAQA,IAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0Cf,eAAsB,YACpB,WACA,MAC2D;CAC3D,MAAM,MAAM,KAAK,OAAO,QAAQ,KAAK;CACrC,MAAM,6BAAuC,IAAI,KAAK;CACtD,KAAK,MAAM,KAAK,WAAW,WAAW,IAAI,EAAE,sBAAM,IAAI,KAAK,CAAC;CAE5D,KAAK,MAAM,QAAQ,KAAK,UAAU;EAChC,MAAM,MAAM,KAAK,WAAW,KAAK,GAAG,OAAO,KAAK,QAAQ,KAAK,KAAK;EAClE,IAAI,CAAC,GAAG,WAAW,IAAI,EAAE;EACzB,MAAM,UAAU,GAAG,aAAa,KAAK,OAAO;EAC5C,IAAI;EACJ,OAAO,YAAY;EACnB,QAAQ,IAAI,OAAO,KAAK,QAAQ,MAAM,MAAM;GAC1C,MAAM,WAAW,EAAE;GACnB,MAAM,KAAK,EAAE;GACb,IAAI,aAAa,KAAA,KAAa,OAAO,KAAA,GAAW;GAChD,MAAM,MAAM,WAAW,IAAI,SAAS;GACpC,IAAI,KAAK,IAAI,IAAI,GAAG;;;CAIxB,MAAM,YAAsC,EAAE;CAC9C,MAAM,QAAQ,IACZ,UAAU,IAAI,OAAO,MAAM;EACzB,MAAM,MAAM,CAAC,GAAI,WAAW,IAAI,EAAE,KAAK,IAAI,EAAE,CAAE;EAC/C,IAAI,IAAI,WAAW,GAAG;GACpB,UAAU,EAAE,QAAQ,EAAE;GACtB;;EAEF,MAAM,EAAE,QAAQ,IAAI;EACpB,UAAU,EAAE,QAAQ;GACpB,CACH;CACD,OAAO,EAAE,WAAW;;;;;;;AAYtB,SAAgB,YACd,WACoD;CACpD,MAAM,MAA0D,EAAE;CAClE,KAAK,MAAM,KAAK,WAAW,IAAI,EAAE,SAAS,OAAO,EAAE,QAAQ,GAAG;CAC9D,OAAO"}
@@ -0,0 +1,54 @@
1
+ import { n as buildProvider, t as MissingSdkError } from "./types-COrFYR0z.js";
2
+ //#region src/plugins/aws.ts
3
+ /**
4
+ * AWS Secrets Manager provider.
5
+ *
6
+ * ```ts
7
+ * import { awsSecrets } from "@super-repo/envx/plugins/aws";
8
+ *
9
+ * const aws = awsSecrets({ region: "us-east-1" });
10
+ * await aws.preload(["prod/db", "prod/api-key"]);
11
+ *
12
+ * envx({
13
+ * resolvers: { [aws.name]: aws.resolve },
14
+ * });
15
+ * ```
16
+ *
17
+ * Reference shape in `.env*`:
18
+ *
19
+ * ```
20
+ * DATABASE_URL=${aws-secrets:prod/db}
21
+ * API_KEY=${aws-secrets:prod/api-key}
22
+ * ```
23
+ *
24
+ * The plugin uses `@aws-sdk/client-secrets-manager` (lazy-loaded —
25
+ * only required when `preload()` runs). Install it in your app:
26
+ *
27
+ * pnpm add @aws-sdk/client-secrets-manager
28
+ */
29
+ function awsSecrets(opts) {
30
+ const name = opts.name ?? "aws-secrets";
31
+ let client = opts.client ?? null;
32
+ let GetSecretValueCommand = null;
33
+ return buildProvider(name, async (id) => {
34
+ if (!client) try {
35
+ const sdk = await import(
36
+ /* @vite-ignore */
37
+ "@aws-sdk/client-secrets-manager"
38
+ );
39
+ client = new sdk.SecretsManagerClient({ region: opts.region });
40
+ GetSecretValueCommand = sdk.GetSecretValueCommand;
41
+ } catch {
42
+ throw new MissingSdkError("aws", "@aws-sdk/client-secrets-manager");
43
+ }
44
+ const cmd = GetSecretValueCommand ? new GetSecretValueCommand({ SecretId: id }) : { SecretId: id };
45
+ const r = await client.send(cmd);
46
+ if (typeof r.SecretString === "string") return r.SecretString;
47
+ if (r.SecretBinary) return Buffer.from(r.SecretBinary).toString("utf8");
48
+ throw new Error(`secret '${id}' has neither SecretString nor SecretBinary`);
49
+ });
50
+ }
51
+ //#endregion
52
+ export { awsSecrets as t };
53
+
54
+ //# sourceMappingURL=aws-DgcXfw-Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aws-DgcXfw-Y.js","names":[],"sources":["../../src/plugins/aws.ts"],"sourcesContent":["import { buildProvider, MissingSdkError, type SecretProvider } from \"./types.js\";\n\n// #region -- AWS Secrets Manager ---------------------------\n\nexport interface AwsSecretsOptions {\n /** AWS region the secrets live in (e.g. \"us-east-1\"). */\n readonly region: string;\n /**\n * Override the default SDK client. Useful for tests, for sharing a\n * client across plugins, or when your environment needs a custom\n * credential provider chain. The object only needs a `send(command)`\n * method that returns a `{ SecretString?: string; SecretBinary?: Uint8Array }`.\n */\n readonly client?: {\n send: (cmd: unknown) => Promise<{\n SecretString?: string;\n SecretBinary?: Uint8Array;\n }>;\n };\n /**\n * Custom name for this provider instance. Defaults to `\"aws-secrets\"`,\n * matching the conventional `${aws-secrets:my-id}` reference shape. If\n * you want multiple AWS regions to coexist, give each a distinct name\n * (`\"aws-us\"`, `\"aws-eu\"`) and reference accordingly.\n */\n readonly name?: string;\n}\n\n/**\n * AWS Secrets Manager provider.\n *\n * ```ts\n * import { awsSecrets } from \"@super-repo/envx/plugins/aws\";\n *\n * const aws = awsSecrets({ region: \"us-east-1\" });\n * await aws.preload([\"prod/db\", \"prod/api-key\"]);\n *\n * envx({\n * resolvers: { [aws.name]: aws.resolve },\n * });\n * ```\n *\n * Reference shape in `.env*`:\n *\n * ```\n * DATABASE_URL=${aws-secrets:prod/db}\n * API_KEY=${aws-secrets:prod/api-key}\n * ```\n *\n * The plugin uses `@aws-sdk/client-secrets-manager` (lazy-loaded —\n * only required when `preload()` runs). Install it in your app:\n *\n * pnpm add @aws-sdk/client-secrets-manager\n */\nexport function awsSecrets(opts: AwsSecretsOptions): SecretProvider {\n const name = opts.name ?? \"aws-secrets\";\n const injected = opts.client;\n let client: AwsSecretsOptions[\"client\"] | null = injected ?? null;\n let GetSecretValueCommand:\n | (new (input: { SecretId: string }) => unknown)\n | null = null;\n\n return buildProvider(name, async (id) => {\n // If the caller didn't inject a client, lazy-load the SDK. With an\n // injected client the SDK is bypassed entirely — useful for tests\n // and for users who want a custom credential chain.\n if (!client) {\n try {\n // Avoid `typeof import(...)` here — that would force tsc to\n // resolve `@aws-sdk/client-secrets-manager` at compile time\n // and the SDKs are intentionally optional. Duck-type the\n // shapes we touch instead.\n interface AwsSdk {\n readonly SecretsManagerClient: new (cfg: { region: string }) => {\n send(cmd: unknown): Promise<{ SecretString?: string; SecretBinary?: Uint8Array }>;\n };\n readonly GetSecretValueCommand: new (input: { SecretId: string }) => unknown;\n }\n // Indirected through a variable so TS doesn't try to resolve\n // the optional SDK at compile time (it's a peer dep).\n const specifier = \"@aws-sdk/client-secrets-manager\";\n const sdk = (await import(/* @vite-ignore */ specifier)) as unknown as AwsSdk;\n client = new sdk.SecretsManagerClient({\n region: opts.region,\n }) as unknown as AwsSecretsOptions[\"client\"];\n GetSecretValueCommand = sdk.GetSecretValueCommand;\n } catch {\n throw new MissingSdkError(\"aws\", \"@aws-sdk/client-secrets-manager\");\n }\n }\n\n // For an injected client we hand `send()` a plain object — the test\n // / custom client decides what to do with it. For the real SDK\n // client we use the proper Command class.\n const cmd = GetSecretValueCommand\n ? new GetSecretValueCommand({ SecretId: id })\n : ({ SecretId: id } as unknown);\n const r = await client!.send(cmd);\n if (typeof r.SecretString === \"string\") return r.SecretString;\n if (r.SecretBinary) {\n return Buffer.from(r.SecretBinary).toString(\"utf8\");\n }\n throw new Error(`secret '${id}' has neither SecretString nor SecretBinary`);\n });\n}\n\n// #endregion -----------------------------------------------\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,SAAgB,WAAW,MAAyC;CAClE,MAAM,OAAO,KAAK,QAAQ;CAE1B,IAAI,SADa,KAAK,UACuC;CAC7D,IAAI,wBAEO;CAEX,OAAO,cAAc,MAAM,OAAO,OAAO;EAIvC,IAAI,CAAC,QACH,IAAI;GAcF,MAAM,MAAO,MAAM;;IAA0B;;GAC7C,SAAS,IAAI,IAAI,qBAAqB,EACpC,QAAQ,KAAK,QACd,CAAC;GACF,wBAAwB,IAAI;UACtB;GACN,MAAM,IAAI,gBAAgB,OAAO,kCAAkC;;EAOvE,MAAM,MAAM,wBACR,IAAI,sBAAsB,EAAE,UAAU,IAAI,CAAC,GAC1C,EAAE,UAAU,IAAI;EACrB,MAAM,IAAI,MAAM,OAAQ,KAAK,IAAI;EACjC,IAAI,OAAO,EAAE,iBAAiB,UAAU,OAAO,EAAE;EACjD,IAAI,EAAE,cACJ,OAAO,OAAO,KAAK,EAAE,aAAa,CAAC,SAAS,OAAO;EAErD,MAAM,IAAI,MAAM,WAAW,GAAG,6CAA6C;GAC3E"}
@@ -0,0 +1,62 @@
1
+ import { n as buildProvider, t as MissingSdkError } from "./types-COrFYR0z.js";
2
+ //#region src/plugins/azure.ts
3
+ /**
4
+ * Azure Key Vault provider.
5
+ *
6
+ * ```ts
7
+ * import { azureKeyVault } from "@super-repo/envx/plugins/azure";
8
+ *
9
+ * const az = azureKeyVault({ vaultUrl: "https://my-vault.vault.azure.net" });
10
+ * await az.preload(["prod-db", "prod-api"]);
11
+ *
12
+ * envx({ resolvers: { [az.name]: az.resolve } });
13
+ * ```
14
+ *
15
+ * Reference shape:
16
+ *
17
+ * ```
18
+ * DB_URL=${azure-keyvault:prod-db}
19
+ * API_KEY=${azure-keyvault:prod-api@<version>}
20
+ * ```
21
+ *
22
+ * Uses `@azure/keyvault-secrets` + `@azure/identity` (lazy-loaded):
23
+ *
24
+ * pnpm add @azure/keyvault-secrets @azure/identity
25
+ */
26
+ function azureKeyVault(opts) {
27
+ const name = opts.name ?? "azure-keyvault";
28
+ let client = opts.client ?? null;
29
+ return buildProvider(name, async (id) => {
30
+ if (!client) {
31
+ let secretsSdk = null;
32
+ let credential = opts.credential;
33
+ try {
34
+ secretsSdk = await import(
35
+ /* @vite-ignore */
36
+ "@azure/keyvault-secrets"
37
+ );
38
+ } catch {
39
+ throw new MissingSdkError("azure", "@azure/keyvault-secrets");
40
+ }
41
+ if (!credential) try {
42
+ credential = new (await (import(
43
+ /* @vite-ignore */
44
+ "@azure/identity"
45
+ ))).DefaultAzureCredential();
46
+ } catch {
47
+ throw new MissingSdkError("azure", "@azure/identity");
48
+ }
49
+ client = new secretsSdk.SecretClient(opts.vaultUrl, credential);
50
+ }
51
+ const at = id.indexOf("@");
52
+ const secretName = at >= 0 ? id.slice(0, at) : id;
53
+ const version = at >= 0 ? id.slice(at + 1) : void 0;
54
+ const result = version ? await client.getSecret(secretName, { version }) : await client.getSecret(secretName);
55
+ if (typeof result.value !== "string") throw new Error(`secret '${id}' had no value`);
56
+ return result.value;
57
+ });
58
+ }
59
+ //#endregion
60
+ export { azureKeyVault as t };
61
+
62
+ //# sourceMappingURL=azure-Cmh5-dPn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-Cmh5-dPn.js","names":[],"sources":["../../src/plugins/azure.ts"],"sourcesContent":["import { buildProvider, MissingSdkError, type SecretProvider } from \"./types.js\";\n\n// #region -- Azure Key Vault -------------------------------\n\nexport interface AzureKeyVaultOptions {\n /** Vault URL (e.g. \"https://my-vault.vault.azure.net\"). */\n readonly vaultUrl: string;\n /**\n * Custom credential. Defaults to `new DefaultAzureCredential()` from\n * `@azure/identity` — which walks env vars, managed identity, Azure\n * CLI, etc. Override for tests or specialized credential chains.\n */\n readonly credential?: unknown;\n /** Pre-built SecretClient for tests. */\n readonly client?: {\n getSecret: (name: string, opts?: { version?: string }) => Promise<{\n value?: string | null;\n }>;\n };\n /** Provider name, defaults to `\"azure-keyvault\"`. */\n readonly name?: string;\n}\n\n/**\n * Azure Key Vault provider.\n *\n * ```ts\n * import { azureKeyVault } from \"@super-repo/envx/plugins/azure\";\n *\n * const az = azureKeyVault({ vaultUrl: \"https://my-vault.vault.azure.net\" });\n * await az.preload([\"prod-db\", \"prod-api\"]);\n *\n * envx({ resolvers: { [az.name]: az.resolve } });\n * ```\n *\n * Reference shape:\n *\n * ```\n * DB_URL=${azure-keyvault:prod-db}\n * API_KEY=${azure-keyvault:prod-api@<version>}\n * ```\n *\n * Uses `@azure/keyvault-secrets` + `@azure/identity` (lazy-loaded):\n *\n * pnpm add @azure/keyvault-secrets @azure/identity\n */\nexport function azureKeyVault(opts: AzureKeyVaultOptions): SecretProvider {\n const name = opts.name ?? \"azure-keyvault\";\n let client: AzureKeyVaultOptions[\"client\"] | null = opts.client ?? null;\n\n return buildProvider(name, async (id) => {\n if (!client) {\n // Duck-typed SDK shapes — avoids tsc's `typeof import(\"...\")`\n // requirement that the optional Azure SDKs be installed.\n interface AzureSecretsSdk {\n readonly SecretClient: new (vaultUrl: string, credential: unknown) => unknown;\n }\n interface AzureIdentitySdk {\n readonly DefaultAzureCredential: new () => unknown;\n }\n let secretsSdk: AzureSecretsSdk | null = null;\n let credential = opts.credential;\n try {\n const secretsSpecifier = \"@azure/keyvault-secrets\";\n secretsSdk = (await import(/* @vite-ignore */ secretsSpecifier)) as unknown as AzureSecretsSdk;\n } catch {\n throw new MissingSdkError(\"azure\", \"@azure/keyvault-secrets\");\n }\n if (!credential) {\n try {\n const identitySpecifier = \"@azure/identity\";\n const identity = (await import(/* @vite-ignore */ identitySpecifier)) as unknown as AzureIdentitySdk;\n credential = new identity.DefaultAzureCredential();\n } catch {\n throw new MissingSdkError(\"azure\", \"@azure/identity\");\n }\n }\n client = new secretsSdk.SecretClient(\n opts.vaultUrl,\n credential,\n ) as unknown as AzureKeyVaultOptions[\"client\"];\n }\n\n const at = id.indexOf(\"@\");\n const secretName = at >= 0 ? id.slice(0, at) : id;\n const version = at >= 0 ? id.slice(at + 1) : undefined;\n const result = version\n ? await client!.getSecret(secretName, { version })\n : await client!.getSecret(secretName);\n if (typeof result.value !== \"string\") {\n throw new Error(`secret '${id}' had no value`);\n }\n return result.value;\n });\n}\n\n// #endregion -----------------------------------------------\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,SAAgB,cAAc,MAA4C;CACxE,MAAM,OAAO,KAAK,QAAQ;CAC1B,IAAI,SAAgD,KAAK,UAAU;CAEnE,OAAO,cAAc,MAAM,OAAO,OAAO;EACvC,IAAI,CAAC,QAAQ;GASX,IAAI,aAAqC;GACzC,IAAI,aAAa,KAAK;GACtB,IAAI;IAEF,aAAc,MAAM;;KAA0B;;WACxC;IACN,MAAM,IAAI,gBAAgB,SAAS,0BAA0B;;GAE/D,IAAI,CAAC,YACH,IAAI;IAGF,aAAa,KAAI,OADO;;KAA0B;IACxB,wBAAwB;WAC5C;IACN,MAAM,IAAI,gBAAgB,SAAS,kBAAkB;;GAGzD,SAAS,IAAI,WAAW,aACtB,KAAK,UACL,WACD;;EAGH,MAAM,KAAK,GAAG,QAAQ,IAAI;EAC1B,MAAM,aAAa,MAAM,IAAI,GAAG,MAAM,GAAG,GAAG,GAAG;EAC/C,MAAM,UAAU,MAAM,IAAI,GAAG,MAAM,KAAK,EAAE,GAAG,KAAA;EAC7C,MAAM,SAAS,UACX,MAAM,OAAQ,UAAU,YAAY,EAAE,SAAS,CAAC,GAChD,MAAM,OAAQ,UAAU,WAAW;EACvC,IAAI,OAAO,OAAO,UAAU,UAC1B,MAAM,IAAI,MAAM,WAAW,GAAG,gBAAgB;EAEhD,OAAO,OAAO;GACd"}
@@ -1,4 +1,4 @@
1
- import { A as isEncrypted, C as parseEnv, D as decryptValueAsymmetric, S as log, T as toRecord, _ as resolveCwdOrWorkspace, a as auditFiles, b as expandEnvSrc, c as encryptFiles, f as DEFAULT_NODE_ENV_MAP, g as loadEnv, h as listEnvFiles, l as defaultKeysPath, m as findWorkspaceRoot, o as rotateFiles, p as detectEnvironment, r as loadDotenvxConfig, s as decryptFiles, t as writeProcessed, u as readKeysFile, v as resolveEnvPaths, x as expandRecord, y as validateCmdVariable } from "./src-Ln2uXfYC.js";
1
+ import { A as loadEnv, C as readKeysFile, E as detectEnvironment, F as expandRecord, I as log, L as parseEnv, M as resolveEnvPaths, N as validateCmdVariable, O as findWorkspaceRoot, P as expandEnvSrc, T as DEFAULT_NODE_ENV_MAP, V as decryptValueAsymmetric, W as isEncrypted, _ as defaultKeysPath, a as auditFiles, c as encryptFiles, j as resolveCwdOrWorkspace, k as listEnvFiles, o as rotateFiles, r as loadDotenvxConfig, s as decryptFiles, t as writeProcessed, z as toRecord } from "./libs-CqVa6LY9.js";
2
2
  import * as fs from "fs";
3
3
  import * as path from "path";
4
4
  import yargs from "yargs";
@@ -1916,4 +1916,4 @@ function createCli(argvInput) {
1916
1916
  //#endregion
1917
1917
  export { createCli as t };
1918
1918
 
1919
- //# sourceMappingURL=commands-KUyDszno.js.map
1919
+ //# sourceMappingURL=commands-Br0Z7uUF.js.map