create-fluxstack 1.17.0 → 1.18.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/LLMD/resources/live-auth.md +462 -465
- package/app/client/.live-stubs/LiveAdminPanel.js +15 -0
- package/app/client/.live-stubs/LiveCounter.js +9 -0
- package/app/client/.live-stubs/LiveForm.js +11 -0
- package/app/client/.live-stubs/LiveLocalCounter.js +8 -0
- package/app/client/.live-stubs/LivePingPong.js +10 -0
- package/app/client/.live-stubs/LiveRoomChat.js +11 -0
- package/app/client/.live-stubs/LiveSharedCounter.js +10 -0
- package/app/client/.live-stubs/LiveUpload.js +15 -0
- package/app/client/src/App.tsx +45 -3
- package/app/client/src/components/AppLayout.tsx +10 -1
- package/app/client/src/components/ErrorBoundary.tsx +117 -0
- package/app/client/src/components/LiveErrorBoundary.tsx +87 -0
- package/app/client/src/components/LiveUploadWidget.tsx +10 -14
- package/app/client/src/lib/eden-api.ts +6 -0
- package/app/client/src/lib/plugin-hooks.ts +82 -0
- package/app/client/src/live/AuthDemo.tsx +0 -1
- package/app/client/src/live/FormDemo.tsx +1 -1
- package/app/client/src/live/PingPongDemo.tsx +4 -1
- package/app/client/src/live/RoomChatDemo.tsx +90 -50
- package/app/client/src/live/SharedCounterDemo.tsx +5 -0
- package/app/server/auth/AuthManager.ts +24 -0
- package/app/server/auth/contracts.ts +12 -1
- package/app/server/auth/errors.ts +84 -0
- package/app/server/auth/guards/TokenGuard.ts +5 -2
- package/app/server/auth/index.ts +1 -1
- package/app/server/auth/providers/InMemoryProvider.ts +1 -1
- package/app/server/index.ts +3 -4
- package/app/server/live/LiveAdminPanel.ts +8 -8
- package/app/server/live/LiveForm.ts +1 -1
- package/app/server/live/LiveProtectedChat.ts +5 -5
- package/app/server/live/LiveRoomChat.ts +50 -28
- package/app/server/live/LiveUpload.ts +17 -3
- package/app/server/live/auto-generated-components.ts +26 -0
- package/app/server/live/rooms/ChatRoom.ts +17 -2
- package/app/server/routes/auth.routes.ts +29 -20
- package/app/server/routes/index.ts +9 -0
- package/app/server/routes/room.routes.ts +6 -6
- package/config/index.ts +3 -3
- package/config/system/app.config.ts +1 -1
- package/config/system/auth.config.ts +1 -1
- package/config/system/build.config.ts +8 -6
- package/config/system/client.config.ts +6 -4
- package/config/system/database.config.ts +1 -1
- package/config/system/logger.config.ts +1 -1
- package/config/system/monitoring.config.ts +6 -4
- package/config/system/plugins.config.ts +1 -1
- package/config/system/runtime.config.ts +1 -1
- package/config/system/server.config.ts +1 -1
- package/config/system/services.config.ts +1 -1
- package/config/system/session.config.ts +3 -3
- package/config/system/system.config.ts +1 -1
- package/core/build/vite-plugins.ts +3 -2
- package/core/cli/generators/plugin.ts +1 -1
- package/core/config/index.ts +8 -1
- package/core/framework/server.ts +9 -5
- package/core/index.ts +1 -1
- package/core/plugins/index.ts +1 -1
- package/core/plugins/manager.ts +5 -1
- package/core/plugins/types.ts +17 -1
- package/core/server/index.ts +5 -2
- package/core/server/live/index.ts +8 -71
- package/core/server/plugin-client-hooks.ts +97 -0
- package/core/types/types.ts +1 -0
- package/core/utils/version.ts +1 -1
- package/create-fluxstack.ts +1 -1
- package/package.json +8 -5
- package/src/client/components/ui/StatusBadge.tsx +23 -0
- package/core/utils/config-schema.ts +0 -480
- package/core/utils/env.ts +0 -305
- package/plugins/crypto-auth/README.md +0 -788
- package/plugins/crypto-auth/ai-context.md +0 -1282
- package/plugins/crypto-auth/cli/make-protected-route.command.ts +0 -383
- package/plugins/crypto-auth/client/CryptoAuthClient.ts +0 -302
- package/plugins/crypto-auth/client/components/AuthProvider.tsx +0 -131
- package/plugins/crypto-auth/client/components/LoginButton.tsx +0 -138
- package/plugins/crypto-auth/client/components/ProtectedRoute.tsx +0 -89
- package/plugins/crypto-auth/client/components/index.ts +0 -12
- package/plugins/crypto-auth/client/index.ts +0 -12
- package/plugins/crypto-auth/config/index.ts +0 -34
- package/plugins/crypto-auth/index.ts +0 -173
- package/plugins/crypto-auth/package.json +0 -66
- package/plugins/crypto-auth/server/AuthMiddleware.ts +0 -181
- package/plugins/crypto-auth/server/CryptoAuthLiveProvider.ts +0 -58
- package/plugins/crypto-auth/server/CryptoAuthService.ts +0 -186
- package/plugins/crypto-auth/server/index.ts +0 -25
- package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +0 -66
- package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +0 -26
- package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +0 -77
- package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +0 -45
- package/plugins/crypto-auth/server/middlewares/helpers.ts +0 -155
- package/plugins/crypto-auth/server/middlewares/index.ts +0 -22
- package/plugins/crypto-auth/server/middlewares.ts +0 -19
package/core/utils/env.ts
DELETED
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ⚡ FluxStack Unified Environment Loader
|
|
3
|
-
*
|
|
4
|
-
* Single source of truth for environment variables with:
|
|
5
|
-
* - Automatic type casting
|
|
6
|
-
* - Build-safe dynamic access (prevents Bun inlining)
|
|
7
|
-
* - Simple, intuitive API
|
|
8
|
-
* - TypeScript type inference
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* import { env } from '@core/utils/env'
|
|
13
|
-
*
|
|
14
|
-
* const port = env.PORT // number (3000)
|
|
15
|
-
* const debug = env.DEBUG // boolean (false)
|
|
16
|
-
* const origins = env.CORS_ORIGINS // string[] (['*'])
|
|
17
|
-
*
|
|
18
|
-
* // Custom vars with smart casting
|
|
19
|
-
* const timeout = env.get('TIMEOUT', 5000) // number
|
|
20
|
-
* const enabled = env.get('FEATURE_X', false) // boolean
|
|
21
|
-
* const tags = env.get('TAGS', ['api']) // string[]
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Smart environment loader with dynamic access
|
|
27
|
-
* Uses Bun.env (runtime) → process.env (fallback) → eval (last resort)
|
|
28
|
-
*/
|
|
29
|
-
class EnvLoader {
|
|
30
|
-
private cache = new Map<string, unknown>()
|
|
31
|
-
private accessor: () => Record<string, string | undefined>
|
|
32
|
-
|
|
33
|
-
constructor() {
|
|
34
|
-
this.accessor = this.createAccessor()
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Create dynamic accessor to prevent build-time inlining
|
|
39
|
-
*/
|
|
40
|
-
private createAccessor(): () => Record<string, string | undefined> {
|
|
41
|
-
const global = globalThis as unknown as Record<string, Record<string, unknown> | undefined>
|
|
42
|
-
|
|
43
|
-
return () => {
|
|
44
|
-
// Try Bun.env first (most reliable in Bun)
|
|
45
|
-
const bun = global['Bun'] as Record<string, unknown> | undefined
|
|
46
|
-
if (bun?.['env']) {
|
|
47
|
-
return bun['env'] as Record<string, string | undefined>
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Fallback to process.env
|
|
51
|
-
const proc = global['process'] as Record<string, unknown> | undefined
|
|
52
|
-
if (proc?.['env']) {
|
|
53
|
-
return proc['env'] as Record<string, string | undefined>
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return {}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Get environment variable with automatic type casting
|
|
62
|
-
* Type is inferred from defaultValue
|
|
63
|
-
*/
|
|
64
|
-
get<T>(key: string, defaultValue?: T): T {
|
|
65
|
-
// Check cache first
|
|
66
|
-
const cacheKey = `${key}:${typeof defaultValue}`
|
|
67
|
-
if (this.cache.has(cacheKey)) {
|
|
68
|
-
return this.cache.get(cacheKey) as T
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const env = this.accessor()
|
|
72
|
-
const value = env[key]
|
|
73
|
-
|
|
74
|
-
if (!value || value === '') {
|
|
75
|
-
this.cache.set(cacheKey, defaultValue as T)
|
|
76
|
-
return defaultValue as T
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Auto-detect type from defaultValue
|
|
80
|
-
let result: unknown = value
|
|
81
|
-
|
|
82
|
-
if (typeof defaultValue === 'number') {
|
|
83
|
-
const parsed = Number(value)
|
|
84
|
-
result = isNaN(parsed) ? defaultValue : parsed
|
|
85
|
-
} else if (typeof defaultValue === 'boolean') {
|
|
86
|
-
result = ['true', '1', 'yes', 'on'].includes(value.toLowerCase())
|
|
87
|
-
} else if (Array.isArray(defaultValue)) {
|
|
88
|
-
result = value.split(',').map(v => v.trim()).filter(Boolean)
|
|
89
|
-
} else if (typeof defaultValue === 'object' && defaultValue !== null) {
|
|
90
|
-
try {
|
|
91
|
-
result = JSON.parse(value)
|
|
92
|
-
} catch {
|
|
93
|
-
result = defaultValue
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
this.cache.set(cacheKey, result)
|
|
98
|
-
return result as T
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Check if environment variable exists and has a value
|
|
103
|
-
*/
|
|
104
|
-
has(key: string): boolean {
|
|
105
|
-
const env = this.accessor()
|
|
106
|
-
const value = env[key]
|
|
107
|
-
return value !== undefined && value !== ''
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Get all environment variables
|
|
112
|
-
*/
|
|
113
|
-
all(): Record<string, string> {
|
|
114
|
-
const env = this.accessor()
|
|
115
|
-
const result: Record<string, string> = {}
|
|
116
|
-
|
|
117
|
-
for (const [key, value] of Object.entries(env)) {
|
|
118
|
-
if (value !== undefined && value !== '') {
|
|
119
|
-
result[key] = value
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return result
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Require specific environment variables (throws if missing)
|
|
128
|
-
*/
|
|
129
|
-
require(keys: string[]): void {
|
|
130
|
-
const missing = keys.filter(key => !this.has(key))
|
|
131
|
-
if (missing.length > 0) {
|
|
132
|
-
throw new Error(
|
|
133
|
-
`Missing required environment variables: ${missing.join(', ')}\n` +
|
|
134
|
-
`Please set them in your .env file or environment.`
|
|
135
|
-
)
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Validate environment variable value
|
|
141
|
-
*/
|
|
142
|
-
validate(key: string, validValues: string[]): void {
|
|
143
|
-
const value = this.get(key, '')
|
|
144
|
-
if (value && !validValues.includes(value)) {
|
|
145
|
-
throw new Error(
|
|
146
|
-
`Invalid value for ${key}: "${value}"\n` +
|
|
147
|
-
`Valid values are: ${validValues.join(', ')}`
|
|
148
|
-
)
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Clear cache (useful for testing)
|
|
154
|
-
*/
|
|
155
|
-
clearCache(): void {
|
|
156
|
-
this.cache.clear()
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Singleton instance
|
|
161
|
-
const loader = new EnvLoader()
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Unified environment variables API
|
|
165
|
-
*/
|
|
166
|
-
export const env = {
|
|
167
|
-
/**
|
|
168
|
-
* Get environment variable with smart type casting
|
|
169
|
-
* @example env.get('PORT', 3000) → number
|
|
170
|
-
*/
|
|
171
|
-
get: <T>(key: string, defaultValue?: T): T => loader.get(key, defaultValue),
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Check if environment variable exists
|
|
175
|
-
*/
|
|
176
|
-
has: (key: string): boolean => loader.has(key),
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Get all environment variables
|
|
180
|
-
*/
|
|
181
|
-
all: (): Record<string, string> => loader.all(),
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Require environment variables (throws if missing)
|
|
185
|
-
*/
|
|
186
|
-
require: (keys: string[]): void => loader.require(keys),
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Validate environment variable value
|
|
190
|
-
*/
|
|
191
|
-
validate: (key: string, validValues: string[]): void => loader.validate(key, validValues),
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Clear cache (for testing)
|
|
195
|
-
*/
|
|
196
|
-
clearCache: (): void => loader.clearCache(),
|
|
197
|
-
|
|
198
|
-
// Common environment variables with smart defaults
|
|
199
|
-
get NODE_ENV() { return this.get('NODE_ENV', 'development') as 'development' | 'production' | 'test' },
|
|
200
|
-
get PORT() { return this.get('PORT', 3000) },
|
|
201
|
-
get HOST() { return this.get('HOST', 'localhost') },
|
|
202
|
-
get DEBUG() { return this.get('DEBUG', false) },
|
|
203
|
-
get LOG_LEVEL() { return this.get('LOG_LEVEL', 'info') as 'debug' | 'info' | 'warn' | 'error' },
|
|
204
|
-
get LOG_FORMAT() { return this.get('LOG_FORMAT', 'pretty') as 'json' | 'pretty' },
|
|
205
|
-
|
|
206
|
-
// API
|
|
207
|
-
get API_PREFIX() { return this.get('API_PREFIX', '/api') },
|
|
208
|
-
get VITE_PORT() { return this.get('VITE_PORT', 5173) },
|
|
209
|
-
|
|
210
|
-
// CORS
|
|
211
|
-
get CORS_ORIGINS() { return this.get('CORS_ORIGINS', ['*']) },
|
|
212
|
-
get CORS_METHODS() { return this.get('CORS_METHODS', ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']) },
|
|
213
|
-
get CORS_HEADERS() { return this.get('CORS_HEADERS', ['Content-Type', 'Authorization']) },
|
|
214
|
-
get CORS_CREDENTIALS() { return this.get('CORS_CREDENTIALS', false) },
|
|
215
|
-
get CORS_MAX_AGE() { return this.get('CORS_MAX_AGE', 86400) },
|
|
216
|
-
|
|
217
|
-
// App
|
|
218
|
-
get FLUXSTACK_APP_NAME() { return this.get('FLUXSTACK_APP_NAME', 'FluxStack') },
|
|
219
|
-
get FLUXSTACK_APP_VERSION() {
|
|
220
|
-
const { FLUXSTACK_VERSION } = require('./version')
|
|
221
|
-
return this.get('FLUXSTACK_APP_VERSION', FLUXSTACK_VERSION)
|
|
222
|
-
},
|
|
223
|
-
|
|
224
|
-
// Features
|
|
225
|
-
get ENABLE_MONITORING() { return this.get('ENABLE_MONITORING', false) },
|
|
226
|
-
get ENABLE_SWAGGER() { return this.get('ENABLE_SWAGGER', true) },
|
|
227
|
-
get ENABLE_METRICS() { return this.get('ENABLE_METRICS', false) },
|
|
228
|
-
|
|
229
|
-
// Database
|
|
230
|
-
get DATABASE_URL() { return this.get('DATABASE_URL', '') },
|
|
231
|
-
get DB_HOST() { return this.get('DB_HOST', 'localhost') },
|
|
232
|
-
get DB_PORT() { return this.get('DB_PORT', 5432) },
|
|
233
|
-
get DB_NAME() { return this.get('DB_NAME', '') },
|
|
234
|
-
get DB_USER() { return this.get('DB_USER', '') },
|
|
235
|
-
get DB_PASSWORD() { return this.get('DB_PASSWORD', '') },
|
|
236
|
-
get DB_SSL() { return this.get('DB_SSL', false) },
|
|
237
|
-
|
|
238
|
-
// Auth
|
|
239
|
-
get JWT_SECRET() { return this.get('JWT_SECRET', '') },
|
|
240
|
-
get JWT_EXPIRES_IN() { return this.get('JWT_EXPIRES_IN', '24h') },
|
|
241
|
-
get JWT_ALGORITHM() { return this.get('JWT_ALGORITHM', 'HS256') },
|
|
242
|
-
|
|
243
|
-
// Email
|
|
244
|
-
get SMTP_HOST() { return this.get('SMTP_HOST', '') },
|
|
245
|
-
get SMTP_PORT() { return this.get('SMTP_PORT', 587) },
|
|
246
|
-
get SMTP_USER() { return this.get('SMTP_USER', '') },
|
|
247
|
-
get SMTP_PASSWORD() { return this.get('SMTP_PASSWORD', '') },
|
|
248
|
-
get SMTP_SECURE() { return this.get('SMTP_SECURE', false) },
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Environment helpers
|
|
253
|
-
*/
|
|
254
|
-
export const helpers = {
|
|
255
|
-
isDevelopment: (): boolean => env.NODE_ENV === 'development',
|
|
256
|
-
isProduction: (): boolean => env.NODE_ENV === 'production',
|
|
257
|
-
isTest: (): boolean => env.NODE_ENV === 'test',
|
|
258
|
-
|
|
259
|
-
getServerUrl: (): string => `http://${env.HOST}:${env.PORT}`,
|
|
260
|
-
getClientUrl: (): string => `http://${env.HOST}:${env.VITE_PORT}`,
|
|
261
|
-
|
|
262
|
-
getDatabaseUrl: (): string | null => {
|
|
263
|
-
if (env.DATABASE_URL) return env.DATABASE_URL
|
|
264
|
-
|
|
265
|
-
const { DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD } = env
|
|
266
|
-
if (DB_HOST && DB_NAME) {
|
|
267
|
-
const auth = DB_USER ? `${DB_USER}:${DB_PASSWORD}@` : ''
|
|
268
|
-
return `postgres://${auth}${DB_HOST}:${DB_PORT}/${DB_NAME}`
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
return null
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Create namespaced environment access
|
|
277
|
-
* @example
|
|
278
|
-
* const db = createNamespace('DATABASE_')
|
|
279
|
-
* db.get('URL') // reads DATABASE_URL
|
|
280
|
-
*/
|
|
281
|
-
export function createNamespace(prefix: string) {
|
|
282
|
-
return {
|
|
283
|
-
get: <T>(key: string, defaultValue?: T): T =>
|
|
284
|
-
env.get(`${prefix}${key}`, defaultValue),
|
|
285
|
-
|
|
286
|
-
has: (key: string): boolean =>
|
|
287
|
-
env.has(`${prefix}${key}`),
|
|
288
|
-
|
|
289
|
-
all: (): Record<string, string> => {
|
|
290
|
-
const allEnv = env.all()
|
|
291
|
-
const namespaced: Record<string, string> = {}
|
|
292
|
-
|
|
293
|
-
for (const [key, value] of Object.entries(allEnv)) {
|
|
294
|
-
if (key.startsWith(prefix)) {
|
|
295
|
-
namespaced[key.slice(prefix.length)] = value
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
return namespaced
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Default export
|
|
305
|
-
export default env
|