@fuzionx/framework 0.1.27 → 0.1.29

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 (38) hide show
  1. package/cli/index.js +66 -53
  2. package/cli/templates/app/database/models/User.js +9 -0
  3. package/cli/templates/app/fuzionx.yaml.tpl +3 -3
  4. package/cli/templates/app/locales/en.json +52 -0
  5. package/cli/templates/app/locales/ko.json +52 -0
  6. package/cli/templates/app/package.json.tpl +2 -1
  7. package/cli/templates/app/shared/events/userEvents.js +10 -0
  8. package/cli/templates/app/shared/jobs/CleanupJob.js +18 -0
  9. package/cli/templates/app/shared/jobs/EmailTask.js +17 -0
  10. package/cli/templates/app/shared/jobs/VideoPreviewTask.js +47 -0
  11. package/cli/templates/app/shared/workers/heavy.js +18 -0
  12. package/cli/templates/app/tester/controllers/FileController.js +288 -0
  13. package/cli/templates/app/tester/controllers/HomeController.js +36 -0
  14. package/cli/templates/app/tester/controllers/UserController.js +43 -0
  15. package/cli/templates/app/tester/middleware/RequestLogger.js +13 -0
  16. package/cli/templates/app/tester/routes/api.js +397 -0
  17. package/cli/templates/app/tester/routes/web.js +8 -0
  18. package/cli/templates/app/tester/services/UserService.js +52 -0
  19. package/cli/templates/app/tester/views/default/errors/404.html +15 -0
  20. package/cli/templates/app/tester/views/default/errors/500.html +14 -0
  21. package/cli/templates/app/tester/views/default/layouts/main.html +82 -0
  22. package/cli/templates/app/tester/views/default/pages/home.html +56 -0
  23. package/cli/templates/app/tester/views/default/pages/i18n.html +104 -0
  24. package/cli/templates/app/tester/views/default/pages/upload.html +149 -0
  25. package/cli/templates/app/tester/views/default/pages/websocket.html +239 -0
  26. package/cli/templates/app/tester/views/default/partials/footer.html +8 -0
  27. package/cli/templates/app/tester/views/default/partials/header.html +20 -0
  28. package/cli/templates/app/tester/ws/ChatHandler.js +98 -0
  29. package/lib/core/Application.js +1 -1
  30. package/lib/helpers/Logger.js +6 -6
  31. package/package.json +2 -2
  32. /package/cli/templates/app/{controllers → fuzionx/controllers}/HomeController.js +0 -0
  33. /package/cli/templates/app/{routes → fuzionx/routes}/api.js.tpl +0 -0
  34. /package/cli/templates/app/{routes → fuzionx/routes}/web.js.tpl +0 -0
  35. /package/cli/templates/app/{views → fuzionx/views}/default/errors/404.html +0 -0
  36. /package/cli/templates/app/{views → fuzionx/views}/default/errors/500.html +0 -0
  37. /package/cli/templates/app/{views → fuzionx/views}/default/layouts/main.html +0 -0
  38. /package/cli/templates/app/{views → fuzionx/views}/default/pages/home.html +0 -0
