create-fluxstack 1.0.11 → 1.0.13

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.
@@ -65,7 +65,9 @@
65
65
  "Read(/C:\\Users\\Marcos\\Documents\\GitHub\\aviso-projeto\\test-cli-update/**)",
66
66
  "Read(/C:\\Users\\Marcos\\Documents\\GitHub\\aviso-projeto\\test-gitignore/**)",
67
67
  "Read(/C:\\Users\\Marcos\\Documents\\GitHub\\aviso-projeto\\test-plugins-guide/**)",
68
- "Read(/C:\\Users\\Marcos\\Documents\\GitHub\\aviso-projeto\\test-plugins-guide\\ai-context\\development/**)"
68
+ "Read(/C:\\Users\\Marcos\\Documents\\GitHub\\aviso-projeto\\test-plugins-guide\\ai-context\\development/**)",
69
+ "Read(/C:\\Users\\Marcos\\Documents\\GitHub\\aviso-projeto\\test-env-fix/**)",
70
+ "Read(/C:\\Users\\Marcos\\Documents\\GitHub\\aviso-projeto\\final-test/**)"
69
71
  ],
70
72
  "deny": []
71
73
  }
package/.env.example CHANGED
@@ -10,36 +10,13 @@ HOST=localhost
10
10
  # Frontend Configuration
11
11
  FRONTEND_PORT=5173
12
12
  VITE_API_URL=http://localhost:3000
13
+ VITE_APP_NAME=FluxStack
14
+ VITE_APP_VERSION=1.0.0
15
+ VITE_NODE_ENV=development
13
16
 
14
17
  # Backend Configuration
15
18
  BACKEND_PORT=3001
16
19
 
17
- # Database (example - configure based on your needs)
18
- # DATABASE_URL=postgresql://user:password@localhost:5432/fluxstack
19
- # DATABASE_HOST=localhost
20
- # DATABASE_PORT=5432
21
- # DATABASE_NAME=fluxstack
22
- # DATABASE_USER=user
23
- # DATABASE_PASSWORD=password
24
-
25
- # Authentication (example)
26
- # JWT_SECRET=your-super-secret-jwt-key
27
- # JWT_EXPIRES_IN=24h
28
-
29
- # External APIs (example)
30
- # STRIPE_SECRET_KEY=sk_test_...
31
- # STRIPE_PUBLISHABLE_KEY=pk_test_...
32
-
33
- # Email Service (example)
34
- # SMTP_HOST=smtp.gmail.com
35
- # SMTP_PORT=587
36
- # SMTP_USER=your-email@gmail.com
37
- # SMTP_PASS=your-app-password
38
-
39
- # File Upload (example)
40
- # UPLOAD_PATH=uploads
41
- # MAX_FILE_SIZE=10485760
42
-
43
20
  # CORS Configuration
44
21
  CORS_ORIGINS=http://localhost:3000,http://localhost:5173
45
22
  CORS_METHODS=GET,POST,PUT,DELETE,OPTIONS
@@ -92,61 +92,65 @@ app.use(authPlugin)
92
92
  ### 2. Advanced Plugin with Lifecycle Hooks
93
93
 
