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.
- package/.env.example +1 -8
- package/app/client/src/App.tsx +1 -4
- package/app/server/index.ts +0 -4
- package/app/server/routes/index.ts +1 -5
- package/config/index.ts +1 -9
- package/core/cli/generators/plugin.ts +34 -324
- package/core/cli/generators/template-engine.ts +0 -5
- package/core/cli/plugin-discovery.ts +12 -33
- package/core/framework/server.ts +0 -10
- package/core/plugins/dependency-manager.ts +22 -89
- package/core/plugins/index.ts +0 -4
- package/core/plugins/manager.ts +2 -3
- package/core/plugins/registry.ts +1 -28
- package/core/utils/logger/index.ts +0 -4
- package/fluxstack.config.ts +114 -253
- package/package.json +117 -117
- package/CRYPTO-AUTH-MIDDLEWARE-GUIDE.md +0 -475
- package/CRYPTO-AUTH-MIDDLEWARES.md +0 -473
- package/CRYPTO-AUTH-USAGE.md +0 -491
- package/EXEMPLO-ROTA-PROTEGIDA.md +0 -347
- package/QUICK-START-CRYPTO-AUTH.md +0 -221
- package/app/client/src/pages/CryptoAuthPage.tsx +0 -394
- package/app/server/routes/crypto-auth-demo.routes.ts +0 -167
- package/app/server/routes/example-with-crypto-auth.routes.ts +0 -235
- package/app/server/routes/exemplo-posts.routes.ts +0 -161
- package/core/plugins/module-resolver.ts +0 -216
- 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 -162
- package/plugins/crypto-auth/package.json +0 -66
- package/plugins/crypto-auth/server/AuthMiddleware.ts +0 -181
- package/plugins/crypto-auth/server/CryptoAuthService.ts +0 -186
- package/plugins/crypto-auth/server/index.ts +0 -22
- package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +0 -65
- package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +0 -26
- package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +0 -76
- package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +0 -45
- package/plugins/crypto-auth/server/middlewares/helpers.ts +0 -140
- package/plugins/crypto-auth/server/middlewares/index.ts +0 -22
- package/plugins/crypto-auth/server/middlewares.ts +0 -19
- 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()
|
package/core/framework/server.ts
CHANGED
|
@@ -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
|
-
|
|
149
|
-
|
|
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
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
160
|
+
// Filtrar dependências que já 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 (
|
|
212
|
-
this.logger?.debug(
|
|
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
|
-
|
|
217
|
-
|
|
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
|
-
|
|
223
|
-
|
|
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(
|
|
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
|
*/
|
package/core/plugins/index.ts
CHANGED
|
@@ -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,
|
package/core/plugins/manager.ts
CHANGED
|
@@ -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:
|
|
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')
|
package/core/plugins/registry.ts
CHANGED
|
@@ -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
|
|