typed-settings 0.1.4 → 0.2.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 (81) hide show
  1. package/README.md +14 -7
  2. package/bin/typed-settings.mjs +5 -0
  3. package/dist/adapters/joi.cjs +1 -26
  4. package/dist/adapters/joi.d.cts +2 -1
  5. package/dist/adapters/joi.d.ts +2 -1
  6. package/dist/adapters/joi.js +1 -1
  7. package/dist/adapters/superstruct.cjs +1 -26
  8. package/dist/adapters/superstruct.js +1 -1
  9. package/dist/adapters/yup.cjs +1 -25
  10. package/dist/adapters/yup.js +1 -1
  11. package/dist/adapters/zod.cjs +3 -36
  12. package/dist/adapters/zod.js +1 -33
  13. package/dist/check-XVFZEVNV.js +1 -0
  14. package/dist/chunk-4EAMKDNK.js +3 -0
  15. package/dist/chunk-5D2AQWDG.js +1 -0
  16. package/dist/chunk-C6CG2D4B.js +2 -0
  17. package/dist/chunk-FQYD5ZKE.js +1 -0
  18. package/dist/chunk-NQDE3WLR.js +3 -0
  19. package/dist/chunk-RURPDXIJ.js +1 -0
  20. package/dist/cli/main.cjs +36 -2225
  21. package/dist/cli/main.js +32 -806
  22. package/dist/errors-JkkOM0u-.d.cts +25 -0
  23. package/dist/errors-JkkOM0u-.d.ts +25 -0
  24. package/dist/framework/next.cjs +5 -1158
  25. package/dist/framework/next.d.cts +3 -3
  26. package/dist/framework/next.d.ts +3 -3
  27. package/dist/framework/next.js +1 -15
  28. package/dist/framework/vite.cjs +5 -1156
  29. package/dist/framework/vite.d.cts +8 -3
  30. package/dist/framework/vite.d.ts +8 -3
  31. package/dist/framework/vite.js +1 -14
  32. package/dist/index.cjs +5 -1181
  33. package/dist/index.d.cts +38 -7
  34. package/dist/index.d.ts +38 -7
  35. package/dist/index.js +1 -6
  36. package/dist/node.cjs +6 -1241
  37. package/dist/node.d.cts +23 -9
  38. package/dist/node.d.ts +23 -9
  39. package/dist/node.js +1 -7
  40. package/dist/{types-B_Dc2L4T.d.cts → types-CcsYDAdO.d.cts} +23 -1
  41. package/dist/{types-B_Dc2L4T.d.ts → types-CcsYDAdO.d.ts} +23 -1
  42. package/dist/vault/aws.cjs +4 -217
  43. package/dist/vault/aws.d.cts +1 -1
  44. package/dist/vault/aws.d.ts +1 -1
  45. package/dist/vault/aws.js +2 -167
  46. package/dist/vault/hashicorp.cjs +4 -183
  47. package/dist/vault/hashicorp.d.cts +1 -1
  48. package/dist/vault/hashicorp.d.ts +1 -1
  49. package/dist/vault/hashicorp.js +2 -77
  50. package/dist/vault/http.cjs +4 -185
  51. package/dist/vault/http.d.cts +1 -1
  52. package/dist/vault/http.d.ts +1 -1
  53. package/dist/vault/http.js +2 -79
  54. package/package.json +2 -3
  55. package/dist/chunk-33M5GIKQ.js +0 -13
  56. package/dist/chunk-A5TCQJ7L.js +0 -65
  57. package/dist/chunk-DEP5SD4J.js +0 -233
  58. package/dist/chunk-EE6LXNJV.js +0 -34
  59. package/dist/chunk-F6DX3HXZ.js +0 -101
  60. package/dist/chunk-OVFMKC2O.js +0 -15
  61. package/dist/chunk-RQC6OMVV.js +0 -86
  62. package/dist/chunk-UFUHHR2J.js +0 -38
  63. package/dist/chunk-YVJEZPPZ.js +0 -989
  64. package/dist/errors-itGaU4Q8.d.cts +0 -17
  65. package/dist/errors-itGaU4Q8.d.ts +0 -17
  66. package/dist/formats/env.cjs +0 -103
  67. package/dist/formats/env.d.cts +0 -8
  68. package/dist/formats/env.d.ts +0 -8
  69. package/dist/formats/env.js +0 -1
  70. package/dist/formats/json.cjs +0 -15
  71. package/dist/formats/json.d.cts +0 -7
  72. package/dist/formats/json.d.ts +0 -7
  73. package/dist/formats/json.js +0 -1
  74. package/dist/formats/toml.cjs +0 -17
  75. package/dist/formats/toml.d.cts +0 -7
  76. package/dist/formats/toml.d.ts +0 -7
  77. package/dist/formats/toml.js +0 -1
  78. package/dist/formats/yaml.cjs +0 -40
  79. package/dist/formats/yaml.d.cts +0 -8
  80. package/dist/formats/yaml.d.ts +0 -8
  81. package/dist/formats/yaml.js +0 -1
