@tsed/platform-response-filter 6.88.1 → 6.92.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/lib/{decorators → cjs/decorators}/responseFilter.d.ts +0 -0
- package/lib/cjs/decorators/responseFilter.js +23 -0
- package/lib/cjs/decorators/responseFilter.js.map +1 -0
- package/lib/{domain → cjs/domain}/ResponseFiltersContainer.d.ts +0 -0
- package/lib/cjs/domain/ResponseFiltersContainer.js +16 -0
- package/lib/cjs/domain/ResponseFiltersContainer.js.map +1 -0
- package/lib/{errors → cjs/errors}/TemplateRenderError.d.ts +0 -0
- package/lib/cjs/errors/TemplateRenderError.js +23 -0
- package/lib/cjs/errors/TemplateRenderError.js.map +1 -0
- package/lib/{index.d.ts → cjs/index.d.ts} +0 -0
- package/lib/cjs/index.js +16 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/{interfaces → cjs/interfaces}/ResponseFilterMethods.d.ts +0 -0
- package/lib/cjs/interfaces/ResponseFilterMethods.js +3 -0
- package/lib/cjs/interfaces/ResponseFilterMethods.js.map +1 -0
- package/lib/{services → cjs/services}/ConverterService.d.ts +0 -0
- package/lib/cjs/services/ConverterService.js +54 -0
- package/lib/cjs/services/ConverterService.js.map +1 -0
- package/lib/{services → cjs/services}/PlatformResponseFilter.d.ts +0 -0
- package/lib/cjs/services/PlatformResponseFilter.js +88 -0
- package/lib/cjs/services/PlatformResponseFilter.js.map +1 -0
- package/lib/{utils → cjs/utils}/getContentType.d.ts +0 -0
- package/lib/cjs/utils/getContentType.js +28 -0
- package/lib/cjs/utils/getContentType.js.map +1 -0
- package/lib/{utils → cjs/utils}/renderView.d.ts +0 -0
- package/lib/cjs/utils/renderView.js +17 -0
- package/lib/cjs/utils/renderView.js.map +1 -0
- package/lib/esm/decorators/responseFilter.js +19 -0
- package/lib/esm/decorators/responseFilter.js.map +1 -0
- package/lib/esm/domain/ResponseFiltersContainer.js +12 -0
- package/lib/esm/domain/ResponseFiltersContainer.js.map +1 -0
- package/lib/esm/errors/TemplateRenderError.js +19 -0
- package/lib/esm/errors/TemplateRenderError.js.map +1 -0
- package/lib/esm/index.js +13 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/interfaces/ResponseFilterMethods.js +2 -0
- package/lib/esm/interfaces/ResponseFilterMethods.js.map +1 -0
- package/lib/esm/services/ConverterService.js +51 -0
- package/lib/esm/services/ConverterService.js.map +1 -0
- package/lib/esm/services/PlatformResponseFilter.js +85 -0
- package/lib/esm/services/PlatformResponseFilter.js.map +1 -0
- package/lib/esm/utils/getContentType.js +24 -0
- package/lib/esm/utils/getContentType.js.map +1 -0
- package/lib/esm/utils/renderView.js +13 -0
- package/lib/esm/utils/renderView.js.map +1 -0
- package/lib/types/decorators/responseFilter.d.ts +7 -0
- package/lib/types/domain/ResponseFiltersContainer.d.ts +14 -0
- package/lib/types/errors/TemplateRenderError.d.ts +14 -0
- package/lib/types/index.d.ts +8 -0
- package/lib/types/interfaces/ResponseFilterMethods.d.ts +15 -0
- package/lib/types/services/ConverterService.d.ts +30 -0
- package/lib/types/services/PlatformResponseFilter.d.ts +27 -0
- package/lib/types/utils/getContentType.d.ts +6 -0
- package/lib/types/utils/renderView.d.ts +2 -0
- package/package.json +22 -18
- package/tsconfig.compile.esm.json +23 -0
- package/lib/index.js +0 -275
- package/lib/index.js.map +0 -1
- package/lib/index.modern.js +0 -269
- package/lib/index.modern.js.map +0 -1
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ResponseFilter = void 0;
|
|
4
|
+
const di_1 = require("@tsed/di");
|
|
5
|
+
const ResponseFiltersContainer_1 = require("../domain/ResponseFiltersContainer");
|
|
6
|
+
/**
|
|
7
|
+
* Register a response filter service.
|
|
8
|
+
* @param contentTypes
|
|
9
|
+
* @decorator
|
|
10
|
+
*/
|
|
11
|
+
function ResponseFilter(...contentTypes) {
|
|
12
|
+
return (target) => {
|
|
13
|
+
contentTypes.forEach((contentType) => {
|
|
14
|
+
(0, ResponseFiltersContainer_1.registerResponseFilter)(contentType, target);
|
|
15
|
+
});
|
|
16
|
+
(0, di_1.registerProvider)({
|
|
17
|
+
provide: target,
|
|
18
|
+
useClass: target
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
exports.ResponseFilter = ResponseFilter;
|
|
23
|
+
//# sourceMappingURL=responseFilter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responseFilter.js","sourceRoot":"","sources":["../../../src/decorators/responseFilter.ts"],"names":[],"mappings":";;;AACA,iCAA0C;AAC1C,iFAA6F;AAE7F;;;;GAIG;AACH,SAAgB,cAAc,CAAC,GAAG,YAAiC;IACjE,OAAO,CAAU,MAAS,EAAY,EAAE;QACtC,YAAY,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE;YACnC,IAAA,iDAAsB,EAAC,WAAW,EAAE,MAAa,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QACH,IAAA,qBAAgB,EAAC;YACf,OAAO,EAAE,MAAM;YACf,QAAQ,EAAG,MAA+B;SAC3C,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAVD,wCAUC","sourcesContent":["import {Type} from \"@tsed/core\";\nimport {registerProvider} from \"@tsed/di\";\nimport {registerResponseFilter, ResponseFilterKey} from \"../domain/ResponseFiltersContainer\";\n\n/**\n * Register a response filter service.\n * @param contentTypes\n * @decorator\n */\nexport function ResponseFilter(...contentTypes: ResponseFilterKey[]): ClassDecorator {\n return <T = any>(target: T): void | T => {\n contentTypes.forEach((contentType) => {\n registerResponseFilter(contentType, target as any);\n });\n registerProvider({\n provide: target,\n useClass: (target as unknown) as Type<any>\n });\n };\n}\n"]}
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerResponseFilter = exports.ResponseFiltersContainer = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @ignore
|
|
6
|
+
*/
|
|
7
|
+
// tslint:disable-next-line:variable-name
|
|
8
|
+
exports.ResponseFiltersContainer = new Map();
|
|
9
|
+
/**
|
|
10
|
+
* @ignore
|
|
11
|
+
*/
|
|
12
|
+
function registerResponseFilter(type, token) {
|
|
13
|
+
exports.ResponseFiltersContainer.set(type, token);
|
|
14
|
+
}
|
|
15
|
+
exports.registerResponseFilter = registerResponseFilter;
|
|
16
|
+
//# sourceMappingURL=ResponseFiltersContainer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseFiltersContainer.js","sourceRoot":"","sources":["../../../src/domain/ResponseFiltersContainer.ts"],"names":[],"mappings":";;;AAMA;;GAEG;AACH,yCAAyC;AAC5B,QAAA,wBAAwB,GAAG,IAAI,GAAG,EAAkD,CAAC;AAClG;;GAEG;AACH,SAAgB,sBAAsB,CAAC,IAAuB,EAAE,KAAkC;IAChG,gCAAwB,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC5C,CAAC;AAFD,wDAEC","sourcesContent":["import {Type} from \"@tsed/core\";\nimport {ResponseFilterMethods} from \"../interfaces/ResponseFilterMethods\";\n/**\n * @ignore\n */\nexport type ResponseFilterKey = \"*/*\" | \"application/json\" | \"text/html\" | \"plain/text\" | string;\n/**\n * @ignore\n */\n// tslint:disable-next-line:variable-name\nexport const ResponseFiltersContainer = new Map<ResponseFilterKey, Type<ResponseFilterMethods>>();\n/**\n * @ignore\n */\nexport function registerResponseFilter(type: ResponseFilterKey, token: Type<ResponseFilterMethods>) {\n ResponseFiltersContainer.set(type, token);\n}\n"]}
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TemplateRenderError = void 0;
|
|
4
|
+
const core_1 = require("@tsed/core");
|
|
5
|
+
const exceptions_1 = require("@tsed/exceptions");
|
|
6
|
+
/**
|
|
7
|
+
* @private
|
|
8
|
+
*/
|
|
9
|
+
class TemplateRenderError extends exceptions_1.InternalServerError {
|
|
10
|
+
constructor(target, method, err) {
|
|
11
|
+
super(TemplateRenderError.buildMessage(target, method, err));
|
|
12
|
+
this.name = "TEMPLATE_RENDER_ERROR";
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
static buildMessage(target, method, err) {
|
|
19
|
+
return `Template rendering error: ${(0, core_1.nameOf)(target)}.${String(method)}()\n` + err;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.TemplateRenderError = TemplateRenderError;
|
|
23
|
+
//# sourceMappingURL=TemplateRenderError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TemplateRenderError.js","sourceRoot":"","sources":["../../../src/errors/TemplateRenderError.ts"],"names":[],"mappings":";;;AAAA,qCAAwC;AACxC,iDAAqD;AAErD;;GAEG;AACH,MAAa,mBAAoB,SAAQ,gCAAmB;IAG1D,YAAY,MAA0B,EAAE,MAAuB,EAAE,GAAU;QACzE,KAAK,CAAC,mBAAmB,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;QAH/D,SAAI,GAAG,uBAAuB,CAAC;IAI/B,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,MAA0B,EAAE,MAAuB,EAAE,GAAU;QACjF,OAAO,6BAA6B,IAAA,aAAM,EAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC;IACnF,CAAC;CACF;AAdD,kDAcC","sourcesContent":["import {nameOf, Type} from \"@tsed/core\";\nimport {InternalServerError} from \"@tsed/exceptions\";\n\n/**\n * @private\n */\nexport class TemplateRenderError extends InternalServerError {\n name = \"TEMPLATE_RENDER_ERROR\";\n\n constructor(target: Type<any> | string, method: string | symbol, err: Error) {\n super(TemplateRenderError.buildMessage(target, method, err));\n }\n\n /**\n *\n * @returns {string}\n */\n static buildMessage(target: Type<any> | string, method: string | symbol, err: Error) {\n return `Template rendering error: ${nameOf(target)}.${String(method)}()\\n` + err;\n }\n}\n"]}
|
|
File without changes
|
package/lib/cjs/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
// decorators
|
|
5
|
+
(0, tslib_1.__exportStar)(require("./decorators/responseFilter"), exports);
|
|
6
|
+
// domain
|
|
7
|
+
(0, tslib_1.__exportStar)(require("./domain/ResponseFiltersContainer"), exports);
|
|
8
|
+
(0, tslib_1.__exportStar)(require("./errors/TemplateRenderError"), exports);
|
|
9
|
+
// interfaces
|
|
10
|
+
(0, tslib_1.__exportStar)(require("./interfaces/ResponseFilterMethods"), exports);
|
|
11
|
+
// services
|
|
12
|
+
(0, tslib_1.__exportStar)(require("./services/PlatformResponseFilter"), exports);
|
|
13
|
+
(0, tslib_1.__exportStar)(require("./services/ConverterService"), exports);
|
|
14
|
+
(0, tslib_1.__exportStar)(require("./utils/getContentType"), exports);
|
|
15
|
+
(0, tslib_1.__exportStar)(require("./utils/renderView"), exports);
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,aAAa;AACb,2EAA4C;AAE5C,SAAS;AACT,iFAAkD;AAClD,4EAA6C;AAE7C,aAAa;AACb,kFAAmD;AAEnD,WAAW;AACX,iFAAkD;AAClD,2EAA4C;AAE5C,sEAAuC;AACvC,kEAAmC","sourcesContent":["// decorators\nexport * from \"./decorators/responseFilter\";\n\n// domain\nexport * from \"./domain/ResponseFiltersContainer\";\nexport * from \"./errors/TemplateRenderError\";\n\n// interfaces\nexport * from \"./interfaces/ResponseFilterMethods\";\n\n// services\nexport * from \"./services/PlatformResponseFilter\";\nexport * from \"./services/ConverterService\";\n\nexport * from \"./utils/getContentType\";\nexport * from \"./utils/renderView\";\n"]}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseFilterMethods.js","sourceRoot":"","sources":["../../../src/interfaces/ResponseFilterMethods.ts"],"names":[],"mappings":"","sourcesContent":["import {Type} from \"@tsed/core\";\nimport type {BaseContext} from \"@tsed/di\";\n\ndeclare global {\n namespace TsED {\n interface Configuration {\n /**\n * A list of response filters must be called before returning a response to the consumer. See more on [Response filters](/docs/response-filter.md).\n */\n responseFilters: Type<ResponseFilterMethods>[];\n }\n }\n}\n\nexport interface ResponseFilterMethods<T = unknown> {\n transform(data: T, ctx: BaseContext): any;\n}\n"]}
|
|
File without changes
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConverterService = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const di_1 = require("@tsed/di");
|
|
6
|
+
const json_mapper_1 = require("@tsed/json-mapper");
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated Since 2021-10-03. Use serialize/deserialize functions from @tsed/json-mapper instead
|
|
9
|
+
*/
|
|
10
|
+
let ConverterService = class ConverterService {
|
|
11
|
+
constructor(injectorService, configuration) {
|
|
12
|
+
this.injectorService = injectorService;
|
|
13
|
+
this._additionalProperties = configuration.get("converter.additionalProperties");
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Convert instance to plainObject.
|
|
17
|
+
*
|
|
18
|
+
* @param obj
|
|
19
|
+
* @param options
|
|
20
|
+
*/
|
|
21
|
+
serialize(obj, options = {}) {
|
|
22
|
+
return (0, json_mapper_1.serialize)(obj, {
|
|
23
|
+
useAlias: true,
|
|
24
|
+
additionalProperties: this._additionalProperties === "accept",
|
|
25
|
+
...options
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Convert a plainObject to targetType.
|
|
30
|
+
*
|
|
31
|
+
* ### Options
|
|
32
|
+
*
|
|
33
|
+
* - `ignoreCallback`: callback called for each object which will be deserialized. The callback can return a boolean to avoid the default converter behavior.
|
|
34
|
+
* - `checkRequiredValue`: Disable the required check condition.
|
|
35
|
+
*
|
|
36
|
+
* @param obj Object source that will be deserialized
|
|
37
|
+
* @param options Mapping options
|
|
38
|
+
* @returns {any}
|
|
39
|
+
*/
|
|
40
|
+
deserialize(obj, options = {}) {
|
|
41
|
+
return (0, json_mapper_1.deserialize)(obj, {
|
|
42
|
+
useAlias: true,
|
|
43
|
+
additionalProperties: this._additionalProperties === "accept",
|
|
44
|
+
...options
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
ConverterService = (0, tslib_1.__decorate)([
|
|
49
|
+
(0, di_1.Injectable)(),
|
|
50
|
+
(0, tslib_1.__param)(1, (0, di_1.Configuration)()),
|
|
51
|
+
(0, tslib_1.__metadata)("design:paramtypes", [di_1.InjectorService, Object])
|
|
52
|
+
], ConverterService);
|
|
53
|
+
exports.ConverterService = ConverterService;
|
|
54
|
+
//# sourceMappingURL=ConverterService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConverterService.js","sourceRoot":"","sources":["../../../src/services/ConverterService.ts"],"names":[],"mappings":";;;;AAAA,iCAAoE;AACpE,mDAAyG;AAEzG;;GAEG;AAEH,IAAa,gBAAgB,GAA7B,MAAa,gBAAgB;IAG3B,YAAoB,eAAgC,EAAmB,aAA4B;QAA/E,oBAAe,GAAf,eAAe,CAAiB;QAClD,IAAI,CAAC,qBAAqB,GAAG,aAAa,CAAC,GAAG,CAAS,gCAAgC,CAAC,CAAC;IAC3F,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,GAAQ,EAAE,UAAiC,EAAE;QACrD,OAAO,IAAA,uBAAS,EAAC,GAAG,EAAE;YACpB,QAAQ,EAAE,IAAI;YACd,oBAAoB,EAAE,IAAI,CAAC,qBAAqB,KAAK,QAAQ;YAC7D,GAAG,OAAO;SACX,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,GAAQ,EAAE,UAAmC,EAAE;QACzD,OAAO,IAAA,yBAAW,EAAC,GAAG,EAAE;YACtB,QAAQ,EAAE,IAAI;YACd,oBAAoB,EAAE,IAAI,CAAC,qBAAqB,KAAK,QAAQ;YAC7D,GAAG,OAAO;SACX,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAxCY,gBAAgB;IAD5B,IAAA,eAAU,GAAE;IAI4C,wBAAA,IAAA,kBAAa,GAAE,CAAA;kDAAjC,oBAAe;GAHzC,gBAAgB,CAwC5B;AAxCY,4CAAgB","sourcesContent":["import {Configuration, Injectable, InjectorService} from \"@tsed/di\";\nimport {deserialize, JsonDeserializerOptions, JsonSerializerOptions, serialize} from \"@tsed/json-mapper\";\n\n/**\n * @deprecated Since 2021-10-03. Use serialize/deserialize functions from @tsed/json-mapper instead\n */\n@Injectable()\nexport class ConverterService {\n private readonly _additionalProperties: string;\n\n constructor(private injectorService: InjectorService, @Configuration() configuration: Configuration) {\n this._additionalProperties = configuration.get<string>(\"converter.additionalProperties\");\n }\n\n /**\n * Convert instance to plainObject.\n *\n * @param obj\n * @param options\n */\n serialize(obj: any, options: JsonSerializerOptions = {}): any {\n return serialize(obj, {\n useAlias: true,\n additionalProperties: this._additionalProperties === \"accept\",\n ...options\n });\n }\n\n /**\n * Convert a plainObject to targetType.\n *\n * ### Options\n *\n * - `ignoreCallback`: callback called for each object which will be deserialized. The callback can return a boolean to avoid the default converter behavior.\n * - `checkRequiredValue`: Disable the required check condition.\n *\n * @param obj Object source that will be deserialized\n * @param options Mapping options\n * @returns {any}\n */\n deserialize(obj: any, options: JsonDeserializerOptions = {}): any {\n return deserialize(obj, {\n useAlias: true,\n additionalProperties: this._additionalProperties === \"accept\",\n ...options\n });\n }\n}\n"]}
|
|
File without changes
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PlatformResponseFilter = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const core_1 = require("@tsed/core");
|
|
6
|
+
const di_1 = require("@tsed/di");
|
|
7
|
+
const ResponseFiltersContainer_1 = require("../domain/ResponseFiltersContainer");
|
|
8
|
+
const getContentType_1 = require("../utils/getContentType");
|
|
9
|
+
const ConverterService_1 = require("./ConverterService");
|
|
10
|
+
const renderView_1 = require("../utils/renderView");
|
|
11
|
+
/**
|
|
12
|
+
* @platform
|
|
13
|
+
*/
|
|
14
|
+
let PlatformResponseFilter = class PlatformResponseFilter {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.types = new Map();
|
|
17
|
+
}
|
|
18
|
+
get contentTypes() {
|
|
19
|
+
return [...this.types.keys()];
|
|
20
|
+
}
|
|
21
|
+
$onInit() {
|
|
22
|
+
ResponseFiltersContainer_1.ResponseFiltersContainer.forEach((token, type) => {
|
|
23
|
+
if (this.responseFilters.includes(token)) {
|
|
24
|
+
this.types.set(type, this.injector.get(token));
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
getBestContentType(data, ctx) {
|
|
29
|
+
const contentType = (0, getContentType_1.getContentType)(data, ctx);
|
|
30
|
+
if (ctx.request.get("Accept")) {
|
|
31
|
+
const bestContentType = ctx.request.accepts([contentType].concat(this.contentTypes).filter(Boolean));
|
|
32
|
+
if (bestContentType) {
|
|
33
|
+
return [].concat(bestContentType).filter((type) => type !== "*/*")[0];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return contentType;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Call filters to transform data
|
|
40
|
+
* @param data
|
|
41
|
+
* @param ctx
|
|
42
|
+
*/
|
|
43
|
+
async transform(data, ctx) {
|
|
44
|
+
const { response } = ctx;
|
|
45
|
+
const bestContentType = this.getBestContentType(data, ctx);
|
|
46
|
+
bestContentType && response.contentType(bestContentType);
|
|
47
|
+
if (this.types.has(bestContentType)) {
|
|
48
|
+
return this.types.get(bestContentType).transform(data, ctx);
|
|
49
|
+
}
|
|
50
|
+
if (this.types.has(getContentType_1.ANY_CONTENT_TYPE)) {
|
|
51
|
+
return this.types.get(getContentType_1.ANY_CONTENT_TYPE).transform(data, ctx);
|
|
52
|
+
}
|
|
53
|
+
return data;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Serialize data before calling filters
|
|
57
|
+
* @param data
|
|
58
|
+
* @param ctx
|
|
59
|
+
*/
|
|
60
|
+
async serialize(data, ctx) {
|
|
61
|
+
const { response, endpoint } = ctx;
|
|
62
|
+
if (endpoint) {
|
|
63
|
+
if (endpoint.view) {
|
|
64
|
+
data = await (0, renderView_1.renderView)(data, ctx);
|
|
65
|
+
}
|
|
66
|
+
else if ((0, core_1.isSerializable)(data)) {
|
|
67
|
+
data = this.injector.get(ConverterService_1.ConverterService).serialize(data, {
|
|
68
|
+
...endpoint.getResponseOptions(response.statusCode),
|
|
69
|
+
endpoint: true
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return data;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
(0, tslib_1.__decorate)([
|
|
77
|
+
(0, di_1.Inject)(),
|
|
78
|
+
(0, tslib_1.__metadata)("design:type", di_1.InjectorService)
|
|
79
|
+
], PlatformResponseFilter.prototype, "injector", void 0);
|
|
80
|
+
(0, tslib_1.__decorate)([
|
|
81
|
+
(0, di_1.Constant)("responseFilters", []),
|
|
82
|
+
(0, tslib_1.__metadata)("design:type", Array)
|
|
83
|
+
], PlatformResponseFilter.prototype, "responseFilters", void 0);
|
|
84
|
+
PlatformResponseFilter = (0, tslib_1.__decorate)([
|
|
85
|
+
(0, di_1.Injectable)()
|
|
86
|
+
], PlatformResponseFilter);
|
|
87
|
+
exports.PlatformResponseFilter = PlatformResponseFilter;
|
|
88
|
+
//# sourceMappingURL=PlatformResponseFilter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlatformResponseFilter.js","sourceRoot":"","sources":["../../../src/services/PlatformResponseFilter.ts"],"names":[],"mappings":"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","sourcesContent":["import {isSerializable, Type} from \"@tsed/core\";\nimport {BaseContext, Constant, Inject, Injectable, InjectorService} from \"@tsed/di\";\nimport {ResponseFilterKey, ResponseFiltersContainer} from \"../domain/ResponseFiltersContainer\";\nimport {ResponseFilterMethods} from \"../interfaces/ResponseFilterMethods\";\nimport {ANY_CONTENT_TYPE, getContentType} from \"../utils/getContentType\";\nimport {ConverterService} from \"./ConverterService\";\nimport {renderView} from \"../utils/renderView\";\n\n/**\n * @platform\n */\n@Injectable()\nexport class PlatformResponseFilter {\n types: Map<ResponseFilterKey, ResponseFilterMethods> = new Map();\n\n @Inject()\n injector: InjectorService;\n\n @Constant(\"responseFilters\", [])\n protected responseFilters: Type<ResponseFilterMethods>[];\n\n get contentTypes(): ResponseFilterKey[] {\n return [...this.types.keys()];\n }\n\n $onInit() {\n ResponseFiltersContainer.forEach((token, type) => {\n if (this.responseFilters.includes(token)) {\n this.types.set(type, this.injector.get(token)!);\n }\n });\n }\n\n getBestContentType(data: any, ctx: BaseContext) {\n const contentType = getContentType(data, ctx);\n\n if (ctx.request.get(\"Accept\")) {\n const bestContentType = ctx.request.accepts([contentType].concat(this.contentTypes).filter(Boolean));\n\n if (bestContentType) {\n return [].concat(bestContentType as any).filter((type) => type !== \"*/*\")[0];\n }\n }\n\n return contentType;\n }\n /**\n * Call filters to transform data\n * @param data\n * @param ctx\n */\n async transform(data: unknown, ctx: BaseContext) {\n const {response} = ctx;\n const bestContentType = this.getBestContentType(data, ctx);\n\n bestContentType && response.contentType(bestContentType);\n\n if (this.types.has(bestContentType)) {\n return this.types.get(bestContentType)!.transform(data, ctx);\n }\n\n if (this.types.has(ANY_CONTENT_TYPE)) {\n return this.types.get(ANY_CONTENT_TYPE)!.transform(data, ctx);\n }\n\n return data;\n }\n /**\n * Serialize data before calling filters\n * @param data\n * @param ctx\n */\n async serialize(data: unknown, ctx: BaseContext) {\n const {response, endpoint} = ctx;\n\n if (endpoint) {\n if (endpoint.view) {\n data = await renderView(data, ctx);\n } else if (isSerializable(data)) {\n data = this.injector.get<ConverterService>(ConverterService)!.serialize(data, {\n ...endpoint.getResponseOptions(response.statusCode),\n endpoint: true\n });\n }\n }\n\n return data;\n }\n}\n"]}
|
|
File without changes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getContentType = exports.ANY_CONTENT_TYPE = void 0;
|
|
4
|
+
const core_1 = require("@tsed/core");
|
|
5
|
+
exports.ANY_CONTENT_TYPE = "*/*";
|
|
6
|
+
/**
|
|
7
|
+
* @ignore
|
|
8
|
+
*/
|
|
9
|
+
function getContentType(data, ctx) {
|
|
10
|
+
const { endpoint, response } = ctx;
|
|
11
|
+
const { operation } = endpoint;
|
|
12
|
+
const contentType = response.getContentType() || operation.getContentTypeOf(response.statusCode) || "";
|
|
13
|
+
if (contentType && contentType !== exports.ANY_CONTENT_TYPE) {
|
|
14
|
+
if (contentType === "application/json") {
|
|
15
|
+
if ((0, core_1.isObject)(data)) {
|
|
16
|
+
return contentType;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
return contentType;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (typeof data === "string" && endpoint.view) {
|
|
24
|
+
return "text/html";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.getContentType = getContentType;
|
|
28
|
+
//# sourceMappingURL=getContentType.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getContentType.js","sourceRoot":"","sources":["../../../src/utils/getContentType.ts"],"names":[],"mappings":";;;AAAA,qCAAoC;AAEvB,QAAA,gBAAgB,GAAG,KAAK,CAAC;AACtC;;GAEG;AACH,SAAgB,cAAc,CAAC,IAAS,EAAE,GAAgB;IACxD,MAAM,EAAC,QAAQ,EAAE,QAAQ,EAAC,GAAG,GAAG,CAAC;IACjC,MAAM,EAAC,SAAS,EAAC,GAAG,QAAQ,CAAC;IAE7B,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,EAAE,IAAI,SAAS,CAAC,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAEvG,IAAI,WAAW,IAAI,WAAW,KAAK,wBAAgB,EAAE;QACnD,IAAI,WAAW,KAAK,kBAAkB,EAAE;YACtC,IAAI,IAAA,eAAQ,EAAC,IAAI,CAAC,EAAE;gBAClB,OAAO,WAAW,CAAC;aACpB;SACF;aAAM;YACL,OAAO,WAAW,CAAC;SACpB;KACF;IAED,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE;QAC7C,OAAO,WAAW,CAAC;KACpB;AACH,CAAC;AAnBD,wCAmBC","sourcesContent":["import {isObject} from \"@tsed/core\";\nimport type {BaseContext} from \"@tsed/di\";\nexport const ANY_CONTENT_TYPE = \"*/*\";\n/**\n * @ignore\n */\nexport function getContentType(data: any, ctx: BaseContext) {\n const {endpoint, response} = ctx;\n const {operation} = endpoint;\n\n const contentType = response.getContentType() || operation.getContentTypeOf(response.statusCode) || \"\";\n\n if (contentType && contentType !== ANY_CONTENT_TYPE) {\n if (contentType === \"application/json\") {\n if (isObject(data)) {\n return contentType;\n }\n } else {\n return contentType;\n }\n }\n\n if (typeof data === \"string\" && endpoint.view) {\n return \"text/html\";\n }\n}\n"]}
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderView = void 0;
|
|
4
|
+
const TemplateRenderError_1 = require("../errors/TemplateRenderError");
|
|
5
|
+
async function renderView(data, $ctx) {
|
|
6
|
+
const { response, endpoint } = $ctx;
|
|
7
|
+
try {
|
|
8
|
+
const { data } = $ctx;
|
|
9
|
+
const { path, options } = endpoint.view;
|
|
10
|
+
return await response.render(path, { ...options, ...data, $ctx });
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
throw new TemplateRenderError_1.TemplateRenderError(endpoint.targetName, endpoint.propertyKey, err);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.renderView = renderView;
|
|
17
|
+
//# sourceMappingURL=renderView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderView.js","sourceRoot":"","sources":["../../../src/utils/renderView.ts"],"names":[],"mappings":";;;AACA,uEAAkE;AAE3D,KAAK,UAAU,UAAU,CAAC,IAAS,EAAE,IAAiB;IAC3D,MAAM,EAAC,QAAQ,EAAE,QAAQ,EAAC,GAAG,IAAI,CAAC;IAClC,IAAI;QACF,MAAM,EAAC,IAAI,EAAC,GAAG,IAAI,CAAC;QACpB,MAAM,EAAC,IAAI,EAAE,OAAO,EAAC,GAAG,QAAQ,CAAC,IAAI,CAAC;QAEtC,OAAO,MAAM,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAC,GAAG,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;KACjE;IAAC,OAAO,GAAG,EAAE;QACZ,MAAM,IAAI,yCAAmB,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;KAC/E;AACH,CAAC;AAVD,gCAUC","sourcesContent":["import {BaseContext} from \"@tsed/di\";\nimport {TemplateRenderError} from \"../errors/TemplateRenderError\";\n\nexport async function renderView(data: any, $ctx: BaseContext) {\n const {response, endpoint} = $ctx;\n try {\n const {data} = $ctx;\n const {path, options} = endpoint.view;\n\n return await response.render(path, {...options, ...data, $ctx});\n } catch (err) {\n throw new TemplateRenderError(endpoint.targetName, endpoint.propertyKey, err);\n }\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { registerProvider } from "@tsed/di";
|
|
2
|
+
import { registerResponseFilter } from "../domain/ResponseFiltersContainer";
|
|
3
|
+
/**
|
|
4
|
+
* Register a response filter service.
|
|
5
|
+
* @param contentTypes
|
|
6
|
+
* @decorator
|
|
7
|
+
*/
|
|
8
|
+
export function ResponseFilter(...contentTypes) {
|
|
9
|
+
return (target) => {
|
|
10
|
+
contentTypes.forEach((contentType) => {
|
|
11
|
+
registerResponseFilter(contentType, target);
|
|
12
|
+
});
|
|
13
|
+
registerProvider({
|
|
14
|
+
provide: target,
|
|
15
|
+
useClass: target
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=responseFilter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responseFilter.js","sourceRoot":"","sources":["../../../src/decorators/responseFilter.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,gBAAgB,EAAC,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAC,sBAAsB,EAAoB,MAAM,oCAAoC,CAAC;AAE7F;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,GAAG,YAAiC;IACjE,OAAO,CAAU,MAAS,EAAY,EAAE;QACtC,YAAY,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE;YACnC,sBAAsB,CAAC,WAAW,EAAE,MAAa,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QACH,gBAAgB,CAAC;YACf,OAAO,EAAE,MAAM;YACf,QAAQ,EAAG,MAA+B;SAC3C,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import {Type} from \"@tsed/core\";\nimport {registerProvider} from \"@tsed/di\";\nimport {registerResponseFilter, ResponseFilterKey} from \"../domain/ResponseFiltersContainer\";\n\n/**\n * Register a response filter service.\n * @param contentTypes\n * @decorator\n */\nexport function ResponseFilter(...contentTypes: ResponseFilterKey[]): ClassDecorator {\n return <T = any>(target: T): void | T => {\n contentTypes.forEach((contentType) => {\n registerResponseFilter(contentType, target as any);\n });\n registerProvider({\n provide: target,\n useClass: (target as unknown) as Type<any>\n });\n };\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ignore
|
|
3
|
+
*/
|
|
4
|
+
// tslint:disable-next-line:variable-name
|
|
5
|
+
export const ResponseFiltersContainer = new Map();
|
|
6
|
+
/**
|
|
7
|
+
* @ignore
|
|
8
|
+
*/
|
|
9
|
+
export function registerResponseFilter(type, token) {
|
|
10
|
+
ResponseFiltersContainer.set(type, token);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=ResponseFiltersContainer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseFiltersContainer.js","sourceRoot":"","sources":["../../../src/domain/ResponseFiltersContainer.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,yCAAyC;AACzC,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,GAAG,EAAkD,CAAC;AAClG;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAuB,EAAE,KAAkC;IAChG,wBAAwB,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["import {Type} from \"@tsed/core\";\nimport {ResponseFilterMethods} from \"../interfaces/ResponseFilterMethods\";\n/**\n * @ignore\n */\nexport type ResponseFilterKey = \"*/*\" | \"application/json\" | \"text/html\" | \"plain/text\" | string;\n/**\n * @ignore\n */\n// tslint:disable-next-line:variable-name\nexport const ResponseFiltersContainer = new Map<ResponseFilterKey, Type<ResponseFilterMethods>>();\n/**\n * @ignore\n */\nexport function registerResponseFilter(type: ResponseFilterKey, token: Type<ResponseFilterMethods>) {\n ResponseFiltersContainer.set(type, token);\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { nameOf } from "@tsed/core";
|
|
2
|
+
import { InternalServerError } from "@tsed/exceptions";
|
|
3
|
+
/**
|
|
4
|
+
* @private
|
|
5
|
+
*/
|
|
6
|
+
export class TemplateRenderError extends InternalServerError {
|
|
7
|
+
constructor(target, method, err) {
|
|
8
|
+
super(TemplateRenderError.buildMessage(target, method, err));
|
|
9
|
+
this.name = "TEMPLATE_RENDER_ERROR";
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
static buildMessage(target, method, err) {
|
|
16
|
+
return `Template rendering error: ${nameOf(target)}.${String(method)}()\n` + err;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=TemplateRenderError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TemplateRenderError.js","sourceRoot":"","sources":["../../../src/errors/TemplateRenderError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAO,MAAM,YAAY,CAAC;AACxC,OAAO,EAAC,mBAAmB,EAAC,MAAM,kBAAkB,CAAC;AAErD;;GAEG;AACH,MAAM,OAAO,mBAAoB,SAAQ,mBAAmB;IAG1D,YAAY,MAA0B,EAAE,MAAuB,EAAE,GAAU;QACzE,KAAK,CAAC,mBAAmB,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;QAH/D,SAAI,GAAG,uBAAuB,CAAC;IAI/B,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,MAA0B,EAAE,MAAuB,EAAE,GAAU;QACjF,OAAO,6BAA6B,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC;IACnF,CAAC;CACF","sourcesContent":["import {nameOf, Type} from \"@tsed/core\";\nimport {InternalServerError} from \"@tsed/exceptions\";\n\n/**\n * @private\n */\nexport class TemplateRenderError extends InternalServerError {\n name = \"TEMPLATE_RENDER_ERROR\";\n\n constructor(target: Type<any> | string, method: string | symbol, err: Error) {\n super(TemplateRenderError.buildMessage(target, method, err));\n }\n\n /**\n *\n * @returns {string}\n */\n static buildMessage(target: Type<any> | string, method: string | symbol, err: Error) {\n return `Template rendering error: ${nameOf(target)}.${String(method)}()\\n` + err;\n }\n}\n"]}
|
package/lib/esm/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// decorators
|
|
2
|
+
export * from "./decorators/responseFilter";
|
|
3
|
+
// domain
|
|
4
|
+
export * from "./domain/ResponseFiltersContainer";
|
|
5
|
+
export * from "./errors/TemplateRenderError";
|
|
6
|
+
// interfaces
|
|
7
|
+
export * from "./interfaces/ResponseFilterMethods";
|
|
8
|
+
// services
|
|
9
|
+
export * from "./services/PlatformResponseFilter";
|
|
10
|
+
export * from "./services/ConverterService";
|
|
11
|
+
export * from "./utils/getContentType";
|
|
12
|
+
export * from "./utils/renderView";
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,cAAc,6BAA6B,CAAC;AAE5C,SAAS;AACT,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAE7C,aAAa;AACb,cAAc,oCAAoC,CAAC;AAEnD,WAAW;AACX,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAE5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC","sourcesContent":["// decorators\nexport * from \"./decorators/responseFilter\";\n\n// domain\nexport * from \"./domain/ResponseFiltersContainer\";\nexport * from \"./errors/TemplateRenderError\";\n\n// interfaces\nexport * from \"./interfaces/ResponseFilterMethods\";\n\n// services\nexport * from \"./services/PlatformResponseFilter\";\nexport * from \"./services/ConverterService\";\n\nexport * from \"./utils/getContentType\";\nexport * from \"./utils/renderView\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseFilterMethods.js","sourceRoot":"","sources":["../../../src/interfaces/ResponseFilterMethods.ts"],"names":[],"mappings":"","sourcesContent":["import {Type} from \"@tsed/core\";\nimport type {BaseContext} from \"@tsed/di\";\n\ndeclare global {\n namespace TsED {\n interface Configuration {\n /**\n * A list of response filters must be called before returning a response to the consumer. See more on [Response filters](/docs/response-filter.md).\n */\n responseFilters: Type<ResponseFilterMethods>[];\n }\n }\n}\n\nexport interface ResponseFilterMethods<T = unknown> {\n transform(data: T, ctx: BaseContext): any;\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { __decorate, __metadata, __param } from "tslib";
|
|
2
|
+
import { Configuration, Injectable, InjectorService } from "@tsed/di";
|
|
3
|
+
import { deserialize, serialize } from "@tsed/json-mapper";
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated Since 2021-10-03. Use serialize/deserialize functions from @tsed/json-mapper instead
|
|
6
|
+
*/
|
|
7
|
+
let ConverterService = class ConverterService {
|
|
8
|
+
constructor(injectorService, configuration) {
|
|
9
|
+
this.injectorService = injectorService;
|
|
10
|
+
this._additionalProperties = configuration.get("converter.additionalProperties");
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Convert instance to plainObject.
|
|
14
|
+
*
|
|
15
|
+
* @param obj
|
|
16
|
+
* @param options
|
|
17
|
+
*/
|
|
18
|
+
serialize(obj, options = {}) {
|
|
19
|
+
return serialize(obj, {
|
|
20
|
+
useAlias: true,
|
|
21
|
+
additionalProperties: this._additionalProperties === "accept",
|
|
22
|
+
...options
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Convert a plainObject to targetType.
|
|
27
|
+
*
|
|
28
|
+
* ### Options
|
|
29
|
+
*
|
|
30
|
+
* - `ignoreCallback`: callback called for each object which will be deserialized. The callback can return a boolean to avoid the default converter behavior.
|
|
31
|
+
* - `checkRequiredValue`: Disable the required check condition.
|
|
32
|
+
*
|
|
33
|
+
* @param obj Object source that will be deserialized
|
|
34
|
+
* @param options Mapping options
|
|
35
|
+
* @returns {any}
|
|
36
|
+
*/
|
|
37
|
+
deserialize(obj, options = {}) {
|
|
38
|
+
return deserialize(obj, {
|
|
39
|
+
useAlias: true,
|
|
40
|
+
additionalProperties: this._additionalProperties === "accept",
|
|
41
|
+
...options
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
ConverterService = __decorate([
|
|
46
|
+
Injectable(),
|
|
47
|
+
__param(1, Configuration()),
|
|
48
|
+
__metadata("design:paramtypes", [InjectorService, Object])
|
|
49
|
+
], ConverterService);
|
|
50
|
+
export { ConverterService };
|
|
51
|
+
//# sourceMappingURL=ConverterService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConverterService.js","sourceRoot":"","sources":["../../../src/services/ConverterService.ts"],"names":[],"mappings":";AAAA,OAAO,EAAC,aAAa,EAAE,UAAU,EAAE,eAAe,EAAC,MAAM,UAAU,CAAC;AACpE,OAAO,EAAC,WAAW,EAAkD,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAEzG;;GAEG;AAEH,IAAa,gBAAgB,GAA7B,MAAa,gBAAgB;IAG3B,YAAoB,eAAgC,EAAmB,aAA4B;QAA/E,oBAAe,GAAf,eAAe,CAAiB;QAClD,IAAI,CAAC,qBAAqB,GAAG,aAAa,CAAC,GAAG,CAAS,gCAAgC,CAAC,CAAC;IAC3F,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,GAAQ,EAAE,UAAiC,EAAE;QACrD,OAAO,SAAS,CAAC,GAAG,EAAE;YACpB,QAAQ,EAAE,IAAI;YACd,oBAAoB,EAAE,IAAI,CAAC,qBAAqB,KAAK,QAAQ;YAC7D,GAAG,OAAO;SACX,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,GAAQ,EAAE,UAAmC,EAAE;QACzD,OAAO,WAAW,CAAC,GAAG,EAAE;YACtB,QAAQ,EAAE,IAAI;YACd,oBAAoB,EAAE,IAAI,CAAC,qBAAqB,KAAK,QAAQ;YAC7D,GAAG,OAAO;SACX,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAxCY,gBAAgB;IAD5B,UAAU,EAAE;IAI4C,WAAA,aAAa,EAAE,CAAA;qCAAjC,eAAe;GAHzC,gBAAgB,CAwC5B;SAxCY,gBAAgB","sourcesContent":["import {Configuration, Injectable, InjectorService} from \"@tsed/di\";\nimport {deserialize, JsonDeserializerOptions, JsonSerializerOptions, serialize} from \"@tsed/json-mapper\";\n\n/**\n * @deprecated Since 2021-10-03. Use serialize/deserialize functions from @tsed/json-mapper instead\n */\n@Injectable()\nexport class ConverterService {\n private readonly _additionalProperties: string;\n\n constructor(private injectorService: InjectorService, @Configuration() configuration: Configuration) {\n this._additionalProperties = configuration.get<string>(\"converter.additionalProperties\");\n }\n\n /**\n * Convert instance to plainObject.\n *\n * @param obj\n * @param options\n */\n serialize(obj: any, options: JsonSerializerOptions = {}): any {\n return serialize(obj, {\n useAlias: true,\n additionalProperties: this._additionalProperties === \"accept\",\n ...options\n });\n }\n\n /**\n * Convert a plainObject to targetType.\n *\n * ### Options\n *\n * - `ignoreCallback`: callback called for each object which will be deserialized. The callback can return a boolean to avoid the default converter behavior.\n * - `checkRequiredValue`: Disable the required check condition.\n *\n * @param obj Object source that will be deserialized\n * @param options Mapping options\n * @returns {any}\n */\n deserialize(obj: any, options: JsonDeserializerOptions = {}): any {\n return deserialize(obj, {\n useAlias: true,\n additionalProperties: this._additionalProperties === \"accept\",\n ...options\n });\n }\n}\n"]}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { isSerializable } from "@tsed/core";
|
|
3
|
+
import { Constant, Inject, Injectable, InjectorService } from "@tsed/di";
|
|
4
|
+
import { ResponseFiltersContainer } from "../domain/ResponseFiltersContainer";
|
|
5
|
+
import { ANY_CONTENT_TYPE, getContentType } from "../utils/getContentType";
|
|
6
|
+
import { ConverterService } from "./ConverterService";
|
|
7
|
+
import { renderView } from "../utils/renderView";
|
|
8
|
+
/**
|
|
9
|
+
* @platform
|
|
10
|
+
*/
|
|
11
|
+
let PlatformResponseFilter = class PlatformResponseFilter {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.types = new Map();
|
|
14
|
+
}
|
|
15
|
+
get contentTypes() {
|
|
16
|
+
return [...this.types.keys()];
|
|
17
|
+
}
|
|
18
|
+
$onInit() {
|
|
19
|
+
ResponseFiltersContainer.forEach((token, type) => {
|
|
20
|
+
if (this.responseFilters.includes(token)) {
|
|
21
|
+
this.types.set(type, this.injector.get(token));
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
getBestContentType(data, ctx) {
|
|
26
|
+
const contentType = getContentType(data, ctx);
|
|
27
|
+
if (ctx.request.get("Accept")) {
|
|
28
|
+
const bestContentType = ctx.request.accepts([contentType].concat(this.contentTypes).filter(Boolean));
|
|
29
|
+
if (bestContentType) {
|
|
30
|
+
return [].concat(bestContentType).filter((type) => type !== "*/*")[0];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return contentType;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Call filters to transform data
|
|
37
|
+
* @param data
|
|
38
|
+
* @param ctx
|
|
39
|
+
*/
|
|
40
|
+
async transform(data, ctx) {
|
|
41
|
+
const { response } = ctx;
|
|
42
|
+
const bestContentType = this.getBestContentType(data, ctx);
|
|
43
|
+
bestContentType && response.contentType(bestContentType);
|
|
44
|
+
if (this.types.has(bestContentType)) {
|
|
45
|
+
return this.types.get(bestContentType).transform(data, ctx);
|
|
46
|
+
}
|
|
47
|
+
if (this.types.has(ANY_CONTENT_TYPE)) {
|
|
48
|
+
return this.types.get(ANY_CONTENT_TYPE).transform(data, ctx);
|
|
49
|
+
}
|
|
50
|
+
return data;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Serialize data before calling filters
|
|
54
|
+
* @param data
|
|
55
|
+
* @param ctx
|
|
56
|
+
*/
|
|
57
|
+
async serialize(data, ctx) {
|
|
58
|
+
const { response, endpoint } = ctx;
|
|
59
|
+
if (endpoint) {
|
|
60
|
+
if (endpoint.view) {
|
|
61
|
+
data = await renderView(data, ctx);
|
|
62
|
+
}
|
|
63
|
+
else if (isSerializable(data)) {
|
|
64
|
+
data = this.injector.get(ConverterService).serialize(data, {
|
|
65
|
+
...endpoint.getResponseOptions(response.statusCode),
|
|
66
|
+
endpoint: true
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return data;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
__decorate([
|
|
74
|
+
Inject(),
|
|
75
|
+
__metadata("design:type", InjectorService)
|
|
76
|
+
], PlatformResponseFilter.prototype, "injector", void 0);
|
|
77
|
+
__decorate([
|
|
78
|
+
Constant("responseFilters", []),
|
|
79
|
+
__metadata("design:type", Array)
|
|
80
|
+
], PlatformResponseFilter.prototype, "responseFilters", void 0);
|
|
81
|
+
PlatformResponseFilter = __decorate([
|
|
82
|
+
Injectable()
|
|
83
|
+
], PlatformResponseFilter);
|
|
84
|
+
export { PlatformResponseFilter };
|
|
85
|
+
//# sourceMappingURL=PlatformResponseFilter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlatformResponseFilter.js","sourceRoot":"","sources":["../../../src/services/PlatformResponseFilter.ts"],"names":[],"mappings":"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","sourcesContent":["import {isSerializable, Type} from \"@tsed/core\";\nimport {BaseContext, Constant, Inject, Injectable, InjectorService} from \"@tsed/di\";\nimport {ResponseFilterKey, ResponseFiltersContainer} from \"../domain/ResponseFiltersContainer\";\nimport {ResponseFilterMethods} from \"../interfaces/ResponseFilterMethods\";\nimport {ANY_CONTENT_TYPE, getContentType} from \"../utils/getContentType\";\nimport {ConverterService} from \"./ConverterService\";\nimport {renderView} from \"../utils/renderView\";\n\n/**\n * @platform\n */\n@Injectable()\nexport class PlatformResponseFilter {\n types: Map<ResponseFilterKey, ResponseFilterMethods> = new Map();\n\n @Inject()\n injector: InjectorService;\n\n @Constant(\"responseFilters\", [])\n protected responseFilters: Type<ResponseFilterMethods>[];\n\n get contentTypes(): ResponseFilterKey[] {\n return [...this.types.keys()];\n }\n\n $onInit() {\n ResponseFiltersContainer.forEach((token, type) => {\n if (this.responseFilters.includes(token)) {\n this.types.set(type, this.injector.get(token)!);\n }\n });\n }\n\n getBestContentType(data: any, ctx: BaseContext) {\n const contentType = getContentType(data, ctx);\n\n if (ctx.request.get(\"Accept\")) {\n const bestContentType = ctx.request.accepts([contentType].concat(this.contentTypes).filter(Boolean));\n\n if (bestContentType) {\n return [].concat(bestContentType as any).filter((type) => type !== \"*/*\")[0];\n }\n }\n\n return contentType;\n }\n /**\n * Call filters to transform data\n * @param data\n * @param ctx\n */\n async transform(data: unknown, ctx: BaseContext) {\n const {response} = ctx;\n const bestContentType = this.getBestContentType(data, ctx);\n\n bestContentType && response.contentType(bestContentType);\n\n if (this.types.has(bestContentType)) {\n return this.types.get(bestContentType)!.transform(data, ctx);\n }\n\n if (this.types.has(ANY_CONTENT_TYPE)) {\n return this.types.get(ANY_CONTENT_TYPE)!.transform(data, ctx);\n }\n\n return data;\n }\n /**\n * Serialize data before calling filters\n * @param data\n * @param ctx\n */\n async serialize(data: unknown, ctx: BaseContext) {\n const {response, endpoint} = ctx;\n\n if (endpoint) {\n if (endpoint.view) {\n data = await renderView(data, ctx);\n } else if (isSerializable(data)) {\n data = this.injector.get<ConverterService>(ConverterService)!.serialize(data, {\n ...endpoint.getResponseOptions(response.statusCode),\n endpoint: true\n });\n }\n }\n\n return data;\n }\n}\n"]}
|