@celljs/mvc 3.0.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 (239) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -0
  3. package/cell.yml +9 -0
  4. package/lib/common/constants.d.ts +2 -0
  5. package/lib/common/constants.d.ts.map +1 -0
  6. package/lib/common/constants.js +5 -0
  7. package/lib/common/constants.js.map +1 -0
  8. package/lib/common/index.d.ts +2 -0
  9. package/lib/common/index.d.ts.map +1 -0
  10. package/lib/common/index.js +18 -0
  11. package/lib/common/index.js.map +1 -0
  12. package/lib/node/annotation/body.d.ts +7 -0
  13. package/lib/node/annotation/body.d.ts.map +1 -0
  14. package/lib/node/annotation/body.js +20 -0
  15. package/lib/node/annotation/body.js.map +1 -0
  16. package/lib/node/annotation/catch.d.ts +10 -0
  17. package/lib/node/annotation/catch.d.ts.map +1 -0
  18. package/lib/node/annotation/catch.js +23 -0
  19. package/lib/node/annotation/catch.js.map +1 -0
  20. package/lib/node/annotation/controller.d.ts +15 -0
  21. package/lib/node/annotation/controller.d.ts.map +1 -0
  22. package/lib/node/annotation/controller.js +35 -0
  23. package/lib/node/annotation/controller.js.map +1 -0
  24. package/lib/node/annotation/cookie.d.ts +16 -0
  25. package/lib/node/annotation/cookie.d.ts.map +1 -0
  26. package/lib/node/annotation/cookie.js +29 -0
  27. package/lib/node/annotation/cookie.js.map +1 -0
  28. package/lib/node/annotation/file.d.ts +3 -0
  29. package/lib/node/annotation/file.d.ts.map +1 -0
  30. package/lib/node/annotation/file.js +10 -0
  31. package/lib/node/annotation/file.js.map +1 -0
  32. package/lib/node/annotation/header.d.ts +16 -0
  33. package/lib/node/annotation/header.d.ts.map +1 -0
  34. package/lib/node/annotation/header.js +29 -0
  35. package/lib/node/annotation/header.js.map +1 -0
  36. package/lib/node/annotation/html.d.ts +3 -0
  37. package/lib/node/annotation/html.d.ts.map +1 -0
  38. package/lib/node/annotation/html.js +10 -0
  39. package/lib/node/annotation/html.js.map +1 -0
  40. package/lib/node/annotation/index.d.ts +17 -0
  41. package/lib/node/annotation/index.d.ts.map +1 -0
  42. package/lib/node/annotation/index.js +33 -0
  43. package/lib/node/annotation/index.js.map +1 -0
  44. package/lib/node/annotation/json.d.ts +3 -0
  45. package/lib/node/annotation/json.d.ts.map +1 -0
  46. package/lib/node/annotation/json.js +10 -0
  47. package/lib/node/annotation/json.js.map +1 -0
  48. package/lib/node/annotation/method.d.ts +24 -0
  49. package/lib/node/annotation/method.d.ts.map +1 -0
  50. package/lib/node/annotation/method.js +54 -0
  51. package/lib/node/annotation/method.js.map +1 -0
  52. package/lib/node/annotation/param.d.ts +7 -0
  53. package/lib/node/annotation/param.d.ts.map +1 -0
  54. package/lib/node/annotation/param.js +20 -0
  55. package/lib/node/annotation/param.js.map +1 -0
  56. package/lib/node/annotation/query.d.ts +7 -0
  57. package/lib/node/annotation/query.d.ts.map +1 -0
  58. package/lib/node/annotation/query.js +20 -0
  59. package/lib/node/annotation/query.js.map +1 -0
  60. package/lib/node/annotation/req.d.ts +6 -0
  61. package/lib/node/annotation/req.d.ts.map +1 -0
  62. package/lib/node/annotation/req.js +18 -0
  63. package/lib/node/annotation/req.js.map +1 -0
  64. package/lib/node/annotation/res.d.ts +6 -0
  65. package/lib/node/annotation/res.d.ts.map +1 -0
  66. package/lib/node/annotation/res.js +18 -0
  67. package/lib/node/annotation/res.js.map +1 -0
  68. package/lib/node/annotation/session.d.ts +16 -0
  69. package/lib/node/annotation/session.d.ts.map +1 -0
  70. package/lib/node/annotation/session.js +29 -0
  71. package/lib/node/annotation/session.js.map +1 -0
  72. package/lib/node/annotation/text.d.ts +3 -0
  73. package/lib/node/annotation/text.d.ts.map +1 -0
  74. package/lib/node/annotation/text.js +10 -0
  75. package/lib/node/annotation/text.js.map +1 -0
  76. package/lib/node/annotation/view.d.ts +13 -0
  77. package/lib/node/annotation/view.d.ts.map +1 -0
  78. package/lib/node/annotation/view.js +15 -0
  79. package/lib/node/annotation/view.js.map +1 -0
  80. package/lib/node/constants.d.ts +18 -0
  81. package/lib/node/constants.d.ts.map +1 -0
  82. package/lib/node/constants.js +21 -0
  83. package/lib/node/constants.js.map +1 -0
  84. package/lib/node/error/error-handler.d.ts +10 -0
  85. package/lib/node/error/error-handler.d.ts.map +1 -0
  86. package/lib/node/error/error-handler.js +42 -0
  87. package/lib/node/error/error-handler.js.map +1 -0
  88. package/lib/node/error/index.d.ts +2 -0
  89. package/lib/node/error/index.d.ts.map +1 -0
  90. package/lib/node/error/index.js +18 -0
  91. package/lib/node/error/index.js.map +1 -0
  92. package/lib/node/handler/handler-adapter.d.ts +22 -0
  93. package/lib/node/handler/handler-adapter.d.ts.map +1 -0
  94. package/lib/node/handler/handler-adapter.js +122 -0
  95. package/lib/node/handler/handler-adapter.js.map +1 -0
  96. package/lib/node/handler/handler-protocol.d.ts +38 -0
  97. package/lib/node/handler/handler-protocol.d.ts.map +1 -0
  98. package/lib/node/handler/handler-protocol.js +7 -0
  99. package/lib/node/handler/handler-protocol.js.map +1 -0
  100. package/lib/node/handler/index.d.ts +6 -0
  101. package/lib/node/handler/index.d.ts.map +1 -0
  102. package/lib/node/handler/index.js +22 -0
  103. package/lib/node/handler/index.js.map +1 -0
  104. package/lib/node/handler/route-builder.d.ts +29 -0
  105. package/lib/node/handler/route-builder.d.ts.map +1 -0
  106. package/lib/node/handler/route-builder.js +117 -0
  107. package/lib/node/handler/route-builder.js.map +1 -0
  108. package/lib/node/handler/route-metadata-matcher.d.ts +9 -0
  109. package/lib/node/handler/route-metadata-matcher.d.ts.map +1 -0
  110. package/lib/node/handler/route-metadata-matcher.js +60 -0
  111. package/lib/node/handler/route-metadata-matcher.js.map +1 -0
  112. package/lib/node/handler/route-provider.d.ts +11 -0
  113. package/lib/node/handler/route-provider.d.ts.map +1 -0
  114. package/lib/node/handler/route-provider.js +44 -0
  115. package/lib/node/handler/route-provider.js.map +1 -0
  116. package/lib/node/index.d.ts +6 -0
  117. package/lib/node/index.d.ts.map +1 -0
  118. package/lib/node/index.js +22 -0
  119. package/lib/node/index.js.map +1 -0
  120. package/lib/node/module.d.ts +4 -0
  121. package/lib/node/module.d.ts.map +1 -0
  122. package/lib/node/module.js +6 -0
  123. package/lib/node/module.js.map +1 -0
  124. package/lib/node/resolver/index.d.ts +8 -0
  125. package/lib/node/resolver/index.d.ts.map +1 -0
  126. package/lib/node/resolver/index.js +24 -0
  127. package/lib/node/resolver/index.js.map +1 -0
  128. package/lib/node/resolver/method-args-resolver-provider.d.ts +8 -0
  129. package/lib/node/resolver/method-args-resolver-provider.d.ts.map +1 -0
  130. package/lib/node/resolver/method-args-resolver-provider.js +35 -0
  131. package/lib/node/resolver/method-args-resolver-provider.js.map +1 -0
  132. package/lib/node/resolver/method-args-resolver.d.ts +35 -0
  133. package/lib/node/resolver/method-args-resolver.d.ts.map +1 -0
  134. package/lib/node/resolver/method-args-resolver.js +152 -0
  135. package/lib/node/resolver/method-args-resolver.js.map +1 -0
  136. package/lib/node/resolver/resolver-protocol.d.ts +15 -0
  137. package/lib/node/resolver/resolver-protocol.d.ts.map +1 -0
  138. package/lib/node/resolver/resolver-protocol.js +7 -0
  139. package/lib/node/resolver/resolver-protocol.js.map +1 -0
  140. package/lib/node/resolver/response-resolver-provider.d.ts +8 -0
  141. package/lib/node/resolver/response-resolver-provider.d.ts.map +1 -0
  142. package/lib/node/resolver/response-resolver-provider.js +35 -0
  143. package/lib/node/resolver/response-resolver-provider.js.map +1 -0
  144. package/lib/node/resolver/response-resolver.d.ts +14 -0
  145. package/lib/node/resolver/response-resolver.d.ts.map +1 -0
  146. package/lib/node/resolver/response-resolver.js +67 -0
  147. package/lib/node/resolver/response-resolver.js.map +1 -0
  148. package/lib/node/resolver/view-resolver-provider.d.ts +8 -0
  149. package/lib/node/resolver/view-resolver-provider.d.ts.map +1 -0
  150. package/lib/node/resolver/view-resolver-provider.js +35 -0
  151. package/lib/node/resolver/view-resolver-provider.js.map +1 -0
  152. package/lib/node/resolver/view-resolver.d.ts +8 -0
  153. package/lib/node/resolver/view-resolver.d.ts.map +1 -0
  154. package/lib/node/resolver/view-resolver.js +44 -0
  155. package/lib/node/resolver/view-resolver.js.map +1 -0
  156. package/lib/node/view/file-view.d.ts +19 -0
  157. package/lib/node/view/file-view.d.ts.map +1 -0
  158. package/lib/node/view/file-view.js +79 -0
  159. package/lib/node/view/file-view.js.map +1 -0
  160. package/lib/node/view/html-view.d.ts +11 -0
  161. package/lib/node/view/html-view.d.ts.map +1 -0
  162. package/lib/node/view/html-view.js +48 -0
  163. package/lib/node/view/html-view.js.map +1 -0
  164. package/lib/node/view/index.d.ts +7 -0
  165. package/lib/node/view/index.d.ts.map +1 -0
  166. package/lib/node/view/index.js +23 -0
  167. package/lib/node/view/index.js.map +1 -0
  168. package/lib/node/view/json-view-template-renderer.d.ts +6 -0
  169. package/lib/node/view/json-view-template-renderer.d.ts.map +1 -0
  170. package/lib/node/view/json-view-template-renderer.js +39 -0
  171. package/lib/node/view/json-view-template-renderer.js.map +1 -0
  172. package/lib/node/view/json-view.d.ts +11 -0
  173. package/lib/node/view/json-view.d.ts.map +1 -0
  174. package/lib/node/view/json-view.js +39 -0
  175. package/lib/node/view/json-view.js.map +1 -0
  176. package/lib/node/view/text-view.d.ts +10 -0
  177. package/lib/node/view/text-view.d.ts.map +1 -0
  178. package/lib/node/view/text-view.js +32 -0
  179. package/lib/node/view/text-view.js.map +1 -0
  180. package/lib/node/view/view-protocol.d.ts +12 -0
  181. package/lib/node/view/view-protocol.d.ts.map +1 -0
  182. package/lib/node/view/view-protocol.js +6 -0
  183. package/lib/node/view/view-protocol.js.map +1 -0
  184. package/lib/node/view/view-provider.d.ts +8 -0
  185. package/lib/node/view/view-provider.d.ts.map +1 -0
  186. package/lib/node/view/view-provider.js +35 -0
  187. package/lib/node/view/view-provider.js.map +1 -0
  188. package/lib/package.spec.d.ts +1 -0
  189. package/lib/package.spec.d.ts.map +1 -0
  190. package/lib/package.spec.js +4 -0
  191. package/lib/package.spec.js.map +1 -0
  192. package/package.json +47 -0
  193. package/src/common/constants.ts +1 -0
  194. package/src/common/index.ts +1 -0
  195. package/src/node/annotation/body.ts +21 -0
  196. package/src/node/annotation/catch.ts +27 -0
  197. package/src/node/annotation/controller.ts +44 -0
  198. package/src/node/annotation/cookie.ts +41 -0
  199. package/src/node/annotation/file.ts +7 -0
  200. package/src/node/annotation/header.ts +41 -0
  201. package/src/node/annotation/html.ts +7 -0
  202. package/src/node/annotation/index.ts +17 -0
  203. package/src/node/annotation/json.ts +7 -0
  204. package/src/node/annotation/method.ts +61 -0
  205. package/src/node/annotation/param.ts +21 -0
  206. package/src/node/annotation/query.ts +21 -0
  207. package/src/node/annotation/req.ts +23 -0
  208. package/src/node/annotation/res.ts +23 -0
  209. package/src/node/annotation/session.ts +41 -0
  210. package/src/node/annotation/text.ts +7 -0
  211. package/src/node/annotation/view.ts +16 -0
  212. package/src/node/constants.ts +17 -0
  213. package/src/node/error/error-handler.ts +27 -0
  214. package/src/node/error/index.ts +1 -0
  215. package/src/node/handler/handler-adapter.ts +100 -0
  216. package/src/node/handler/handler-protocol.ts +62 -0
  217. package/src/node/handler/index.ts +5 -0
  218. package/src/node/handler/route-builder.ts +119 -0
  219. package/src/node/handler/route-metadata-matcher.ts +44 -0
  220. package/src/node/handler/route-provider.ts +27 -0
  221. package/src/node/index.ts +5 -0
  222. package/src/node/module.ts +4 -0
  223. package/src/node/resolver/index.ts +7 -0
  224. package/src/node/resolver/method-args-resolver-provider.ts +21 -0
  225. package/src/node/resolver/method-args-resolver.ts +119 -0
  226. package/src/node/resolver/resolver-protocol.ts +18 -0
  227. package/src/node/resolver/response-resolver-provider.ts +21 -0
  228. package/src/node/resolver/response-resolver.ts +46 -0
  229. package/src/node/resolver/view-resolver-provider.ts +21 -0
  230. package/src/node/resolver/view-resolver.ts +29 -0
  231. package/src/node/view/file-view.ts +68 -0
  232. package/src/node/view/html-view.ts +34 -0
  233. package/src/node/view/index.ts +6 -0
  234. package/src/node/view/json-view-template-renderer.ts +23 -0
  235. package/src/node/view/json-view.ts +26 -0
  236. package/src/node/view/text-view.ts +23 -0
  237. package/src/node/view/view-protocol.ts +14 -0
  238. package/src/node/view/view-provider.ts +21 -0
  239. package/src/package.spec.ts +4 -0
