create-fluxstack 1.21.1 → 1.22.1
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/app/client/src/App.tsx +9 -11
- package/app/client/src/components/AppLayout.tsx +291 -290
- package/app/client/src/components/BackButton.tsx +17 -16
- package/app/client/src/components/ColorWheel.tsx +1 -0
- package/app/client/src/components/DemoPage.tsx +136 -135
- package/app/client/src/components/ErrorBoundary.tsx +2 -1
- package/app/client/src/components/LiveErrorBoundary.tsx +2 -1
- package/app/client/src/components/ThemePicker.tsx +1 -0
- package/app/client/src/framework/ClientOnly.tsx +14 -0
- package/app/client/src/framework/LivePage.tsx +55 -0
- package/app/client/src/framework/RscHomePage.tsx +125 -0
- package/app/client/src/framework/RscLink.tsx +31 -0
- package/app/client/src/framework/RscNav.tsx +42 -0
- package/app/client/src/framework/RscRoot.tsx +54 -0
- package/app/client/src/framework/csrf.ts +22 -0
- package/app/client/src/framework/entry.browser.tsx +51 -0
- package/app/client/src/framework/entry.rsc.tsx +41 -0
- package/app/client/src/framework/entry.ssr.tsx +12 -0
- package/app/client/src/framework/navigation.ts +29 -0
- package/app/client/src/framework/params.tsx +22 -0
- package/app/client/src/framework/routes.ts +143 -0
- package/app/client/src/framework/vite-rsc.d.ts +21 -0
- package/app/client/src/hooks/useThemeClock.ts +16 -1
- package/app/client/src/live/AuthDemo.tsx +271 -270
- package/app/client/src/live/CounterDemo.tsx +152 -151
- package/app/client/src/live/FormDemo.tsx +141 -140
- package/app/client/src/live/PingPongDemo.tsx +181 -180
- package/app/client/src/live/RoomChatDemo.tsx +398 -397
- package/app/client/src/live/SharedCounterDemo.tsx +2 -1
- package/app/client/src/pages/ApiTestPage.tsx +1 -0
- package/app/client/src/pages/auth.tsx +13 -0
- package/app/client/src/pages/blog/[slug].tsx +23 -0
- package/app/client/src/pages/counter.tsx +15 -0
- package/app/client/src/pages/form.tsx +13 -0
- package/app/client/src/pages/index.tsx +9 -0
- package/app/client/src/pages/ping-pong.tsx +13 -0
- package/app/client/src/pages/room-chat.tsx +13 -0
- package/app/client/src/pages/shared-counter.tsx +13 -0
- package/app/client/src/pages/sobre.tsx +19 -0
- package/app/server/index.ts +5 -1
- package/app/server/live/rooms/index.ts +14 -0
- package/config/system/plugins.config.ts +12 -2
- package/core/cli/commands/dev.ts +9 -1
- package/core/plugins/built-in/rsc/index.ts +156 -0
- package/core/plugins/built-in/ssr/bun-asset-loader.ts +46 -0
- package/core/plugins/built-in/ssr/index.ts +143 -0
- package/core/plugins/built-in/ssr/registry.ts +38 -0
- package/core/plugins/built-in/vite/index.ts +7 -0
- package/core/server/live/websocket-plugin.ts +29 -10
- package/core/utils/version.ts +6 -6
- package/create-fluxstack.ts +64 -5
- package/package.json +112 -108
- package/playwright.config.ts +6 -2
- package/vite.config.ts +22 -0
- package/app/client/.live-stubs/LiveUpload.js +0 -15
|
@@ -26,24 +26,43 @@ export const liveComponentsPlugin: Plugin = {
|
|
|
26
26
|
tags: ['websocket', 'real-time', 'live-components'],
|
|
27
27
|
|
|
28
28
|
setup: async (context: PluginContext) => {
|
|
29
|
-
|
|
29
|
+
const isProd = process.env.NODE_ENV === 'production'
|
|
30
30
|
const componentsPath = path.join(process.cwd(), 'app', 'server', 'live')
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
|
|
32
|
+
// Em DEV: (re)gera o auto-generated-components.ts varrendo o disco.
|
|
33
|
+
// Em PROD: o app/server/live não existe no dist — o registro estático já
|
|
34
|
+
// foi gerado no build e bundlado. Pular a geração (evita erro de FS).
|
|
35
|
+
if (!isProd) {
|
|
36
|
+
generateLiveComponentsFile({
|
|
37
|
+
componentsDir: componentsPath,
|
|
38
|
+
outFile: path.join(__dirname, 'auto-generated-components.ts'),
|
|
39
|
+
importPrefix: '@app/server/live',
|
|
40
|
+
})
|
|
41
|
+
}
|
|
36
42
|
const { liveComponentClasses } = await import('./auto-generated-components')
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
// dual-Elysia: FluxStack tem elysia@1.4.7, @fluxstack/live-elysia (monorepo
|
|
45
|
+
// linkado) tem elysia@1.4.28 — tipos de instâncias DIFERENTES, mesma API em
|
|
46
|
+
// runtime. `as never` neutraliza o mismatch de tipo no argumento.
|
|
47
|
+
const transport = new ElysiaTransport(context.app as never)
|
|
39
48
|
|
|
40
|
-
//
|
|
49
|
+
// Rooms: em DEV, auto-descobre varrendo rooms/ (import do disco). Em PROD,
|
|
50
|
+
// usa o registro ESTÁTICO (@app/server/live/rooms) — import do disco em prod
|
|
51
|
+
// carregaria uma instância separada do @fluxstack/live (context null). O
|
|
52
|
+
// registro estático entra no bundle com o context único do LiveServer.
|
|
41
53
|
const roomsPath = path.join(componentsPath, 'rooms')
|
|
42
|
-
const discoveredRooms =
|
|
54
|
+
const discoveredRooms = isProd
|
|
55
|
+
? (await import('@app/server/live/rooms')).liveRoomClasses as LiveRoomClass[]
|
|
56
|
+
: await discoverRoomClasses(roomsPath)
|
|
43
57
|
|
|
44
58
|
liveServer = new LiveServer({
|
|
45
59
|
transport,
|
|
46
|
-
componentsPath
|
|
60
|
+
// SÓ em dev: componentsPath dispara o auto-discover dinâmico (import() do
|
|
61
|
+
// disco). Em PROD isso carrega os componentes de uma instância SEPARADA do
|
|
62
|
+
// @fluxstack/live (source linkado), com _ctx null → "LiveServer.start() must
|
|
63
|
+
// be called". Em prod usamos APENAS o registro estático (components), que
|
|
64
|
+
// está no mesmo bundle onde start() setou o context.
|
|
65
|
+
...(isProd ? {} : { componentsPath }),
|
|
47
66
|
wsPath: '/api/live/ws',
|
|
48
67
|
httpPrefix: '/api/live',
|
|
49
68
|
rooms: [...discoveredRooms, ...pendingRoomClasses],
|
package/core/utils/version.ts
CHANGED
|
@@ -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.
|
|
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.22.1'
|
package/create-fluxstack.ts
CHANGED
|
@@ -35,8 +35,12 @@ import { resolve, join, basename } from 'path'
|
|
|
35
35
|
import { existsSync, mkdirSync, cpSync, writeFileSync, readFileSync, readdirSync } from 'fs'
|
|
36
36
|
import chalk from 'chalk'
|
|
37
37
|
import ora from 'ora'
|
|
38
|
+
import prompts from 'prompts'
|
|
38
39
|
import { FLUXSTACK_VERSION } from './core/utils/version'
|
|
39
40
|
|
|
41
|
+
/** Modo de renderização do projeto criado. */
|
|
42
|
+
type RenderMode = 'spa' | 'ssr'
|
|
43
|
+
|
|
40
44
|
const logo = `
|
|
41
45
|
⚡ ███████ ██ ██ ██ ██ ██ ███████ ████████ █████ ██████ ██ ██
|
|
42
46
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
|
@@ -52,20 +56,67 @@ program
|
|
|
52
56
|
.name('create-fluxstack')
|
|
53
57
|
.description('⚡ Create FluxStack apps with zero configuration')
|
|
54
58
|
.version(FLUXSTACK_VERSION)
|
|
55
|
-
.argument('[project-name]', 'Name of the project to create')
|
|
59
|
+
.argument('[project-name]', 'Name of the project to create (use "." for current dir; omit for interactive mode)')
|
|
56
60
|
.option('--no-install', 'Skip dependency installation')
|
|
57
61
|
.option('--no-git', 'Skip git initialization')
|
|
62
|
+
.option('--mode <mode>', 'Render mode: "spa" or "ssr" (skips the prompt)')
|
|
58
63
|
.action(async (projectName, options) => {
|
|
59
64
|
console.clear()
|
|
60
65
|
console.log(chalk.magenta(logo))
|
|
61
66
|
|
|
67
|
+
// ── Modo INTERATIVO: sem project-name → pergunta tudo pelo terminal ──
|
|
68
|
+
// create-fluxstack . → cria na pasta atual
|
|
69
|
+
// create-fluxstack my-app → cria em ./my-app
|
|
70
|
+
// create-fluxstack → menu interativo (pergunta nome + modo)
|
|
71
|
+
let renderMode: RenderMode | undefined =
|
|
72
|
+
options.mode === 'spa' || options.mode === 'ssr' ? options.mode : undefined
|
|
73
|
+
|
|
62
74
|
if (!projectName || projectName.trim().length === 0) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
75
|
+
const answers = await prompts(
|
|
76
|
+
[
|
|
77
|
+
{
|
|
78
|
+
type: 'text',
|
|
79
|
+
name: 'projectName',
|
|
80
|
+
message: 'Nome do projeto (use "." para a pasta atual):',
|
|
81
|
+
initial: 'my-fluxstack-app',
|
|
82
|
+
validate: (v: string) => (v && v.trim().length > 0 ? true : 'Informe um nome ou "."'),
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
type: renderMode ? null : 'select',
|
|
86
|
+
name: 'mode',
|
|
87
|
+
message: 'Modo de renderização:',
|
|
88
|
+
choices: [
|
|
89
|
+
{ title: 'SSR (RSC)', description: 'Server-rendered + React Server Components + ilhas Live (padrão)', value: 'ssr' },
|
|
90
|
+
{ title: 'SPA', description: 'Client-side puro (mais simples)', value: 'spa' },
|
|
91
|
+
],
|
|
92
|
+
initial: 0, // SSR é o padrão
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
{ onCancel: () => { console.log(chalk.gray('\nCancelado.')); process.exit(0) } },
|
|
96
|
+
)
|
|
97
|
+
projectName = answers.projectName
|
|
98
|
+
renderMode = renderMode ?? (answers.mode as RenderMode)
|
|
99
|
+
} else if (!renderMode) {
|
|
100
|
+
// Tem nome mas não passou --mode → pergunta só o modo.
|
|
101
|
+
const { mode } = await prompts(
|
|
102
|
+
{
|
|
103
|
+
type: 'select',
|
|
104
|
+
name: 'mode',
|
|
105
|
+
message: 'Modo de renderização:',
|
|
106
|
+
choices: [
|
|
107
|
+
{ title: 'SSR (RSC)', description: 'Server-rendered + React Server Components + ilhas Live (padrão)', value: 'ssr' },
|
|
108
|
+
{ title: 'SPA', description: 'Client-side puro (mais simples)', value: 'spa' },
|
|
109
|
+
],
|
|
110
|
+
initial: 0, // SSR é o padrão
|
|
111
|
+
},
|
|
112
|
+
{ onCancel: () => { console.log(chalk.gray('\nCancelado.')); process.exit(0) } },
|
|
113
|
+
)
|
|
114
|
+
renderMode = (mode as RenderMode) ?? 'ssr'
|
|
67
115
|
}
|
|
68
116
|
|
|
117
|
+
// SSR é o padrão do FluxStack; SPA continua disponível via escolha/--mode.
|
|
118
|
+
renderMode = renderMode ?? 'ssr'
|
|
119
|
+
|
|
69
120
|
const currentDir = import.meta.dir
|
|
70
121
|
|
|
71
122
|
// Normalize path: remove trailing slashes (which may indicate current dir usage like path/.)
|
|
@@ -105,6 +156,7 @@ program
|
|
|
105
156
|
|
|
106
157
|
console.log(chalk.cyan(`\n🚀 Creating FluxStack project: ${chalk.bold(displayName)}`))
|
|
107
158
|
console.log(chalk.gray(`📁 Location: ${projectPath}`))
|
|
159
|
+
console.log(chalk.gray(`🎨 Render mode: ${chalk.bold(renderMode === 'ssr' ? 'SSR (RSC)' : 'SPA')}`))
|
|
108
160
|
|
|
109
161
|
// Create project directory
|
|
110
162
|
const spinner = ora('Creating project structure...').start()
|
|
@@ -427,6 +479,13 @@ bun.lockb
|
|
|
427
479
|
envContent = envContent.replace('NODE_ENV=production', 'NODE_ENV=development')
|
|
428
480
|
// Customize app name to match project name
|
|
429
481
|
envContent = envContent.replace('VITE_APP_NAME=FluxStack', `VITE_APP_NAME=${actualProjectName}`)
|
|
482
|
+
// Render mode escolhido: liga RSC (SSR) ou mantém SPA.
|
|
483
|
+
const rscLine = `\n# Render mode (escolhido na criação): RSC/SSR liga server-rendering\nRSC_ENABLED=${renderMode === 'ssr' ? 'true' : 'false'}\n`
|
|
484
|
+
if (/^RSC_ENABLED=/m.test(envContent)) {
|
|
485
|
+
envContent = envContent.replace(/^RSC_ENABLED=.*$/m, `RSC_ENABLED=${renderMode === 'ssr' ? 'true' : 'false'}`)
|
|
486
|
+
} else {
|
|
487
|
+
envContent += rscLine
|
|
488
|
+
}
|
|
430
489
|
writeFileSync(envPath, envContent)
|
|
431
490
|
}
|
|
432
491
|
|
package/package.json
CHANGED
|
@@ -1,108 +1,112 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "create-fluxstack",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "⚡ Revolutionary full-stack TypeScript framework with Declarative Config System, Elysia + React + Bun",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"framework",
|
|
7
|
-
"full-stack",
|
|
8
|
-
"typescript",
|
|
9
|
-
"elysia",
|
|
10
|
-
"react",
|
|
11
|
-
"bun",
|
|
12
|
-
"vite"
|
|
13
|
-
],
|
|
14
|
-
"author": "FluxStack Team",
|
|
15
|
-
"license": "MIT",
|
|
16
|
-
"homepage": "https://github.com/MarcosBrendonDePaula/FluxStack",
|
|
17
|
-
"repository": {
|
|
18
|
-
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/MarcosBrendonDePaula/FluxStack.git"
|
|
20
|
-
},
|
|
21
|
-
"module": "app/server/index.ts",
|
|
22
|
-
"type": "module",
|
|
23
|
-
"bin": {
|
|
24
|
-
"create-fluxstack": "create-fluxstack.ts"
|
|
25
|
-
},
|
|
26
|
-
"scripts": {
|
|
27
|
-
"dev": "bun run core/cli/index.ts dev",
|
|
28
|
-
"dev:frontend": "bun run core/cli/index.ts dev --frontend-only",
|
|
29
|
-
"dev:backend": "bun run core/cli/index.ts dev --backend-only",
|
|
30
|
-
"build": "cross-env NODE_ENV=production bun run core/cli/index.ts build",
|
|
31
|
-
"build:frontend": "cross-env NODE_ENV=production bun run core/cli/index.ts build --frontend-only",
|
|
32
|
-
"build:backend": "cross-env NODE_ENV=production bun run core/cli/index.ts build --backend-only",
|
|
33
|
-
"build:exe": "cross-env NODE_ENV=production && bun run core/cli/index.ts build && bun run core/cli/index.ts build:exe",
|
|
34
|
-
"start": "NODE_ENV=production bun dist/index.js",
|
|
35
|
-
"create": "bun run core/cli/index.ts create",
|
|
36
|
-
"cli": "bun run core/cli/index.ts",
|
|
37
|
-
"make:component": "bun run core/cli/index.ts make:component",
|
|
38
|
-
"sync-version": "bun run core/utils/sync-version.ts",
|
|
39
|
-
"test": "vitest",
|
|
40
|
-
"test:ui": "vitest --ui",
|
|
41
|
-
"test:coverage": "vitest run --coverage",
|
|
42
|
-
"typecheck:api": "tsc --noEmit -p tsconfig.api-strict.json",
|
|
43
|
-
"test:e2e": "playwright test",
|
|
44
|
-
"test:e2e:ui": "playwright test --ui",
|
|
45
|
-
"test:e2e:headed": "playwright test --headed"
|
|
46
|
-
},
|
|
47
|
-
"devDependencies": {
|
|
48
|
-
"@eslint/js": "^9.30.1",
|
|
49
|
-
"@noble/curves": "1.2.0",
|
|
50
|
-
"@noble/hashes": "1.3.2",
|
|
51
|
-
"@playwright/test": "^1.58.2",
|
|
52
|
-
"@tailwindcss/vite": "^4.1.13",
|
|
53
|
-
"@testing-library/jest-dom": "^6.6.4",
|
|
54
|
-
"@testing-library/react": "^16.3.0",
|
|
55
|
-
"@testing-library/user-event": "^14.6.1",
|
|
56
|
-
"@types/bun": "latest",
|
|
57
|
-
"@types/node": "^24.5.2",
|
|
58
|
-
"@types/react": "^19.1.8",
|
|
59
|
-
"@types/react-dom": "^19.1.6",
|
|
60
|
-
"@vitest/coverage-v8": "^3.2.4",
|
|
61
|
-
"@vitest/ui": "^3.2.4",
|
|
62
|
-
"baseline-browser-mapping": "^2.10.7",
|
|
63
|
-
"cross-env": "^10.1.0",
|
|
64
|
-
"eslint": "^9.30.1",
|
|
65
|
-
"eslint-plugin-react-hooks": "^5.2.0",
|
|
66
|
-
"eslint-plugin-react-refresh": "^0.4.20",
|
|
67
|
-
"globals": "^16.3.0",
|
|
68
|
-
"jsdom": "^26.1.0",
|
|
69
|
-
"rollup": "4.20.0",
|
|
70
|
-
"tailwindcss": "^4.1.13",
|
|
71
|
-
"typescript": "^5.8.3",
|
|
72
|
-
"typescript-eslint": "^8.35.1",
|
|
73
|
-
"vite-plugin-checker": "^0.12.0",
|
|
74
|
-
"vite-tsconfig-paths": "^6.0.5",
|
|
75
|
-
"vitest": "^3.2.4"
|
|
76
|
-
},
|
|
77
|
-
"dependencies": {
|
|
78
|
-
"@elysiajs/eden": "^1.3.2",
|
|
79
|
-
"@elysiajs/swagger": "^1.3.1",
|
|
80
|
-
"@fluxstack/config": "^1.0.0",
|
|
81
|
-
"@fluxstack/live": "^
|
|
82
|
-
"@fluxstack/live-client": "^0.
|
|
83
|
-
"@fluxstack/live-elysia": "^0.
|
|
84
|
-
"@fluxstack/live-react": "^0.
|
|
85
|
-
"@fluxstack/plugin-
|
|
86
|
-
"@fluxstack/plugin-
|
|
87
|
-
"@fluxstack/plugin-
|
|
88
|
-
"@
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"react
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
"
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "create-fluxstack",
|
|
3
|
+
"version": "1.22.1",
|
|
4
|
+
"description": "⚡ Revolutionary full-stack TypeScript framework with Declarative Config System, Elysia + React + Bun",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"framework",
|
|
7
|
+
"full-stack",
|
|
8
|
+
"typescript",
|
|
9
|
+
"elysia",
|
|
10
|
+
"react",
|
|
11
|
+
"bun",
|
|
12
|
+
"vite"
|
|
13
|
+
],
|
|
14
|
+
"author": "FluxStack Team",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"homepage": "https://github.com/MarcosBrendonDePaula/FluxStack",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/MarcosBrendonDePaula/FluxStack.git"
|
|
20
|
+
},
|
|
21
|
+
"module": "app/server/index.ts",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"bin": {
|
|
24
|
+
"create-fluxstack": "create-fluxstack.ts"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"dev": "bun run core/cli/index.ts dev",
|
|
28
|
+
"dev:frontend": "bun run core/cli/index.ts dev --frontend-only",
|
|
29
|
+
"dev:backend": "bun run core/cli/index.ts dev --backend-only",
|
|
30
|
+
"build": "cross-env NODE_ENV=production bun run core/cli/index.ts build",
|
|
31
|
+
"build:frontend": "cross-env NODE_ENV=production bun run core/cli/index.ts build --frontend-only",
|
|
32
|
+
"build:backend": "cross-env NODE_ENV=production bun run core/cli/index.ts build --backend-only",
|
|
33
|
+
"build:exe": "cross-env NODE_ENV=production && bun run core/cli/index.ts build && bun run core/cli/index.ts build:exe",
|
|
34
|
+
"start": "NODE_ENV=production bun dist/index.js",
|
|
35
|
+
"create": "bun run core/cli/index.ts create",
|
|
36
|
+
"cli": "bun run core/cli/index.ts",
|
|
37
|
+
"make:component": "bun run core/cli/index.ts make:component",
|
|
38
|
+
"sync-version": "bun run core/utils/sync-version.ts",
|
|
39
|
+
"test": "vitest",
|
|
40
|
+
"test:ui": "vitest --ui",
|
|
41
|
+
"test:coverage": "vitest run --coverage",
|
|
42
|
+
"typecheck:api": "tsc --noEmit -p tsconfig.api-strict.json",
|
|
43
|
+
"test:e2e": "playwright test",
|
|
44
|
+
"test:e2e:ui": "playwright test --ui",
|
|
45
|
+
"test:e2e:headed": "playwright test --headed"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@eslint/js": "^9.30.1",
|
|
49
|
+
"@noble/curves": "1.2.0",
|
|
50
|
+
"@noble/hashes": "1.3.2",
|
|
51
|
+
"@playwright/test": "^1.58.2",
|
|
52
|
+
"@tailwindcss/vite": "^4.1.13",
|
|
53
|
+
"@testing-library/jest-dom": "^6.6.4",
|
|
54
|
+
"@testing-library/react": "^16.3.0",
|
|
55
|
+
"@testing-library/user-event": "^14.6.1",
|
|
56
|
+
"@types/bun": "latest",
|
|
57
|
+
"@types/node": "^24.5.2",
|
|
58
|
+
"@types/react": "^19.1.8",
|
|
59
|
+
"@types/react-dom": "^19.1.6",
|
|
60
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
61
|
+
"@vitest/ui": "^3.2.4",
|
|
62
|
+
"baseline-browser-mapping": "^2.10.7",
|
|
63
|
+
"cross-env": "^10.1.0",
|
|
64
|
+
"eslint": "^9.30.1",
|
|
65
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
66
|
+
"eslint-plugin-react-refresh": "^0.4.20",
|
|
67
|
+
"globals": "^16.3.0",
|
|
68
|
+
"jsdom": "^26.1.0",
|
|
69
|
+
"rollup": "4.20.0",
|
|
70
|
+
"tailwindcss": "^4.1.13",
|
|
71
|
+
"typescript": "^5.8.3",
|
|
72
|
+
"typescript-eslint": "^8.35.1",
|
|
73
|
+
"vite-plugin-checker": "^0.12.0",
|
|
74
|
+
"vite-tsconfig-paths": "^6.0.5",
|
|
75
|
+
"vitest": "^3.2.4"
|
|
76
|
+
},
|
|
77
|
+
"dependencies": {
|
|
78
|
+
"@elysiajs/eden": "^1.3.2",
|
|
79
|
+
"@elysiajs/swagger": "^1.3.1",
|
|
80
|
+
"@fluxstack/config": "^1.0.0",
|
|
81
|
+
"@fluxstack/live": "^0.10.0",
|
|
82
|
+
"@fluxstack/live-client": "^0.10.0",
|
|
83
|
+
"@fluxstack/live-elysia": "^0.10.0",
|
|
84
|
+
"@fluxstack/live-react": "^0.10.0",
|
|
85
|
+
"@fluxstack/plugin-crypto-auth": "^1.0.0",
|
|
86
|
+
"@fluxstack/plugin-csrf-protection": "^1.2.0",
|
|
87
|
+
"@fluxstack/plugin-kit": "^0.4.0",
|
|
88
|
+
"@types/prompts": "^2.4.9",
|
|
89
|
+
"@vitejs/plugin-react": "^4.6.0",
|
|
90
|
+
"@vitejs/plugin-rsc": "^0.5.26",
|
|
91
|
+
"chalk": "^5.3.0",
|
|
92
|
+
"commander": "^12.1.0",
|
|
93
|
+
"elysia": "^1.4.6",
|
|
94
|
+
"lightningcss": "^1.30.1",
|
|
95
|
+
"ora": "^8.1.0",
|
|
96
|
+
"prompts": "^2.4.2",
|
|
97
|
+
"react": "^19.1.0",
|
|
98
|
+
"react-dom": "^19.1.0",
|
|
99
|
+
"react-icons": "^5.5.0",
|
|
100
|
+
"react-router": "^7.9.3",
|
|
101
|
+
"react-server-dom-webpack": "^19.2.6",
|
|
102
|
+
"uuid": "^13.0.0",
|
|
103
|
+
"vite": "^7.1.7",
|
|
104
|
+
"winston": "^3.18.3",
|
|
105
|
+
"winston-daily-rotate-file": "^5.0.0",
|
|
106
|
+
"zustand": "^5.0.8"
|
|
107
|
+
},
|
|
108
|
+
"engines": {
|
|
109
|
+
"bun": ">=1.2.0"
|
|
110
|
+
},
|
|
111
|
+
"preferredPackageManager": "bun"
|
|
112
|
+
}
|
package/playwright.config.ts
CHANGED
|
@@ -11,7 +11,10 @@ export default defineConfig({
|
|
|
11
11
|
timeout: 30_000,
|
|
12
12
|
|
|
13
13
|
use: {
|
|
14
|
-
|
|
14
|
+
// Entrar pela 3000 (Elysia) — o app de verdade: API + WebSocket + frontend
|
|
15
|
+
// (via proxy Vite). A 5173 é o Vite dev cru (sem WebSocket Live), detalhe
|
|
16
|
+
// interno. Pela 3000 tudo é mesma origem, então o WS conecta sozinho.
|
|
17
|
+
baseURL: 'http://localhost:3000',
|
|
15
18
|
trace: 'on-first-retry',
|
|
16
19
|
},
|
|
17
20
|
|
|
@@ -24,7 +27,8 @@ export default defineConfig({
|
|
|
24
27
|
|
|
25
28
|
webServer: {
|
|
26
29
|
command: 'bun run dev',
|
|
27
|
-
|
|
30
|
+
// Espera a 3000 (Elysia) ficar pronta — é por onde os testes entram.
|
|
31
|
+
port: 3000,
|
|
28
32
|
reuseExistingServer: !process.env.CI,
|
|
29
33
|
timeout: 30_000,
|
|
30
34
|
},
|
package/vite.config.ts
CHANGED
|
@@ -9,6 +9,13 @@ import { fluxstackVitePlugins } from './core/build/vite-plugins'
|
|
|
9
9
|
// Root directory (vite.config.ts is in project root)
|
|
10
10
|
const rootDir = import.meta.dirname
|
|
11
11
|
|
|
12
|
+
// RSC (React Server Components) — modo PADRÃO do FluxStack. Adiciona os 3
|
|
13
|
+
// ambientes (rsc/ssr/client) ao Vite e o Elysia dirige o handler RSC
|
|
14
|
+
// (serverHandler:false = plugin não instala middleware próprio). Paths dos
|
|
15
|
+
// entries relativos ao `root` do Vite (app/client).
|
|
16
|
+
// Para SPA puro: RSC_ENABLED=false no ambiente.
|
|
17
|
+
const RSC_ENABLED = process.env.RSC_ENABLED !== 'false'
|
|
18
|
+
|
|
12
19
|
// When using bun-linked @fluxstack/live-* packages locally, point Vite at the
|
|
13
20
|
// TypeScript source instead of pre-built dist. This ensures a single React
|
|
14
21
|
// context (no dual-instance problem) and gives us HMR for the library code.
|
|
@@ -29,6 +36,21 @@ export default defineConfig({
|
|
|
29
36
|
plugins: [
|
|
30
37
|
// FluxStack internal plugins (live-strip, tsconfig-paths, type-checker)
|
|
31
38
|
...fluxstackVitePlugins(),
|
|
39
|
+
// RSC plugin ANTES do react() — quando ligado, ele gerencia os ambientes.
|
|
40
|
+
// Entries com caminho ABSOLUTO: no dev relativo ao root funciona, mas no
|
|
41
|
+
// `vite build` o rollup resolve relativo ao cwd e não acha — absoluto cobre os dois.
|
|
42
|
+
...(RSC_ENABLED
|
|
43
|
+
? [
|
|
44
|
+
(await import('@vitejs/plugin-rsc')).default({
|
|
45
|
+
serverHandler: false,
|
|
46
|
+
entries: {
|
|
47
|
+
rsc: resolve(rootDir, 'app/client/src/framework/entry.rsc.tsx'),
|
|
48
|
+
ssr: resolve(rootDir, 'app/client/src/framework/entry.ssr.tsx'),
|
|
49
|
+
client: resolve(rootDir, 'app/client/src/framework/entry.browser.tsx'),
|
|
50
|
+
},
|
|
51
|
+
}),
|
|
52
|
+
]
|
|
53
|
+
: []),
|
|
32
54
|
react(),
|
|
33
55
|
tailwindcss(),
|
|
34
56
|
],
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export class LiveUpload {
|
|
2
|
-
static componentName = 'LiveUpload'
|
|
3
|
-
static defaultState = {
|
|
4
|
-
status: 'idle',
|
|
5
|
-
progress: 0,
|
|
6
|
-
fileName: '',
|
|
7
|
-
fileSize: 0,
|
|
8
|
-
fileType: '',
|
|
9
|
-
fileUrl: '',
|
|
10
|
-
bytesUploaded: 0,
|
|
11
|
-
totalBytes: 0,
|
|
12
|
-
error: null
|
|
13
|
-
}
|
|
14
|
-
static publicActions = ['startUpload', 'updateProgress', 'completeUpload', 'failUpload', 'reset']
|
|
15
|
-
}
|