@@ -1,183 +1,4 @@
1
- 'use strict';
2
-
3
- // src/errors.ts
4
- function byteLengthUtf8(text) {
5
- try {
6
- const g = globalThis;
7
- if (g.TextEncoder) return new g.TextEncoder().encode(text).length;
8
- if (g.Buffer) return g.Buffer.byteLength(text, "utf8");
9
- } catch {
10
- }
11
- return text.length;
12
- }
13
- var ConfigError = class extends Error {
14
- code = "E_INVALID_CONFIG";
15
- issues;
16
- constructor(issues, code = "E_INVALID_CONFIG") {
17
- const lines = issues.map(
18
- (i) => `- ${i.path} (from ${i.from}): ${i.message}`
19
- );
20
- super(`Invalid config (${issues.length} issue${issues.length === 1 ? "" : "s"}):
21
- ${lines.join("\n")}`);
22
- this.name = "ConfigError";
23
- this.code = code;
24
- this.issues = issues;
25
- }
26
- };
27
-
28
- // src/vault/shared.ts
29
- function getFetch(fetchFn) {
30
- if (fetchFn) return fetchFn;
31
- const g = globalThis;
32
- if (g.fetch) return g.fetch.bind(globalThis);
33
- throw new ConfigError(
34
- [{ path: "<provider>", from: "vault", message: "E_NO_FETCH: global fetch unavailable" }],
35
- "E_NO_FETCH"
36
- );
37
- }
38
- function sameHost(a, b) {
39
- return new URL(a).host === new URL(b).host;
40
- }
41
- var SENSITIVE_HEADER_RE = /authorization|token|secret|api[-_]?key|cookie|auth/i;
42
- function stripSensitiveForCrossHost(headers) {
43
- const next = new Headers();
44
- headers.forEach((value, key) => {
45
- if (!SENSITIVE_HEADER_RE.test(key)) next.set(key, value);
46
- });
47
- return next;
48
- }
49
- async function fetchWithRedirectGuard(url, init, fetchFn, maxRedirects = 2) {
50
- let current = url;
51
- let headers = new Headers(init.headers);
52
- for (let i = 0; i <= maxRedirects; i++) {
53
- const res = await fetchFn(current, { ...init, headers, redirect: "manual" });
54
- const status = res.status;
55
- if (![301, 302, 303, 307, 308].includes(status)) return res;
56
- const loc = res.headers.get("location");
57
- if (!loc) return res;
58
- let next;
59
- try {
60
- next = new URL(loc, current).toString();
61
- } catch {
62
- throw new ConfigError(
63
- [{ path: current, from: "vault", message: "E_REDIRECT: invalid Location header" }],
64
- "E_REDIRECT"
65
- );
66
- }
67
- if (i === maxRedirects) {
68
- throw new ConfigError(
69
- [{ path: next, from: "vault", message: "E_REDIRECT: too many redirects" }],
70
- "E_REDIRECT"
71
- );
72
- }
73
- if (!sameHost(current, next)) headers = stripSensitiveForCrossHost(headers);
74
- current = next;
75
- }
76
- throw new ConfigError([{ path: url, from: "vault", message: "E_REDIRECT" }], "E_REDIRECT");
77
- }
78
- function normalizeSecretMap(raw, providerName, opts) {
79
- const clean = (v) => {
80
- if (v === null || v === void 0) return void 0;
81
- let s = typeof v === "string" ? v : String(v);
82
- s = s.replace(/\r?\n$/, "");
83
- return s;
84
- };
85
- const out = {};
86
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
87
- throw new ConfigError(
88
- [{ path: "<root>", from: providerName, message: "E_SHAPE: provider returned non-object" }],
89
- "E_SHAPE"
90
- );
91
- }
92
- for (const [k, v] of Object.entries(raw)) {
93
- if (v !== null && typeof v === "object" && !Array.isArray(v)) {
94
- out[k] = v;
95
- continue;
96
- }
97
- const c = clean(v);
98
- if (c !== void 0) out[k] = c;
99
- }
100
- return out;
101
- }
102
- function statusToCode(status) {
103
- if (status === 403 || status === 401) return "E_DENIED";
104
- if (status === 404) return "E_NOT_FOUND";
105
- if (status === 429) return "E_THROTTLED";
106
- if (status >= 500) return "E_UPSTREAM";
107
- return "E_PROVIDER";
108
- }
109
-
110
- // src/vault/hashicorp.ts
111
- function tokenFromEnv(explicit) {
112
- if (explicit !== void 0) return explicit || void 0;
113
- const g = globalThis;
114
- return g.process?.env?.["VAULT_TOKEN"];
115
- }
116
- function hashicorpProvider(opts) {
117
- const mount = (opts.mount ?? "secret").replace(/^\/+|\/+$/g, "");
118
- const timeoutMs = opts.timeoutMs ?? 5e3;
119
- const maxBytes = opts.maxBytes ?? 1024 * 1024;
120
- const name = `hashicorp://${mount}/${opts.path}`;
121
- let inflight = null;
122
- async function doLoad() {
123
- const token = tokenFromEnv(opts.auth?.token);
124
- const fetchFn = getFetch(opts.fetchFn);
125
- const base = opts.url.replace(/\/+$/g, "");
126
- const p = opts.path.replace(/^\/+/, "");
127
- const qs = opts.version !== void 0 ? `?version=${encodeURIComponent(String(opts.version))}` : "";
128
- const url = `${base}/v1/${mount}/${p}${qs}`;
129
- const headers = new Headers();
130
- if (token) headers.set("X-Vault-Token", token);
131
- headers.set("Accept", "application/json");
132
- let res;
133
- try {
134
- res = await fetchWithRedirectGuard(
135
- url,
136
- { headers, signal: AbortSignal.timeout(timeoutMs) },
137
- fetchFn
138
- );
139
- } catch (e) {
140
- if (e instanceof ConfigError) throw e;
141
- const err = e;
142
- const isTimeout = /timeout|abort/i.test(err?.name + err?.message);
143
- throw new ConfigError(
144
- [{ path: p, from: name, message: `${isTimeout ? "E_TIMEOUT" : "E_CONN"}: ${err?.message ?? String(e)}` }],
145
- isTimeout ? "E_TIMEOUT" : "E_CONN"
146
- );
147
- }
148
- if (!res.ok) {
149
- const code = statusToCode(res.status);
150
- throw new ConfigError([{ path: p, from: name, message: `${code}: HTTP ${res.status}` }], code);
151
- }
152
- const text = await res.text();
153
- if (byteLengthUtf8(text) > maxBytes) {
154
- throw new ConfigError([{ path: p, from: name, message: "E_TOO_LARGE: secret >cap" }], "E_TOO_LARGE");
155
- }
156
- let json;
157
- try {
158
- json = JSON.parse(text);
159
- } catch {
160
- throw new ConfigError([{ path: p, from: name, message: "E_PARSE: invalid JSON" }], "E_PARSE");
161
- }
162
- const data = json.data;
163
- const isKv2 = !!data && typeof data === "object" && "data" in data && "metadata" in data;
164
- const inner = isKv2 ? data.data : data;
165
- if (!inner || typeof inner !== "object" || Array.isArray(inner)) {
166
- throw new ConfigError([{ path: p, from: name, message: "E_SHAPE: missing data" }], "E_SHAPE");
167
- }
168
- return normalizeSecretMap(inner, name);
169
- }
170
- return {
171
- name,
172
- load() {
173
- if (!inflight) {
174
- inflight = doLoad().finally(() => {
175
- inflight = null;
176
- });
177
- }
178
- return inflight;
179
- }
180
- };
181
- }
182
-
183
- exports.hashicorpProvider = hashicorpProvider;
1
+ 'use strict';function R(e){try{let n=globalThis;if(n.TextEncoder)return new n.TextEncoder().encode(e).length;if(n.Buffer)return n.Buffer.byteLength(e,"utf8")}catch{}return e.length}var s=class extends Error{code="E_INVALID_CONFIG";issues;static[Symbol.hasInstance](n){return typeof n=="object"&&n!==null&&n.name==="ConfigError"&&typeof n.code=="string"&&Array.isArray(n.issues)}constructor(n=[],o="E_INVALID_CONFIG"){let c=n.map(t=>`- ${t.path} (from ${t.from}): ${t.message}`);super(n.length===0?"Invalid config: unknown error (no issues attached)":`Invalid config (${n.length} issue${n.length===1?"":"s"}):
2
+ ${c.join(`
3
+ `)}`),this.name="ConfigError",this.code=o,this.issues=n;}};function A(e){return e.toLowerCase()==="__proto__"}function k(e){if(e)return e;let n=globalThis;if(n.fetch)return n.fetch.bind(globalThis);throw new s([{path:"<provider>",from:"vault",message:"E_NO_FETCH: global fetch unavailable"}],"E_NO_FETCH")}function j(e,n){try{return new URL(e).host===new URL(n).host}catch{return false}}var M=/authorization|token|secret|api[-_]?key|cookie|auth/i;function F(e,n){try{return new URL(e).protocol==="https:"&&new URL(n).protocol!=="https:"}catch{return false}}function L(e){let n=new Headers;return e.forEach((o,c)=>{M.test(c)||n.set(c,o);}),n}async function b(e,n,o,c=2){let t=e,a=new Headers(n.headers);for(let i=0;i<=c;i++){let r=await o(t,{...n,headers:a,redirect:"manual"}),u=r.status;if(![301,302,303,307,308].includes(u))return r;let m=r.headers.get("location");if(!m)return r;let f;try{f=new URL(m,t).toString();}catch{throw new s([{path:t,from:"vault",message:"E_REDIRECT: invalid Location header"}],"E_REDIRECT")}if(i===c)throw new s([{path:f,from:"vault",message:"E_REDIRECT: too many redirects"}],"E_REDIRECT");(!j(t,f)||F(t,f))&&(a=L(a)),t=f;}throw new s([{path:e,from:"vault",message:"E_REDIRECT"}],"E_REDIRECT")}function T(e,n,o){let t=i=>{if(i==null)return;let r=typeof i=="string"?i:String(i);return (r=r.replace(/\r?\n$/,"")),r},a={};if(!e||typeof e!="object"||Array.isArray(e))throw new s([{path:"<root>",from:n,message:"E_SHAPE: provider returned non-object"}],"E_SHAPE");for(let[i,r]of Object.entries(e)){if(A(i))throw new s([{path:i,from:n,message:"E_PROTO: forbidden key"}],"E_PROTO");if(r!==null&&typeof r=="object"&&!Array.isArray(r)){a[i]=r;continue}let u=t(r);u!==void 0&&(a[i]=u);}return a}function O(e){return e===403||e===401?"E_DENIED":e===404?"E_NOT_FOUND":e===429?"E_THROTTLED":e===408||e===504?"E_TIMEOUT":e>=500?"E_UPSTREAM":"E_PROVIDER"}function x(e,n){let o=AbortSignal;if(typeof o.timeout=="function")try{return o.timeout(e)}catch{return}}function E(e,n,o){if(!Number.isFinite(e)||e<=0)throw new s([{path:n,from:o,message:`E_USAGE: ${n} must be a positive finite number`}],"E_USAGE")}async function P(e,n,o,c){let t,a=new Promise((i,r)=>{t=setTimeout(()=>r(new s([{path:o,from:c,message:"E_TIMEOUT: request timed out"}],"E_TIMEOUT")),n);});e.catch(()=>{});try{return await Promise.race([e,a])}finally{t&&clearTimeout(t);}}async function I(e,n,o,c,t){let a,i=new Promise((r,u)=>{a=setTimeout(()=>u(new s([{path:n,from:o,message:"E_TIMEOUT: response body timed out"}],"E_TIMEOUT")),t);});try{let r=e.text();r.catch(()=>{});let u=await Promise.race([r,i]);if(R(u)>c)throw new s([{path:n,from:o,message:"E_TOO_LARGE"}],"E_TOO_LARGE");return u}finally{a&&clearTimeout(a);}}function N(e){return e!==void 0?e||void 0:globalThis.process?.env?.VAULT_TOKEN}function G(e){let n=(e.mount??"secret").replace(/^\/+|\/+$/g,""),o=e.timeoutMs??5e3,c=e.maxBytes??1024*1024;E(o,"timeoutMs","hashicorp"),E(c,"maxBytes","hashicorp");let t=`hashicorp://${n}/${e.path}`,a=null;async function i(){let r=N(e.auth?.token),u=k(e.fetchFn),m=e.url.replace(/\/+$/g,""),f=e.path.replace(/^\/+/,""),S=e.version!==void 0?`?version=${encodeURIComponent(String(e.version))}`:"",C=`${m}/v1/${n}/${f}${S}`,h=new Headers;r&&h.set("X-Vault-Token",r),h.has("Accept")||h.set("Accept","application/json");let d;try{d=await P(b(C,{headers:h,signal:x(o)},u),o,f,t);}catch(l){if(l instanceof s)throw l;let w=l,y=/timeout|abort/i.test(w?.name+w?.message);throw new s([{path:f,from:t,message:`${y?"E_TIMEOUT":"E_CONN"}: ${w?.message??String(l)}`}],y?"E_TIMEOUT":"E_CONN")}if(!d.ok){let l=O(d.status);throw new s([{path:f,from:t,message:`${l}: HTTP ${d.status}`}],l)}let $=await I(d,f,t,c,o),_;try{_=JSON.parse($);}catch{throw new s([{path:f,from:t,message:"E_PARSE: invalid JSON"}],"E_PARSE")}let g=_.data,p=!!g&&typeof g=="object"&&Object.hasOwn(g,"data")&&Object.hasOwn(g,"metadata")?g.data:g;if(!p||typeof p!="object"||Array.isArray(p))throw new s([{path:f,from:t,message:"E_SHAPE: missing data"}],"E_SHAPE");return T(p,t)}return {name:t,load(){return a||(a=i().finally(()=>{a=null;})),a}}}
4
+ exports.hashicorpProvider=G;
@@ -1,4 +1,4 @@
1
- import { a as SecretProvider } from '../types-B_Dc2L4T.cjs';
1
+ import { a as SecretProvider } from '../types-CcsYDAdO.cjs';
2
2
  import { F as FetchFn } from '../shared-CucO_XsG.cjs';
