@geekmidas/envkit 0.2.0 → 0.4.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 (73) hide show
  1. package/dist/{EnvironmentBuilder-DfmYRBm-.mjs → EnvironmentBuilder-BSuHZm0y.mjs} +2 -4
  2. package/dist/EnvironmentBuilder-BSuHZm0y.mjs.map +1 -0
  3. package/dist/EnvironmentBuilder-DHfDXJUm.d.mts.map +1 -0
  4. package/dist/{EnvironmentBuilder-W2wku49g.cjs → EnvironmentBuilder-Djr1VsWM.cjs} +2 -4
  5. package/dist/EnvironmentBuilder-Djr1VsWM.cjs.map +1 -0
  6. package/dist/EnvironmentBuilder-Xuf2Dd9u.d.cts.map +1 -0
  7. package/dist/EnvironmentBuilder.cjs +1 -1
  8. package/dist/EnvironmentBuilder.mjs +1 -1
  9. package/dist/EnvironmentParser-Bt246UeP.cjs.map +1 -1
  10. package/dist/{EnvironmentParser-CVWU1ooT.d.mts → EnvironmentParser-CY8TosTN.d.mts} +2 -1
  11. package/dist/EnvironmentParser-CY8TosTN.d.mts.map +1 -0
  12. package/dist/{EnvironmentParser-tV-JjCg7.d.cts → EnvironmentParser-DtOL86NU.d.cts} +2 -1
  13. package/dist/EnvironmentParser-DtOL86NU.d.cts.map +1 -0
  14. package/dist/EnvironmentParser-c06agx31.mjs.map +1 -1
  15. package/dist/EnvironmentParser.d.cts +1 -1
  16. package/dist/EnvironmentParser.d.mts +1 -1
  17. package/dist/SnifferEnvironmentParser.cjs.map +1 -1
  18. package/dist/SnifferEnvironmentParser.d.cts +3 -2
  19. package/dist/SnifferEnvironmentParser.d.cts.map +1 -0
  20. package/dist/SnifferEnvironmentParser.d.mts +3 -2
  21. package/dist/SnifferEnvironmentParser.d.mts.map +1 -0
  22. package/dist/SnifferEnvironmentParser.mjs.map +1 -1
  23. package/dist/{SstEnvironmentBuilder-DEa3lTUB.mjs → SstEnvironmentBuilder-BEBFSUYr.mjs} +2 -2
  24. package/dist/SstEnvironmentBuilder-BEBFSUYr.mjs.map +1 -0
  25. package/dist/SstEnvironmentBuilder-CjURMGjW.d.mts.map +1 -0
  26. package/dist/SstEnvironmentBuilder-D4oSo_KX.d.cts.map +1 -0
  27. package/dist/{SstEnvironmentBuilder-BuFw1hCe.cjs → SstEnvironmentBuilder-wFnN2M5O.cjs} +2 -2
  28. package/dist/SstEnvironmentBuilder-wFnN2M5O.cjs.map +1 -0
  29. package/dist/SstEnvironmentBuilder.cjs +2 -2
  30. package/dist/SstEnvironmentBuilder.mjs +2 -2
  31. package/dist/credentials.cjs +66 -0
  32. package/dist/credentials.cjs.map +1 -0
  33. package/dist/credentials.d.cts +31 -0
  34. package/dist/credentials.d.cts.map +1 -0
  35. package/dist/credentials.d.mts +31 -0
  36. package/dist/credentials.d.mts.map +1 -0
  37. package/dist/credentials.mjs +62 -0
  38. package/dist/credentials.mjs.map +1 -0
  39. package/dist/index.cjs +1 -1
  40. package/dist/index.d.cts +1 -1
  41. package/dist/index.d.mts +1 -1
  42. package/dist/index.mjs +1 -1
  43. package/dist/sst.cjs +2 -2
  44. package/dist/sst.cjs.map +1 -1
  45. package/dist/sst.d.cts +1 -0
  46. package/dist/sst.d.cts.map +1 -0
  47. package/dist/sst.d.mts +1 -0
  48. package/dist/sst.d.mts.map +1 -0
  49. package/dist/sst.mjs +2 -2
  50. package/dist/sst.mjs.map +1 -1
  51. package/examples/basic-usage.ts +329 -333
  52. package/package.json +6 -1
  53. package/src/EnvironmentBuilder.ts +76 -80
  54. package/src/EnvironmentParser.ts +231 -231
  55. package/src/SnifferEnvironmentParser.ts +178 -178
  56. package/src/SstEnvironmentBuilder.ts +127 -127
  57. package/src/__tests__/ConfigParser.spec.ts +388 -388
  58. package/src/__tests__/EnvironmentBuilder.spec.ts +245 -265
  59. package/src/__tests__/EnvironmentParser.spec.ts +828 -828
  60. package/src/__tests__/SnifferEnvironmentParser.spec.ts +380 -326
  61. package/src/__tests__/SstEnvironmentBuilder.spec.ts +347 -367
  62. package/src/__tests__/credentials.integration.spec.ts +239 -0
  63. package/src/__tests__/credentials.spec.ts +136 -0
  64. package/src/__tests__/sst.spec.ts +390 -413
  65. package/src/credentials.ts +99 -0
  66. package/src/index.ts +11 -11
  67. package/src/sst.ts +24 -24
  68. package/sst-env.d.ts +0 -1
  69. package/tsconfig.json +9 -0
  70. package/dist/EnvironmentBuilder-DfmYRBm-.mjs.map +0 -1
  71. package/dist/EnvironmentBuilder-W2wku49g.cjs.map +0 -1
  72. package/dist/SstEnvironmentBuilder-BuFw1hCe.cjs.map +0 -1
  73. package/dist/SstEnvironmentBuilder-DEa3lTUB.mjs.map +0 -1
