create-fluxstack 1.18.0 → 1.19.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/app/client/src/App.tsx +7 -7
  3. package/app/client/src/components/AppLayout.tsx +60 -23
  4. package/app/client/src/components/ColorWheel.tsx +195 -0
  5. package/app/client/src/components/DemoPage.tsx +5 -3
  6. package/app/client/src/components/LiveUploadWidget.tsx +1 -1
  7. package/app/client/src/components/ThemePicker.tsx +307 -0
  8. package/app/client/src/config/theme.config.ts +127 -0
  9. package/app/client/src/hooks/useThemeClock.ts +66 -0
  10. package/app/client/src/index.css +193 -0
  11. package/app/client/src/lib/theme-clock.ts +201 -0
  12. package/app/client/src/live/AuthDemo.tsx +9 -9
  13. package/app/client/src/live/CounterDemo.tsx +10 -10
  14. package/app/client/src/live/FormDemo.tsx +8 -8
  15. package/app/client/src/live/PingPongDemo.tsx +10 -10
  16. package/app/client/src/live/RoomChatDemo.tsx +10 -10
  17. package/app/client/src/live/SharedCounterDemo.tsx +5 -5
  18. package/app/client/src/pages/ApiTestPage.tsx +5 -5
  19. package/app/client/src/pages/HomePage.tsx +12 -12
  20. package/app/server/index.ts +8 -0
  21. package/app/server/live/auto-generated-components.ts +1 -1
  22. package/app/server/live/rooms/ChatRoom.ts +13 -8
  23. package/app/server/routes/index.ts +20 -10
  24. package/core/build/index.ts +1 -1
  25. package/core/cli/command-registry.ts +1 -1
  26. package/core/cli/commands/build.ts +25 -6
  27. package/core/cli/commands/plugin-deps.ts +1 -2
  28. package/core/cli/generators/plugin.ts +433 -581
  29. package/core/framework/server.ts +34 -8
  30. package/core/index.ts +6 -5
  31. package/core/plugins/index.ts +71 -199
  32. package/core/plugins/types.ts +76 -461
  33. package/core/server/index.ts +1 -1
  34. package/core/utils/logger/startup-banner.ts +26 -4
  35. package/core/utils/version.ts +6 -6
  36. package/create-fluxstack.ts +216 -107
  37. package/package.json +108 -107
  38. package/tsconfig.json +2 -1
  39. package/app/client/.live-stubs/LiveAdminPanel.js +0 -15
  40. package/app/client/.live-stubs/LiveCounter.js +0 -9
  41. package/app/client/.live-stubs/LiveForm.js +0 -11
  42. package/app/client/.live-stubs/LiveLocalCounter.js +0 -8
  43. package/app/client/.live-stubs/LivePingPong.js +0 -10
  44. package/app/client/.live-stubs/LiveRoomChat.js +0 -11
  45. package/app/client/.live-stubs/LiveSharedCounter.js +0 -10
  46. package/app/client/.live-stubs/LiveUpload.js +0 -15
  47. package/core/plugins/config.ts +0 -356
  48. package/core/plugins/dependency-manager.ts +0 -481
  49. package/core/plugins/discovery.ts +0 -379
  50. package/core/plugins/executor.ts +0 -353
  51. package/core/plugins/manager.ts +0 -645
  52. package/core/plugins/module-resolver.ts +0 -227
  53. package/core/plugins/registry.ts +0 -913
  54. package/vitest.config.live.ts +0 -69