3
3
  import '@standard-schema/spec';
4
4
 
@@ -1,4 +1,4 @@
1
- import { a as SecretProvider } from '../types-B_Dc2L4T.js';
1
+ import { a as SecretProvider } from '../types-CcsYDAdO.js';
2
2
  import { F as FetchFn } from '../shared-CucO_XsG.js';
3
3
  import '@standard-schema/spec';
4
4
 
@@ -1,77 +1,2 @@
1
- import { getFetch, fetchWithRedirectGuard, statusToCode, normalizeSecretMap } from '../chunk-RQC6OMVV.js';
2
- import { ConfigError, byteLengthUtf8 } from '../chunk-EE6LXNJV.js';
3
-
4
- // src/vault/hashicorp.ts
5
- function tokenFromEnv(explicit) {
6
- if (explicit !== void 0) return explicit || void 0;
7
- const g = globalThis;
8
- return g.process?.env?.["VAULT_TOKEN"];
9
- }
10
- function hashicorpProvider(opts) {
11
- const mount = (opts.mount ?? "secret").replace(/^\/+|\/+$/g, "");
12
- const timeoutMs = opts.timeoutMs ?? 5e3;
13
- const maxBytes = opts.maxBytes ?? 1024 * 1024;
14
- const name = `hashicorp://${mount}/${opts.path}`;
15
- let inflight = null;
16
- async function doLoad() {
17
- const token = tokenFromEnv(opts.auth?.token);
18
- const fetchFn = getFetch(opts.fetchFn);
19
- const base = opts.url.replace(/\/+$/g, "");
20
- const p = opts.path.replace(/^\/+/, "");
21
- const qs = opts.version !== void 0 ? `?version=${encodeURIComponent(String(opts.version))}` : "";
22
- const url = `${base}/v1/${mount}/${p}${qs}`;
23
- const headers = new Headers();
24
- if (token) headers.set("X-Vault-Token", token);
25
- headers.set("Accept", "application/json");
26
- let res;
27
- try {
28
- res = await fetchWithRedirectGuard(
29
- url,
30
- { headers, signal: AbortSignal.timeout(timeoutMs) },
31
- fetchFn
32
- );
33
- } catch (e) {
34
- if (e instanceof ConfigError) throw e;
35
- const err = e;
36
- const isTimeout = /timeout|abort/i.test(err?.name + err?.message);
37
- throw new ConfigError(
38
- [{ path: p, from: name, message: `${isTimeout ? "E_TIMEOUT" : "E_CONN"}: ${err?.message ?? String(e)}` }],
39
- isTimeout ? "E_TIMEOUT" : "E_CONN"
40
- );
41
- }
42
- if (!res.ok) {
43
- const code = statusToCode(res.status);
44
- throw new ConfigError([{ path: p, from: name, message: `${code}: HTTP ${res.status}` }], code);
45
- }
46
- const text = await res.text();
47
- if (byteLengthUtf8(text) > maxBytes) {
48
- throw new ConfigError([{ path: p, from: name, message: "E_TOO_LARGE: secret >cap" }], "E_TOO_LARGE");
49
- }
50
- let json;
51
- try {
52
- json = JSON.parse(text);
53
- } catch {
54
- throw new ConfigError([{ path: p, from: name, message: "E_PARSE: invalid JSON" }], "E_PARSE");
55
- }
56
- const data = json.data;
57
- const isKv2 = !!data && typeof data === "object" && "data" in data && "metadata" in data;
58
- const inner = isKv2 ? data.data : data;
59
- if (!inner || typeof inner !== "object" || Array.isArray(inner)) {
60
- throw new ConfigError([{ path: p, from: name, message: "E_SHAPE: missing data" }], "E_SHAPE");
61
- }
62
- return normalizeSecretMap(inner, name);
63
- }
64
- return {
65
- name,
66
- load() {
67
- if (!inflight) {
68
- inflight = doLoad().finally(() => {
69
- inflight = null;
70
- });
71
- }
72
- return inflight;
73
- }
74
- };
75
- }
76
-
77
- export { hashicorpProvider };
1
+ import {f,a,h,b,e,d as d$1,i,c}from'../chunk-5D2AQWDG.js';import {d}from'../chunk-NQDE3WLR.js';function R(e){return e!==void 0?e||void 0:globalThis.process?.env?.VAULT_TOKEN}function x(e$1){let d$2=(e$1.mount??"secret").replace(/^\/+|\/+$/g,""),i$1=e$1.timeoutMs??5e3,p=e$1.maxBytes??1024*1024;f(i$1,"timeoutMs","hashicorp"),f(p,"maxBytes","hashicorp");let t=`hashicorp://${d$2}/${e$1.path}`,c$1=null;async function P(){let g=R(e$1.auth?.token),S=a(e$1.fetchFn),k=e$1.url.replace(/\/+$/g,""),n=e$1.path.replace(/^\/+/,""),b$1=e$1.version!==void 0?`?version=${encodeURIComponent(String(e$1.version))}`:"",A=`${k}/v1/${d$2}/${n}${b$1}`,u=new Headers;g&&u.set("X-Vault-Token",g),u.has("Accept")||u.set("Accept","application/json");let a$1;try{a$1=await h(b(A,{headers:u,signal:e(i$1)},S),i$1,n,t);}catch(r){if(r instanceof d)throw r;let h=r,w=/timeout|abort/i.test(h?.name+h?.message);throw new d([{path:n,from:t,message:`${w?"E_TIMEOUT":"E_CONN"}: ${h?.message??String(r)}`}],w?"E_TIMEOUT":"E_CONN")}if(!a$1.ok){let r=d$1(a$1.status);throw new d([{path:n,from:t,message:`${r}: HTTP ${a$1.status}`}],r)}let _=await i(a$1,n,t,p,i$1),l;try{l=JSON.parse(_);}catch{throw new d([{path:n,from:t,message:"E_PARSE: invalid JSON"}],"E_PARSE")}let s=l.data,m=!!s&&typeof s=="object"&&Object.hasOwn(s,"data")&&Object.hasOwn(s,"metadata")?s.data:s;if(!m||typeof m!="object"||Array.isArray(m))throw new d([{path:n,from:t,message:"E_SHAPE: missing data"}],"E_SHAPE");return c(m,t)}return {name:t,load(){return c$1||(c$1=P().finally(()=>{c$1=null;})),c$1}}}
2
+ export{x as hashicorpProvider};
@@ -1,185 +1,4 @@
1
- 'use strict';
2
-
3
- // src/errors.ts
4
- function byteLengthUtf8(text) {
5
- try {
6
- const g = globalThis;
7
- if (g.TextEncoder) return new g.TextEncoder().encode(text).length;
8
- if (g.Buffer) return g.Buffer.byteLength(text, "utf8");
9
- } catch {
10
- }
11
- return text.length;
12
- }
13
- var ConfigError = class extends Error {
14
- code = "E_INVALID_CONFIG";
15
- issues;
16
- constructor(issues, code = "E_INVALID_CONFIG") {
17
- const lines = issues.map(
18
- (i) => `- ${i.path} (from ${i.from}): ${i.message}`
19
- );
20
- super(`Invalid config (${issues.length} issue${issues.length === 1 ? "" : "s"}):
21
- ${lines.join("\n")}`);
22
- this.name = "ConfigError";
23
- this.code = code;
24
- this.issues = issues;
25
- }
26
- };
27
-
28
- // src/vault/shared.ts
29
- function getFetch(fetchFn) {
30
- if (fetchFn) return fetchFn;
31
- const g = globalThis;
32
- if (g.fetch) return g.fetch.bind(globalThis);
33
- throw new ConfigError(
34
- [{ path: "<provider>", from: "vault", message: "E_NO_FETCH: global fetch unavailable" }],
35
- "E_NO_FETCH"
36
- );
37
- }
38
- function sameHost(a, b) {
39
- return new URL(a).host === new URL(b).host;
40
- }
41
- var SENSITIVE_HEADER_RE = /authorization|token|secret|api[-_]?key|cookie|auth/i;
42
- function stripSensitiveForCrossHost(headers) {
43
- const next = new Headers();
44
- headers.forEach((value, key) => {
45
- if (!SENSITIVE_HEADER_RE.test(key)) next.set(key, value);
46
- });
47
- return next;
48
- }
49
- async function fetchWithRedirectGuard(url, init, fetchFn, maxRedirects = 2) {
50
- let current = url;
51
- let headers = new Headers(init.headers);
52
- for (let i = 0; i <= maxRedirects; i++) {
53
- const res = await fetchFn(current, { ...init, headers, redirect: "manual" });
54
- const status = res.status;
55
- if (![301, 302, 303, 307, 308].includes(status)) return res;
56
- const loc = res.headers.get("location");
57
- if (!loc) return res;
58
- let next;
59
- try {
60
- next = new URL(loc, current).toString();
61
- } catch {
62
- throw new ConfigError(
63
- [{ path: current, from: "vault", message: "E_REDIRECT: invalid Location header" }],
64
- "E_REDIRECT"
65
- );
66
- }
67
- if (i === maxRedirects) {
68
- throw new ConfigError(
69
- [{ path: next, from: "vault", message: "E_REDIRECT: too many redirects" }],
70
- "E_REDIRECT"
71
- );
72
- }
73
- if (!sameHost(current, next)) headers = stripSensitiveForCrossHost(headers);
74
- current = next;
75
- }
76
- throw new ConfigError([{ path: url, from: "vault", message: "E_REDIRECT" }], "E_REDIRECT");
77
- }
78
- function normalizeSecretMap(raw, providerName, opts) {
79
- const clean = (v) => {
80
- if (v === null || v === void 0) return void 0;
81
- let s = typeof v === "string" ? v : String(v);
82
- s = s.replace(/\r?\n$/, "");
83
- return s;
84
- };
85
- const out = {};
86
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
87
- throw new ConfigError(
88
- [{ path: "<root>", from: providerName, message: "E_SHAPE: provider returned non-object" }],
89
- "E_SHAPE"
90
- );
91
- }
92
- for (const [k, v] of Object.entries(raw)) {
93
- if (v !== null && typeof v === "object" && !Array.isArray(v)) {
94
- out[k] = v;
95
- continue;
96
- }
97
- const c = clean(v);
98
- if (c !== void 0) out[k] = c;
99
- }
100
- return out;
101
- }
102
- function statusToCode(status) {
103
- if (status === 403 || status === 401) return "E_DENIED";
104
- if (status === 404) return "E_NOT_FOUND";
105
- if (status === 429) return "E_THROTTLED";
106
- if (status >= 500) return "E_UPSTREAM";
107
- return "E_PROVIDER";
108
- }
109
-
110
- // src/vault/http.ts
111
- function getAtPath(obj, path) {
112
- if (!path) return obj;
113
- let cur = obj;
114
- for (const seg of path.split(".")) {
115
- if (cur && typeof cur === "object" && seg in cur) cur = cur[seg];
116
- else return void 0;
117
- }
118
- return cur;
119
- }
120
- function httpProvider(opts) {
121
- const timeoutMs = opts.timeoutMs ?? 5e3;
122
- const maxBytes = opts.maxBytes ?? 1024 * 1024;
123
- const jsonPath = opts.jsonPath ?? "data";
124
- const name = `http://${opts.url}`;
125
- let inflight = null;
126
- async function doLoad() {
127
- const fetchFn = getFetch(opts.fetchFn);
128
- const headers = new Headers();
129
- for (const [k, v] of Object.entries(opts.headers ?? {})) {
130
- if (v !== void 0) headers.set(k, v);
131
- }
132
- headers.set("Accept", "application/json");
133
- let res;
134
- try {
135
- res = await fetchWithRedirectGuard(
136
- opts.url,
137
- { headers, signal: AbortSignal.timeout(timeoutMs) },
138
- fetchFn
139
- );
140
- } catch (e) {
141
- if (e instanceof ConfigError) throw e;
142
- const err = e;
143
- const isTimeout = /timeout|abort/i.test(err?.name + err?.message);
144
- throw new ConfigError(
145
- [{ path: opts.url, from: name, message: `${isTimeout ? "E_TIMEOUT" : "E_CONN"}: ${err?.message ?? String(e)}` }],
146
- isTimeout ? "E_TIMEOUT" : "E_CONN"
147
- );
148
- }
149
- if (!res.ok) {
150
- const code = statusToCode(res.status);
151
- throw new ConfigError([{ path: opts.url, from: name, message: `${code}: HTTP ${res.status}` }], code);
152
- }
153
- const text = await res.text();
154
- if (byteLengthUtf8(text) > maxBytes) {
155
- throw new ConfigError([{ path: opts.url, from: name, message: "E_TOO_LARGE" }], "E_TOO_LARGE");
156
- }
157
- let json;
158
- try {
159
- json = JSON.parse(text);
160
- } catch {
161
- throw new ConfigError([{ path: opts.url, from: name, message: "E_PARSE: invalid JSON" }], "E_PARSE");
162
- }
163
- let inner = getAtPath(json, jsonPath);
164
- if (inner && typeof inner === "object" && !Array.isArray(inner) && "data" in inner && "metadata" in inner) {
165
- inner = inner.data;
166
- }
167
- if (!inner || typeof inner !== "object" || Array.isArray(inner)) {
168
- throw new ConfigError([{ path: jsonPath, from: name, message: "E_SHAPE: missing data" }], "E_SHAPE");
169
- }
170
- return normalizeSecretMap(inner, name);
171
- }
172
- return {
173
- name,
174
- load() {
175
- if (!inflight) {
176
- inflight = doLoad().finally(() => {
177
- inflight = null;
178
- });
179
- }
180
- return inflight;
181
- }
182
- };
183
- }
184
-
185
- exports.httpProvider = httpProvider;
1
+ 'use strict';function E(t){try{let e=globalThis;if(e.TextEncoder)return new e.TextEncoder().encode(t).length;if(e.Buffer)return e.Buffer.byteLength(t,"utf8")}catch{}return t.length}var a=class extends Error{code="E_INVALID_CONFIG";issues;static[Symbol.hasInstance](e){return typeof e=="object"&&e!==null&&e.name==="ConfigError"&&typeof e.code=="string"&&Array.isArray(e.issues)}constructor(e=[],n="E_INVALID_CONFIG"){let c=e.map(r=>`- ${r.path} (from ${r.from}): ${r.message}`);super(e.length===0?"Invalid config: unknown error (no issues attached)":`Invalid config (${e.length} issue${e.length===1?"":"s"}):
2
+ ${c.join(`
3
+ `)}`),this.name="ConfigError",this.code=n,this.issues=e;}};function y(t){return t.toLowerCase()==="__proto__"}function _(t){if(t)return t;let e=globalThis;if(e.fetch)return e.fetch.bind(globalThis);throw new a([{path:"<provider>",from:"vault",message:"E_NO_FETCH: global fetch unavailable"}],"E_NO_FETCH")}function I(t,e){try{return new URL(t).host===new URL(e).host}catch{return false}}var S=/authorization|token|secret|api[-_]?key|cookie|auth/i;function C(t,e){try{return new URL(t).protocol==="https:"&&new URL(e).protocol!=="https:"}catch{return false}}function j(t){let e=new Headers;return t.forEach((n,c)=>{S.test(c)||e.set(c,n);}),e}async function R(t,e,n,c=2){let r=t,o=new Headers(e.headers);for(let s=0;s<=c;s++){let i=await n(r,{...e,headers:o,redirect:"manual"}),f=i.status;if(![301,302,303,307,308].includes(f))return i;let d=i.headers.get("location");if(!d)return i;let u;try{u=new URL(d,r).toString();}catch{throw new a([{path:r,from:"vault",message:"E_REDIRECT: invalid Location header"}],"E_REDIRECT")}if(s===c)throw new a([{path:u,from:"vault",message:"E_REDIRECT: too many redirects"}],"E_REDIRECT");(!I(r,u)||C(r,u))&&(o=j(o)),r=u;}throw new a([{path:t,from:"vault",message:"E_REDIRECT"}],"E_REDIRECT")}function A(t,e,n){let r=s=>{if(s==null)return;let i=typeof s=="string"?s:String(s);return (i=i.replace(/\r?\n$/,"")),i},o={};if(!t||typeof t!="object"||Array.isArray(t))throw new a([{path:"<root>",from:e,message:"E_SHAPE: provider returned non-object"}],"E_SHAPE");for(let[s,i]of Object.entries(t)){if(y(s))throw new a([{path:s,from:e,message:"E_PROTO: forbidden key"}],"E_PROTO");if(i!==null&&typeof i=="object"&&!Array.isArray(i)){o[s]=i;continue}let f=r(i);f!==void 0&&(o[s]=f);}return o}function k(t){return t===403||t===401?"E_DENIED":t===404?"E_NOT_FOUND":t===429?"E_THROTTLED":t===408||t===504?"E_TIMEOUT":t>=500?"E_UPSTREAM":"E_PROVIDER"}function b(t,e){let n=AbortSignal;if(typeof n.timeout=="function")try{return n.timeout(t)}catch{return}}function h(t,e,n){if(!Number.isFinite(t)||t<=0)throw new a([{path:e,from:n,message:`E_USAGE: ${e} must be a positive finite number`}],"E_USAGE")}function O(t){try{let e=new URL(t);e.username="",e.password="";for(let n of [...e.searchParams.keys()])/token|secret|auth|password|credential|api[-_]?key|pwd|passphrase/i.test(n)&&e.searchParams.delete(n);return e.hash="",e.toString()}catch{return t}}async function T(t,e,n,c){let r,o=new Promise((s,i)=>{r=setTimeout(()=>i(new a([{path:n,from:c,message:"E_TIMEOUT: request timed out"}],"E_TIMEOUT")),e);});t.catch(()=>{});try{return await Promise.race([t,o])}finally{r&&clearTimeout(r);}}async function P(t,e,n,c,r){let o,s=new Promise((i,f)=>{o=setTimeout(()=>f(new a([{path:e,from:n,message:"E_TIMEOUT: response body timed out"}],"E_TIMEOUT")),r);});try{let i=t.text();i.catch(()=>{});let f=await Promise.race([i,s]);if(E(f)>c)throw new a([{path:e,from:n,message:"E_TOO_LARGE"}],"E_TOO_LARGE");return f}finally{o&&clearTimeout(o);}}function $(t,e){if(!e)return t;let n=t;for(let c of e.split("."))if(n&&typeof n=="object"&&Object.hasOwn(n,c))n=n[c];else return;return n}function v(t){let e=t.timeoutMs??5e3,n=t.maxBytes??1024*1024;h(e,"timeoutMs","http"),h(n,"maxBytes","http");let c=t.jsonPath??"data",r=O(t.url),o=`http://${r}`,s=null;async function i(){let f=_(t.fetchFn),d=new Headers;for(let[g,m]of Object.entries(t.headers??{}))m!==void 0&&d.set(g,m);d.has("Accept")||d.set("Accept","application/json");let u;try{u=await T(R(t.url,{headers:d,signal:b(e)},f),e,r,o);}catch(g){if(g instanceof a)throw g;let m=g,w=/timeout|abort/i.test(m?.name+m?.message);throw new a([{path:r,from:o,message:`${w?"E_TIMEOUT":"E_CONN"}: ${m?.message??String(g)}`}],w?"E_TIMEOUT":"E_CONN")}if(!u.ok){let g=k(u.status);throw new a([{path:r,from:o,message:`${g}: HTTP ${u.status}`}],g)}let x=await P(u,r,o,n,e),p;try{p=JSON.parse(x);}catch{throw new a([{path:r,from:o,message:"E_PARSE: invalid JSON"}],"E_PARSE")}let l=$(p,c);if(l&&typeof l=="object"&&!Array.isArray(l)&&Object.hasOwn(l,"data")&&Object.hasOwn(l,"metadata")&&(l=l.data),!l||typeof l!="object"||Array.isArray(l))throw new a([{path:c,from:o,message:"E_SHAPE: missing data"}],"E_SHAPE");return A(l,o)}return {name:o,load(){return s||(s=i().finally(()=>{s=null;})),s}}}
4
+ exports.httpProvider=v;
@@ -1,4 +1,4 @@
1
- import { F as Flat, a as SecretProvider } from '../types-B_Dc2L4T.cjs';
1
+ import { F as Flat, a as SecretProvider } from '../types-CcsYDAdO.cjs';
2
2
  import { F as FetchFn } from '../shared-CucO_XsG.cjs';