@@ -9,86 +9,86 @@ import { z } from 'zod/v4';
9
9
  * @template TResponse - The shape of the configuration object
10
10
  */
11
11
  export class ConfigParser<TResponse extends EmptyObject> {
12
- /**
13
- * Creates a new ConfigParser instance.
14
- *
15
- * @param config - The configuration object to parse
16
- * @param envVars - Set of environment variable names that were accessed
17
- */
18
- constructor(
19
- private readonly config: TResponse,
20
- private readonly envVars: Set<string> = new Set(),
21
- ) {}
22
- /**
23
- * Parses the config object and validates it against the Zod schemas
24
- * @returns The parsed config object
25
- */
26
- parse(): InferConfig<TResponse> {
27
- const errors: z.core.$ZodIssue[] = [];
12
+ /**
13
+ * Creates a new ConfigParser instance.
14
+ *
15
+ * @param config - The configuration object to parse
16
+ * @param envVars - Set of environment variable names that were accessed
17
+ */
18
+ constructor(
19
+ private readonly config: TResponse,
20
+ private readonly envVars: Set<string> = new Set(),
21
+ ) {}
22
+ /**
23
+ * Parses the config object and validates it against the Zod schemas
24
+ * @returns The parsed config object
25
+ */
26
+ parse(): InferConfig<TResponse> {
27
+ const errors: z.core.$ZodIssue[] = [];
28
28
 
29
- const parseDeep = <T>(config: T, path: string[] = []) => {
30
- const result: EmptyObject = {};
29
+ const parseDeep = <T>(config: T, path: string[] = []) => {
30
+ const result: EmptyObject = {};
31
31
 
32
- if (config && typeof config !== 'object') {
33
- return config;
34
- }
32
+ if (config && typeof config !== 'object') {
33
+ return config;
34
+ }
35
35
 
36
- for (const key in config) {
37
- const schema = config[key];
38
- const currentPath = [...path, key];
36
+ for (const key in config) {
37
+ const schema = config[key];
38
+ const currentPath = [...path, key];
39
39
 
40
- if (schema instanceof z.ZodType) {
41
- const parsed = schema.safeParse(undefined);
42
- if (parsed.success) {
43
- set(result, key, parsed.data);
44
- } else {
45
- // If the schema is invalid, assign the error
46
- errors.push(
47
- ...parsed.error.issues.map((issue) => ({
48
- ...issue,
49
- path: [...currentPath, ...(issue.path as string[])],
50
- })),
51
- );
52
- }
53
- } else if (schema) {
54
- set(result, key, parseDeep(schema as EmptyObject, currentPath));
55
- }
56
- }
40
+ if (schema instanceof z.ZodType) {
41
+ const parsed = schema.safeParse(undefined);
42
+ if (parsed.success) {
43
+ set(result, key, parsed.data);
44
+ } else {
45
+ // If the schema is invalid, assign the error
46
+ errors.push(
47
+ ...parsed.error.issues.map((issue) => ({
48
+ ...issue,
49
+ path: [...currentPath, ...(issue.path as string[])],
50
+ })),
51
+ );
52
+ }
53
+ } else if (schema) {
54
+ set(result, key, parseDeep(schema as EmptyObject, currentPath));
55
+ }
56
+ }
57
57
 
58
- return result;
59
- };
58
+ return result;
59
+ };
60
60
 
61
- const parsedConfig = parseDeep(
62
- this.config,
63
- ) as unknown as InferConfig<TResponse>;
61
+ const parsedConfig = parseDeep(
62
+ this.config,
63
+ ) as unknown as InferConfig<TResponse>;
64
64
 
65
- if (errors.length > 0) {
66
- // If there are errors, throw them
67
- throw new z.ZodError(errors);
68
- }
65
+ if (errors.length > 0) {
66
+ // If there are errors, throw them
67
+ throw new z.ZodError(errors);
68
+ }
69
69
 
70
- return parsedConfig;
71
- }
70
+ return parsedConfig;
71
+ }
72
72
 
73
- /**
74
- * Returns an array of environment variable names that were accessed during config creation.
75
- * This is useful for deployment and configuration management to know which env vars are required.
76
- *
77
- * @returns Array of environment variable names, sorted alphabetically
78
- *
79
- * @example
80
- * ```typescript
81
- * const config = envParser.create((get) => ({
82
- * dbUrl: get('DATABASE_URL').string(),
83
- * port: get('PORT').number()
84
- * }));
85
- *
86
- * config.getEnvironmentVariables(); // ['DATABASE_URL', 'PORT']
87
- * ```
88
- */
89
- getEnvironmentVariables(): string[] {
90
- return Array.from(this.envVars).sort();
91
- }
73
+ /**
74
+ * Returns an array of environment variable names that were accessed during config creation.
75
+ * This is useful for deployment and configuration management to know which env vars are required.
76
+ *
77
+ * @returns Array of environment variable names, sorted alphabetically
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const config = envParser.create((get) => ({
82
+ * dbUrl: get('DATABASE_URL').string(),
83
+ * port: get('PORT').number()
84
+ * }));
85
+ *
86
+ * config.getEnvironmentVariables(); // ['DATABASE_URL', 'PORT']
87
+ * ```
88
+ */
89
+ getEnvironmentVariables(): string[] {
90
+ return Array.from(this.envVars).sort();
91
+ }
92
92
  }
