@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.
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/cell.yml +9 -0
- package/lib/common/constants.d.ts +2 -0
- package/lib/common/constants.d.ts.map +1 -0
- package/lib/common/constants.js +5 -0
- package/lib/common/constants.js.map +1 -0
- package/lib/common/index.d.ts +2 -0
- package/lib/common/index.d.ts.map +1 -0
- package/lib/common/index.js +18 -0
- package/lib/common/index.js.map +1 -0
- package/lib/node/annotation/body.d.ts +7 -0
- package/lib/node/annotation/body.d.ts.map +1 -0
- package/lib/node/annotation/body.js +20 -0
- package/lib/node/annotation/body.js.map +1 -0
- package/lib/node/annotation/catch.d.ts +10 -0
- package/lib/node/annotation/catch.d.ts.map +1 -0
- package/lib/node/annotation/catch.js +23 -0
- package/lib/node/annotation/catch.js.map +1 -0
- package/lib/node/annotation/controller.d.ts +15 -0
- package/lib/node/annotation/controller.d.ts.map +1 -0
- package/lib/node/annotation/controller.js +35 -0
- package/lib/node/annotation/controller.js.map +1 -0
- package/lib/node/annotation/cookie.d.ts +16 -0
- package/lib/node/annotation/cookie.d.ts.map +1 -0
- package/lib/node/annotation/cookie.js +29 -0
- package/lib/node/annotation/cookie.js.map +1 -0
- package/lib/node/annotation/file.d.ts +3 -0
- package/lib/node/annotation/file.d.ts.map +1 -0
- package/lib/node/annotation/file.js +10 -0
- package/lib/node/annotation/file.js.map +1 -0
- package/lib/node/annotation/header.d.ts +16 -0
- package/lib/node/annotation/header.d.ts.map +1 -0
- package/lib/node/annotation/header.js +29 -0
- package/lib/node/annotation/header.js.map +1 -0
- package/lib/node/annotation/html.d.ts +3 -0
- package/lib/node/annotation/html.d.ts.map +1 -0
- package/lib/node/annotation/html.js +10 -0
- package/lib/node/annotation/html.js.map +1 -0
- package/lib/node/annotation/index.d.ts +17 -0
- package/lib/node/annotation/index.d.ts.map +1 -0
- package/lib/node/annotation/index.js +33 -0
- package/lib/node/annotation/index.js.map +1 -0
- package/lib/node/annotation/json.d.ts +3 -0
- package/lib/node/annotation/json.d.ts.map +1 -0
- package/lib/node/annotation/json.js +10 -0
- package/lib/node/annotation/json.js.map +1 -0
- package/lib/node/annotation/method.d.ts +24 -0
- package/lib/node/annotation/method.d.ts.map +1 -0
- package/lib/node/annotation/method.js +54 -0
- package/lib/node/annotation/method.js.map +1 -0
- package/lib/node/annotation/param.d.ts +7 -0
- package/lib/node/annotation/param.d.ts.map +1 -0
- package/lib/node/annotation/param.js +20 -0
- package/lib/node/annotation/param.js.map +1 -0
- package/lib/node/annotation/query.d.ts +7 -0
- package/lib/node/annotation/query.d.ts.map +1 -0
- package/lib/node/annotation/query.js +20 -0
- package/lib/node/annotation/query.js.map +1 -0
- package/lib/node/annotation/req.d.ts +6 -0
- package/lib/node/annotation/req.d.ts.map +1 -0
- package/lib/node/annotation/req.js +18 -0
- package/lib/node/annotation/req.js.map +1 -0
- package/lib/node/annotation/res.d.ts +6 -0
- package/lib/node/annotation/res.d.ts.map +1 -0
- package/lib/node/annotation/res.js +18 -0
- package/lib/node/annotation/res.js.map +1 -0
- package/lib/node/annotation/session.d.ts +16 -0
- package/lib/node/annotation/session.d.ts.map +1 -0
- package/lib/node/annotation/session.js +29 -0
- package/lib/node/annotation/session.js.map +1 -0
- package/lib/node/annotation/text.d.ts +3 -0
- package/lib/node/annotation/text.d.ts.map +1 -0
- package/lib/node/annotation/text.js +10 -0
- package/lib/node/annotation/text.js.map +1 -0
- package/lib/node/annotation/view.d.ts +13 -0
- package/lib/node/annotation/view.d.ts.map +1 -0
- package/lib/node/annotation/view.js +15 -0
- package/lib/node/annotation/view.js.map +1 -0
- package/lib/node/constants.d.ts +18 -0
- package/lib/node/constants.d.ts.map +1 -0
- package/lib/node/constants.js +21 -0
- package/lib/node/constants.js.map +1 -0
- package/lib/node/error/error-handler.d.ts +10 -0
- package/lib/node/error/error-handler.d.ts.map +1 -0
- package/lib/node/error/error-handler.js +42 -0
- package/lib/node/error/error-handler.js.map +1 -0
- package/lib/node/error/index.d.ts +2 -0
- package/lib/node/error/index.d.ts.map +1 -0
- package/lib/node/error/index.js +18 -0
- package/lib/node/error/index.js.map +1 -0
- package/lib/node/handler/handler-adapter.d.ts +22 -0
- package/lib/node/handler/handler-adapter.d.ts.map +1 -0
- package/lib/node/handler/handler-adapter.js +122 -0
- package/lib/node/handler/handler-adapter.js.map +1 -0
- package/lib/node/handler/handler-protocol.d.ts +38 -0
- package/lib/node/handler/handler-protocol.d.ts.map +1 -0
- package/lib/node/handler/handler-protocol.js +7 -0
- package/lib/node/handler/handler-protocol.js.map +1 -0
- package/lib/node/handler/index.d.ts +6 -0
- package/lib/node/handler/index.d.ts.map +1 -0
- package/lib/node/handler/index.js +22 -0
- package/lib/node/handler/index.js.map +1 -0
- package/lib/node/handler/route-builder.d.ts +29 -0
- package/lib/node/handler/route-builder.d.ts.map +1 -0
- package/lib/node/handler/route-builder.js +117 -0
- package/lib/node/handler/route-builder.js.map +1 -0
- package/lib/node/handler/route-metadata-matcher.d.ts +9 -0
- package/lib/node/handler/route-metadata-matcher.d.ts.map +1 -0
- package/lib/node/handler/route-metadata-matcher.js +60 -0
- package/lib/node/handler/route-metadata-matcher.js.map +1 -0
- package/lib/node/handler/route-provider.d.ts +11 -0
- package/lib/node/handler/route-provider.d.ts.map +1 -0
- package/lib/node/handler/route-provider.js +44 -0
- package/lib/node/handler/route-provider.js.map +1 -0
- package/lib/node/index.d.ts +6 -0
- package/lib/node/index.d.ts.map +1 -0
- package/lib/node/index.js +22 -0
- package/lib/node/index.js.map +1 -0
- package/lib/node/module.d.ts +4 -0
- package/lib/node/module.d.ts.map +1 -0
- package/lib/node/module.js +6 -0
- package/lib/node/module.js.map +1 -0
- package/lib/node/resolver/index.d.ts +8 -0
- package/lib/node/resolver/index.d.ts.map +1 -0
- package/lib/node/resolver/index.js +24 -0
- package/lib/node/resolver/index.js.map +1 -0
- package/lib/node/resolver/method-args-resolver-provider.d.ts +8 -0
- package/lib/node/resolver/method-args-resolver-provider.d.ts.map +1 -0
- package/lib/node/resolver/method-args-resolver-provider.js +35 -0
- package/lib/node/resolver/method-args-resolver-provider.js.map +1 -0
- package/lib/node/resolver/method-args-resolver.d.ts +35 -0
- package/lib/node/resolver/method-args-resolver.d.ts.map +1 -0
- package/lib/node/resolver/method-args-resolver.js +152 -0
- package/lib/node/resolver/method-args-resolver.js.map +1 -0
- package/lib/node/resolver/resolver-protocol.d.ts +15 -0
- package/lib/node/resolver/resolver-protocol.d.ts.map +1 -0
- package/lib/node/resolver/resolver-protocol.js +7 -0
- package/lib/node/resolver/resolver-protocol.js.map +1 -0
- package/lib/node/resolver/response-resolver-provider.d.ts +8 -0
- package/lib/node/resolver/response-resolver-provider.d.ts.map +1 -0
- package/lib/node/resolver/response-resolver-provider.js +35 -0
- package/lib/node/resolver/response-resolver-provider.js.map +1 -0
- package/lib/node/resolver/response-resolver.d.ts +14 -0
- package/lib/node/resolver/response-resolver.d.ts.map +1 -0
- package/lib/node/resolver/response-resolver.js +67 -0
- package/lib/node/resolver/response-resolver.js.map +1 -0
- package/lib/node/resolver/view-resolver-provider.d.ts +8 -0
- package/lib/node/resolver/view-resolver-provider.d.ts.map +1 -0
- package/lib/node/resolver/view-resolver-provider.js +35 -0
- package/lib/node/resolver/view-resolver-provider.js.map +1 -0
- package/lib/node/resolver/view-resolver.d.ts +8 -0
- package/lib/node/resolver/view-resolver.d.ts.map +1 -0
- package/lib/node/resolver/view-resolver.js +44 -0
- package/lib/node/resolver/view-resolver.js.map +1 -0
- package/lib/node/view/file-view.d.ts +19 -0
- package/lib/node/view/file-view.d.ts.map +1 -0
- package/lib/node/view/file-view.js +79 -0
- package/lib/node/view/file-view.js.map +1 -0
- package/lib/node/view/html-view.d.ts +11 -0
- package/lib/node/view/html-view.d.ts.map +1 -0
- package/lib/node/view/html-view.js +48 -0
- package/lib/node/view/html-view.js.map +1 -0
- package/lib/node/view/index.d.ts +7 -0
- package/lib/node/view/index.d.ts.map +1 -0
- package/lib/node/view/index.js +23 -0
- package/lib/node/view/index.js.map +1 -0
- package/lib/node/view/json-view-template-renderer.d.ts +6 -0
- package/lib/node/view/json-view-template-renderer.d.ts.map +1 -0
- package/lib/node/view/json-view-template-renderer.js +39 -0
- package/lib/node/view/json-view-template-renderer.js.map +1 -0
- package/lib/node/view/json-view.d.ts +11 -0
- package/lib/node/view/json-view.d.ts.map +1 -0
- package/lib/node/view/json-view.js +39 -0
- package/lib/node/view/json-view.js.map +1 -0
- package/lib/node/view/text-view.d.ts +10 -0
- package/lib/node/view/text-view.d.ts.map +1 -0
- package/lib/node/view/text-view.js +32 -0
- package/lib/node/view/text-view.js.map +1 -0
- package/lib/node/view/view-protocol.d.ts +12 -0
- package/lib/node/view/view-protocol.d.ts.map +1 -0
- package/lib/node/view/view-protocol.js +6 -0
- package/lib/node/view/view-protocol.js.map +1 -0
- package/lib/node/view/view-provider.d.ts +8 -0
- package/lib/node/view/view-provider.d.ts.map +1 -0
- package/lib/node/view/view-provider.js +35 -0
- package/lib/node/view/view-provider.js.map +1 -0
- package/lib/package.spec.d.ts +1 -0
- package/lib/package.spec.d.ts.map +1 -0
- package/lib/package.spec.js +4 -0
- package/lib/package.spec.js.map +1 -0
- package/package.json +47 -0
- package/src/common/constants.ts +1 -0
- package/src/common/index.ts +1 -0
- package/src/node/annotation/body.ts +21 -0
- package/src/node/annotation/catch.ts +27 -0
- package/src/node/annotation/controller.ts +44 -0
- package/src/node/annotation/cookie.ts +41 -0
- package/src/node/annotation/file.ts +7 -0
- package/src/node/annotation/header.ts +41 -0
- package/src/node/annotation/html.ts +7 -0
- package/src/node/annotation/index.ts +17 -0
- package/src/node/annotation/json.ts +7 -0
- package/src/node/annotation/method.ts +61 -0
- package/src/node/annotation/param.ts +21 -0
- package/src/node/annotation/query.ts +21 -0
- package/src/node/annotation/req.ts +23 -0
- package/src/node/annotation/res.ts +23 -0
- package/src/node/annotation/session.ts +41 -0
- package/src/node/annotation/text.ts +7 -0
- package/src/node/annotation/view.ts +16 -0
- package/src/node/constants.ts +17 -0
- package/src/node/error/error-handler.ts +27 -0
- package/src/node/error/index.ts +1 -0
- package/src/node/handler/handler-adapter.ts +100 -0
- package/src/node/handler/handler-protocol.ts +62 -0
- package/src/node/handler/index.ts +5 -0
- package/src/node/handler/route-builder.ts +119 -0
- package/src/node/handler/route-metadata-matcher.ts +44 -0
- package/src/node/handler/route-provider.ts +27 -0
- package/src/node/index.ts +5 -0
- package/src/node/module.ts +4 -0
- package/src/node/resolver/index.ts +7 -0
- package/src/node/resolver/method-args-resolver-provider.ts +21 -0
- package/src/node/resolver/method-args-resolver.ts +119 -0
- package/src/node/resolver/resolver-protocol.ts +18 -0
- package/src/node/resolver/response-resolver-provider.ts +21 -0
- package/src/node/resolver/response-resolver.ts +46 -0
- package/src/node/resolver/view-resolver-provider.ts +21 -0
- package/src/node/resolver/view-resolver.ts +29 -0
- package/src/node/view/file-view.ts +68 -0
- package/src/node/view/html-view.ts +34 -0
- package/src/node/view/index.ts +6 -0
- package/src/node/view/json-view-template-renderer.ts +23 -0
- package/src/node/view/json-view.ts +26 -0
- package/src/node/view/text-view.ts +23 -0
- package/src/node/view/view-protocol.ts +14 -0
- package/src/node/view/view-provider.ts +21 -0
- package/src/package.spec.ts +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Component, Autowired, Prioritizeable } from '@celljs/core';
|
|
2
|
+
import { MethodArgsResolver } from './resolver-protocol';
|
|
3
|
+
|
|
4
|
+
@Component()
|
|
5
|
+
export class MethodArgsResolverProvider {
|
|
6
|
+
|
|
7
|
+
protected prioritized: MethodArgsResolver[];
|
|
8
|
+
|
|
9
|
+
constructor(
|
|
10
|
+
@Autowired(MethodArgsResolver)
|
|
11
|
+
protected readonly methodArgsResolvers: MethodArgsResolver[]
|
|
12
|
+
) { }
|
|
13
|
+
|
|
14
|
+
provide(): MethodArgsResolver[] {
|
|
15
|
+
if (!this.prioritized) {
|
|
16
|
+
this.prioritized = Prioritizeable.prioritizeAllSync(this.methodArgsResolvers).map(c => c.value);
|
|
17
|
+
}
|
|
18
|
+
return this.prioritized;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { MethodArgsResolver } from './resolver-protocol';
|
|
2
|
+
import { Context } from '@celljs/web/lib/node';
|
|
3
|
+
import { Component } from '@celljs/core';
|
|
4
|
+
import {
|
|
5
|
+
RequestHeaderMetadata,
|
|
6
|
+
ParamMetadata,
|
|
7
|
+
QueryMetadata,
|
|
8
|
+
RequestCookieMetadata,
|
|
9
|
+
RequestSessionMetadata,
|
|
10
|
+
BodyMetadata
|
|
11
|
+
} from '../annotation';
|
|
12
|
+
import {PATH_PARMAS_ATTR, RouteMetadata} from '../handler';
|
|
13
|
+
|
|
14
|
+
@Component(MethodArgsResolver)
|
|
15
|
+
export class BodyMethodArgsResolver implements MethodArgsResolver {
|
|
16
|
+
readonly priority = 100;
|
|
17
|
+
async resolve(metadata: any, args: any[]): Promise<void> {
|
|
18
|
+
const body: any = Context.getCurrent().request.body;
|
|
19
|
+
const bodyMetadatas = <BodyMetadata[]>metadata.bodyMetadata;
|
|
20
|
+
if (bodyMetadatas && body !== undefined) {
|
|
21
|
+
for (const m of bodyMetadatas) {
|
|
22
|
+
args[m.parameterIndex] = m.name ? body[m.name] : body;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@Component(MethodArgsResolver)
|
|
29
|
+
export class HeaderMethodArgsResolver implements MethodArgsResolver {
|
|
30
|
+
readonly priority = 200;
|
|
31
|
+
async resolve(metadata: any, args: any[]): Promise<void> {
|
|
32
|
+
const headerMetadatas = <RequestHeaderMetadata[]>metadata.requestHeaderMetadata;
|
|
33
|
+
if (headerMetadatas) {
|
|
34
|
+
const request = Context.getCurrent().request;
|
|
35
|
+
for (const m of headerMetadatas) {
|
|
36
|
+
args[m.parameterIndex] = m.name ? request.get(m.name) : request.headers;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@Component(MethodArgsResolver)
|
|
43
|
+
export class ParamMethodArgsResolver implements MethodArgsResolver {
|
|
44
|
+
readonly priority = 300;
|
|
45
|
+
|
|
46
|
+
async resolve(metadata: any, args: any[]): Promise<void> {
|
|
47
|
+
const params: any = Context.getAttr(PATH_PARMAS_ATTR);
|
|
48
|
+
const paramMetadatas = <ParamMetadata[]>metadata.paramMetadata;
|
|
49
|
+
if (paramMetadatas && params) {
|
|
50
|
+
for (const m of paramMetadatas) {
|
|
51
|
+
args[m.parameterIndex] = m.name ? params[m.name] : params;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@Component(MethodArgsResolver)
|
|
58
|
+
export class QueryMethodArgsResolver implements MethodArgsResolver {
|
|
59
|
+
readonly priority = 400;
|
|
60
|
+
async resolve(metadata: any, args: any[]): Promise<void> {
|
|
61
|
+
const query: any = Context.getCurrent().request.query;
|
|
62
|
+
const queryMetadatas = <QueryMetadata[]>metadata.queryMetadata;
|
|
63
|
+
if (queryMetadatas && query !== undefined) {
|
|
64
|
+
for (const m of queryMetadatas) {
|
|
65
|
+
args[m.parameterIndex] = m.name ? query[m.name] : query;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@Component(MethodArgsResolver)
|
|
72
|
+
export class CookieMethodArgsResolver implements MethodArgsResolver {
|
|
73
|
+
readonly priority = 500;
|
|
74
|
+
async resolve(metadata: any, args: any[]): Promise<void> {
|
|
75
|
+
const cookies = Context.getCookies();
|
|
76
|
+
const cookieMetadatas = <RequestCookieMetadata[]>metadata.requestCookieMetadata;
|
|
77
|
+
if (cookieMetadatas && cookies !== undefined) {
|
|
78
|
+
for (const m of cookieMetadatas) {
|
|
79
|
+
args[m.parameterIndex] = m.name ? cookies.get(m.name) : cookies;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@Component(MethodArgsResolver)
|
|
86
|
+
export class SessionMethodArgsResolver implements MethodArgsResolver {
|
|
87
|
+
readonly priority = 600;
|
|
88
|
+
async resolve(metadata: any, args: any[]): Promise<void> {
|
|
89
|
+
const session = Context.getSession();
|
|
90
|
+
const sessionMetadatas = <RequestSessionMetadata[]>metadata.requestSessionMetadata;
|
|
91
|
+
if (sessionMetadatas && session !== undefined) {
|
|
92
|
+
for (const m of sessionMetadatas) {
|
|
93
|
+
args[m.parameterIndex] = m.name ? session[m.name] : session;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@Component(MethodArgsResolver)
|
|
100
|
+
export class RequestMethodArgsResolver implements MethodArgsResolver {
|
|
101
|
+
readonly priority = 700;
|
|
102
|
+
async resolve(metadata: RouteMetadata, args: any[]): Promise<void> {
|
|
103
|
+
const requestMetadata = metadata.requestMetadata;
|
|
104
|
+
if (requestMetadata) {
|
|
105
|
+
args[requestMetadata.parameterIndex] = Context.getRequest();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@Component(MethodArgsResolver)
|
|
111
|
+
export class ResponseMethodArgsResolver implements MethodArgsResolver {
|
|
112
|
+
readonly priority = 800;
|
|
113
|
+
async resolve(metadata: RouteMetadata, args: any[]): Promise<void> {
|
|
114
|
+
const responseMetadata = metadata.responseMetadata;
|
|
115
|
+
if (responseMetadata) {
|
|
116
|
+
args[responseMetadata.parameterIndex] = Context.getResponse();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
export const MethodArgsResolver = Symbol('MethodArgsResolver');
|
|
3
|
+
export const ResponseResolver = Symbol('ResponseResolver');
|
|
4
|
+
export const ViewResolver = Symbol('ViewResolver');
|
|
5
|
+
|
|
6
|
+
export interface MethodArgsResolver {
|
|
7
|
+
readonly priority: number;
|
|
8
|
+
resolve(metadata: any, args: any[]): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ResponseResolver {
|
|
12
|
+
readonly priority: number;
|
|
13
|
+
resolve(metadata: any): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ViewResolver {
|
|
17
|
+
resolve(metadata: any, model: any): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Component, Autowired, Prioritizeable } from '@celljs/core';
|
|
2
|
+
import { ResponseResolver } from './resolver-protocol';
|
|
3
|
+
|
|
4
|
+
@Component()
|
|
5
|
+
export class ResponseResolverProvider {
|
|
6
|
+
|
|
7
|
+
protected prioritized: ResponseResolver[];
|
|
8
|
+
|
|
9
|
+
constructor(
|
|
10
|
+
@Autowired(ResponseResolver)
|
|
11
|
+
protected readonly responseResolvers: ResponseResolver[]
|
|
12
|
+
) { }
|
|
13
|
+
|
|
14
|
+
provide(): ResponseResolver[] {
|
|
15
|
+
if (!this.prioritized) {
|
|
16
|
+
this.prioritized = Prioritizeable.prioritizeAllSync(this.responseResolvers).map(c => c.value);
|
|
17
|
+
}
|
|
18
|
+
return this.prioritized;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ResponseResolver } from './resolver-protocol';
|
|
2
|
+
import { Context } from '@celljs/web/lib/node';
|
|
3
|
+
import { Component } from '@celljs/core';
|
|
4
|
+
import { ResponseHeaderMetadata, ResponseCookieMetadata, ResponseSessionMetadata } from '../annotation';
|
|
5
|
+
|
|
6
|
+
@Component(ResponseResolver)
|
|
7
|
+
export class HeaderResponseResolver implements ResponseResolver {
|
|
8
|
+
readonly priority = 500;
|
|
9
|
+
async resolve(metadata: any): Promise<void> {
|
|
10
|
+
const response = Context.getCurrent().response;
|
|
11
|
+
const headerMetadatas = <ResponseHeaderMetadata[]>metadata.responseHeaderMetadata;
|
|
12
|
+
if (headerMetadatas) {
|
|
13
|
+
for (const m of headerMetadatas) {
|
|
14
|
+
response.setHeader(m.name, m.value);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Component(ResponseResolver)
|
|
21
|
+
export class CookieResponseResolver implements ResponseResolver {
|
|
22
|
+
readonly priority = 500;
|
|
23
|
+
async resolve(metadata: any): Promise<void> {
|
|
24
|
+
const cookies = Context.getCookies();
|
|
25
|
+
const cookieMetadatas = <ResponseCookieMetadata[]>metadata.responseCookieMetadata;
|
|
26
|
+
if (cookieMetadatas && cookies) {
|
|
27
|
+
for (const m of cookieMetadatas) {
|
|
28
|
+
cookies.set(m.name, m.value);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Component(ResponseResolver)
|
|
35
|
+
export class SessionResponseResolver implements ResponseResolver {
|
|
36
|
+
readonly priority = 500;
|
|
37
|
+
async resolve(metadata: any): Promise<void> {
|
|
38
|
+
const session = Context.getSession();
|
|
39
|
+
const sessionMetadatas = <ResponseSessionMetadata[]>metadata.responseSessionMetadata;
|
|
40
|
+
if (sessionMetadatas && session) {
|
|
41
|
+
for (const m of sessionMetadatas) {
|
|
42
|
+
session[m.name] = m.value;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Component, Autowired, Prioritizeable } from '@celljs/core';
|
|
2
|
+
import { ViewResolver } from './resolver-protocol';
|
|
3
|
+
|
|
4
|
+
@Component()
|
|
5
|
+
export class ViewResolverProvider {
|
|
6
|
+
|
|
7
|
+
protected prioritized: ViewResolver[];
|
|
8
|
+
|
|
9
|
+
constructor(
|
|
10
|
+
@Autowired(ViewResolver)
|
|
11
|
+
protected readonly viewResolvers: ViewResolver[]
|
|
12
|
+
) { }
|
|
13
|
+
|
|
14
|
+
provide(): ViewResolver[] {
|
|
15
|
+
if (!this.prioritized) {
|
|
16
|
+
this.prioritized = Prioritizeable.prioritizeAllSync(this.viewResolvers).map(c => c.value);
|
|
17
|
+
}
|
|
18
|
+
return this.prioritized;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ViewResolver } from './resolver-protocol';
|
|
2
|
+
import { Component, Autowired, Value } from '@celljs/core';
|
|
3
|
+
import { ViewProvider } from '../view/view-provider';
|
|
4
|
+
import { ViewMetadata } from '../annotation/view';
|
|
5
|
+
import { Context } from '@celljs/web/lib/node';
|
|
6
|
+
import { HttpHeaders } from '@celljs/http';
|
|
7
|
+
|
|
8
|
+
@Component(ViewResolver)
|
|
9
|
+
export class ViewResolverImpl implements ViewResolver {
|
|
10
|
+
|
|
11
|
+
@Value('cell.mvc.defaultViewName')
|
|
12
|
+
protected readonly defaultViewName: string;
|
|
13
|
+
|
|
14
|
+
@Autowired(ViewProvider)
|
|
15
|
+
protected readonly viewProvider: ViewProvider;
|
|
16
|
+
|
|
17
|
+
async resolve(metadata: any, model: any): Promise<void> {
|
|
18
|
+
const viewMetadata = <ViewMetadata>metadata.viewMetadata;
|
|
19
|
+
viewMetadata.viewName = viewMetadata.viewName || this.defaultViewName;
|
|
20
|
+
for (const view of this.viewProvider.provide()) {
|
|
21
|
+
if (await view.support(viewMetadata)) {
|
|
22
|
+
Context.getResponse().setHeader(HttpHeaders.CONTENT_TYPE, view.contentType);
|
|
23
|
+
await view.render(model, viewMetadata);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
throw new Error('Not found a suitable view.');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Autowired, Component, Logger, Value } from '@celljs/core';
|
|
2
|
+
import { View } from './view-protocol';
|
|
3
|
+
import { HttpHeaders, HttpStatus, MediaType } from '@celljs/http';
|
|
4
|
+
import { Context, Response } from '@celljs/web/lib/node';
|
|
5
|
+
import { Stream } from 'stream';
|
|
6
|
+
import { FILE_VIEW_NAME } from '../annotation/file';
|
|
7
|
+
import { ViewMetadata } from '../annotation/view';
|
|
8
|
+
import { createReadStream } from 'fs-extra';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
|
|
11
|
+
@Component(View)
|
|
12
|
+
export class FileView implements View {
|
|
13
|
+
|
|
14
|
+
readonly contentType = MediaType.APPLICATION_OCTET_STREAM;
|
|
15
|
+
|
|
16
|
+
readonly priority = 600;
|
|
17
|
+
|
|
18
|
+
@Autowired(Logger)
|
|
19
|
+
protected readonly logger: Logger;
|
|
20
|
+
|
|
21
|
+
@Value('cell.mvc.baseFileDir')
|
|
22
|
+
protected readonly baseFileDir: any;
|
|
23
|
+
|
|
24
|
+
protected isStream(model: any) {
|
|
25
|
+
return typeof model === 'object'
|
|
26
|
+
&& typeof model.pipe === 'function';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async render(model: any, { metadata }: ViewMetadata): Promise<void> {
|
|
30
|
+
if (metadata?.file) {
|
|
31
|
+
model = createReadStream(join(__dirname, this.baseFileDir, metadata.file));
|
|
32
|
+
}
|
|
33
|
+
const response = Context.getCurrent().response;
|
|
34
|
+
if (this.isStream(model)) {
|
|
35
|
+
Context.setSkipAutoEnd(true);
|
|
36
|
+
this.streamDownload(response, model);
|
|
37
|
+
} else {
|
|
38
|
+
if (Buffer.isBuffer(model)) {
|
|
39
|
+
response.setHeader(HttpHeaders.CONTENT_LENGTH, model.byteLength);
|
|
40
|
+
}
|
|
41
|
+
response.body = model;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
protected streamDownload(response: Response, stream: Stream): void {
|
|
46
|
+
stream.on('error', error => {
|
|
47
|
+
this.handleError(response, error);
|
|
48
|
+
});
|
|
49
|
+
response.on('error', error => {
|
|
50
|
+
this.handleError(response, error);
|
|
51
|
+
});
|
|
52
|
+
response.on('close', () => {
|
|
53
|
+
if (typeof (stream as any).destroy === 'function') {
|
|
54
|
+
(stream as any).destroy();
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
stream.pipe(response);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
protected async handleError(response: Response, reason: string | Error, status: number = HttpStatus.INTERNAL_SERVER_ERROR): Promise<void> {
|
|
61
|
+
this.logger.error(reason);
|
|
62
|
+
response.status(status).send('Unable to download file.').end();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
support({ viewName }: ViewMetadata): Promise<boolean> {
|
|
66
|
+
return Promise.resolve(viewName === FILE_VIEW_NAME);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Component, Value } from '@celljs/core';
|
|
2
|
+
import { View } from './view-protocol';
|
|
3
|
+
import { Context } from '@celljs/web/lib/node';
|
|
4
|
+
import { parse, render } from 'mustache';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { readFile } from 'fs-extra';
|
|
7
|
+
import { ViewMetadata } from '../annotation/view';
|
|
8
|
+
import { HTML_VIEW_NAME } from '../annotation/html';
|
|
9
|
+
import { MediaType } from '@celljs/http';
|
|
10
|
+
|
|
11
|
+
@Component(View)
|
|
12
|
+
export class HtmlView implements View {
|
|
13
|
+
|
|
14
|
+
readonly contentType = MediaType.TEXT_HTML;
|
|
15
|
+
|
|
16
|
+
readonly priority = 500;
|
|
17
|
+
|
|
18
|
+
@Value('cell.mustache')
|
|
19
|
+
protected readonly options: any;
|
|
20
|
+
|
|
21
|
+
async render(model: any, { metadata }: ViewMetadata): Promise<void> {
|
|
22
|
+
const response = Context.getCurrent().response;
|
|
23
|
+
const { baseViewDir, cache } = this.options;
|
|
24
|
+
const template = await readFile(join(__dirname, baseViewDir, metadata!.file), { encoding: 'utf8' });
|
|
25
|
+
if (cache) {
|
|
26
|
+
parse(template);
|
|
27
|
+
}
|
|
28
|
+
response.body = render(template, model);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
support({ viewName, metadata }: ViewMetadata): Promise<boolean> {
|
|
32
|
+
return Promise.resolve(viewName === HTML_VIEW_NAME && metadata?.file?.endsWith('.mustache'));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Component, Value } from '@celljs/core';
|
|
2
|
+
import { JsonViewTemplateRenderer } from './view-protocol';
|
|
3
|
+
|
|
4
|
+
@Component(JsonViewTemplateRenderer)
|
|
5
|
+
export class JsonViewTemplateRendererImpl implements JsonViewTemplateRenderer {
|
|
6
|
+
|
|
7
|
+
@Value('cell.mvc.jsonView.template')
|
|
8
|
+
protected readonly jsonViewTemplate?: string;
|
|
9
|
+
|
|
10
|
+
async render(model?: any, error?: Error): Promise<string> {
|
|
11
|
+
if (this.jsonViewTemplate) {
|
|
12
|
+
return this.jsonViewTemplate
|
|
13
|
+
.replace('{{model}}', JSON.stringify(model))
|
|
14
|
+
.replace('{{error}}', error?.message ?? '')
|
|
15
|
+
.replace('{{success}}', error ? 'false' : 'true')
|
|
16
|
+
.replace('{{code}}', (error as any)?.code ?? (error as any)?.statusCode ?? '');
|
|
17
|
+
}
|
|
18
|
+
if (error) {
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
return JSON.stringify(model);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Autowired, Component } from '@celljs/core';
|
|
2
|
+
import { JsonViewTemplateRenderer, View } from './view-protocol';
|
|
3
|
+
import { Context } from '@celljs/web/lib/node';
|
|
4
|
+
import { ViewMetadata } from '../annotation/view';
|
|
5
|
+
import { JSON_VIEW_NAME } from '../annotation/json';
|
|
6
|
+
import { MediaType } from '@celljs/http';
|
|
7
|
+
|
|
8
|
+
@Component(View)
|
|
9
|
+
export class JsonView implements View {
|
|
10
|
+
|
|
11
|
+
readonly contentType = MediaType.APPLICATION_JSON_UTF8;
|
|
12
|
+
|
|
13
|
+
readonly priority = 500;
|
|
14
|
+
|
|
15
|
+
@Autowired(JsonViewTemplateRenderer)
|
|
16
|
+
protected readonly jsonViewTemplateRenderer: JsonViewTemplateRenderer;
|
|
17
|
+
|
|
18
|
+
async render(model: any, metadata: ViewMetadata): Promise<void> {
|
|
19
|
+
const response = Context.getCurrent().response;
|
|
20
|
+
response.body = await this.jsonViewTemplateRenderer.render(model);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
support({ viewName }: ViewMetadata): Promise<boolean> {
|
|
24
|
+
return Promise.resolve(viewName === JSON_VIEW_NAME);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Component } from '@celljs/core';
|
|
2
|
+
import { View } from './view-protocol';
|
|
3
|
+
import { Context } from '@celljs/web/lib/node';
|
|
4
|
+
import { ViewMetadata } from '../annotation/view';
|
|
5
|
+
import { TEXT_VIEW_NAME } from '../annotation/text';
|
|
6
|
+
import { MediaType } from '@celljs/http';
|
|
7
|
+
|
|
8
|
+
@Component(View)
|
|
9
|
+
export class TextView implements View {
|
|
10
|
+
|
|
11
|
+
readonly contentType = MediaType.TEXT_PLAIN;
|
|
12
|
+
|
|
13
|
+
readonly priority = 600;
|
|
14
|
+
|
|
15
|
+
async render(model: any, metadata: ViewMetadata): Promise<void> {
|
|
16
|
+
const response = Context.getCurrent().response;
|
|
17
|
+
response.body = model;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
support({ viewName }: ViewMetadata): Promise<boolean> {
|
|
21
|
+
return Promise.resolve(viewName === TEXT_VIEW_NAME);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ViewMetadata } from '../annotation/view';
|
|
2
|
+
|
|
3
|
+
export const View = Symbol('View');
|
|
4
|
+
export const JsonViewTemplateRenderer = Symbol('JsonViewTemplateRenderer');
|
|
5
|
+
|
|
6
|
+
export interface View {
|
|
7
|
+
readonly contentType: string;
|
|
8
|
+
render(model: any, metadata: ViewMetadata): Promise<void>;
|
|
9
|
+
support(metadata: ViewMetadata): Promise<boolean>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface JsonViewTemplateRenderer {
|
|
13
|
+
render(model?: any, error?: Error): Promise<string>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Component, Autowired, Prioritizeable } from '@celljs/core';
|
|
2
|
+
import { View } from './view-protocol';
|
|
3
|
+
|
|
4
|
+
@Component()
|
|
5
|
+
export class ViewProvider {
|
|
6
|
+
|
|
7
|
+
protected prioritized: View[];
|
|
8
|
+
|
|
9
|
+
constructor(
|
|
10
|
+
@Autowired(View)
|
|
11
|
+
protected readonly views: View[]
|
|
12
|
+
) { }
|
|
13
|
+
|
|
14
|
+
provide(): View[] {
|
|
15
|
+
if (!this.prioritized) {
|
|
16
|
+
this.prioritized = Prioritizeable.prioritizeAllSync(this.views).map(c => c.value);
|
|
17
|
+
}
|
|
18
|
+
return this.prioritized;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|