create-fluxstack 1.18.0 → 1.18.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/server/live/rooms/ChatRoom.ts +13 -8
- package/app/server/routes/index.ts +20 -10
- package/core/framework/server.ts +12 -0
- package/core/utils/version.ts +1 -1
- package/package.json +107 -107
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { LiveRoom } from '@fluxstack/live'
|
|
4
4
|
import type { RoomJoinContext, RoomLeaveContext } from '@fluxstack/live'
|
|
5
|
-
import { createHash, timingSafeEqual } from 'crypto'
|
|
5
|
+
import { createHash, randomBytes, timingSafeEqual } from 'crypto'
|
|
6
6
|
|
|
7
7
|
export interface ChatMessage {
|
|
8
8
|
id: string
|
|
@@ -33,15 +33,20 @@ export class ChatRoom extends LiveRoom<ChatState, ChatMeta, ChatEvents> {
|
|
|
33
33
|
static defaultMeta: ChatMeta = { password: null, createdBy: null }
|
|
34
34
|
static $options = { maxMembers: 100 }
|
|
35
35
|
|
|
36
|
-
/** Hash a password using SHA-256. */
|
|
36
|
+
/** Hash a password using SHA-256 with a random salt. Returns "salt:hash". */
|
|
37
37
|
private static hashPassword(password: string): string {
|
|
38
|
-
|
|
38
|
+
const salt = randomBytes(16).toString('hex')
|
|
39
|
+
const hash = createHash('sha256').update(salt + password).digest('hex')
|
|
40
|
+
return salt + ':' + hash
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
/**
|
|
42
|
-
private static
|
|
43
|
-
const
|
|
44
|
-
|
|
43
|
+
/** Verify a password against a stored "salt:hash" string using constant-time comparison. */
|
|
44
|
+
private static verifyPassword(password: string, stored: string): boolean {
|
|
45
|
+
const [salt, hash] = stored.split(':')
|
|
46
|
+
if (!salt || !hash) return false
|
|
47
|
+
const computed = createHash('sha256').update(salt + password).digest('hex')
|
|
48
|
+
const bufA = Buffer.from(computed, 'hex')
|
|
49
|
+
const bufB = Buffer.from(hash, 'hex')
|
|
45
50
|
if (bufA.length !== bufB.length) return false
|
|
46
51
|
return timingSafeEqual(bufA, bufB)
|
|
47
52
|
}
|
|
@@ -56,7 +61,7 @@ export class ChatRoom extends LiveRoom<ChatState, ChatMeta, ChatEvents> {
|
|
|
56
61
|
// Validate password if room is protected
|
|
57
62
|
if (this.meta.password) {
|
|
58
63
|
const provided = ctx.payload?.password
|
|
59
|
-
if (!provided || !ChatRoom.
|
|
64
|
+
if (!provided || !ChatRoom.verifyPassword(provided, this.meta.password)) {
|
|
60
65
|
return false // Rejected — wrong or missing password
|
|
61
66
|
}
|
|
62
67
|
}
|
|
@@ -3,6 +3,7 @@ import { usersRoutes } from "./users.routes"
|
|
|
3
3
|
import { roomRoutes } from "./room.routes"
|
|
4
4
|
import { authRoutes } from "./auth.routes"
|
|
5
5
|
import { pluginClientHooks } from "@core/server/plugin-client-hooks"
|
|
6
|
+
import { FLUXSTACK_VERSION } from "@core/utils/version"
|
|
6
7
|
|
|
7
8
|
export const apiRoutes = new Elysia({ prefix: "/api" })
|
|
8
9
|
.get("/", () => ({ message: "🔥 Hot Reload funcionando! FluxStack API v1.4.0 ⚡" }), {
|
|
@@ -15,24 +16,33 @@ export const apiRoutes = new Elysia({ prefix: "/api" })
|
|
|
15
16
|
description: 'Returns a welcome message from the FluxStack API'
|
|
16
17
|
}
|
|
17
18
|
})
|
|
18
|
-
.get("/health", () =>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
.get("/health", () => {
|
|
20
|
+
const checks = {
|
|
21
|
+
status: 'ok' as 'ok' | 'degraded' | 'error',
|
|
22
|
+
timestamp: new Date().toISOString(),
|
|
23
|
+
uptime: process.uptime(),
|
|
24
|
+
memory: {
|
|
25
|
+
used: Math.round(process.memoryUsage().heapUsed / 1024 / 1024),
|
|
26
|
+
total: Math.round(process.memoryUsage().heapTotal / 1024 / 1024),
|
|
27
|
+
},
|
|
28
|
+
version: FLUXSTACK_VERSION,
|
|
29
|
+
}
|
|
30
|
+
return checks
|
|
31
|
+
}, {
|
|
25
32
|
response: t.Object({
|
|
26
33
|
status: t.String(),
|
|
27
34
|
timestamp: t.String(),
|
|
28
|
-
uptime: t.
|
|
35
|
+
uptime: t.Number(),
|
|
36
|
+
memory: t.Object({
|
|
37
|
+
used: t.Number(),
|
|
38
|
+
total: t.Number(),
|
|
39
|
+
}),
|
|
29
40
|
version: t.String(),
|
|
30
|
-
environment: t.String()
|
|
31
41
|
}),
|
|
32
42
|
detail: {
|
|
33
43
|
tags: ['Health'],
|
|
34
44
|
summary: 'Health Check',
|
|
35
|
-
description: 'Returns the current health status of the API
|
|
45
|
+
description: 'Returns the current health status of the API including uptime, memory usage, and version'
|
|
36
46
|
}
|
|
37
47
|
})
|
|
38
48
|
// Plugin client hooks endpoint
|
package/core/framework/server.ts
CHANGED
|
@@ -157,6 +157,7 @@ export class FluxStackFramework {
|
|
|
157
157
|
})
|
|
158
158
|
|
|
159
159
|
this.setupCors()
|
|
160
|
+
this.setupSecurityHeaders()
|
|
160
161
|
this.setupHeadHandler()
|
|
161
162
|
this.setupElysiaHeadBugFilter()
|
|
162
163
|
this.setupHooks()
|
|
@@ -233,6 +234,17 @@ export class FluxStackFramework {
|
|
|
233
234
|
})
|
|
234
235
|
}
|
|
235
236
|
|
|
237
|
+
private setupSecurityHeaders() {
|
|
238
|
+
// Security headers middleware — protects against common web vulnerabilities
|
|
239
|
+
this.app.onBeforeHandle(({ set }) => {
|
|
240
|
+
set.headers['X-Content-Type-Options'] = 'nosniff'
|
|
241
|
+
set.headers['X-Frame-Options'] = 'DENY'
|
|
242
|
+
set.headers['X-XSS-Protection'] = '0' // Deprecated, CSP is better
|
|
243
|
+
set.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin'
|
|
244
|
+
// CSP is intentionally not set here — apps should configure it per their needs
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
|
|
236
248
|
private setupHeadHandler() {
|
|
237
249
|
// Global HEAD handler to prevent Elysia's automatic HEAD conversion bug
|
|
238
250
|
this.app.head("*", ({ request, set }) => {
|
package/core/utils/version.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "create-fluxstack",
|
|
3
|
-
"version": "1.18.
|
|
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.
|
|
82
|
-
"@fluxstack/live-client": "^0.
|
|
83
|
-
"@fluxstack/live-elysia": "^0.
|
|
84
|
-
"@fluxstack/live-react": "^0.
|
|
85
|
-
"@fluxstack/plugin-crypto-auth": "^1.0.0",
|
|
86
|
-
"@fluxstack/plugin-csrf-protection": "^1.1.0",
|
|
87
|
-
"@vitejs/plugin-react": "^4.6.0",
|
|
88
|
-
"chalk": "^5.3.0",
|
|
89
|
-
"commander": "^12.1.0",
|
|
90
|
-
"elysia": "^1.4.6",
|
|
91
|
-
"lightningcss": "^1.30.1",
|
|
92
|
-
"ora": "^8.1.0",
|
|
93
|
-
"react": "^19.1.0",
|
|
94
|
-
"react-dom": "^19.1.0",
|
|
95
|
-
"react-icons": "^5.5.0",
|
|
96
|
-
"react-router": "^7.9.3",
|
|
97
|
-
"uuid": "^13.0.0",
|
|
98
|
-
"vite": "^7.1.7",
|
|
99
|
-
"winston": "^3.18.3",
|
|
100
|
-
"winston-daily-rotate-file": "^5.0.0",
|
|
101
|
-
"zustand": "^5.0.8"
|
|
102
|
-
},
|
|
103
|
-
"engines": {
|
|
104
|
-
"bun": ">=1.2.0"
|
|
105
|
-
},
|
|
106
|
-
"preferredPackageManager": "bun"
|
|
107
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "create-fluxstack",
|
|
3
|
+
"version": "1.18.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.6.0",
|
|
82
|
+
"@fluxstack/live-client": "^0.6.0",
|
|
83
|
+
"@fluxstack/live-elysia": "^0.6.0",
|
|
84
|
+
"@fluxstack/live-react": "^0.6.0",
|
|
85
|
+
"@fluxstack/plugin-crypto-auth": "^1.0.0",
|
|
86
|
+
"@fluxstack/plugin-csrf-protection": "^1.1.0",
|
|
87
|
+
"@vitejs/plugin-react": "^4.6.0",
|
|
88
|
+
"chalk": "^5.3.0",
|
|
89
|
+
"commander": "^12.1.0",
|
|
90
|
+
"elysia": "^1.4.6",
|
|
91
|
+
"lightningcss": "^1.30.1",
|
|
92
|
+
"ora": "^8.1.0",
|
|
93
|
+
"react": "^19.1.0",
|
|
94
|
+
"react-dom": "^19.1.0",
|
|
95
|
+
"react-icons": "^5.5.0",
|
|
96
|
+
"react-router": "^7.9.3",
|
|
97
|
+
"uuid": "^13.0.0",
|
|
98
|
+
"vite": "^7.1.7",
|
|
99
|
+
"winston": "^3.18.3",
|
|
100
|
+
"winston-daily-rotate-file": "^5.0.0",
|
|
101
|
+
"zustand": "^5.0.8"
|
|
102
|
+
},
|
|
103
|
+
"engines": {
|
|
104
|
+
"bun": ">=1.2.0"
|
|
105
|
+
},
|
|
106
|
+
"preferredPackageManager": "bun"
|
|
107
|
+
}
|