create-fluxstack 1.5.0 → 1.5.1

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 (49) hide show
  1. package/.env.example +1 -8
  2. package/app/client/src/App.tsx +1 -4
  3. package/app/server/index.ts +0 -4
  4. package/app/server/routes/index.ts +1 -5
  5. package/config/index.ts +1 -9
  6. package/core/cli/generators/plugin.ts +34 -324
  7. package/core/cli/generators/template-engine.ts +0 -5
  8. package/core/cli/plugin-discovery.ts +12 -33
  9. package/core/framework/server.ts +0 -10
  10. package/core/plugins/dependency-manager.ts +22 -89
  11. package/core/plugins/index.ts +0 -4
  12. package/core/plugins/manager.ts +2 -3
  13. package/core/plugins/registry.ts +1 -28
  14. package/core/utils/logger/index.ts +0 -4
  15. package/fluxstack.config.ts +114 -253
  16. package/package.json +117 -117
  17. package/CRYPTO-AUTH-MIDDLEWARE-GUIDE.md +0 -475
  18. package/CRYPTO-AUTH-MIDDLEWARES.md +0 -473
  19. package/CRYPTO-AUTH-USAGE.md +0 -491
  20. package/EXEMPLO-ROTA-PROTEGIDA.md +0 -347
  21. package/QUICK-START-CRYPTO-AUTH.md +0 -221
  22. package/app/client/src/pages/CryptoAuthPage.tsx +0 -394
  23. package/app/server/routes/crypto-auth-demo.routes.ts +0 -167
  24. package/app/server/routes/example-with-crypto-auth.routes.ts +0 -235
  25. package/app/server/routes/exemplo-posts.routes.ts +0 -161
  26. package/core/plugins/module-resolver.ts +0 -216
  27. package/plugins/crypto-auth/README.md +0 -788
  28. package/plugins/crypto-auth/ai-context.md +0 -1282
  29. package/plugins/crypto-auth/cli/make-protected-route.command.ts +0 -383
  30. package/plugins/crypto-auth/client/CryptoAuthClient.ts +0 -302
  31. package/plugins/crypto-auth/client/components/AuthProvider.tsx +0 -131
  32. package/plugins/crypto-auth/client/components/LoginButton.tsx +0 -138
  33. package/plugins/crypto-auth/client/components/ProtectedRoute.tsx +0 -89
  34. package/plugins/crypto-auth/client/components/index.ts +0 -12
  35. package/plugins/crypto-auth/client/index.ts +0 -12
  36. package/plugins/crypto-auth/config/index.ts +0 -34
  37. package/plugins/crypto-auth/index.ts +0 -162
  38. package/plugins/crypto-auth/package.json +0 -66
  39. package/plugins/crypto-auth/server/AuthMiddleware.ts +0 -181
  40. package/plugins/crypto-auth/server/CryptoAuthService.ts +0 -186
  41. package/plugins/crypto-auth/server/index.ts +0 -22
  42. package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +0 -65
  43. package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +0 -26
  44. package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +0 -76
  45. package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +0 -45
  46. package/plugins/crypto-auth/server/middlewares/helpers.ts +0 -140
  47. package/plugins/crypto-auth/server/middlewares/index.ts +0 -22
  48. package/plugins/crypto-auth/server/middlewares.ts +0 -19
  49. package/test-crypto-auth.ts +0 -101
