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.
@@ -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
- return createHash('sha256').update(password).digest('hex')
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
- /** Constant-time comparison of two hex strings. */
42
- private static safeCompare(a: string, b: string): boolean {
43
- const bufA = Buffer.from(a, 'hex')
44
- const bufB = Buffer.from(b, 'hex')
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.safeCompare(ChatRoom.hashPassword(provided), this.meta.password)) {
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
- status: "🚀 Hot Reload ativo!",
20
- timestamp: new Date().toISOString(),
21
- uptime: `${Math.floor(process.uptime())}s`,
22
- version: "1.4.0",
23
- environment: "development"
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.String(),
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 server'
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
@@ -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 }) => {
@@ -3,4 +3,4 @@
3
3
  * Single source of truth for version number
4
4
  * Auto-synced with package.json
5
5
  */
6
- export const FLUXSTACK_VERSION = '1.18.0'
6
+ export const FLUXSTACK_VERSION = '1.18.1'
package/package.json CHANGED
@@ -1,107 +1,107 @@
1
- {
2
- "name": "create-fluxstack",
3
- "version": "1.18.0",
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.5.1",
82
- "@fluxstack/live-client": "^0.5.1",
83
- "@fluxstack/live-elysia": "^0.5.1",
84
- "@fluxstack/live-react": "^0.5.1",
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
+ }