@fuzionx/framework 0.1.29 → 0.1.31

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 (63) hide show
  1. package/cli/index.js +230 -114
  2. package/cli/templates/{app/fuzionx → make/app}/controllers/HomeController.js +1 -0
  3. package/cli/templates/{app/tester → make/app}/views/default/errors/404.html +0 -4
  4. package/cli/templates/{app/fuzionx/views/default/errors/404.html → make/app/views/default/errors/500.html} +1 -2
  5. package/cli/templates/make/app/views/default/pages/home.html +11 -0
  6. package/index.js +3 -0
  7. package/lib/core/Application.js +31 -6
  8. package/lib/core/Context.js +30 -1
  9. package/lib/helpers/I18nHelper.js +10 -6
  10. package/lib/middleware/apiAuth.js +79 -0
  11. package/lib/middleware/auth.js +42 -0
  12. package/lib/middleware/bodyParser.js +19 -0
  13. package/lib/middleware/cors.js +47 -0
  14. package/lib/middleware/csrf.js +32 -0
  15. package/lib/middleware/index.js +8 -277
  16. package/lib/middleware/session.js +27 -0
  17. package/lib/middleware/theme.js +20 -0
  18. package/lib/schedule/Job.js +4 -0
  19. package/lib/schedule/Queue.js +20 -8
  20. package/lib/schedule/Scheduler.js +84 -75
  21. package/lib/utilities/ArrUtil.js +112 -0
  22. package/lib/utilities/DateUtil.js +98 -0
  23. package/lib/utilities/FunctionUtil.js +119 -0
  24. package/lib/utilities/NumUtil.js +75 -0
  25. package/lib/utilities/ObjectUtil.js +170 -0
  26. package/lib/utilities/PaginationUtil.js +81 -0
  27. package/lib/utilities/StrUtil.js +105 -0
  28. package/lib/utilities/index.js +18 -0
  29. package/package.json +2 -2
  30. package/cli/templates/app/.env.example.tpl +0 -14
  31. package/cli/templates/app/.gitignore.tpl +0 -4
  32. package/cli/templates/app/app.js.tpl +0 -6
  33. package/cli/templates/app/database/models/User.js +0 -9
  34. package/cli/templates/app/fuzionx/views/default/errors/500.html +0 -14
  35. package/cli/templates/app/fuzionx/views/default/pages/home.html +0 -188
  36. package/cli/templates/app/fuzionx.yaml.tpl +0 -202
  37. package/cli/templates/app/locales/en.json +0 -52
  38. package/cli/templates/app/locales/ko.json +0 -52
  39. package/cli/templates/app/package.json.tpl +0 -16
  40. package/cli/templates/app/shared/events/userEvents.js +0 -10
  41. package/cli/templates/app/shared/jobs/CleanupJob.js +0 -18
  42. package/cli/templates/app/shared/jobs/EmailTask.js +0 -17
  43. package/cli/templates/app/shared/jobs/VideoPreviewTask.js +0 -47
  44. package/cli/templates/app/shared/workers/heavy.js +0 -18
  45. package/cli/templates/app/tester/controllers/FileController.js +0 -288
  46. package/cli/templates/app/tester/controllers/HomeController.js +0 -36
  47. package/cli/templates/app/tester/controllers/UserController.js +0 -43
  48. package/cli/templates/app/tester/middleware/RequestLogger.js +0 -13
  49. package/cli/templates/app/tester/routes/api.js +0 -397
  50. package/cli/templates/app/tester/routes/web.js +0 -8
  51. package/cli/templates/app/tester/services/UserService.js +0 -52
  52. package/cli/templates/app/tester/views/default/errors/500.html +0 -14
  53. package/cli/templates/app/tester/views/default/layouts/main.html +0 -82
  54. package/cli/templates/app/tester/views/default/pages/home.html +0 -56
  55. package/cli/templates/app/tester/views/default/pages/i18n.html +0 -104
  56. package/cli/templates/app/tester/views/default/pages/upload.html +0 -149
  57. package/cli/templates/app/tester/views/default/pages/websocket.html +0 -239
  58. package/cli/templates/app/tester/views/default/partials/footer.html +0 -8
  59. package/cli/templates/app/tester/views/default/partials/header.html +0 -20
  60. package/cli/templates/app/tester/ws/ChatHandler.js +0 -98
  61. /package/cli/templates/{app/fuzionx/routes/api.js.tpl → make/app/routes/api.js} +0 -0
  62. /package/cli/templates/{app/fuzionx/routes/web.js.tpl → make/app/routes/web.js} +0 -0
  63. /package/cli/templates/{app/fuzionx → make/app}/views/default/layouts/main.html +0 -0