93
93
 
94
94
  /**
@@ -111,173 +111,173 @@ export class ConfigParser<TResponse extends EmptyObject> {
111
111
  * ```
112
112
  */
113
113
  export class EnvironmentParser<T extends EmptyObject> {
114
- /**
115
- * Set to track which environment variable names have been accessed
116
- */
117
- private readonly accessedVars: Set<string> = new Set();
114
+ /**
115
+ * Set to track which environment variable names have been accessed
116
+ */
117
+ private readonly accessedVars: Set<string> = new Set();
118
118
 
119
- /**
120
- * Creates a new EnvironmentParser instance.
121
- *
122
- * @param config - The configuration object to parse (typically process.env)
123
- */
124
- constructor(private readonly config: T) {}
119
+ /**
120
+ * Creates a new EnvironmentParser instance.
121
+ *
122
+ * @param config - The configuration object to parse (typically process.env)
123
+ */
124
+ constructor(private readonly config: T) {}
125
125
 
126
- /**
127
- * Wraps a Zod schema to intercept parse/safeParse calls and enrich error messages
128
- * with environment variable context.
129
- *
130
- * @param schema - The Zod schema to wrap
131
- * @param name - The environment variable name for error context
132
- * @returns A wrapped Zod schema with enhanced error reporting
133
- */
134
- private wrapSchema = (schema: z.ZodType, name: string): z.ZodType => {
135
- // Create a proxy that intercepts all method calls on the schema
136
- return new Proxy(schema, {
137
- get: (target, prop) => {
138
- if (prop === 'parse') {
139
- return () => {
140
- const value = get(this.config, name);
141
- try {
142
- return target.parse(value);
143
- } catch (error) {
144
- if (error instanceof z.ZodError) {
145
- // Modify the error to include the environment variable name
146
- const modifiedIssues = error.issues.map((issue) => ({
147
- ...issue,
148
- message: `Environment variable "${name}": ${issue.message}`,
149
- path: [name, ...issue.path],
150
- }));
151
- throw new z.ZodError(modifiedIssues);
152
- }
153
- throw error;
154
- }
155
- };
156
- }
126
+ /**
127
+ * Wraps a Zod schema to intercept parse/safeParse calls and enrich error messages
128
+ * with environment variable context.
129
+ *
130
+ * @param schema - The Zod schema to wrap
131
+ * @param name - The environment variable name for error context
132
+ * @returns A wrapped Zod schema with enhanced error reporting
133
+ */
134
+ private wrapSchema = (schema: z.ZodType, name: string): z.ZodType => {
135
+ // Create a proxy that intercepts all method calls on the schema
136
+ return new Proxy(schema, {
137
+ get: (target, prop) => {
138
+ if (prop === 'parse') {
139
+ return () => {
140
+ const value = get(this.config, name);
141
+ try {
142
+ return target.parse(value);
143
+ } catch (error) {
144
+ if (error instanceof z.ZodError) {
145
+ // Modify the error to include the environment variable name
146
+ const modifiedIssues = error.issues.map((issue) => ({
147
+ ...issue,
148
+ message: `Environment variable "${name}": ${issue.message}`,
149
+ path: [name, ...issue.path],
150
+ }));
151
+ throw new z.ZodError(modifiedIssues);
152
+ }
153
+ throw error;
154
+ }
155
+ };
156
+ }
157
157
 
158
- if (prop === 'safeParse') {
159
- return () => {
160
- const value = get(this.config, name);
161
- const result = target.safeParse(value);
158
+ if (prop === 'safeParse') {
159
+ return () => {
160
+ const value = get(this.config, name);
161
+ const result = target.safeParse(value);
162
162
 
163
- if (!result.success) {
164
- // Modify the error to include the environment variable name
165
- const modifiedIssues = result.error.issues.map(
166
- (issue: z.core.$ZodIssue) => ({
167
- ...issue,
168
- message: `Environment variable "${name}": ${issue.message}`,
169
- path: [name, ...issue.path],
170
- }),
171
- );
172
- return {
173
- success: false as const,
174
- error: new z.ZodError(modifiedIssues),
175
- };
176
- }
163
+ if (!result.success) {
164
+ // Modify the error to include the environment variable name
165
+ const modifiedIssues = result.error.issues.map(
166
+ (issue: z.core.$ZodIssue) => ({
167
+ ...issue,
168
+ message: `Environment variable "${name}": ${issue.message}`,
169
+ path: [name, ...issue.path],
170
+ }),
171
+ );
172
+ return {
173
+ success: false as const,
174
+ error: new z.ZodError(modifiedIssues),
175
+ };
176
+ }
177
177
 
178
- return result;
179
- };
180
- }
178
+ return result;
179
+ };
180
+ }
181
181
 
182
- // For any method that returns a new schema (like transform, optional, etc.),
183
- // wrap the result as well
184
- const originalProp = target[prop as keyof typeof target];
185
- if (typeof originalProp === 'function') {
186
- return (...args: any[]) => {
187
- const result = originalProp.apply(target, args);
188
- // If the result is a ZodType, wrap it too
189
- if (result && typeof result === 'object' && 'parse' in result) {
190
- return this.wrapSchema(result, name);
191
- }
192
- return result;
193
- };
194
- }
182
+ // For any method that returns a new schema (like transform, optional, etc.),
183
+ // wrap the result as well
184
+ const originalProp = target[prop as keyof typeof target];
185
+ if (typeof originalProp === 'function') {
186
+ return (...args: any[]) => {
187
+ const result = originalProp.apply(target, args);
188
+ // If the result is a ZodType, wrap it too
189
+ if (result && typeof result === 'object' && 'parse' in result) {
190
+ return this.wrapSchema(result, name);
191
+ }
192
+ return result;
193
+ };
194
+ }
195
195
 
196
- return originalProp;
197
- },
198
- });
199
- };
196
+ return originalProp;
197
+ },
198
+ });
199
+ };
200
200
 
201
- /**
202
- * Creates a proxied version of the Zod object that wraps all schema creators
203
- * to provide enhanced error messages with environment variable context.
204
- *
205
- * @param name - The environment variable name
206
- * @returns A proxied Zod object with wrapped schema creators
207
- */
208
- private getZodGetter = (name: string) => {
209
- // Track that this environment variable was accessed
210
- this.accessedVars.add(name);
201
+ /**
202
+ * Creates a proxied version of the Zod object that wraps all schema creators
203
+ * to provide enhanced error messages with environment variable context.
204
+ *
205
+ * @param name - The environment variable name
206
+ * @returns A proxied Zod object with wrapped schema creators
207
+ */
208
+ private getZodGetter = (name: string) => {
209
+ // Track that this environment variable was accessed
210
+ this.accessedVars.add(name);
211
211
 
212
- // Return an object that has all Zod schemas but with our wrapper
213
- return new Proxy(
214
- { ...z },
215
- {
216
- get: (target, prop) => {
217
- // deno-lint-ignore ban-ts-comment
218
- // @ts-ignore
219
- const value = target[prop];
212
+ // Return an object that has all Zod schemas but with our wrapper
213
+ return new Proxy(
214
+ { ...z },
215
+ {
216
+ get: (target, prop) => {
217
+ // deno-lint-ignore ban-ts-comment
218
+ // @ts-expect-error
219
+ const value = target[prop];
220
220
 
221
- if (typeof value === 'function') {
222
- // Return a wrapper around each Zod schema creator
223
- return (...args: any[]) => {
224
- const schema = value(...args);
225
- return this.wrapSchema(schema, name);
226
- };
227
- }
221
+ if (typeof value === 'function') {
222
+ // Return a wrapper around each Zod schema creator
223
+ return (...args: any[]) => {
224
+ const schema = value(...args);
225
+ return this.wrapSchema(schema, name);
226
+ };
227
+ }
228
228
 
229
- // Handle objects like z.coerce
230
- if (value && typeof value === 'object') {
231
- return new Proxy(value, {
232
- get: (nestedTarget, nestedProp) => {
233
- const nestedValue =
234
- nestedTarget[nestedProp as keyof typeof nestedTarget];
235
- if (typeof nestedValue === 'function') {
236
- return (...args: any[]) => {
237
- const schema = nestedValue(...args);
238
- return this.wrapSchema(schema, name);
239
- };
240
- }
241
- return nestedValue;
242
- },
243
- });
244
- }
229
+ // Handle objects like z.coerce
230
+ if (value && typeof value === 'object') {
231
+ return new Proxy(value, {
232
+ get: (nestedTarget, nestedProp) => {
233
+ const nestedValue =
234
+ nestedTarget[nestedProp as keyof typeof nestedTarget];
235
+ if (typeof nestedValue === 'function') {
236
+ return (...args: any[]) => {
237
+ const schema = nestedValue(...args);
238
+ return this.wrapSchema(schema, name);
239
+ };
240
+ }
241
+ return nestedValue;
242
+ },
243
+ });
244
+ }
245
245
 
246
- return value;
247
- },
248
- },
249
- );
250
- };
246
+ return value;
247
+ },
248
+ },
249
+ );
250
+ };
251
251
 
252
- /**
253
- * Creates a new ConfigParser object that can be used to parse the config object
254
- *
255
- * @param builder - A function that takes a getter function and returns a config object
256
- * @returns A ConfigParser object that can be used to parse the config object
257
- */
258
- create<TReturn extends EmptyObject>(
259
- builder: (get: EnvFetcher) => TReturn,
260
- ): ConfigParser<TReturn> {
261
- const config = builder(this.getZodGetter);
262
- return new ConfigParser(config, this.accessedVars);
263
- }
252
+ /**
253
+ * Creates a new ConfigParser object that can be used to parse the config object
254
+ *
255
+ * @param builder - A function that takes a getter function and returns a config object
256
+ * @returns A ConfigParser object that can be used to parse the config object
257
+ */
258
+ create<TReturn extends EmptyObject>(
259
+ builder: (get: EnvFetcher) => TReturn,
260
+ ): ConfigParser<TReturn> {
261
+ const config = builder(this.getZodGetter);
262
+ return new ConfigParser(config, this.accessedVars);
263
+ }
264
264
 
265
- /**
266
- * Returns an array of environment variable names that were accessed via the getter.
267
- * This is useful for build-time analysis to determine which env vars a service needs.
268
- *
269
- * @returns Array of environment variable names, sorted alphabetically
270
- *
271
- * @example
272
- * ```typescript
273
- * const sniffer = new EnvironmentParser({});
274
- * service.register(sniffer);
275
- * const envVars = sniffer.getEnvironmentVariables(); // ['DATABASE_URL', 'PORT']
276
- * ```
277
- */
278
- getEnvironmentVariables(): string[] {
279
- return Array.from(this.accessedVars).sort();
280
- }
265
+ /**
266
+ * Returns an array of environment variable names that were accessed via the getter.
267
+ * This is useful for build-time analysis to determine which env vars a service needs.
268
+ *
269
+ * @returns Array of environment variable names, sorted alphabetically
270
+ *
271
+ * @example
272
+ * ```typescript
273
+ * const sniffer = new EnvironmentParser({});
274
+ * service.register(sniffer);
275
+ * const envVars = sniffer.getEnvironmentVariables(); // ['DATABASE_URL', 'PORT']
276
+ * ```
277
+ */
278
+ getEnvironmentVariables(): string[] {
279
+ return Array.from(this.accessedVars).sort();
280
+ }
281
281
  }