@@ -10,14 +10,14 @@ export class CliPluginDiscovery {
10
10
  async discoverAndRegisterCommands(): Promise<void> {
11
11
  // 1. Load built-in plugins with CLI commands
12
12
  await this.loadBuiltInPlugins()
13
-
13
+
14
14
  // 2. Load local plugins from project
15
15
  await this.loadLocalPlugins()
16
16
  }
17
17
 
18
18
  private async loadBuiltInPlugins(): Promise<void> {
19
19
  const builtInPluginsDir = join(__dirname, '../plugins/built-in')
20
-
20
+
21
21
  if (!existsSync(builtInPluginsDir)) {
22
22
  return
23
23
  }
@@ -33,7 +33,7 @@ export class CliPluginDiscovery {
33
33
  const pluginPath = join(builtInPluginsDir, pluginName, 'index.ts')
34
34
  if (existsSync(pluginPath)) {
35
35
  const pluginModule = await import(pluginPath)
36
-
36
+
37
37
  if (pluginModule.commands) {
38
38
  for (const command of pluginModule.commands) {
39
39
  cliRegistry.register(command)
@@ -57,7 +57,7 @@ export class CliPluginDiscovery {
57
57
 
58
58
  private async loadLocalPlugins(): Promise<void> {
59
59
  const localPluginsDir = join(process.cwd(), 'plugins')
60
-
60
+
61
61
  if (!existsSync(localPluginsDir)) {
62
62
  return
63
63
  }
@@ -65,18 +65,17 @@ export class CliPluginDiscovery {
65
65
  try {
66
66
  const fs = await import('fs')
67
67
  const entries = fs.readdirSync(localPluginsDir, { withFileTypes: true })
68
-
68
+
69
69
  for (const entry of entries) {
70
- // Buscar arquivos .ts/.js diretamente
71
70
  if (entry.isFile() && (entry.name.endsWith('.ts') || entry.name.endsWith('.js'))) {
72
71
  const pluginPath = join(localPluginsDir, entry.name)
73
-
72
+
74
73
  try {
75
74
  const pluginModule = await import(pluginPath)
76
75
  const plugin = pluginModule.default || Object.values(pluginModule).find(
77
76
  (exp: any) => exp && typeof exp === 'object' && exp.name && exp.commands
78
77
  ) as Plugin
79
-
78
+
80
79
  if (plugin && plugin.commands) {
81
80
  this.registerPluginCommands(plugin)
82
81
  }
@@ -84,26 +83,6 @@ export class CliPluginDiscovery {
84
83
  logger.debug(`Failed to load local plugin ${entry.name}:`, error)
85
84
  }
86
85
  }
87
-
88
- // ✅ Buscar em subdiretórios (plugins/nome-plugin/index.ts)
89
- if (entry.isDirectory()) {
90
- const pluginIndexPath = join(localPluginsDir, entry.name, 'index.ts')
91
-
92
- if (existsSync(pluginIndexPath)) {
93
- try {
94
- const pluginModule = await import(pluginIndexPath)
95
- const plugin = pluginModule.default || Object.values(pluginModule).find(
96
- (exp: any) => exp && typeof exp === 'object' && exp.name && exp.commands
97
- ) as Plugin
98
-
99
- if (plugin && plugin.commands) {
100
- this.registerPluginCommands(plugin)
101
- }
102
- } catch (error) {
103
- logger.debug(`Failed to load local plugin ${entry.name}:`, error)
104
- }
105
- }
106
- }
107
86
  }
108
87
  } catch (error) {
109
88
  logger.debug('Failed to scan local plugins:', error)
@@ -124,9 +103,9 @@ export class CliPluginDiscovery {
124
103
  category: command.category || `Plugin: ${plugin.name}`,
125
104
  aliases: command.aliases?.map(alias => `${plugin.name}:${alias}`)
126
105
  }
127
-
106
+
128
107
  cliRegistry.register(prefixedCommand)
129
-
108
+
130
109
  // Also register without prefix if no conflict exists
131
110
  if (!cliRegistry.has(command.name)) {
132
111
  cliRegistry.register({
@@ -135,10 +114,10 @@ export class CliPluginDiscovery {
135
114
  })
136
115
  }
137
116
  }
138
-
117
+
139
118
  this.loadedPlugins.add(plugin.name)
140
119
  logger.debug(`Registered ${plugin.commands.length} CLI commands from plugin: ${plugin.name}`)
141
-
120
+
142
121
  } catch (error) {
143
122
  logger.error(`Failed to register CLI commands for plugin ${plugin.name}:`, error)
144
123
  }
@@ -149,4 +128,4 @@ export class CliPluginDiscovery {
149
128
  }
150
129
  }
151
130
 
152
- export const pluginDiscovery = new CliPluginDiscovery()
131
+ export const pluginDiscovery = new CliPluginDiscovery()
@@ -469,16 +469,6 @@ export class FluxStackFramework {
469
469
  }
470
470
  }
471
471
 
472
- // Mount plugin routes if they have a plugin property
473
- for (const pluginName of loadOrder) {
474
- const plugin = this.pluginRegistry.get(pluginName)!
475
-
476
- if ((plugin as any).plugin) {
477
- this.app.use((plugin as any).plugin)
478
- logger.debug(`Plugin '${pluginName}' routes mounted`)
479
- }
480
- }
481
-
482
472
  // Call onServerStart hooks
483
473
  for (const pluginName of loadOrder) {
484
474
  const plugin = this.pluginRegistry.get(pluginName)!
@@ -136,8 +136,6 @@ export class PluginDependencyManager {
136
136
 
137
137
  /**
138
138
  * Instalar dependências de plugins
139
- * NOVA ESTRATÉGIA: Instala no node_modules local do plugin primeiro,
140
- * com fallback para o projeto principal
141
139
  */
142
140
  async installPluginDependencies(resolutions: DependencyResolution[]): Promise<void> {
143
141
  if (!this.config.autoInstall) {
@@ -145,109 +143,44 @@ export class PluginDependencyManager {
145
143
  return
146
144
  }
147
145
 
148
- // Instalar dependências para cada plugin individualmente
149
- for (const resolution of resolutions) {
150
- if (resolution.dependencies.length === 0) continue
151
-
152
- const pluginPath = this.findPluginDirectory(resolution.plugin)
153
- if (!pluginPath) {
154
- this.logger?.warn(`Não foi possível encontrar diretório do plugin '${resolution.plugin}'`)
155
- continue
156
- }
157
-
158
- this.logger?.debug(`📦 Instalando dependências localmente para plugin '${resolution.plugin}'`, {
159
- plugin: resolution.plugin,
160
- path: pluginPath,
161
- dependencies: resolution.dependencies.length
162
- })
163
-
164
- try {
165
- // Instalar APENAS no node_modules local do plugin
166
- await this.installPluginDependenciesLocally(pluginPath, resolution.dependencies)
146
+ const toInstall: PluginDependency[] = []
147
+ const conflicts: DependencyConflict[] = []
167
148
 
168
- this.logger?.debug(`✅ Dependências do plugin '${resolution.plugin}' instaladas localmente`)
169
- } catch (error) {
170
- this.logger?.error(`❌ Erro ao instalar dependências do plugin '${resolution.plugin}'`, { error })
171
- // Continuar com outros plugins
172
- }
149
+ // Coletar todas as dependências e conflitos
150
+ for (const resolution of resolutions) {
151
+ toInstall.push(...resolution.dependencies)
152
+ conflicts.push(...resolution.conflicts)
173
153
  }
174
- }
175
-
176
- /**
177
- * Instalar dependências no diretório local do plugin
178
- */
179
- private async installPluginDependenciesLocally(pluginPath: string, dependencies: PluginDependency[]): Promise<void> {
180
- if (dependencies.length === 0) return
181
-
182
- const regularDeps = dependencies.filter(d => d.type === 'dependency')
183
- const peerDeps = dependencies.filter(d => d.type === 'peerDependency' && !d.optional)
184
-
185
- const allDeps = [...regularDeps, ...peerDeps]
186
- if (allDeps.length === 0) return
187
154
 
188
- // Verificar quais dependências já estão instaladas localmente
189
- const toInstall = allDeps.filter(dep => {
190
- const depPath = join(pluginPath, 'node_modules', dep.name, 'package.json')
191
- if (!existsSync(depPath)) {
192
- return true // Precisa instalar
193
- }
194
-
195
- try {
196
- const installedPkg = JSON.parse(readFileSync(depPath, 'utf-8'))
197
- const installedVersion = installedPkg.version
198
-
199
- // Verificar se a versão é compatível
200
- if (!this.isVersionCompatible(installedVersion, dep.version)) {
201
- this.logger?.debug(`📦 Dependência '${dep.name}' está desatualizada (${installedVersion} → ${dep.version})`)
202
- return true // Precisa atualizar
203
- }
155
+ // Resolver conflitos primeiro
156
+ if (conflicts.length > 0) {
157
+ await this.resolveConflicts(conflicts)
158
+ }
204
159
 
205
- return false // está instalado corretamente
206
- } catch (error) {
207
- return true // Erro ao ler, melhor reinstalar
208
- }
160
+ // Filtrar dependências que estão instaladas
161
+ const needsInstallation = toInstall.filter(dep => {
162
+ const installed = this.installedDependencies.get(dep.name)
163
+ return !installed || !this.isVersionCompatible(installed, dep.version)
209
164
  })
210
165
 
211
- if (toInstall.length === 0) {
212
- this.logger?.debug(`✅ Todas as dependências do plugin já estão instaladas`)
166
+ if (needsInstallation.length === 0) {
167
+ this.logger?.debug('Todas as dependências de plugins já estão instaladas')
213
168
  return
214
169
  }
215
170
 
216
- const packages = toInstall.map(d => `${d.name}@${d.version}`).join(' ')
217
- const command = this.getInstallCommand(packages, false)
218
-
219
- this.logger?.debug(`🔧 Instalando ${toInstall.length} dependência(s): ${command}`, { cwd: pluginPath })
171
+ this.logger?.debug(`Instalando ${needsInstallation.length} dependências de plugins`, {
172
+ dependencies: needsInstallation.map(d => `${d.name}@${d.version}`)
173
+ })
220
174
 
221
175
  try {
222
- execSync(command, {
223
- cwd: pluginPath,
224
- stdio: 'inherit'
225
- })
226
- this.logger?.debug(`✅ Pacotes instalados localmente em ${pluginPath}`)
176
+ await this.installDependencies(needsInstallation)
177
+ this.logger?.debug('Dependências de plugins instaladas com sucesso')
227
178
  } catch (error) {
228
- this.logger?.error(`❌ Falha ao instalar dependências localmente`, { error, pluginPath })
179
+ this.logger?.error('Erro ao instalar dependências de plugins', { error })
229
180
  throw error
230
181
  }
231
182
  }
232
183
 
233
- /**
234
- * Encontrar diretório de um plugin pelo nome
235
- */
236
- private findPluginDirectory(pluginName: string): string | null {
237
- const possiblePaths = [
238
- `plugins/${pluginName}`,
239
- `core/plugins/built-in/${pluginName}`
240
- ]
241
-
242
- for (const path of possiblePaths) {
243
- if (existsSync(path)) {
244
- return resolve(path)
245
- }
246
- }
247
-
248
- return null
249
- }
250
-
251
184
  /**
252
185
  * Detectar conflitos de versão
253
186
  */
@@ -54,10 +54,6 @@ export {
54
54
  } from './manager'
55
55
  export type { PluginManagerConfig } from './manager'
56
56
 
57
- // Module resolver for plugins
58
- export { PluginModuleResolver } from './module-resolver'
59
- export type { ModuleResolverConfig } from './module-resolver'
60
-
61
57
  // Plugin executor
62
58
  export {
63
59
  PluginExecutor,
@@ -19,7 +19,7 @@ import type {
19
19
 
20
20
  type Plugin = FluxStack.Plugin
21
21
  import type { FluxStackConfig } from "../config/schema"
22
- import type { Logger } from "../utils/logger"
22
+ import type { Logger } from "../utils/logger/index"
23
23
  import { PluginRegistry } from "./registry"
24
24
  import { createPluginUtils } from "./config"
25
25
  import { FluxStackError } from "../utils/errors"
@@ -422,7 +422,6 @@ export class PluginManager extends EventEmitter {
422
422
  // Try to use auto-generated registry for external plugins (if available from build)
423
423
  let externalResults: any[] = []
424
424
  try {
425
- // @ts-expect-error - auto-registry is generated during build, may not exist in dev
426
425
  const autoRegistryModule = await import('./auto-registry')
427
426
  if (autoRegistryModule.discoveredPlugins && autoRegistryModule.registerDiscoveredPlugins) {
428
427
  this.logger.debug('🚀 Using auto-generated external plugins registry')
@@ -433,7 +432,7 @@ export class PluginManager extends EventEmitter {
433
432
  }))
434
433
  }
435
434
  } catch (error) {
436
- this.logger.debug('Auto-generated external plugins registry not found, falling back to discovery', { error: (error as Error).message })
435
+ this.logger.debug('Auto-generated external plugins registry not found, falling back to discovery', { error: error.message })
437
436
 
438
437
  // Fallback to runtime discovery for external plugins
439
438
  this.logger.debug('Discovering external plugins in directory: plugins')
@@ -2,7 +2,7 @@ import type { FluxStack, PluginManifest, PluginLoadResult, PluginDiscoveryOption
2
2
 
3
3
  type FluxStackPlugin = FluxStack.Plugin
4
4
  import type { FluxStackConfig } from "../config/schema"
5
- import type { Logger } from "../utils/logger"
5
+ import type { Logger } from "../utils/logger/index"
6
6
  import { FluxStackError } from "../utils/errors"
7
7
  import { PluginDependencyManager } from "./dependency-manager"
8
8
  import { readdir, readFile } from "fs/promises"
@@ -262,33 +262,6 @@ export class PluginRegistry {
262
262
  if (existsSync(manifestPath)) {
263
263
  const manifestContent = await readFile(manifestPath, 'utf-8')
264
264
  manifest = JSON.parse(manifestContent)
265
- } else {
266
- // Try package.json for npm plugins
267
- const packagePath = join(pluginPath, 'package.json')
268
- if (existsSync(packagePath)) {
269
- try {
270
- const packageContent = await readFile(packagePath, 'utf-8')
271
- const packageJson = JSON.parse(packageContent)
272
-
273
- if (packageJson.fluxstack) {
274
- manifest = {
275
- name: packageJson.name,
276
- version: packageJson.version,
277
- description: packageJson.description || '',
278
- author: packageJson.author || '',
279
- license: packageJson.license || '',
280
- homepage: packageJson.homepage,
281
- repository: packageJson.repository,
282
- keywords: packageJson.keywords || [],
283
- dependencies: packageJson.dependencies || {},
284
- peerDependencies: packageJson.peerDependencies,
285
- fluxstack: packageJson.fluxstack
286
- }
287
- }
288
- } catch (error) {
289
- this.logger?.warn(`Failed to parse package.json in '${pluginPath}'`, { error })
290
- }
291
- }
292
265
  }
293
266
 
294
267
  // Try to import the plugin
@@ -23,10 +23,6 @@ export { clearColorCache } from './colors'
23
23
  export { clearCallerCache } from './stack-trace'
24
24
  export { clearLoggerCache } from './winston-logger'
25
25
 
26
- // Export Logger type from winston
27
- import type winston from 'winston'
28
- export type Logger = winston.Logger
29
-
30
26
  // Re-export banner utilities for custom banners
31
27
  export { displayStartupBanner, type StartupInfo } from './startup-banner'
32
28