@@ -1,202 +0,0 @@
1
- # ═══════════════════════════════════════════════
2
- # fuzionx.yaml — FuzionX 전체 설정 레퍼런스
3
- # ═══════════════════════════════════════════════
4
-
5
- # ── Bridge (Rust 엔진) ──────────────────────────
6
- bridge:
7
- port: 49080
8
- workers: 0 # 0 = CPU 코어 수 자동
9
- worker_timeout: 30 # 워커 요청 타임아웃 (초)
10
-
11
- # ── 보안: CORS ──
12
- cors:
13
- enabled: false
14
- origins:
15
- - "*"
16
-
17
- # ── 보안: Rate Limit ──
18
- rate_limit:
19
- enabled: true
20
- per_ip: 1000 # IP당 초당 요청 수
21
-
22
- # ── 보안: HSTS ──
23
- hsts:
24
- enabled: false
25
- max_age: 31536000 # 1년 (초)
26
-
27
- # ── 보안: CSP ──
28
- csp:
29
- enabled: false
30
- directives:
31
- - "default-src 'self'"
32
-
33
- # ── 보안: IP Filter ──
34
- ip_filter:
35
- enabled: false
36
- whitelist: [] # CIDR 형식
37
- blacklist: []
38
-
39
- # ── 세션 ──
40
- session:
41
- enabled: false
42
- store: memory # memory | redis
43
- ttl: 3600 # 세션 TTL (초)
44
- cookie_name: fuzionx.sid
45
- # redis_url: "redis://localhost:6379"
46
-
47
- # ── 국제화 (i18n) ──
48
- i18n:
49
- enabled: false
50
- default_locale: ko
51
- locale_dir: ./locales
52
- auto_complete: false
53
- locales:
54
- - ko
55
- - en
56
-
57
- # ── WebSocket ──
58
- websocket:
59
- enabled: false
60
- path: /ws
61
- check_interval: 60 # 헬스체크 간격 (초)
62
- timeout: 60 # 타임아웃 (초)
63
-
64
- # ── Hub (멀티서버 동기화) ──
65
- hub:
66
- enabled: false
67
- url: "ws://127.0.0.1:9100/ws/bridge"
68
- group: "{{name}}"
69
-
70
- # ── 파일 업로드 ──
71
- upload:
72
- dir: /tmp
73
- max_size: "1gb"
74
- max_files: 20
75
- allowed_types:
76
- - image/jpeg
77
- - image/png
78
- - image/webp
79
- - image/gif
80
- - video/mp4
81
- - video/webm
82
- - application/pdf
83
- # watermark: ./assets/watermark.png
84
- # watermark_opacity: 50
85
-
86
- # ── 정적 파일 ──
87
- static:
88
- - url: /public
89
- path: ./public
90
-
91
- # ── 로깅 ──
92
- logging:
93
- level: info # error | warn | info | debug
94
- intercept_console: true # console.* 가로채기
95
- file:
96
- enabled: false
97
- path: ./logs/app.log
98
-
99
- # ── 액세스 로그 ──
100
- access_log:
101
- enabled: false
102
- path: ./logs/access.log
103
- error_path: ./logs/error.log
104
-
105
- # ── 트래픽 캡처 ──
106
- traffic_capture:
107
- enabled: false
108
- max_body_size: "64KB"
109
- exclude_content_types: []
110
- loki:
111
- enabled: false
112
- url: ""
113
- labels: []
114
- fields: []
115
- batch_size: 100
116
- flush_interval: "2s"
117
- clickhouse:
118
- enabled: false
119
- url: ""
120
- database: fuzionx
121
- table: traffic
122
- format: full # metadata | headers_only | full
123
- batch_size: 100
124
- flush_interval: "1s"
125
-
126
- # ── ASP 암호화 ──
127
- asp:
128
- enabled: false
129
- master_secret: "${ASP_SECRET:change-me-in-production}"
130
- header_signal: Ruxy-Enc-Mode
131
-
132
- # ── Database ────────────────────────────────────
133
- database:
134
- default: main
135
- connections:
136
- main:
137
- driver: sqlite # sqlite | mariadb | postgres | mongodb
138
- database: ./storage/database.sqlite
139
- # host: "127.0.0.1"
140
- # port: 3306
141
- # user: root
142
- # password: ""
143
- # charset: utf8mb4
144
- # pool:
145
- # min: 2
146
- # max: 10
147
-
148
- # ── App (프레임워크) ────────────────────────────
149
- app:
150
- name: '{{name}}'
151
- environment: development # development | production
152
-
153
- asp:
154
- enabled: false
155
-
156
- # 인증
157
- auth:
158
- secret: '${JWT_SECRET:change-me-in-production}'
159
- accessTtl: '15m'
160
- # refreshTtl: '7d'
161
- # bcrypt_rounds: 12
162
-
163
- # 국제화 (프레임워크 편의 설정)
164
- i18n:
165
- default_locale: 'ko'
166
- fallback: 'en'
167
-
168
- # Swagger/OpenAPI
169
- docs:
170
- enabled: true
171
- path: '/docs'
172
-
173
- # 테마
174
- themes:
175
- default: 'default'
176
-
177
- # 스토리지
178
- # storage:
179
- # driver: local
180
- # local:
181
- # path: ./storage
182
- # url_prefix: /storage
183
-
184
- # 스케줄러
185
- # scheduler:
186
- # enabled: true
187
- # lock:
188
- # driver: null # null | redis
189
- # redis_url: ""
190
- # prefix: "myapp:lock"
191
-
192
- # 큐
193
- # queue:
194
- # driver: memory # memory | redis
195
- # redis_url: ""
196
- # prefix: "myapp:queue"
197
-
198
- # ── Multi-App (도메인 → 앱 라우팅) ────────────────
199
- # tester를 실행하려면 fuzionx를 주석 처리하고 tester 주석을 해제하세요.
200
- apps:
201
- "127.0.0.1:49080": fuzionx
202
- # "127.0.0.1:49080": tester
@@ -1,52 +0,0 @@
1
- {
2
- "app": {
3
- "name": "FuzionX Test App",
4
- "welcome": "Welcome to FuzionX",
5
- "description": "Full-stack framework testing environment"
6
- },
7
- "nav": {
8
- "home": "Home",
9
- "dashboard": "Dashboard",
10
- "users": "Users",
11
- "upload": "Upload",
12
- "websocket": "WebSocket",
13
- "docs": "API Docs",
14
- "settings": "Settings"
15
- },
16
- "user": {
17
- "name": "Name",
18
- "email": "Email",
19
- "role": "Role",
20
- "create": "Create User",
21
- "edit": "Edit",
22
- "delete": "Delete",
23
- "list": "User List",
24
- "created": "User has been created",
25
- "deleted": "User has been deleted",
26
- "not_found": "User not found"
27
- },
28
- "auth": {
29
- "login": "Login",
30
- "logout": "Logout",
31
- "login_required": "Login required",
32
- "invalid_credentials": "Invalid credentials"
33
- },
34
- "common": {
35
- "save": "Save",
36
- "cancel": "Cancel",
37
- "confirm": "Confirm",
38
- "search": "Search",
39
- "loading": "Loading...",
40
- "error": "An error occurred",
41
- "success": "Success",
42
- "greeting": "Hello, {name}!",
43
- "items_count": "{count} items total"
44
- },
45
- "upload": {
46
- "select_file": "Select a file",
47
- "drag_drop": "Drag & drop or click to select",
48
- "uploading": "Uploading...",
49
- "complete": "Upload complete",
50
- "error": "Upload failed"
51
- }
52
- }
@@ -1,52 +0,0 @@
1
- {
2
- "app": {
3
- "name": "FuzionX 테스트 앱",
4
- "welcome": "FuzionX에 오신 것을 환영합니다",
5
- "description": "풀스택 프레임워크 테스트 환경입니다"
6
- },
7
- "nav": {
8
- "home": "홈",
9
- "dashboard": "대시보드",
10
- "users": "사용자",
11
- "upload": "업로드",
12
- "websocket": "웹소켓",
13
- "docs": "API 문서",
14
- "settings": "설정"
15
- },
16
- "user": {
17
- "name": "이름",
18
- "email": "이메일",
19
- "role": "역할",
20
- "create": "사용자 생성",
21
- "edit": "수정",
22
- "delete": "삭제",
23
- "list": "사용자 목록",
24
- "created": "사용자가 생성되었습니다",
25
- "deleted": "사용자가 삭제되었습니다",
26
- "not_found": "사용자를 찾을 수 없습니다"
27
- },
28
- "auth": {
29
- "login": "로그인",
30
- "logout": "로그아웃",
31
- "login_required": "로그인이 필요합니다",
32
- "invalid_credentials": "잘못된 인증 정보입니다"
33
- },
34
- "common": {
35
- "save": "저장",
36
- "cancel": "취소",
37
- "confirm": "확인",
38
- "search": "검색",
39
- "loading": "로딩중...",
40
- "error": "오류가 발생했습니다",
41
- "success": "성공",
42
- "greeting": "{name}님, 안녕하세요!",
43
- "items_count": "총 {count}개 항목"
44
- },
45
- "upload": {
46
- "select_file": "파일을 선택하세요",
47
- "drag_drop": "파일을 드래그하거나 클릭하세요",
48
- "uploading": "업로드 중...",
49
- "complete": "업로드 완료",
50
- "error": "업로드 실패"
51
- }
52
- }
@@ -1,16 +0,0 @@
1
- {
2
- "name": "{{name}}",
3
- "version": "1.0.0",
4
- "type": "module",
5
- "scripts": {
6
- "dev": "fx dev",
7
- "test": "vitest run"
8
- },
9
- "dependencies": {
10
- "@fuzionx/framework": "^0.1.29",
11
- "joi": "^18.1.1"
12
- },
13
- "devDependencies": {
14
- "vitest": "^3.0.0"
15
- }
16
- }
@@ -1,10 +0,0 @@
1
- /** 이벤트 리스너 등록 */
2
- export default (app) => {
3
- app.on('user:created', (data) => {
4
- console.log(`[Event] user:created → id=${data.id}, name=${data.name}`);
5
- });
6
-
7
- app.on('user:deleted', (data) => {
8
- console.log(`[Event] user:deleted → id=${data.id}`);
9
- });
10
- };
@@ -1,18 +0,0 @@
1
- import { Job } from '@fuzionx/framework';
2
-
3
- /** 매 5분마다 만료 세션 정리 (스케줄러 테스트) */
4
- export default class CleanupJob extends Job {
5
- static schedule = 'every:5m';
6
- static timeout = 10000;
7
- static enabled = true;
8
-
9
- async handle() {
10
- const cleaned = Math.floor(Math.random() * 10);
11
- console.log(`[CleanupJob] ${cleaned}개 만료 세션 정리 완료`);
12
- return { cleaned };
13
- }
14
-
15
- async onError(error) {
16
- console.error('[CleanupJob] 실패:', error.message);
17
- }
18
- }
@@ -1,17 +0,0 @@
1
- import { Task } from '@fuzionx/framework';
2
-
3
- /** 이메일 전송 비동기 Task (큐 테스트) */
4
- export default class EmailTask extends Task {
5
- static queue = 'default';
6
- static retries = 3;
7
- static retryDelay = 1000;
8
-
9
- async handle(data) {
10
- console.log(`[EmailTask] 이메일 전송: to=${data.to}, subject=${data.subject}`);
11
- return { sent: true, to: data.to };
12
- }
13
-
14
- async failed(data, error) {
15
- console.error(`[EmailTask] 최종 실패: to=${data.to}, error=${error.message}`);
16
- }
17
- }
@@ -1,47 +0,0 @@
1
- import { Task } from '@fuzionx/framework';
2
- import path from 'node:path';
3
-
4
- /**
5
- * 비디오 미리보기 생성 Task (큐 비동기 처리)
6
- *
7
- * 다중 썸네일 추출 + 스프라이트 시트 합성을 백그라운드에서 실행.
8
- * 대용량 비디오에서 수백 장 추출 시 수 분 소요될 수 있으므로 큐로 위임.
9
- */
10
- export default class VideoPreviewTask extends Task {
11
- static queue = 'media';
12
- static retries = 1;
13
- static retryDelay = 3000;
14
- static timeout = 600000; // 10분
15
-
16
- async handle(data) {
17
- const { filePath, outputDir, sheetPath, interval, width, cols } = data;
18
- const app = this.app;
19
-
20
- console.log(`[VideoPreview] 시작: interval=${interval}s, width=${width}px, file=${path.basename(filePath)}`);
21
-
22
- // 1. 간격 기반 다중 썸네일 추출
23
- const thumbs = app.media.videoThumbnails(filePath, outputDir, interval, width);
24
- console.log(`[VideoPreview] 썸네일 ${thumbs.length}장 추출 완료`);
25
-
26
- // 2. 스프라이트 시트 합성
27
- if (thumbs.length > 0) {
28
- app.media.videoPreviewSheet(thumbs, sheetPath, cols, Math.floor(width / 2));
29
- console.log(`[VideoPreview] 스프라이트 시트 생성: ${sheetPath}`);
30
-
31
- // 3. 워터마크 적용 (config에 경로가 있으면)
32
- const wmPath = app.config.get('bridge.upload.watermark');
33
- if (wmPath) {
34
- const wmOpacity = app.config.get('bridge.upload.watermark_opacity', 50);
35
- app.media.applyWatermark(sheetPath, wmPath, wmOpacity, 'jpeg', 90);
36
- console.log(`[VideoPreview] 워터마크 적용 완료`);
37
- }
38
- }
39
-
40
- console.log(`[VideoPreview] 완료: ${thumbs.length}장, sheet=${sheetPath}`);
41
- return { count: thumbs.length, sheetPath };
42
- }
43
-
44
- async failed(data, error) {
45
- console.error(`[VideoPreview] 최종 실패: ${error.message}`);
46
- }
47
- }
@@ -1,18 +0,0 @@
1
- /** CPU-intensive 워커 스크립트 */
2
- import { parentPort, workerData } from 'worker_threads';
3
-
4
- function heavyCompute(n) {
5
- let result = 0;
6
- for (let i = 0; i < n; i++) {
7
- result += Math.sqrt(i) * Math.sin(i);
8
- }
9
- return result;
10
- }
11
-
12
- const result = heavyCompute(workerData?.iterations || 1_000_000);
13
-
14
- parentPort?.postMessage({
15
- result,
16
- iterations: workerData?.iterations || 1_000_000,
17
- pid: process.pid,
18
- });