@@ -0,0 +1,61 @@
1
+ import { METADATA_KEY } from '../constants';
2
+ import { HttpMethod } from '@celljs/http';
3
+
4
+ export type StrOrRegex = string | RegExp;
5
+ export type RouteOptions = StrOrRegex | { path: StrOrRegex } | { options: Object, path: StrOrRegex } & Object;
6
+
7
+ export interface MethodMetadata {
8
+ options: RouteOptions;
9
+ target: any;
10
+ method: string;
11
+ key: string | symbol;
12
+ descriptor: TypedPropertyDescriptor<any>;
13
+ }
14
+
15
+ export function Get(options?: RouteOptions): MethodDecorator {
16
+ return Method(options, HttpMethod.GET);
17
+ }
18
+
19
+ export function Post(options?: RouteOptions): MethodDecorator {
20
+ return Method(options, HttpMethod.POST);
21
+ }
22
+
23
+ export function Put(options?: RouteOptions): MethodDecorator {
24
+ return Method(options, HttpMethod.PUT);
25
+ }
26
+
27
+ export function Patch(options?: RouteOptions): MethodDecorator {
28
+ return Method(options, HttpMethod.PATCH);
29
+ }
30
+
31
+ export function Head(options?: RouteOptions): MethodDecorator {
32
+ return Method(options, HttpMethod.HEAD);
33
+ }
34
+
35
+ export function Delete(options?: RouteOptions): MethodDecorator {
36
+ return Method(options, HttpMethod.DELETE);
37
+ }
38
+
39
+ export function Options(options?: RouteOptions): MethodDecorator {
40
+ return Method(options, HttpMethod.OPTIONS);
41
+ }
42
+
43
+ export function All(options?: RouteOptions): MethodDecorator {
44
+ return Method(options, HttpMethod.GET, HttpMethod.DELETE, HttpMethod.HEAD, HttpMethod.PATCH, HttpMethod.POST, HttpMethod.PUT, HttpMethod.TRACE, HttpMethod.OPTIONS);
45
+ }
46
+
47
+ export const Method = function (options: RouteOptions = '', ...methods: string[]): MethodDecorator {
48
+ return function (target, key, descriptor) {
49
+ let metadataList: MethodMetadata[] = [];
50
+
51
+ if (!Reflect.hasOwnMetadata(METADATA_KEY.controllerMethod, target.constructor)) {
52
+ Reflect.defineMetadata(METADATA_KEY.controllerMethod, metadataList, target.constructor);
53
+ } else {
54
+ metadataList = Reflect.getOwnMetadata(METADATA_KEY.controllerMethod, target.constructor);
55
+ }
56
+ for (const method of methods) {
57
+ const metadata: MethodMetadata = { options, method, target, key, descriptor };
58
+ metadataList.push(metadata);
59
+ }
60
+ };
61
+ };
@@ -0,0 +1,21 @@
1
+ import { METADATA_KEY } from '../constants';
2
+
3
+ export interface ParamMetadata {
4
+ name?: string;
5
+ parameterIndex: number;
6
+ }
7
+
8
+ export function Param(name?: string): ParameterDecorator {
9
+ return (t, tk, i) => {
10
+ applyParamDecorator(t, tk, i, name);
11
+ };
12
+ }
13
+
14
+ export function applyParamDecorator(target: any, targetKey: string | symbol | undefined, parameterIndex: number, name?: string): void {
15
+ if (!targetKey) {
16
+ return;
17
+ }
18
+ const metadatas: ParamMetadata[] = Reflect.getOwnMetadata(METADATA_KEY.controllerParam, target.constructor, targetKey) || [];
19
+ metadatas.push({ name, parameterIndex });
20
+ Reflect.defineMetadata(METADATA_KEY.controllerParam, metadatas, target.constructor, targetKey);
21
+ }
@@ -0,0 +1,21 @@
1
+ import { METADATA_KEY } from '../constants';
2
+
3
+ export interface QueryMetadata {
4
+ name?: string;
5
+ parameterIndex: number;
6
+ }
7
+
8
+ export function Query(name?: string): ParameterDecorator {
9
+ return (t, tk, i) => {
10
+ applyQueryDecorator(t, tk, i, name);
11
+ };
12
+ }
13
+
14
+ export function applyQueryDecorator(target: any, targetKey: string | symbol | undefined, parameterIndex: number, name?: string): void {
15
+ if (!targetKey) {
16
+ return;
17
+ }
18
+ const metadatas: QueryMetadata[] = Reflect.getOwnMetadata(METADATA_KEY.controllerQuery, target.constructor, targetKey) || [];
19
+ metadatas.push({ name, parameterIndex });
20
+ Reflect.defineMetadata(METADATA_KEY.controllerQuery, metadatas, target.constructor, targetKey);
21
+ }
@@ -0,0 +1,23 @@
1
+ import { METADATA_KEY } from '../constants';
2
+
3
+ export interface RequestMetadata {
4
+ parameterIndex: number;
5
+ }
6
+
7
+ export function Req(): ParameterDecorator {
8
+ return (t, tk, i) => {
9
+ applyRequestDecorator(t, tk, i);
10
+ };
11
+ }
12
+
13
+ export function applyRequestDecorator(target: any, targetKey: string | symbol | undefined, parameterIndex: number): void {
14
+ if (!targetKey) {
15
+ return;
16
+ }
17
+ Reflect.defineMetadata(
18
+ METADATA_KEY.controllerRequest,
19
+ { parameterIndex } as RequestMetadata,
20
+ target.constructor,
21
+ targetKey
22
+ );
23
+ }
@@ -0,0 +1,23 @@
1
+ import { METADATA_KEY } from '../constants';
2
+
3
+ export interface ResponseMetadata {
4
+ parameterIndex: number;
5
+ }
6
+
7
+ export function Res(): ParameterDecorator {
8
+ return (t, tk, i) => {
9
+ applyResponseDecorator(t, tk, i);
10
+ };
11
+ }
12
+
13
+ export function applyResponseDecorator(target: any, targetKey: string | symbol | undefined, parameterIndex: number): void {
14
+ if (!targetKey) {
15
+ return;
16
+ }
17
+ Reflect.defineMetadata(
18
+ METADATA_KEY.controllerResponse,
19
+ { parameterIndex } as ResponseMetadata,
20
+ target.constructor,
21
+ targetKey
22
+ );
23
+ }
@@ -0,0 +1,41 @@
1
+ import { METADATA_KEY } from '../constants';
2
+
3
+ export interface RequestSessionMetadata {
4
+ name?: string;
5
+ parameterIndex: number;
6
+ }
7
+
8
+ export interface ResponseSessionMetadata {
9
+ name: string;
10
+ value: string;
11
+ }
12
+
13
+ export interface SessionDecorator {
14
+ (name?: string): ParameterDecorator;
15
+ (name: string, value: string): MethodDecorator;
16
+
17
+ }
18
+
19
+ export const Session = <SessionDecorator>function (name?: string, value?: string) {
20
+ if (name && value) {
21
+ return (t: any, tk: string | symbol, d: PropertyDescriptor) => {
22
+ applyResponseSessionDecorator(t, tk, d, name, value);
23
+ };
24
+ } else {
25
+ return (t: any, tk: string | symbol, i: number) => {
26
+ applyRequestSessionDecorator(t, tk, i, name);
27
+ };
28
+ }
29
+ };
30
+
31
+ export function applyRequestSessionDecorator(target: any, targetKey: string | symbol, parameterIndex: number, name?: string): void {
32
+ const metadatas: RequestSessionMetadata[] = Reflect.getOwnMetadata(METADATA_KEY.controllerRequestSession, target.constructor, targetKey) || [];
33
+ metadatas.push({ name, parameterIndex });
34
+ Reflect.defineMetadata(METADATA_KEY.controllerRequestSession, metadatas, target.constructor, targetKey);
35
+ }
36
+
37
+ export function applyResponseSessionDecorator(target: any, targetKey: string | symbol, descriptor: PropertyDescriptor, name: string, value: string): void {
38
+ const metadatas: ResponseSessionMetadata[] = Reflect.getOwnMetadata(METADATA_KEY.controllerResponseSession, target.constructor, targetKey) || [];
39
+ metadatas.push({ name, value });
40
+ Reflect.defineMetadata(METADATA_KEY.controllerResponseSession, metadatas, target.constructor, targetKey);
41
+ }
@@ -0,0 +1,7 @@
1
+ import { View } from './view';
2
+
3
+ export const TEXT_VIEW_NAME = 'text';
4
+
5
+ export function Text(): MethodDecorator {
6
+ return View(TEXT_VIEW_NAME);
7
+ }
@@ -0,0 +1,16 @@
1
+ import { METADATA_KEY } from '../constants';
2
+
3
+ export interface ViewMetadata {
4
+ viewName: string;
5
+ metadata?: { [key: string]: any };
6
+ }
7
+
8
+ export function View(viewName: string, metadata?: { [key: string]: any }): MethodDecorator {
9
+ return (t, k, d) => {
10
+ applyViewDecorator(t, k, d, viewName, metadata);
11
+ };
12
+ }
13
+
14
+ export function applyViewDecorator(target: any, targetKey: string | symbol, descriptor: TypedPropertyDescriptor<any>, viewName: string, metadata?: { [key: string]: any }): void {
15
+ Reflect.defineMetadata(METADATA_KEY.controllerView, { viewName, metadata }, target.constructor, targetKey);
16
+ }
@@ -0,0 +1,17 @@
1
+ export const METADATA_KEY = {
2
+ controller: 'cell:controller',
3
+ controllerMethod: 'cell:controller-method',
4
+ controllerParam: 'cell:controller-param',
5
+ controllerRequestHeader: 'cell:controller-request-header',
6
+ controllerResponseHeader: 'cell:controller-response-header',
7
+ controllerRequestCookie: 'cell:controller-request-cookie',
8
+ controllerResponseCookie: 'cell:controller-response-cookie',
9
+ controllerRequestSession: 'cell:controller-request-session',
10
+ controllerResponseSession: 'cell:controller-response-session',
11
+ controllerQuery: 'cell:controller-query',
12
+ controllerBody: 'cell:controller-body',
13
+ controllerView: 'cell:controller-view',
14
+ controllerCatch: 'cell:controller-catch',
15
+ controllerRequest: 'cell:controller-request',
16
+ controllerResponse: 'cell:controller-response',
17
+ };
@@ -0,0 +1,27 @@
1
+ import { ErrorHandler, Context } from '@celljs/web/lib/node';
2
+ import { Component, Autowired, Value } from '@celljs/core';
3
+ import { JsonViewTemplateRenderer } from '../view/view-protocol';
4
+ import { HttpHeaders, MediaType } from '@celljs/http';
5
+
6
+ @Component(ErrorHandler)
7
+ export class JsonViewErrorHandler implements ErrorHandler {
8
+
9
+ @Value('cell.mvc.jsonView.errorHandler.priority?:2000')
10
+ readonly priority: number;
11
+
12
+ @Value('cell.mvc.jsonView.errorHandler.enabled?:true')
13
+ protected readonly enabled: boolean;
14
+
15
+ @Autowired(JsonViewTemplateRenderer)
16
+ protected readonly jsonViewTemplateRenderer: JsonViewTemplateRenderer;
17
+
18
+ async canHandle(ctx: Context, err: Error): Promise<boolean> {
19
+ return this.enabled;
20
+ }
21
+
22
+ async handle(ctx: Context, err: Error): Promise<void> {
23
+ ctx.response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8);
24
+ ctx.response.end(await this.jsonViewTemplateRenderer.render(undefined, err));
25
+ }
26
+ }
27
+
@@ -0,0 +1 @@
1
+ export * from './error-handler';
@@ -0,0 +1,100 @@
1
+ import { Component, Autowired, Value } from '@celljs/core';
2
+ import { PathResolver, PipeManager } from '@celljs/web';
3
+ import { Context, RequestMatcher, HandlerAdapter, NotFoundAndContinueError } from '@celljs/web/lib/node';
4
+ import { ViewResolver, ResponseResolverProvider, MethodArgsResolverProvider } from '../resolver';
5
+ import { MVC_HANDLER_ADAPTER_PRIORITY, RouteMetadataMatcher } from './handler-protocol';
6
+ import { MVC_PATH } from '../../common';
7
+
8
+ @Component(HandlerAdapter)
9
+ export class MvcHandlerAdapter implements HandlerAdapter {
10
+ readonly priority = MVC_HANDLER_ADAPTER_PRIORITY;
11
+
12
+ @Autowired(MethodArgsResolverProvider)
13
+ protected readonly methodArgsResolverProvider: MethodArgsResolverProvider;
14
+
15
+ @Autowired(ResponseResolverProvider)
16
+ protected readonly responseResolverProvider: ResponseResolverProvider;
17
+
18
+ @Autowired(ViewResolver)
19
+ protected readonly viewResolver: ViewResolver;
20
+
21
+ @Autowired(RequestMatcher)
22
+ protected readonly requestMatcher: RequestMatcher;
23
+
24
+ @Autowired(PathResolver)
25
+ protected readonly pathResolver: PathResolver;
26
+
27
+ @Autowired(PipeManager)
28
+ protected readonly pipeManager: PipeManager;
29
+
30
+ @Value(MVC_PATH)
31
+ protected readonly mvcPath: string;
32
+
33
+ @Autowired(RouteMetadataMatcher)
34
+ protected readonly routeMetadataMatcher: RouteMetadataMatcher;
35
+
36
+ protected async resolveMethodArgs(metadata: any) {
37
+ const args: any[] = [];
38
+ for (const resolver of this.methodArgsResolverProvider.provide()) {
39
+ await resolver.resolve(metadata, args);
40
+ }
41
+ return args;
42
+ }
43
+
44
+ protected async resolveResponse(metadata: any) {
45
+ for (const resolver of this.responseResolverProvider.provide()) {
46
+ await resolver.resolve(metadata);
47
+ }
48
+ }
49
+
50
+ async handle(): Promise<void> {
51
+ const ctx = Context.getCurrent();
52
+ const path = ctx.request.path;
53
+ const routeMetadata = await this.routeMetadataMatcher.match();
54
+ if (routeMetadata) {
55
+ await this.doHandle(routeMetadata);
56
+ } else {
57
+ throw new NotFoundAndContinueError(`No mapping found: ${ctx.request.method} ${path}`);
58
+ }
59
+ }
60
+
61
+ protected async doHandle(metadata: any, err?: any): Promise<void> {
62
+ let args = await this.resolveMethodArgs(metadata);
63
+ if (err) {
64
+ args = [err, ...args];
65
+ }
66
+ const methodMetadata = metadata.methodMetadata;
67
+ const target = methodMetadata.target;
68
+ let model: any;
69
+ try {
70
+ await this.pipeManager.apply({ target, method: methodMetadata.key }, args);
71
+ model = await target[methodMetadata.key](...args);
72
+ } catch (error) {
73
+ if (!err) {
74
+ const errorMetadata = await this.getErrorMetadata(error);
75
+ if (!errorMetadata.viewMetadata.viewName) {
76
+ errorMetadata.viewMetadata.viewName = metadata.viewMetadata.viewName;
77
+ }
78
+ await this.doHandle(errorMetadata, error);
79
+ } else {
80
+ throw error;
81
+ }
82
+ }
83
+ if (model) {
84
+ await this.viewResolver.resolve(metadata, model);
85
+ }
86
+ await this.resolveResponse(metadata);
87
+ }
88
+
89
+ protected async getErrorMetadata(error: Error) {
90
+ const routeMetadata = await this.routeMetadataMatcher.match(error);
91
+ if (routeMetadata) {
92
+ return routeMetadata;
93
+ }
94
+ throw error;
95
+ }
96
+
97
+ async canHandle(): Promise<boolean> {
98
+ return this.requestMatcher.match(await this.pathResolver.resolve(this.mvcPath));
99
+ }
100
+ }
@@ -0,0 +1,62 @@
1
+ import {
2
+ StrOrRegex,
3
+ ParamMetadata,
4
+ RequestMetadata,
5
+ QueryMetadata,
6
+ RequestHeaderMetadata,
7
+ ResponseHeaderMetadata,
8
+ RequestCookieMetadata,
9
+ ResponseCookieMetadata,
10
+ RequestSessionMetadata,
11
+ ResponseSessionMetadata,
12
+ ViewMetadata,
13
+ MethodMetadata,
14
+ CatchMetadata,
15
+ ControllerMetadata,
16
+ BodyMetadata,
17
+ ResponseMetadata,
18
+ } from '../annotation';
19
+ import { ErrorType } from '@celljs/core';
20
+
21
+ export const MVC_HANDLER_ADAPTER_PRIORITY = 2000;
22
+
23
+ export const RouteProvider = Symbol('RouteProvider');
24
+ export const RouteMetadataMatcher = Symbol('RouteMetadataMatcher');
25
+
26
+ export interface Route {
27
+ mapping: Map<string, PathRouteMetadata[]>;
28
+ errorMapping: Map<ErrorType, ErrorRouteMetadata>;
29
+ }
30
+
31
+ export interface RouteMetadata {
32
+ controllerMetadata: ControllerMetadata;
33
+ methodMetadata: MethodMetadata | CatchMetadata;
34
+ requestMetadata?: RequestMetadata;
35
+ responseMetadata?: ResponseMetadata;
36
+ paramMetadata?: ParamMetadata[];
37
+ bodyMetadata?: BodyMetadata[];
38
+ queryMetadata?: QueryMetadata[];
39
+ requestHeaderMetadata?: RequestHeaderMetadata[];
40
+ responseHeaderMetadata?: ResponseHeaderMetadata[];
41
+ requestCookieMetadata?: RequestCookieMetadata[];
42
+ responseCookieMetadata?: ResponseCookieMetadata[];
43
+ requestSessionMetadata?: RequestSessionMetadata[];
44
+ responseSessionMetadata?: ResponseSessionMetadata[];
45
+ viewMetadata: ViewMetadata;
46
+ }
47
+
48
+ export interface PathRouteMetadata extends RouteMetadata {
49
+ path: StrOrRegex;
50
+ }
51
+
52
+ export interface ErrorRouteMetadata extends RouteMetadata {
53
+ errorType: ErrorType;
54
+ }
55
+
56
+ export interface RouteProvider {
57
+ provide(): Promise<Route>;
58
+ }
59
+
60
+ export interface RouteMetadataMatcher {
61
+ match(error?: Error): Promise<RouteMetadata | undefined>;
62
+ }
@@ -0,0 +1,5 @@
1
+ export * from './handler-adapter';
2
+ export * from './handler-protocol';
3
+ export * from './route-builder';
4
+ export * from './route-provider';
5
+ export * from './route-metadata-matcher';
@@ -0,0 +1,119 @@
1
+ import { CONTROLLER, ControllerMetadata } from '../annotation/controller';
2
+ import { METADATA_KEY } from '../constants';
3
+ import { StrOrRegex, MethodMetadata } from '../annotation/method';
4
+ import { getOwnMetadata, Component, Autowired, Optional, ErrorType, Prioritizeable, getTargetClass } from '@celljs/core';
5
+ import { PathResolver } from '@celljs/web';
6
+ import { CatchMetadata } from '../annotation';
7
+ import { PathRouteMetadata, ErrorRouteMetadata } from './handler-protocol';
8
+
9
+ @Component()
10
+ export class RouteBuilder {
11
+
12
+ @Autowired(CONTROLLER) @Optional()
13
+ protected readonly controllers: any[] = [];
14
+
15
+ @Autowired(PathResolver)
16
+ protected readonly pathResolver: PathResolver;
17
+
18
+ async build() {
19
+ const mapping: Map<string, PathRouteMetadata[]> = new Map<string, PathRouteMetadata[]>();
20
+ const errorMapping: Map<ErrorType, any> = new Map<ErrorType, ErrorRouteMetadata>();
21
+
22
+ for (const controller of this.controllers) {
23
+ const targetConstructor = getTargetClass(controller);
24
+
25
+ const controllerMetadata = <ControllerMetadata>Reflect.getOwnMetadata(METADATA_KEY.controller, targetConstructor);
26
+ await this.doBuildRouteMap(mapping, targetConstructor, controller, controllerMetadata);
27
+ await this.doBuildErrorRouteMap(errorMapping, targetConstructor, controller, controllerMetadata);
28
+
29
+ }
30
+ return {
31
+ mapping,
32
+ errorMapping
33
+ };
34
+ }
35
+
36
+ protected async doBuildRouteMap(mapping: Map<string, PathRouteMetadata[]>, targetConstructor: any, controller: any, controllerMetadata: ControllerMetadata) {
37
+ const methodMetadata: MethodMetadata[] = getOwnMetadata(
38
+ METADATA_KEY.controllerMethod,
39
+ targetConstructor
40
+ );
41
+ for (const metadata of methodMetadata) {
42
+ const routeOptions: any = (typeof metadata.options === 'string' || metadata.options instanceof RegExp) ? { path: metadata.options } : metadata.options;
43
+ const m = { ...metadata };
44
+ const method = m.method;
45
+ m.target = controller;
46
+ let paths = mapping.get(method);
47
+ if (!paths) {
48
+ paths = [];
49
+ mapping.set(method, paths);
50
+ }
51
+ let path: StrOrRegex = routeOptions.path;
52
+ if (typeof path === 'string' ) {
53
+ path = await this.pathResolver.resolve(controllerMetadata.path, path);
54
+ } else if (path instanceof RegExp) {
55
+ if (controllerMetadata.path) {
56
+ path = new RegExp(await this.pathResolver.resolve(controllerMetadata.path, path.source));
57
+ }
58
+ }
59
+ const routeMetadata = {
60
+ path,
61
+ controllerMetadata,
62
+ methodMetadata: m,
63
+ ...this.doRouteMetadata(targetConstructor, m.key.toString())
64
+ };
65
+ paths.push(routeMetadata);
66
+ }
67
+
68
+ for (const [method, paths] of mapping) {
69
+ const sorted = Prioritizeable.prioritizeAllSync(paths, value => {
70
+ if (value.path instanceof RegExp) {
71
+ return Number.MIN_SAFE_INTEGER + value.path.toString().length;
72
+ } else if (value.path.includes('*')) {
73
+ return value.path.replace('*', '').length;
74
+ }
75
+ return value.path.length + 1;
76
+ }).map(({ value }) => value);
77
+ mapping.set(method, sorted);
78
+ }
79
+ }
80
+
81
+ protected async doBuildErrorRouteMap(errorMapping: Map<ErrorType, ErrorRouteMetadata>, targetConstructor: any, controller: any, controllerMetadata: ControllerMetadata) {
82
+ const methodMetadata: CatchMetadata[] = getOwnMetadata(
83
+ METADATA_KEY.controllerCatch,
84
+ targetConstructor
85
+ );
86
+ for (const metadata of methodMetadata) {
87
+ const m = { ...metadata };
88
+ m.target = controller;
89
+ for (const errorType of metadata.errorTypes) {
90
+ errorMapping.set(errorType, {
91
+ errorType,
92
+ controllerMetadata,
93
+ methodMetadata: m,
94
+ ...this.doRouteMetadata(targetConstructor, m.key.toString())
95
+ });
96
+ }
97
+ }
98
+ }
99
+
100
+ protected doRouteMetadata(targetConstructor: any, method: string) {
101
+ const viewMetadata = getOwnMetadata(METADATA_KEY.controllerView, targetConstructor, method);
102
+ const requestMetadata = getOwnMetadata(METADATA_KEY.controllerRequest, targetConstructor, method);
103
+ const responseMetadata = getOwnMetadata(METADATA_KEY.controllerResponse, targetConstructor, method);
104
+ return {
105
+ requestMetadata: requestMetadata[0],
106
+ responseMetadata: responseMetadata[0],
107
+ paramMetadata: getOwnMetadata(METADATA_KEY.controllerParam, targetConstructor, method),
108
+ bodyMetadata: getOwnMetadata(METADATA_KEY.controllerBody, targetConstructor, method),
109
+ queryMetadata: getOwnMetadata(METADATA_KEY.controllerQuery, targetConstructor, method),
110
+ requestHeaderMetadata: getOwnMetadata(METADATA_KEY.controllerRequestHeader, targetConstructor, method),
111
+ responseHeaderMetadata: getOwnMetadata(METADATA_KEY.controllerResponseHeader, targetConstructor, method),
112
+ requestCookieMetadata: getOwnMetadata(METADATA_KEY.controllerRequestCookie, targetConstructor, method),
113
+ responseCookieMetadata: getOwnMetadata(METADATA_KEY.controllerResponseCookie, targetConstructor, method),
114
+ requestSessionMetadata: getOwnMetadata(METADATA_KEY.controllerRequestSession, targetConstructor, method),
115
+ responseSessionMetadata: getOwnMetadata(METADATA_KEY.controllerResponseSession, targetConstructor, method),
116
+ viewMetadata: viewMetadata.length ? viewMetadata[0] : {}
117
+ };
118
+ }
119
+ }
@@ -0,0 +1,44 @@
1
+ import { Component, Autowired } from '@celljs/core';
2
+ import { RouteProvider, RouteMetadata, RouteMetadataMatcher } from './handler-protocol';
3
+ import { Context, RequestMatcher } from '@celljs/web/lib/node';
4
+
5
+ export const PATH_PARMAS_ATTR = 'pathParams';
6
+
7
+ @Component(RouteMetadataMatcher)
8
+ export class RouteMetadataMatcherImpl implements RouteMetadataMatcher {
9
+
10
+ @Autowired(RouteProvider)
11
+ protected readonly routeProvider: RouteProvider;
12
+
13
+ @Autowired(RequestMatcher)
14
+ protected readonly requestMatcher: RequestMatcher;
15
+
16
+ async match(error?: Error): Promise<RouteMetadata | undefined> {
17
+ const route = await this.routeProvider.provide();
18
+ if (error) {
19
+ const metadata = route.errorMapping.get(error.constructor);
20
+ if (metadata) {
21
+ return metadata;
22
+ } else {
23
+ for (const entry of route.errorMapping) {
24
+ if (error instanceof <any>entry[0]) {
25
+ return entry[1];
26
+ }
27
+ }
28
+ }
29
+ } else {
30
+ const request = Context.getRequest();
31
+ const paths = route.mapping.get(request.method!.toUpperCase());
32
+ if (paths) {
33
+ for (const pathRouteMetadata of paths) {
34
+ const pathParams = await this.requestMatcher.match(pathRouteMetadata.path);
35
+ if (pathParams) {
36
+ Context.setAttr(PATH_PARMAS_ATTR, pathParams);
37
+ return pathRouteMetadata;
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ }
@@ -0,0 +1,27 @@
1
+ import { Component, Autowired, Deferred, PostConstruct } from '@celljs/core';
2
+ import { Route, RouteProvider } from './handler-protocol';
3
+ import { RouteBuilder } from './route-builder';
4
+
5
+ @Component(RouteProvider)
6
+ export class RouteProviderImpl implements RouteProvider {
7
+
8
+ protected route: Route;
9
+
10
+ protected routeDeferred = new Deferred<Route>();
11
+
12
+ @Autowired(RouteBuilder)
13
+ protected readonly routeBuilder: RouteBuilder;
14
+
15
+ @PostConstruct()
16
+ protected init() {
17
+ this.routeBuilder.build().then(route => {
18
+ this.route = route;
19
+ this.routeDeferred.resolve(route);
20
+ });
21
+ }
22
+
23
+ provide(): Promise<Route> {
24
+ return this.routeDeferred.promise;
25
+ }
26
+
27
+ }
@@ -0,0 +1,5 @@
1
+ export * from './annotation';
2
+ export * from './handler';
3
+ export * from './resolver';
4
+ export * from './view';
5
+ export * from './error';
@@ -0,0 +1,4 @@
1
+ import { autoBind } from '@celljs/core';
2
+ import './index';
3
+
4
+ export default autoBind();
@@ -0,0 +1,7 @@
1
+ export * from './response-resolver';
2
+ export * from './method-args-resolver';
3
+ export * from './method-args-resolver-provider';
4
+ export * from './resolver-protocol';
5
+ export * from './response-resolver-provider';
6
+ export * from './view-resolver';
7
+ export * from './view-resolver-provider';