moost 0.0.1-beta.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.
Files changed (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -0
  3. package/dist/moost.cjs.prod.js +742 -0
  4. package/dist/moost.d.ts +274 -0
  5. package/dist/moost.esm-bundler.js +693 -0
  6. package/dist/src/binding/bind-controller.d.ts +13 -0
  7. package/dist/src/binding/bind-controller.d.ts.map +1 -0
  8. package/dist/src/binding/bind-handler.d.ts +18 -0
  9. package/dist/src/binding/bind-handler.d.ts.map +1 -0
  10. package/dist/src/binding/index.d.ts +3 -0
  11. package/dist/src/binding/index.d.ts.map +1 -0
  12. package/dist/src/binding/tests/binding.spec.d.ts +2 -0
  13. package/dist/src/binding/tests/binding.spec.d.ts.map +1 -0
  14. package/dist/src/binding/utils.d.ts +3 -0
  15. package/dist/src/binding/utils.d.ts.map +1 -0
  16. package/dist/src/class-function/class-function.d.ts +4 -0
  17. package/dist/src/class-function/class-function.d.ts.map +1 -0
  18. package/dist/src/class-function/index.d.ts +2 -0
  19. package/dist/src/class-function/index.d.ts.map +1 -0
  20. package/dist/src/class-function/types.d.ts +9 -0
  21. package/dist/src/class-function/types.d.ts.map +1 -0
  22. package/dist/src/composables/cache-object.d.ts +3 -0
  23. package/dist/src/composables/cache-object.d.ts.map +1 -0
  24. package/dist/src/composables/controller-meta.d.ts +8 -0
  25. package/dist/src/composables/controller-meta.d.ts.map +1 -0
  26. package/dist/src/composables/index.d.ts +2 -0
  27. package/dist/src/composables/index.d.ts.map +1 -0
  28. package/dist/src/decorators/circular.decorator.d.ts +3 -0
  29. package/dist/src/decorators/circular.decorator.d.ts.map +1 -0
  30. package/dist/src/decorators/common.decorator.d.ts +4 -0
  31. package/dist/src/decorators/common.decorator.d.ts.map +1 -0
  32. package/dist/src/decorators/controller.decorator.d.ts +6 -0
  33. package/dist/src/decorators/controller.decorator.d.ts.map +1 -0
  34. package/dist/src/decorators/http-method.decorator.d.ts +8 -0
  35. package/dist/src/decorators/http-method.decorator.d.ts.map +1 -0
  36. package/dist/src/decorators/index.d.ts +10 -0
  37. package/dist/src/decorators/index.d.ts.map +1 -0
  38. package/dist/src/decorators/injectable.decorator.d.ts +3 -0
  39. package/dist/src/decorators/injectable.decorator.d.ts.map +1 -0
  40. package/dist/src/decorators/intercept.decorator.d.ts +20 -0
  41. package/dist/src/decorators/intercept.decorator.d.ts.map +1 -0
  42. package/dist/src/decorators/pipe.decorator.d.ts +3 -0
  43. package/dist/src/decorators/pipe.decorator.d.ts.map +1 -0
  44. package/dist/src/decorators/provide.decorator.d.ts +5 -0
  45. package/dist/src/decorators/provide.decorator.d.ts.map +1 -0
  46. package/dist/src/decorators/resolve.decorator.d.ts +21 -0
  47. package/dist/src/decorators/resolve.decorator.d.ts.map +1 -0
  48. package/dist/src/decorators/tests/circular.artifacts.d.ts +7 -0
  49. package/dist/src/decorators/tests/circular.artifacts.d.ts.map +1 -0
  50. package/dist/src/decorators/tests/circular.spec.d.ts +2 -0
  51. package/dist/src/decorators/tests/circular.spec.d.ts.map +1 -0
  52. package/dist/src/decorators/tests/common.artifacts.d.ts +4 -0
  53. package/dist/src/decorators/tests/common.artifacts.d.ts.map +1 -0
  54. package/dist/src/decorators/tests/common.spec.d.ts +2 -0
  55. package/dist/src/decorators/tests/common.spec.d.ts.map +1 -0
  56. package/dist/src/decorators/tests/controller.spec.d.ts +2 -0
  57. package/dist/src/decorators/tests/controller.spec.d.ts.map +1 -0
  58. package/dist/src/decorators/tests/http-method.artifacts.d.ts +12 -0
  59. package/dist/src/decorators/tests/http-method.artifacts.d.ts.map +1 -0
  60. package/dist/src/decorators/tests/http-method.spec.d.ts +2 -0
  61. package/dist/src/decorators/tests/http-method.spec.d.ts.map +1 -0
  62. package/dist/src/decorators/tests/injectable.spec.d.ts +2 -0
  63. package/dist/src/decorators/tests/injectable.spec.d.ts.map +1 -0
  64. package/dist/src/decorators/tests/intercept.spec.d.ts +2 -0
  65. package/dist/src/decorators/tests/intercept.spec.d.ts.map +1 -0
  66. package/dist/src/decorators/tests/pipe.artifacts.d.ts +4 -0
  67. package/dist/src/decorators/tests/pipe.artifacts.d.ts.map +1 -0
  68. package/dist/src/decorators/tests/pipe.spec.d.ts +2 -0
  69. package/dist/src/decorators/tests/pipe.spec.d.ts.map +1 -0
  70. package/dist/src/decorators/tests/provide.artifacts.d.ts +9 -0
  71. package/dist/src/decorators/tests/provide.artifacts.d.ts.map +1 -0
  72. package/dist/src/decorators/tests/provide.spec.d.ts +2 -0
  73. package/dist/src/decorators/tests/provide.spec.d.ts.map +1 -0
  74. package/dist/src/decorators/tests/resolve.artifacts.d.ts +4 -0
  75. package/dist/src/decorators/tests/resolve.artifacts.d.ts.map +1 -0
  76. package/dist/src/decorators/tests/resolve.spec.d.ts +2 -0
  77. package/dist/src/decorators/tests/resolve.spec.d.ts.map +1 -0
  78. package/dist/src/decorators/tests/validate.artifacts.d.ts +21 -0
  79. package/dist/src/decorators/tests/validate.artifacts.d.ts.map +1 -0
  80. package/dist/src/decorators/tests/validate.spec.d.ts +2 -0
  81. package/dist/src/decorators/tests/validate.spec.d.ts.map +1 -0
  82. package/dist/src/decorators/validate.decorator.d.ts +10 -0
  83. package/dist/src/decorators/validate.decorator.d.ts.map +1 -0
  84. package/dist/src/index.d.ts +7 -0
  85. package/dist/src/index.d.ts.map +1 -0
  86. package/dist/src/metadata/index.d.ts +2 -0
  87. package/dist/src/metadata/index.d.ts.map +1 -0
  88. package/dist/src/metadata/infact.d.ts +7 -0
  89. package/dist/src/metadata/infact.d.ts.map +1 -0
  90. package/dist/src/metadata/moost-metadata.d.ts +62 -0
  91. package/dist/src/metadata/moost-metadata.d.ts.map +1 -0
  92. package/dist/src/metadata/valido.d.ts +3 -0
  93. package/dist/src/metadata/valido.d.ts.map +1 -0
  94. package/dist/src/moost.d.ts +34 -0
  95. package/dist/src/moost.d.ts.map +1 -0
  96. package/dist/src/moost.spec.d.ts +2 -0
  97. package/dist/src/moost.spec.d.ts.map +1 -0
  98. package/dist/src/pipes/generic-types-cast.pipe.d.ts +3 -0
  99. package/dist/src/pipes/generic-types-cast.pipe.d.ts.map +1 -0
  100. package/dist/src/pipes/index.d.ts +5 -0
  101. package/dist/src/pipes/index.d.ts.map +1 -0
  102. package/dist/src/pipes/resolve.pipe.d.ts +3 -0
  103. package/dist/src/pipes/resolve.pipe.d.ts.map +1 -0
  104. package/dist/src/pipes/run-pipes.d.ts +5 -0
  105. package/dist/src/pipes/run-pipes.d.ts.map +1 -0
  106. package/dist/src/pipes/shared-pipes.d.ts +3 -0
  107. package/dist/src/pipes/shared-pipes.d.ts.map +1 -0
  108. package/dist/src/pipes/types.d.ts +21 -0
  109. package/dist/src/pipes/types.d.ts.map +1 -0
  110. package/dist/src/pipes/validate.pipe.d.ts +7 -0
  111. package/dist/src/pipes/validate.pipe.d.ts.map +1 -0
  112. package/dist/src/pipes/validation.spec.d.ts +2 -0
  113. package/dist/src/pipes/validation.spec.d.ts.map +1 -0
  114. package/dist/src/tests/e2e.artifacts.d.ts +17 -0
  115. package/dist/src/tests/e2e.artifacts.d.ts.map +1 -0
  116. package/dist/src/tests/e2e.spec.d.ts +2 -0
  117. package/dist/src/tests/e2e.spec.d.ts.map +1 -0
  118. package/dist/src/tests/request.artifacts.d.ts +10 -0
  119. package/dist/src/tests/request.artifacts.d.ts.map +1 -0
  120. package/dist/src/types.d.ts +8 -0
  121. package/dist/src/types.d.ts.map +1 -0
  122. package/dist/src/utils/banner.d.ts +2 -0
  123. package/dist/src/utils/banner.d.ts.map +1 -0
  124. package/dist/src/utils/log.d.ts +5 -0
  125. package/dist/src/utils/log.d.ts.map +1 -0
  126. package/dist/src/utils/panic.d.ts +2 -0
  127. package/dist/src/utils/panic.d.ts.map +1 -0
  128. package/index.js +2 -0
  129. package/package.json +90 -0
@@ -0,0 +1,693 @@
1
+ import { useCurrentWooksContext, useRequest, useHeaders, useCookies, useRouteParams, useSearchParams, useResponse, useBody, Wooks, WooksError } from 'wooks';
2
+ import { Mate, getConstructor, isConstructor } from '@prostojs/mate';
3
+ import { Infact, createProvideRegistry } from '@prostojs/infact';
4
+ import { validoIsTypeOf, validoIsString, validoIsNumber, validoIsBoolean, Valido } from '@prostojs/valido';
5
+
6
+ const METADATA_WORKSPACE = 'moost';
7
+ const moostMate = new Mate(METADATA_WORKSPACE, {
8
+ readType: true,
9
+ readReturnType: true,
10
+ });
11
+ function getMoostMate() {
12
+ return moostMate;
13
+ }
14
+
15
+ const prefix = '__moost_';
16
+ function useCacheObject(name, def) {
17
+ const cc = useCurrentWooksContext().getCtx().customContext;
18
+ const key = prefix + name;
19
+ const cache = cc[key] = (cc[key] || def);
20
+ return cache;
21
+ }
22
+ function setCacheObject(name, value) {
23
+ const cc = useCurrentWooksContext().getCtx().customContext;
24
+ const key = prefix + name;
25
+ cc[key] = value;
26
+ }
27
+
28
+ function useControllerMeta() {
29
+ const controller = useCacheObject('controller', undefined);
30
+ const method = useCacheObject('method', '');
31
+ return {
32
+ getClassMeta: () => getMoostMate().read(controller),
33
+ getMethodMeta: () => getMoostMate().read(controller, method),
34
+ };
35
+ }
36
+ function setComposableControllerContext(controller, method) {
37
+ setCacheObject('controller', controller);
38
+ setCacheObject('method', method);
39
+ }
40
+
41
+ async function runPipes(pipes, meta, restoreCtx) {
42
+ let v = undefined;
43
+ for (const pipe of pipes) {
44
+ restoreCtx && restoreCtx();
45
+ v = await pipe.handler(v, meta);
46
+ }
47
+ return v;
48
+ }
49
+
50
+ var TPipePriority;
51
+ (function (TPipePriority) {
52
+ TPipePriority[TPipePriority["BEFORE_RESOLVE"] = 0] = "BEFORE_RESOLVE";
53
+ TPipePriority[TPipePriority["RESOLVE"] = 1] = "RESOLVE";
54
+ TPipePriority[TPipePriority["AFTER_RESOLVE"] = 2] = "AFTER_RESOLVE";
55
+ TPipePriority[TPipePriority["BEFORE_TRANSFORM"] = 3] = "BEFORE_TRANSFORM";
56
+ TPipePriority[TPipePriority["TRANSFORM"] = 4] = "TRANSFORM";
57
+ TPipePriority[TPipePriority["AFTER_TRANSFORM"] = 5] = "AFTER_TRANSFORM";
58
+ TPipePriority[TPipePriority["BEFORE_VALIDATE"] = 6] = "BEFORE_VALIDATE";
59
+ TPipePriority[TPipePriority["VALIDATE"] = 7] = "VALIDATE";
60
+ TPipePriority[TPipePriority["AFTER_VALIDATE"] = 8] = "AFTER_VALIDATE";
61
+ })(TPipePriority || (TPipePriority = {}));
62
+
63
+ const resolvePipe = (_value, meta) => {
64
+ if (meta === null || meta === void 0 ? void 0 : meta.resolver) {
65
+ return meta.resolver();
66
+ }
67
+ return undefined;
68
+ };
69
+ resolvePipe.priority = TPipePriority.RESOLVE;
70
+
71
+ const sharedPipes = [
72
+ {
73
+ handler: resolvePipe,
74
+ priority: TPipePriority.RESOLVE,
75
+ },
76
+ ];
77
+
78
+ const sharedMoostInfact = getNewMoostInfact();
79
+ function getMoostInfact() {
80
+ return sharedMoostInfact;
81
+ }
82
+ function getNewMoostInfact() {
83
+ return new Infact({
84
+ describeClass(classConstructor) {
85
+ const meta = getMoostMate().read(classConstructor);
86
+ const infactMeta = {
87
+ injectable: !!(meta === null || meta === void 0 ? void 0 : meta.injectable),
88
+ global: false,
89
+ constructorParams: (meta === null || meta === void 0 ? void 0 : meta.params) || [],
90
+ provide: meta === null || meta === void 0 ? void 0 : meta.provide,
91
+ scopeId: (meta === null || meta === void 0 ? void 0 : meta.injectable) === 'FOR_REQUEST' ? useRequest().reqId() : undefined,
92
+ };
93
+ return infactMeta;
94
+ },
95
+ resolveParam(paramMeta) {
96
+ if (paramMeta.resolver) {
97
+ return runPipes(sharedPipes, paramMeta);
98
+ }
99
+ },
100
+ storeProvideRegByInstance: true,
101
+ });
102
+ }
103
+
104
+ function bindHandler(getInstance, method, wooksApp, options) {
105
+ wooksApp.on(options.httpMethod, options.path, async () => {
106
+ const { restoreCtx } = useCurrentWooksContext();
107
+ const { reqId, rawRequest } = useRequest();
108
+ const infact = getMoostInfact();
109
+ const scopeId = reqId();
110
+ infact.registerScope(scopeId);
111
+ rawRequest.on('end', () => infact.unregisterScope(scopeId));
112
+ const instance = await getInstance();
113
+ restoreCtx();
114
+ setComposableControllerContext(instance, method);
115
+ let response;
116
+ let responseOverwritten = false;
117
+ const before = [];
118
+ const after = [];
119
+ const onError = [];
120
+ function replyFn(reply) {
121
+ response = reply;
122
+ responseOverwritten = true;
123
+ }
124
+ for (const handler of options.interceptorHandlers) {
125
+ restoreCtx();
126
+ await handler((fn) => { before.push(fn); }, (fn) => { after.unshift(fn); }, (fn) => { onError.unshift(fn); });
127
+ }
128
+ let args = [];
129
+ try {
130
+ restoreCtx();
131
+ args = await applyPipesToArgs(options.argsPipes);
132
+ }
133
+ catch (e) {
134
+ response = e;
135
+ }
136
+ if (!response) {
137
+ for (const handler of before) {
138
+ restoreCtx();
139
+ await handler(replyFn);
140
+ if (responseOverwritten)
141
+ break;
142
+ }
143
+ if (!responseOverwritten) {
144
+ try {
145
+ restoreCtx();
146
+ response = await instance[method](...args);
147
+ }
148
+ catch (e) {
149
+ response = e;
150
+ }
151
+ }
152
+ }
153
+ if (response instanceof Error) {
154
+ for (const handler of onError) {
155
+ restoreCtx();
156
+ await handler(response, replyFn);
157
+ }
158
+ }
159
+ else {
160
+ for (const handler of after) {
161
+ restoreCtx();
162
+ await handler(response, replyFn);
163
+ }
164
+ }
165
+ return response;
166
+ });
167
+ }
168
+ async function applyPipesToArgs(argsPipes) {
169
+ const args = [];
170
+ const { restoreCtx } = useCurrentWooksContext();
171
+ for (let i = 0; i < argsPipes.length; i++) {
172
+ const { pipes, meta } = argsPipes[i];
173
+ args[i] = await runPipes(pipes, meta, restoreCtx);
174
+ }
175
+ return args;
176
+ }
177
+
178
+ function getInstanceOwnMethods(instance) {
179
+ const proto = Object.getPrototypeOf(instance);
180
+ return [
181
+ ...Object.getOwnPropertyNames(proto),
182
+ ...Object.getOwnPropertyNames(instance),
183
+ ].filter(m => typeof instance[m] === 'function');
184
+ }
185
+
186
+ const banner = () => `[moost][${new Date().toISOString().replace('T', ' ').replace(/\.\d{3}z$/i, '')}] `;
187
+
188
+ function log(text) {
189
+ console.log('' + '' + banner() + text + '');
190
+ }
191
+ function logBright(text) {
192
+ console.log('' + banner() + text + '');
193
+ }
194
+ function logError(error) {
195
+ console.error('' + '' + banner() + error + '');
196
+ }
197
+
198
+ function panic(error) {
199
+ logError(error);
200
+ return new Error(error);
201
+ }
202
+
203
+ async function getCallableFn(targetInstance, fn, restoreCtx) {
204
+ const mate = getMoostMate();
205
+ const meta = mate.read(fn);
206
+ if (meta === null || meta === void 0 ? void 0 : meta.injectable) {
207
+ const infact = getMoostInfact();
208
+ infact.silent(meta.injectable === 'FOR_REQUEST');
209
+ const instance = await infact.getForInstance(targetInstance, fn, [], () => { restoreCtx && restoreCtx(); });
210
+ infact.silent(false);
211
+ return ((...args) => {
212
+ return instance.handler(...args);
213
+ });
214
+ }
215
+ if (typeof fn === 'function') {
216
+ return fn;
217
+ }
218
+ throw panic(`getCallableFn failed for "${getConstructor(targetInstance).name}" because the passed arg is not a Function nor TClassFunction`);
219
+ }
220
+
221
+ function bindControllerMethods(getInstance, classConstructor, wooksApp, options) {
222
+ var _a;
223
+ const opts = options || {};
224
+ opts.globalPrefix = opts.globalPrefix || '';
225
+ opts.provide = opts.provide || {};
226
+ const fakeInstance = Object.create(classConstructor.prototype);
227
+ const methods = getInstanceOwnMethods(fakeInstance);
228
+ const mate = getMoostMate();
229
+ const meta = mate.read(classConstructor) || {};
230
+ const ownPrefix = typeof opts.replaceOwnPrefix === 'string' ? opts.replaceOwnPrefix : (((_a = meta.controller) === null || _a === void 0 ? void 0 : _a.prefix) || '');
231
+ const prefix = `${opts.globalPrefix}/${ownPrefix}`;
232
+ for (const method of methods) {
233
+ const methodMeta = getMoostMate().read(fakeInstance, method) || {};
234
+ if (!methodMeta.httpHandler || !methodMeta.httpHandler.length)
235
+ continue;
236
+ const interceptors = [...(opts.interceptors || []), ...(meta.interceptors || []), ...(methodMeta.interceptors || [])].sort((a, b) => a.priority - b.priority);
237
+ const interceptorHandlers = [];
238
+ for (const { handler } of interceptors) {
239
+ const interceptorMeta = mate.read(handler);
240
+ if (interceptorMeta === null || interceptorMeta === void 0 ? void 0 : interceptorMeta.injectable) {
241
+ interceptorHandlers.push(async (...args) => {
242
+ const { restoreCtx } = useCurrentWooksContext();
243
+ const targetInstance = await getInstance();
244
+ restoreCtx();
245
+ return (await getCallableFn(targetInstance, handler, restoreCtx))(...args);
246
+ });
247
+ }
248
+ else {
249
+ interceptorHandlers.push(handler);
250
+ }
251
+ }
252
+ const pipes = [...(opts.pipes || []), ...(meta.pipes || []), ...(methodMeta.pipes || [])];
253
+ const argsPipes = [];
254
+ for (const p of methodMeta.params || []) {
255
+ argsPipes.push({
256
+ meta: p,
257
+ pipes: [...pipes, ...(p.pipes || [])].sort((a, b) => a.priority - b.priority),
258
+ });
259
+ }
260
+ const provide = { ...(opts.provide || {}), ...(meta.provide || {}) };
261
+ for (const { method: httpMethod, path: httpPath } of methodMeta.httpHandler) {
262
+ const path = typeof httpPath === 'string' ? httpPath : typeof method === 'string' ? method : '';
263
+ const targetPath = `${prefix || ''}/${path}`.replace(/\/\/+/g, '/');
264
+ bindHandler(getInstance, method, wooksApp, {
265
+ path: targetPath,
266
+ httpMethod,
267
+ interceptorHandlers,
268
+ provide,
269
+ argsMeta: methodMeta.params,
270
+ argsPipes,
271
+ });
272
+ log(`(${httpMethod})${targetPath} -> ${classConstructor.name}.${method}()`);
273
+ }
274
+ }
275
+ }
276
+
277
+ function HttpMethod(method, path) {
278
+ return getMoostMate().decorate('httpHandler', { method, path }, true);
279
+ }
280
+ const All = (path) => HttpMethod('*', path);
281
+ const Get = (path) => HttpMethod('GET', path);
282
+ const Post = (path) => HttpMethod('POST', path);
283
+ const Put = (path) => HttpMethod('PUT', path);
284
+ const Delete = (path) => HttpMethod('DELETE', path);
285
+ const Patch = (path) => HttpMethod('PATCH', path);
286
+
287
+ function Label(value) {
288
+ return getMoostMate().decorate('label', value);
289
+ }
290
+ function Optional() {
291
+ return getMoostMate().decorate('optional', true);
292
+ }
293
+ function Required() {
294
+ const mate = getMoostMate();
295
+ return mate.apply(mate.decorate('required', true), mate.decorateClass((meta, key, index) => {
296
+ if (typeof index !== 'number' && meta && ['string', 'symbol'].includes(typeof key)) {
297
+ meta.requiredProps = meta.requiredProps || [];
298
+ meta.requiredProps.push(key);
299
+ }
300
+ return meta;
301
+ }));
302
+ }
303
+
304
+ function Resolve(resolver, label) {
305
+ return (target, key, index) => {
306
+ fillLabel(target, key, index, label);
307
+ getMoostMate().decorate('resolver', resolver)(target, key, index);
308
+ };
309
+ }
310
+ function Header(name) {
311
+ return Resolve(() => {
312
+ const headers = useHeaders();
313
+ return headers[name];
314
+ }, 'header: ' + name);
315
+ }
316
+ function Cookie(name) {
317
+ return Resolve(() => useCookies().getCookie(name), 'cookie: ' + name);
318
+ }
319
+ function Param(name) {
320
+ return Resolve(() => useRouteParams().getRouteParam(name), name);
321
+ }
322
+ function Params() {
323
+ return Resolve(() => useRouteParams().routeParams, 'params');
324
+ }
325
+ function Query(name) {
326
+ return Resolve(() => {
327
+ const { jsonSearchParams, urlSearchParams } = useSearchParams();
328
+ if (name) {
329
+ const p = urlSearchParams();
330
+ const value = p.get(name);
331
+ console.log(name + ' = ', value);
332
+ return value === '' && p.has(name) || value;
333
+ }
334
+ const json = jsonSearchParams();
335
+ return Object.keys(json).length ? json : undefined;
336
+ }, name || 'Query');
337
+ }
338
+ function Url() {
339
+ return Resolve(() => useRequest().url, 'url');
340
+ }
341
+ function Method() {
342
+ return Resolve(() => useRequest().method, 'http_method');
343
+ }
344
+ function Req() {
345
+ return Resolve(() => useRequest().rawRequest, 'request');
346
+ }
347
+ function ReqId() {
348
+ return Resolve(() => useRequest().reqId(), 'reqId');
349
+ }
350
+ function Ip(opts) {
351
+ return Resolve(() => useRequest().getIp(opts), 'ip');
352
+ }
353
+ function IpList() {
354
+ return Resolve(() => useRequest().getIpList(), 'ipList');
355
+ }
356
+ function Res(options) {
357
+ return Resolve(() => useResponse().rawResponse(options), 'response');
358
+ }
359
+ function Const(value, label) {
360
+ return Resolve(() => value, label);
361
+ }
362
+ function Body() {
363
+ return Resolve(() => useBody().parseBody(), 'body');
364
+ }
365
+ function RawBody() {
366
+ return Resolve(() => useBody().rawBody(), 'body');
367
+ }
368
+ function fillLabel(target, key, index, name) {
369
+ if (name) {
370
+ const meta = getMoostMate().read(target, key);
371
+ if (!(meta === null || meta === void 0 ? void 0 : meta.params) || !(meta === null || meta === void 0 ? void 0 : meta.params[index].label)) {
372
+ Label(name)(target, key, index);
373
+ }
374
+ }
375
+ }
376
+
377
+ function Controller(prefix) {
378
+ return getMoostMate().decorate('controller', { prefix: prefix || '' });
379
+ }
380
+ function ImportController(prefix, controller, provide) {
381
+ return getMoostMate().decorate('importController', {
382
+ prefix: typeof prefix === 'string' ? prefix : undefined,
383
+ typeResolver: typeof prefix === 'string' ? controller : prefix,
384
+ provide: typeof prefix === 'string' ? provide || undefined : controller || undefined,
385
+ }, true);
386
+ }
387
+
388
+ function Injectable(scope = true) {
389
+ return getMoostMate().decorate('injectable', scope);
390
+ }
391
+
392
+ function Circular(resolver) {
393
+ return getMoostMate().decorate('circular', resolver);
394
+ }
395
+
396
+ var TInterceptorPriority;
397
+ (function (TInterceptorPriority) {
398
+ TInterceptorPriority[TInterceptorPriority["BEFORE_ALL"] = 0] = "BEFORE_ALL";
399
+ TInterceptorPriority[TInterceptorPriority["BEFORE_GUARD"] = 1] = "BEFORE_GUARD";
400
+ TInterceptorPriority[TInterceptorPriority["GUARD"] = 2] = "GUARD";
401
+ TInterceptorPriority[TInterceptorPriority["AFTER_GUARD"] = 3] = "AFTER_GUARD";
402
+ TInterceptorPriority[TInterceptorPriority["INTERCEPTOR"] = 4] = "INTERCEPTOR";
403
+ TInterceptorPriority[TInterceptorPriority["CATCH_ERROR"] = 5] = "CATCH_ERROR";
404
+ TInterceptorPriority[TInterceptorPriority["AFTER_ALL"] = 6] = "AFTER_ALL";
405
+ })(TInterceptorPriority || (TInterceptorPriority = {}));
406
+ function Intercept(handler, priority) {
407
+ return getMoostMate().decorate('interceptors', {
408
+ handler,
409
+ priority: priority || handler.priority || TInterceptorPriority.INTERCEPTOR,
410
+ }, true);
411
+ }
412
+
413
+ function Provide(type, fn) {
414
+ return getMoostMate().decorate(meta => {
415
+ meta.provide = meta.provide || {};
416
+ Object.assign(meta.provide, createProvideRegistry([type, fn]));
417
+ return meta;
418
+ });
419
+ }
420
+ function Inject(type) {
421
+ return getMoostMate().decorate('inject', type);
422
+ }
423
+
424
+ function Dto(dtoOptions = {}) {
425
+ return getMoostMate().decorate('dto', dtoOptions || {});
426
+ }
427
+ let isArrayItemValidator = false;
428
+ function Validate(validator) {
429
+ return getMoostMate().decorate(isArrayItemValidator ? 'validatorsOfItem' : 'validators', validator, true);
430
+ }
431
+ function IsArray(opts) {
432
+ const mate = getMoostMate();
433
+ const decorators = [mate.decorate('arrayType', opts || true)];
434
+ if ((opts === null || opts === void 0 ? void 0 : opts.itemValidators) && !isArrayItemValidator) {
435
+ isArrayItemValidator = true;
436
+ decorators.push(...opts.itemValidators());
437
+ isArrayItemValidator = false;
438
+ }
439
+ else if ((opts === null || opts === void 0 ? void 0 : opts.itemValidators) && isArrayItemValidator) {
440
+ throw new Error('IsArray validator is not supported inside of array type');
441
+ }
442
+ const decorator = mate.apply(...decorators);
443
+ return decorator;
444
+ }
445
+ function IsTypeOf(type, errorText) {
446
+ return Validate(validoIsTypeOf(type, errorText));
447
+ }
448
+ function IsString(...args) {
449
+ return Validate(validoIsString(...args));
450
+ }
451
+ function IsNumber(...args) {
452
+ return Validate(validoIsNumber(...args));
453
+ }
454
+ function IsBoolean(...args) {
455
+ return Validate(validoIsBoolean(...args));
456
+ }
457
+
458
+ class Moost {
459
+ constructor(options) {
460
+ this.options = options;
461
+ this.pipes = [...sharedPipes];
462
+ this.interceptors = [];
463
+ this.provide = {};
464
+ this.unregisteredControllers = [];
465
+ }
466
+ async listen(port, hostname, cb) {
467
+ var _a, _b, _c;
468
+ this.wooksApp = new Wooks((_a = this.options) === null || _a === void 0 ? void 0 : _a.wooksOptions);
469
+ const _port = Number(((_b = this.options) === null || _b === void 0 ? void 0 : _b.port) || port);
470
+ const _hostname = ((_c = this.options) === null || _c === void 0 ? void 0 : _c.hostname) || hostname;
471
+ if (!_port) {
472
+ throw panic('Port is not specified for "listen" method');
473
+ }
474
+ await this.init();
475
+ await this.wooksApp.listen(_port, _hostname, cb);
476
+ logBright(`${getConstructor(this).name} is up and running on port ${_port}`);
477
+ return this.wooksApp;
478
+ }
479
+ close() {
480
+ var _a;
481
+ return (_a = this.wooksApp) === null || _a === void 0 ? void 0 : _a.close();
482
+ }
483
+ async init() {
484
+ if (this.wooksApp) {
485
+ this.unregisteredControllers.unshift(this);
486
+ await this.bindControllers();
487
+ }
488
+ }
489
+ async bindControllers() {
490
+ var _a;
491
+ if (this.wooksApp) {
492
+ const meta = getMoostMate();
493
+ const thisMeta = meta.read(this);
494
+ const provide = { ...((thisMeta === null || thisMeta === void 0 ? void 0 : thisMeta.provide) || {}), ...this.provide };
495
+ for (const controller of this.unregisteredControllers) {
496
+ await this.bindController(controller, provide, ((_a = this.options) === null || _a === void 0 ? void 0 : _a.globalPrefix) || '');
497
+ }
498
+ this.unregisteredControllers = [];
499
+ }
500
+ }
501
+ async bindController(controller, provide, globalPrefix, replaceOwnPrefix) {
502
+ var _a;
503
+ if (this.wooksApp) {
504
+ const meta = getMoostMate();
505
+ const classMeta = meta.read(controller);
506
+ const infact = getMoostInfact();
507
+ const isControllerConsructor = isConstructor(controller);
508
+ let instance;
509
+ if (isControllerConsructor && (classMeta === null || classMeta === void 0 ? void 0 : classMeta.injectable) === 'SINGLETON') {
510
+ instance = await infact.get(controller, provide);
511
+ }
512
+ else if (!isControllerConsructor) {
513
+ instance = controller;
514
+ infact.setProvideRegByInstance(instance, provide);
515
+ }
516
+ const getInstance = instance ? () => Promise.resolve(instance) : async () => {
517
+ infact.silent();
518
+ const instance = await infact.get(controller, provide);
519
+ infact.silent(false);
520
+ return instance;
521
+ };
522
+ const classConstructor = isConstructor(controller) ? controller : getConstructor(controller);
523
+ bindControllerMethods(getInstance, classConstructor, this.wooksApp, {
524
+ globalPrefix,
525
+ replaceOwnPrefix,
526
+ interceptors: [...this.interceptors],
527
+ pipes: [...this.pipes],
528
+ provide: (classMeta === null || classMeta === void 0 ? void 0 : classMeta.provide) || {},
529
+ });
530
+ if (classMeta && classMeta.importController) {
531
+ const prefix = typeof replaceOwnPrefix === 'string' ? replaceOwnPrefix : (_a = classMeta === null || classMeta === void 0 ? void 0 : classMeta.controller) === null || _a === void 0 ? void 0 : _a.prefix;
532
+ const mergedProvide = { ...provide, ...((classMeta === null || classMeta === void 0 ? void 0 : classMeta.provide) || {}) };
533
+ for (const ic of classMeta.importController) {
534
+ if (ic.typeResolver) {
535
+ const isConstr = isConstructor(ic.typeResolver);
536
+ const isFunc = typeof ic.typeResolver === 'function';
537
+ await this.bindController(isConstr ? ic.typeResolver : isFunc ? await ic.typeResolver() : ic.typeResolver, ic.provide ? { ...mergedProvide, ...ic.provide } : mergedProvide, `${globalPrefix}/${(prefix || '')}`, ic.prefix);
538
+ }
539
+ }
540
+ }
541
+ }
542
+ }
543
+ applyGlobalPipes(...items) {
544
+ for (const item of items) {
545
+ if (typeof item === 'function') {
546
+ this.pipes.push({
547
+ handler: item,
548
+ priority: typeof item.priority === 'number' ? item.priority : TPipePriority.TRANSFORM,
549
+ });
550
+ }
551
+ else {
552
+ this.pipes.push({
553
+ handler: item.handler,
554
+ priority: item.priority,
555
+ });
556
+ }
557
+ }
558
+ return this;
559
+ }
560
+ applyGlobalInterceptors(...items) {
561
+ for (const item of items) {
562
+ if (typeof item === 'function') {
563
+ this.interceptors.push({
564
+ handler: item,
565
+ priority: typeof item.priority === 'number' ? item.priority : TInterceptorPriority.INTERCEPTOR,
566
+ });
567
+ }
568
+ else {
569
+ this.interceptors.push({
570
+ handler: item.handler,
571
+ priority: item.priority,
572
+ });
573
+ }
574
+ }
575
+ return this;
576
+ }
577
+ setProvideRegistry(provide) {
578
+ this.provide = { ...this.provide, ...provide };
579
+ return this;
580
+ }
581
+ registerControllers(...controllers) {
582
+ this.unregisteredControllers.push(...controllers);
583
+ return this;
584
+ }
585
+ }
586
+
587
+ const genericTypesCastPipe = (strict) => {
588
+ const handler = (value, meta) => {
589
+ if (meta === null || meta === void 0 ? void 0 : meta.type) {
590
+ if ((value === undefined || value === null || (meta.type !== String && value === '')) && meta.optional) {
591
+ return undefined;
592
+ }
593
+ switch (meta.type) {
594
+ case Date: {
595
+ let d;
596
+ if (typeof value === 'string') {
597
+ d = new Date(/^\d+$/.test(value) ? Number(value) : value);
598
+ }
599
+ else {
600
+ d = new Date(value);
601
+ }
602
+ if (strict && Number.isNaN(d.getTime())) {
603
+ typeError(value, 'Date', meta.label);
604
+ }
605
+ return Number.isNaN(d.getTime()) ? value : d;
606
+ }
607
+ case Boolean:
608
+ if ([true, 'true', 'TRUE', 'True', 1, '1', 'X', 'x'].includes(value)) {
609
+ return true;
610
+ }
611
+ if ([false, 'false', 'FALSE', 'False', 0, '0', '', ' ', null, undefined].includes(value)) {
612
+ return false;
613
+ }
614
+ if (strict) {
615
+ typeError(value, 'boolean', meta.label);
616
+ }
617
+ return value;
618
+ case Number: {
619
+ if (strict && !value && value !== 0) {
620
+ typeError(value, 'numeric', meta.label);
621
+ }
622
+ const n = typeof value === 'string' && value.length > 0 ? Number(value) : NaN;
623
+ if (strict && Number.isNaN(n)) {
624
+ typeError(value, 'numeric', meta.label);
625
+ }
626
+ return Number.isNaN(n) ? value : n;
627
+ }
628
+ case String:
629
+ if (strict && ['object', 'function'].includes(typeof value)) {
630
+ typeError(value, 'string', meta.label);
631
+ }
632
+ return value && String(value) || value;
633
+ default:
634
+ return value;
635
+ }
636
+ }
637
+ };
638
+ handler.priority = TPipePriority.AFTER_TRANSFORM;
639
+ return handler;
640
+ };
641
+ function typeError(value, targetType, label) {
642
+ const prefix = label ? `Argument "${label}" with value ` : '';
643
+ throw new WooksError(400, `${prefix}${JSON.stringify(value)} is not a ${targetType} type`);
644
+ }
645
+
646
+ const valido = new Valido({
647
+ getDtoMeta(value, _type) {
648
+ let type = _type;
649
+ if (!type) {
650
+ type = getConstructor(value);
651
+ }
652
+ const mate = getMoostMate();
653
+ return mate.read(type);
654
+ },
655
+ getDtoParamMeta(value, type, key) {
656
+ const mate = getMoostMate();
657
+ return mate.read(type, key);
658
+ },
659
+ });
660
+ function getMoostValido() {
661
+ return valido;
662
+ }
663
+
664
+ const DEFAULT_ERROR_LIMIT = 10;
665
+ function firstString(errors) {
666
+ const keys = Object.keys(errors);
667
+ for (const key of keys) {
668
+ if (typeof errors[key] === 'string')
669
+ return errors[key];
670
+ return firstString(errors[key]);
671
+ }
672
+ return '';
673
+ }
674
+ const validatePipe = (opts) => {
675
+ const pipe = async (_value, meta) => {
676
+ const { restoreCtx } = useCurrentWooksContext();
677
+ const valido = getMoostValido();
678
+ const result = await valido.validateParam(_value, meta, undefined, undefined, undefined, undefined, 0, 0, (opts === null || opts === void 0 ? void 0 : opts.errorLimit) || DEFAULT_ERROR_LIMIT, restoreCtx);
679
+ if (result !== true) {
680
+ throw new WooksError(400, {
681
+ statusCode: 400,
682
+ message: typeof result === 'string' ? result : firstString(result),
683
+ error: 'Validation Error',
684
+ details: result,
685
+ });
686
+ }
687
+ return _value;
688
+ };
689
+ pipe.priority = TPipePriority.VALIDATE;
690
+ return pipe;
691
+ };
692
+
693
+ export { All, Body, Circular, Const, Controller, Cookie, Delete, Dto, Get, Header, HttpMethod, ImportController, Inject, Injectable, Intercept, Ip, IpList, IsArray, IsBoolean, IsNumber, IsString, IsTypeOf, Label, Method, Moost, Optional, Param, Params, Patch, Post, Provide, Put, Query, RawBody, Req, ReqId, Required, Res, Resolve, TInterceptorPriority, TPipePriority, Url, Validate, genericTypesCastPipe, getMoostMate, resolvePipe, useControllerMeta, validatePipe };