@geekmidas/envkit 0.1.0 → 0.3.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
@@ -3,392 +3,392 @@ import { z } from 'zod/v4';
3
3
  import { ConfigParser } from '../EnvironmentParser';
4
4
 
5
5
  describe('ConfigParser', () => {
6
- describe('Basic functionality', () => {
7
- it('should parse simple Zod schemas', () => {
8
- const config = {
9
- name: z.string().default('Test'),
10
- age: z.number().default(25),
11
- active: z.boolean().default(true),
12
- };
13
-
14
- const parser = new ConfigParser(config);
15
- const result = parser.parse();
16
-
17
- expect(result).toEqual({
18
- name: 'Test',
19
- age: 25,
20
- active: true,
21
- });
22
- });
23
-
24
- it('should handle optional values', () => {
25
- const config = {
26
- required: z.string().default('value'),
27
- optional: z.string().optional(),
28
- };
29
-
30
- const parser = new ConfigParser(config);
31
- const result = parser.parse();
32
-
33
- expect(result).toEqual({
34
- required: 'value',
35
- optional: undefined,
36
- });
37
- });
38
-
39
- it('should validate and use provided default values', () => {
40
- const config = {
41
- port: z.number().default(3000),
42
- host: z.string().default('localhost'),
43
- debug: z.boolean().default(false),
44
- };
45
-
46
- const parser = new ConfigParser(config);
47
- const result = parser.parse();
48
-
49
- expect(result).toEqual({
50
- port: 3000,
51
- host: 'localhost',
52
- debug: false,
53
- });
54
- });
55
- });
56
-
57
- describe('Nested objects', () => {
58
- it('should parse nested configuration objects', () => {
59
- const config = {
60
- database: {
61
- host: z.string().default('localhost'),
62
- port: z.number().default(5432),
63
- ssl: z.boolean().default(false),
64
- },
65
- api: {
66
- key: z.string().default('default-key'),
67
- timeout: z.number().default(5000),
68
- },
69
- };
70
-
71
- const parser = new ConfigParser(config);
72
- const result = parser.parse();
73
-
74
- expect(result).toEqual({
75
- database: {
76
- host: 'localhost',
77
- port: 5432,
78
- ssl: false,
79
- },
80
- api: {
81
- key: 'default-key',
82
- timeout: 5000,
83
- },
84
- });
85
- });
86
-
87
- it('should handle deeply nested objects', () => {
88
- const config = {
89
- app: {
90
- name: z.string().default('MyApp'),
91
- version: z.string().default('1.0.0'),
92
- features: {
93
- auth: {
94
- enabled: z.boolean().default(true),
95
- provider: z.string().default('local'),
96
- },
97
- cache: {
98
- enabled: z.boolean().default(false),
99
- ttl: z.number().default(3600),
100
- },
101
- },
102
- },
103
- };
104
-
105
- const parser = new ConfigParser(config);
106
- const result = parser.parse();
107
-
108
- expect(result).toEqual({
109
- app: {
110
- name: 'MyApp',
111
- version: '1.0.0',
112
- features: {
113
- auth: {
114
- enabled: true,
115
- provider: 'local',
116
- },
117
- cache: {
118
- enabled: false,
119
- ttl: 3600,
120
- },
121
- },
122
- },
123
- });
124
- });
125
-
126
- it('should handle mixed nested and flat configuration', () => {
127
- const config = {
128
- appName: z.string().default('Test App'),
129
- database: {
130
- url: z.string().default('postgres://localhost/test'),
131
- poolSize: z.number().default(10),
132
- },
133
- port: z.number().default(3000),
134
- features: {
135
- logging: {
136
- level: z.string().default('info'),
137
- pretty: z.boolean().default(true),
138
- },
139
- },
140
- };
141
-
142
- const parser = new ConfigParser(config);
143
- const result = parser.parse();
144
-
145
- expect(result).toEqual({
146
- appName: 'Test App',
147
- database: {
148
- url: 'postgres://localhost/test',
149
- poolSize: 10,
150
- },
151
- port: 3000,
152
- features: {
153
- logging: {
154
- level: 'info',
155
- pretty: true,
156
- },
157
- },
158
- });
159
- });
160
- });
161
-
162
- describe('Error handling', () => {
163
- it('should throw ZodError for schemas without defaults', () => {
164
- const config = {
165
- required: z.string(),
166
- alsoRequired: z.number(),
167
- };
168
-
169
- const parser = new ConfigParser(config);
170
-
171
- expect(() => parser.parse()).toThrow(z.ZodError);
172
- });
173
-
174
- it('should collect multiple validation errors', () => {
175
- const config = {
176
- field1: z.string(),
177
- field2: z.number(),
178
- field3: z.boolean(),
179
- };
180
-
181
- const parser = new ConfigParser(config);
182
-
183
- try {
184
- parser.parse();
185
- // Should not reach here
186
- expect(true).toBe(false);
187
- } catch (error) {
188
- expect(error).toBeInstanceOf(z.ZodError);
189
- const zodError = error as z.ZodError;
190
- expect(zodError.issues).toHaveLength(3);
191
- }
192
- });
193
-
194
- it('should include correct paths in nested validation errors', () => {
195
- const config = {
196
- database: {
197
- host: z.string(),
198
- port: z.number(),
199
- },
200
- api: {
201
- key: z.string(),
202
- },
203
- };
204
-
205
- const parser = new ConfigParser(config);
206
-
207
- try {
208
- parser.parse();
209
- // Should not reach here
210
- expect(true).toBe(false);
211
- } catch (error) {
212
- expect(error).toBeInstanceOf(z.ZodError);
213
- const zodError = error as z.ZodError;
214
-
215
- const paths = zodError.issues.map((err) => err.path.join('.'));
216
- expect(paths).toContain('database.host');
217
- expect(paths).toContain('database.port');
218
- expect(paths).toContain('api.key');
219
- }
220
- });
221
-
222
- it('should use default values that pass validation', () => {
223
- const config = {
224
- port: z.number().min(1000).max(65535).default(3000),
225
- email: z.string().email().default('admin@example.com'),
226
- };
227
-
228
- const parser = new ConfigParser(config);
229
- const result = parser.parse();
230
-
231
- expect(result).toEqual({
232
- port: 3000,
233
- email: 'admin@example.com',
234
- });
235
- });
236
- });
237
-
238
- describe('Type safety', () => {
239
- it('should infer correct types for simple configuration', () => {
240
- const config = {
241
- name: z.string().default('test'),
242
- count: z.number().default(42),
243
- enabled: z.boolean().default(true),
244
- };
245
-
246
- const parser = new ConfigParser(config);
247
- const result = parser.parse();
248
-
249
- // TypeScript should infer the correct types
250
- type ResultType = typeof result;
251
- type ExpectedType = {
252
- name: string;
253
- count: number;
254
- enabled: boolean;
255
- };
256
-
257
- const _typeCheck: ResultType extends ExpectedType ? true : false = true;
258
- const _typeCheck2: ExpectedType extends ResultType ? true : false = true;
259
-
260
- expect(_typeCheck).toBe(true);
261
- expect(_typeCheck2).toBe(true);
262
- });
263
-
264
- it('should infer correct types for nested configuration', () => {
265
- const config = {
266
- database: {
267
- host: z.string().default('localhost'),
268
- port: z.number().default(5432),
269
- },
270
- features: {
271
- auth: z.boolean().default(true),
272
- },
273
- };
274
-
275
- const parser = new ConfigParser(config);
276
- const result = parser.parse();
277
-
278
- // TypeScript should infer the correct nested structure
279
- type ResultType = typeof result;
280
- type ExpectedType = {
281
- database: { host: string; port: number };
282
- features: { auth: boolean };
283
- };
284
-
285
- const _typeCheck: ResultType extends ExpectedType ? true : false = true;
286
- const _typeCheck2: ExpectedType extends ResultType ? true : false = true;
287
-
288
- expect(_typeCheck).toBe(true);
289
- expect(_typeCheck2).toBe(true);
290
- });
291
-
292
- it('should handle optional types correctly', () => {
293
- const config = {
294
- required: z.string().default('value'),
295
- optional: z.string().optional(),
296
- nullable: z.string().nullable().default(null),
297
- };
298
-
299
- const parser = new ConfigParser(config);
300
- const result = parser.parse();
301
- });
302
- });
303
-
304
- describe('Complex schemas', () => {
305
- it('should handle enum schemas', () => {
306
- const config = {
307
- environment: z
308
- .enum(['development', 'staging', 'production'])
309
- .default('development'),
310
- logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
311
- };
312
-
313
- const parser = new ConfigParser(config);
314
- const result = parser.parse();
315
-
316
- expect(result).toEqual({
317
- environment: 'development',
318
- logLevel: 'info',
319
- });
320
- });
321
-
322
- it('should handle union schemas', () => {
323
- const config = {
324
- port: z.union([z.string(), z.number()]).default(3000),
325
- timeout: z.union([z.number(), z.null()]).default(null),
326
- };
327
-
328
- const parser = new ConfigParser(config);
329
- const result = parser.parse();
330
-
331
- expect(result).toEqual({
332
- port: 3000,
333
- timeout: null,
334
- });
335
- });
336
-
337
- it('should handle array schemas', () => {
338
- const config = {
339
- tags: z.array(z.string()).default(['tag1', 'tag2']),
340
- ports: z.array(z.number()).default([3000, 3001]),
341
- };
342
-
343
- const parser = new ConfigParser(config);
344
- const result = parser.parse();
345
-
346
- expect(result).toEqual({
347
- tags: ['tag1', 'tag2'],
348
- ports: [3000, 3001],
349
- });
350
- });
351
-
352
- it('should handle record schemas', () => {
353
- const config = {
354
- metadata: z
355
- .record(z.string(), z.string())
356
- .default({ key1: 'value1', key2: 'value2' }),
357
- counters: z
358
- .record(z.string(), z.number())
359
- .default({ count1: 1, count2: 2 }),
360
- };
361
-
362
- const parser = new ConfigParser(config);
363
- const result = parser.parse();
364
-
365
- expect(result).toEqual({
366
- metadata: { key1: 'value1', key2: 'value2' },
367
- counters: { count1: 1, count2: 2 },
368
- });
369
- });
370
-
371
- it('should handle transformed schemas', () => {
372
- const config = {
373
- portString: z.string().transform(Number).default(8080),
374
- booleanString: z
375
- .string()
376
- .transform((v) => v === 'true')
377
- .default(false),
378
- jsonString: z
379
- .string()
380
- .transform((v) => JSON.parse(v))
381
- .default({ key: 'value' }),
382
- };
383
-
384
- const parser = new ConfigParser(config);
385
- const result = parser.parse();
386
-
387
- expect(result).toEqual({
388
- portString: 8080,
389
- booleanString: false,
390
- jsonString: { key: 'value' },
391
- });
392
- });
393
- });
6
+ describe('Basic functionality', () => {
7
+ it('should parse simple Zod schemas', () => {
8
+ const config = {
9
+ name: z.string().default('Test'),
10
+ age: z.number().default(25),
11
+ active: z.boolean().default(true),
12
+ };
13
+
14
+ const parser = new ConfigParser(config);
15
+ const result = parser.parse();
16
+
17
+ expect(result).toEqual({
18
+ name: 'Test',
19
+ age: 25,
20
+ active: true,
21
+ });
22
+ });
23
+
24
+ it('should handle optional values', () => {
25
+ const config = {
26
+ required: z.string().default('value'),
27
+ optional: z.string().optional(),
28
+ };
29
+
30
+ const parser = new ConfigParser(config);
31
+ const result = parser.parse();
32
+
33
+ expect(result).toEqual({
34
+ required: 'value',
35
+ optional: undefined,
36
+ });
37
+ });
38
+
39
+ it('should validate and use provided default values', () => {
40
+ const config = {
41
+ port: z.number().default(3000),
42
+ host: z.string().default('localhost'),
43
+ debug: z.boolean().default(false),
44
+ };
45
+
46
+ const parser = new ConfigParser(config);
47
+ const result = parser.parse();
48
+
49
+ expect(result).toEqual({
50
+ port: 3000,
51
+ host: 'localhost',
52
+ debug: false,
53
+ });
54
+ });
55
+ });
56
+
57
+ describe('Nested objects', () => {
58
+ it('should parse nested configuration objects', () => {
59
+ const config = {
60
+ database: {
61
+ host: z.string().default('localhost'),
62
+ port: z.number().default(5432),
63
+ ssl: z.boolean().default(false),
64
+ },
65
+ api: {
66
+ key: z.string().default('default-key'),
67
+ timeout: z.number().default(5000),
68
+ },
69
+ };
70
+
71
+ const parser = new ConfigParser(config);
72
+ const result = parser.parse();
73
+
74
+ expect(result).toEqual({
75
+ database: {
76
+ host: 'localhost',
77
+ port: 5432,
78
+ ssl: false,
79
+ },
80
+ api: {
81
+ key: 'default-key',
82
+ timeout: 5000,
83
+ },
84
+ });
85
+ });
86
+
87
+ it('should handle deeply nested objects', () => {
88
+ const config = {
89
+ app: {
90
+ name: z.string().default('MyApp'),
91
+ version: z.string().default('1.0.0'),
92
+ features: {
93
+ auth: {
94
+ enabled: z.boolean().default(true),
95
+ provider: z.string().default('local'),
96
+ },
97
+ cache: {
98
+ enabled: z.boolean().default(false),
99
+ ttl: z.number().default(3600),
100
+ },
101
+ },
102
+ },
103
+ };
104
+
105
+ const parser = new ConfigParser(config);
106
+ const result = parser.parse();
107
+
108
+ expect(result).toEqual({
109
+ app: {
110
+ name: 'MyApp',
111
+ version: '1.0.0',
112
+ features: {
113
+ auth: {
114
+ enabled: true,
115
+ provider: 'local',
116
+ },
117
+ cache: {
118
+ enabled: false,
119
+ ttl: 3600,
120
+ },
121
+ },
122
+ },
123
+ });
124
+ });
125
+
126
+ it('should handle mixed nested and flat configuration', () => {
127
+ const config = {
128
+ appName: z.string().default('Test App'),
129
+ database: {
130
+ url: z.string().default('postgres://localhost/test'),
131
+ poolSize: z.number().default(10),
132
+ },
133
+ port: z.number().default(3000),
134
+ features: {
135
+ logging: {
136
+ level: z.string().default('info'),
137
+ pretty: z.boolean().default(true),
138
+ },
139
+ },
140
+ };
141
+
142
+ const parser = new ConfigParser(config);
143
+ const result = parser.parse();
144
+
145
+ expect(result).toEqual({
146
+ appName: 'Test App',
147
+ database: {
148
+ url: 'postgres://localhost/test',
149
+ poolSize: 10,
150
+ },
151
+ port: 3000,
152
+ features: {
153
+ logging: {
154
+ level: 'info',
155
+ pretty: true,
156
+ },
157
+ },
158
+ });
159
+ });
160
+ });
161
+
162
+ describe('Error handling', () => {
163
+ it('should throw ZodError for schemas without defaults', () => {
164
+ const config = {
165
+ required: z.string(),
166
+ alsoRequired: z.number(),
167
+ };
168
+
169
+ const parser = new ConfigParser(config);
170
+
171
+ expect(() => parser.parse()).toThrow(z.ZodError);
172
+ });
173
+
174
+ it('should collect multiple validation errors', () => {
175
+ const config = {
176
+ field1: z.string(),
177
+ field2: z.number(),
178
+ field3: z.boolean(),
179
+ };
180
+
181
+ const parser = new ConfigParser(config);
182
+
183
+ try {
184
+ parser.parse();
185
+ // Should not reach here
186
+ expect(true).toBe(false);
187
+ } catch (error) {
188
+ expect(error).toBeInstanceOf(z.ZodError);
189
+ const zodError = error as z.ZodError;
190
+ expect(zodError.issues).toHaveLength(3);
191
+ }
192
+ });
193
+
194
+ it('should include correct paths in nested validation errors', () => {
195
+ const config = {
196
+ database: {
197
+ host: z.string(),
198
+ port: z.number(),
199
+ },
200
+ api: {
201
+ key: z.string(),
202
+ },
203
+ };
204
+
205
+ const parser = new ConfigParser(config);
206
+
207
+ try {
208
+ parser.parse();
209
+ // Should not reach here
210
+ expect(true).toBe(false);
211
+ } catch (error) {
212
+ expect(error).toBeInstanceOf(z.ZodError);
213
+ const zodError = error as z.ZodError;
214
+
215
+ const paths = zodError.issues.map((err) => err.path.join('.'));
216
+ expect(paths).toContain('database.host');
217
+ expect(paths).toContain('database.port');
218
+ expect(paths).toContain('api.key');
219
+ }
220
+ });
221
+
222
+ it('should use default values that pass validation', () => {
223
+ const config = {
224
+ port: z.number().min(1000).max(65535).default(3000),
225
+ email: z.string().email().default('admin@example.com'),
226
+ };
227
+
228
+ const parser = new ConfigParser(config);
229
+ const result = parser.parse();
230
+
231
+ expect(result).toEqual({
232
+ port: 3000,
233
+ email: 'admin@example.com',
234
+ });
235
+ });
236
+ });
237
+
238
+ describe('Type safety', () => {
239
+ it('should infer correct types for simple configuration', () => {
240
+ const config = {
241
+ name: z.string().default('test'),
242
+ count: z.number().default(42),
243
+ enabled: z.boolean().default(true),
244
+ };
245
+
246
+ const parser = new ConfigParser(config);
247
+ const result = parser.parse();
248
+
249
+ // TypeScript should infer the correct types
250
+ type ResultType = typeof result;
251
+ type ExpectedType = {
252
+ name: string;
253
+ count: number;
254
+ enabled: boolean;
255
+ };
256
+
257
+ const _typeCheck: ResultType extends ExpectedType ? true : false = true;
258
+ const _typeCheck2: ExpectedType extends ResultType ? true : false = true;
259
+
260
+ expect(_typeCheck).toBe(true);
261
+ expect(_typeCheck2).toBe(true);
262
+ });
263
+
264
+ it('should infer correct types for nested configuration', () => {
265
+ const config = {
266
+ database: {
267
+ host: z.string().default('localhost'),
268
+ port: z.number().default(5432),
269
+ },
270
+ features: {
271
+ auth: z.boolean().default(true),
272
+ },
273
+ };
274
+
275
+ const parser = new ConfigParser(config);
276
+ const result = parser.parse();
277
+
278
+ // TypeScript should infer the correct nested structure
279
+ type ResultType = typeof result;
280
+ type ExpectedType = {
281
+ database: { host: string; port: number };
282
+ features: { auth: boolean };
283
+ };
284
+
285
+ const _typeCheck: ResultType extends ExpectedType ? true : false = true;
286
+ const _typeCheck2: ExpectedType extends ResultType ? true : false = true;
287
+
288
+ expect(_typeCheck).toBe(true);
289
+ expect(_typeCheck2).toBe(true);
290
+ });
291
+
292
+ it('should handle optional types correctly', () => {
293
+ const config = {
294
+ required: z.string().default('value'),
295
+ optional: z.string().optional(),
296
+ nullable: z.string().nullable().default(null),
297
+ };
298
+
299
+ const parser = new ConfigParser(config);
300
+ const _result = parser.parse();
301
+ });
302
+ });
303
+
304
+ describe('Complex schemas', () => {
305
+ it('should handle enum schemas', () => {
306
+ const config = {
307
+ environment: z
308
+ .enum(['development', 'staging', 'production'])
309
+ .default('development'),
310
+ logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
311
+ };
312
+
313
+ const parser = new ConfigParser(config);
314
+ const result = parser.parse();
315
+
316
+ expect(result).toEqual({
317
+ environment: 'development',
318
+ logLevel: 'info',
319
+ });
320
+ });
321
+
322
+ it('should handle union schemas', () => {
323
+ const config = {
324
+ port: z.union([z.string(), z.number()]).default(3000),
325
+ timeout: z.union([z.number(), z.null()]).default(null),
326
+ };
327
+
328
+ const parser = new ConfigParser(config);
329
+ const result = parser.parse();
330
+
331
+ expect(result).toEqual({
332
+ port: 3000,
333
+ timeout: null,
334
+ });
335
+ });
336
+
337
+ it('should handle array schemas', () => {
338
+ const config = {
339
+ tags: z.array(z.string()).default(['tag1', 'tag2']),
340
+ ports: z.array(z.number()).default([3000, 3001]),
341
+ };
342
+
343
+ const parser = new ConfigParser(config);
344
+ const result = parser.parse();
345
+
346
+ expect(result).toEqual({
347
+ tags: ['tag1', 'tag2'],
348
+ ports: [3000, 3001],
349
+ });
350
+ });
351
+
352
+ it('should handle record schemas', () => {
353
+ const config = {
354
+ metadata: z
355
+ .record(z.string(), z.string())
356
+ .default({ key1: 'value1', key2: 'value2' }),
357
+ counters: z
358
+ .record(z.string(), z.number())
359
+ .default({ count1: 1, count2: 2 }),
360
+ };
361
+
362
+ const parser = new ConfigParser(config);
363
+ const result = parser.parse();
364
+
365
+ expect(result).toEqual({
366
+ metadata: { key1: 'value1', key2: 'value2' },
367
+ counters: { count1: 1, count2: 2 },
368
+ });
369
+ });
370
+
371
+ it('should handle transformed schemas', () => {
372
+ const config = {
373
+ portString: z.string().transform(Number).default(8080),
374
+ booleanString: z
375
+ .string()
376
+ .transform((v) => v === 'true')
377
+ .default(false),
378
+ jsonString: z
379
+ .string()
380
+ .transform((v) => JSON.parse(v))
381
+ .default({ key: 'value' }),
382
+ };
383
+
384
+ const parser = new ConfigParser(config);
385
+ const result = parser.parse();
386
+
387
+ expect(result).toEqual({
388
+ portString: 8080,
389
+ booleanString: false,
390
+ jsonString: { key: 'value' },
391
+ });
392
+ });
393
+ });
394
394
  });