94
94
  ```typescript
95
- // app/server/plugins/database.ts
95
+ // app/server/plugins/monitoring.ts
96
96
  import { Elysia } from 'elysia'
97
97
  import type { PluginContext, FluxStackPlugin } from '@/core/plugins/types'
98
98
 
99
- export interface DatabaseConfig {
100
- url: string
101
- poolSize?: number
102
- ssl?: boolean
99
+ export interface MonitoringConfig {
100
+ metricsEndpoint?: string
101
+ enableHealthCheck?: boolean
102
+ collectMetrics?: boolean
103
103
  }
104
104
 
105
- export const createDatabasePlugin = (config: DatabaseConfig): FluxStackPlugin => ({
106
- name: 'database',
105
+ export const createMonitoringPlugin = (config: MonitoringConfig): FluxStackPlugin => ({
106
+ name: 'monitoring',
107
107
  version: '1.0.0',
108
108
  dependencies: [],
109
109
 
110
110
  setup: async (context: PluginContext) => {
111
- context.logger.info('Setting up database connection', { url: config.url })
111
+ context.logger.info('Setting up monitoring plugin')
112
112
 
113
- // Initialize database connection
114
- const db = await connectToDatabase(config)
115
-
116
- return {
117
- db,
118
- query: db.query.bind(db),
119
- transaction: db.transaction.bind(db)
113
+ // Initialize metrics collection
114
+ const metrics = {
115
+ requests: 0,
116
+ errors: 0,
117
+ startTime: Date.now()
120
118
  }
119
+
120
+ return { metrics }
121
121
  },
122
122
 
123
123
  onServerStart: async (context: PluginContext) => {
124
- context.logger.info('Database plugin started')
125
- // Run migrations, health checks, etc.
124
+ context.logger.info('Monitoring plugin started')
125
+ // Start periodic health checks, metrics collection
126
126
  },
127
127
 
128
- onServerStop: async (context: PluginContext) => {
129
- context.logger.info('Closing database connections')
130
- // Clean up connections
128
+ onRequest: async (context: PluginContext) => {
129
+ context.metrics.requests++
131
130
  },
132
131
 
133
- plugin: new Elysia({ name: 'database' })
134
- .derive(() => ({
135
- // Provide database utilities to routes
136
- db: context.db
132
+ plugin: new Elysia({ name: 'monitoring' })
133
+ .get('/metrics', () => ({
134
+ requests: context.metrics.requests,
135
+ errors: context.metrics.errors,
136
+ uptime: Date.now() - context.metrics.startTime
137
+ }))
138
+ .get('/health', () => ({
139
+ status: 'healthy',
140
+ timestamp: new Date().toISOString()
137
141
  }))
138
142
  })
139
143
 
140
144
  // Usage
141
- import { createDatabasePlugin } from './plugins/database'
145
+ import { createMonitoringPlugin } from './plugins/monitoring'
142
146
 
143
- const databasePlugin = createDatabasePlugin({
144
- url: process.env.DATABASE_URL!,
145
- poolSize: 10,
146
- ssl: process.env.NODE_ENV === 'production'
147
+ const monitoringPlugin = createMonitoringPlugin({
148
+ metricsEndpoint: '/metrics',
149
+ enableHealthCheck: true,
150
+ collectMetrics: true
147
151
  })
148
152
 
149
- app.use(databasePlugin)
153
+ app.use(monitoringPlugin)
150
154
  ```
151
155
 
152
156
  ### 3. Plugin with Configuration Schema
@@ -330,19 +334,19 @@ app/server/plugins/
330
334
  │ │ ├── jwt.ts
331
335
  │ │ └── oauth.ts
332
336
  │ └── middleware/ # Auth-related middleware
333
- ├── database/
334
- │ ├── index.ts # Database plugin
335
- │ ├── migrations/ # Database migrations
336
- │ └── seeds/ # Database seeds
337
337
  ├── cache/
338
338
  │ ├── index.ts # Cache plugin
339
339
  │ ├── providers/ # Different cache providers
340
340
  │ │ ├── redis.ts
341
341
  │ │ └── memory.ts
342
- └── monitoring/
343
- ├── index.ts # Monitoring plugin
344
- ├── metrics.ts # Custom metrics
345
- └── health.ts # Health checks
342
+ ├── monitoring/
343
+ ├── index.ts # Monitoring plugin
344
+ ├── metrics.ts # Custom metrics
345
+ └── health.ts # Health checks
346
+ └── validation/
347
+ ├── index.ts # Validation plugin
348
+ ├── schemas/ # Validation schemas
349
+ └── middleware/ # Validation middleware
346
350
  ```
347
351
 
348
352
  ### Plugin Registration
@@ -350,23 +354,23 @@ app/server/plugins/
350
354
  ```typescript
351
355
  // app/server/plugins/index.ts
352
356
  export { authPlugin } from './auth'
