create-fluxstack 1.10.1 → 1.12.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/.dockerignore +1 -2
- package/Dockerfile +8 -8
- package/LLMD/INDEX.md +64 -0
- package/LLMD/MAINTENANCE.md +197 -0
- package/LLMD/MIGRATION.md +156 -0
- package/LLMD/config/.gitkeep +1 -0
- package/LLMD/config/declarative-system.md +268 -0
- package/LLMD/config/environment-vars.md +327 -0
- package/LLMD/config/runtime-reload.md +401 -0
- package/LLMD/core/.gitkeep +1 -0
- package/LLMD/core/build-system.md +599 -0
- package/LLMD/core/framework-lifecycle.md +229 -0
- package/LLMD/core/plugin-system.md +451 -0
- package/LLMD/patterns/.gitkeep +1 -0
- package/LLMD/patterns/anti-patterns.md +297 -0
- package/LLMD/patterns/project-structure.md +264 -0
- package/LLMD/patterns/type-safety.md +440 -0
- package/LLMD/reference/.gitkeep +1 -0
- package/LLMD/reference/cli-commands.md +250 -0
- package/LLMD/reference/plugin-hooks.md +357 -0
- package/LLMD/reference/routing.md +39 -0
- package/LLMD/reference/troubleshooting.md +364 -0
- package/LLMD/resources/.gitkeep +1 -0
- package/LLMD/resources/controllers.md +465 -0
- package/LLMD/resources/live-components.md +703 -0
- package/LLMD/resources/live-rooms.md +482 -0
- package/LLMD/resources/live-upload.md +130 -0
- package/LLMD/resources/plugins-external.md +617 -0
- package/LLMD/resources/routes-eden.md +254 -0
- package/README.md +37 -17
- package/app/client/index.html +0 -1
- package/app/client/src/App.tsx +107 -150
- package/app/client/src/components/AppLayout.tsx +68 -0
- package/app/client/src/components/BackButton.tsx +13 -0
- package/app/client/src/components/DemoPage.tsx +20 -0
- package/app/client/src/components/LiveUploadWidget.tsx +204 -0
- package/app/client/src/lib/eden-api.ts +85 -60
- package/app/client/src/live/ChatDemo.tsx +107 -0
- package/app/client/src/live/CounterDemo.tsx +206 -0
- package/app/client/src/live/FormDemo.tsx +119 -0
- package/app/client/src/live/RoomChatDemo.tsx +242 -0
- package/app/client/src/live/UploadDemo.tsx +21 -0
- package/app/client/src/main.tsx +4 -1
- package/app/client/src/pages/ApiTestPage.tsx +108 -0
- package/app/client/src/pages/HomePage.tsx +76 -0
- package/app/server/app.ts +1 -4
- package/app/server/controllers/users.controller.ts +36 -44
- package/app/server/index.ts +25 -35
- package/app/server/live/LiveChat.ts +77 -0
- package/app/server/live/LiveCounter.ts +67 -0
- package/app/server/live/LiveForm.ts +63 -0
- package/app/server/live/LiveLocalCounter.ts +32 -0
- package/app/server/live/LiveRoomChat.ts +285 -0
- package/app/server/live/LiveUpload.ts +81 -0
- package/app/server/routes/index.ts +3 -1
- package/app/server/routes/room.routes.ts +117 -0
- package/app/server/routes/users.routes.ts +35 -27
- package/app/shared/types/index.ts +14 -2
- package/config/app.config.ts +2 -62
- package/config/client.config.ts +2 -95
- package/config/database.config.ts +2 -99
- package/config/fluxstack.config.ts +25 -45
- package/config/index.ts +57 -38
- package/config/monitoring.config.ts +2 -114
- package/config/plugins.config.ts +2 -80
- package/config/server.config.ts +2 -68
- package/config/services.config.ts +2 -130
- package/config/system/app.config.ts +29 -0
- package/config/system/build.config.ts +49 -0
- package/config/system/client.config.ts +68 -0
- package/config/system/database.config.ts +17 -0
- package/config/system/fluxstack.config.ts +114 -0
- package/config/{logger.config.ts → system/logger.config.ts} +3 -1
- package/config/system/monitoring.config.ts +114 -0
- package/config/system/plugins.config.ts +84 -0
- package/config/{runtime.config.ts → system/runtime.config.ts} +1 -1
- package/config/system/server.config.ts +68 -0
- package/config/system/services.config.ts +46 -0
- package/config/{system.config.ts → system/system.config.ts} +1 -1
- package/core/build/flux-plugins-generator.ts +325 -325
- package/core/build/index.ts +39 -27
- package/core/build/live-components-generator.ts +3 -3
- package/core/build/optimizer.ts +235 -235
- package/core/cli/command-registry.ts +6 -4
- package/core/cli/commands/build.ts +79 -0
- package/core/cli/commands/create.ts +54 -0
- package/core/cli/commands/dev.ts +101 -0
- package/core/cli/commands/help.ts +34 -0
- package/core/cli/commands/index.ts +34 -0
- package/core/cli/commands/make-plugin.ts +90 -0
- package/core/cli/commands/plugin-add.ts +197 -0
- package/core/cli/commands/plugin-deps.ts +2 -2
- package/core/cli/commands/plugin-list.ts +208 -0
- package/core/cli/commands/plugin-remove.ts +170 -0
- package/core/cli/generators/component.ts +769 -769
- package/core/cli/generators/controller.ts +1 -1
- package/core/cli/generators/index.ts +146 -146
- package/core/cli/generators/interactive.ts +227 -227
- package/core/cli/generators/plugin.ts +2 -2
- package/core/cli/generators/prompts.ts +82 -82
- package/core/cli/generators/route.ts +6 -6
- package/core/cli/generators/service.ts +2 -2
- package/core/cli/generators/template-engine.ts +4 -3
- package/core/cli/generators/types.ts +2 -2
- package/core/cli/generators/utils.ts +191 -191
- package/core/cli/index.ts +115 -686
- package/core/cli/plugin-discovery.ts +2 -2
- package/core/client/LiveComponentsProvider.tsx +60 -8
- package/core/client/api/eden.ts +183 -0
- package/core/client/api/index.ts +11 -0
- package/core/client/components/Live.tsx +104 -0
- package/core/client/fluxstack.ts +1 -9
- package/core/client/hooks/AdaptiveChunkSizer.ts +215 -215
- package/core/client/hooks/state-validator.ts +1 -1
- package/core/client/hooks/useAuth.ts +48 -48
- package/core/client/hooks/useChunkedUpload.ts +85 -35
- package/core/client/hooks/useLiveChunkedUpload.ts +87 -0
- package/core/client/hooks/useLiveComponent.ts +800 -0
- package/core/client/hooks/useLiveUpload.ts +71 -0
- package/core/client/hooks/useRoom.ts +409 -0
- package/core/client/hooks/useRoomProxy.ts +382 -0
- package/core/client/index.ts +17 -68
- package/core/client/standalone-entry.ts +8 -0
- package/core/client/standalone.ts +74 -53
- package/core/client/state/createStore.ts +192 -192
- package/core/client/state/index.ts +14 -14
- package/core/config/index.ts +70 -291
- package/core/config/schema.ts +42 -723
- package/core/framework/client.ts +131 -131
- package/core/framework/index.ts +7 -7
- package/core/framework/server.ts +47 -40
- package/core/framework/types.ts +2 -2
- package/core/index.ts +23 -4
- package/core/live/ComponentRegistry.ts +3 -3
- package/core/live/types.ts +77 -0
- package/core/plugins/built-in/index.ts +134 -134
- package/core/plugins/built-in/live-components/commands/create-live-component.ts +242 -1066
- package/core/plugins/built-in/live-components/index.ts +1 -1
- package/core/plugins/built-in/monitoring/index.ts +111 -47
- package/core/plugins/built-in/static/index.ts +1 -1
- package/core/plugins/built-in/swagger/index.ts +68 -265
- package/core/plugins/built-in/vite/index.ts +85 -185
- package/core/plugins/built-in/vite/vite-dev.ts +10 -16
- package/core/plugins/config.ts +9 -7
- package/core/plugins/dependency-manager.ts +31 -1
- package/core/plugins/discovery.ts +19 -7
- package/core/plugins/executor.ts +2 -2
- package/core/plugins/index.ts +203 -203
- package/core/plugins/manager.ts +27 -39
- package/core/plugins/module-resolver.ts +19 -8
- package/core/plugins/registry.ts +255 -19
- package/core/plugins/types.ts +20 -53
- package/core/server/framework.ts +66 -43
- package/core/server/index.ts +15 -15
- package/core/server/live/ComponentRegistry.ts +78 -71
- package/core/server/live/FileUploadManager.ts +23 -10
- package/core/server/live/LiveComponentPerformanceMonitor.ts +1 -1
- package/core/server/live/LiveRoomManager.ts +261 -0
- package/core/server/live/RoomEventBus.ts +234 -0
- package/core/server/live/RoomStateManager.ts +172 -0
- package/core/server/live/StateSignature.ts +643 -643
- package/core/server/live/WebSocketConnectionManager.ts +30 -19
- package/core/server/live/auto-generated-components.ts +21 -9
- package/core/server/live/index.ts +14 -0
- package/core/server/live/websocket-plugin.ts +214 -67
- package/core/server/middleware/elysia-helpers.ts +7 -2
- package/core/server/middleware/errorHandling.ts +1 -1
- package/core/server/middleware/index.ts +31 -31
- package/core/server/plugins/database.ts +180 -180
- package/core/server/plugins/static-files-plugin.ts +69 -69
- package/core/server/plugins/swagger.ts +1 -1
- package/core/server/rooms/RoomBroadcaster.ts +357 -0
- package/core/server/rooms/RoomSystem.ts +463 -0
- package/core/server/rooms/index.ts +13 -0
- package/core/server/services/BaseService.ts +1 -1
- package/core/server/services/ServiceContainer.ts +1 -1
- package/core/server/services/index.ts +8 -8
- package/core/templates/create-project.ts +12 -12
- package/core/testing/index.ts +9 -9
- package/core/testing/setup.ts +73 -73
- package/core/types/api.ts +168 -168
- package/core/types/build.ts +219 -219
- package/core/types/config.ts +56 -26
- package/core/types/index.ts +4 -4
- package/core/types/plugin.ts +107 -107
- package/core/types/types.ts +353 -14
- package/core/utils/build-logger.ts +324 -324
- package/core/utils/config-schema.ts +480 -480
- package/core/utils/env.ts +2 -8
- package/core/utils/errors/codes.ts +114 -114
- package/core/utils/errors/handlers.ts +36 -1
- package/core/utils/errors/index.ts +49 -5
- package/core/utils/errors/middleware.ts +113 -113
- package/core/utils/helpers.ts +6 -16
- package/core/utils/index.ts +17 -17
- package/core/utils/logger/colors.ts +114 -114
- package/core/utils/logger/config.ts +13 -9
- package/core/utils/logger/formatter.ts +82 -82
- package/core/utils/logger/group-logger.ts +101 -101
- package/core/utils/logger/index.ts +6 -1
- package/core/utils/logger/stack-trace.ts +3 -1
- package/core/utils/logger/startup-banner.ts +82 -82
- package/core/utils/logger/winston-logger.ts +152 -152
- package/core/utils/monitoring/index.ts +211 -211
- package/core/utils/sync-version.ts +66 -66
- package/core/utils/version.ts +1 -1
- package/create-fluxstack.ts +8 -7
- package/package.json +12 -13
- package/plugins/crypto-auth/cli/make-protected-route.command.ts +1 -1
- package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -302
- package/plugins/crypto-auth/client/components/index.ts +11 -11
- package/plugins/crypto-auth/client/index.ts +11 -11
- package/plugins/crypto-auth/config/index.ts +1 -1
- package/plugins/crypto-auth/index.ts +4 -4
- package/plugins/crypto-auth/package.json +65 -65
- package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
- package/plugins/crypto-auth/server/CryptoAuthService.ts +185 -185
- package/plugins/crypto-auth/server/index.ts +21 -21
- package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +3 -3
- package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +1 -1
- package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +2 -2
- package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +2 -2
- package/plugins/crypto-auth/server/middlewares/helpers.ts +1 -1
- package/plugins/crypto-auth/server/middlewares/index.ts +22 -22
- package/tsconfig.api-strict.json +16 -0
- package/tsconfig.json +48 -52
- package/{app/client/tsconfig.node.json → tsconfig.node.json} +25 -25
- package/types/global.d.ts +29 -29
- package/types/vitest.d.ts +8 -8
- package/vite.config.ts +38 -62
- package/vitest.config.live.ts +10 -9
- package/vitest.config.ts +29 -17
- package/app/client/README.md +0 -69
- package/app/client/SIMPLIFICATION.md +0 -140
- package/app/client/frontend-only.ts +0 -12
- package/app/client/src/live/FileUploadExample.tsx +0 -359
- package/app/client/src/live/MinimalLiveClock.tsx +0 -47
- package/app/client/src/live/QuickUploadTest.tsx +0 -193
- package/app/client/tsconfig.app.json +0 -45
- package/app/client/tsconfig.json +0 -7
- package/app/client/zustand-setup.md +0 -65
- package/app/server/backend-only.ts +0 -18
- package/app/server/live/LiveClockComponent.ts +0 -215
- package/app/server/live/LiveFileUploadComponent.ts +0 -77
- package/app/server/routes/env-test.ts +0 -110
- package/core/client/hooks/index.ts +0 -7
- package/core/client/hooks/useHybridLiveComponent.ts +0 -685
- package/core/client/hooks/useTypedLiveComponent.ts +0 -133
- package/core/client/hooks/useWebSocket.ts +0 -361
- package/core/config/env.ts +0 -546
- package/core/config/loader.ts +0 -522
- package/core/config/runtime-config.ts +0 -327
- package/core/config/validator.ts +0 -540
- package/core/server/backend-entry.ts +0 -51
- package/core/server/standalone.ts +0 -106
- package/core/utils/regenerate-files.ts +0 -69
- package/fluxstack.config.ts +0 -354
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FluxStack CLI - Plugin List Command
|
|
3
|
+
* List all plugins (installed, whitelisted, discovered)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Command } from 'commander'
|
|
7
|
+
import { readFileSync, existsSync } from 'fs'
|
|
8
|
+
import { join } from 'path'
|
|
9
|
+
import chalk from 'chalk'
|
|
10
|
+
|
|
11
|
+
export function createPluginListCommand(): Command {
|
|
12
|
+
const command = new Command('plugin:list')
|
|
13
|
+
.description('List all plugins (installed, whitelisted, and discovered)')
|
|
14
|
+
.option('--installed', 'Show only installed NPM plugins')
|
|
15
|
+
.option('--whitelisted', 'Show only whitelisted plugins')
|
|
16
|
+
.option('--json', 'Output as JSON')
|
|
17
|
+
.action(async (options: { installed?: boolean; whitelisted?: boolean; json?: boolean }) => {
|
|
18
|
+
try {
|
|
19
|
+
const info = getPluginInfo()
|
|
20
|
+
|
|
21
|
+
if (options.json) {
|
|
22
|
+
console.log(JSON.stringify(info, null, 2))
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log(chalk.blue('\n🔌 FluxStack Plugin Status\n'))
|
|
27
|
+
|
|
28
|
+
// Configuration
|
|
29
|
+
console.log(chalk.bold('⚙️ Configuration:'))
|
|
30
|
+
console.log(chalk.gray(` NPM Plugin Discovery: ${info.config.npmDiscoveryEnabled ? chalk.green('enabled') : chalk.red('disabled')}`))
|
|
31
|
+
console.log(chalk.gray(` Project Plugin Discovery: ${info.config.projectDiscoveryEnabled ? chalk.green('enabled') : chalk.red('disabled')}`))
|
|
32
|
+
console.log()
|
|
33
|
+
|
|
34
|
+
// Whitelisted plugins
|
|
35
|
+
if (!options.installed) {
|
|
36
|
+
console.log(chalk.bold('🛡️ Whitelisted NPM Plugins:'))
|
|
37
|
+
if (info.whitelisted.length === 0) {
|
|
38
|
+
console.log(chalk.gray(' (none)'))
|
|
39
|
+
} else {
|
|
40
|
+
info.whitelisted.forEach(plugin => {
|
|
41
|
+
const isInstalled = info.installed.includes(plugin)
|
|
42
|
+
const status = isInstalled ? chalk.green('✓ installed') : chalk.yellow('⚠ not installed')
|
|
43
|
+
console.log(chalk.gray(` • ${plugin} ${status}`))
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
console.log()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Installed NPM plugins
|
|
50
|
+
if (!options.whitelisted) {
|
|
51
|
+
console.log(chalk.bold('📦 Installed NPM Plugins:'))
|
|
52
|
+
if (info.installed.length === 0) {
|
|
53
|
+
console.log(chalk.gray(' (none)'))
|
|
54
|
+
} else {
|
|
55
|
+
info.installed.forEach(plugin => {
|
|
56
|
+
const isWhitelisted = info.whitelisted.includes(plugin)
|
|
57
|
+
let status = ''
|
|
58
|
+
if (!info.config.npmDiscoveryEnabled) {
|
|
59
|
+
status = chalk.red('✗ discovery disabled')
|
|
60
|
+
} else if (!isWhitelisted) {
|
|
61
|
+
status = chalk.red('✗ not whitelisted (blocked)')
|
|
62
|
+
} else {
|
|
63
|
+
status = chalk.green('✓ whitelisted (loaded)')
|
|
64
|
+
}
|
|
65
|
+
console.log(chalk.gray(` • ${plugin} ${status}`))
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
console.log()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Project plugins (from plugins/ directory)
|
|
72
|
+
console.log(chalk.bold('📁 Project Plugins (plugins/):'))
|
|
73
|
+
if (info.projectPlugins.length === 0) {
|
|
74
|
+
console.log(chalk.gray(' (none found)'))
|
|
75
|
+
} else {
|
|
76
|
+
info.projectPlugins.forEach(plugin => {
|
|
77
|
+
const status = info.config.projectDiscoveryEnabled
|
|
78
|
+
? chalk.green('✓ auto-discovered')
|
|
79
|
+
: chalk.red('✗ discovery disabled')
|
|
80
|
+
console.log(chalk.gray(` • ${plugin} ${status}`))
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
console.log()
|
|
84
|
+
|
|
85
|
+
// Summary
|
|
86
|
+
console.log(chalk.bold('📊 Summary:'))
|
|
87
|
+
console.log(chalk.gray(` Total NPM plugins installed: ${info.installed.length}`))
|
|
88
|
+
console.log(chalk.gray(` Total NPM plugins whitelisted: ${info.whitelisted.length}`))
|
|
89
|
+
console.log(chalk.gray(` Total project plugins: ${info.projectPlugins.length}`))
|
|
90
|
+
|
|
91
|
+
const blockedCount = info.installed.filter(p => !info.whitelisted.includes(p)).length
|
|
92
|
+
if (blockedCount > 0) {
|
|
93
|
+
console.log(chalk.yellow(` ⚠️ ${blockedCount} installed plugin(s) blocked (not whitelisted)`))
|
|
94
|
+
}
|
|
95
|
+
console.log()
|
|
96
|
+
|
|
97
|
+
// Help
|
|
98
|
+
if (info.installed.length > 0 && !info.config.npmDiscoveryEnabled) {
|
|
99
|
+
console.log(chalk.yellow('💡 Tip: Enable NPM plugin discovery with:'))
|
|
100
|
+
console.log(chalk.gray(' echo "PLUGINS_DISCOVER_NPM=true" >> .env'))
|
|
101
|
+
console.log()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (blockedCount > 0 && info.config.npmDiscoveryEnabled) {
|
|
105
|
+
console.log(chalk.yellow('💡 Tip: Add blocked plugins to whitelist with:'))
|
|
106
|
+
console.log(chalk.gray(' bun run fluxstack plugin:add <plugin-name>'))
|
|
107
|
+
console.log()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.error(chalk.red('\n❌ Failed to list plugins:'))
|
|
112
|
+
console.error(chalk.red(error instanceof Error ? error.message : String(error)))
|
|
113
|
+
process.exit(1)
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
return command
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface PluginInfo {
|
|
121
|
+
config: {
|
|
122
|
+
npmDiscoveryEnabled: boolean
|
|
123
|
+
projectDiscoveryEnabled: boolean
|
|
124
|
+
}
|
|
125
|
+
whitelisted: string[]
|
|
126
|
+
installed: string[]
|
|
127
|
+
projectPlugins: string[]
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get plugin information from package.json and .env
|
|
132
|
+
*/
|
|
133
|
+
function getPluginInfo(): PluginInfo {
|
|
134
|
+
const info: PluginInfo = {
|
|
135
|
+
config: {
|
|
136
|
+
npmDiscoveryEnabled: false,
|
|
137
|
+
projectDiscoveryEnabled: true,
|
|
138
|
+
},
|
|
139
|
+
whitelisted: [],
|
|
140
|
+
installed: [],
|
|
141
|
+
projectPlugins: [],
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Read .env for configuration
|
|
145
|
+
const envPath = join(process.cwd(), '.env')
|
|
146
|
+
if (existsSync(envPath)) {
|
|
147
|
+
const envContent = readFileSync(envPath, 'utf-8')
|
|
148
|
+
|
|
149
|
+
// Check NPM discovery enabled
|
|
150
|
+
const npmDiscoveryMatch = envContent.match(/^PLUGINS_DISCOVER_NPM=(.*)$/m)
|
|
151
|
+
if (npmDiscoveryMatch) {
|
|
152
|
+
info.config.npmDiscoveryEnabled = npmDiscoveryMatch[1].toLowerCase() === 'true'
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Check project discovery enabled
|
|
156
|
+
const projectDiscoveryMatch = envContent.match(/^PLUGINS_DISCOVER_PROJECT=(.*)$/m)
|
|
157
|
+
if (projectDiscoveryMatch) {
|
|
158
|
+
info.config.projectDiscoveryEnabled = projectDiscoveryMatch[1].toLowerCase() === 'true'
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Get whitelisted plugins
|
|
162
|
+
const whitelistMatch = envContent.match(/^PLUGINS_ALLOWED=(.*)$/m)
|
|
163
|
+
if (whitelistMatch) {
|
|
164
|
+
info.whitelisted = whitelistMatch[1]
|
|
165
|
+
.split(',')
|
|
166
|
+
.map(p => p.trim())
|
|
167
|
+
.filter(p => p.length > 0)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Read package.json for installed plugins
|
|
172
|
+
const packageJsonPath = join(process.cwd(), 'package.json')
|
|
173
|
+
if (existsSync(packageJsonPath)) {
|
|
174
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'))
|
|
175
|
+
const allDeps = {
|
|
176
|
+
...packageJson.dependencies,
|
|
177
|
+
...packageJson.devDependencies,
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Find FluxStack plugins
|
|
181
|
+
const pluginPatterns = [
|
|
182
|
+
/^fluxstack-plugin-/,
|
|
183
|
+
/^fplugin-/,
|
|
184
|
+
/^@fluxstack\/plugin-/,
|
|
185
|
+
/^@fplugin\//,
|
|
186
|
+
]
|
|
187
|
+
|
|
188
|
+
info.installed = Object.keys(allDeps).filter(name =>
|
|
189
|
+
pluginPatterns.some(pattern => pattern.test(name))
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Scan plugins/ directory for project plugins
|
|
194
|
+
const pluginsDir = join(process.cwd(), 'plugins')
|
|
195
|
+
if (existsSync(pluginsDir)) {
|
|
196
|
+
const fs = require('fs')
|
|
197
|
+
try {
|
|
198
|
+
const entries = fs.readdirSync(pluginsDir, { withFileTypes: true })
|
|
199
|
+
info.projectPlugins = entries
|
|
200
|
+
.filter((entry: any) => entry.isDirectory())
|
|
201
|
+
.map((entry: any) => entry.name)
|
|
202
|
+
} catch (error) {
|
|
203
|
+
// Ignore errors reading directory
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return info
|
|
208
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FluxStack CLI - Plugin Remove Command
|
|
3
|
+
* Safely remove and un-whitelist NPM plugins
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Command } from 'commander'
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs'
|
|
8
|
+
import { join } from 'path'
|
|
9
|
+
import { $ } from 'bun'
|
|
10
|
+
import chalk from 'chalk'
|
|
11
|
+
|
|
12
|
+
interface PluginRemoveOptions {
|
|
13
|
+
skipConfirmation?: boolean
|
|
14
|
+
keepInstalled?: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function createPluginRemoveCommand(): Command {
|
|
18
|
+
const command = new Command('plugin:remove')
|
|
19
|
+
.description('Remove plugin from whitelist and optionally uninstall')
|
|
20
|
+
.argument('<plugin-name>', 'Name of the plugin to remove (e.g., fluxstack-plugin-auth)')
|
|
21
|
+
.option('--skip-confirmation', 'Skip confirmation prompt')
|
|
22
|
+
.option('--keep-installed', 'Keep plugin installed, only remove from whitelist')
|
|
23
|
+
.action(async (pluginName: string, options: PluginRemoveOptions) => {
|
|
24
|
+
console.log(chalk.blue('\n🔌 FluxStack Plugin Remover\n'))
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
// 1. Check if plugin is installed
|
|
28
|
+
const packageJsonPath = join(process.cwd(), 'package.json')
|
|
29
|
+
if (!existsSync(packageJsonPath)) {
|
|
30
|
+
console.error(chalk.red('❌ package.json not found'))
|
|
31
|
+
process.exit(1)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'))
|
|
35
|
+
const isInstalled =
|
|
36
|
+
packageJson.dependencies?.[pluginName] ||
|
|
37
|
+
packageJson.devDependencies?.[pluginName]
|
|
38
|
+
|
|
39
|
+
if (!isInstalled && !options.keepInstalled) {
|
|
40
|
+
console.log(chalk.yellow(`⚠️ Plugin ${pluginName} is not installed`))
|
|
41
|
+
console.log(chalk.yellow(' Will only remove from whitelist\n'))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 2. Confirmation prompt (unless skipped)
|
|
45
|
+
if (!options.skipConfirmation) {
|
|
46
|
+
const action = options.keepInstalled
|
|
47
|
+
? 'remove from whitelist'
|
|
48
|
+
: 'uninstall and remove from whitelist'
|
|
49
|
+
|
|
50
|
+
const answer = prompt(chalk.yellow(`Remove ${pluginName}? This will ${action}. (yes/no): `))
|
|
51
|
+
if (answer?.toLowerCase() !== 'yes' && answer?.toLowerCase() !== 'y') {
|
|
52
|
+
console.log(chalk.red('❌ Removal cancelled'))
|
|
53
|
+
process.exit(0)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 3. Remove from whitelist
|
|
58
|
+
console.log(chalk.blue('\n🔧 Updating configuration...\n'))
|
|
59
|
+
const removed = removeFromWhitelist(pluginName)
|
|
60
|
+
|
|
61
|
+
if (!removed) {
|
|
62
|
+
console.log(chalk.yellow(`⚠️ Plugin ${pluginName} was not in whitelist`))
|
|
63
|
+
} else {
|
|
64
|
+
console.log(chalk.gray(` • Removed ${pluginName} from PLUGINS_ALLOWED`))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 4. Uninstall plugin (unless --keep-installed)
|
|
68
|
+
if (!options.keepInstalled && isInstalled) {
|
|
69
|
+
console.log(chalk.blue(`\n📦 Uninstalling ${pluginName}...\n`))
|
|
70
|
+
await $`bun remove ${pluginName}`.quiet()
|
|
71
|
+
console.log(chalk.green(`✅ Plugin uninstalled successfully`))
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 5. Check if should disable NPM discovery
|
|
75
|
+
checkAndDisableNpmDiscovery()
|
|
76
|
+
|
|
77
|
+
// 6. Success message
|
|
78
|
+
console.log(chalk.green('\n✅ Plugin removal complete!\n'))
|
|
79
|
+
console.log(chalk.blue('📋 What was done:'))
|
|
80
|
+
console.log(chalk.gray(` • Removed ${pluginName} from whitelist (PLUGINS_ALLOWED)`))
|
|
81
|
+
if (!options.keepInstalled && isInstalled) {
|
|
82
|
+
console.log(chalk.gray(` • Uninstalled ${pluginName}`))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
console.log(chalk.blue('\n🚀 Next steps:'))
|
|
86
|
+
console.log(chalk.gray(' 1. Restart your dev server: bun run dev'))
|
|
87
|
+
console.log(chalk.gray(' 2. Plugin will no longer be loaded'))
|
|
88
|
+
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error(chalk.red('\n❌ Failed to remove plugin:'))
|
|
91
|
+
console.error(chalk.red(error instanceof Error ? error.message : String(error)))
|
|
92
|
+
process.exit(1)
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
return command
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Remove plugin from whitelist in .env file
|
|
101
|
+
*/
|
|
102
|
+
function removeFromWhitelist(pluginName: string): boolean {
|
|
103
|
+
const envPath = join(process.cwd(), '.env')
|
|
104
|
+
|
|
105
|
+
if (!existsSync(envPath)) {
|
|
106
|
+
return false
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let envContent = readFileSync(envPath, 'utf-8')
|
|
110
|
+
const allowedPluginsRegex = /^PLUGINS_ALLOWED=(.*)$/m
|
|
111
|
+
const match = envContent.match(allowedPluginsRegex)
|
|
112
|
+
|
|
113
|
+
if (!match) {
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const currentPlugins = match[1]
|
|
118
|
+
.split(',')
|
|
119
|
+
.map(p => p.trim())
|
|
120
|
+
.filter(p => p.length > 0)
|
|
121
|
+
|
|
122
|
+
if (!currentPlugins.includes(pluginName)) {
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const newPlugins = currentPlugins.filter(p => p !== pluginName)
|
|
127
|
+
envContent = envContent.replace(
|
|
128
|
+
allowedPluginsRegex,
|
|
129
|
+
`PLUGINS_ALLOWED=${newPlugins.join(',')}`
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
writeFileSync(envPath, envContent, 'utf-8')
|
|
133
|
+
return true
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Check if whitelist is empty and disable NPM discovery if so
|
|
138
|
+
*/
|
|
139
|
+
function checkAndDisableNpmDiscovery(): void {
|
|
140
|
+
const envPath = join(process.cwd(), '.env')
|
|
141
|
+
|
|
142
|
+
if (!existsSync(envPath)) {
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let envContent = readFileSync(envPath, 'utf-8')
|
|
147
|
+
const allowedPluginsRegex = /^PLUGINS_ALLOWED=(.*)$/m
|
|
148
|
+
const match = envContent.match(allowedPluginsRegex)
|
|
149
|
+
|
|
150
|
+
if (!match) {
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const currentPlugins = match[1]
|
|
155
|
+
.split(',')
|
|
156
|
+
.map(p => p.trim())
|
|
157
|
+
.filter(p => p.length > 0)
|
|
158
|
+
|
|
159
|
+
// If whitelist is empty, disable NPM discovery
|
|
160
|
+
if (currentPlugins.length === 0) {
|
|
161
|
+
if (/^PLUGINS_DISCOVER_NPM=true/m.test(envContent)) {
|
|
162
|
+
envContent = envContent.replace(
|
|
163
|
+
/^PLUGINS_DISCOVER_NPM=true/m,
|
|
164
|
+
'PLUGINS_DISCOVER_NPM=false'
|
|
165
|
+
)
|
|
166
|
+
writeFileSync(envPath, envContent, 'utf-8')
|
|
167
|
+
console.log(chalk.gray(' • Disabled NPM plugin discovery (whitelist empty)'))
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|