3
3
  import '@standard-schema/spec';
4
4
 
@@ -1,4 +1,4 @@
1
- import { F as Flat, a as SecretProvider } from '../types-B_Dc2L4T.js';
1
+ import { F as Flat, a as SecretProvider } from '../types-CcsYDAdO.js';
2
2
  import { F as FetchFn } from '../shared-CucO_XsG.js';
3
3
  import '@standard-schema/spec';
4
4
 
@@ -1,79 +1,2 @@
1
- import { getFetch, fetchWithRedirectGuard, statusToCode, normalizeSecretMap } from '../chunk-RQC6OMVV.js';
2
- import { ConfigError, byteLengthUtf8 } from '../chunk-EE6LXNJV.js';
3
-
4
- // src/vault/http.ts
5
- function getAtPath(obj, path) {
6
- if (!path) return obj;
7
- let cur = obj;
8
- for (const seg of path.split(".")) {
9
- if (cur && typeof cur === "object" && seg in cur) cur = cur[seg];
10
- else return void 0;
11
- }
12
- return cur;
13
- }
14
- function httpProvider(opts) {
15
- const timeoutMs = opts.timeoutMs ?? 5e3;
16
- const maxBytes = opts.maxBytes ?? 1024 * 1024;
17
- const jsonPath = opts.jsonPath ?? "data";
18
- const name = `http://${opts.url}`;
19
- let inflight = null;
20
- async function doLoad() {
21
- const fetchFn = getFetch(opts.fetchFn);
22
- const headers = new Headers();
23
- for (const [k, v] of Object.entries(opts.headers ?? {})) {
24
- if (v !== void 0) headers.set(k, v);
25
- }
26
- headers.set("Accept", "application/json");
27
- let res;
28
- try {
29
- res = await fetchWithRedirectGuard(
30
- opts.url,
31
- { headers, signal: AbortSignal.timeout(timeoutMs) },
32
- fetchFn
33
- );
34
- } catch (e) {
35
- if (e instanceof ConfigError) throw e;
36
- const err = e;
37
- const isTimeout = /timeout|abort/i.test(err?.name + err?.message);
38
- throw new ConfigError(
39
- [{ path: opts.url, from: name, message: `${isTimeout ? "E_TIMEOUT" : "E_CONN"}: ${err?.message ?? String(e)}` }],
40
- isTimeout ? "E_TIMEOUT" : "E_CONN"
41
- );
42
- }
43
- if (!res.ok) {
44
- const code = statusToCode(res.status);
45
- throw new ConfigError([{ path: opts.url, from: name, message: `${code}: HTTP ${res.status}` }], code);
46
- }
47
- const text = await res.text();
48
- if (byteLengthUtf8(text) > maxBytes) {
49
- throw new ConfigError([{ path: opts.url, from: name, message: "E_TOO_LARGE" }], "E_TOO_LARGE");
50
- }
51
- let json;
52
- try {
53
- json = JSON.parse(text);
54
- } catch {
55
- throw new ConfigError([{ path: opts.url, from: name, message: "E_PARSE: invalid JSON" }], "E_PARSE");
56
- }
57
- let inner = getAtPath(json, jsonPath);
58
- if (inner && typeof inner === "object" && !Array.isArray(inner) && "data" in inner && "metadata" in inner) {
59
- inner = inner.data;
60
- }
61
- if (!inner || typeof inner !== "object" || Array.isArray(inner)) {
62
- throw new ConfigError([{ path: jsonPath, from: name, message: "E_SHAPE: missing data" }], "E_SHAPE");
63
- }
64
- return normalizeSecretMap(inner, name);
65
- }
66
- return {
67
- name,
68
- load() {
69
- if (!inflight) {
70
- inflight = doLoad().finally(() => {
71
- inflight = null;
72
- });
73
- }
74
- return inflight;
75
- }
76
- };
77
- }
78
-
79
- export { httpProvider };
1
+ import {f,g,a,h,b,e,d as d$1,i,c}from'../chunk-5D2AQWDG.js';import {d}from'../chunk-NQDE3WLR.js';function k(e,s){if(!s)return e;let n=e;for(let u of s.split("."))if(n&&typeof n=="object"&&Object.hasOwn(n,u))n=n[u];else return;return n}function _(e$1){let s=e$1.timeoutMs??5e3,n=e$1.maxBytes??1024*1024;f(s,"timeoutMs","http"),f(n,"maxBytes","http");let u=e$1.jsonPath??"data",a$1=g(e$1.url),o=`http://${a$1}`,m=null;async function b$1(){let A=a(e$1.fetchFn),h$1=new Headers;for(let[r,i]of Object.entries(e$1.headers??{}))i!==void 0&&h$1.set(r,i);h$1.has("Accept")||h$1.set("Accept","application/json");let f;try{f=await h(b(e$1.url,{headers:h$1,signal:e(s)},A),s,a$1,o);}catch(r){if(r instanceof d)throw r;let i=r,p=/timeout|abort/i.test(i?.name+i?.message);throw new d([{path:a$1,from:o,message:`${p?"E_TIMEOUT":"E_CONN"}: ${i?.message??String(r)}`}],p?"E_TIMEOUT":"E_CONN")}if(!f.ok){let r=d$1(f.status);throw new d([{path:a$1,from:o,message:`${r}: HTTP ${f.status}`}],r)}let S=await i(f,a$1,o,n,s),d$2;try{d$2=JSON.parse(S);}catch{throw new d([{path:a$1,from:o,message:"E_PARSE: invalid JSON"}],"E_PARSE")}let t=k(d$2,u);if(t&&typeof t=="object"&&!Array.isArray(t)&&Object.hasOwn(t,"data")&&Object.hasOwn(t,"metadata")&&(t=t.data),!t||typeof t!="object"||Array.isArray(t))throw new d([{path:u,from:o,message:"E_SHAPE: missing data"}],"E_SHAPE");return c(t,o)}return {name:o,load(){return m||(m=b$1().finally(()=>{m=null;})),m}}}
2
+ export{_ as httpProvider};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typed-settings",
3
- "version": "0.1.4",
3
+ "version": "0.2.1",
4
4
  "description": "One-call typed config for TS: env + .env + yaml/toml/json + secrets-dir + vault -> frozen object. Standard Schema + legacy bridges.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -74,6 +74,7 @@