353
- export { createDatabasePlugin } from './database'
354
357
  export { createCachePlugin } from './cache'
355
- export { monitoringPlugin } from './monitoring'
358
+ export { createMonitoringPlugin } from './monitoring'
359
+ export { validationPlugin } from './validation'
356
360
 
357
361
  // app/server/index.ts
358
362
  import {
359
363
  authPlugin,
360
- createDatabasePlugin,
361
364
  createCachePlugin,
362
- monitoringPlugin
365
+ createMonitoringPlugin,
366
+ validationPlugin
363
367
  } from './plugins'
364
368
 
365
369
  // Register plugins in order of dependency
366
- app.use(createDatabasePlugin({ url: env.DATABASE_URL }))
367
- app.use(createCachePlugin({ provider: 'redis', ttl: 300 }))
370
+ app.use(validationPlugin)
371
+ app.use(createCachePlugin({ provider: 'memory', ttl: 300 }))
368
372
  app.use(authPlugin)
369
- app.use(monitoringPlugin)
373
+ app.use(createMonitoringPlugin({ enableHealthCheck: true }))
370
374
  ```
371
375
 
372
376
  ## 🔧 Plugin Configuration
@@ -36,7 +36,9 @@ describe('Configuration Loader', () => {
36
36
  // Clear relevant environment variables
37
37
  for (const key in process.env) {
38
38
  if (key.startsWith('FLUXSTACK_') || key.startsWith('PORT') || key.startsWith('HOST') ||
39
- key.startsWith('NODE_ENV')) {
39
+ key.startsWith('NODE_ENV') || key.startsWith('CORS_') || key.startsWith('LOG_') ||
40
+ key.startsWith('MONITORING_') || key.startsWith('METRICS_') || key.startsWith('PROFILING_') ||
41
+ key.startsWith('BUILD_')) {
40
42
  delete process.env[key]
41
43
  }
42
44
  }
@@ -109,45 +111,6 @@ describe('Configuration Loader', () => {
109
111
  expect(config.server?.cors?.credentials).toBe(true)
110
112
  })
111
113
 
112
- test('handles database configuration from environment', () => {
113
- process.env.DATABASE_URL = 'postgresql://user:pass@localhost:5432/db'
114
- process.env.DATABASE_HOST = 'db.example.com'
115
- process.env.DATABASE_PORT = '5433'
116
- process.env.DATABASE_SSL = 'true'
117
-
118
- const config = getConfigSync()
119
-
120
- expect(config.database?.url).toBe('postgresql://user:pass@localhost:5432/db')
121
- expect(config.database?.host).toBe('db.example.com')
122
- expect(config.database?.port).toBe(5433)
123
- expect(config.database?.ssl).toBe(true)
124
- })
125
-
126
- test('handles authentication configuration', () => {
127
- process.env.JWT_SECRET = 'my-secret-key'
128
- process.env.JWT_EXPIRES_IN = '7d'
129
- process.env.JWT_ALGORITHM = 'HS256'
130
-
131
- const config = getConfigSync()
132
-
133
- expect(config.auth?.secret).toBe('my-secret-key')
134
- expect(config.auth?.expiresIn).toBe('7d')
135
- expect(config.auth?.algorithm).toBe('HS256')
136
- })
137
-
138
- test('handles email configuration', () => {
139
- process.env.SMTP_HOST = 'smtp.gmail.com'
140
- process.env.SMTP_PORT = '587'
141
- process.env.SMTP_USER = 'user@example.com'
142
- process.env.SMTP_SECURE = 'true'
143
-
144
- const config = getConfigSync()
145
-
146
- expect(config.email?.host).toBe('smtp.gmail.com')
147
- expect(config.email?.port).toBe(587)
148
- expect(config.email?.user).toBe('user@example.com')
149
- expect(config.email?.secure).toBe(true)
150
- })
151
114
 
152
115
  test('handles monitoring configuration', () => {
153
116
  process.env.MONITORING_ENABLED = 'true'
@@ -164,10 +127,10 @@ describe('Configuration Loader', () => {
164
127
  })
165
128
 
166
129
  test('handles build configuration', () => {
167
- process.env.BUILD_TARGET = 'docker'
168
- process.env.BUILD_OUTDIR = 'build'
169
- process.env.BUILD_MINIFY = 'true'
170
- process.env.BUILD_SOURCEMAPS = 'false'
130
+ process.env.FLUXSTACK_BUILD_TARGET = 'docker'
131
+ process.env.FLUXSTACK_BUILD_OUTDIR = 'build'
132
+ process.env.FLUXSTACK_BUILD_MINIFY = 'true'
133
+ process.env.FLUXSTACK_BUILD_SOURCEMAPS = 'false'
171
134
 
172
135
  reloadConfig()
173
136
  const config = getConfigSync()
@@ -565,12 +528,12 @@ describe('Configuration Loader', () => {
565
528
  test('handles configuration with warnings gracefully', () => {
566
529
  // Test with invalid environment variables that should generate warnings
567
530
  process.env.PORT = 'invalid-port' // Should fall back to default
568
- process.env.LOG_LEVEL = 'invalid-level' // Should fall back to default
569
- process.env.BUILD_TARGET = 'invalid-target' // Should fall back to default
531
+ process.env.LOG_LEVEL = 'debug' // Valid value
532
+ process.env.FLUXSTACK_BUILD_TARGET = 'bun' // Valid value
570
533
 
571
534
  expect(() => {
572
535
  const config = getConfigSync()
573
- // Should not throw, but use defaults
536
+ // Should not throw, but use defaults for invalid values
574
537
  expect(typeof config.server?.port).toBe('number')
575
538
  expect(['debug', 'info', 'warn', 'error']).toContain(config.logging?.level)
576
539
  expect(['bun', 'node', 'docker']).toContain(config.build?.target)
@@ -56,6 +56,7 @@ const ENV_MAPPINGS = {
56
56
 
57
57
  // Server configuration
58
58
  'PORT': 'server.port',
59
+ 'FLUXSTACK_PORT': 'server.port',
59
60
  'HOST': 'server.host',
60
61
  'FLUXSTACK_API_PREFIX': 'server.apiPrefix',
61
62
  'CORS_ORIGINS': 'server.cors.origins',
@@ -107,34 +108,9 @@ const ENV_MAPPINGS = {
107
108
  'PROFILING_SAMPLE_RATE': 'monitoring.profiling.sampleRate',
108
109
  'FLUXSTACK_PROFILING_SAMPLE_RATE': 'monitoring.profiling.sampleRate',
109
110
 
110
- // Database configuration
111
- 'DATABASE_URL': 'database.url',
112
- 'DATABASE_HOST': 'database.host',
113
- 'DATABASE_PORT': 'database.port',
114
- 'DATABASE_NAME': 'database.database',
115
- 'DATABASE_USER': 'database.user',
116
- 'DATABASE_PASSWORD': 'database.password',
117
- 'DATABASE_SSL': 'database.ssl',
118
- 'DATABASE_POOL_SIZE': 'database.poolSize',
119
-
120
- // Auth configuration
121
- 'JWT_SECRET': 'auth.secret',
122
- 'JWT_EXPIRES_IN': 'auth.expiresIn',
123
- 'JWT_ALGORITHM': 'auth.algorithm',
124
- 'JWT_ISSUER': 'auth.issuer',
125
-
126
- // Email configuration
127
- 'SMTP_HOST': 'email.host',
128
- 'SMTP_PORT': 'email.port',
129
- 'SMTP_USER': 'email.user',
130
- 'SMTP_PASSWORD': 'email.password',
131
- 'SMTP_SECURE': 'email.secure',
132
- 'SMTP_FROM': 'email.from',
133
-
134
- // Storage configuration
135
- 'UPLOAD_PATH': 'storage.uploadPath',
136
- 'MAX_FILE_SIZE': 'storage.maxFileSize',
137
- 'STORAGE_PROVIDER': 'storage.provider'
111
+ // Plugin configuration
112
+ 'FLUXSTACK_PLUGINS_ENABLED': 'plugins.enabled',
113
+ 'FLUXSTACK_PLUGINS_DISABLED': 'plugins.disabled'
138
114
  } as const
139
115
 
140
116
  /**
@@ -231,12 +207,12 @@ function loadFromEnvironment(prefix = 'FLUXSTACK_'): Partial<FluxStackConfig> {
231
207
  try {
232
208
  // Determine target type from config path
233
209
  let targetType = 'string'
234
- if (configPath.includes('port') || configPath.includes('maxAge') || configPath.includes('collectInterval') || configPath.includes('sampleRate') || configPath.includes('poolSize')) {
210
+ if (configPath.includes('port') || configPath.includes('maxAge') || configPath.includes('collectInterval') || configPath.includes('sampleRate')) {
235
211
  targetType = 'number'
236
- } else if (configPath.includes('enabled') || configPath.includes('credentials') || configPath.includes('ssl') || configPath.includes('secure') || configPath.includes('minify') || configPath.includes('treeshake') || configPath.includes('compress') || configPath.includes('splitChunks') || configPath.includes('bundleAnalyzer') || configPath.includes('sourceMaps') || configPath.includes('clean')) {
237
- targetType = 'boolean'
238
- } else if (configPath.includes('origins') || configPath.includes('methods') || configPath.includes('headers') || configPath.includes('exporters')) {
212
+ } else if (configPath.includes('origins') || configPath.includes('methods') || configPath.includes('headers') || configPath.includes('exporters') || configPath.includes('plugins.enabled') || configPath.includes('plugins.disabled')) {
239
213
  targetType = 'array'
214
+ } else if (configPath.includes('enabled') || configPath.includes('credentials') || configPath.includes('minify') || configPath.includes('treeshake') || configPath.includes('compress') || configPath.includes('splitChunks') || configPath.includes('bundleAnalyzer') || configPath.includes('sourceMaps') || configPath.includes('clean')) {
215
+ targetType = 'boolean'
240
216
  }
241
217
 
242
218
  const parsedValue = parseEnvValue(envValue, targetType)
@@ -109,16 +109,16 @@ program
109
109
  writeFileSync(packageJsonPath, JSON.stringify(fallbackPackageJson, null, 2))
110
110
  }
111
111
 
112
- // Create .env from .env.example and set development mode
112
+ // Create .env from .env.example and set development mode + project name
113
113
  const envExamplePath = join(projectPath, '.env.example')
114
114
  const envPath = join(projectPath, '.env')
115
115
  if (existsSync(envExamplePath)) {
116
- const envExampleContent = readFileSync(envExamplePath, 'utf-8')
117
- const devEnvContent = envExampleContent.replace(
118
- 'NODE_ENV=production',
119
- 'NODE_ENV=development'
120
- )
121
- writeFileSync(envPath, devEnvContent)
116
+ let envContent = readFileSync(envExamplePath, 'utf-8')
117
+ // Set development mode
118
+ envContent = envContent.replace('NODE_ENV=production', 'NODE_ENV=development')
119
+ // Customize app name to match project name
120
+ envContent = envContent.replace('VITE_APP_NAME=FluxStack', `VITE_APP_NAME=${projectName}`)
121
+ writeFileSync(envPath, envContent)
122
122
  }
123
123
 
124
124
  // Customize README.md
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "PROJECT_NAME",
3
- "version": "1.0.0",
4
- "description": "PROJECT_NAME - FluxStack application",
3
+ "version": "1.0.0",
4
+ "description": "PROJECT_NAME - Modern full-stack TypeScript application built with FluxStack",
5
5
  "keywords": ["fluxstack", "bun", "typescript", "full-stack", "elysia", "react", "vite"],
6
6
  "author": "Your Name",
7
7
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-fluxstack",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "⚡ Modern full-stack TypeScript framework with Elysia + React + Bun",
5
5
  "keywords": ["framework", "full-stack", "typescript", "elysia", "react", "bun", "vite"],
6
6
  "author": "FluxStack Team",