hanzio 1.2.0 → 2.1.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 (155) hide show
  1. package/README.md +786 -239
  2. package/dist/api-wrapper/builders.d.ts +4 -3
  3. package/dist/api-wrapper/create-client.d.ts +1 -1
  4. package/dist/api-wrapper/describe.d.ts +16 -0
  5. package/dist/api-wrapper/endpoint.d.ts +18 -0
  6. package/dist/api-wrapper/errors.d.ts +39 -2
  7. package/dist/api-wrapper/index.d.ts +5 -0
  8. package/dist/api-wrapper/otel.d.ts +44 -0
  9. package/dist/api-wrapper/paginate.d.ts +12 -0
  10. package/dist/api-wrapper/redaction.d.ts +2 -0
  11. package/dist/api-wrapper/shared.d.ts +16 -2
  12. package/dist/api-wrapper/testing.d.ts +23 -0
  13. package/dist/api-wrapper/transport.d.ts +4 -5
  14. package/dist/api-wrapper/types.d.ts +103 -18
  15. package/dist/array/index.d.ts +50 -4
  16. package/dist/cache/createCache.d.ts +31 -0
  17. package/dist/cache/index.d.ts +19 -2
  18. package/dist/color/contrast.d.ts +40 -0
  19. package/dist/color/index.d.ts +2 -0
  20. package/dist/{math → color}/metricsSeriesColors.d.ts +14 -7
  21. package/dist/cool-console-log/index.d.ts +34 -5
  22. package/dist/crypto/encoding.d.ts +18 -0
  23. package/dist/crypto/hash.d.ts +33 -0
  24. package/dist/crypto/index.d.ts +4 -0
  25. package/dist/crypto/sealer.d.ts +25 -0
  26. package/dist/crypto/webhook.d.ts +20 -0
  27. package/dist/date/index.d.ts +46 -2
  28. package/dist/emitter/index.d.ts +21 -0
  29. package/dist/error/index.d.ts +12 -0
  30. package/dist/format/index.d.ts +102 -0
  31. package/dist/function/index.d.ts +60 -0
  32. package/dist/guard/index.d.ts +20 -0
  33. package/dist/i18n/index.d.ts +37 -0
  34. package/dist/index-0zvtcbzy.js +224 -0
  35. package/dist/index-8r2vdzjg.js +87 -0
  36. package/dist/index-hy7kbb99.js +157 -0
  37. package/dist/index-hyt6c56h.js +290 -0
  38. package/dist/{src/secrets/infisical.js → index-j1ybktbr.js} +500 -538
  39. package/dist/index-k9yx6bne.js +89 -0
  40. package/dist/index-kj1phgrx.js +169 -0
  41. package/dist/index-ktynw3vs.js +37 -0
  42. package/dist/index-mnkcfyx8.js +78 -0
  43. package/dist/{p-queue/index.js → index-pwt0dz63.js} +7 -11
  44. package/dist/index-rp5pqghz.js +157 -0
  45. package/dist/index-w882zry3.js +29 -0
  46. package/dist/index.d.ts +7 -7
  47. package/dist/jwt/index.d.ts +50 -2
  48. package/dist/math/index.d.ts +2 -2
  49. package/dist/math/linearRegressionTrend.d.ts +14 -1
  50. package/dist/math/scale.d.ts +8 -0
  51. package/dist/object/index.d.ts +19 -0
  52. package/dist/p-queue/index.d.ts +1 -1
  53. package/dist/promise/index.d.ts +97 -2
  54. package/dist/secrets/core.d.ts +7 -0
  55. package/dist/secrets/index.d.ts +3 -1
  56. package/dist/secrets/public-config.d.ts +7 -0
  57. package/dist/secrets/vite.d.ts +1 -0
  58. package/dist/secrets/worker.d.ts +1 -0
  59. package/dist/sitemap/index.d.ts +48 -6
  60. package/dist/src/api-wrapper/index.js +60 -1130
  61. package/dist/src/api-wrapper/testing.js +20 -0
  62. package/dist/{cool-console-log → src/cool-console-log}/index.js +80 -33
  63. package/dist/src/crypto/index.js +195 -0
  64. package/dist/src/format/index.js +211 -0
  65. package/dist/src/i18n/index.js +36 -0
  66. package/dist/src/index.js +739 -3145
  67. package/dist/src/jwt/index.js +138 -92
  68. package/dist/src/p-queue/index.js +9 -437
  69. package/dist/src/secrets/index.js +50 -1428
  70. package/dist/src/secrets/vite.js +10 -39
  71. package/dist/src/secrets/worker.js +14 -273
  72. package/dist/src/sitemap/index.js +183 -511
  73. package/dist/src/storage/index.js +119 -0
  74. package/dist/src/zod/index.js +340 -167
  75. package/dist/state/index.d.ts +21 -0
  76. package/dist/storage/index.d.ts +58 -0
  77. package/dist/string/index.d.ts +75 -2
  78. package/dist/typedswitch/index.d.ts +31 -24
  79. package/dist/types/index.d.ts +11 -0
  80. package/dist/url/index.d.ts +50 -1
  81. package/dist/zod/index.d.ts +32 -3
  82. package/dist/zod/introspect.d.ts +19 -0
  83. package/dist/zod/jsonToZodSchemaMapper.d.ts +3 -1
  84. package/dist/zod/zodMinMaxFilter.d.ts +22 -3
  85. package/dist/zod/zodToTypeString.d.ts +8 -3
  86. package/package.json +78 -7
  87. package/src/api-wrapper/actions-impl.ts +11 -72
  88. package/src/api-wrapper/builders.ts +32 -25
  89. package/src/api-wrapper/create-client.ts +171 -41
  90. package/src/api-wrapper/describe.ts +157 -0
  91. package/src/api-wrapper/endpoint.ts +26 -0
  92. package/src/api-wrapper/error-reporting.ts +7 -1
  93. package/src/api-wrapper/errors.ts +107 -2
  94. package/src/api-wrapper/headers.ts +11 -6
  95. package/src/api-wrapper/index.ts +5 -0
  96. package/src/api-wrapper/otel.ts +139 -0
  97. package/src/api-wrapper/paginate.ts +28 -0
  98. package/src/api-wrapper/redaction.ts +42 -0
  99. package/src/api-wrapper/shared.ts +21 -2
  100. package/src/api-wrapper/testing.ts +48 -0
  101. package/src/api-wrapper/transport.ts +41 -43
  102. package/src/api-wrapper/types.ts +185 -18
  103. package/src/array/index.ts +195 -42
  104. package/src/cache/createCache.ts +157 -0
  105. package/src/cache/index.ts +132 -147
  106. package/src/color/contrast.ts +163 -0
  107. package/src/color/index.ts +22 -0
  108. package/src/{math → color}/metricsSeriesColors.ts +47 -49
  109. package/src/cool-console-log/index.ts +128 -41
  110. package/src/crypto/encoding.ts +83 -0
  111. package/src/crypto/hash.ts +170 -0
  112. package/src/crypto/index.ts +26 -0
  113. package/src/crypto/sealer.ts +168 -0
  114. package/src/crypto/webhook.ts +86 -0
  115. package/src/date/index.ts +109 -34
  116. package/src/emitter/index.ts +82 -0
  117. package/src/error/index.ts +63 -0
  118. package/src/format/index.ts +389 -0
  119. package/src/function/index.ts +201 -0
  120. package/src/guard/index.ts +80 -0
  121. package/src/i18n/index.ts +125 -0
  122. package/src/index.ts +11 -7
  123. package/src/jwt/index.ts +199 -125
  124. package/src/math/index.ts +5 -10
  125. package/src/math/linearRegressionTrend.ts +33 -8
  126. package/src/math/scale.ts +17 -0
  127. package/src/object/index.ts +99 -0
  128. package/src/p-queue/index.ts +2 -0
  129. package/src/promise/index.ts +304 -9
  130. package/src/secrets/core.ts +72 -16
  131. package/src/secrets/index.ts +16 -4
  132. package/src/secrets/public-config.ts +47 -0
  133. package/src/secrets/vite.ts +2 -0
  134. package/src/secrets/worker.ts +2 -0
  135. package/src/sitemap/index.ts +293 -130
  136. package/src/state/index.ts +133 -81
  137. package/src/storage/index.ts +187 -0
  138. package/src/string/index.ts +261 -23
  139. package/src/typedswitch/index.ts +58 -38
  140. package/src/types/index.ts +14 -0
  141. package/src/url/index.ts +146 -1
  142. package/src/zod/index.ts +105 -9
  143. package/src/zod/introspect.ts +103 -0
  144. package/src/zod/jsonToZodSchemaMapper.ts +44 -21
  145. package/src/zod/zodMinMaxFilter.ts +37 -13
  146. package/src/zod/zodToTypeString.ts +184 -181
  147. package/dist/api-wrapper/index.js +0 -250
  148. package/dist/gzip/index.d.ts +0 -2
  149. package/dist/gzip/index.js +0 -16
  150. package/dist/index.js +0 -1823
  151. package/dist/jwt/index.js +0 -19
  152. package/dist/sitemap/index.js +0 -552
  153. package/dist/src/gzip/index.js +0 -16
  154. package/dist/src/secrets/loaders.js +0 -1529
  155. package/dist/zod/index.js +0 -210
