@tsed/platform-response-filter 6.87.2 → 6.90.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/cjs/errors/TemplateRenderError.d.ts +14 -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} +2 -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/cjs/utils/renderView.d.ts +2 -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 -230
- package/lib/index.js.map +0 -1
- package/lib/index.modern.js +0 -226
- package/lib/index.modern.js.map +0 -1
|
@@ -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"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { isObject } from "@tsed/core";
|
|
2
|
+
export const ANY_CONTENT_TYPE = "*/*";
|
|
3
|
+
/**
|
|
4
|
+
* @ignore
|
|
5
|
+
*/
|
|
6
|
+
export function getContentType(data, ctx) {
|
|
7
|
+
const { endpoint, response } = ctx;
|
|
8
|
+
const { operation } = endpoint;
|
|
9
|
+
const contentType = response.getContentType() || operation.getContentTypeOf(response.statusCode) || "";
|
|
10
|
+
if (contentType && contentType !== ANY_CONTENT_TYPE) {
|
|
11
|
+
if (contentType === "application/json") {
|
|
12
|
+
if (isObject(data)) {
|
|
13
|
+
return contentType;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return contentType;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (typeof data === "string" && endpoint.view) {
|
|
21
|
+
return "text/html";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=getContentType.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getContentType.js","sourceRoot":"","sources":["../../../src/utils/getContentType.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEpC,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AACtC;;GAEG;AACH,MAAM,UAAU,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,gBAAgB,EAAE;QACnD,IAAI,WAAW,KAAK,kBAAkB,EAAE;YACtC,IAAI,QAAQ,CAAC,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","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"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TemplateRenderError } from "../errors/TemplateRenderError";
|
|
2
|
+
export async function renderView(data, $ctx) {
|
|
3
|
+
const { response, endpoint } = $ctx;
|
|
4
|
+
try {
|
|
5
|
+
const { data } = $ctx;
|
|
6
|
+
const { path, options } = endpoint.view;
|
|
7
|
+
return await response.render(path, { ...options, ...data, $ctx });
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
throw new TemplateRenderError(endpoint.targetName, endpoint.propertyKey, err);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=renderView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderView.js","sourceRoot":"","sources":["../../../src/utils/renderView.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,mBAAmB,EAAC,MAAM,+BAA+B,CAAC;AAElE,MAAM,CAAC,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,mBAAmB,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;KAC/E;AACH,CAAC","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,14 @@
|
|
|
1
|
+
import { Type } from "@tsed/core";
|
|
2
|
+
import { ResponseFilterMethods } from "../interfaces/ResponseFilterMethods";
|
|
3
|
+
/**
|
|
4
|
+
* @ignore
|
|
5
|
+
*/
|
|
6
|
+
export declare type ResponseFilterKey = "*/*" | "application/json" | "text/html" | "plain/text" | string;
|
|
7
|
+
/**
|
|
8
|
+
* @ignore
|
|
9
|
+
*/
|
|
10
|
+
export declare const ResponseFiltersContainer: Map<string, Type<ResponseFilterMethods<unknown>>>;
|
|
11
|
+
/**
|
|
12
|
+
* @ignore
|
|
13
|
+
*/
|
|
14
|
+
export declare function registerResponseFilter(type: ResponseFilterKey, token: Type<ResponseFilterMethods>): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Type } from "@tsed/core";
|
|
2
|
+
import { InternalServerError } from "@tsed/exceptions";
|
|
3
|
+
/**
|
|
4
|
+
* @private
|
|
5
|
+
*/
|
|
6
|
+
export declare class TemplateRenderError extends InternalServerError {
|
|
7
|
+
name: string;
|
|
8
|
+
constructor(target: Type<any> | string, method: string | symbol, err: Error);
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
static buildMessage(target: Type<any> | string, method: string | symbol, err: Error): string;
|
|
14
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./decorators/responseFilter";
|
|
2
|
+
export * from "./domain/ResponseFiltersContainer";
|
|
3
|
+
export * from "./errors/TemplateRenderError";
|
|
4
|
+
export * from "./interfaces/ResponseFilterMethods";
|
|
5
|
+
export * from "./services/PlatformResponseFilter";
|
|
6
|
+
export * from "./services/ConverterService";
|
|
7
|
+
export * from "./utils/getContentType";
|
|
8
|
+
export * from "./utils/renderView";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Type } from "@tsed/core";
|
|
2
|
+
import type { BaseContext } from "@tsed/di";
|
|
3
|
+
declare global {
|
|
4
|
+
namespace TsED {
|
|
5
|
+
interface Configuration {
|
|
6
|
+
/**
|
|
7
|
+
* A list of response filters must be called before returning a response to the consumer. See more on [Response filters](/docs/response-filter.md).
|
|
8
|
+
*/
|
|
9
|
+
responseFilters: Type<ResponseFilterMethods>[];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export interface ResponseFilterMethods<T = unknown> {
|
|
14
|
+
transform(data: T, ctx: BaseContext): any;
|
|
15
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Configuration, InjectorService } from "@tsed/di";
|
|
2
|
+
import { JsonDeserializerOptions, JsonSerializerOptions } from "@tsed/json-mapper";
|
|
3
|
+
/**
|
|
4
|
+
* @deprecated Since 2021-10-03. Use serialize/deserialize functions from @tsed/json-mapper instead
|
|
5
|
+
*/
|
|
6
|
+
export declare class ConverterService {
|
|
7
|
+
private injectorService;
|
|
8
|
+
private readonly _additionalProperties;
|
|
9
|
+
constructor(injectorService: InjectorService, configuration: Configuration);
|
|
10
|
+
/**
|
|
11
|
+
* Convert instance to plainObject.
|
|
12
|
+
*
|
|
13
|
+
* @param obj
|
|
14
|
+
* @param options
|
|
15
|
+
*/
|
|
16
|
+
serialize(obj: any, options?: JsonSerializerOptions): any;
|
|
17
|
+
/**
|
|
18
|
+
* Convert a plainObject to targetType.
|
|
19
|
+
*
|
|
20
|
+
* ### Options
|
|
21
|
+
*
|
|
22
|
+
* - `ignoreCallback`: callback called for each object which will be deserialized. The callback can return a boolean to avoid the default converter behavior.
|
|
23
|
+
* - `checkRequiredValue`: Disable the required check condition.
|
|
24
|
+
*
|
|
25
|
+
* @param obj Object source that will be deserialized
|
|
26
|
+
* @param options Mapping options
|
|
27
|
+
* @returns {any}
|
|
28
|
+
*/
|
|
29
|
+
deserialize(obj: any, options?: JsonDeserializerOptions): any;
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Type } from "@tsed/core";
|
|
2
|
+
import { BaseContext, InjectorService } from "@tsed/di";
|
|
3
|
+
import { ResponseFilterKey } from "../domain/ResponseFiltersContainer";
|
|
4
|
+
import { ResponseFilterMethods } from "../interfaces/ResponseFilterMethods";
|
|
5
|
+
/**
|
|
6
|
+
* @platform
|
|
7
|
+
*/
|
|
8
|
+
export declare class PlatformResponseFilter {
|
|
9
|
+
types: Map<ResponseFilterKey, ResponseFilterMethods>;
|
|
10
|
+
injector: InjectorService;
|
|
11
|
+
protected responseFilters: Type<ResponseFilterMethods>[];
|
|
12
|
+
get contentTypes(): ResponseFilterKey[];
|
|
13
|
+
$onInit(): void;
|
|
14
|
+
getBestContentType(data: any, ctx: BaseContext): any;
|
|
15
|
+
/**
|
|
16
|
+
* Call filters to transform data
|
|
17
|
+
* @param data
|
|
18
|
+
* @param ctx
|
|
19
|
+
*/
|
|
20
|
+
transform(data: unknown, ctx: BaseContext): Promise<any>;
|
|
21
|
+
/**
|
|
22
|
+
* Serialize data before calling filters
|
|
23
|
+
* @param data
|
|
24
|
+
* @param ctx
|
|
25
|
+
*/
|
|
26
|
+
serialize(data: unknown, ctx: BaseContext): Promise<unknown>;
|
|
27
|
+
}
|
package/package.json
CHANGED
|
@@ -1,36 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsed/platform-response-filter",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.90.0",
|
|
4
4
|
"description": "Platform response filter module for Ts.ED Framework",
|
|
5
5
|
"private": false,
|
|
6
6
|
"source": "./src/index.ts",
|
|
7
|
-
"main": "./lib/index.js",
|
|
8
|
-
"typings": "./lib/index.d.ts",
|
|
7
|
+
"main": "./lib/cjs/index.js",
|
|
8
|
+
"typings": "./lib/types/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"types": "./lib/types/index.d.ts",
|
|
11
|
+
"import": "./lib/esm/index.js",
|
|
12
|
+
"require": "./lib/cjs/index.js",
|
|
13
|
+
"default": "./lib/esm/index.js"
|
|
12
14
|
},
|
|
13
15
|
"scripts": {
|
|
14
|
-
"build": "
|
|
16
|
+
"build": "yarn run build:esm && yarn run build:cjs",
|
|
17
|
+
"build:cjs": "tsc --build tsconfig.compile.json",
|
|
18
|
+
"build:esm": "tsc --build tsconfig.compile.esm.json"
|
|
15
19
|
},
|
|
16
20
|
"dependencies": {
|
|
17
21
|
"tslib": "2.2.0"
|
|
18
22
|
},
|
|
19
23
|
"devDependencies": {
|
|
20
|
-
"@tsed/core": "6.
|
|
21
|
-
"@tsed/di": "6.
|
|
22
|
-
"@tsed/exceptions": "6.
|
|
23
|
-
"@tsed/json-mapper": "6.
|
|
24
|
-
"@tsed/platform-views": "6.
|
|
25
|
-
"@tsed/schema": "6.
|
|
24
|
+
"@tsed/core": "6.90.0",
|
|
25
|
+
"@tsed/di": "6.90.0",
|
|
26
|
+
"@tsed/exceptions": "6.90.0",
|
|
27
|
+
"@tsed/json-mapper": "6.90.0",
|
|
28
|
+
"@tsed/platform-views": "6.90.0",
|
|
29
|
+
"@tsed/schema": "6.90.0"
|
|
26
30
|
},
|
|
27
31
|
"peerDependencies": {
|
|
28
|
-
"@tsed/core": "^6.
|
|
29
|
-
"@tsed/di": "^6.
|
|
30
|
-
"@tsed/exceptions": "^6.
|
|
31
|
-
"@tsed/json-mapper": "^6.
|
|
32
|
-
"@tsed/platform-views": "^6.
|
|
33
|
-
"@tsed/schema": "^6.
|
|
32
|
+
"@tsed/core": "^6.90.0",
|
|
33
|
+
"@tsed/di": "^6.90.0",
|
|
34
|
+
"@tsed/exceptions": "^6.90.0",
|
|
35
|
+
"@tsed/json-mapper": "^6.90.0",
|
|
36
|
+
"@tsed/platform-views": "^6.90.0",
|
|
37
|
+
"@tsed/schema": "^6.90.0"
|
|
34
38
|
},
|
|
35
39
|
"repository": "https://github.com/tsedio/tsed",
|
|
36
40
|
"bugs": {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.compile.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"baseUrl": ".",
|
|
5
|
+
"module": "ES2020",
|
|
6
|
+
"rootDir": "src",
|
|
7
|
+
"outDir": "./lib/esm",
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"declarationDir": "./lib/types"
|
|
10
|
+
},
|
|
11
|
+
"exclude": [
|
|
12
|
+
"node_modules",
|
|
13
|
+
"test",
|
|
14
|
+
"lib",
|
|
15
|
+
"benchmark",
|
|
16
|
+
"coverage",
|
|
17
|
+
"spec",
|
|
18
|
+
"**/*.benchmark.ts",
|
|
19
|
+
"**/*.spec.ts",
|
|
20
|
+
"keys",
|
|
21
|
+
"jest.config.js"
|
|
22
|
+
]
|
|
23
|
+
}
|
package/lib/index.js
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
var di = require('@tsed/di');
|
|
2
|
-
var tslib = require('tslib');
|
|
3
|
-
var core = require('@tsed/core');
|
|
4
|
-
var platformViews = require('@tsed/platform-views');
|
|
5
|
-
var jsonMapper = require('@tsed/json-mapper');
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @ignore
|
|
9
|
-
*/
|
|
10
|
-
// tslint:disable-next-line:variable-name
|
|
11
|
-
const ResponseFiltersContainer = new Map();
|
|
12
|
-
/**
|
|
13
|
-
* @ignore
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
function registerResponseFilter(type, token) {
|
|
17
|
-
ResponseFiltersContainer.set(type, token);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Register a response filter service.
|
|
22
|
-
* @param contentTypes
|
|
23
|
-
* @decorator
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
function ResponseFilter(...contentTypes) {
|
|
27
|
-
return target => {
|
|
28
|
-
contentTypes.forEach(contentType => {
|
|
29
|
-
registerResponseFilter(contentType, target);
|
|
30
|
-
});
|
|
31
|
-
di.registerProvider({
|
|
32
|
-
provide: target,
|
|
33
|
-
useClass: target
|
|
34
|
-
});
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function _extends() {
|
|
39
|
-
_extends = Object.assign || function (target) {
|
|
40
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
41
|
-
var source = arguments[i];
|
|
42
|
-
|
|
43
|
-
for (var key in source) {
|
|
44
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
45
|
-
target[key] = source[key];
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return target;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
return _extends.apply(this, arguments);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const ANY_CONTENT_TYPE = "*/*";
|
|
57
|
-
/**
|
|
58
|
-
* @ignore
|
|
59
|
-
*/
|
|
60
|
-
|
|
61
|
-
function getContentType(data, ctx) {
|
|
62
|
-
const {
|
|
63
|
-
endpoint,
|
|
64
|
-
response
|
|
65
|
-
} = ctx;
|
|
66
|
-
const {
|
|
67
|
-
operation
|
|
68
|
-
} = endpoint;
|
|
69
|
-
const contentType = response.getContentType() || operation.getContentTypeOf(response.statusCode) || "";
|
|
70
|
-
|
|
71
|
-
if (contentType && contentType !== ANY_CONTENT_TYPE) {
|
|
72
|
-
if (contentType === "application/json") {
|
|
73
|
-
if (core.isObject(data)) {
|
|
74
|
-
return contentType;
|
|
75
|
-
}
|
|
76
|
-
} else {
|
|
77
|
-
return contentType;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (typeof data === "string" && endpoint.view) {
|
|
82
|
-
return "text/html";
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* @deprecated Since 2021-10-03. Use serialize/deserialize functions from @tsed/json-mapper instead
|
|
88
|
-
*/
|
|
89
|
-
|
|
90
|
-
exports.ConverterService = class ConverterService {
|
|
91
|
-
constructor(injectorService, configuration) {
|
|
92
|
-
this.injectorService = injectorService;
|
|
93
|
-
this._additionalProperties = configuration.get("converter.additionalProperties");
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Convert instance to plainObject.
|
|
97
|
-
*
|
|
98
|
-
* @param obj
|
|
99
|
-
* @param options
|
|
100
|
-
*/
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
serialize(obj, options = {}) {
|
|
104
|
-
return jsonMapper.serialize(obj, _extends({
|
|
105
|
-
useAlias: true,
|
|
106
|
-
additionalProperties: this._additionalProperties === "accept"
|
|
107
|
-
}, options));
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Convert a plainObject to targetType.
|
|
111
|
-
*
|
|
112
|
-
* ### Options
|
|
113
|
-
*
|
|
114
|
-
* - `ignoreCallback`: callback called for each object which will be deserialized. The callback can return a boolean to avoid the default converter behavior.
|
|
115
|
-
* - `checkRequiredValue`: Disable the required check condition.
|
|
116
|
-
*
|
|
117
|
-
* @param obj Object source that will be deserialized
|
|
118
|
-
* @param options Mapping options
|
|
119
|
-
* @returns {any}
|
|
120
|
-
*/
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
deserialize(obj, options = {}) {
|
|
124
|
-
return jsonMapper.deserialize(obj, _extends({
|
|
125
|
-
useAlias: true,
|
|
126
|
-
additionalProperties: this._additionalProperties === "accept"
|
|
127
|
-
}, options));
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
};
|
|
131
|
-
exports.ConverterService = tslib.__decorate([di.Injectable(), tslib.__param(1, di.Configuration()), tslib.__metadata("design:paramtypes", [di.InjectorService, Object])], exports.ConverterService);
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* @platform
|
|
135
|
-
*/
|
|
136
|
-
|
|
137
|
-
exports.PlatformResponseFilter = class PlatformResponseFilter {
|
|
138
|
-
constructor() {
|
|
139
|
-
this.types = new Map();
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
get contentTypes() {
|
|
143
|
-
return [...this.types.keys()];
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
$onInit() {
|
|
147
|
-
ResponseFiltersContainer.forEach((token, type) => {
|
|
148
|
-
if (this.responseFilters.includes(token)) {
|
|
149
|
-
this.types.set(type, this.injector.get(token));
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
getBestContentType(data, ctx) {
|
|
155
|
-
const contentType = getContentType(data, ctx);
|
|
156
|
-
|
|
157
|
-
if (ctx.request.get("Accept")) {
|
|
158
|
-
const bestContentType = ctx.request.accepts([contentType].concat(this.contentTypes).filter(Boolean));
|
|
159
|
-
|
|
160
|
-
if (bestContentType) {
|
|
161
|
-
return [].concat(bestContentType).filter(type => type !== "*/*")[0];
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return contentType;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Call filters to transform data
|
|
169
|
-
* @param data
|
|
170
|
-
* @param ctx
|
|
171
|
-
*/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
async transform(data, ctx) {
|
|
175
|
-
const {
|
|
176
|
-
response
|
|
177
|
-
} = ctx;
|
|
178
|
-
const bestContentType = this.getBestContentType(data, ctx);
|
|
179
|
-
bestContentType && response.contentType(bestContentType);
|
|
180
|
-
|
|
181
|
-
if (this.types.has(bestContentType)) {
|
|
182
|
-
return this.types.get(bestContentType).transform(data, ctx);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (this.types.has(ANY_CONTENT_TYPE)) {
|
|
186
|
-
return this.types.get(ANY_CONTENT_TYPE).transform(data, ctx);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return data;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Serialize data before calling filters
|
|
193
|
-
* @param data
|
|
194
|
-
* @param ctx
|
|
195
|
-
*/
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
async serialize(data, ctx) {
|
|
199
|
-
const {
|
|
200
|
-
response,
|
|
201
|
-
endpoint
|
|
202
|
-
} = ctx;
|
|
203
|
-
|
|
204
|
-
if (endpoint) {
|
|
205
|
-
if (endpoint.view) {
|
|
206
|
-
data = await platformViews.renderView(data, ctx);
|
|
207
|
-
} else if (core.isSerializable(data)) {
|
|
208
|
-
data = this.injector.get(exports.ConverterService).serialize(data, _extends({}, endpoint.getResponseOptions(response.statusCode), {
|
|
209
|
-
endpoint: true
|
|
210
|
-
}));
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return data;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
tslib.__decorate([di.Inject(), tslib.__metadata("design:type", di.InjectorService)], exports.PlatformResponseFilter.prototype, "injector", void 0);
|
|
220
|
-
|
|
221
|
-
tslib.__decorate([di.Constant("responseFilters", []), tslib.__metadata("design:type", Array)], exports.PlatformResponseFilter.prototype, "responseFilters", void 0);
|
|
222
|
-
|
|
223
|
-
exports.PlatformResponseFilter = tslib.__decorate([di.Injectable()], exports.PlatformResponseFilter);
|
|
224
|
-
|
|
225
|
-
exports.ANY_CONTENT_TYPE = ANY_CONTENT_TYPE;
|
|
226
|
-
exports.ResponseFilter = ResponseFilter;
|
|
227
|
-
exports.ResponseFiltersContainer = ResponseFiltersContainer;
|
|
228
|
-
exports.getContentType = getContentType;
|
|
229
|
-
exports.registerResponseFilter = registerResponseFilter;
|
|
230
|
-
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/domain/ResponseFiltersContainer.ts","../src/decorators/responseFilter.ts","../src/utils/getContentType.ts","../src/services/ConverterService.ts","../src/services/PlatformResponseFilter.ts"],"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","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","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","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","import {isSerializable, Type} from \"@tsed/core\";\nimport {BaseContext, Constant, Inject, Injectable, InjectorService} from \"@tsed/di\";\nimport {renderView} from \"@tsed/platform-views\";\nimport {ResponseFilterKey, ResponseFiltersContainer} from \"../domain/ResponseFiltersContainer\";\nimport {ResponseFilterMethods} from \"../interfaces/ResponseFilterMethods\";\nimport {ANY_CONTENT_TYPE, getContentType} from \"../utils/getContentType\";\nimport {ConverterService} from \"./ConverterService\";\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"],"names":["ResponseFiltersContainer","Map","registerResponseFilter","type","token","set","ResponseFilter","contentTypes","target","forEach","contentType","registerProvider","provide","useClass","ANY_CONTENT_TYPE","getContentType","data","ctx","endpoint","response","operation","getContentTypeOf","statusCode","isObject","view","ConverterService","constructor","injectorService","configuration","_additionalProperties","get","serialize","obj","options","useAlias","additionalProperties","deserialize","Injectable","__param","Configuration","InjectorService","PlatformResponseFilter","types","keys","$onInit","responseFilters","includes","injector","getBestContentType","request","bestContentType","accepts","concat","filter","Boolean","transform","has","renderView","isSerializable","getResponseOptions","__decorate","Inject","Constant"],"mappings":"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"}
|