@alloy-framework/core 0.4.0 β 0.14.0
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/package.json +3 -3
- package/src/app/AlloyApp.js +0 -610
- package/src/config/AlloyConfig.js +0 -131
- package/src/data/AlloyModel.js +0 -405
- package/src/data/AlloyMongoModel.js +0 -265
- package/src/data/AlloyRedisModel.js +0 -158
- package/src/data/GooseValidator.js +0 -168
- package/src/data/index.js +0 -6
- package/src/data/validationHelper.js +0 -79
- package/src/http/AlloyController.js +0 -322
- package/src/http/AlloyRouter.js +0 -130
- package/src/http/Validator.js +0 -52
- package/src/http/index.js +0 -6
- package/src/index.d.ts +0 -345
- package/src/index.js +0 -43
- package/src/security/AlloyCrypto.js +0 -96
- package/src/security/AlloySession.js +0 -81
- package/src/security/index.js +0 -5
- package/src/service/AlloyService.js +0 -171
- package/src/util/AlloyError.js +0 -23
- package/src/util/Pagination.js +0 -39
- package/src/util/index.js +0 -6
- package/src/ws/AlloyWebSocket.js +0 -130
- package/wasm/alloy_client_wasm.d.ts +0 -174
- package/wasm/alloy_client_wasm.js +0 -1215
- package/wasm/alloy_client_wasm_bg.wasm +0 -0
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
import { performance } from 'perf_hooks';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ποΈ Alloy HTTP 컨νΈλ‘€λ¬ κΈ°λ° ν΄λμ€
|
|
5
|
-
* Rust Axum μλ²μ HTTP μμ²μ μ²λ¦¬ν©λλ€.
|
|
6
|
-
* μμ²(req)κ³Ό μλ£μ(completer)λ₯Ό λ°μ JSON/HTML/Redirect λ± λ€μν μλ΅μ μμ±ν©λλ€.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* export const HomeController = createController(class HomeController extends AlloyController {
|
|
10
|
-
* async index() {
|
|
11
|
-
* this.render('index.html', { title: 'Home' });
|
|
12
|
-
* }
|
|
13
|
-
*
|
|
14
|
-
* async api() {
|
|
15
|
-
* this.success({ version: '1.0' });
|
|
16
|
-
* }
|
|
17
|
-
* });
|
|
18
|
-
*/
|
|
19
|
-
export class AlloyController {
|
|
20
|
-
/**
|
|
21
|
-
* @param {object} req - Rust AlloyRequest λ€μ΄ν°λΈ κ°μ²΄
|
|
22
|
-
* @param {object} completer - Rust AlloyCompleter λ€μ΄ν°λΈ νΈλ€
|
|
23
|
-
*/
|
|
24
|
-
constructor(req, completer) {
|
|
25
|
-
/** @type {object} λ€μ΄ν°λΈ μμ² κ°μ²΄ */
|
|
26
|
-
this.req = req;
|
|
27
|
-
/** @type {object} λ€μ΄ν°λΈ μλ΅ μλ£μ */
|
|
28
|
-
this.completer = completer;
|
|
29
|
-
/** @type {object|null} AlloyApp μ°Έμ‘° (dispatch μ μ£Όμ
) */
|
|
30
|
-
this.app = null;
|
|
31
|
-
|
|
32
|
-
/** @type {number} HTTP μλ΅ μν μ½λ */
|
|
33
|
-
this._status = 200;
|
|
34
|
-
/** @type {object} μλ΅ ν€λ */
|
|
35
|
-
this._headers = {};
|
|
36
|
-
/** @type {number} μμ² μμ μκ° (μ±λ₯ μΆμ ) */
|
|
37
|
-
this._start = performance.now();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// ββββββββββββββββββββββββββββββββββββββ
|
|
41
|
-
// π₯ μμ² μ κ·Όμ
|
|
42
|
-
// ββββββββββββββββββββββββββββββββββββββ
|
|
43
|
-
|
|
44
|
-
/** @returns {string} μμ² URL */
|
|
45
|
-
get url() { return this.req.url; }
|
|
46
|
-
|
|
47
|
-
/** @returns {string} HTTP λ©μλ */
|
|
48
|
-
get method() { return this.req.method; }
|
|
49
|
-
|
|
50
|
-
/** @returns {string} ν΄λΌμ΄μΈνΈ IP */
|
|
51
|
-
get ip() { return this.req.ip; }
|
|
52
|
-
|
|
53
|
-
/** @returns {object} URL κ²½λ‘ νλΌλ―Έν° (:id λ±) */
|
|
54
|
-
get params() { return this.req.params || {}; }
|
|
55
|
-
|
|
56
|
-
/** @returns {object} 쿼리 νλΌλ―Έν° */
|
|
57
|
-
get queries() { return this.req.query || {}; }
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* μμ² λ³Έλ¬Έ (μλ JSON / URL-encoded νμ±)
|
|
61
|
-
* @returns {object|string}
|
|
62
|
-
*/
|
|
63
|
-
get body() {
|
|
64
|
-
if (this._parsedBody !== undefined) return this._parsedBody;
|
|
65
|
-
|
|
66
|
-
// dispatchμμ validator μ²λ¦¬ μ μ΄λ―Έ νμ±λ κ²°κ³Ό μ¬μ¬μ© (μ΄μ€ νμ± λ°©μ§)
|
|
67
|
-
if (this.req.parsedBody !== undefined) {
|
|
68
|
-
this._parsedBody = this.req.parsedBody;
|
|
69
|
-
return this._parsedBody;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const raw = this.req.body;
|
|
73
|
-
if (!raw || typeof raw !== 'string') {
|
|
74
|
-
this._parsedBody = raw || {};
|
|
75
|
-
return this._parsedBody;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const trimmed = raw.trim();
|
|
79
|
-
|
|
80
|
-
// JSON κ°μ§
|
|
81
|
-
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
|
|
82
|
-
try { this._parsedBody = JSON.parse(trimmed); return this._parsedBody; } catch { /* fallthrough */ }
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// URL-encoded κ°μ§
|
|
86
|
-
if (trimmed.includes('=')) {
|
|
87
|
-
try {
|
|
88
|
-
const params = new URLSearchParams(trimmed);
|
|
89
|
-
this._parsedBody = Object.fromEntries(params.entries());
|
|
90
|
-
return this._parsedBody;
|
|
91
|
-
} catch { /* fallthrough */ }
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
this._parsedBody = raw;
|
|
95
|
-
return this._parsedBody;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* ν€λ κ° μ‘°ν (λμλ¬Έμ 무κ΄)
|
|
100
|
-
* @param {string} key
|
|
101
|
-
* @returns {string|undefined}
|
|
102
|
-
*/
|
|
103
|
-
header(key) {
|
|
104
|
-
return this.req.headers?.[key.toLowerCase()] || this.req.headers?.[key];
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* 쿼리 νλΌλ―Έν° λ¨μΌ μ‘°ν
|
|
109
|
-
* @param {string} key
|
|
110
|
-
* @returns {string|null}
|
|
111
|
-
*/
|
|
112
|
-
query(key) {
|
|
113
|
-
return this.req.query ? this.req.query[key] : null;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// ββββββββββββββββββββββββββββββββββββββ
|
|
117
|
-
// π μΈμ
ν¬νΌ
|
|
118
|
-
// ββββββββββββββββββββββββββββββββββββββ
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* μΈμ
κ° μ€μ
|
|
122
|
-
* @param {string} key
|
|
123
|
-
* @param {any} value - κ°μ²΄λ μλ JSON μ§λ ¬ν
|
|
124
|
-
*/
|
|
125
|
-
setSession(key, value) {
|
|
126
|
-
this.req.session = this.req.session || {};
|
|
127
|
-
this.req.session[key] = typeof value === 'object' ? JSON.stringify(value) : value;
|
|
128
|
-
this._sessionDirty = true; // μΈμ
λ³κ²½ μ write-back νλκ·Έ
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* μΈμ
κ° μ‘°ν (μλ μμ§λ ¬ν)
|
|
133
|
-
* @param {string} key
|
|
134
|
-
* @returns {any}
|
|
135
|
-
*/
|
|
136
|
-
getSession(key) {
|
|
137
|
-
if (!this.req.session) return null;
|
|
138
|
-
const val = this.req.session[key];
|
|
139
|
-
if (val == null) return null;
|
|
140
|
-
if (typeof val === 'string') {
|
|
141
|
-
try { return JSON.parse(val); } catch { return val; }
|
|
142
|
-
}
|
|
143
|
-
return val;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// ββββββββββββββββββββββββββββββββββββββ
|
|
147
|
-
// π€ μλ΅ ν¬νΌ
|
|
148
|
-
// ββββββββββββββββββββββββββββββββββββββ
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* HTTP μν μ½λ μ€μ (체μ΄λ)
|
|
152
|
-
* @param {number} code
|
|
153
|
-
* @returns {this}
|
|
154
|
-
*/
|
|
155
|
-
status(code) {
|
|
156
|
-
this._status = code;
|
|
157
|
-
return this;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* μλ΅ ν€λ μ€μ (체μ΄λ)
|
|
162
|
-
* @param {string} key
|
|
163
|
-
* @param {string} value
|
|
164
|
-
* @returns {this}
|
|
165
|
-
*/
|
|
166
|
-
setHeader(key, value) {
|
|
167
|
-
this._headers[key] = value;
|
|
168
|
-
return this;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* JSON μλ΅ μ μ‘
|
|
173
|
-
* @param {object} data
|
|
174
|
-
*/
|
|
175
|
-
json(data) {
|
|
176
|
-
this.setHeader('Content-Type', 'application/json');
|
|
177
|
-
this.send(JSON.stringify(data));
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Raw Body μλ΅ μ μ‘
|
|
182
|
-
* @param {string} body
|
|
183
|
-
*/
|
|
184
|
-
send(body) {
|
|
185
|
-
this._finalize();
|
|
186
|
-
this.completer.done({
|
|
187
|
-
status: this._status,
|
|
188
|
-
headers: this._headers,
|
|
189
|
-
body: typeof body === 'string' ? body : String(body),
|
|
190
|
-
session: this._sessionDirty ? this.req.session : undefined,
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* HTML μλ΅ μ μ‘
|
|
196
|
-
* @param {string} html - HTML λ¬Έμμ΄
|
|
197
|
-
*/
|
|
198
|
-
html(html) {
|
|
199
|
-
this.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
200
|
-
this.send(html);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Tera ν
νλ¦Ώ λ λλ§ (Rust μμ§ νμ©)
|
|
205
|
-
* @param {string} view - ν
νλ¦Ώ μ΄λ¦ (μ: 'index.html')
|
|
206
|
-
* @param {object} [data={}] - 컨ν
μ€νΈ λ°μ΄ν°
|
|
207
|
-
*/
|
|
208
|
-
render(view, data = {}) {
|
|
209
|
-
// ν
λ§ λ―Έλ€μ¨μ΄ μ§μ
|
|
210
|
-
if (this.req.theme && !view.startsWith('/') && !view.startsWith(this.req.theme)) {
|
|
211
|
-
view = `${this.req.theme}/${view}`;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
this._finalize();
|
|
215
|
-
this.completer.done({
|
|
216
|
-
status: this._status,
|
|
217
|
-
headers: this._headers,
|
|
218
|
-
body: '',
|
|
219
|
-
template: view,
|
|
220
|
-
context: JSON.stringify(data),
|
|
221
|
-
session: this._sessionDirty ? this.req.session : undefined,
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* 리λ€μ΄λ νΈ
|
|
227
|
-
* @param {string} url
|
|
228
|
-
* @param {number} [statusCode=302]
|
|
229
|
-
*/
|
|
230
|
-
redirect(url, statusCode = 302) {
|
|
231
|
-
this.status(statusCode);
|
|
232
|
-
this.setHeader('Location', url);
|
|
233
|
-
this.send('');
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// ββββββββββββββββββββββββββββββββββββββ
|
|
237
|
-
// π νμ€ μλ΅ ν¬λ§·
|
|
238
|
-
// ββββββββββββββββββββββββββββββββββββββ
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* μ±κ³΅ μλ΅
|
|
242
|
-
* @param {any} data
|
|
243
|
-
* @param {string} [message='Ok']
|
|
244
|
-
* @param {string} [code='SUCCESS']
|
|
245
|
-
*/
|
|
246
|
-
success(data, message = 'Ok', code = 'SUCCESS') {
|
|
247
|
-
this.json({
|
|
248
|
-
status: this._status,
|
|
249
|
-
code,
|
|
250
|
-
message,
|
|
251
|
-
timestamp: Date.now(),
|
|
252
|
-
data,
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* μλ¬ μλ΅
|
|
258
|
-
* @param {string} message
|
|
259
|
-
* @param {string} [code='ERR_GENERIC']
|
|
260
|
-
* @param {number} [statusCode=400]
|
|
261
|
-
* @param {any} [data=null]
|
|
262
|
-
*/
|
|
263
|
-
error(message, code = 'ERR_GENERIC', statusCode = 400, data = null) {
|
|
264
|
-
this.status(statusCode);
|
|
265
|
-
this.json({
|
|
266
|
-
status: this._status,
|
|
267
|
-
code,
|
|
268
|
-
message,
|
|
269
|
-
timestamp: Date.now(),
|
|
270
|
-
data,
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// ββββββββββββββββββββββββββββββββββββββ
|
|
275
|
-
// π§ λ΄λΆ λ©μλ
|
|
276
|
-
// ββββββββββββββββββββββββββββββββββββββ
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* μλ΅ μ§μ μ²λ¦¬ (μ±λ₯ ν€λ μΆκ° λ±)
|
|
280
|
-
* @private
|
|
281
|
-
*/
|
|
282
|
-
_finalize() {
|
|
283
|
-
const duration = performance.now() - this._start;
|
|
284
|
-
this.setHeader('X-Alloy-Time', `${duration.toFixed(2)}ms`);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* π 컨νΈλ‘€λ¬ Proxy ν©ν 리
|
|
290
|
-
* `Controller.methodName` β `{ controller, method }` λΌμ°νΈ λμ€ν¬λ¦½ν° μλ λ³ν
|
|
291
|
-
*
|
|
292
|
-
* @example
|
|
293
|
-
* export const Home = createController(class extends AlloyController {
|
|
294
|
-
* async index() { this.html('<h1>Hello</h1>'); }
|
|
295
|
-
* async about() { this.html('<h1>About</h1>'); }
|
|
296
|
-
* });
|
|
297
|
-
*
|
|
298
|
-
* // λΌμ°νΈ λ±λ‘
|
|
299
|
-
* router.get('/', Home); // β index() νΈμΆ
|
|
300
|
-
* router.get('/about', Home.about); // β about() νΈμΆ
|
|
301
|
-
*
|
|
302
|
-
* @param {typeof AlloyController} ControllerClass
|
|
303
|
-
* @returns {Proxy}
|
|
304
|
-
*/
|
|
305
|
-
export function createController(ControllerClass) {
|
|
306
|
-
return new Proxy(ControllerClass, {
|
|
307
|
-
get(target, prop, receiver) {
|
|
308
|
-
// prototype λ©μλ β λΌμ°νΈ λμ€ν¬λ¦½ν° λ°ν
|
|
309
|
-
if (
|
|
310
|
-
typeof prop === 'string' &&
|
|
311
|
-
prop !== 'prototype' &&
|
|
312
|
-
prop !== 'name' &&
|
|
313
|
-
prop !== 'length' &&
|
|
314
|
-
prop !== 'constructor' &&
|
|
315
|
-
typeof target.prototype[prop] === 'function'
|
|
316
|
-
) {
|
|
317
|
-
return { controller: target, method: prop };
|
|
318
|
-
}
|
|
319
|
-
return Reflect.get(target, prop, receiver);
|
|
320
|
-
},
|
|
321
|
-
});
|
|
322
|
-
}
|
package/src/http/AlloyRouter.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { isMainThread } from 'worker_threads';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* URL κ²½λ‘ κ²°ν© (path.joinμ OS νμΌ κ²½λ‘μ©μ΄λ―λ‘ URLμ λΆμ ν©)
|
|
5
|
-
* @param {...string} segments - κ²°ν©ν κ²½λ‘ μΈκ·Έλ¨ΌνΈ
|
|
6
|
-
* @returns {string} μ κ·νλ URL κ²½λ‘
|
|
7
|
-
* @private
|
|
8
|
-
*/
|
|
9
|
-
function joinUrl(...segments) {
|
|
10
|
-
return ('/' + segments.join('/')).replace(/\/+/g, '/');
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* πΊοΈ Alloy λΌμ°ν°
|
|
15
|
-
* HTTP/HTTPS λΌμ°νΈλ₯Ό λ±λ‘νκ³ Rust λ€μ΄ν°λΈ λΌμ°ν°μ μ λ¬ν©λλ€.
|
|
16
|
-
* `controllers/` λλ ν 리μ Route νμΌμμ μ¬μ©ν©λλ€.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* // controllers/HomeRoute.js
|
|
20
|
-
* import { HomeController } from './HomeController.js';
|
|
21
|
-
*
|
|
22
|
-
* export default (router) => {
|
|
23
|
-
* router.get('/', HomeController);
|
|
24
|
-
* router.get('/about', HomeController.about);
|
|
25
|
-
* router.get('/api/status', HomeController.status);
|
|
26
|
-
* };
|
|
27
|
-
*/
|
|
28
|
-
export class AlloyRouter {
|
|
29
|
-
/**
|
|
30
|
-
* @param {object} app - AlloyApp μΈμ€ν΄μ€
|
|
31
|
-
*/
|
|
32
|
-
constructor(app) {
|
|
33
|
-
/** @type {object} AlloyApp μ°Έμ‘° */
|
|
34
|
-
this.app = app;
|
|
35
|
-
/** @type {string} νμ¬ URL ν리ν½μ€ (group λ΄λΆμμ μ¬μ©) */
|
|
36
|
-
this.prefix = '';
|
|
37
|
-
/** @type {Map<number, object>} νΈλ€λ¬ ID β { handler, middlewares, validator } */
|
|
38
|
-
this.handlers = new Map();
|
|
39
|
-
/** @type {Array} κΈλ‘λ² λ―Έλ€μ¨μ΄ μ€ν */
|
|
40
|
-
this.middlewares = [];
|
|
41
|
-
/** @type {number} νΈλ€λ¬ ID μΉ΄μ΄ν° */
|
|
42
|
-
this.handlerIdCounter = 1000;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* κΈλ‘λ² λ―Έλ€μ¨μ΄ λ±λ‘
|
|
47
|
-
* @param {object|Function} middleware
|
|
48
|
-
*/
|
|
49
|
-
use(middleware) {
|
|
50
|
-
this.middlewares.push(middleware);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* λΌμ°νΈ κ·Έλ£Ή (κ³΅ν΅ ν리ν½μ€)
|
|
55
|
-
* @param {string} prefix - URL ν리ν½μ€
|
|
56
|
-
* @param {Function} callback - (router) => { ... }
|
|
57
|
-
*/
|
|
58
|
-
group(prefix, callback) {
|
|
59
|
-
const parentPrefix = this.prefix;
|
|
60
|
-
this.prefix = joinUrl(parentPrefix, prefix);
|
|
61
|
-
callback(this);
|
|
62
|
-
this.prefix = parentPrefix;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** GET λΌμ°νΈ */
|
|
66
|
-
get(path, ...handlers) { this.register('GET', path, ...handlers); }
|
|
67
|
-
/** POST λΌμ°νΈ */
|
|
68
|
-
post(path, ...handlers) { this.register('POST', path, ...handlers); }
|
|
69
|
-
/** PUT λΌμ°νΈ */
|
|
70
|
-
put(path, ...handlers) { this.register('PUT', path, ...handlers); }
|
|
71
|
-
/** DELETE λΌμ°νΈ */
|
|
72
|
-
delete(path, ...handlers) { this.register('DELETE', path, ...handlers); }
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* λΌμ°νΈ λ±λ‘ (λ€μ΄ν°λΈ Rust λΌμ°ν°μ μ λ¬)
|
|
76
|
-
*
|
|
77
|
-
* @param {string} method - HTTP λ©μλ
|
|
78
|
-
* @param {string} path - URL κ²½λ‘
|
|
79
|
-
* @param {...any} args - [λ―Έλ€μ¨μ΄ λ°°μ΄?, μ΅μ
?, νΈλ€λ¬]
|
|
80
|
-
*/
|
|
81
|
-
register(method, path, ...args) {
|
|
82
|
-
// κ²½λ‘ μ κ·ν
|
|
83
|
-
let fullPath = joinUrl(this.prefix, path);
|
|
84
|
-
if (!fullPath.startsWith('/')) fullPath = '/' + fullPath;
|
|
85
|
-
// trailing slash μ κ±° (λ£¨νΈ '/' μ μΈ) β path.joinμ΄ URL κ²½λ‘μ μ¬λμλ₯Ό μΆκ°νλ λ¬Έμ λ°©μ§
|
|
86
|
-
if (fullPath.length > 1 && fullPath.endsWith('/')) fullPath = fullPath.slice(0, -1);
|
|
87
|
-
|
|
88
|
-
// λ§μ§λ§ μΈμ = νΈλ€λ¬
|
|
89
|
-
let handler = args.pop();
|
|
90
|
-
|
|
91
|
-
// νμνΈν: (Controller, 'methodName') ν¨ν΄
|
|
92
|
-
if (typeof handler === 'string') {
|
|
93
|
-
const methodName = handler;
|
|
94
|
-
const controllerClass = args.pop();
|
|
95
|
-
handler = { controller: controllerClass, method: methodName };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// λ―Έλ€μ¨μ΄ + validator λΆλ¦¬
|
|
99
|
-
let validator = null;
|
|
100
|
-
const middlewares = [];
|
|
101
|
-
|
|
102
|
-
for (const arg of args) {
|
|
103
|
-
if (Array.isArray(arg)) {
|
|
104
|
-
middlewares.push(...arg);
|
|
105
|
-
} else if (arg && typeof arg === 'object' && !Array.isArray(arg) && (arg.validator || arg.validate)) {
|
|
106
|
-
validator = arg.validator || arg.validate;
|
|
107
|
-
} else if (arg) {
|
|
108
|
-
middlewares.push(arg);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// νΈλ€λ¬ ID λΆμ¬ + λ§΅ μ μ₯
|
|
113
|
-
const id = this.handlerIdCounter++;
|
|
114
|
-
this.handlers.set(id, { handler, middlewares, validator });
|
|
115
|
-
|
|
116
|
-
// Rust λ€μ΄ν°λΈ λΌμ°ν°μ λ±λ‘ (λ©μΈ μ€λ λμμλ§)
|
|
117
|
-
if (isMainThread) {
|
|
118
|
-
this.app.native.registerRoute(method, fullPath, id);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* νΈλ€λ¬ IDλ‘ νΈλ€λ¬ λ°μ΄ν° μ‘°ν
|
|
124
|
-
* @param {number} id
|
|
125
|
-
* @returns {object|undefined}
|
|
126
|
-
*/
|
|
127
|
-
getHandler(id) {
|
|
128
|
-
return this.handlers.get(id);
|
|
129
|
-
}
|
|
130
|
-
}
|
package/src/http/Validator.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import Joi from 'joi';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* β
Alloy μμ² κ²μ¦κΈ°
|
|
5
|
-
* Joi μ€ν€λ§λ₯Ό νμ©ν λ°μ΄ν° κ²μ¦ μ νΈλ¦¬ν°μ
λλ€.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* class Users extends AlloyModel {
|
|
9
|
-
* static schema = Joi.object({
|
|
10
|
-
* username: Joi.string().required(),
|
|
11
|
-
* email: Joi.string().email().required(),
|
|
12
|
-
* });
|
|
13
|
-
* }
|
|
14
|
-
*/
|
|
15
|
-
export class Validator {
|
|
16
|
-
/**
|
|
17
|
-
* Joi μ€ν€λ§λ‘ λ°μ΄ν° κ²μ¦ + μ μ
|
|
18
|
-
* @param {import('joi').ObjectSchema} schema - Joi μ€ν€λ§
|
|
19
|
-
* @param {object} data - κ²μ¦ν λ°μ΄ν°
|
|
20
|
-
* @param {boolean} [isPartial=false] - trueλ©΄ λλ½ νλ νμ© (UPDATEμ©)
|
|
21
|
-
* @returns {object} κ²μ¦ + μ μ λ λ°μ΄ν°
|
|
22
|
-
* @throws {Error} κ²μ¦ μ€ν¨ μ
|
|
23
|
-
*/
|
|
24
|
-
static validate(schema, data, isPartial = false) {
|
|
25
|
-
const options = {
|
|
26
|
-
abortEarly: false, // λͺ¨λ μλ¬ μμ§
|
|
27
|
-
stripUnknown: true, // μ€ν€λ§μ μλ νλ μ κ±°
|
|
28
|
-
allowUnknown: false,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// UPDATE μ partial κ²μ¦ β λλ½ νλ νμ©
|
|
32
|
-
const target = isPartial ? schema.fork(
|
|
33
|
-
Object.keys(schema.describe().keys),
|
|
34
|
-
(s) => s.optional(),
|
|
35
|
-
) : schema;
|
|
36
|
-
|
|
37
|
-
const { error, value } = target.validate(data, options);
|
|
38
|
-
|
|
39
|
-
if (error) {
|
|
40
|
-
const details = error.details.map(d => d.message).join(', ');
|
|
41
|
-
const err = new Error(`Validation Error: ${details}`);
|
|
42
|
-
err.statusCode = 400; // Bad Request
|
|
43
|
-
err.code = 'VALIDATION_ERROR';
|
|
44
|
-
throw err;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return value;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Joiλ₯Ό re-exportνμ¬ SDK μ¬μ©μκ° λ³λ μ€μΉ μμ΄ μ¬μ© κ°λ₯
|
|
52
|
-
export { Joi };
|