282
282
 
283
283
  /**
@@ -287,11 +287,11 @@ export class EnvironmentParser<T extends EmptyObject> {
287
287
  * @template T - The configuration object type
288
288
  */
289
289
  export type InferConfig<T extends EmptyObject> = {
290
- [K in keyof T]: T[K] extends z.ZodSchema
291
- ? z.infer<T[K]>
292
- : T[K] extends Record<string, unknown>
293
- ? InferConfig<T[K]>
294
- : T[K];
290
+ [K in keyof T]: T[K] extends z.ZodSchema
291
+ ? z.infer<T[K]>
292
+ : T[K] extends Record<string, unknown>
293
+ ? InferConfig<T[K]>
294
+ : T[K];
295
295
  };
296
296
 
297
297
  /**
@@ -303,7 +303,7 @@ export type InferConfig<T extends EmptyObject> = {
303
303
  * @returns A Zod object for defining the schema
304
304
  */
305
305
  export type EnvFetcher<TPath extends string = string> = (
306
- name: TPath,
306
+ name: TPath,
307
307
  ) => typeof z;
308
308
 
309
309
  /**
@@ -315,7 +315,7 @@ export type EnvFetcher<TPath extends string = string> = (
315
315
  * @returns The configuration object with Zod schemas
316
316
  */
317
317
  export type EnvironmentBuilder<TResponse extends EmptyObject> = (
318
- get: EnvFetcher,
318
+ get: EnvFetcher,
319
319
  ) => TResponse;
320
320
 
321
321
  /**