create-fluxstack 1.18.1 → 1.20.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/CHANGELOG.md +132 -0
- package/LLMD/INDEX.md +1 -1
- package/LLMD/MAINTENANCE.md +197 -197
- package/LLMD/MIGRATION.md +44 -1
- package/LLMD/agent.md +20 -7
- package/LLMD/config/declarative-system.md +268 -268
- package/LLMD/config/environment-vars.md +3 -6
- package/LLMD/config/runtime-reload.md +401 -401
- package/LLMD/core/build-system.md +599 -599
- package/LLMD/core/framework-lifecycle.md +249 -229
- package/LLMD/core/plugin-system.md +154 -100
- package/LLMD/patterns/anti-patterns.md +397 -397
- package/LLMD/patterns/project-structure.md +264 -264
- package/LLMD/patterns/type-safety.md +61 -5
- package/LLMD/reference/cli-commands.md +31 -7
- package/LLMD/reference/plugin-hooks.md +4 -2
- package/LLMD/reference/troubleshooting.md +364 -364
- package/LLMD/resources/controllers.md +465 -465
- package/LLMD/resources/live-auth.md +178 -1
- package/LLMD/resources/live-binary-delta.md +3 -1
- package/LLMD/resources/live-components.md +1192 -1041
- package/LLMD/resources/live-logging.md +3 -1
- package/LLMD/resources/live-rooms.md +1 -1
- package/LLMD/resources/live-upload.md +228 -181
- package/LLMD/resources/plugins-external.md +8 -7
- package/LLMD/resources/rest-auth.md +290 -290
- package/LLMD/resources/routes-eden.md +254 -254
- package/app/client/src/App.tsx +7 -7
- package/app/client/src/components/AppLayout.tsx +60 -23
- package/app/client/src/components/ColorWheel.tsx +195 -0
- package/app/client/src/components/DemoPage.tsx +5 -3
- package/app/client/src/components/LiveUploadWidget.tsx +1 -1
- package/app/client/src/components/ThemePicker.tsx +307 -0
- package/app/client/src/config/theme.config.ts +127 -0
- package/app/client/src/hooks/useThemeClock.ts +66 -0
- package/app/client/src/index.css +193 -0
- package/app/client/src/lib/theme-clock.ts +201 -0
- package/app/client/src/live/AuthDemo.tsx +9 -9
- package/app/client/src/live/CounterDemo.tsx +10 -10
- package/app/client/src/live/FormDemo.tsx +8 -8
- package/app/client/src/live/PingPongDemo.tsx +10 -10
- package/app/client/src/live/RoomChatDemo.tsx +10 -10
- package/app/client/src/live/SharedCounterDemo.tsx +5 -5
- package/app/client/src/pages/ApiTestPage.tsx +5 -5
- package/app/client/src/pages/HomePage.tsx +12 -12
- package/app/server/index.ts +8 -0
- package/app/server/live/auto-generated-components.ts +1 -1
- package/core/build/index.ts +1 -1
- package/core/cli/command-registry.ts +1 -1
- package/core/cli/commands/build.ts +25 -6
- package/core/cli/commands/plugin-deps.ts +1 -2
- package/core/cli/generators/plugin.ts +433 -581
- package/core/framework/server.ts +22 -8
- package/core/index.ts +6 -5
- package/core/plugins/index.ts +71 -199
- package/core/plugins/types.ts +76 -461
- package/core/server/index.ts +1 -1
- package/core/utils/logger/startup-banner.ts +26 -4
- package/create-fluxstack.ts +216 -107
- package/package.json +108 -107
- package/tsconfig.json +2 -1
- package/core/plugins/config.ts +0 -356
- package/core/plugins/dependency-manager.ts +0 -481
- package/core/plugins/discovery.ts +0 -379
- package/core/plugins/executor.ts +0 -353
- package/core/plugins/manager.ts +0 -645
- package/core/plugins/module-resolver.ts +0 -227
- package/core/plugins/registry.ts +0 -913
- package/vitest.config.live.ts +0 -69
|
@@ -1,20 +1,36 @@
|
|
|
1
1
|
# Plugin System
|
|
2
2
|
|
|
3
|
-
**Version:** 1.
|
|
3
|
+
**Version:** 1.19.0 | **Updated:** 2026-04-14
|
|
4
4
|
|
|
5
5
|
## Quick Facts
|
|
6
6
|
|
|
7
|
-
- Plugin
|
|
7
|
+
- Plugin types/runtime: `@fluxstack/plugin-kit` (v0.4.0) — canonical source
|
|
8
|
+
- Local shim: `core/plugins/types.ts` re-exports with `FluxStackConfig` specialization
|
|
8
9
|
- Registry: `PluginRegistry` manages all plugins
|
|
9
10
|
- Manager: `PluginManager` handles lifecycle and execution
|
|
10
|
-
-
|
|
11
|
-
- Security: Whitelist system for npm plugins
|
|
11
|
+
- Registration: **Manual only** via `.use(plugin)` — no auto-discovery
|
|
12
12
|
- Dependencies: Automatic resolution with topological sort
|
|
13
13
|
|
|
14
|
+
## plugin-kit@0.4.0
|
|
15
|
+
|
|
16
|
+
All plugin types and runtime classes now live in the `@fluxstack/plugin-kit`
|
|
17
|
+
package (extracted from the old `core/plugins/` monolith). The local file
|
|
18
|
+
`core/plugins/types.ts` is a thin re-export shim that specializes the generic
|
|
19
|
+
`Plugin<TConfig>` against `FluxStackConfig`, so existing imports from
|
|
20
|
+
`@core/plugins/types` keep working.
|
|
21
|
+
|
|
22
|
+
Key exports from `@fluxstack/plugin-kit`:
|
|
23
|
+
- **Types**: `Plugin`, `PluginContext`, `PluginHook`, `PluginPriority`, etc.
|
|
24
|
+
- **Runtime**: `PluginRegistry`, `PluginManager`, `PluginExecutor`,
|
|
25
|
+
`PluginModuleResolver`, `PluginDiscovery`
|
|
26
|
+
- **Helpers**: `createPluginUtils`, `createRequestContext`,
|
|
27
|
+
`createResponseContext`, `createErrorContext`, `createBuildContext`
|
|
28
|
+
|
|
14
29
|
## Plugin Interface
|
|
15
30
|
|
|
16
31
|
```typescript
|
|
17
|
-
|
|
32
|
+
// Canonical source: @fluxstack/plugin-kit
|
|
33
|
+
interface Plugin<TConfig = unknown> {
|
|
18
34
|
// Required
|
|
19
35
|
name: string
|
|
20
36
|
|
|
@@ -65,89 +81,82 @@ interface FluxStack.Plugin {
|
|
|
65
81
|
}
|
|
66
82
|
```
|
|
67
83
|
|
|
68
|
-
## Plugin
|
|
84
|
+
## Plugin Registration
|
|
69
85
|
|
|
70
|
-
|
|
86
|
+
Since `@fluxstack/plugin-kit@0.4.0`, **all plugins are registered manually**
|
|
87
|
+
via `.use()`. Auto-discovery from `plugins/` and `node_modules/` was removed
|
|
88
|
+
because it broke silently in production bundles (`dist/node_modules/` does not
|
|
89
|
+
exist after bundling). Every plugin the app uses must be explicitly imported
|
|
90
|
+
and `.use()`-d in the server entry point.
|
|
71
91
|
|
|
72
|
-
|
|
73
|
-
- Part of framework core
|
|
74
|
-
- Manually registered via `.use(plugin)`
|
|
75
|
-
- Examples: vite, swagger, static, live-components
|
|
76
|
-
- No automatic discovery (developer chooses)
|
|
92
|
+
### How It Works
|
|
77
93
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
- Always trusted (no whitelist required)
|
|
82
|
-
- Can have local dependencies
|
|
94
|
+
```typescript
|
|
95
|
+
// app/server/index.ts
|
|
96
|
+
import { FluxStackFramework } from "@core/server"
|
|
83
97
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
- Naming patterns:
|
|
89
|
-
- `fluxstack-plugin-*`
|
|
90
|
-
- `fplugin-*`
|
|
91
|
-
- `@fluxstack/plugin-*`
|
|
92
|
-
- `@fplugin/*`
|
|
93
|
-
- `@org/fluxstack-plugin-*`
|
|
94
|
-
- `@org/fplugin-*`
|
|
95
|
-
|
|
96
|
-
### Discovery Process
|
|
98
|
+
// Built-in plugins (shipped with FluxStack core)
|
|
99
|
+
import { vitePlugin } from "@core/plugins/built-in/vite"
|
|
100
|
+
import { swaggerPlugin } from "@core/plugins/built-in/swagger"
|
|
101
|
+
import { liveComponentsPlugin } from "@core/server/live"
|
|
97
102
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
A[Plugin Discovery] --> B{PLUGINS_DISCOVER_PROJECT?}
|
|
101
|
-
B -->|Yes| C[Scan plugins/ directory]
|
|
102
|
-
B -->|No| D[Skip project plugins]
|
|
103
|
-
C --> E[Load plugin files]
|
|
104
|
-
|
|
105
|
-
A --> F{PLUGINS_DISCOVER_NPM?}
|
|
106
|
-
F -->|Yes| G[Scan node_modules/]
|
|
107
|
-
F -->|No| H[Skip npm plugins]
|
|
108
|
-
G --> I{In PLUGINS_ALLOWED?}
|
|
109
|
-
I -->|Yes| J[Load npm plugin]
|
|
110
|
-
I -->|No| K[Block plugin]
|
|
111
|
-
|
|
112
|
-
E --> L[Register in PluginRegistry]
|
|
113
|
-
J --> L
|
|
114
|
-
L --> M[Resolve dependencies]
|
|
115
|
-
M --> N[Calculate load order]
|
|
116
|
-
N --> O[Execute onConfigLoad hooks]
|
|
117
|
-
```
|
|
103
|
+
// External / NPM plugins — import + .use() explicitly
|
|
104
|
+
import { csrfProtectionPlugin } from "@fluxstack/plugin-csrf-protection"
|
|
118
105
|
|
|
119
|
-
|
|
106
|
+
const framework = new FluxStackFramework()
|
|
107
|
+
.use(swaggerPlugin)
|
|
108
|
+
.use(liveComponentsPlugin)
|
|
109
|
+
.use(csrfProtectionPlugin)
|
|
120
110
|
|
|
121
|
-
|
|
111
|
+
// Conditional registration
|
|
112
|
+
if (appConfig.mode !== 'backend-only') {
|
|
113
|
+
framework.use(vitePlugin)
|
|
114
|
+
}
|
|
122
115
|
|
|
123
|
-
|
|
116
|
+
framework.routes(appInstance)
|
|
117
|
+
await framework.listen()
|
|
118
|
+
```
|
|
124
119
|
|
|
125
|
-
|
|
126
|
-
```bash
|
|
127
|
-
# Enable npm plugin discovery
|
|
128
|
-
PLUGINS_DISCOVER_NPM=true
|
|
120
|
+
### Registration Flow
|
|
129
121
|
|
|
130
|
-
|
|
131
|
-
|
|
122
|
+
```mermaid
|
|
123
|
+
graph TD
|
|
124
|
+
A[Server Entry Point] --> B[import plugin]
|
|
125
|
+
B --> C[framework.use plugin]
|
|
126
|
+
C --> D[PluginRegistry.register]
|
|
127
|
+
D --> E[Resolve dependencies]
|
|
128
|
+
E --> F[Calculate load order]
|
|
129
|
+
F --> G[Execute setup hooks]
|
|
132
130
|
```
|
|
133
131
|
|
|
134
|
-
|
|
135
|
-
- Project plugins (`plugins/`) are **always trusted** (developer added them)
|
|
136
|
-
- NPM plugins (`node_modules/`) **require whitelist** (supply chain protection)
|
|
137
|
-
- Empty whitelist = no npm plugins allowed
|
|
138
|
-
- Blocked plugins logged with warning
|
|
132
|
+
### Plugin Categories
|
|
139
133
|
|
|
140
|
-
**
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
134
|
+
**Built-in Plugins** (`core/plugins/built-in/`):
|
|
135
|
+
- Part of framework core: vite, swagger, static, live-components, monitoring
|
|
136
|
+
- Imported from `@core/plugins/built-in/*`
|
|
137
|
+
- Registered via `.use()`
|
|
144
138
|
|
|
145
|
-
|
|
146
|
-
|
|
139
|
+
**Project Plugins** (`plugins/`):
|
|
140
|
+
- User-created plugins in the project directory
|
|
141
|
+
- Imported with relative paths or path aliases
|
|
142
|
+
- Registered via `.use()`
|
|
147
143
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
144
|
+
**NPM Plugins** (`node_modules/`):
|
|
145
|
+
- Third-party plugins installed via `bun add`
|
|
146
|
+
- Imported by package name (e.g., `@fluxstack/plugin-csrf-protection`)
|
|
147
|
+
- Registered via `.use()`
|
|
148
|
+
- The bundler includes them statically — no runtime filesystem scanning
|
|
149
|
+
|
|
150
|
+
### Why No Auto-Discovery
|
|
151
|
+
|
|
152
|
+
Auto-discovery was removed in plugin-kit@0.4.0 for these reasons:
|
|
153
|
+
|
|
154
|
+
1. **Production bundles break**: `dist/node_modules/` does not exist after
|
|
155
|
+
bundling, so runtime scanning finds nothing in production.
|
|
156
|
+
2. **Implicit behavior**: Plugins activating without explicit code made
|
|
157
|
+
debugging harder and created security concerns.
|
|
158
|
+
3. **Static analysis**: Explicit imports let bundlers tree-shake unused
|
|
159
|
+
plugins and let TypeScript verify types at compile time.
|
|
151
160
|
|
|
152
161
|
## Dependency Resolution
|
|
153
162
|
|
|
@@ -197,7 +206,6 @@ monitoring (priority: -50, deps: [api])
|
|
|
197
206
|
- Manage plugin manifests
|
|
198
207
|
- Calculate load order
|
|
199
208
|
- Validate dependencies
|
|
200
|
-
- Discover plugins from filesystem
|
|
201
209
|
|
|
202
210
|
**Key Methods**:
|
|
203
211
|
```typescript
|
|
@@ -209,8 +217,6 @@ getLoadOrder(): string[]
|
|
|
209
217
|
getDependencies(pluginName: string): string[]
|
|
210
218
|
getDependents(pluginName: string): string[]
|
|
211
219
|
has(name: string): boolean
|
|
212
|
-
discoverPlugins(options: PluginDiscoveryOptions): Promise<PluginLoadResult[]>
|
|
213
|
-
discoverNpmPlugins(): Promise<PluginLoadResult[]>
|
|
214
220
|
```
|
|
215
221
|
|
|
216
222
|
### Plugin Manifest
|
|
@@ -228,7 +234,7 @@ Optional `plugin.json` or `package.json` with `fluxstack` field:
|
|
|
228
234
|
"jsonwebtoken": "^9.0.0"
|
|
229
235
|
},
|
|
230
236
|
"fluxstack": {
|
|
231
|
-
"version": "1.
|
|
237
|
+
"version": "1.19.0",
|
|
232
238
|
"hooks": ["setup", "onRequest", "onBeforeRoute"],
|
|
233
239
|
"category": "security",
|
|
234
240
|
"tags": ["auth", "jwt"]
|
|
@@ -386,23 +392,17 @@ onPluginError: async (context) => {
|
|
|
386
392
|
|
|
387
393
|
## Dependency Management
|
|
388
394
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
**Project Plugins**:
|
|
392
|
-
- Dependencies installed in plugin directory
|
|
393
|
-
- Runs `bun install` in plugin folder
|
|
394
|
-
- Isolated from main project dependencies
|
|
395
|
+
Since all plugins are explicitly imported, their npm dependencies must be
|
|
396
|
+
installed in the project's `package.json` like any other dependency:
|
|
395
397
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
### Missing Dependencies
|
|
398
|
+
```bash
|
|
399
|
+
# Install a plugin and its dependencies
|
|
400
|
+
bun add @fluxstack/plugin-csrf-protection
|
|
401
|
+
```
|
|
402
402
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
403
|
+
Plugin *inter-dependencies* (one plugin depending on another plugin) are
|
|
404
|
+
declared via the `dependencies` array in the plugin object and resolved
|
|
405
|
+
automatically by the registry at startup.
|
|
406
406
|
|
|
407
407
|
## Plugin Validation
|
|
408
408
|
|
|
@@ -432,16 +432,70 @@ If plugin has `configSchema`, validates config against schema:
|
|
|
432
432
|
}
|
|
433
433
|
```
|
|
434
434
|
|
|
435
|
+
## Creating a Plugin
|
|
436
|
+
|
|
437
|
+
### Minimal Example
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
// plugins/my-logger/index.ts
|
|
441
|
+
import type { Plugin } from '@fluxstack/plugin-kit'
|
|
442
|
+
|
|
443
|
+
export const myLoggerPlugin: Plugin = {
|
|
444
|
+
name: 'my-logger',
|
|
445
|
+
version: '1.0.0',
|
|
446
|
+
|
|
447
|
+
setup: async (context) => {
|
|
448
|
+
context.logger.info('My logger plugin initialized')
|
|
449
|
+
},
|
|
450
|
+
|
|
451
|
+
onRequest: async (context) => {
|
|
452
|
+
console.log(`${context.method} ${context.path}`)
|
|
453
|
+
},
|
|
454
|
+
|
|
455
|
+
onServerStop: async () => {
|
|
456
|
+
console.log('Flushing logs...')
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Registering It
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
// app/server/index.ts
|
|
465
|
+
import { myLoggerPlugin } from '../../plugins/my-logger'
|
|
466
|
+
|
|
467
|
+
const framework = new FluxStackFramework()
|
|
468
|
+
.use(myLoggerPlugin)
|
|
469
|
+
// ... other plugins
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Publishing as NPM Package
|
|
473
|
+
|
|
474
|
+
1. Create a package that exports a `Plugin` object
|
|
475
|
+
2. Depend on `@fluxstack/plugin-kit` for types
|
|
476
|
+
3. Consumers install the package and `.use()` it explicitly
|
|
477
|
+
|
|
478
|
+
```bash
|
|
479
|
+
bun add my-fluxstack-plugin
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
import { myPlugin } from 'my-fluxstack-plugin'
|
|
484
|
+
framework.use(myPlugin)
|
|
485
|
+
```
|
|
486
|
+
|
|
435
487
|
## Best Practices
|
|
436
488
|
|
|
437
|
-
1. **
|
|
438
|
-
2. **
|
|
439
|
-
3. **
|
|
440
|
-
4. **
|
|
441
|
-
5. **
|
|
442
|
-
6. **
|
|
443
|
-
7. **
|
|
444
|
-
8. **
|
|
489
|
+
1. **Register explicitly**: Always import and `.use()` every plugin
|
|
490
|
+
2. **Declare inter-dependencies**: List plugin dependencies in the `dependencies` array
|
|
491
|
+
3. **Use Priority**: Set priority for load order control
|
|
492
|
+
4. **Handle Errors**: Implement error hooks for resilience
|
|
493
|
+
5. **Cleanup Resources**: Use `onServerStop` for cleanup
|
|
494
|
+
6. **Avoid Blocking**: Keep hooks fast, use async for I/O
|
|
495
|
+
7. **Log Appropriately**: Use `context.logger` for plugin logs
|
|
496
|
+
8. **Validate Input**: Check context data before use
|
|
497
|
+
9. **Test Isolation**: Ensure plugin works independently
|
|
498
|
+
10. **Use `@fluxstack/plugin-kit`**: Import types from the canonical package
|
|
445
499
|
|
|
446
500
|
## Related
|
|
447
501
|
|