create-fluxstack 1.0.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.
- package/.env +30 -0
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/app/client/README.md +69 -0
- package/app/client/frontend-only.ts +12 -0
- package/app/client/index.html +13 -0
- package/app/client/public/vite.svg +1 -0
- package/app/client/src/App.css +883 -0
- package/app/client/src/App.tsx +669 -0
- package/app/client/src/assets/react.svg +1 -0
- package/app/client/src/components/TestPage.tsx +453 -0
- package/app/client/src/index.css +51 -0
- package/app/client/src/lib/eden-api.ts +110 -0
- package/app/client/src/main.tsx +10 -0
- package/app/client/src/vite-env.d.ts +1 -0
- package/app/client/tsconfig.app.json +43 -0
- package/app/client/tsconfig.json +7 -0
- package/app/client/tsconfig.node.json +25 -0
- package/app/server/app.ts +10 -0
- package/app/server/backend-only.ts +15 -0
- package/app/server/controllers/users.controller.ts +69 -0
- package/app/server/index.ts +104 -0
- package/app/server/routes/index.ts +25 -0
- package/app/server/routes/users.routes.ts +121 -0
- package/app/server/types/index.ts +1 -0
- package/app/shared/types/index.ts +18 -0
- package/bun.lock +1053 -0
- package/core/__tests__/integration.test.ts +227 -0
- package/core/build/index.ts +186 -0
- package/core/cli/command-registry.ts +334 -0
- package/core/cli/index.ts +394 -0
- package/core/cli/plugin-discovery.ts +200 -0
- package/core/client/standalone.ts +57 -0
- package/core/config/__tests__/config-loader.test.ts +591 -0
- package/core/config/__tests__/config-merger.test.ts +657 -0
- package/core/config/__tests__/env-converter.test.ts +372 -0
- package/core/config/__tests__/env-processor.test.ts +431 -0
- package/core/config/__tests__/env.test.ts +452 -0
- package/core/config/__tests__/integration.test.ts +418 -0
- package/core/config/__tests__/loader.test.ts +331 -0
- package/core/config/__tests__/schema.test.ts +129 -0
- package/core/config/__tests__/validator.test.ts +318 -0
- package/core/config/env-dynamic.ts +326 -0
- package/core/config/env.ts +597 -0
- package/core/config/index.ts +317 -0
- package/core/config/loader.ts +546 -0
- package/core/config/runtime-config.ts +322 -0
- package/core/config/schema.ts +694 -0
- package/core/config/validator.ts +540 -0
- package/core/framework/__tests__/server.test.ts +233 -0
- package/core/framework/client.ts +132 -0
- package/core/framework/index.ts +8 -0
- package/core/framework/server.ts +501 -0
- package/core/framework/types.ts +63 -0
- package/core/plugins/__tests__/built-in.test.ts.disabled +366 -0
- package/core/plugins/__tests__/manager.test.ts +398 -0
- package/core/plugins/__tests__/monitoring.test.ts +401 -0
- package/core/plugins/__tests__/registry.test.ts +335 -0
- package/core/plugins/built-in/index.ts +142 -0
- package/core/plugins/built-in/logger/index.ts +180 -0
- package/core/plugins/built-in/monitoring/README.md +193 -0
- package/core/plugins/built-in/monitoring/index.ts +912 -0
- package/core/plugins/built-in/static/index.ts +289 -0
- package/core/plugins/built-in/swagger/index.ts +229 -0
- package/core/plugins/built-in/vite/index.ts +316 -0
- package/core/plugins/config.ts +348 -0
- package/core/plugins/discovery.ts +350 -0
- package/core/plugins/executor.ts +351 -0
- package/core/plugins/index.ts +195 -0
- package/core/plugins/manager.ts +583 -0
- package/core/plugins/registry.ts +424 -0
- package/core/plugins/types.ts +254 -0
- package/core/server/framework.ts +123 -0
- package/core/server/index.ts +8 -0
- package/core/server/plugins/database.ts +182 -0
- package/core/server/plugins/logger.ts +47 -0
- package/core/server/plugins/swagger.ts +34 -0
- package/core/server/standalone.ts +91 -0
- package/core/templates/create-project.ts +455 -0
- package/core/types/api.ts +169 -0
- package/core/types/build.ts +174 -0
- package/core/types/config.ts +68 -0
- package/core/types/index.ts +127 -0
- package/core/types/plugin.ts +94 -0
- package/core/utils/__tests__/errors.test.ts +139 -0
- package/core/utils/__tests__/helpers.test.ts +297 -0
- package/core/utils/__tests__/logger.test.ts +141 -0
- package/core/utils/env-runtime-v2.ts +232 -0
- package/core/utils/env-runtime.ts +252 -0
- package/core/utils/errors/codes.ts +115 -0
- package/core/utils/errors/handlers.ts +63 -0
- package/core/utils/errors/index.ts +81 -0
- package/core/utils/helpers.ts +180 -0
- package/core/utils/index.ts +18 -0
- package/core/utils/logger/index.ts +161 -0
- package/core/utils/logger.ts +106 -0
- package/core/utils/monitoring/index.ts +212 -0
- package/create-fluxstack.ts +231 -0
- package/package.json +43 -0
- package/tsconfig.json +51 -0
- package/vite.config.ts +42 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Environment Variable Type Conversion Utilities
|
|
3
|
+
* Tests edge cases and type conversion robustness
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, test, expect } from 'vitest'
|
|
7
|
+
import { EnvConverter } from '../env'
|
|
8
|
+
|
|
9
|
+
describe('EnvConverter Edge Cases and Robustness', () => {
|
|
10
|
+
describe('toNumber edge cases', () => {
|
|
11
|
+
test('handles various number formats correctly', () => {
|
|
12
|
+
// Basic cases
|
|
13
|
+
expect(EnvConverter.toNumber('42', 0)).toBe(42)
|
|
14
|
+
expect(EnvConverter.toNumber('-123', 0)).toBe(-123)
|
|
15
|
+
expect(EnvConverter.toNumber('0', 42)).toBe(0)
|
|
16
|
+
|
|
17
|
+
// Edge cases
|
|
18
|
+
expect(EnvConverter.toNumber('00000123', 0)).toBe(123)
|
|
19
|
+
expect(EnvConverter.toNumber('+456', 0)).toBe(456)
|
|
20
|
+
expect(EnvConverter.toNumber(' 789 ', 0)).toBe(789) // With whitespace
|
|
21
|
+
|
|
22
|
+
// Hex and octal (parseInt with base 10 behavior)
|
|
23
|
+
expect(EnvConverter.toNumber('0x10', 0)).toBe(0) // parseInt with base 10 doesn't parse hex
|
|
24
|
+
expect(EnvConverter.toNumber('0o10', 0)).toBe(0) // parseInt doesn't handle 0o prefix
|
|
25
|
+
expect(EnvConverter.toNumber('010', 0)).toBe(10) // Treated as decimal, not octal
|
|
26
|
+
|
|
27
|
+
// Invalid cases
|
|
28
|
+
expect(EnvConverter.toNumber('abc', 42)).toBe(42)
|
|
29
|
+
expect(EnvConverter.toNumber('123abc', 42)).toBe(123) // parseInt stops at first non-digit
|
|
30
|
+
expect(EnvConverter.toNumber('', 42)).toBe(42)
|
|
31
|
+
expect(EnvConverter.toNumber(' ', 42)).toBe(42)
|
|
32
|
+
expect(EnvConverter.toNumber('Infinity', 42)).toBe(42)
|
|
33
|
+
expect(EnvConverter.toNumber('NaN', 42)).toBe(42)
|
|
34
|
+
expect(EnvConverter.toNumber(undefined, 42)).toBe(42)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('handles floating point strings (parseInt behavior)', () => {
|
|
38
|
+
// parseInt truncates to integer
|
|
39
|
+
expect(EnvConverter.toNumber('12.34', 0)).toBe(12)
|
|
40
|
+
expect(EnvConverter.toNumber('56.78', 0)).toBe(56)
|
|
41
|
+
expect(EnvConverter.toNumber('.123', 0)).toBe(0) // parseInt behavior with leading dot
|
|
42
|
+
expect(EnvConverter.toNumber('9.', 0)).toBe(9)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('handles extreme values', () => {
|
|
46
|
+
expect(EnvConverter.toNumber('999999999999999', 0)).toBe(999999999999999)
|
|
47
|
+
expect(EnvConverter.toNumber('-999999999999999', 0)).toBe(-999999999999999)
|
|
48
|
+
expect(EnvConverter.toNumber('1e10', 0)).toBe(1) // parseInt stops at 'e'
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe('toBoolean edge cases', () => {
|
|
53
|
+
test('handles various truthy representations', () => {
|
|
54
|
+
// Standard truthy values
|
|
55
|
+
expect(EnvConverter.toBoolean('true', false)).toBe(true)
|
|
56
|
+
expect(EnvConverter.toBoolean('1', false)).toBe(true)
|
|
57
|
+
expect(EnvConverter.toBoolean('yes', false)).toBe(true)
|
|
58
|
+
expect(EnvConverter.toBoolean('on', false)).toBe(true)
|
|
59
|
+
|
|
60
|
+
// Case variations
|
|
61
|
+
expect(EnvConverter.toBoolean('TRUE', false)).toBe(true)
|
|
62
|
+
expect(EnvConverter.toBoolean('True', false)).toBe(true)
|
|
63
|
+
expect(EnvConverter.toBoolean('YES', false)).toBe(true)
|
|
64
|
+
expect(EnvConverter.toBoolean('Yes', false)).toBe(true)
|
|
65
|
+
expect(EnvConverter.toBoolean('ON', false)).toBe(true)
|
|
66
|
+
expect(EnvConverter.toBoolean('On', false)).toBe(true)
|
|
67
|
+
|
|
68
|
+
// With whitespace
|
|
69
|
+
expect(EnvConverter.toBoolean(' true ', false)).toBe(false) // No trim in current implementation
|
|
70
|
+
expect(EnvConverter.toBoolean(' 1 ', false)).toBe(false)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('handles various falsy representations', () => {
|
|
74
|
+
// Standard falsy values
|
|
75
|
+
expect(EnvConverter.toBoolean('false', true)).toBe(false)
|
|
76
|
+
expect(EnvConverter.toBoolean('0', true)).toBe(false)
|
|
77
|
+
expect(EnvConverter.toBoolean('no', true)).toBe(false)
|
|
78
|
+
expect(EnvConverter.toBoolean('off', true)).toBe(false)
|
|
79
|
+
|
|
80
|
+
// Any other string is falsy
|
|
81
|
+
expect(EnvConverter.toBoolean('maybe', true)).toBe(false)
|
|
82
|
+
expect(EnvConverter.toBoolean('2', true)).toBe(false)
|
|
83
|
+
expect(EnvConverter.toBoolean('anything', true)).toBe(false)
|
|
84
|
+
expect(EnvConverter.toBoolean('', true)).toBe(false)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('handles edge cases', () => {
|
|
88
|
+
expect(EnvConverter.toBoolean(undefined, true)).toBe(true)
|
|
89
|
+
expect(EnvConverter.toBoolean(undefined, false)).toBe(false)
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
describe('toArray edge cases', () => {
|
|
94
|
+
test('handles various delimiter scenarios', () => {
|
|
95
|
+
// Basic cases
|
|
96
|
+
expect(EnvConverter.toArray('a,b,c')).toEqual(['a', 'b', 'c'])
|
|
97
|
+
expect(EnvConverter.toArray('single')).toEqual(['single'])
|
|
98
|
+
|
|
99
|
+
// Whitespace handling
|
|
100
|
+
expect(EnvConverter.toArray('a, b , c')).toEqual(['a', 'b', 'c'])
|
|
101
|
+
expect(EnvConverter.toArray(' a , b , c ')).toEqual(['a', 'b', 'c'])
|
|
102
|
+
|
|
103
|
+
// Empty values
|
|
104
|
+
expect(EnvConverter.toArray('a,,c')).toEqual(['a', 'c'])
|
|
105
|
+
expect(EnvConverter.toArray(',a,b,')).toEqual(['a', 'b'])
|
|
106
|
+
expect(EnvConverter.toArray(',,,')).toEqual([])
|
|
107
|
+
|
|
108
|
+
// Special characters
|
|
109
|
+
expect(EnvConverter.toArray('a\\,b,c')).toEqual(['a\\', 'b', 'c']) // No escape handling
|
|
110
|
+
expect(EnvConverter.toArray('a"b,c')).toEqual(['a"b', 'c'])
|
|
111
|
+
expect(EnvConverter.toArray("a'b,c")).toEqual(["a'b", 'c'])
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test('handles empty and undefined inputs', () => {
|
|
115
|
+
expect(EnvConverter.toArray('')).toEqual([])
|
|
116
|
+
expect(EnvConverter.toArray(undefined)).toEqual([])
|
|
117
|
+
expect(EnvConverter.toArray(undefined, ['default'])).toEqual(['default'])
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('handles URLs and complex strings', () => {
|
|
121
|
+
const urls = 'http://localhost:3000,https://example.com:8080,ftp://ftp.example.com'
|
|
122
|
+
expect(EnvConverter.toArray(urls)).toEqual([
|
|
123
|
+
'http://localhost:3000',
|
|
124
|
+
'https://example.com:8080',
|
|
125
|
+
'ftp://ftp.example.com'
|
|
126
|
+
])
|
|
127
|
+
|
|
128
|
+
const methods = 'GET,POST,PUT,DELETE,PATCH,OPTIONS,HEAD'
|
|
129
|
+
expect(EnvConverter.toArray(methods)).toEqual([
|
|
130
|
+
'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD'
|
|
131
|
+
])
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
describe('toLogLevel edge cases', () => {
|
|
136
|
+
test('handles case variations', () => {
|
|
137
|
+
expect(EnvConverter.toLogLevel('DEBUG', 'info')).toBe('debug')
|
|
138
|
+
expect(EnvConverter.toLogLevel('Info', 'debug')).toBe('info')
|
|
139
|
+
expect(EnvConverter.toLogLevel('WARN', 'info')).toBe('warn')
|
|
140
|
+
expect(EnvConverter.toLogLevel('Error', 'info')).toBe('error')
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
test('handles invalid levels', () => {
|
|
144
|
+
expect(EnvConverter.toLogLevel('verbose', 'info')).toBe('info')
|
|
145
|
+
expect(EnvConverter.toLogLevel('trace', 'warn')).toBe('warn')
|
|
146
|
+
expect(EnvConverter.toLogLevel('critical', 'error')).toBe('error')
|
|
147
|
+
expect(EnvConverter.toLogLevel('', 'debug')).toBe('debug')
|
|
148
|
+
expect(EnvConverter.toLogLevel('123', 'info')).toBe('info')
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
test('handles whitespace and special characters', () => {
|
|
152
|
+
expect(EnvConverter.toLogLevel(' debug ', 'info')).toBe('info') // No trim
|
|
153
|
+
expect(EnvConverter.toLogLevel('debug\n', 'info')).toBe('info')
|
|
154
|
+
expect(EnvConverter.toLogLevel('de-bug', 'info')).toBe('info')
|
|
155
|
+
})
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
describe('toBuildTarget edge cases', () => {
|
|
159
|
+
test('handles case variations', () => {
|
|
160
|
+
expect(EnvConverter.toBuildTarget('BUN', 'node')).toBe('bun')
|
|
161
|
+
expect(EnvConverter.toBuildTarget('Node', 'bun')).toBe('node')
|
|
162
|
+
expect(EnvConverter.toBuildTarget('DOCKER', 'bun')).toBe('docker')
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
test('handles invalid targets', () => {
|
|
166
|
+
expect(EnvConverter.toBuildTarget('webpack', 'bun')).toBe('bun')
|
|
167
|
+
expect(EnvConverter.toBuildTarget('rollup', 'node')).toBe('node')
|
|
168
|
+
expect(EnvConverter.toBuildTarget('vite', 'docker')).toBe('docker')
|
|
169
|
+
expect(EnvConverter.toBuildTarget('', 'bun')).toBe('bun')
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
test('handles similar but invalid targets', () => {
|
|
173
|
+
expect(EnvConverter.toBuildTarget('nodejs', 'bun')).toBe('bun')
|
|
174
|
+
expect(EnvConverter.toBuildTarget('bunjs', 'node')).toBe('node')
|
|
175
|
+
expect(EnvConverter.toBuildTarget('container', 'bun')).toBe('bun')
|
|
176
|
+
})
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
describe('toLogFormat edge cases', () => {
|
|
180
|
+
test('handles case variations', () => {
|
|
181
|
+
expect(EnvConverter.toLogFormat('JSON', 'pretty')).toBe('json')
|
|
182
|
+
expect(EnvConverter.toLogFormat('Pretty', 'json')).toBe('pretty')
|
|
183
|
+
expect(EnvConverter.toLogFormat('PRETTY', 'json')).toBe('pretty')
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
test('handles invalid formats', () => {
|
|
187
|
+
expect(EnvConverter.toLogFormat('text', 'json')).toBe('json')
|
|
188
|
+
expect(EnvConverter.toLogFormat('yaml', 'pretty')).toBe('pretty')
|
|
189
|
+
expect(EnvConverter.toLogFormat('structured', 'json')).toBe('json')
|
|
190
|
+
expect(EnvConverter.toLogFormat('', 'pretty')).toBe('pretty')
|
|
191
|
+
})
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
describe('toObject edge cases', () => {
|
|
195
|
+
test('handles valid JSON variations', () => {
|
|
196
|
+
expect(EnvConverter.toObject('{"key":"value"}', {})).toEqual({ key: 'value' })
|
|
197
|
+
expect(EnvConverter.toObject('{"nested":{"key":"value"}}', {})).toEqual({
|
|
198
|
+
nested: { key: 'value' }
|
|
199
|
+
})
|
|
200
|
+
expect(EnvConverter.toObject('[1,2,3]', {})).toEqual([1, 2, 3])
|
|
201
|
+
expect(EnvConverter.toObject('null', {})).toBe(null)
|
|
202
|
+
expect(EnvConverter.toObject('true', {})).toBe(true)
|
|
203
|
+
expect(EnvConverter.toObject('42', {})).toBe(42)
|
|
204
|
+
expect(EnvConverter.toObject('"string"', {})).toBe('string')
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
test('handles malformed JSON', () => {
|
|
208
|
+
const defaultValue = { default: true }
|
|
209
|
+
|
|
210
|
+
expect(EnvConverter.toObject('{key:"value"}', defaultValue)).toBe(defaultValue) // Missing quotes
|
|
211
|
+
expect(EnvConverter.toObject('{"key":value}', defaultValue)).toBe(defaultValue) // Unquoted value
|
|
212
|
+
expect(EnvConverter.toObject('{key:value}', defaultValue)).toBe(defaultValue) // No quotes
|
|
213
|
+
expect(EnvConverter.toObject('{"key":"value",}', defaultValue)).toBe(defaultValue) // Trailing comma
|
|
214
|
+
expect(EnvConverter.toObject('{', defaultValue)).toBe(defaultValue) // Incomplete
|
|
215
|
+
expect(EnvConverter.toObject('not json at all', defaultValue)).toBe(defaultValue)
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
test('handles edge JSON cases', () => {
|
|
219
|
+
expect(EnvConverter.toObject('{}', { default: true })).toEqual({})
|
|
220
|
+
expect(EnvConverter.toObject('[]', { default: true })).toEqual([])
|
|
221
|
+
expect(EnvConverter.toObject('""', { default: true })).toBe('')
|
|
222
|
+
expect(EnvConverter.toObject('0', { default: true })).toBe(0)
|
|
223
|
+
expect(EnvConverter.toObject('false', { default: true })).toBe(false)
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
test('handles complex nested objects', () => {
|
|
227
|
+
const complexJson = JSON.stringify({
|
|
228
|
+
server: {
|
|
229
|
+
port: 3000,
|
|
230
|
+
host: 'localhost',
|
|
231
|
+
options: {
|
|
232
|
+
cors: true,
|
|
233
|
+
compression: false,
|
|
234
|
+
middleware: ['auth', 'logging']
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
database: {
|
|
238
|
+
url: 'postgresql://localhost:5432/db',
|
|
239
|
+
pool: { min: 2, max: 10 }
|
|
240
|
+
}
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
const result = EnvConverter.toObject(complexJson, {})
|
|
244
|
+
expect(result).toEqual({
|
|
245
|
+
server: {
|
|
246
|
+
port: 3000,
|
|
247
|
+
host: 'localhost',
|
|
248
|
+
options: {
|
|
249
|
+
cors: true,
|
|
250
|
+
compression: false,
|
|
251
|
+
middleware: ['auth', 'logging']
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
database: {
|
|
255
|
+
url: 'postgresql://localhost:5432/db',
|
|
256
|
+
pool: { min: 2, max: 10 }
|
|
257
|
+
}
|
|
258
|
+
})
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
test('handles undefined and empty inputs', () => {
|
|
262
|
+
const defaultValue = { default: true }
|
|
263
|
+
expect(EnvConverter.toObject(undefined, defaultValue)).toBe(defaultValue)
|
|
264
|
+
expect(EnvConverter.toObject('', defaultValue)).toBe(defaultValue)
|
|
265
|
+
})
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
describe('Conversion consistency', () => {
|
|
269
|
+
test('maintains type safety across conversions', () => {
|
|
270
|
+
// Number conversions should always return numbers or defaults
|
|
271
|
+
const numResult = EnvConverter.toNumber('invalid', 42)
|
|
272
|
+
expect(typeof numResult).toBe('number')
|
|
273
|
+
expect(numResult).toBe(42)
|
|
274
|
+
|
|
275
|
+
// Boolean conversions should always return booleans
|
|
276
|
+
const boolResult = EnvConverter.toBoolean('maybe', true)
|
|
277
|
+
expect(typeof boolResult).toBe('boolean')
|
|
278
|
+
|
|
279
|
+
// Array conversions should always return arrays
|
|
280
|
+
const arrayResult = EnvConverter.toArray('a,b,c')
|
|
281
|
+
expect(Array.isArray(arrayResult)).toBe(true)
|
|
282
|
+
|
|
283
|
+
// String enums should return valid enum values or defaults
|
|
284
|
+
const logLevelResult = EnvConverter.toLogLevel('invalid', 'info')
|
|
285
|
+
expect(['debug', 'info', 'warn', 'error']).toContain(logLevelResult)
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
test('handles null and undefined consistently', () => {
|
|
289
|
+
expect(EnvConverter.toNumber(undefined, 42)).toBe(42)
|
|
290
|
+
expect(EnvConverter.toBoolean(undefined, true)).toBe(true)
|
|
291
|
+
expect(EnvConverter.toArray(undefined)).toEqual([])
|
|
292
|
+
expect(EnvConverter.toLogLevel(undefined, 'info')).toBe('info')
|
|
293
|
+
expect(EnvConverter.toBuildTarget(undefined, 'bun')).toBe('bun')
|
|
294
|
+
expect(EnvConverter.toLogFormat(undefined, 'pretty')).toBe('pretty')
|
|
295
|
+
expect(EnvConverter.toObject(undefined, {})).toEqual({})
|
|
296
|
+
})
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
describe('Real-world environment variable scenarios', () => {
|
|
300
|
+
test('handles PORT environment variable edge cases', () => {
|
|
301
|
+
// Common port scenarios
|
|
302
|
+
expect(EnvConverter.toNumber('3000', 8080)).toBe(3000)
|
|
303
|
+
expect(EnvConverter.toNumber('0', 8080)).toBe(0) // Dynamic port
|
|
304
|
+
expect(EnvConverter.toNumber('80', 8080)).toBe(80)
|
|
305
|
+
expect(EnvConverter.toNumber('443', 8080)).toBe(443)
|
|
306
|
+
expect(EnvConverter.toNumber('8080', 3000)).toBe(8080)
|
|
307
|
+
|
|
308
|
+
// Invalid port values
|
|
309
|
+
expect(EnvConverter.toNumber('port', 3000)).toBe(3000)
|
|
310
|
+
expect(EnvConverter.toNumber('-1', 3000)).toBe(-1) // Negative (invalid but parsed)
|
|
311
|
+
expect(EnvConverter.toNumber('70000', 3000)).toBe(70000) // Out of range but parsed
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
test('handles CORS_ORIGINS environment variable', () => {
|
|
315
|
+
// Single origin
|
|
316
|
+
expect(EnvConverter.toArray('http://localhost:3000')).toEqual(['http://localhost:3000'])
|
|
317
|
+
|
|
318
|
+
// Multiple origins
|
|
319
|
+
expect(EnvConverter.toArray('http://localhost:3000,https://example.com')).toEqual([
|
|
320
|
+
'http://localhost:3000',
|
|
321
|
+
'https://example.com'
|
|
322
|
+
])
|
|
323
|
+
|
|
324
|
+
// With ports and paths
|
|
325
|
+
expect(EnvConverter.toArray('http://localhost:3000,https://example.com:8080/app')).toEqual([
|
|
326
|
+
'http://localhost:3000',
|
|
327
|
+
'https://example.com:8080/app'
|
|
328
|
+
])
|
|
329
|
+
|
|
330
|
+
// Wildcard
|
|
331
|
+
expect(EnvConverter.toArray('*')).toEqual(['*'])
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
test('handles boolean flags from different tools', () => {
|
|
335
|
+
// Docker-style
|
|
336
|
+
expect(EnvConverter.toBoolean('true', false)).toBe(true)
|
|
337
|
+
expect(EnvConverter.toBoolean('false', true)).toBe(false)
|
|
338
|
+
|
|
339
|
+
// Shell-style
|
|
340
|
+
expect(EnvConverter.toBoolean('1', false)).toBe(true)
|
|
341
|
+
expect(EnvConverter.toBoolean('0', true)).toBe(false)
|
|
342
|
+
|
|
343
|
+
// Human-readable
|
|
344
|
+
expect(EnvConverter.toBoolean('yes', false)).toBe(true)
|
|
345
|
+
expect(EnvConverter.toBoolean('no', true)).toBe(false)
|
|
346
|
+
expect(EnvConverter.toBoolean('on', false)).toBe(true)
|
|
347
|
+
expect(EnvConverter.toBoolean('off', true)).toBe(false)
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
test('handles complex JSON configurations', () => {
|
|
351
|
+
// Plugin configuration
|
|
352
|
+
const pluginConfig = JSON.stringify({
|
|
353
|
+
enabled: true,
|
|
354
|
+
options: {
|
|
355
|
+
timeout: 5000,
|
|
356
|
+
retries: 3,
|
|
357
|
+
endpoints: ['api', 'webhook']
|
|
358
|
+
}
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
const result = EnvConverter.toObject(pluginConfig, {})
|
|
362
|
+
expect(result).toEqual({
|
|
363
|
+
enabled: true,
|
|
364
|
+
options: {
|
|
365
|
+
timeout: 5000,
|
|
366
|
+
retries: 3,
|
|
367
|
+
endpoints: ['api', 'webhook']
|
|
368
|
+
}
|
|
369
|
+
})
|
|
370
|
+
})
|
|
371
|
+
})
|
|
372
|
+
})
|