@@ -0,0 +1,98 @@
1
+ import { WsHandler } from '@fuzionx/framework';
2
+
3
+ /** 채팅 WebSocket 핸들러 */
4
+ export default class ChatHandler extends WsHandler {
5
+ static namespace = '/chat';
6
+ static middleware = [];
7
+
8
+ static events(e) {
9
+ e.on('message', ChatHandler.prototype.handleMessage);
10
+ e.on('broadcast', ChatHandler.prototype.handleBroadcast);
11
+ e.on('typing', ChatHandler.prototype.handleTyping);
12
+ e.on('userlist', ChatHandler.prototype.handleUserList);
13
+ }
14
+
15
+ /** 접속자 목록 브로드캐스트 헬퍼 */
16
+ _broadcastUserList(socket) {
17
+ try {
18
+ const count = socket.onlineCount;
19
+ const sessions = socket.sessionIds;
20
+ const payload = JSON.stringify({
21
+ type: 'userlist',
22
+ data: { count, sessions: sessions.map(s => s.slice(0, 8)) },
23
+ });
24
+ socket.broadcast(payload);
25
+ } catch (e) {
26
+ console.error('[Chat] userlist error:', e.message);
27
+ }
28
+ }
29
+
30
+ async onConnect(socket) {
31
+ const sid = socket.sessionId;
32
+ console.log(`[Chat] 연결: ${sid.slice(0,8)}`);
33
+ // 전체 알림: 새 사용자 입장
34
+ socket.broadcastExcluding(JSON.stringify({
35
+ type: 'system',
36
+ data: { text: `사용자(${sid.slice(0,8)}) 입장`, timestamp: Date.now() },
37
+ }));
38
+ // 접속자 목록 갱신
39
+ this._broadcastUserList(socket);
40
+ }
41
+
42
+ /** message — 본인 제외 전체 전송 */
43
+ async handleMessage(socket, data) {
44
+ const sid = socket.sessionId;
45
+ console.log(`[Chat] msg(${sid.slice(0,8)}): ${JSON.stringify(data)}`);
46
+ const payload = JSON.stringify({
47
+ type: 'message',
48
+ data: { user: sid.slice(0,8), text: data.text || data, timestamp: Date.now() },
49
+ });
50
+ // 본인 제외 전체 전송 (본인은 UI에서 이미 sent로 표시)
51
+ socket.broadcastExcluding(payload);
52
+ }
53
+
54
+ /** broadcast — 본인 제외 전체 전송 (공지) */
55
+ async handleBroadcast(socket, data) {
56
+ const sid = socket.sessionId;
57
+ console.log(`[Chat] broadcast(${sid.slice(0,8)}): ${JSON.stringify(data)}`);
58
+ const payload = JSON.stringify({
59
+ type: 'broadcast',
60
+ data: { user: sid.slice(0,8), text: data.text || data, timestamp: Date.now() },
61
+ });
62
+ socket.broadcastExcluding(payload);
63
+ }
64
+
65
+ /** typing — 본인 제외 전체 전송 */
66
+ async handleTyping(socket, data) {
67
+ const sid = socket.sessionId;
68
+ socket.broadcastExcluding(JSON.stringify({
69
+ type: 'typing',
70
+ data: { user: sid.slice(0,8) },
71
+ }));
72
+ }
73
+
74
+ /** userlist 요청 — 접속자 목록 반환 */
75
+ async handleUserList(socket, data) {
76
+ try {
77
+ const count = socket.onlineCount;
78
+ const sessions = socket.sessionIds;
79
+ return {
80
+ type: 'userlist',
81
+ data: { count, sessions: sessions.map(s => s.slice(0, 8)) },
82
+ };
83
+ } catch (e) {
84
+ return { type: 'userlist', data: { count: 0, sessions: [] } };
85
+ }
86
+ }
87
+
88
+ async onDisconnect(socket, code, reason) {
89
+ const sid = socket.sessionId;
90
+ console.log(`[Chat] 해제: ${sid.slice(0,8)} code=${code}`);
91
+ socket.broadcastExcluding(JSON.stringify({
92
+ type: 'system',
93
+ data: { text: `사용자(${sid.slice(0,8)}) 퇴장`, timestamp: Date.now() },
94
+ }));
95
+ // 접속자 목록 갱신
96
+ this._broadcastUserList(socket);
97
+ }
98
+ }
@@ -370,7 +370,7 @@ export default class Application {
370
370
  _getDefaultAppName() {
371
371
  const appsConfig = this.config.get('apps') || {};
372
372
  const values = Object.values(appsConfig);
373
- return values[0] || 'backend';
373
+ return values[0] || 'fuzionx';
374
374
  }
375
375
 
376
376
  /**
@@ -53,12 +53,12 @@ export default class Logger {
53
53
  _log(level, message, context) {
54
54
  if (this._levels[level] > this._minLevel) return;
55
55
 
56
- const msg = context
57
- ? `${message} ${JSON.stringify(context)}`
58
- : message;
56
+ // Error 객체면 전체 스택 포함
57
+ const isErr = message instanceof Error;
58
+ const text = isErr ? (message.stack || `${message}`) : `${message}`;
59
+ const msg = context ? `${text} ${JSON.stringify(context)}` : text;
59
60
 
60
61
  // ── Bridge N-API 위임 ──
61
- // Core logger.js 참조: bridge.logInfo(target, msg), bridge.logWarn(target, msg, location?)
62
62
  if (this._bridge) {
63
63
  try {
64
64
  if (level === 'info' && typeof this._bridge.logInfo === 'function') {
@@ -88,13 +88,13 @@ export default class Logger {
88
88
  timestamp,
89
89
  level,
90
90
  target: this._prefix,
91
- message,
91
+ message: msg,
92
92
  ...(context || {}),
93
93
  };
94
94
  console[level === 'debug' ? 'log' : level](JSON.stringify(entry));
95
95
  } else {
96
96
  const levelTag = level.toUpperCase().padEnd(5);
97
- const fullMsg = `${timestamp} ${levelTag} [${this._prefix}] ${message}`;
97
+ const fullMsg = `${timestamp} ${levelTag} [${this._prefix}] ${msg}`;
98
98
  if (context && Object.keys(context).length > 0) {
99
99
  console[level === 'debug' ? 'log' : level](fullMsg, context);
100
100
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzionx/framework",
3
- "version": "0.1.27",
3
+ "version": "0.1.29",
4
4
  "type": "module",
5
5
  "description": "Full-stack MVC framework built on @fuzionx/core — Controller, Service, Model, Middleware, DI, EventBus",
6
6
  "main": "index.js",
@@ -34,7 +34,7 @@
34
34
  "url": "https://github.com/saytohenry/fuzionx"
35
35
  },
36
36
  "dependencies": {
37
- "@fuzionx/core": "^0.1.27",
37
+ "@fuzionx/core": "^0.1.29",
38
38
  "better-sqlite3": "^12.8.0",
39
39
  "knex": "^3.2.5",
40
40
  "mongoose": "^9.3.2",