create-fluxstack 1.0.13 → 1.0.14
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 +29 -29
- package/app/client/README.md +69 -69
- package/app/client/index.html +14 -13
- package/app/client/src/App.tsx +157 -524
- package/app/client/src/components/ErrorBoundary.tsx +107 -0
- package/app/client/src/components/ErrorDisplay.css +365 -0
- package/app/client/src/components/ErrorDisplay.tsx +258 -0
- package/app/client/src/components/FluxStackConfig.tsx +1321 -0
- package/app/client/src/components/HybridLiveCounter.tsx +140 -0
- package/app/client/src/components/LiveClock.tsx +286 -0
- package/app/client/src/components/MainLayout.tsx +390 -0
- package/app/client/src/components/SidebarNavigation.tsx +391 -0
- package/app/client/src/components/StateDemo.tsx +178 -0
- package/app/client/src/components/SystemMonitor.tsx +1038 -0
- package/app/client/src/components/Teste.tsx +104 -0
- package/app/client/src/components/UserProfile.tsx +809 -0
- package/app/client/src/hooks/useAuth.ts +39 -0
- package/app/client/src/hooks/useNotifications.ts +56 -0
- package/app/client/src/lib/eden-api.ts +189 -53
- package/app/client/src/lib/errors.ts +340 -0
- package/app/client/src/lib/hooks/useErrorHandler.ts +258 -0
- package/app/client/src/lib/index.ts +45 -0
- package/app/client/src/main.tsx +3 -2
- package/app/client/src/pages/ApiDocs.tsx +182 -0
- package/app/client/src/pages/Demo.tsx +174 -0
- package/app/client/src/pages/HybridLive.tsx +263 -0
- package/app/client/src/pages/Overview.tsx +155 -0
- package/app/client/src/store/README.md +43 -0
- package/app/client/src/store/index.ts +16 -0
- package/app/client/src/store/slices/uiSlice.ts +151 -0
- package/app/client/src/store/slices/userSlice.ts +161 -0
- package/app/client/src/test/README.md +257 -0
- package/app/client/src/test/setup.ts +70 -0
- package/app/client/src/test/types.ts +12 -0
- package/app/client/src/vite-env.d.ts +1 -1
- package/app/client/tsconfig.app.json +44 -43
- package/app/client/tsconfig.json +7 -7
- package/app/client/tsconfig.node.json +25 -25
- package/app/client/zustand-setup.md +65 -0
- package/app/server/controllers/users.controller.ts +68 -68
- package/app/server/index.ts +9 -1
- package/app/server/live/CounterComponent.ts +191 -0
- package/app/server/live/FluxStackConfig.ts +529 -0
- package/app/server/live/LiveClockComponent.ts +214 -0
- package/app/server/live/SidebarNavigation.ts +156 -0
- package/app/server/live/SystemMonitor.ts +594 -0
- package/app/server/live/SystemMonitorIntegration.ts +151 -0
- package/app/server/live/TesteComponent.ts +87 -0
- package/app/server/live/UserProfileComponent.ts +135 -0
- package/app/server/live/register-components.ts +28 -0
- package/app/server/middleware/auth.ts +136 -0
- package/app/server/middleware/errorHandling.ts +250 -0
- package/app/server/middleware/index.ts +10 -0
- package/app/server/middleware/rateLimit.ts +193 -0
- package/app/server/middleware/requestLogging.ts +215 -0
- package/app/server/middleware/validation.ts +270 -0
- package/app/server/routes/index.ts +14 -2
- package/app/server/routes/upload.ts +92 -0
- package/app/server/routes/users.routes.ts +2 -9
- package/app/server/services/NotificationService.ts +302 -0
- package/app/server/services/UserService.ts +222 -0
- package/app/server/services/index.ts +46 -0
- package/core/cli/commands/plugin-deps.ts +263 -0
- package/core/cli/generators/README.md +339 -0
- package/core/cli/generators/component.ts +770 -0
- package/core/cli/generators/controller.ts +299 -0
- package/core/cli/generators/index.ts +144 -0
- package/core/cli/generators/interactive.ts +228 -0
- package/core/cli/generators/prompts.ts +83 -0
- package/core/cli/generators/route.ts +513 -0
- package/core/cli/generators/service.ts +465 -0
- package/core/cli/generators/template-engine.ts +154 -0
- package/core/cli/generators/types.ts +71 -0
- package/core/cli/generators/utils.ts +192 -0
- package/core/cli/index.ts +69 -0
- package/core/cli/plugin-discovery.ts +16 -85
- package/core/client/fluxstack.ts +17 -0
- package/core/client/hooks/index.ts +7 -0
- package/core/client/hooks/state-validator.ts +130 -0
- package/core/client/hooks/useAuth.ts +49 -0
- package/core/client/hooks/useChunkedUpload.ts +258 -0
- package/core/client/hooks/useHybridLiveComponent.ts +967 -0
- package/core/client/hooks/useWebSocket.ts +373 -0
- package/core/client/index.ts +47 -0
- package/core/client/state/createStore.ts +193 -0
- package/core/client/state/index.ts +15 -0
- package/core/config/env-dynamic.ts +1 -1
- package/core/config/env.ts +2 -1
- package/core/config/runtime-config.ts +3 -3
- package/core/config/schema.ts +84 -49
- package/core/framework/server.ts +30 -0
- package/core/index.ts +25 -0
- package/core/live/ComponentRegistry.ts +399 -0
- package/core/live/types.ts +164 -0
- package/core/plugins/built-in/live-components/commands/create-live-component.ts +1201 -0
- package/core/plugins/built-in/live-components/index.ts +27 -0
- package/core/plugins/built-in/logger/index.ts +1 -1
- package/core/plugins/built-in/monitoring/index.ts +1 -1
- package/core/plugins/built-in/static/index.ts +1 -1
- package/core/plugins/built-in/swagger/index.ts +1 -1
- package/core/plugins/built-in/vite/index.ts +1 -1
- package/core/plugins/dependency-manager.ts +384 -0
- package/core/plugins/index.ts +5 -1
- package/core/plugins/manager.ts +7 -3
- package/core/plugins/registry.ts +88 -10
- package/core/plugins/types.ts +11 -11
- package/core/server/framework.ts +43 -0
- package/core/server/index.ts +11 -1
- package/core/server/live/ComponentRegistry.ts +1017 -0
- package/core/server/live/FileUploadManager.ts +272 -0
- package/core/server/live/LiveComponentPerformanceMonitor.ts +930 -0
- package/core/server/live/SingleConnectionManager.ts +0 -0
- package/core/server/live/StateSignature.ts +644 -0
- package/core/server/live/WebSocketConnectionManager.ts +688 -0
- package/core/server/live/websocket-plugin.ts +435 -0
- package/core/server/middleware/errorHandling.ts +141 -0
- package/core/server/middleware/index.ts +16 -0
- package/core/server/plugins/static-files-plugin.ts +232 -0
- package/core/server/services/BaseService.ts +95 -0
- package/core/server/services/ServiceContainer.ts +144 -0
- package/core/server/services/index.ts +9 -0
- package/core/templates/create-project.ts +46 -2
- package/core/testing/index.ts +10 -0
- package/core/testing/setup.ts +74 -0
- package/core/types/build.ts +38 -14
- package/core/types/types.ts +319 -0
- package/core/utils/env-runtime.ts +7 -0
- package/core/utils/errors/handlers.ts +264 -39
- package/core/utils/errors/index.ts +528 -18
- package/core/utils/errors/middleware.ts +114 -0
- package/core/utils/logger/formatters.ts +222 -0
- package/core/utils/logger/index.ts +167 -48
- package/core/utils/logger/middleware.ts +253 -0
- package/core/utils/logger/performance.ts +384 -0
- package/core/utils/logger/transports.ts +365 -0
- package/create-fluxstack.ts +296 -296
- package/fluxstack.config.ts +17 -1
- package/package-template.json +66 -66
- package/package.json +31 -6
- package/public/README.md +16 -0
- package/vite.config.ts +29 -14
- package/.claude/settings.local.json +0 -74
- package/.github/workflows/ci-build-tests.yml +0 -480
- package/.github/workflows/dependency-management.yml +0 -324
- package/.github/workflows/release-validation.yml +0 -355
- package/.kiro/specs/fluxstack-architecture-optimization/design.md +0 -700
- package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +0 -127
- package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +0 -330
- package/CLAUDE.md +0 -200
- package/Dockerfile +0 -58
- package/Dockerfile.backend +0 -52
- package/Dockerfile.frontend +0 -54
- package/README-Docker.md +0 -85
- package/ai-context/00-QUICK-START.md +0 -86
- package/ai-context/README.md +0 -88
- package/ai-context/development/eden-treaty-guide.md +0 -362
- package/ai-context/development/patterns.md +0 -382
- package/ai-context/development/plugins-guide.md +0 -572
- package/ai-context/examples/crud-complete.md +0 -626
- package/ai-context/project/architecture.md +0 -399
- package/ai-context/project/overview.md +0 -213
- package/ai-context/recent-changes/eden-treaty-refactor.md +0 -281
- package/ai-context/recent-changes/type-inference-fix.md +0 -223
- package/ai-context/reference/environment-vars.md +0 -384
- package/ai-context/reference/troubleshooting.md +0 -407
- package/app/client/src/components/TestPage.tsx +0 -453
- package/bun.lock +0 -1063
- package/bunfig.toml +0 -16
- package/core/__tests__/integration.test.ts +0 -227
- package/core/build/index.ts +0 -186
- package/core/config/__tests__/config-loader.test.ts +0 -554
- package/core/config/__tests__/config-merger.test.ts +0 -657
- package/core/config/__tests__/env-converter.test.ts +0 -372
- package/core/config/__tests__/env-processor.test.ts +0 -431
- package/core/config/__tests__/env.test.ts +0 -452
- package/core/config/__tests__/integration.test.ts +0 -418
- package/core/config/__tests__/loader.test.ts +0 -331
- package/core/config/__tests__/schema.test.ts +0 -129
- package/core/config/__tests__/validator.test.ts +0 -318
- package/core/framework/__tests__/server.test.ts +0 -233
- package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
- package/core/plugins/__tests__/manager.test.ts +0 -398
- package/core/plugins/__tests__/monitoring.test.ts +0 -401
- package/core/plugins/__tests__/registry.test.ts +0 -335
- package/core/utils/__tests__/errors.test.ts +0 -139
- package/core/utils/__tests__/helpers.test.ts +0 -297
- package/core/utils/__tests__/logger.test.ts +0 -141
- package/create-test-app.ts +0 -156
- package/docker-compose.microservices.yml +0 -75
- package/docker-compose.simple.yml +0 -57
- package/docker-compose.yml +0 -71
- package/eslint.config.js +0 -23
- package/flux-cli.ts +0 -214
- package/nginx-lb.conf +0 -37
- package/publish.sh +0 -63
- package/run-clean.ts +0 -26
- package/run-env-tests.ts +0 -313
- package/tailwind.config.js +0 -34
- package/tests/__mocks__/api.ts +0 -56
- package/tests/fixtures/users.ts +0 -69
- package/tests/integration/api/users.routes.test.ts +0 -221
- package/tests/setup.ts +0 -29
- package/tests/unit/app/client/App-simple.test.tsx +0 -56
- package/tests/unit/app/client/App.test.tsx.skip +0 -237
- package/tests/unit/app/client/eden-api.test.ts +0 -186
- package/tests/unit/app/client/simple.test.tsx +0 -23
- package/tests/unit/app/controllers/users.controller.test.ts +0 -150
- package/tests/unit/core/create-project.test.ts.skip +0 -95
- package/tests/unit/core/framework.test.ts +0 -144
- package/tests/unit/core/plugins/logger.test.ts.skip +0 -268
- package/tests/unit/core/plugins/vite.test.ts.disabled +0 -188
- package/tests/utils/test-helpers.ts +0 -61
- package/vitest.config.ts +0 -50
- package/workspace.json +0 -6
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { FluxStack, PluginContext } from '../../types'
|
|
2
|
+
import { createLiveComponentCommand } from './commands/create-live-component'
|
|
3
|
+
|
|
4
|
+
type Plugin = FluxStack.Plugin
|
|
5
|
+
|
|
6
|
+
// This is the entry point for the live-components built-in plugin.
|
|
7
|
+
export const liveComponentsPlugin: Plugin = {
|
|
8
|
+
name: 'live-components',
|
|
9
|
+
version: '1.0.0',
|
|
10
|
+
description: 'Live Components CLI commands for FluxStack',
|
|
11
|
+
author: 'FluxStack Team',
|
|
12
|
+
priority: 500,
|
|
13
|
+
category: 'development',
|
|
14
|
+
tags: ['live-components', 'cli', 'generator'],
|
|
15
|
+
|
|
16
|
+
setup: async (context: PluginContext) => {
|
|
17
|
+
context.logger.info('Live Components plugin initialized (CLI commands only)')
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
// CLI commands
|
|
21
|
+
commands: [createLiveComponentCommand]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Export commands for backward compatibility
|
|
25
|
+
export const commands = [createLiveComponentCommand]
|
|
26
|
+
|
|
27
|
+
export default liveComponentsPlugin
|
|
@@ -5,7 +5,7 @@ export const loggerPlugin: Plugin = {
|
|
|
5
5
|
version: "1.0.0",
|
|
6
6
|
description: "Enhanced logging plugin for FluxStack with request/response logging",
|
|
7
7
|
author: "FluxStack Team",
|
|
8
|
-
priority:
|
|
8
|
+
priority: 1000, // Logger should run first
|
|
9
9
|
category: "core",
|
|
10
10
|
tags: ["logging", "monitoring"],
|
|
11
11
|
|
|
@@ -66,7 +66,7 @@ export const monitoringPlugin: Plugin = {
|
|
|
66
66
|
version: "1.0.0",
|
|
67
67
|
description: "Performance monitoring plugin with metrics collection and system monitoring",
|
|
68
68
|
author: "FluxStack Team",
|
|
69
|
-
priority:
|
|
69
|
+
priority: 900, // Should run early to capture all metrics
|
|
70
70
|
category: "monitoring",
|
|
71
71
|
tags: ["monitoring", "metrics", "performance", "observability"],
|
|
72
72
|
dependencies: [], // No dependencies
|
|
@@ -7,7 +7,7 @@ export const staticPlugin: Plugin = {
|
|
|
7
7
|
version: "1.0.0",
|
|
8
8
|
description: "Enhanced static file serving plugin for FluxStack with caching and compression",
|
|
9
9
|
author: "FluxStack Team",
|
|
10
|
-
priority:
|
|
10
|
+
priority: 100, // Should run after other plugins
|
|
11
11
|
category: "core",
|
|
12
12
|
tags: ["static", "files", "spa"],
|
|
13
13
|
dependencies: [], // No hard dependencies, but works with vite plugin
|
|
@@ -6,7 +6,7 @@ export const swaggerPlugin: Plugin = {
|
|
|
6
6
|
version: '1.0.0',
|
|
7
7
|
description: 'Enhanced Swagger documentation plugin for FluxStack with customizable options',
|
|
8
8
|
author: 'FluxStack Team',
|
|
9
|
-
priority:
|
|
9
|
+
priority: 500,
|
|
10
10
|
category: 'documentation',
|
|
11
11
|
tags: ['swagger', 'documentation', 'api'],
|
|
12
12
|
dependencies: [], // No dependencies
|
|
@@ -8,7 +8,7 @@ export const vitePlugin: Plugin = {
|
|
|
8
8
|
version: "1.0.0",
|
|
9
9
|
description: "Enhanced Vite integration plugin for FluxStack with improved error handling and monitoring",
|
|
10
10
|
author: "FluxStack Team",
|
|
11
|
-
priority:
|
|
11
|
+
priority: 800, // Should run early to setup proxying
|
|
12
12
|
category: "development",
|
|
13
13
|
tags: ["vite", "development", "hot-reload"],
|
|
14
14
|
dependencies: [], // No dependencies
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gerenciador de Dependências de Plugins
|
|
3
|
+
* Resolve e instala dependências de plugins automaticamente
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
|
7
|
+
import { join, resolve } from 'path'
|
|
8
|
+
import { execSync } from 'child_process'
|
|
9
|
+
import type { Logger } from '../utils/logger'
|
|
10
|
+
|
|
11
|
+
export interface PluginDependency {
|
|
12
|
+
name: string
|
|
13
|
+
version: string
|
|
14
|
+
type: 'dependency' | 'devDependency' | 'peerDependency'
|
|
15
|
+
optional?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface DependencyResolution {
|
|
19
|
+
plugin: string
|
|
20
|
+
dependencies: PluginDependency[]
|
|
21
|
+
conflicts: DependencyConflict[]
|
|
22
|
+
resolved: boolean
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface DependencyConflict {
|
|
26
|
+
package: string
|
|
27
|
+
versions: Array<{
|
|
28
|
+
plugin: string
|
|
29
|
+
version: string
|
|
30
|
+
}>
|
|
31
|
+
resolution?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface DependencyManagerConfig {
|
|
35
|
+
logger?: Logger
|
|
36
|
+
autoInstall?: boolean
|
|
37
|
+
packageManager?: 'npm' | 'yarn' | 'pnpm' | 'bun'
|
|
38
|
+
workspaceRoot?: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class PluginDependencyManager {
|
|
42
|
+
private logger?: Logger
|
|
43
|
+
private config: DependencyManagerConfig
|
|
44
|
+
private installedDependencies: Map<string, string> = new Map()
|
|
45
|
+
private pluginDependencies: Map<string, PluginDependency[]> = new Map()
|
|
46
|
+
|
|
47
|
+
constructor(config: DependencyManagerConfig = {}) {
|
|
48
|
+
this.config = {
|
|
49
|
+
autoInstall: true,
|
|
50
|
+
packageManager: 'bun',
|
|
51
|
+
workspaceRoot: process.cwd(),
|
|
52
|
+
...config
|
|
53
|
+
}
|
|
54
|
+
this.logger = config.logger
|
|
55
|
+
|
|
56
|
+
this.loadInstalledDependencies()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Registrar dependências de um plugin
|
|
61
|
+
*/
|
|
62
|
+
registerPluginDependencies(pluginName: string, dependencies: PluginDependency[]): void {
|
|
63
|
+
this.pluginDependencies.set(pluginName, dependencies)
|
|
64
|
+
this.logger?.debug(`Dependências registradas para plugin '${pluginName}'`, {
|
|
65
|
+
plugin: pluginName,
|
|
66
|
+
dependencies: dependencies.length
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Resolver dependências de um plugin a partir do package.json
|
|
72
|
+
*/
|
|
73
|
+
async resolvePluginDependencies(pluginPath: string): Promise<DependencyResolution> {
|
|
74
|
+
const pluginName = this.getPluginNameFromPath(pluginPath)
|
|
75
|
+
const packageJsonPath = join(pluginPath, 'package.json')
|
|
76
|
+
|
|
77
|
+
if (!existsSync(packageJsonPath)) {
|
|
78
|
+
return {
|
|
79
|
+
plugin: pluginName,
|
|
80
|
+
dependencies: [],
|
|
81
|
+
conflicts: [],
|
|
82
|
+
resolved: true
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'))
|
|
88
|
+
const dependencies: PluginDependency[] = []
|
|
89
|
+
|
|
90
|
+
// Processar dependencies
|
|
91
|
+
if (packageJson.dependencies) {
|
|
92
|
+
for (const [name, version] of Object.entries(packageJson.dependencies)) {
|
|
93
|
+
dependencies.push({
|
|
94
|
+
name,
|
|
95
|
+
version: version as string,
|
|
96
|
+
type: 'dependency'
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Processar peerDependencies
|
|
102
|
+
if (packageJson.peerDependencies) {
|
|
103
|
+
for (const [name, version] of Object.entries(packageJson.peerDependencies)) {
|
|
104
|
+
const isOptional = packageJson.peerDependenciesMeta?.[name]?.optional || false
|
|
105
|
+
dependencies.push({
|
|
106
|
+
name,
|
|
107
|
+
version: version as string,
|
|
108
|
+
type: 'peerDependency',
|
|
109
|
+
optional: isOptional
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Registrar dependências
|
|
115
|
+
this.registerPluginDependencies(pluginName, dependencies)
|
|
116
|
+
|
|
117
|
+
// Detectar conflitos
|
|
118
|
+
const conflicts = this.detectConflicts(pluginName, dependencies)
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
plugin: pluginName,
|
|
122
|
+
dependencies,
|
|
123
|
+
conflicts,
|
|
124
|
+
resolved: conflicts.length === 0
|
|
125
|
+
}
|
|
126
|
+
} catch (error) {
|
|
127
|
+
this.logger?.error(`Erro ao resolver dependências do plugin '${pluginName}'`, { error })
|
|
128
|
+
return {
|
|
129
|
+
plugin: pluginName,
|
|
130
|
+
dependencies: [],
|
|
131
|
+
conflicts: [],
|
|
132
|
+
resolved: false
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Instalar dependências de plugins
|
|
139
|
+
*/
|
|
140
|
+
async installPluginDependencies(resolutions: DependencyResolution[]): Promise<void> {
|
|
141
|
+
if (!this.config.autoInstall) {
|
|
142
|
+
this.logger?.info('Auto-instalação desabilitada, pulando instalação de dependências')
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const toInstall: PluginDependency[] = []
|
|
147
|
+
const conflicts: DependencyConflict[] = []
|
|
148
|
+
|
|
149
|
+
// Coletar todas as dependências e conflitos
|
|
150
|
+
for (const resolution of resolutions) {
|
|
151
|
+
toInstall.push(...resolution.dependencies)
|
|
152
|
+
conflicts.push(...resolution.conflicts)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Resolver conflitos primeiro
|
|
156
|
+
if (conflicts.length > 0) {
|
|
157
|
+
await this.resolveConflicts(conflicts)
|
|
158
|
+
}
|
|
159
|
+
|
|
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)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
if (needsInstallation.length === 0) {
|
|
167
|
+
this.logger?.info('Todas as dependências de plugins já estão instaladas')
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
this.logger?.info(`Instalando ${needsInstallation.length} dependências de plugins`, {
|
|
172
|
+
dependencies: needsInstallation.map(d => `${d.name}@${d.version}`)
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
await this.installDependencies(needsInstallation)
|
|
177
|
+
this.logger?.info('Dependências de plugins instaladas com sucesso')
|
|
178
|
+
} catch (error) {
|
|
179
|
+
this.logger?.error('Erro ao instalar dependências de plugins', { error })
|
|
180
|
+
throw error
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Detectar conflitos de versão
|
|
186
|
+
*/
|
|
187
|
+
private detectConflicts(pluginName: string, dependencies: PluginDependency[]): DependencyConflict[] {
|
|
188
|
+
const conflicts: DependencyConflict[] = []
|
|
189
|
+
|
|
190
|
+
for (const dep of dependencies) {
|
|
191
|
+
const existingVersions: Array<{ plugin: string; version: string }> = []
|
|
192
|
+
|
|
193
|
+
// Verificar se outros plugins já declararam esta dependência
|
|
194
|
+
for (const [otherPlugin, otherDeps] of this.pluginDependencies.entries()) {
|
|
195
|
+
if (otherPlugin === pluginName) continue
|
|
196
|
+
|
|
197
|
+
const conflictingDep = otherDeps.find(d => d.name === dep.name)
|
|
198
|
+
if (conflictingDep && !this.isVersionCompatible(conflictingDep.version, dep.version)) {
|
|
199
|
+
existingVersions.push({
|
|
200
|
+
plugin: otherPlugin,
|
|
201
|
+
version: conflictingDep.version
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (existingVersions.length > 0) {
|
|
207
|
+
existingVersions.push({
|
|
208
|
+
plugin: pluginName,
|
|
209
|
+
version: dep.version
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
conflicts.push({
|
|
213
|
+
package: dep.name,
|
|
214
|
+
versions: existingVersions
|
|
215
|
+
})
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return conflicts
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Resolver conflitos de dependências
|
|
224
|
+
*/
|
|
225
|
+
private async resolveConflicts(conflicts: DependencyConflict[]): Promise<void> {
|
|
226
|
+
this.logger?.warn(`Detectados ${conflicts.length} conflitos de dependências`, {
|
|
227
|
+
conflicts: conflicts.map(c => ({
|
|
228
|
+
package: c.package,
|
|
229
|
+
versions: c.versions.length
|
|
230
|
+
}))
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
for (const conflict of conflicts) {
|
|
234
|
+
// Estratégia simples: usar a versão mais alta
|
|
235
|
+
const sortedVersions = conflict.versions.sort((a, b) => {
|
|
236
|
+
return this.compareVersions(b.version, a.version)
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
const resolution = sortedVersions[0].version
|
|
240
|
+
conflict.resolution = resolution
|
|
241
|
+
|
|
242
|
+
this.logger?.info(`Conflito resolvido para '${conflict.package}': usando versão ${resolution}`, {
|
|
243
|
+
package: conflict.package,
|
|
244
|
+
resolution,
|
|
245
|
+
conflictingVersions: conflict.versions
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Instalar dependências usando o package manager configurado
|
|
252
|
+
*/
|
|
253
|
+
private async installDependencies(dependencies: PluginDependency[]): Promise<void> {
|
|
254
|
+
const regularDeps = dependencies.filter(d => d.type === 'dependency')
|
|
255
|
+
const peerDeps = dependencies.filter(d => d.type === 'peerDependency' && !d.optional)
|
|
256
|
+
|
|
257
|
+
if (regularDeps.length > 0) {
|
|
258
|
+
const packages = regularDeps.map(d => `${d.name}@${d.version}`).join(' ')
|
|
259
|
+
const command = this.getInstallCommand(packages, false)
|
|
260
|
+
|
|
261
|
+
this.logger?.debug(`Executando: ${command}`)
|
|
262
|
+
execSync(command, {
|
|
263
|
+
cwd: this.config.workspaceRoot,
|
|
264
|
+
stdio: 'inherit'
|
|
265
|
+
})
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (peerDeps.length > 0) {
|
|
269
|
+
const packages = peerDeps.map(d => `${d.name}@${d.version}`).join(' ')
|
|
270
|
+
const command = this.getInstallCommand(packages, false) // Peer deps como regulares
|
|
271
|
+
|
|
272
|
+
this.logger?.debug(`Executando: ${command}`)
|
|
273
|
+
execSync(command, {
|
|
274
|
+
cwd: this.config.workspaceRoot,
|
|
275
|
+
stdio: 'inherit'
|
|
276
|
+
})
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Recarregar dependências instaladas
|
|
280
|
+
this.loadInstalledDependencies()
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Obter comando de instalação baseado no package manager
|
|
285
|
+
*/
|
|
286
|
+
private getInstallCommand(packages: string, dev: boolean): string {
|
|
287
|
+
const devFlag = dev ? '--save-dev' : ''
|
|
288
|
+
|
|
289
|
+
switch (this.config.packageManager) {
|
|
290
|
+
case 'npm':
|
|
291
|
+
return `npm install ${devFlag} ${packages}`
|
|
292
|
+
case 'yarn':
|
|
293
|
+
return `yarn add ${dev ? '--dev' : ''} ${packages}`
|
|
294
|
+
case 'pnpm':
|
|
295
|
+
return `pnpm add ${devFlag} ${packages}`
|
|
296
|
+
case 'bun':
|
|
297
|
+
return `bun add ${devFlag} ${packages}`
|
|
298
|
+
default:
|
|
299
|
+
return `npm install ${devFlag} ${packages}`
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Carregar dependências já instaladas
|
|
305
|
+
*/
|
|
306
|
+
private loadInstalledDependencies(): void {
|
|
307
|
+
const packageJsonPath = join(this.config.workspaceRoot!, 'package.json')
|
|
308
|
+
|
|
309
|
+
if (!existsSync(packageJsonPath)) {
|
|
310
|
+
return
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'))
|
|
315
|
+
|
|
316
|
+
// Carregar dependencies
|
|
317
|
+
if (packageJson.dependencies) {
|
|
318
|
+
for (const [name, version] of Object.entries(packageJson.dependencies)) {
|
|
319
|
+
this.installedDependencies.set(name, version as string)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Carregar devDependencies
|
|
324
|
+
if (packageJson.devDependencies) {
|
|
325
|
+
for (const [name, version] of Object.entries(packageJson.devDependencies)) {
|
|
326
|
+
this.installedDependencies.set(name, version as string)
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
} catch (error) {
|
|
330
|
+
this.logger?.warn('Erro ao carregar package.json principal', { error })
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Verificar se versões são compatíveis
|
|
336
|
+
*/
|
|
337
|
+
private isVersionCompatible(installed: string, required: string): boolean {
|
|
338
|
+
// Implementação simples - em produção usaria semver
|
|
339
|
+
if (required.startsWith('^') || required.startsWith('~')) {
|
|
340
|
+
const requiredVersion = required.slice(1)
|
|
341
|
+
return this.compareVersions(installed, requiredVersion) >= 0
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return installed === required
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Comparar versões (implementação simples)
|
|
349
|
+
*/
|
|
350
|
+
private compareVersions(a: string, b: string): number {
|
|
351
|
+
const aParts = a.replace(/[^\d.]/g, '').split('.').map(Number)
|
|
352
|
+
const bParts = b.replace(/[^\d.]/g, '').split('.').map(Number)
|
|
353
|
+
|
|
354
|
+
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
355
|
+
const aPart = aParts[i] || 0
|
|
356
|
+
const bPart = bParts[i] || 0
|
|
357
|
+
|
|
358
|
+
if (aPart > bPart) return 1
|
|
359
|
+
if (aPart < bPart) return -1
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return 0
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Extrair nome do plugin do caminho
|
|
367
|
+
*/
|
|
368
|
+
private getPluginNameFromPath(pluginPath: string): string {
|
|
369
|
+
return pluginPath.split('/').pop() || 'unknown'
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Obter estatísticas de dependências
|
|
374
|
+
*/
|
|
375
|
+
getStats() {
|
|
376
|
+
return {
|
|
377
|
+
totalPlugins: this.pluginDependencies.size,
|
|
378
|
+
totalDependencies: Array.from(this.pluginDependencies.values())
|
|
379
|
+
.reduce((sum, deps) => sum + deps.length, 0),
|
|
380
|
+
installedDependencies: this.installedDependencies.size,
|
|
381
|
+
packageManager: this.config.packageManager
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
package/core/plugins/index.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
// Core plugin types and interfaces
|
|
7
7
|
export type {
|
|
8
|
-
|
|
8
|
+
FluxStack,
|
|
9
9
|
PluginContext,
|
|
10
10
|
PluginHook,
|
|
11
11
|
PluginPriority,
|
|
@@ -27,6 +27,8 @@ export type {
|
|
|
27
27
|
BuildContext
|
|
28
28
|
} from './types'
|
|
29
29
|
|
|
30
|
+
export type Plugin = FluxStack.Plugin
|
|
31
|
+
|
|
30
32
|
// Plugin registry
|
|
31
33
|
export { PluginRegistry } from './registry'
|
|
32
34
|
export type { PluginRegistryConfig } from './registry'
|
|
@@ -78,6 +80,7 @@ export const PluginUtils = {
|
|
|
78
80
|
onServerStart?: (context: PluginContext) => void | Promise<void>
|
|
79
81
|
onServerStop?: (context: PluginContext) => void | Promise<void>
|
|
80
82
|
onRequest?: (context: RequestContext) => void | Promise<void>
|
|
83
|
+
onBeforeRoute?: (context: RequestContext) => void | Promise<void>
|
|
81
84
|
onResponse?: (context: ResponseContext) => void | Promise<void>
|
|
82
85
|
onError?: (context: ErrorContext) => void | Promise<void>
|
|
83
86
|
configSchema?: any
|
|
@@ -93,6 +96,7 @@ export const PluginUtils = {
|
|
|
93
96
|
...(config.onServerStart && { onServerStart: config.onServerStart }),
|
|
94
97
|
...(config.onServerStop && { onServerStop: config.onServerStop }),
|
|
95
98
|
...(config.onRequest && { onRequest: config.onRequest }),
|
|
99
|
+
...(config.onBeforeRoute && { onBeforeRoute: config.onBeforeRoute }),
|
|
96
100
|
...(config.onResponse && { onResponse: config.onResponse }),
|
|
97
101
|
...(config.onError && { onError: config.onError }),
|
|
98
102
|
...(config.configSchema && { configSchema: config.configSchema }),
|
package/core/plugins/manager.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type {
|
|
7
|
-
|
|
7
|
+
FluxStack,
|
|
8
8
|
PluginContext,
|
|
9
9
|
PluginHook,
|
|
10
10
|
PluginHookResult,
|
|
@@ -16,6 +16,8 @@ import type {
|
|
|
16
16
|
ErrorContext,
|
|
17
17
|
BuildContext
|
|
18
18
|
} from "./types"
|
|
19
|
+
|
|
20
|
+
type Plugin = FluxStack.Plugin
|
|
19
21
|
import type { FluxStackConfig } from "../config/schema"
|
|
20
22
|
import type { Logger } from "../utils/logger/index"
|
|
21
23
|
import { PluginRegistry } from "./registry"
|
|
@@ -394,8 +396,10 @@ export class PluginManager extends EventEmitter {
|
|
|
394
396
|
*/
|
|
395
397
|
private async discoverPlugins(): Promise<void> {
|
|
396
398
|
try {
|
|
399
|
+
this.logger.info('Discovering external plugins in directory: plugins')
|
|
397
400
|
const results = await this.registry.discoverPlugins({
|
|
398
|
-
|
|
401
|
+
directories: ['plugins'],
|
|
402
|
+
includeBuiltIn: false,
|
|
399
403
|
includeExternal: true
|
|
400
404
|
})
|
|
401
405
|
|
|
@@ -444,7 +448,7 @@ export class PluginManager extends EventEmitter {
|
|
|
444
448
|
|
|
445
449
|
const context: PluginContext = {
|
|
446
450
|
config: this.config,
|
|
447
|
-
logger: this.logger
|
|
451
|
+
logger: this.logger,
|
|
448
452
|
app: this.app,
|
|
449
453
|
utils: createPluginUtils(this.logger),
|
|
450
454
|
registry: this.registry
|