@@ -1,463 +1,78 @@
1
- import type { FluxStackConfig } from "@config"
2
- import type { Logger } from "@core/utils/logger/index"
3
-
4
- export type PluginHook =
5
- // Lifecycle hooks
6
- | 'setup'
7
- | 'onConfigLoad'
8
- | 'onBeforeServerStart'
9
- | 'onServerStart'
10
- | 'onAfterServerStart'
11
- | 'onBeforeServerStop'
12
- | 'onServerStop'
13
- // Request/Response pipeline hooks
14
- | 'onRequest'
15
- | 'onBeforeRoute'
16
- | 'onAfterRoute'
17
- | 'onBeforeResponse'
18
- | 'onResponse'
19
- | 'onRequestValidation'
20
- | 'onResponseTransform'
21
- // Error handling hooks
22
- | 'onError'
23
- // Build pipeline hooks
24
- | 'onBeforeBuild'
25
- | 'onBuild'
26
- | 'onBuildAsset'
27
- | 'onBuildComplete'
28
- | 'onBuildError'
29
- // Plugin system hooks
30
- | 'onPluginRegister'
31
- | 'onPluginUnregister'
32
- | 'onPluginError'
33
-
34
- export type PluginPriority = 'highest' | 'high' | 'normal' | 'low' | 'lowest' | number
35
-
36
- export interface PluginClientHooksAPI {
37
- /**
38
- * Register JavaScript code to be executed on the client at a specific hook point.
39
- *
40
- * Built-in hook points:
41
- * - 'onEdenInit' — runs after the Eden Treaty client is created
42
- * - 'onLiveConnect' — runs when the LiveComponents WebSocket connects
43
- *
44
- * @param hookName - The hook point name
45
- * @param jsCode - JavaScript code string to execute on the client
46
- */
47
- register(hookName: string, jsCode: string): void
48
- }
49
-
50
- export interface PluginContext {
51
- config: FluxStackConfig
52
- logger: Logger
53
- app: unknown // Elysia app
54
- utils: PluginUtils
55
- registry?: unknown // Plugin registry reference
56
- /** Register client-side JS hooks that plugins can inject */
57
- clientHooks: PluginClientHooksAPI
58
- }
59
-
60
- export interface PluginUtils {
61
- // Utility functions that plugins can use
62
- createTimer: (label: string) => { end: () => number }
63
- formatBytes: (bytes: number) => string
64
- isProduction: () => boolean
65
- isDevelopment: () => boolean
66
- getEnvironment: () => string
67
- createHash: (data: string) => string
68
- deepMerge: (target: Record<string, unknown>, source: Record<string, unknown>) => Record<string, unknown>
69
- validateSchema: (data: Record<string, unknown>, schema: PluginConfigSchema) => { valid: boolean; errors: string[] }
70
- }
71
-
72
- export interface RequestContext {
73
- request: Request
74
- path: string
75
- method: string
76
- headers: Record<string, string>
77
- query: Record<string, string>
78
- params: Record<string, string>
79
- body?: unknown
80
- user?: unknown
81
- startTime: number
82
- handled?: boolean
83
- response?: Response
84
- }
85
-
86
- export interface ResponseContext extends RequestContext {
87
- response: Response
88
- statusCode: number
89
- duration: number
90
- size?: number
91
- }
92
-
93
- export interface ErrorContext extends RequestContext {
94
- error: Error
95
- duration: number
96
- handled: boolean
97
- }
98
-
99
- export interface BuildContext {
100
- target: string
101
- outDir: string
102
- mode: 'development' | 'production'
103
- config: FluxStackConfig
104
- }
105
-
106
- export interface ConfigLoadContext {
107
- config: FluxStackConfig
108
- envVars: Record<string, string | undefined>
109
- configPath?: string
110
- }
111
-
112
- export interface RouteContext extends RequestContext {
113
- route?: string
114
- handler?: Function
115
- params: Record<string, string>
116
- }
117
-
118
- export interface ValidationContext extends RequestContext {
119
- errors: Array<{ field: string; message: string; code: string }>
120
- isValid: boolean
121
- }
122
-
123
- export interface TransformContext extends ResponseContext {
124
- transformed: boolean
125
- originalResponse?: Response
126
- }
127
-
128
- export interface BuildAssetContext {
129
- assetPath: string
130
- assetType: 'js' | 'css' | 'html' | 'image' | 'font' | 'other'
131
- size: number
132
- content?: string | Buffer
133
- }
134
-
135
- export interface BuildErrorContext {
136
- error: Error
137
- file?: string
138
- line?: number
139
- column?: number
140
- }
141
-
142
- export interface PluginEventContext {
143
- pluginName: string
144
- pluginVersion?: string
145
- timestamp: number
146
- data?: unknown
147
- }
148
-
149
- export interface PluginConfigSchema {
150
- type: 'object'
151
- properties: Record<string, unknown>
152
- required?: string[]
153
- additionalProperties?: boolean
154
- }
155
-
1
+ /**
2
+ * FluxStack plugin types thin re-export layer over @fluxstack/plugin-kit.
3
+ *
4
+ * Historically this file was the canonical source. As of the plugin-kit
5
+ * extraction (see .ai-notes/plans/2026-04-11-plugin-kit-extraction.md),
6
+ * the canonical source is `@fluxstack/plugin-kit`. This file exists to:
7
+ *
8
+ * 1. Preserve every existing `import ... from '@core/plugins/types'` call
9
+ * site in the FluxStack app — no downstream code needs to change.
10
+ * 2. Specialize the generic `<TConfig>` parameters against FluxStack's
11
+ * concrete `FluxStackConfig`, so consumers get full autocomplete
12
+ * against the app's real config shape.
13
+ *
14
+ * Future PRs will migrate individual call sites to import directly from
15
+ * `@fluxstack/plugin-kit` and this shim will eventually be deleted.
16
+ */
17
+
18
+ import type { FluxStackConfig } from '@config'
19
+ import type {
20
+ Plugin as BasePlugin,
21
+ PluginContext as BasePluginContext,
22
+ BuildContext as BaseBuildContext,
23
+ ConfigLoadContext as BaseConfigLoadContext,
24
+ CliCommand as BaseCliCommand,
25
+ CliContext as BaseCliContext,
26
+ PluginLoadResult as BasePluginLoadResult,
27
+ PluginRegistryState as BasePluginRegistryState,
28
+ PluginExecutionContext as BasePluginExecutionContext,
29
+ } from '@fluxstack/plugin-kit'
30
+
31
+ // ─── Specialized generics (FluxStack passes FluxStackConfig everywhere) ───
32
+
33
+ export type Plugin = BasePlugin<FluxStackConfig>
34
+ export type PluginContext = BasePluginContext<FluxStackConfig>
35
+ export type BuildContext = BaseBuildContext<FluxStackConfig>
36
+ export type ConfigLoadContext = BaseConfigLoadContext<FluxStackConfig>
37
+ export type CliCommand = BaseCliCommand<FluxStackConfig>
38
+ export type CliContext = BaseCliContext<FluxStackConfig>
39
+ export type PluginLoadResult = BasePluginLoadResult<FluxStackConfig>
40
+ export type PluginRegistryState = BasePluginRegistryState<FluxStackConfig>
41
+ export type PluginExecutionContext = BasePluginExecutionContext<FluxStackConfig>
42
+
43
+ // ─── Straight re-exports (no generic to specialize) ───
44
+
45
+ export type {
46
+ Logger,
47
+ PluginHook,
48
+ PluginPriority,
49
+ PluginLifecycleEvent,
50
+ HookExecutionOptions,
51
+ PluginClientHooksAPI,
52
+ PluginUtils,
53
+ PluginConfigSchema,
54
+ RequestContext,
55
+ ResponseContext,
56
+ ErrorContext,
57
+ RouteContext,
58
+ ValidationContext,
59
+ TransformContext,
60
+ BuildAssetContext,
61
+ BuildErrorContext,
62
+ PluginEventContext,
63
+ CliArgument,
64
+ CliOption,
65
+ PluginManifest,
66
+ PluginHookResult,
67
+ PluginMetrics,
68
+ PluginDiscoveryOptions,
69
+ PluginInstallOptions,
70
+ PluginValidationResult,
71
+ } from '@fluxstack/plugin-kit'
72
+
73
+ // ─── Namespace backward-compat ───
74
+ // Legacy code uses `FluxStack.Plugin` — keep that form working.
75
+ // eslint-disable-next-line @typescript-eslint/no-namespace
156
76
  export namespace FluxStack {
157
- export interface Plugin {
158
- name: string
159
- version?: string
160
- description?: string
161
- author?: string
162
- dependencies?: string[]
163
- priority?: number | PluginPriority
164
- category?: string
165
- tags?: string[]
166
-
167
- // Lifecycle hooks
168
- setup?: (context: PluginContext) => void | Promise<void>
169
- onConfigLoad?: (context: ConfigLoadContext) => void | Promise<void>
170
- onBeforeServerStart?: (context: PluginContext) => void | Promise<void>
171
- onServerStart?: (context: PluginContext) => void | Promise<void>
172
- onAfterServerStart?: (context: PluginContext) => void | Promise<void>
173
- onBeforeServerStop?: (context: PluginContext) => void | Promise<void>
174
- onServerStop?: (context: PluginContext) => void | Promise<void>
175
-
176
- // Request/Response pipeline hooks
177
- onRequest?: (context: RequestContext) => void | Promise<void>
178
- onBeforeRoute?: (context: RequestContext) => void | Promise<void>
179
- onAfterRoute?: (context: RouteContext) => void | Promise<void>
180
- onBeforeResponse?: (context: ResponseContext) => void | Promise<void>
181
- onResponse?: (context: ResponseContext) => void | Promise<void>
182
- onRequestValidation?: (context: ValidationContext) => void | Promise<void>
183
- onResponseTransform?: (context: TransformContext) => void | Promise<void>
184
-
185
- // Error handling hooks
186
- onError?: (context: ErrorContext) => void | Promise<void>
187
-
188
- // Build pipeline hooks
189
- onBeforeBuild?: (context: BuildContext) => void | Promise<void>
190
- onBuild?: (context: BuildContext) => void | Promise<void>
191
- onBuildAsset?: (context: BuildAssetContext) => void | Promise<void>
192
- onBuildComplete?: (context: BuildContext) => void | Promise<void>
193
- onBuildError?: (context: BuildErrorContext) => void | Promise<void>
194
-
195
- // Plugin system hooks
196
- onPluginRegister?: (context: PluginEventContext) => void | Promise<void>
197
- onPluginUnregister?: (context: PluginEventContext) => void | Promise<void>
198
- onPluginError?: (context: PluginEventContext & { error: Error }) => void | Promise<void>
199
-
200
- // Configuration
201
- /**
202
- * @deprecated Use declarative config system instead (plugins/[name]/config/)
203
- * Create a config/ folder with defineConfig() for type-safe configuration.
204
- * This property is kept for backward compatibility with built-in plugins.
205
- *
206
- * @example
207
- * // ✅ New way (recommended):
208
- * // plugins/my-plugin/config/index.ts
209
- * import { defineConfig, config } from '@fluxstack/config'
210
- * export const myConfig = defineConfig({ ... })
211
- *
212
- * // ❌ Old way (deprecated):
213
- * configSchema: { type: 'object', properties: { ... } }
214
- */
215
- configSchema?: PluginConfigSchema
216
-
217
- /**
218
- * @deprecated Use declarative config system with defineConfig()
219
- * This property will be removed in a future major version.
220
- * Use the config/ folder structure for automatic type inference.
221
- */
222
- defaultConfig?: unknown
223
-
224
- // CLI commands
225
- commands?: CliCommand[]
226
- }
227
- }
228
-
229
-
230
- export interface PluginManifest {
231
- name: string
232
- version: string
233
- description: string
234
- author: string
235
- license: string
236
- homepage?: string
237
- repository?: string
238
- keywords: string[]
239
- dependencies: Record<string, string>
240
- peerDependencies?: Record<string, string>
241
- fluxstack: {
242
- version: string
243
- hooks: PluginHook[]
244
- config?: PluginConfigSchema
245
- category?: string
246
- tags?: string[]
247
- }
248
- }
249
-
250
- export interface PluginLoadResult {
251
- success: boolean
252
- plugin?: FluxStack.Plugin
253
- error?: string
254
- warnings?: string[]
255
- }
256
-
257
- export interface PluginRegistryState {
258
- plugins: Map<string, FluxStack.Plugin>
259
- manifests: Map<string, PluginManifest>
260
- loadOrder: string[]
261
- dependencies: Map<string, string[]>
262
- conflicts: string[]
263
- }
264
-
265
- export interface PluginHookResult {
266
- success: boolean
267
- error?: Error
268
- duration: number
269
- plugin: string
270
- hook: PluginHook
271
- context?: unknown
272
- }
273
-
274
- export interface PluginMetrics {
275
- loadTime: number
276
- setupTime: number
277
- hookExecutions: Map<PluginHook, number>
278
- errors: number
279
- warnings: number
280
- lastExecution?: Date
281
- }
282
-
283
- export interface PluginDiscoveryOptions {
284
- directories?: string[]
285
- patterns?: string[]
286
- includeBuiltIn?: boolean
287
- includeExternal?: boolean
288
- includeNpm?: boolean
289
- }
290
-
291
- export interface PluginInstallOptions {
292
- version?: string
293
- registry?: string
294
- force?: boolean
295
- dev?: boolean
296
- source?: 'npm' | 'git' | 'local'
297
- }
298
-
299
- export interface PluginExecutionContext {
300
- plugin: FluxStack.Plugin
301
- hook: PluginHook
302
- startTime: number
303
- timeout?: number
304
- retries?: number
305
- }
306
-
307
- export interface PluginValidationResult {
308
- valid: boolean
309
- errors: string[]
310
- warnings: string[]
311
- }
312
-
313
- // Plugin hook execution options
314
- export interface HookExecutionOptions {
315
- timeout?: number
316
- parallel?: boolean
317
- stopOnError?: boolean
318
- retries?: number
319
- }
320
-
321
- // Plugin lifecycle events
322
- export type PluginLifecycleEvent =
323
- | 'plugin:registered'
324
- | 'plugin:unregistered'
325
- | 'plugin:enabled'
326
- | 'plugin:disabled'
327
- | 'plugin:error'
328
- | 'hook:before'
329
- | 'hook:after'
330
- | 'hook:error'
331
-
332
- // CLI Command interfaces
333
- export interface CliArgument {
334
- name: string
335
- description: string
336
- required?: boolean
337
- type?: 'string' | 'number' | 'boolean'
338
- default?: unknown
339
- choices?: string[]
77
+ export type Plugin = BasePlugin<FluxStackConfig>
340
78
  }
