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
package/core/cli/index.ts
CHANGED
|
@@ -1,25 +1,115 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
/**
|
|
4
|
+
* FluxStack CLI Entry Point
|
|
5
|
+
* Modular command structure with each command in its own file
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
8
|
import { cliRegistry } from "./command-registry"
|
|
9
9
|
import { pluginDiscovery } from "./plugin-discovery"
|
|
10
10
|
import { generateCommand, interactiveGenerateCommand } from "./generators/index"
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
// Import modular commands
|
|
13
|
+
import { builtInCommands } from "./commands"
|
|
12
14
|
|
|
13
15
|
const command = process.argv[2]
|
|
14
16
|
const args = process.argv.slice(3)
|
|
15
17
|
|
|
16
18
|
// Register built-in commands
|
|
17
19
|
async function registerBuiltInCommands() {
|
|
18
|
-
// Register
|
|
20
|
+
// Register modular commands from commands/
|
|
21
|
+
for (const cmd of builtInCommands) {
|
|
22
|
+
cliRegistry.register(cmd)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Register generate commands (still in generators/)
|
|
19
26
|
cliRegistry.register(generateCommand)
|
|
20
27
|
cliRegistry.register(interactiveGenerateCommand)
|
|
21
|
-
|
|
22
|
-
// Register plugin
|
|
28
|
+
|
|
29
|
+
// Register plugin commands that use Commander.js (dynamic imports)
|
|
30
|
+
cliRegistry.register({
|
|
31
|
+
name: 'plugin:add',
|
|
32
|
+
description: 'Install and whitelist an NPM plugin securely',
|
|
33
|
+
category: 'Plugins',
|
|
34
|
+
arguments: [
|
|
35
|
+
{
|
|
36
|
+
name: 'plugin-name',
|
|
37
|
+
description: 'Name of the plugin to install (e.g., fluxstack-plugin-auth)',
|
|
38
|
+
required: true
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
options: [
|
|
42
|
+
{
|
|
43
|
+
name: '--skip-audit',
|
|
44
|
+
description: 'Skip npm audit check'
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: '--skip-confirmation',
|
|
48
|
+
description: 'Skip confirmation prompt'
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
handler: async (args, options, context) => {
|
|
52
|
+
const { createPluginAddCommand } = await import('./commands/plugin-add')
|
|
53
|
+
const cmd = createPluginAddCommand()
|
|
54
|
+
await cmd.parseAsync(['node', 'cli', ...args], { from: 'user' })
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
cliRegistry.register({
|
|
59
|
+
name: 'plugin:remove',
|
|
60
|
+
description: 'Remove plugin from whitelist and optionally uninstall',
|
|
61
|
+
category: 'Plugins',
|
|
62
|
+
aliases: ['plugin:rm'],
|
|
63
|
+
arguments: [
|
|
64
|
+
{
|
|
65
|
+
name: 'plugin-name',
|
|
66
|
+
description: 'Name of the plugin to remove',
|
|
67
|
+
required: true
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
options: [
|
|
71
|
+
{
|
|
72
|
+
name: '--skip-confirmation',
|
|
73
|
+
description: 'Skip confirmation prompt'
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: '--keep-installed',
|
|
77
|
+
description: 'Keep plugin installed, only remove from whitelist'
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
handler: async (args, options, context) => {
|
|
81
|
+
const { createPluginRemoveCommand } = await import('./commands/plugin-remove')
|
|
82
|
+
const cmd = createPluginRemoveCommand()
|
|
83
|
+
await cmd.parseAsync(['node', 'cli', ...args], { from: 'user' })
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
cliRegistry.register({
|
|
88
|
+
name: 'plugin:list',
|
|
89
|
+
description: 'List all plugins (installed, whitelisted, and discovered)',
|
|
90
|
+
category: 'Plugins',
|
|
91
|
+
aliases: ['plugin:ls'],
|
|
92
|
+
options: [
|
|
93
|
+
{
|
|
94
|
+
name: '--installed',
|
|
95
|
+
description: 'Show only installed NPM plugins'
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: '--whitelisted',
|
|
99
|
+
description: 'Show only whitelisted plugins'
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: '--json',
|
|
103
|
+
description: 'Output as JSON'
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
handler: async (args, options, context) => {
|
|
107
|
+
const { createPluginListCommand } = await import('./commands/plugin-list')
|
|
108
|
+
const cmd = createPluginListCommand()
|
|
109
|
+
await cmd.parseAsync(['node', 'cli', ...args], { from: 'user' })
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
|
|
23
113
|
cliRegistry.register({
|
|
24
114
|
name: 'plugin:deps',
|
|
25
115
|
description: 'Gerenciar dependências de plugins',
|
|
@@ -31,7 +121,7 @@ async function registerBuiltInCommands() {
|
|
|
31
121
|
|
|
32
122
|
Usage:
|
|
33
123
|
flux plugin:deps install Install plugin dependencies
|
|
34
|
-
flux plugin:deps list List plugin dependencies
|
|
124
|
+
flux plugin:deps list List plugin dependencies
|
|
35
125
|
flux plugin:deps check Check for dependency conflicts
|
|
36
126
|
flux plugin:deps clean Clean unused dependencies
|
|
37
127
|
|
|
@@ -42,15 +132,13 @@ Examples:
|
|
|
42
132
|
`)
|
|
43
133
|
return
|
|
44
134
|
}
|
|
45
|
-
|
|
46
|
-
// Handle subcommands
|
|
135
|
+
|
|
47
136
|
const subcommand = args[0]
|
|
48
137
|
const subArgs = args.slice(1)
|
|
49
|
-
|
|
50
|
-
// Import dinamicamente para evitar problemas de inicialização
|
|
138
|
+
|
|
51
139
|
const { createPluginDepsCommand } = await import('./commands/plugin-deps')
|
|
52
140
|
const cmd = createPluginDepsCommand()
|
|
53
|
-
|
|
141
|
+
|
|
54
142
|
switch (subcommand) {
|
|
55
143
|
case 'install':
|
|
56
144
|
const installCmd = cmd.commands.find(c => c.name() === 'install')
|
|
@@ -82,682 +170,23 @@ Examples:
|
|
|
82
170
|
}
|
|
83
171
|
}
|
|
84
172
|
})
|
|
85
|
-
|
|
86
|
-
// Help command
|
|
87
|
-
cliRegistry.register({
|
|
88
|
-
name: 'help',
|
|
89
|
-
description: 'Show help information',
|
|
90
|
-
category: 'General',
|
|
91
|
-
aliases: ['h', '--help', '-h'],
|
|
92
|
-
arguments: [
|
|
93
|
-
{
|
|
94
|
-
name: 'command',
|
|
95
|
-
description: 'Command to show help for',
|
|
96
|
-
required: false
|
|
97
|
-
}
|
|
98
|
-
],
|
|
99
|
-
handler: async (args, options, context) => {
|
|
100
|
-
if (args[0]) {
|
|
101
|
-
const targetCommand = cliRegistry.get(args[0])
|
|
102
|
-
if (targetCommand) {
|
|
103
|
-
cliRegistry.showCommandHelp(targetCommand)
|
|
104
|
-
} else {
|
|
105
|
-
console.error(`❌ Unknown command: ${args[0]}`)
|
|
106
|
-
cliRegistry.showHelp()
|
|
107
|
-
}
|
|
108
|
-
} else {
|
|
109
|
-
cliRegistry.showHelp()
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
// Dev command
|
|
115
|
-
cliRegistry.register({
|
|
116
|
-
name: 'dev',
|
|
117
|
-
description: 'Start full-stack development server',
|
|
118
|
-
category: 'Development',
|
|
119
|
-
usage: 'flux dev [options]',
|
|
120
|
-
examples: [
|
|
121
|
-
'flux dev # Start development server',
|
|
122
|
-
'flux dev --port 4000 # Start on custom port'
|
|
123
|
-
],
|
|
124
|
-
options: [
|
|
125
|
-
{
|
|
126
|
-
name: 'port',
|
|
127
|
-
short: 'p',
|
|
128
|
-
description: 'Port for backend server',
|
|
129
|
-
type: 'number',
|
|
130
|
-
default: serverConfig.server.port
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
name: 'frontend-port',
|
|
134
|
-
description: 'Port for frontend server',
|
|
135
|
-
type: 'number',
|
|
136
|
-
default: clientConfig.vite.port
|
|
137
|
-
}
|
|
138
|
-
],
|
|
139
|
-
handler: async (args, options, context) => {
|
|
140
|
-
// Grouped startup messages
|
|
141
|
-
startGroup({
|
|
142
|
-
title: 'FluxStack Development Server',
|
|
143
|
-
icon: '',
|
|
144
|
-
color: 'cyan'
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
logInGroup(`Server: http://localhost:${options.port}`, '')
|
|
148
|
-
logInGroup(`API: http://localhost:${options.port}/api`, '')
|
|
149
|
-
logInGroup(`Swagger: http://localhost:${options.port}/swagger`, '')
|
|
150
|
-
logInGroup('Starting with hot reload...', '')
|
|
151
|
-
|
|
152
|
-
endGroup()
|
|
153
|
-
console.log('') // Separator line
|
|
154
|
-
|
|
155
|
-
const { spawn } = await import("child_process")
|
|
156
|
-
const devProcess = spawn("bun", ["--watch", "app/server/index.ts"], {
|
|
157
|
-
stdio: "inherit",
|
|
158
|
-
cwd: process.cwd(),
|
|
159
|
-
env: {
|
|
160
|
-
...process.env,
|
|
161
|
-
FRONTEND_PORT: options['frontend-port'].toString(),
|
|
162
|
-
BACKEND_PORT: options.port.toString()
|
|
163
|
-
}
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
process.on('SIGINT', () => {
|
|
167
|
-
console.log('\n🛑 Shutting down gracefully...')
|
|
168
|
-
devProcess.kill('SIGTERM')
|
|
169
|
-
setTimeout(() => {
|
|
170
|
-
devProcess.kill('SIGKILL')
|
|
171
|
-
process.exit(0)
|
|
172
|
-
}, 5000)
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
devProcess.on('close', (code) => {
|
|
176
|
-
process.exit(code || 0)
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
// Keep the CLI running until the child process exits
|
|
180
|
-
return new Promise((resolve) => {
|
|
181
|
-
devProcess.on('exit', resolve)
|
|
182
|
-
})
|
|
183
|
-
}
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
// Build command
|
|
187
|
-
cliRegistry.register({
|
|
188
|
-
name: 'build',
|
|
189
|
-
description: 'Build the application for production',
|
|
190
|
-
category: 'Build',
|
|
191
|
-
usage: 'flux build [options]',
|
|
192
|
-
examples: [
|
|
193
|
-
'flux build # Build both frontend and backend',
|
|
194
|
-
'flux build --frontend-only # Build only frontend',
|
|
195
|
-
'flux build --backend-only # Build only backend'
|
|
196
|
-
],
|
|
197
|
-
options: [
|
|
198
|
-
{
|
|
199
|
-
name: 'frontend-only',
|
|
200
|
-
description: 'Build only frontend',
|
|
201
|
-
type: 'boolean'
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
name: 'backend-only',
|
|
205
|
-
description: 'Build only backend',
|
|
206
|
-
type: 'boolean'
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
name: 'production',
|
|
210
|
-
description: 'Build for production (minified)',
|
|
211
|
-
type: 'boolean',
|
|
212
|
-
default: true
|
|
213
|
-
}
|
|
214
|
-
],
|
|
215
|
-
handler: async (args, options, context) => {
|
|
216
|
-
const config = getConfigSync()
|
|
217
|
-
|
|
218
|
-
// Load plugins for build hooks
|
|
219
|
-
const { PluginRegistry } = await import('../plugins/registry')
|
|
220
|
-
const { PluginManager } = await import('../plugins/manager')
|
|
221
|
-
const pluginRegistry = new PluginRegistry({ config, logger: context.logger })
|
|
222
|
-
const pluginManager = new PluginManager({ config, logger: context.logger })
|
|
223
|
-
|
|
224
|
-
try {
|
|
225
|
-
await pluginManager.initialize()
|
|
226
|
-
// Sync plugins to registry (same as framework does)
|
|
227
|
-
const discoveredPlugins = pluginManager.getRegistry().getAll()
|
|
228
|
-
for (const plugin of discoveredPlugins) {
|
|
229
|
-
if (!pluginRegistry.has(plugin.name)) {
|
|
230
|
-
(pluginRegistry as any).plugins.set(plugin.name, plugin)
|
|
231
|
-
if (plugin.dependencies) {
|
|
232
|
-
(pluginRegistry as any).dependencies.set(plugin.name, plugin.dependencies)
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
try {
|
|
237
|
-
(pluginRegistry as any).updateLoadOrder()
|
|
238
|
-
} catch (error) {
|
|
239
|
-
const plugins = (pluginRegistry as any).plugins as Map<string, any>
|
|
240
|
-
;(pluginRegistry as any).loadOrder = Array.from(plugins.keys())
|
|
241
|
-
}
|
|
242
|
-
} catch (error) {
|
|
243
|
-
context.logger.warn('Failed to load plugins for build hooks', { error })
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const builder = new FluxStackBuilder(config, pluginRegistry)
|
|
247
|
-
|
|
248
|
-
if (options['frontend-only']) {
|
|
249
|
-
await builder.buildClient()
|
|
250
|
-
} else if (options['backend-only']) {
|
|
251
|
-
await builder.buildServer()
|
|
252
|
-
} else {
|
|
253
|
-
await builder.build()
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
})
|
|
257
|
-
|
|
258
|
-
// Create command
|
|
259
|
-
cliRegistry.register({
|
|
260
|
-
name: 'create',
|
|
261
|
-
description: 'Create a new FluxStack project',
|
|
262
|
-
category: 'Project',
|
|
263
|
-
usage: 'flux create <project-name> [template]',
|
|
264
|
-
examples: [
|
|
265
|
-
'flux create my-app # Create basic project',
|
|
266
|
-
'flux create my-app full # Create full-featured project'
|
|
267
|
-
],
|
|
268
|
-
arguments: [
|
|
269
|
-
{
|
|
270
|
-
name: 'project-name',
|
|
271
|
-
description: 'Name of the project to create',
|
|
272
|
-
required: true,
|
|
273
|
-
type: 'string'
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
name: 'template',
|
|
277
|
-
description: 'Project template to use',
|
|
278
|
-
required: false,
|
|
279
|
-
type: 'string',
|
|
280
|
-
default: 'basic',
|
|
281
|
-
choices: ['basic', 'full']
|
|
282
|
-
}
|
|
283
|
-
],
|
|
284
|
-
handler: async (args, options, context) => {
|
|
285
|
-
const [projectName, template] = args
|
|
286
|
-
|
|
287
|
-
if (!/^[a-zA-Z0-9-_]+$/.test(projectName)) {
|
|
288
|
-
console.error("❌ Project name can only contain letters, numbers, hyphens, and underscores")
|
|
289
|
-
return
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
try {
|
|
293
|
-
const creator = new ProjectCreator({
|
|
294
|
-
name: projectName,
|
|
295
|
-
template: template as 'basic' | 'full' || 'basic'
|
|
296
|
-
})
|
|
297
|
-
|
|
298
|
-
await creator.create()
|
|
299
|
-
} catch (error) {
|
|
300
|
-
console.error("❌ Failed to create project:", error instanceof Error ? error.message : String(error))
|
|
301
|
-
throw error
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
})
|
|
305
|
-
|
|
306
|
-
// Make:plugin command (shortcut for generate plugin)
|
|
307
|
-
cliRegistry.register({
|
|
308
|
-
name: 'make:plugin',
|
|
309
|
-
description: 'Create a new FluxStack plugin',
|
|
310
|
-
category: 'Plugins',
|
|
311
|
-
usage: 'flux make:plugin <name> [options]',
|
|
312
|
-
aliases: ['create:plugin'],
|
|
313
|
-
examples: [
|
|
314
|
-
'flux make:plugin my-plugin # Create basic plugin',
|
|
315
|
-
'flux make:plugin my-plugin --template full # Create full plugin with server/client',
|
|
316
|
-
'flux make:plugin auth --template server # Create server-only plugin'
|
|
317
|
-
],
|
|
318
|
-
arguments: [
|
|
319
|
-
{
|
|
320
|
-
name: 'name',
|
|
321
|
-
description: 'Name of the plugin to create',
|
|
322
|
-
required: true,
|
|
323
|
-
type: 'string'
|
|
324
|
-
}
|
|
325
|
-
],
|
|
326
|
-
options: [
|
|
327
|
-
{
|
|
328
|
-
name: 'template',
|
|
329
|
-
short: 't',
|
|
330
|
-
description: 'Plugin template to use',
|
|
331
|
-
type: 'string',
|
|
332
|
-
choices: ['basic', 'full', 'server', 'client'],
|
|
333
|
-
default: 'basic'
|
|
334
|
-
},
|
|
335
|
-
{
|
|
336
|
-
name: 'description',
|
|
337
|
-
short: 'd',
|
|
338
|
-
description: 'Plugin description',
|
|
339
|
-
type: 'string',
|
|
340
|
-
default: 'A FluxStack plugin'
|
|
341
|
-
},
|
|
342
|
-
{
|
|
343
|
-
name: 'force',
|
|
344
|
-
short: 'f',
|
|
345
|
-
description: 'Overwrite existing plugin',
|
|
346
|
-
type: 'boolean',
|
|
347
|
-
default: false
|
|
348
|
-
}
|
|
349
|
-
],
|
|
350
|
-
handler: async (args, options, context) => {
|
|
351
|
-
const [name] = args
|
|
352
|
-
|
|
353
|
-
if (!/^[a-zA-Z0-9-_]+$/.test(name)) {
|
|
354
|
-
console.error("❌ Plugin name can only contain letters, numbers, hyphens, and underscores")
|
|
355
|
-
return
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// Use the plugin generator
|
|
359
|
-
const { generatorRegistry } = await import('./generators/index')
|
|
360
|
-
const pluginGenerator = generatorRegistry.get('plugin')
|
|
361
|
-
|
|
362
|
-
if (!pluginGenerator) {
|
|
363
|
-
console.error("❌ Plugin generator not found")
|
|
364
|
-
return
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
const generatorContext = {
|
|
368
|
-
workingDir: context.workingDir,
|
|
369
|
-
config: context.config,
|
|
370
|
-
logger: context.logger,
|
|
371
|
-
utils: context.utils
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
const generatorOptions = {
|
|
375
|
-
name,
|
|
376
|
-
template: options.template,
|
|
377
|
-
force: options.force,
|
|
378
|
-
dryRun: false,
|
|
379
|
-
description: options.description
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
try {
|
|
383
|
-
await pluginGenerator.generate(generatorContext, generatorOptions)
|
|
384
|
-
} catch (error) {
|
|
385
|
-
console.error("❌ Failed to create plugin:", error instanceof Error ? error.message : String(error))
|
|
386
|
-
throw error
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
})
|
|
390
|
-
|
|
391
|
-
// Frontend command (frontend-only development)
|
|
392
|
-
cliRegistry.register({
|
|
393
|
-
name: 'frontend',
|
|
394
|
-
description: 'Start frontend development server only',
|
|
395
|
-
category: 'Development',
|
|
396
|
-
usage: 'flux frontend [options]',
|
|
397
|
-
examples: [
|
|
398
|
-
'flux frontend # Start Vite dev server on port 5173',
|
|
399
|
-
'flux frontend --port 3000 # Start on custom port'
|
|
400
|
-
],
|
|
401
|
-
options: [
|
|
402
|
-
{
|
|
403
|
-
name: 'port',
|
|
404
|
-
short: 'p',
|
|
405
|
-
description: 'Port for frontend server',
|
|
406
|
-
type: 'number',
|
|
407
|
-
default: 5173
|
|
408
|
-
}
|
|
409
|
-
],
|
|
410
|
-
handler: async (args, options, context) => {
|
|
411
|
-
console.log("🎨 FluxStack Frontend Development")
|
|
412
|
-
console.log(`🌐 Frontend: http://localhost:${options.port}`)
|
|
413
|
-
console.log("📦 Starting Vite dev server...")
|
|
414
|
-
console.log()
|
|
415
|
-
|
|
416
|
-
const { spawn } = await import("child_process")
|
|
417
|
-
const frontendProcess = spawn("vite", ["--config", "vite.config.ts", "--port", options.port.toString()], {
|
|
418
|
-
stdio: "inherit",
|
|
419
|
-
cwd: process.cwd()
|
|
420
|
-
})
|
|
421
173
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
})
|
|
430
|
-
}
|
|
431
|
-
})
|
|
432
|
-
|
|
433
|
-
// Backend command (backend-only development)
|
|
434
|
-
cliRegistry.register({
|
|
435
|
-
name: 'backend',
|
|
436
|
-
description: 'Start backend development server only',
|
|
437
|
-
category: 'Development',
|
|
438
|
-
usage: 'flux backend [options]',
|
|
439
|
-
examples: [
|
|
440
|
-
'flux backend # Start backend on port 3001',
|
|
441
|
-
'flux backend --port 4000 # Start on custom port'
|
|
442
|
-
],
|
|
443
|
-
options: [
|
|
444
|
-
{
|
|
445
|
-
name: 'port',
|
|
446
|
-
short: 'p',
|
|
447
|
-
description: 'Port for backend server',
|
|
448
|
-
type: 'number',
|
|
449
|
-
default: 3001
|
|
450
|
-
}
|
|
451
|
-
],
|
|
452
|
-
handler: async (args, options, context) => {
|
|
453
|
-
console.log("⚡ FluxStack Backend Development")
|
|
454
|
-
console.log(`🚀 API Server: http://localhost:${options.port}`)
|
|
455
|
-
console.log("📦 Starting backend with hot reload...")
|
|
456
|
-
console.log()
|
|
457
|
-
|
|
458
|
-
// Ensure backend-only.ts exists
|
|
459
|
-
const { ensureBackendEntry } = await import("../utils/regenerate-files")
|
|
460
|
-
await ensureBackendEntry()
|
|
461
|
-
|
|
462
|
-
// Start backend with Bun watch for hot reload
|
|
463
|
-
const { spawn } = await import("child_process")
|
|
464
|
-
const backendProcess = spawn("bun", ["--watch", "app/server/backend-only.ts"], {
|
|
465
|
-
stdio: "inherit",
|
|
466
|
-
cwd: process.cwd(),
|
|
467
|
-
env: {
|
|
468
|
-
...process.env,
|
|
469
|
-
BACKEND_PORT: options.port.toString()
|
|
470
|
-
}
|
|
471
|
-
})
|
|
472
|
-
|
|
473
|
-
// Handle process cleanup
|
|
474
|
-
process.on('SIGINT', () => {
|
|
475
|
-
backendProcess.kill('SIGINT')
|
|
476
|
-
process.exit(0)
|
|
477
|
-
})
|
|
478
|
-
|
|
479
|
-
return new Promise((resolve) => {
|
|
480
|
-
backendProcess.on('exit', resolve)
|
|
481
|
-
})
|
|
482
|
-
}
|
|
483
|
-
})
|
|
484
|
-
|
|
485
|
-
// Start command (production server)
|
|
486
|
-
cliRegistry.register({
|
|
487
|
-
name: 'start',
|
|
488
|
-
description: 'Start production server',
|
|
489
|
-
category: 'Production',
|
|
490
|
-
usage: 'flux start',
|
|
491
|
-
examples: [
|
|
492
|
-
'flux start # Start production server from dist/'
|
|
493
|
-
],
|
|
494
|
-
handler: async (args, options, context) => {
|
|
495
|
-
console.log("🚀 Starting FluxStack production server...")
|
|
496
|
-
const { join } = await import("path")
|
|
497
|
-
await import(join(process.cwd(), "dist", "index.js"))
|
|
498
|
-
}
|
|
499
|
-
})
|
|
500
|
-
|
|
501
|
-
// Build:frontend command (shortcut)
|
|
502
|
-
cliRegistry.register({
|
|
503
|
-
name: 'build:frontend',
|
|
504
|
-
description: 'Build frontend only (shortcut for build --frontend-only)',
|
|
505
|
-
category: 'Build',
|
|
506
|
-
usage: 'flux build:frontend',
|
|
507
|
-
examples: [
|
|
508
|
-
'flux build:frontend # Build only frontend'
|
|
509
|
-
],
|
|
510
|
-
handler: async (args, options, context) => {
|
|
511
|
-
const config = getConfigSync()
|
|
512
|
-
const builder = new FluxStackBuilder(config)
|
|
513
|
-
await builder.buildClient()
|
|
514
|
-
}
|
|
515
|
-
})
|
|
516
|
-
|
|
517
|
-
// Build:backend command (shortcut)
|
|
518
|
-
cliRegistry.register({
|
|
519
|
-
name: 'build:backend',
|
|
520
|
-
description: 'Build backend only (shortcut for build --backend-only)',
|
|
521
|
-
category: 'Build',
|
|
522
|
-
usage: 'flux build:backend',
|
|
523
|
-
examples: [
|
|
524
|
-
'flux build:backend # Build only backend'
|
|
525
|
-
],
|
|
526
|
-
handler: async (args, options, context) => {
|
|
527
|
-
const config = getConfigSync()
|
|
528
|
-
const builder = new FluxStackBuilder(config)
|
|
529
|
-
await builder.buildServer()
|
|
530
|
-
}
|
|
531
|
-
})
|
|
532
|
-
|
|
533
|
-
// Build:exe command (compile to executable)
|
|
534
|
-
cliRegistry.register({
|
|
535
|
-
name: 'build:exe',
|
|
536
|
-
description: 'Compile application to standalone executable',
|
|
537
|
-
category: 'Build',
|
|
538
|
-
usage: 'flux build:exe [options]',
|
|
539
|
-
examples: [
|
|
540
|
-
'flux build:exe # Compile for current platform (auto-detected)',
|
|
541
|
-
'flux build:exe --target bun-linux-x64 # Compile for specific target',
|
|
542
|
-
'flux build:exe --name MyApp # Compile with custom name',
|
|
543
|
-
'flux build:exe --windows-hide-console # Hide console window on Windows'
|
|
544
|
-
],
|
|
545
|
-
options: [
|
|
546
|
-
{
|
|
547
|
-
name: 'name',
|
|
548
|
-
short: 'n',
|
|
549
|
-
description: 'Name for the executable file',
|
|
550
|
-
type: 'string',
|
|
551
|
-
default: 'CLauncher'
|
|
552
|
-
},
|
|
553
|
-
{
|
|
554
|
-
name: 'target',
|
|
555
|
-
short: 't',
|
|
556
|
-
description: 'Target platform (if not specified, builds all Windows targets)',
|
|
557
|
-
type: 'string',
|
|
558
|
-
choices: [
|
|
559
|
-
'bun-windows-x64',
|
|
560
|
-
'bun-windows-x64-baseline',
|
|
561
|
-
'bun-linux-x64',
|
|
562
|
-
'bun-linux-x64-baseline',
|
|
563
|
-
'bun-linux-arm64',
|
|
564
|
-
'bun-darwin-x64',
|
|
565
|
-
'bun-darwin-arm64'
|
|
566
|
-
]
|
|
567
|
-
},
|
|
568
|
-
{
|
|
569
|
-
name: 'windows-hide-console',
|
|
570
|
-
description: 'Hide console window on Windows',
|
|
571
|
-
type: 'boolean',
|
|
572
|
-
default: false
|
|
573
|
-
},
|
|
574
|
-
{
|
|
575
|
-
name: 'windows-icon',
|
|
576
|
-
description: 'Path to .ico file for Windows executable',
|
|
577
|
-
type: 'string'
|
|
578
|
-
},
|
|
579
|
-
{
|
|
580
|
-
name: 'windows-title',
|
|
581
|
-
description: 'Product name for Windows executable',
|
|
582
|
-
type: 'string'
|
|
583
|
-
},
|
|
584
|
-
{
|
|
585
|
-
name: 'windows-publisher',
|
|
586
|
-
description: 'Company name for Windows executable',
|
|
587
|
-
type: 'string'
|
|
588
|
-
},
|
|
589
|
-
{
|
|
590
|
-
name: 'windows-version',
|
|
591
|
-
description: 'Version string for Windows executable (e.g. 1.2.3.4)',
|
|
592
|
-
type: 'string'
|
|
593
|
-
},
|
|
594
|
-
{
|
|
595
|
-
name: 'windows-description',
|
|
596
|
-
description: 'Description for Windows executable',
|
|
597
|
-
type: 'string'
|
|
598
|
-
},
|
|
599
|
-
{
|
|
600
|
-
name: 'windows-copyright',
|
|
601
|
-
description: 'Copyright string for Windows executable',
|
|
602
|
-
type: 'string'
|
|
603
|
-
}
|
|
604
|
-
],
|
|
605
|
-
handler: async (args, options, context) => {
|
|
606
|
-
const config = getConfigSync()
|
|
607
|
-
const builder = new FluxStackBuilder(config)
|
|
608
|
-
|
|
609
|
-
// Build executable options from CLI args with smart defaults
|
|
610
|
-
const appName = config.app.name || 'CLauncher'
|
|
611
|
-
const appVersion = config.app.version || '1.0.0'
|
|
612
|
-
const currentYear = new Date().getFullYear()
|
|
613
|
-
|
|
614
|
-
// Convert semver to Windows version format (1.0.0 -> 1.0.0.0)
|
|
615
|
-
const windowsVersion = options['windows-version'] ||
|
|
616
|
-
(appVersion.split('.').length === 3 ? `${appVersion}.0` : appVersion)
|
|
617
|
-
|
|
618
|
-
// Determine targets to build based on current platform
|
|
619
|
-
const getDefaultTargets = (): string[] => {
|
|
620
|
-
const platform = process.platform
|
|
621
|
-
const arch = process.arch
|
|
622
|
-
|
|
623
|
-
if (platform === 'win32') {
|
|
624
|
-
return ['bun-windows-x64', 'bun-windows-x64-baseline']
|
|
625
|
-
} else if (platform === 'linux') {
|
|
626
|
-
if (arch === 'arm64') {
|
|
627
|
-
return ['bun-linux-arm64']
|
|
628
|
-
}
|
|
629
|
-
return ['bun-linux-x64', 'bun-linux-x64-baseline']
|
|
630
|
-
} else if (platform === 'darwin') {
|
|
631
|
-
if (arch === 'arm64') {
|
|
632
|
-
return ['bun-darwin-arm64']
|
|
633
|
-
}
|
|
634
|
-
return ['bun-darwin-x64']
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
// Fallback to current platform
|
|
638
|
-
return [`bun-${platform}-${arch}`]
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
const targets: string[] = options.target
|
|
642
|
-
? [options.target]
|
|
643
|
-
: getDefaultTargets()
|
|
644
|
-
|
|
645
|
-
const results: Array<{ target: string; success: boolean; outputPath?: string; error?: string }> = []
|
|
646
|
-
|
|
647
|
-
for (const target of targets) {
|
|
648
|
-
// Determine if this is a Windows target
|
|
649
|
-
const isWindowsTarget = target.includes('windows')
|
|
650
|
-
|
|
651
|
-
// Build executable options for this target
|
|
652
|
-
const executableOptions: import("../types/build").BundleOptions = {
|
|
653
|
-
target,
|
|
654
|
-
executable: isWindowsTarget ? {
|
|
655
|
-
windows: {
|
|
656
|
-
hideConsole: options['windows-hide-console'],
|
|
657
|
-
icon: options['windows-icon'],
|
|
658
|
-
title: options['windows-title'] || appName,
|
|
659
|
-
publisher: options['windows-publisher'] || appName,
|
|
660
|
-
version: windowsVersion,
|
|
661
|
-
description: options['windows-description'] || `${appName} Application`,
|
|
662
|
-
copyright: options['windows-copyright'] || `Copyright © ${currentYear} ${appName}`
|
|
663
|
-
}
|
|
664
|
-
} : {}
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
// Generate output name with target suffix
|
|
668
|
-
const baseName = options.name || appName
|
|
669
|
-
const targetSuffix = target.replace('bun-', '').replace(/-/g, '_')
|
|
670
|
-
const outputName = targets.length > 1 ? `${baseName}_${targetSuffix}` : baseName
|
|
671
|
-
|
|
672
|
-
console.log(`\n🔨 Building for ${target}...`)
|
|
673
|
-
const result = await builder.buildExecutable(outputName, executableOptions)
|
|
674
|
-
|
|
675
|
-
results.push({
|
|
676
|
-
target,
|
|
677
|
-
success: result.success,
|
|
678
|
-
outputPath: result.outputPath,
|
|
679
|
-
error: result.error
|
|
680
|
-
})
|
|
681
|
-
|
|
682
|
-
if (result.success) {
|
|
683
|
-
console.log(`✅ ${target}: ${result.outputPath}`)
|
|
684
|
-
} else {
|
|
685
|
-
console.error(`❌ ${target}: ${result.error}`)
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
// Summary
|
|
690
|
-
const successful = results.filter(r => r.success)
|
|
691
|
-
const failed = results.filter(r => !r.success)
|
|
692
|
-
|
|
693
|
-
console.log('\n' + '═'.repeat(50))
|
|
694
|
-
console.log('📊 Build Summary')
|
|
695
|
-
console.log('═'.repeat(50))
|
|
696
|
-
|
|
697
|
-
if (successful.length > 0) {
|
|
698
|
-
console.log(`\n✅ Successful (${successful.length}):`)
|
|
699
|
-
for (const r of successful) {
|
|
700
|
-
console.log(` • ${r.target} → ${r.outputPath}`)
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
if (failed.length > 0) {
|
|
705
|
-
console.log(`\n❌ Failed (${failed.length}):`)
|
|
706
|
-
for (const r of failed) {
|
|
707
|
-
console.log(` • ${r.target}: ${r.error}`)
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
// Show Windows metadata if any Windows target was built
|
|
712
|
-
const hasWindowsTarget = targets.some(t => t.includes('windows'))
|
|
713
|
-
if (hasWindowsTarget && successful.length > 0) {
|
|
714
|
-
console.log('\n📦 Windows executable metadata:')
|
|
715
|
-
if (options['windows-hide-console']) console.log(' • Console window: hidden')
|
|
716
|
-
if (options['windows-icon']) console.log(` • Icon: ${options['windows-icon']}`)
|
|
717
|
-
console.log(` • Title: ${options['windows-title'] || appName}`)
|
|
718
|
-
console.log(` • Publisher: ${options['windows-publisher'] || appName}`)
|
|
719
|
-
console.log(` • Version: ${windowsVersion}`)
|
|
720
|
-
console.log(` • Description: ${options['windows-description'] || `${appName} Application`}`)
|
|
721
|
-
console.log(` • Copyright: ${options['windows-copyright'] || `Copyright © ${currentYear} ${appName}`}`)
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
if (failed.length > 0) {
|
|
725
|
-
process.exit(1)
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
})
|
|
174
|
+
// Discover and register plugin-provided commands
|
|
175
|
+
try {
|
|
176
|
+
await pluginDiscovery.discoverAndRegisterCommands()
|
|
177
|
+
} catch (error) {
|
|
178
|
+
// Plugin command discovery is optional
|
|
179
|
+
// console.warn('Failed to discover plugin commands:', error)
|
|
180
|
+
}
|
|
729
181
|
}
|
|
730
182
|
|
|
731
|
-
//
|
|
183
|
+
// Initialize and run CLI
|
|
732
184
|
async function main() {
|
|
733
|
-
// Register built-in commands
|
|
734
185
|
await registerBuiltInCommands()
|
|
735
|
-
|
|
736
|
-
// Discover and register plugin commands
|
|
737
|
-
await pluginDiscovery.discoverAndRegisterCommands()
|
|
738
|
-
|
|
739
|
-
// Handle special cases first
|
|
740
|
-
if (!command || command === 'help' || command === '--help' || command === '-h') {
|
|
741
|
-
await cliRegistry.execute('help', args)
|
|
742
|
-
return
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
// Check if it's a registered command (built-in or plugin)
|
|
746
|
-
if (cliRegistry.has(command)) {
|
|
747
|
-
const exitCode = await cliRegistry.execute(command, args)
|
|
748
|
-
process.exit(exitCode)
|
|
749
|
-
return
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
// Command not found - show error and help
|
|
753
|
-
console.error(`❌ Unknown command: ${command}`)
|
|
754
|
-
console.error()
|
|
755
|
-
await cliRegistry.execute('help', args)
|
|
756
|
-
process.exit(1)
|
|
186
|
+
await cliRegistry.execute(command, args)
|
|
757
187
|
}
|
|
758
188
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
console.error('❌ CLI Error:', error instanceof Error ? error.message : String(error))
|
|
189
|
+
main().catch((error) => {
|
|
190
|
+
console.error('CLI Error:', error)
|
|
762
191
|
process.exit(1)
|
|
763
|
-
})
|
|
192
|
+
})
|