@@ -0,0 +1,290 @@
1
+ import {
2
+ SecretLoadError2
3
+ } from "./index-ktynw3vs.js";
4
+
5
+ // src/secrets/environment.ts
6
+ function getProcessEnvironment() {
7
+ return typeof process === "undefined" ? undefined : process.env;
8
+ }
9
+ function resolveSecretEnvironment(option, env) {
10
+ const explicit = typeof option === "function" ? option() : option;
11
+ if (typeof explicit === "object" && explicit !== null) {
12
+ if (typeof explicit.slug !== "string" || !/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(explicit.slug)) {
13
+ throw new SecretLoadError2("CONFIGURATION", "Custom secret environment requires a valid slug.");
14
+ }
15
+ return explicit.slug;
16
+ }
17
+ const selected = explicit ?? env?.SECRETS_ENV;
18
+ if (selected !== undefined) {
19
+ if (selected === "production" || selected === "prod") {
20
+ return "prod";
21
+ }
22
+ if (selected === "development" || selected === "dev") {
23
+ return "dev";
24
+ }
25
+ if (selected === "staging") {
26
+ return "staging";
27
+ }
28
+ throw new SecretLoadError2("CONFIGURATION", "Invalid secret environment. Use dev, staging, prod, or an explicit { slug } option.");
29
+ }
30
+ if (env?.NODE_ENV === "production" || env?.NODE_ENV === "prod") {
31
+ return "prod";
32
+ }
33
+ if (env?.NODE_ENV === "staging") {
34
+ return "staging";
35
+ }
36
+ return "dev";
37
+ }
38
+
39
+ // src/secrets/deadline.ts
40
+ async function withSecretDeadline(options, operation) {
41
+ const timeoutMs = options.timeoutMs ?? 30000;
42
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647) {
43
+ throw new SecretLoadError2("CONFIGURATION", "Secret timeoutMs must be a positive finite timer duration.");
44
+ }
45
+ const controller = new AbortController;
46
+ const cancel = () => controller.abort(new SecretLoadError2("ABORTED", "Secret loading was cancelled."));
47
+ if (options.signal?.aborted) {
48
+ cancel();
49
+ } else {
50
+ options.signal?.addEventListener("abort", cancel, { once: true });
51
+ }
52
+ const timer = setTimeout(() => controller.abort(new SecretLoadError2("TIMEOUT", `Secret loading timed out after ${timeoutMs}ms.`)), timeoutMs);
53
+ let rejectOnAbort = () => {};
54
+ try {
55
+ const aborted = new Promise((_, reject) => {
56
+ rejectOnAbort = () => reject(controller.signal.reason);
57
+ controller.signal.addEventListener("abort", rejectOnAbort, { once: true });
58
+ });
59
+ if (controller.signal.aborted) {
60
+ throw controller.signal.reason;
61
+ }
62
+ return await Promise.race([operation(controller.signal), aborted]);
63
+ } finally {
64
+ clearTimeout(timer);
65
+ options.signal?.removeEventListener("abort", cancel);
66
+ controller.signal.removeEventListener("abort", rejectOnAbort);
67
+ }
68
+ }
69
+
70
+ // src/secrets/core.ts
71
+ var registryKey = Symbol.for("hanzio.secrets.environmentWrites.v1");
72
+ var shared = globalThis;
73
+ var environmentWrites = shared[registryKey] ?? new WeakMap;
74
+ shared[registryKey] = environmentWrites;
75
+ var defaultLogger = {
76
+ info: (message, attrs) => console.log(`${message} environment=${attrs.environment} count=${attrs.count} source=${attrs.source} durationMs=${attrs.durationMs}`, { sources: attrs.sources }),
77
+ error: (message, attrs) => console.error(message, attrs)
78
+ };
79
+ function readOverrides(keys, env) {
80
+ if (!env) {
81
+ return {};
82
+ }
83
+ const writes = environmentWrites.get(env);
84
+ return Object.fromEntries(keys.flatMap((key) => {
85
+ const value = Object.hasOwn(env, key) ? env[key] : undefined;
86
+ if (writes?.has(key)) {
87
+ if (writes.get(key) === value) {
88
+ return [];
89
+ }
90
+ writes.delete(key);
91
+ }
92
+ return value ? [[key, value]] : [];
93
+ }));
94
+ }
95
+ function createSecretSet2(keys, options, environmentVariables) {
96
+ const keySet = [...new Set(keys)];
97
+ let environment;
98
+ let initialized = false;
99
+ const logger = options.logger === false ? undefined : options.logger ?? defaultLogger;
100
+ let cached;
101
+ let parsed;
102
+ let sources;
103
+ let inFlight;
104
+ const log = (level, message, attributes) => {
105
+ try {
106
+ logger?.[level](message, attributes);
107
+ } catch {}
108
+ };
109
+ const loadSnapshot = async (request, signal, environment) => {
110
+ const local = readOverrides(keySet, environmentVariables);
111
+ const missing = keySet.filter((key) => !Object.hasOwn(local, key));
112
+ let loaderSource = options.loader.source ?? "custom loader";
113
+ let loaded = {};
114
+ if (missing.length) {
115
+ try {
116
+ loaded = await options.loader({
117
+ keys: missing,
118
+ environment,
119
+ signal,
120
+ timeoutMs: request.timeoutMs ?? options.timeoutMs ?? 30000,
121
+ reportSource: (source) => {
122
+ loaderSource = source;
123
+ }
124
+ });
125
+ } catch (error) {
126
+ if (error instanceof SecretLoadError2) {
127
+ throw error;
128
+ }
129
+ throw new SecretLoadError2("LOADER", "Secret loader failed.");
130
+ }
131
+ }
132
+ const overrides = readOverrides(keySet, environmentVariables);
133
+ const next = Object.fromEntries(keySet.map((key) => {
134
+ if (Object.hasOwn(overrides, key)) {
135
+ return [key, overrides[key]];
136
+ }
137
+ if (Object.hasOwn(loaded, key)) {
138
+ return [key, loaded[key]];
139
+ }
140
+ return [key, undefined];
141
+ }));
142
+ const missingKeys = keySet.filter((key) => typeof next[key] !== "string" || !next[key]);
143
+ if (missingKeys.length) {
144
+ throw new SecretLoadError2("MISSING_SECRETS", `Missing secrets: ${missingKeys.join(", ")}`);
145
+ }
146
+ let nextParsed;
147
+ try {
148
+ nextParsed = options.schema ? await options.schema.parseAsync({ ...next }) : { ...next };
149
+ nextParsed = structuredClone(nextParsed);
150
+ } catch {
151
+ throw new SecretLoadError2("VALIDATION", "Secret schema validation failed. Check the configured schema; values are omitted.");
152
+ }
153
+ signal.throwIfAborted();
154
+ const nextSources = Object.fromEntries(keySet.map((key) => [
155
+ key,
156
+ Object.hasOwn(overrides, key) ? "process.env" : loaderSource
157
+ ]));
158
+ if (options.writeToProcessEnv !== false && environmentVariables) {
159
+ let writes = environmentWrites.get(environmentVariables);
160
+ if (!writes) {
161
+ writes = new Map;
162
+ environmentWrites.set(environmentVariables, writes);
163
+ }
164
+ for (const key of keySet) {
165
+ if (Object.hasOwn(overrides, key)) {
166
+ continue;
167
+ }
168
+ environmentVariables[key] = next[key];
169
+ writes.set(key, next[key]);
170
+ }
171
+ }
172
+ cached = next;
173
+ parsed = nextParsed;
174
+ sources = nextSources;
175
+ initialized = true;
176
+ };
177
+ const load = (request = {}) => {
178
+ if (inFlight) {
179
+ return inFlight;
180
+ }
181
+ inFlight = (async () => {
182
+ const start = Date.now();
183
+ try {
184
+ environment ??= resolveSecretEnvironment(options.environment, environmentVariables);
185
+ const resolvedEnvironment = environment;
186
+ await withSecretDeadline({
187
+ timeoutMs: request.timeoutMs ?? options.timeoutMs,
188
+ signal: request.signal ?? options.signal
189
+ }, (signal) => loadSnapshot(request, signal, resolvedEnvironment));
190
+ const sourceCounts = new Map;
191
+ for (const key of keySet) {
192
+ const source = sources[key];
193
+ sourceCounts.set(source, (sourceCounts.get(source) ?? 0) + 1);
194
+ }
195
+ const counts = Object.fromEntries(sourceCounts);
196
+ log("info", "Loaded secrets", {
197
+ environment: resolvedEnvironment,
198
+ count: keySet.length,
199
+ durationMs: Date.now() - start,
200
+ source: Object.keys(counts).join(" + ") || "none",
201
+ sources: counts
202
+ });
203
+ } catch (error) {
204
+ const safe = error instanceof SecretLoadError2 ? error : new SecretLoadError2("LOADER", "Secret loading failed.");
205
+ log("error", "Secret loading failed", {
206
+ environment: environment ?? "unresolved",
207
+ count: keySet.length,
208
+ durationMs: Date.now() - start,
209
+ code: safe.code
210
+ });
211
+ throw safe;
212
+ }
213
+ })().finally(() => {
214
+ inFlight = undefined;
215
+ });
216
+ return inFlight;
217
+ };
218
+ const assertLoaded = () => {
219
+ if (!initialized) {
220
+ throw new SecretLoadError2("CONFIGURATION", "Secret set has not been loaded. Await load() before reading values.");
221
+ }
222
+ };
223
+ const secretSet = {
224
+ secret(key) {
225
+ assertLoaded();
226
+ if (!Object.hasOwn(cached, key)) {
227
+ throw new SecretLoadError2("MISSING_SECRETS", `Secret ${key} not found`);
228
+ }
229
+ return cached[key];
230
+ },
231
+ secrets() {
232
+ assertLoaded();
233
+ return { ...cached };
234
+ },
235
+ parsed() {
236
+ assertLoaded();
237
+ return structuredClone(parsed);
238
+ },
239
+ sources() {
240
+ assertLoaded();
241
+ return { ...sources };
242
+ },
243
+ async load(request) {
244
+ if (!initialized) {
245
+ await load(request);
246
+ }
247
+ return secretSet;
248
+ },
249
+ async reload(request) {
250
+ await load(request);
251
+ return secretSet;
252
+ }
253
+ };
254
+ return secretSet;
255
+ }
256
+ async function defineSecretSet2(keys, options, environmentVariables) {
257
+ return createSecretSet2(keys, options, environmentVariables).load();
258
+ }
259
+
260
+ // src/secrets/worker-loader.ts
261
+ function cloudflareWorkerEnvLoader2(workerEnv) {
262
+ const loader = async (ctx) => {
263
+ const out = Object.create(null);
264
+ for (const key of ctx.keys) {
265
+ const str = workerBindingToString(Object.hasOwn(workerEnv, key) ? workerEnv[key] : undefined);
266
+ if (str !== undefined) {
267
+ out[key] = str;
268
+ }
269
+ }
270
+ return out;
271
+ };
272
+ return Object.assign(loader, { source: "Cloudflare Worker bindings" });
273
+ }
274
+ function workerBindingToString(value) {
275
+ if (value === undefined || value === null) {
276
+ return;
277
+ }
278
+ if (typeof value === "string") {
279
+ return value === "" ? undefined : value;
280
+ }
281
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
282
+ return String(value);
283
+ }
284
+ if (typeof value === "object") {
285
+ return JSON.stringify(value);
286
+ }
287
+ return String(value);
288
+ }
289
+
290
+ export { withSecretDeadline, getProcessEnvironment, resolveSecretEnvironment, createSecretSet2, defineSecretSet2, cloudflareWorkerEnvLoader2 };