341
-
342
- export interface CliOption {
343
- name: string
344
- short?: string
345
- description: string
346
- type?: 'string' | 'number' | 'boolean' | 'array'
347
- default?: unknown
348
- required?: boolean
349
- choices?: string[]
350
- }
351
-
352
- export interface CliCommand {
353
- name: string
354
- description: string
355
- usage?: string
356
- examples?: string[]
357
- arguments?: CliArgument[]
358
- options?: CliOption[]
359
- aliases?: string[]
360
- category?: string
361
- hidden?: boolean
362
- handler: (args: unknown[], options: Record<string, unknown>, context: CliContext) => Promise<void> | void
363
- }
364
-
365
- export interface CliContext {
366
- config: FluxStackConfig
367
- logger: Logger
368
- utils: PluginUtils
369
- workingDir: string
370
- packageInfo: {
371
- name: string
372
- version: string
373
- }
374
- }
375
-
376
- // Live Components Types - Re-exported from core/types/types.ts
377
- // See core/types/types.ts for full implementation
378
- // Note: These are re-exported at the end of this file
379
-
380
- // File Upload Types
381
- export interface ActiveUpload {
382
- uploadId: string
383
- componentId?: string
384
- filename: string
385
- fileType?: string
386
- fileSize?: number
387
- totalChunks: number
388
- receivedChunks: Map<number, unknown>
389
- startTime: number
390
- lastChunkTime?: number
391
- }
392
-
393
- export interface FileUploadStartMessage {
394
- type: 'upload:start' | 'FILE_UPLOAD_START'
395
- uploadId: string
396
- filename: string
397
- totalChunks: number
398
- fileSize: number
399
- componentId?: string
400
- fileType?: string
401
- chunkSize?: number
402
- requestId?: string
403
- }
404
-
405
- export interface FileUploadChunkMessage {
406
- type: 'upload:chunk' | 'FILE_UPLOAD_CHUNK'
407
- uploadId: string
408
- chunkIndex: number
409
- data: string | ArrayBuffer
410
- totalChunks?: number
411
- componentId?: string
412
- requestId?: string
413
- }
414
-
415
- export interface FileUploadCompleteMessage {
416
- type: 'upload:complete' | 'FILE_UPLOAD_COMPLETE'
417
- uploadId: string
418
- requestId?: string
419
- }
420
-
421
- export interface FileUploadProgressResponse {
422
- type: 'upload:progress' | 'FILE_UPLOAD_PROGRESS'
423
- uploadId: string
424
- receivedChunks?: number
425
- totalChunks?: number
426
- percentage?: number
427
- componentId?: string
428
- chunkIndex?: number
429
- bytesUploaded?: number
430
- totalBytes?: number
431
- progress?: number
432
- timestamp?: number
433
- }
434
-
435
- export interface FileUploadCompleteResponse {
436
- type: 'upload:complete' | 'FILE_UPLOAD_COMPLETE'
437
- uploadId: string
438
- url?: string
439
- filename?: string
440
- size?: number
441
- componentId?: string
442
- success?: boolean
443
- error?: string
444
- message?: string
445
- fileUrl?: string
446
- timestamp?: number
447
- }
448
-
449
- // Plugin Type Export
450
- export type Plugin = FluxStack.Plugin
451
-
452
- // Re-export all WebSocket and LiveComponent types from core/types/types.ts
453
- export {
454
- LiveComponent,
455
- type FluxStackWebSocket,
456
- type FluxStackWSData,
457
- type FluxStackServerWebSocket,
458
- type LiveMessage,
459
- type BroadcastMessage,
460
- type ComponentState,
461
- type ComponentDefinition,
462
- type WebSocketData
463
- } from '@core/types/types'
@@ -2,7 +2,7 @@
2
2
  export { FluxStackFramework } from "../framework/server"