74
74
  },
75
75
  "scripts": {
76
76
  "build": "tsup",
77
+ "prepack": "npm run build",
77
78
  "test": "vitest run",
78
79
  "test:watch": "vitest",
79
80
  "typecheck": "tsc --noEmit",
@@ -126,12 +127,10 @@
126
127
  "@types/node": "^26.6.4",
127
128
  "@vitest/coverage-v8": "^3.2.7",
128
129
  "arktype": "^2.1.0",
129
- "smol-toml": "^1.3.1",
130
130
  "tsup": "^8.3.5",
131
131
  "typescript": "^5.6.3",
132
132
  "valibot": "^1.0.0",
133
133
  "vitest": "^3.0.0",
134
- "yaml": "^2.6.1",
135
134
  "zod": "^3.24.0 || ^4.0.0"
136
135
  }
137
136
  }
@@ -1,13 +0,0 @@
1
- // src/formats/json.ts
2
- function parseJsonText(text, from = "json") {
3
- const stripped = text.charCodeAt(0) === 65279 ? text.slice(1) : text;
4
- if (!stripped.trim()) return {};
5
- try {
6
- return JSON.parse(stripped);
7
- } catch (e) {
8
- const err = e;
9
- throw new Error(`ParseError (${from}): ${err.message}`);
10
- }
11
- }
12
-
13
- export { parseJsonText };