@fuzionx/framework 0.1.39 → 0.1.41
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/README.md +501 -501
- package/bin/fx.js +12 -12
- package/cli/db-sync.js +99 -99
- package/cli/index.js +493 -493
- package/cli/templates/make/app/controllers/HomeController.js +14 -14
- package/cli/templates/make/app/routes/api.js +7 -7
- package/cli/templates/make/app/routes/web.js +5 -5
- package/cli/templates/make/app/views/default/errors/404.html +11 -11
- package/cli/templates/make/app/views/default/errors/500.html +14 -14
- package/cli/templates/make/app/views/default/layouts/main.html +22 -22
- package/cli/templates/make/app/views/default/pages/home.html +11 -11
- package/cli/templates/make/controller.js.tpl +40 -40
- package/cli/templates/make/event.js.tpl +8 -8
- package/cli/templates/make/job.js.tpl +10 -10
- package/cli/templates/make/middleware.js.tpl +10 -10
- package/cli/templates/make/model.js.tpl +15 -15
- package/cli/templates/make/service.js.tpl +15 -15
- package/cli/templates/make/task.js.tpl +15 -15
- package/cli/templates/make/test.js.tpl +7 -7
- package/cli/templates/make/worker.js.tpl +14 -14
- package/cli/templates/make/ws.js.tpl +18 -18
- package/index.js +67 -67
- package/lib/core/AppError.js +46 -46
- package/lib/core/Application.js +1006 -1006
- package/lib/core/AutoLoader.js +226 -226
- package/lib/core/Base.js +64 -64
- package/lib/core/Config.js +228 -228
- package/lib/core/Context.js +484 -484
- package/lib/database/ConnectionManager.js +208 -208
- package/lib/database/MariaModel.js +29 -29
- package/lib/database/Model.js +247 -247
- package/lib/database/ModelRegistry.js +72 -72
- package/lib/database/MongoModel.js +232 -232
- package/lib/database/Pagination.js +37 -37
- package/lib/database/PostgreModel.js +29 -29
- package/lib/database/QueryBuilder.js +172 -172
- package/lib/database/SQLiteModel.js +27 -27
- package/lib/database/SqlModel.js +257 -257
- package/lib/database/SqlQueryBuilder.js +332 -332
- package/lib/helpers/CryptoHelper.js +48 -48
- package/lib/helpers/FileHelper.js +61 -61
- package/lib/helpers/HashHelper.js +39 -39
- package/lib/helpers/I18nHelper.js +174 -174
- package/lib/helpers/Logger.js +108 -108
- package/lib/helpers/MediaHelper.js +84 -84
- package/lib/http/Controller.js +34 -34
- package/lib/http/ErrorHandler.js +136 -136
- package/lib/http/Middleware.js +43 -43
- package/lib/http/Router.js +109 -109
- package/lib/http/Validation.js +125 -125
- package/lib/middleware/apiAuth.js +79 -79
- package/lib/middleware/auth.js +42 -42
- package/lib/middleware/bodyParser.js +19 -19
- package/lib/middleware/cors.js +47 -47
- package/lib/middleware/csrf.js +32 -32
- package/lib/middleware/index.js +13 -13
- package/lib/middleware/session.js +27 -27
- package/lib/middleware/theme.js +20 -20
- package/lib/realtime/RoomManager.js +85 -85
- package/lib/realtime/WsHandler.js +107 -107
- package/lib/schedule/Job.js +38 -38
- package/lib/schedule/Queue.js +103 -103
- package/lib/schedule/Scheduler.js +171 -171
- package/lib/schedule/Task.js +39 -39
- package/lib/schedule/WorkerPool.js +225 -225
- package/lib/services/EventBus.js +94 -94
- package/lib/services/Service.js +261 -261
- package/lib/services/Storage.js +112 -112
- package/lib/utilities/ArrUtil.js +112 -112
- package/lib/utilities/DateUtil.js +98 -98
- package/lib/utilities/FunctionUtil.js +119 -119
- package/lib/utilities/NumUtil.js +75 -75
- package/lib/utilities/ObjectUtil.js +170 -170
- package/lib/utilities/PaginationUtil.js +81 -81
- package/lib/utilities/StrUtil.js +105 -105
- package/lib/utilities/index.js +18 -18
- package/lib/view/OpenAPI.js +231 -231
- package/lib/view/View.js +83 -83
- package/package.json +2 -2
- package/testing/index.js +232 -232
|
@@ -1,119 +1,119 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FunctionUtil — 함수 순수 유틸리티
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Debounce — 마지막 호출 후 delay ms 뒤 실행
|
|
7
|
-
* @param {Function} fn
|
|
8
|
-
* @param {number} delay - ms
|
|
9
|
-
* @returns {Function}
|
|
10
|
-
*/
|
|
11
|
-
export function debounce(fn, delay = 300) {
|
|
12
|
-
let timer;
|
|
13
|
-
const debounced = (...args) => {
|
|
14
|
-
clearTimeout(timer);
|
|
15
|
-
timer = setTimeout(() => fn(...args), delay);
|
|
16
|
-
};
|
|
17
|
-
debounced.cancel = () => clearTimeout(timer);
|
|
18
|
-
return debounced;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Throttle — delay ms 간격으로 최대 1회 실행
|
|
23
|
-
* @param {Function} fn
|
|
24
|
-
* @param {number} delay - ms
|
|
25
|
-
* @returns {Function}
|
|
26
|
-
*/
|
|
27
|
-
export function throttle(fn, delay = 300) {
|
|
28
|
-
let last = 0;
|
|
29
|
-
let timer;
|
|
30
|
-
return (...args) => {
|
|
31
|
-
const now = Date.now();
|
|
32
|
-
const remaining = delay - (now - last);
|
|
33
|
-
clearTimeout(timer);
|
|
34
|
-
if (remaining <= 0) {
|
|
35
|
-
last = now;
|
|
36
|
-
fn(...args);
|
|
37
|
-
} else {
|
|
38
|
-
timer = setTimeout(() => {
|
|
39
|
-
last = Date.now();
|
|
40
|
-
fn(...args);
|
|
41
|
-
}, remaining);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* 한 번만 실행
|
|
48
|
-
* @param {Function} fn
|
|
49
|
-
* @returns {Function}
|
|
50
|
-
*/
|
|
51
|
-
export function once(fn) {
|
|
52
|
-
let called = false;
|
|
53
|
-
let result;
|
|
54
|
-
return (...args) => {
|
|
55
|
-
if (called) return result;
|
|
56
|
-
called = true;
|
|
57
|
-
result = fn(...args);
|
|
58
|
-
return result;
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Promise 타임아웃 래퍼
|
|
64
|
-
* @param {Promise} promise
|
|
65
|
-
* @param {number} ms
|
|
66
|
-
* @param {string} [message='Timeout']
|
|
67
|
-
* @returns {Promise}
|
|
68
|
-
*/
|
|
69
|
-
export function timeout(promise, ms, message = 'Timeout') {
|
|
70
|
-
return Promise.race([
|
|
71
|
-
promise,
|
|
72
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error(message)), ms)),
|
|
73
|
-
]);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* 딜레이 (async sleep)
|
|
78
|
-
* @param {number} ms
|
|
79
|
-
* @returns {Promise<void>}
|
|
80
|
-
*/
|
|
81
|
-
export function sleep(ms) {
|
|
82
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* 함수 파이프라인 (왼→오) — 순차 실행
|
|
87
|
-
* @param {...Function} fns
|
|
88
|
-
* @returns {Function}
|
|
89
|
-
*
|
|
90
|
-
* @example pipe(addOne, double, square)(2) → square(double(addOne(2)))
|
|
91
|
-
*/
|
|
92
|
-
export function pipe(...fns) {
|
|
93
|
-
return (x) => fns.reduce((v, fn) => fn(v), x);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* 메모이제이션 — 결과 캐싱
|
|
98
|
-
* @param {Function} fn
|
|
99
|
-
* @param {Function} [keyFn] - 캐시 키 생성 함수 (기본: 첫 인자)
|
|
100
|
-
* @returns {Function}
|
|
101
|
-
*/
|
|
102
|
-
export function memoize(fn, keyFn) {
|
|
103
|
-
const cache = new Map();
|
|
104
|
-
const memoized = (...args) => {
|
|
105
|
-
const key = keyFn ? keyFn(...args) : args[0];
|
|
106
|
-
if (cache.has(key)) return cache.get(key);
|
|
107
|
-
const result = fn(...args);
|
|
108
|
-
cache.set(key, result);
|
|
109
|
-
return result;
|
|
110
|
-
};
|
|
111
|
-
memoized.cache = cache;
|
|
112
|
-
memoized.clear = () => cache.clear();
|
|
113
|
-
return memoized;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* noop — 아무것도 하지 않는 함수
|
|
118
|
-
*/
|
|
119
|
-
export function noop() {}
|
|
1
|
+
/**
|
|
2
|
+
* FunctionUtil — 함수 순수 유틸리티
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Debounce — 마지막 호출 후 delay ms 뒤 실행
|
|
7
|
+
* @param {Function} fn
|
|
8
|
+
* @param {number} delay - ms
|
|
9
|
+
* @returns {Function}
|
|
10
|
+
*/
|
|
11
|
+
export function debounce(fn, delay = 300) {
|
|
12
|
+
let timer;
|
|
13
|
+
const debounced = (...args) => {
|
|
14
|
+
clearTimeout(timer);
|
|
15
|
+
timer = setTimeout(() => fn(...args), delay);
|
|
16
|
+
};
|
|
17
|
+
debounced.cancel = () => clearTimeout(timer);
|
|
18
|
+
return debounced;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Throttle — delay ms 간격으로 최대 1회 실행
|
|
23
|
+
* @param {Function} fn
|
|
24
|
+
* @param {number} delay - ms
|
|
25
|
+
* @returns {Function}
|
|
26
|
+
*/
|
|
27
|
+
export function throttle(fn, delay = 300) {
|
|
28
|
+
let last = 0;
|
|
29
|
+
let timer;
|
|
30
|
+
return (...args) => {
|
|
31
|
+
const now = Date.now();
|
|
32
|
+
const remaining = delay - (now - last);
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
if (remaining <= 0) {
|
|
35
|
+
last = now;
|
|
36
|
+
fn(...args);
|
|
37
|
+
} else {
|
|
38
|
+
timer = setTimeout(() => {
|
|
39
|
+
last = Date.now();
|
|
40
|
+
fn(...args);
|
|
41
|
+
}, remaining);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 한 번만 실행
|
|
48
|
+
* @param {Function} fn
|
|
49
|
+
* @returns {Function}
|
|
50
|
+
*/
|
|
51
|
+
export function once(fn) {
|
|
52
|
+
let called = false;
|
|
53
|
+
let result;
|
|
54
|
+
return (...args) => {
|
|
55
|
+
if (called) return result;
|
|
56
|
+
called = true;
|
|
57
|
+
result = fn(...args);
|
|
58
|
+
return result;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Promise 타임아웃 래퍼
|
|
64
|
+
* @param {Promise} promise
|
|
65
|
+
* @param {number} ms
|
|
66
|
+
* @param {string} [message='Timeout']
|
|
67
|
+
* @returns {Promise}
|
|
68
|
+
*/
|
|
69
|
+
export function timeout(promise, ms, message = 'Timeout') {
|
|
70
|
+
return Promise.race([
|
|
71
|
+
promise,
|
|
72
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(message)), ms)),
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 딜레이 (async sleep)
|
|
78
|
+
* @param {number} ms
|
|
79
|
+
* @returns {Promise<void>}
|
|
80
|
+
*/
|
|
81
|
+
export function sleep(ms) {
|
|
82
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 함수 파이프라인 (왼→오) — 순차 실행
|
|
87
|
+
* @param {...Function} fns
|
|
88
|
+
* @returns {Function}
|
|
89
|
+
*
|
|
90
|
+
* @example pipe(addOne, double, square)(2) → square(double(addOne(2)))
|
|
91
|
+
*/
|
|
92
|
+
export function pipe(...fns) {
|
|
93
|
+
return (x) => fns.reduce((v, fn) => fn(v), x);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 메모이제이션 — 결과 캐싱
|
|
98
|
+
* @param {Function} fn
|
|
99
|
+
* @param {Function} [keyFn] - 캐시 키 생성 함수 (기본: 첫 인자)
|
|
100
|
+
* @returns {Function}
|
|
101
|
+
*/
|
|
102
|
+
export function memoize(fn, keyFn) {
|
|
103
|
+
const cache = new Map();
|
|
104
|
+
const memoized = (...args) => {
|
|
105
|
+
const key = keyFn ? keyFn(...args) : args[0];
|
|
106
|
+
if (cache.has(key)) return cache.get(key);
|
|
107
|
+
const result = fn(...args);
|
|
108
|
+
cache.set(key, result);
|
|
109
|
+
return result;
|
|
110
|
+
};
|
|
111
|
+
memoized.cache = cache;
|
|
112
|
+
memoized.clear = () => cache.clear();
|
|
113
|
+
return memoized;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* noop — 아무것도 하지 않는 함수
|
|
118
|
+
*/
|
|
119
|
+
export function noop() {}
|
package/lib/utilities/NumUtil.js
CHANGED
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* NumUtil — 숫자 순수 유틸리티
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 범위 제한 (clamp)
|
|
7
|
-
* @param {number} n
|
|
8
|
-
* @param {number} min
|
|
9
|
-
* @param {number} max
|
|
10
|
-
* @returns {number}
|
|
11
|
-
*/
|
|
12
|
-
export function clamp(n, min, max) {
|
|
13
|
-
return Math.min(Math.max(n, min), max);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 범위 내 랜덤 정수
|
|
18
|
-
* @param {number} min
|
|
19
|
-
* @param {number} max
|
|
20
|
-
* @returns {number}
|
|
21
|
-
*/
|
|
22
|
-
export function random(min = 0, max = 100) {
|
|
23
|
-
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 숫자 포맷 (로케일)
|
|
28
|
-
* @param {number} n
|
|
29
|
-
* @param {string} [locale='ko-KR']
|
|
30
|
-
* @returns {string}
|
|
31
|
-
*
|
|
32
|
-
* @example format(1234567) → '1,234,567'
|
|
33
|
-
*/
|
|
34
|
-
export function format(n, locale = 'ko-KR') {
|
|
35
|
-
return new Intl.NumberFormat(locale).format(n);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* 바이트 → 읽기 쉬운 단위 변환
|
|
40
|
-
* @param {number} bytes
|
|
41
|
-
* @param {number} [decimals=2]
|
|
42
|
-
* @returns {string}
|
|
43
|
-
*
|
|
44
|
-
* @example fileSize(1536) → '1.50 KB'
|
|
45
|
-
*/
|
|
46
|
-
export function fileSize(bytes, decimals = 2) {
|
|
47
|
-
if (bytes === 0) return '0 B';
|
|
48
|
-
const k = 1024;
|
|
49
|
-
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
50
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
51
|
-
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(decimals))} ${units[i]}`;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* 퍼센트 계산
|
|
56
|
-
* @param {number} part
|
|
57
|
-
* @param {number} total
|
|
58
|
-
* @param {number} [decimals=1]
|
|
59
|
-
* @returns {number}
|
|
60
|
-
*/
|
|
61
|
-
export function percent(part, total, decimals = 1) {
|
|
62
|
-
if (total === 0) return 0;
|
|
63
|
-
return parseFloat(((part / total) * 100).toFixed(decimals));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* 안전한 정수 파싱
|
|
68
|
-
* @param {*} value
|
|
69
|
-
* @param {number} [fallback=0]
|
|
70
|
-
* @returns {number}
|
|
71
|
-
*/
|
|
72
|
-
export function toInt(value, fallback = 0) {
|
|
73
|
-
const n = parseInt(value, 10);
|
|
74
|
-
return isNaN(n) ? fallback : n;
|
|
75
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* NumUtil — 숫자 순수 유틸리티
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 범위 제한 (clamp)
|
|
7
|
+
* @param {number} n
|
|
8
|
+
* @param {number} min
|
|
9
|
+
* @param {number} max
|
|
10
|
+
* @returns {number}
|
|
11
|
+
*/
|
|
12
|
+
export function clamp(n, min, max) {
|
|
13
|
+
return Math.min(Math.max(n, min), max);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 범위 내 랜덤 정수
|
|
18
|
+
* @param {number} min
|
|
19
|
+
* @param {number} max
|
|
20
|
+
* @returns {number}
|
|
21
|
+
*/
|
|
22
|
+
export function random(min = 0, max = 100) {
|
|
23
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 숫자 포맷 (로케일)
|
|
28
|
+
* @param {number} n
|
|
29
|
+
* @param {string} [locale='ko-KR']
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*
|
|
32
|
+
* @example format(1234567) → '1,234,567'
|
|
33
|
+
*/
|
|
34
|
+
export function format(n, locale = 'ko-KR') {
|
|
35
|
+
return new Intl.NumberFormat(locale).format(n);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 바이트 → 읽기 쉬운 단위 변환
|
|
40
|
+
* @param {number} bytes
|
|
41
|
+
* @param {number} [decimals=2]
|
|
42
|
+
* @returns {string}
|
|
43
|
+
*
|
|
44
|
+
* @example fileSize(1536) → '1.50 KB'
|
|
45
|
+
*/
|
|
46
|
+
export function fileSize(bytes, decimals = 2) {
|
|
47
|
+
if (bytes === 0) return '0 B';
|
|
48
|
+
const k = 1024;
|
|
49
|
+
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
50
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
51
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(decimals))} ${units[i]}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 퍼센트 계산
|
|
56
|
+
* @param {number} part
|
|
57
|
+
* @param {number} total
|
|
58
|
+
* @param {number} [decimals=1]
|
|
59
|
+
* @returns {number}
|
|
60
|
+
*/
|
|
61
|
+
export function percent(part, total, decimals = 1) {
|
|
62
|
+
if (total === 0) return 0;
|
|
63
|
+
return parseFloat(((part / total) * 100).toFixed(decimals));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 안전한 정수 파싱
|
|
68
|
+
* @param {*} value
|
|
69
|
+
* @param {number} [fallback=0]
|
|
70
|
+
* @returns {number}
|
|
71
|
+
*/
|
|
72
|
+
export function toInt(value, fallback = 0) {
|
|
73
|
+
const n = parseInt(value, 10);
|
|
74
|
+
return isNaN(n) ? fallback : n;
|
|
75
|
+
}
|