3
3
  export { vitePlugin } from "../plugins/built-in"
4
4
  export { swaggerPlugin } from "../plugins/built-in/swagger"
5
- export { PluginRegistry } from "../plugins/registry"
5
+ export { PluginRegistry } from "@fluxstack/plugin-kit"
6
6
  export * from "../types"
7
7
 
8
8
  // Live Components exports
@@ -22,6 +22,17 @@ export interface StartupInfo {
22
22
  viteEmbedded?: boolean // true when Vite runs programmatically with backend
23
23
  swaggerPath?: string
24
24
  liveComponents?: string[]
25
+ /**
26
+ * List of registered plugins to display. If omitted, falls back to
27
+ * the legacy `globalThis.__fluxstackPlugins` convention for backwards
28
+ * compatibility with plugins that still push themselves there.
29
+ *
30
+ * Prefer passing this explicitly — read it from the PluginRegistry
31
+ * (`framework.getPluginRegistry().getAll()`) so the banner reflects
32
+ * exactly what's in the registry, not what each plugin manually
33
+ * decided to advertise.
34
+ */
35
+ plugins?: Array<{ name: string }>
25
36
  }
26
37
 
27
38
  /**
@@ -43,8 +54,14 @@ export function displayStartupBanner(info: StartupInfo): void {
43
54
  const displayHost = host === '0.0.0.0' ? 'localhost' : host
44
55
  const serverUrl = `http://${displayHost}:${port}`
45
56
 
46
- // Simple ready message with URL
47
- console.log(chalk.green('\nServer ready!') + chalk.gray(` Environment: ${environment}${viteEmbedded ? ' | Vite: embedded' : ''}`))
57
+ // Simple ready message with URL.
58
+ // "Vite: embedded" only makes sense in development, where the vite
59
+ // plugin actually runs the Vite dev server. In production, the same
60
+ // plugin acts as a static-file fallback (serving the compiled
61
+ // dist/client bundle), so the "Vite: embedded" label is misleading.
62
+ const isDev = environment === 'development'
63
+ const viteLabel = viteEmbedded && isDev ? ' | Vite: embedded' : ''
64
+ console.log(chalk.green('\nServer ready!') + chalk.gray(` Environment: ${environment}${viteLabel}`))
48
65
  console.log(chalk.cyan(` → ${serverUrl}`))
49
66
 
50
67
  // Display Live Components
@@ -52,8 +69,13 @@ export function displayStartupBanner(info: StartupInfo): void {
52
69
  console.log(chalk.gray(` Live Components (${liveComponents.length}): `) + chalk.yellow(liveComponents.join(', ')))
53
70
  }
54
71
 
55
- // Display plugins in compact format
56
- const plugins = ((globalThis as Record<string, unknown>).__fluxstackPlugins || []) as Array<{ name: string }>
72
+ // Display plugins in compact format. Prefer the explicit list from
73
+ // info.plugins (read from the PluginRegistry); fall back to the
74
+ // legacy global convention if the caller didn't pass anything.
75
+ const plugins =
76
+ info.plugins ??
77
+ (((globalThis as Record<string, unknown>).__fluxstackPlugins ||
78
+ []) as Array<{ name: string }>)
57
79
  if (plugins.length > 0) {
58
80
  const pluginList = plugins.map((p) => p.name).join(', ')
59
81
  console.log(chalk.gray(` Plugins (${plugins.length}): `) + chalk.magenta(pluginList))
@@ -1,6 +1,6 @@
1
- /**
2
- * FluxStack Framework Version
3
- * Single source of truth for version number
4
- * Auto-synced with package.json
5
- */
6
- export const FLUXSTACK_VERSION = '1.18.0'
1
+ /**
2
+ * FluxStack Framework Version
3
+ * Single source of truth for version number
4
+ * Auto-synced with package.json
5
+ */
6
+ export const FLUXSTACK_VERSION = '1.19.0'