@tsed/platform-response-filter 7.0.0-alpha.2 → 7.0.0-beta.11
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/cjs/decorators/responseFilter.js +23 -0
- package/lib/cjs/decorators/responseFilter.js.map +1 -0
- package/lib/cjs/domain/ResponseFiltersContainer.js +16 -0
- package/lib/cjs/domain/ResponseFiltersContainer.js.map +1 -0
- package/lib/cjs/errors/TemplateRenderError.js +23 -0
- package/lib/cjs/errors/TemplateRenderError.js.map +1 -0
- package/lib/cjs/index.js +14 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/cjs/interfaces/ResponseFilterMethods.js +3 -0
- package/lib/cjs/interfaces/ResponseFilterMethods.js.map +1 -0
- package/lib/cjs/package.json +3 -0
- package/lib/cjs/services/PlatformResponseFilter.js +94 -0
- package/lib/cjs/services/PlatformResponseFilter.js.map +1 -0
- package/lib/cjs/utils/getContentType.js +28 -0
- package/lib/cjs/utils/getContentType.js.map +1 -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 +11 -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/package.json +3 -0
- package/lib/esm/services/PlatformResponseFilter.js +91 -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/{decorators → types/decorators}/responseFilter.d.ts +0 -0
- package/lib/{domain → types/domain}/ResponseFiltersContainer.d.ts +0 -0
- package/lib/types/errors/TemplateRenderError.d.ts +14 -0
- package/lib/{index.d.ts → types/index.d.ts} +5 -0
- package/lib/{interfaces → types/interfaces}/ResponseFilterMethods.d.ts +0 -0
- package/lib/{services → types/services}/PlatformResponseFilter.d.ts +4 -4
- package/lib/{utils → types/utils}/getContentType.d.ts +0 -0
- package/lib/types/utils/renderView.d.ts +2 -0
- package/package.json +42 -22
- package/tsconfig.compile.esm.json +12 -0
- package/lib/index.js +0 -566
- package/lib/index.js.map +0 -1
- package/lib/index.modern.js +0 -562
- package/lib/index.modern.js.map +0 -1
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","../../../specs/json-mapper/lib/index.modern.js","../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 { __decorate } from 'tslib';\nimport { isBoolean, objectKeys, isCollection, isEmpty, isArray, nameOf, isNil, classOf, isClass, isClassObject, isFunction } from '@tsed/core';\nimport { BadRequest } from '@tsed/exceptions';\nimport { JsonEntityFn, JsonEntityStore, getProperties, alterIgnore, JsonSchema, getPropertiesStores } from '@tsed/schema';\n\n/**\n * @ignore\n */\n// tslint:disable-next-line:variable-name\nconst JsonMapperTypesContainer = new Map();\n/**\n * @ignore\n */\n\nfunction registerJsonTypeMapper(type, token) {\n JsonMapperTypesContainer.set(type, new token());\n}\n/**\n * @ignore\n */\n\nfunction getJsonMapperTypes() {\n return JsonMapperTypesContainer;\n}\n\n/**\n * Register a new JsonMapper Type\n * @param types\n * @constructor\n */\n\nfunction JsonMapper(...types) {\n return target => {\n types.forEach(type => {\n registerJsonTypeMapper(type, target);\n });\n };\n}\n\n/**\n * Mapper for `Array` type.\n * @jsonmapper\n * @component\n */\n\nlet ArrayMapper = class ArrayMapper {\n deserialize(data, options) {\n return [].concat(data).map(item => options.next(item));\n }\n\n serialize(data, options) {\n return [].concat(data).map(item => options.next(item));\n }\n\n};\nArrayMapper = __decorate([JsonMapper(Array)], ArrayMapper);\n\n/**\n * Mapper for `Date` type.\n * @jsonmapper\n * @component\n */\n\nlet DateMapper = class DateMapper {\n deserialize(data) {\n // don't convert unexpected data. In normal case, Ajv reject unexpected data.\n // But by default, we have to skip data deserialization and let user to apply\n // the right mapping\n if (isBoolean(data) || data === null || data === undefined) {\n return data;\n }\n\n return new Date(data);\n }\n\n serialize(object) {\n return new Date(object).toISOString();\n }\n\n};\nDateMapper = __decorate([JsonMapper(Date)], DateMapper);\n\n/**\n * Mapper for `Map` type.\n * @jsonmapper\n * @component\n */\n\nlet MapMapper = class MapMapper {\n deserialize(data, ctx) {\n const obj = new Map();\n objectKeys(data).forEach(key => {\n obj.set(key, ctx.next(data[key]));\n });\n return obj;\n }\n\n serialize(data, ctx) {\n const obj = {};\n data.forEach((value, key) => obj[key] = ctx.next(value));\n return obj;\n }\n\n};\nMapMapper = __decorate([JsonMapper(Map)], MapMapper);\n\n/**\n * Mapper for the `String`, `Number` and `Boolean` types.\n * @jsonmapper\n * @component\n */\n\nlet PrimitiveMapper = class PrimitiveMapper {\n deserialize(data, ctx) {\n switch (ctx.type) {\n case String:\n return data === null ? null : \"\" + data;\n\n case Number:\n if ([null, \"null\"].includes(data)) return null;\n const n = +data;\n\n if (isNaN(n)) {\n throw new BadRequest(\"Cast error. Expression value is not a number.\");\n }\n\n return n;\n\n case Boolean:\n if ([\"true\", \"1\", true].includes(data)) return true;\n if ([\"false\", \"0\", false].includes(data)) return false;\n if ([null, \"null\"].includes(data)) return null;\n if (data === undefined) return undefined;\n return !!data;\n }\n }\n\n serialize(object) {\n return object;\n }\n\n};\nPrimitiveMapper = __decorate([JsonMapper(String, Number, Boolean)], PrimitiveMapper);\n\n/**\n * Mapper for the `Set` Type.\n * @jsonmapper\n * @component\n */\n\nlet SetMapper = class SetMapper {\n deserialize(data, ctx) {\n const obj = new Set();\n objectKeys(data).forEach(key => {\n obj.add(ctx.next(data[key]));\n });\n return obj;\n }\n\n serialize(data, ctx) {\n const array = [];\n data.forEach(value => array.push(ctx.next(value)));\n return array;\n }\n\n};\nSetMapper = __decorate([JsonMapper(Set)], SetMapper);\n\n/**\n * Mapper for the `Symbol` type.\n *\n * @jsonmapper\n * @component\n */\n\nlet SymbolMapper = class SymbolMapper {\n deserialize(data) {\n return Symbol.for(data);\n }\n\n serialize(object) {\n return object.toString().replace(\"Symbol(\", \"\").replace(\")\", \"\");\n }\n\n};\nSymbolMapper = __decorate([JsonMapper(Symbol)], SymbolMapper);\n\n/**\n * Call the function before property deserialization.\n *\n * ## Example\n *\n * ```typescript\n * class Model {\n * @OnDeserialize(v => v + 1)\n * property: string;\n * }\n * ```\n *\n * @returns {Function}\n * @decorator\n * @schema\n * @property\n * @param cb\n */\n\nfunction OnDeserialize(cb) {\n return JsonEntityFn(storedJson => {\n storedJson.schema.$hooks.on(\"onDeserialize\", cb);\n });\n}\n\n/**\n * Call the function before property serialization.\n *\n * ## Example\n *\n * ```typescript\n * class Model {\n * @OnSerialize(v => v + 1)\n * property: string;\n * }\n * ```\n *\n * @returns {Function}\n * @decorator\n * @schema\n * @property\n * @param cb\n */\n\nfunction OnSerialize(cb) {\n return JsonEntityFn(storedJson => {\n storedJson.schema.$hooks.on(\"onSerialize\", cb);\n });\n}\n\n/**\n * Call the function after JsonMapper.\n *\n * ## Example\n *\n * ```typescript\n * @AfterDeserialize((data: Model) => { // After deserialize get the instance class\n * if (data.prop1 === 'VALUE' && data.prop2 !== 'VALUE2') {\n * throw BadRequest('MyMessage'); // or throw a ValidationError\n * } else {\n * data.prop2 = 'VALUE2';\n * return data;\n * }\n * })\n * class Model {\n * @Property()\n * prop1: string;\n * @Property()\n * prop2: string;\n * }\n * ```\n *\n * @returns {Function}\n * @decorator\n * @schema\n * @property\n * @param cb\n */\n\nfunction AfterDeserialize(cb) {\n return JsonEntityFn(storedJson => {\n storedJson.schema.$hooks.on(\"afterDeserialize\", cb);\n });\n}\n\n/**\n * Call the function before JsonMapper.\n *\n * ## Example\n *\n * ```typescript\n * @BeforeDeserialize((data: Record<string, unknown>) => { // Before deserialize get the data\n * if (data.prop1 === 'VALUE' && data.prop2 !== 'VALUE2') {\n * throw BadRequest('MyMessage'); // or throw a ValidationError\n * } else {\n * data.prop2 = 'VALUE2';\n * return data;\n * }\n * })\n * class Model {\n * @Property()\n * prop1: string;\n * @Property()\n * prop2: string;\n * }\n * ```\n *\n * @returns {Function}\n * @decorator\n * @schema\n * @property\n * @param cb\n */\n\nfunction BeforeDeserialize(cb) {\n return JsonEntityFn(storedJson => {\n storedJson.schema.$hooks.on(\"beforeDeserialize\", cb);\n });\n}\n\nfunction _extends() {\n _extends = Object.assign || function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n };\n\n return _extends.apply(this, arguments);\n}\n\nfunction _objectWithoutPropertiesLoose(source, excluded) {\n if (source == null) return {};\n var target = {};\n var sourceKeys = Object.keys(source);\n var key, i;\n\n for (i = 0; i < sourceKeys.length; i++) {\n key = sourceKeys[i];\n if (excluded.indexOf(key) >= 0) continue;\n target[key] = source[key];\n }\n\n return target;\n}\n\n/**\n * @ignore\n */\n\nclass JsonMapperContext {\n constructor({\n type,\n collectionType,\n next,\n options\n }) {\n this.type = type;\n this.collectionType = isCollection(collectionType) ? collectionType : undefined;\n this._next = next;\n this.options = options;\n }\n\n next(data) {\n return this._next(data, _extends({}, this.options, {\n type: this.type\n }));\n }\n\n}\n\nfunction alterAfterDeserialize(data, schema, options) {\n var _schema$$hooks;\n\n return schema == null ? void 0 : (_schema$$hooks = schema.$hooks) == null ? void 0 : _schema$$hooks.alter(\"afterDeserialize\", data, [options]);\n}\n\nfunction alterBeforeDeserialize(data, schema, options) {\n var _schema$$hooks;\n\n return schema == null ? void 0 : (_schema$$hooks = schema.$hooks) == null ? void 0 : _schema$$hooks.alter(\"beforeDeserialize\", data, [options]);\n}\n\nconst _excluded$1 = [\"collectionType\"],\n _excluded2$1 = [\"type\"],\n _excluded3 = [\"type\", \"store\"];\n\nfunction isDeserializable(obj, options) {\n if (!!options.collectionType && isNil(obj) || obj === undefined) {\n return false;\n }\n\n return !(isEmpty(options.type) || options.type === Object && !options.collectionType);\n}\n\nfunction alterValue$1(schema, value, options) {\n return schema.$hooks.alter(\"onDeserialize\", value, [options]);\n}\n\nfunction transformCollection(src, options) {\n var _types$get;\n\n const {\n types,\n type = Object,\n collectionType\n } = options;\n const context = new JsonMapperContext({\n type,\n collectionType,\n options,\n next: (data, _ref) => {\n let options = _objectWithoutPropertiesLoose(_ref, _excluded$1);\n\n return deserialize(data, options);\n }\n });\n return types == null ? void 0 : (_types$get = types.get(options.collectionType)) == null ? void 0 : _types$get.deserialize(src, context);\n}\n\nfunction transformType(src, options) {\n var _types$get2;\n\n const {\n types,\n type = Object\n } = options;\n const context = new JsonMapperContext({\n type,\n options,\n next: (data, _ref2) => {\n let options = _objectWithoutPropertiesLoose(_ref2, _excluded2$1);\n\n return deserialize(data, options);\n }\n });\n return types == null ? void 0 : (_types$get2 = types.get(type)) == null ? void 0 : _types$get2.deserialize(src, context);\n}\n/**\n * Transform given plain object to class.\n * @param src\n * @param options\n */\n\n\nfunction plainObjectToClass(src, options) {\n if (isEmpty(src)) {\n return src;\n }\n\n const {\n type,\n store = JsonEntityStore.from(type)\n } = options,\n next = _objectWithoutPropertiesLoose(options, _excluded3);\n\n const propertiesMap = getProperties(store, _extends({}, options, {\n withIgnoredProps: true\n }));\n let keys = objectKeys(src);\n const additionalProperties = propertiesMap.size ? !!store.schema.get(\"additionalProperties\") || options.additionalProperties : true;\n src = alterBeforeDeserialize(src, store.schema, options);\n const out = new type(src);\n propertiesMap.forEach(propStore => {\n const key = options.useAlias ? propStore.parent.schema.getAliasOf(propStore.propertyName) || propStore.propertyName : propStore.propertyName;\n keys = keys.filter(k => k !== key);\n next.type = propStore.computedType;\n\n if (alterIgnore(propStore.itemSchema, options)) {\n return;\n }\n\n let value = alterValue$1(propStore.schema, src[key], _extends({}, options, {\n self: src\n }));\n\n if (propStore.schema.hasGenerics) {\n next.nestedGenerics = propStore.schema.nestedGenerics;\n } else if (propStore.schema.isGeneric && options.nestedGenerics) {\n const [genericTypes = [], ...nestedGenerics] = options.nestedGenerics;\n const genericLabels = propStore.parent.schema.genericLabels || [];\n next.type = genericTypes[genericLabels.indexOf(propStore.schema.genericType)] || Object;\n\n if (next.type instanceof JsonSchema) {\n next.type = next.type.getTarget();\n }\n\n next.nestedGenerics = nestedGenerics;\n }\n\n value = deserialize(value, _extends({}, next, {\n type: value === src[key] ? next.type : undefined,\n collectionType: propStore.collectionType\n }));\n\n if (value !== undefined) {\n out[propStore.propertyName] = value;\n }\n });\n\n if (additionalProperties) {\n keys.forEach(key => {\n out[key] = src[key];\n });\n }\n\n return alterAfterDeserialize(out, store.schema, options);\n}\n\nfunction buildOptions(options) {\n if (options.store instanceof JsonEntityStore) {\n if (options.store.parameter && options.store.parameter.nestedGenerics.length) {\n options.nestedGenerics = options.store.parameter.nestedGenerics;\n }\n\n options.type = options.store.computedType;\n options.collectionType = options.store.collectionType;\n delete options.store;\n }\n\n return _extends({\n groups: false,\n useAlias: true\n }, options, {\n type: options.type ? options.type : undefined,\n types: options.types ? options.types : getJsonMapperTypes()\n });\n}\n/**\n * Transform given source to class base on the given `options.type`.\n *\n * @param src\n * @param options\n */\n\n\nfunction deserialize(src, options = {}) {\n var _options$types2;\n\n options = buildOptions(options);\n\n if (!isDeserializable(src, options)) {\n return src;\n }\n\n if (!options.collectionType && isArray(src)) {\n options.collectionType = Array;\n }\n\n if (options.collectionType) {\n var _options$types;\n\n if (!((_options$types = options.types) != null && _options$types.has(options.collectionType))) {\n throw new Error(`${nameOf(options.collectionType)} is not supported by JsonMapper.`);\n }\n\n return transformCollection(src, options);\n }\n\n if ((_options$types2 = options.types) != null && _options$types2.has(options.type)) {\n return transformType(src, options);\n } // class converter\n\n\n return plainObjectToClass(src, options);\n}\n\nconst _excluded = [\"useAlias\", \"type\"],\n _excluded2 = [\"type\", \"collectionType\", \"groups\"];\n\nfunction alterValue(schema, value, options) {\n return schema.$hooks.alter(\"onSerialize\", value, [options]);\n}\n\nfunction getSchemaProperties(storedJson, obj) {\n const stores = Array.from(getPropertiesStores(storedJson).entries());\n\n if (!stores.length) {\n // fallback to auto discovering field from obj\n objectKeys(obj).forEach(key => {\n const propStore = JsonEntityStore.from(classOf(storedJson.target), key);\n stores.push([key, propStore]);\n });\n }\n\n return stores;\n}\n\nfunction getObjectProperties(obj) {\n return Object.entries(obj).filter(([, value]) => !isFunction(value));\n}\n\nfunction getType(propStore, value) {\n if (isNil(value) || propStore.type === Object || isCollection(propStore.type)) {\n return undefined;\n }\n\n return propStore.type;\n}\n\nfunction classToPlainObject(obj, options) {\n const {\n useAlias = true,\n type\n } = options,\n props = _objectWithoutPropertiesLoose(options, _excluded);\n\n const entity = JsonEntityStore.from(type || obj);\n return getSchemaProperties(entity, obj).reduce((newObj, [key, propStore]) => {\n const schema = propStore.schema;\n\n if (alterIgnore(schema, _extends({\n useAlias\n }, props, {\n self: obj\n }))) {\n return newObj;\n }\n\n let value = alterValue(schema, obj[key], _extends({\n useAlias\n }, props, {\n self: obj\n }));\n value = serialize(value, _extends({\n useAlias,\n type: value === obj[key] ? getType(propStore, value) : undefined,\n collectionType: propStore.collectionType\n }, props));\n\n if (value === undefined) {\n return newObj;\n }\n\n key = useAlias ? propStore.parent.schema.getAliasOf(key) || key : key;\n return _extends({}, newObj, {\n [key]: value\n });\n }, {});\n}\n\nfunction toObject(obj, options) {\n return getObjectProperties(obj).reduce((newObj, [key, value]) => _extends({}, newObj, {\n [key]: serialize(value, options)\n }), {});\n}\n\nfunction serialize(obj, _ref = {}) {\n let {\n type,\n groups = false\n } = _ref,\n options = _objectWithoutPropertiesLoose(_ref, _excluded2);\n\n const types = options.types ? options.types : getJsonMapperTypes(); // prevent Object metadata assignation. TypeScript set Object by default on endpoint.type\n\n type = type === Object ? undefined : type;\n options.groups = groups;\n\n if (isEmpty(obj)) {\n return obj;\n } // FIX custom serialization function from @tsed/mongoose\n\n\n if (typeof obj.toJSON === \"function\" && obj.$isMongooseModelPrototype) {\n return obj.toJSON(options);\n }\n\n if (typeof obj.toJSON === \"function\") {\n return serialize(obj.toJSON(), _extends({}, options, {\n type: classOf(obj)\n }));\n }\n\n if (type && isClass(type)) {\n options.type = type;\n }\n\n if (isCollection(obj) && !options.collectionType) {\n type = classOf(obj);\n options.collectionType = type;\n }\n\n type = classOf(type || obj);\n const context = new JsonMapperContext({\n type,\n options,\n next: data => serialize(data, _extends({}, options, {\n collectionType: undefined,\n type: options.type\n }))\n });\n\n if (types.has(type)) {\n const jsonMapper = types.get(type);\n return jsonMapper.serialize(obj, context);\n }\n\n if (isArray(obj)) {\n var _types$get;\n\n // Serialize Array class like\n return (_types$get = types.get(Array)) == null ? void 0 : _types$get.serialize(obj, context);\n }\n\n return !isClassObject(classOf(type)) ? classToPlainObject(obj, options) : toObject(obj, options);\n}\n\nexport { AfterDeserialize, ArrayMapper, BeforeDeserialize, DateMapper, JsonMapper, JsonMapperContext, MapMapper, OnDeserialize, OnSerialize, PrimitiveMapper, SetMapper, SymbolMapper, classToPlainObject, deserialize, getJsonMapperTypes, plainObjectToClass, registerJsonTypeMapper, serialize };\n//# sourceMappingURL=index.modern.js.map\n","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 {serialize} from \"@tsed/json-mapper\";\nimport {renderView} from \"@tsed/platform-views\";\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 @Constant(\"additionalProperties\")\n private additionalProperties: boolean;\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 /**\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\n const bestContentType = this.getBestContentType(data, ctx);\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 /**\n * Serialize data from endpoint metadata\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 = serialize(data, {\n ...endpoint.getResponseOptions(response.statusCode),\n additionalProperties: this.additionalProperties,\n useAlias: true,\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","JsonMapperTypesContainer","registerJsonTypeMapper","getJsonMapperTypes","PlatformResponseFilter","constructor","types","keys","$onInit","responseFilters","includes","injector","get","getBestContentType","request","bestContentType","accepts","concat","filter","Boolean","transform","has","serialize","renderView","isSerializable","getResponseOptions","additionalProperties","useAlias","__decorate","Inject","InjectorService","Constant","Injectable"],"mappings":"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"}
|
package/lib/index.modern.js
DELETED
|
@@ -1,562 +0,0 @@
|
|
|
1
|
-
import { registerProvider, Inject, InjectorService, Constant, Injectable } from '@tsed/di';
|
|
2
|
-
import { __decorate, __metadata } from 'tslib';
|
|
3
|
-
import { isObject, isBoolean, objectKeys, isEmpty, classOf, isClass, isCollection, isArray, isClassObject, isFunction, isNil, isSerializable } from '@tsed/core';
|
|
4
|
-
import { BadRequest } from '@tsed/exceptions';
|
|
5
|
-
import { alterIgnore, getPropertiesStores, JsonEntityStore } from '@tsed/schema';
|
|
6
|
-
import { renderView } from '@tsed/platform-views';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @ignore
|
|
10
|
-
*/
|
|
11
|
-
// tslint:disable-next-line:variable-name
|
|
12
|
-
const ResponseFiltersContainer = new Map();
|
|
13
|
-
/**
|
|
14
|
-
* @ignore
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
function registerResponseFilter(type, token) {
|
|
18
|
-
ResponseFiltersContainer.set(type, token);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Register a response filter service.
|
|
23
|
-
* @param contentTypes
|
|
24
|
-
* @decorator
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
function ResponseFilter(...contentTypes) {
|
|
28
|
-
return target => {
|
|
29
|
-
contentTypes.forEach(contentType => {
|
|
30
|
-
registerResponseFilter(contentType, target);
|
|
31
|
-
});
|
|
32
|
-
registerProvider({
|
|
33
|
-
provide: target,
|
|
34
|
-
useClass: target
|
|
35
|
-
});
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function _extends$1() {
|
|
40
|
-
_extends$1 = Object.assign || function (target) {
|
|
41
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
42
|
-
var source = arguments[i];
|
|
43
|
-
|
|
44
|
-
for (var key in source) {
|
|
45
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
46
|
-
target[key] = source[key];
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return target;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
return _extends$1.apply(this, arguments);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const ANY_CONTENT_TYPE = "*/*";
|
|
58
|
-
/**
|
|
59
|
-
* @ignore
|
|
60
|
-
*/
|
|
61
|
-
|
|
62
|
-
function getContentType(data, ctx) {
|
|
63
|
-
const {
|
|
64
|
-
endpoint,
|
|
65
|
-
response
|
|
66
|
-
} = ctx;
|
|
67
|
-
const {
|
|
68
|
-
operation
|
|
69
|
-
} = endpoint;
|
|
70
|
-
const contentType = response.getContentType() || operation.getContentTypeOf(response.statusCode) || "";
|
|
71
|
-
|
|
72
|
-
if (contentType && contentType !== ANY_CONTENT_TYPE) {
|
|
73
|
-
if (contentType === "application/json") {
|
|
74
|
-
if (isObject(data)) {
|
|
75
|
-
return contentType;
|
|
76
|
-
}
|
|
77
|
-
} else {
|
|
78
|
-
return contentType;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (typeof data === "string" && endpoint.view) {
|
|
83
|
-
return "text/html";
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* @ignore
|
|
89
|
-
*/
|
|
90
|
-
// tslint:disable-next-line:variable-name
|
|
91
|
-
|
|
92
|
-
const JsonMapperTypesContainer = new Map();
|
|
93
|
-
/**
|
|
94
|
-
* @ignore
|
|
95
|
-
*/
|
|
96
|
-
|
|
97
|
-
function registerJsonTypeMapper(type, token) {
|
|
98
|
-
JsonMapperTypesContainer.set(type, new token());
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* @ignore
|
|
102
|
-
*/
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
function getJsonMapperTypes() {
|
|
106
|
-
return JsonMapperTypesContainer;
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Register a new JsonMapper Type
|
|
110
|
-
* @param types
|
|
111
|
-
* @constructor
|
|
112
|
-
*/
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
function JsonMapper(...types) {
|
|
116
|
-
return target => {
|
|
117
|
-
types.forEach(type => {
|
|
118
|
-
registerJsonTypeMapper(type, target);
|
|
119
|
-
});
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Mapper for `Array` type.
|
|
124
|
-
* @jsonmapper
|
|
125
|
-
* @component
|
|
126
|
-
*/
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
let ArrayMapper = class ArrayMapper {
|
|
130
|
-
deserialize(data, options) {
|
|
131
|
-
return [].concat(data).map(item => options.next(item));
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
serialize(data, options) {
|
|
135
|
-
return [].concat(data).map(item => options.next(item));
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
};
|
|
139
|
-
ArrayMapper = __decorate([JsonMapper(Array)], ArrayMapper);
|
|
140
|
-
/**
|
|
141
|
-
* Mapper for `Date` type.
|
|
142
|
-
* @jsonmapper
|
|
143
|
-
* @component
|
|
144
|
-
*/
|
|
145
|
-
|
|
146
|
-
let DateMapper = class DateMapper {
|
|
147
|
-
deserialize(data) {
|
|
148
|
-
// don't convert unexpected data. In normal case, Ajv reject unexpected data.
|
|
149
|
-
// But by default, we have to skip data deserialization and let user to apply
|
|
150
|
-
// the right mapping
|
|
151
|
-
if (isBoolean(data) || data === null || data === undefined) {
|
|
152
|
-
return data;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return new Date(data);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
serialize(object) {
|
|
159
|
-
return new Date(object).toISOString();
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
};
|
|
163
|
-
DateMapper = __decorate([JsonMapper(Date)], DateMapper);
|
|
164
|
-
/**
|
|
165
|
-
* Mapper for `Map` type.
|
|
166
|
-
* @jsonmapper
|
|
167
|
-
* @component
|
|
168
|
-
*/
|
|
169
|
-
|
|
170
|
-
let MapMapper = class MapMapper {
|
|
171
|
-
deserialize(data, ctx) {
|
|
172
|
-
const obj = new Map();
|
|
173
|
-
objectKeys(data).forEach(key => {
|
|
174
|
-
obj.set(key, ctx.next(data[key]));
|
|
175
|
-
});
|
|
176
|
-
return obj;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
serialize(data, ctx) {
|
|
180
|
-
const obj = {};
|
|
181
|
-
data.forEach((value, key) => obj[key] = ctx.next(value));
|
|
182
|
-
return obj;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
};
|
|
186
|
-
MapMapper = __decorate([JsonMapper(Map)], MapMapper);
|
|
187
|
-
/**
|
|
188
|
-
* Mapper for the `String`, `Number` and `Boolean` types.
|
|
189
|
-
* @jsonmapper
|
|
190
|
-
* @component
|
|
191
|
-
*/
|
|
192
|
-
|
|
193
|
-
let PrimitiveMapper = class PrimitiveMapper {
|
|
194
|
-
deserialize(data, ctx) {
|
|
195
|
-
switch (ctx.type) {
|
|
196
|
-
case String:
|
|
197
|
-
return data === null ? null : "" + data;
|
|
198
|
-
|
|
199
|
-
case Number:
|
|
200
|
-
if ([null, "null"].includes(data)) return null;
|
|
201
|
-
const n = +data;
|
|
202
|
-
|
|
203
|
-
if (isNaN(n)) {
|
|
204
|
-
throw new BadRequest("Cast error. Expression value is not a number.");
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
return n;
|
|
208
|
-
|
|
209
|
-
case Boolean:
|
|
210
|
-
if (["true", "1", true].includes(data)) return true;
|
|
211
|
-
if (["false", "0", false].includes(data)) return false;
|
|
212
|
-
if ([null, "null"].includes(data)) return null;
|
|
213
|
-
if (data === undefined) return undefined;
|
|
214
|
-
return !!data;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
serialize(object) {
|
|
219
|
-
return object;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
};
|
|
223
|
-
PrimitiveMapper = __decorate([JsonMapper(String, Number, Boolean)], PrimitiveMapper);
|
|
224
|
-
/**
|
|
225
|
-
* Mapper for the `Set` Type.
|
|
226
|
-
* @jsonmapper
|
|
227
|
-
* @component
|
|
228
|
-
*/
|
|
229
|
-
|
|
230
|
-
let SetMapper = class SetMapper {
|
|
231
|
-
deserialize(data, ctx) {
|
|
232
|
-
const obj = new Set();
|
|
233
|
-
objectKeys(data).forEach(key => {
|
|
234
|
-
obj.add(ctx.next(data[key]));
|
|
235
|
-
});
|
|
236
|
-
return obj;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
serialize(data, ctx) {
|
|
240
|
-
const array = [];
|
|
241
|
-
data.forEach(value => array.push(ctx.next(value)));
|
|
242
|
-
return array;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
};
|
|
246
|
-
SetMapper = __decorate([JsonMapper(Set)], SetMapper);
|
|
247
|
-
/**
|
|
248
|
-
* Mapper for the `Symbol` type.
|
|
249
|
-
*
|
|
250
|
-
* @jsonmapper
|
|
251
|
-
* @component
|
|
252
|
-
*/
|
|
253
|
-
|
|
254
|
-
let SymbolMapper = class SymbolMapper {
|
|
255
|
-
deserialize(data) {
|
|
256
|
-
return Symbol.for(data);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
serialize(object) {
|
|
260
|
-
return object.toString().replace("Symbol(", "").replace(")", "");
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
};
|
|
264
|
-
SymbolMapper = __decorate([JsonMapper(Symbol)], SymbolMapper);
|
|
265
|
-
|
|
266
|
-
function _extends() {
|
|
267
|
-
_extends = Object.assign || function (target) {
|
|
268
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
269
|
-
var source = arguments[i];
|
|
270
|
-
|
|
271
|
-
for (var key in source) {
|
|
272
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
273
|
-
target[key] = source[key];
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
return target;
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
return _extends.apply(this, arguments);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
285
|
-
if (source == null) return {};
|
|
286
|
-
var target = {};
|
|
287
|
-
var sourceKeys = Object.keys(source);
|
|
288
|
-
var key, i;
|
|
289
|
-
|
|
290
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
|
291
|
-
key = sourceKeys[i];
|
|
292
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
293
|
-
target[key] = source[key];
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
return target;
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* @ignore
|
|
300
|
-
*/
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
class JsonMapperContext {
|
|
304
|
-
constructor({
|
|
305
|
-
type,
|
|
306
|
-
collectionType,
|
|
307
|
-
next,
|
|
308
|
-
options
|
|
309
|
-
}) {
|
|
310
|
-
this.type = type;
|
|
311
|
-
this.collectionType = isCollection(collectionType) ? collectionType : undefined;
|
|
312
|
-
this._next = next;
|
|
313
|
-
this.options = options;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
next(data) {
|
|
317
|
-
return this._next(data, _extends({}, this.options, {
|
|
318
|
-
type: this.type
|
|
319
|
-
}));
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
const _excluded = ["useAlias", "type"],
|
|
325
|
-
_excluded2 = ["type", "collectionType", "groups"];
|
|
326
|
-
|
|
327
|
-
function alterValue(schema, value, options) {
|
|
328
|
-
return schema.$hooks.alter("onSerialize", value, [options]);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
function getSchemaProperties(storedJson, obj) {
|
|
332
|
-
const stores = Array.from(getPropertiesStores(storedJson).entries());
|
|
333
|
-
|
|
334
|
-
if (!stores.length) {
|
|
335
|
-
// fallback to auto discovering field from obj
|
|
336
|
-
objectKeys(obj).forEach(key => {
|
|
337
|
-
const propStore = JsonEntityStore.from(classOf(storedJson.target), key);
|
|
338
|
-
stores.push([key, propStore]);
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
return stores;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function getObjectProperties(obj) {
|
|
346
|
-
return Object.entries(obj).filter(([, value]) => !isFunction(value));
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function getType(propStore, value) {
|
|
350
|
-
if (isNil(value) || propStore.type === Object || isCollection(propStore.type)) {
|
|
351
|
-
return undefined;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
return propStore.type;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
function classToPlainObject(obj, options) {
|
|
358
|
-
const {
|
|
359
|
-
useAlias = true,
|
|
360
|
-
type
|
|
361
|
-
} = options,
|
|
362
|
-
props = _objectWithoutPropertiesLoose(options, _excluded);
|
|
363
|
-
|
|
364
|
-
const entity = JsonEntityStore.from(type || obj);
|
|
365
|
-
return getSchemaProperties(entity, obj).reduce((newObj, [key, propStore]) => {
|
|
366
|
-
const schema = propStore.schema;
|
|
367
|
-
|
|
368
|
-
if (alterIgnore(schema, _extends({
|
|
369
|
-
useAlias
|
|
370
|
-
}, props, {
|
|
371
|
-
self: obj
|
|
372
|
-
}))) {
|
|
373
|
-
return newObj;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
let value = alterValue(schema, obj[key], _extends({
|
|
377
|
-
useAlias
|
|
378
|
-
}, props, {
|
|
379
|
-
self: obj
|
|
380
|
-
}));
|
|
381
|
-
value = serialize(value, _extends({
|
|
382
|
-
useAlias,
|
|
383
|
-
type: value === obj[key] ? getType(propStore, value) : undefined,
|
|
384
|
-
collectionType: propStore.collectionType
|
|
385
|
-
}, props));
|
|
386
|
-
|
|
387
|
-
if (value === undefined) {
|
|
388
|
-
return newObj;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
key = useAlias ? propStore.parent.schema.getAliasOf(key) || key : key;
|
|
392
|
-
return _extends({}, newObj, {
|
|
393
|
-
[key]: value
|
|
394
|
-
});
|
|
395
|
-
}, {});
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
function toObject(obj, options) {
|
|
399
|
-
return getObjectProperties(obj).reduce((newObj, [key, value]) => _extends({}, newObj, {
|
|
400
|
-
[key]: serialize(value, options)
|
|
401
|
-
}), {});
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
function serialize(obj, _ref = {}) {
|
|
405
|
-
let {
|
|
406
|
-
type,
|
|
407
|
-
groups = false
|
|
408
|
-
} = _ref,
|
|
409
|
-
options = _objectWithoutPropertiesLoose(_ref, _excluded2);
|
|
410
|
-
|
|
411
|
-
const types = options.types ? options.types : getJsonMapperTypes(); // prevent Object metadata assignation. TypeScript set Object by default on endpoint.type
|
|
412
|
-
|
|
413
|
-
type = type === Object ? undefined : type;
|
|
414
|
-
options.groups = groups;
|
|
415
|
-
|
|
416
|
-
if (isEmpty(obj)) {
|
|
417
|
-
return obj;
|
|
418
|
-
} // FIX custom serialization function from @tsed/mongoose
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
if (typeof obj.toJSON === "function" && obj.$isMongooseModelPrototype) {
|
|
422
|
-
return obj.toJSON(options);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
if (typeof obj.toJSON === "function") {
|
|
426
|
-
return serialize(obj.toJSON(), _extends({}, options, {
|
|
427
|
-
type: classOf(obj)
|
|
428
|
-
}));
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
if (type && isClass(type)) {
|
|
432
|
-
options.type = type;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
if (isCollection(obj) && !options.collectionType) {
|
|
436
|
-
type = classOf(obj);
|
|
437
|
-
options.collectionType = type;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
type = classOf(type || obj);
|
|
441
|
-
const context = new JsonMapperContext({
|
|
442
|
-
type,
|
|
443
|
-
options,
|
|
444
|
-
next: data => serialize(data, _extends({}, options, {
|
|
445
|
-
collectionType: undefined,
|
|
446
|
-
type: options.type
|
|
447
|
-
}))
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
if (types.has(type)) {
|
|
451
|
-
const jsonMapper = types.get(type);
|
|
452
|
-
return jsonMapper.serialize(obj, context);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
if (isArray(obj)) {
|
|
456
|
-
var _types$get; // Serialize Array class like
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
return (_types$get = types.get(Array)) == null ? void 0 : _types$get.serialize(obj, context);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
return !isClassObject(classOf(type)) ? classToPlainObject(obj, options) : toObject(obj, options);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
/**
|
|
466
|
-
* @platform
|
|
467
|
-
*/
|
|
468
|
-
|
|
469
|
-
let PlatformResponseFilter = class PlatformResponseFilter {
|
|
470
|
-
constructor() {
|
|
471
|
-
this.types = new Map();
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
get contentTypes() {
|
|
475
|
-
return [...this.types.keys()];
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
$onInit() {
|
|
479
|
-
ResponseFiltersContainer.forEach((token, type) => {
|
|
480
|
-
if (this.responseFilters.includes(token)) {
|
|
481
|
-
this.types.set(type, this.injector.get(token));
|
|
482
|
-
}
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
getBestContentType(data, ctx) {
|
|
487
|
-
const contentType = getContentType(data, ctx);
|
|
488
|
-
|
|
489
|
-
if (ctx.request.get("Accept")) {
|
|
490
|
-
const bestContentType = ctx.request.accepts([contentType].concat(this.contentTypes).filter(Boolean));
|
|
491
|
-
|
|
492
|
-
if (bestContentType) {
|
|
493
|
-
return [].concat(bestContentType).filter(type => type !== "*/*")[0];
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
return contentType;
|
|
498
|
-
}
|
|
499
|
-
/**
|
|
500
|
-
* Call filters to transform data
|
|
501
|
-
* @param data
|
|
502
|
-
* @param ctx
|
|
503
|
-
*/
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
async transform(data, ctx) {
|
|
507
|
-
const {
|
|
508
|
-
response
|
|
509
|
-
} = ctx;
|
|
510
|
-
const bestContentType = this.getBestContentType(data, ctx);
|
|
511
|
-
bestContentType && response.contentType(bestContentType);
|
|
512
|
-
|
|
513
|
-
if (this.types.has(bestContentType)) {
|
|
514
|
-
return this.types.get(bestContentType).transform(data, ctx);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
if (this.types.has(ANY_CONTENT_TYPE)) {
|
|
518
|
-
return this.types.get(ANY_CONTENT_TYPE).transform(data, ctx);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
return data;
|
|
522
|
-
}
|
|
523
|
-
/**
|
|
524
|
-
* Serialize data from endpoint metadata
|
|
525
|
-
* @param data
|
|
526
|
-
* @param ctx
|
|
527
|
-
*/
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
async serialize(data, ctx) {
|
|
531
|
-
const {
|
|
532
|
-
response,
|
|
533
|
-
endpoint
|
|
534
|
-
} = ctx;
|
|
535
|
-
|
|
536
|
-
if (endpoint) {
|
|
537
|
-
if (endpoint.view) {
|
|
538
|
-
data = await renderView(data, ctx);
|
|
539
|
-
} else if (isSerializable(data)) {
|
|
540
|
-
data = serialize(data, _extends$1({}, endpoint.getResponseOptions(response.statusCode), {
|
|
541
|
-
additionalProperties: this.additionalProperties,
|
|
542
|
-
useAlias: true,
|
|
543
|
-
endpoint: true
|
|
544
|
-
}));
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
return data;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
};
|
|
552
|
-
|
|
553
|
-
__decorate([Inject(), __metadata("design:type", InjectorService)], PlatformResponseFilter.prototype, "injector", void 0);
|
|
554
|
-
|
|
555
|
-
__decorate([Constant("responseFilters", []), __metadata("design:type", Array)], PlatformResponseFilter.prototype, "responseFilters", void 0);
|
|
556
|
-
|
|
557
|
-
__decorate([Constant("additionalProperties"), __metadata("design:type", Boolean)], PlatformResponseFilter.prototype, "additionalProperties", void 0);
|
|
558
|
-
|
|
559
|
-
PlatformResponseFilter = __decorate([Injectable()], PlatformResponseFilter);
|
|
560
|
-
|
|
561
|
-
export { ANY_CONTENT_TYPE, PlatformResponseFilter, ResponseFilter, ResponseFiltersContainer, getContentType, registerResponseFilter };
|
|
562
|
-
//# sourceMappingURL=index.modern.js.map
|
package/lib/index.modern.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.modern.js","sources":["../src/domain/ResponseFiltersContainer.ts","../src/decorators/responseFilter.ts","../src/utils/getContentType.ts","../../../specs/json-mapper/lib/index.modern.js","../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 { __decorate } from 'tslib';\nimport { isBoolean, objectKeys, isCollection, isEmpty, isArray, nameOf, isNil, classOf, isClass, isClassObject, isFunction } from '@tsed/core';\nimport { BadRequest } from '@tsed/exceptions';\nimport { JsonEntityFn, JsonEntityStore, getProperties, alterIgnore, JsonSchema, getPropertiesStores } from '@tsed/schema';\n\n/**\n * @ignore\n */\n// tslint:disable-next-line:variable-name\nconst JsonMapperTypesContainer = new Map();\n/**\n * @ignore\n */\n\nfunction registerJsonTypeMapper(type, token) {\n JsonMapperTypesContainer.set(type, new token());\n}\n/**\n * @ignore\n */\n\nfunction getJsonMapperTypes() {\n return JsonMapperTypesContainer;\n}\n\n/**\n * Register a new JsonMapper Type\n * @param types\n * @constructor\n */\n\nfunction JsonMapper(...types) {\n return target => {\n types.forEach(type => {\n registerJsonTypeMapper(type, target);\n });\n };\n}\n\n/**\n * Mapper for `Array` type.\n * @jsonmapper\n * @component\n */\n\nlet ArrayMapper = class ArrayMapper {\n deserialize(data, options) {\n return [].concat(data).map(item => options.next(item));\n }\n\n serialize(data, options) {\n return [].concat(data).map(item => options.next(item));\n }\n\n};\nArrayMapper = __decorate([JsonMapper(Array)], ArrayMapper);\n\n/**\n * Mapper for `Date` type.\n * @jsonmapper\n * @component\n */\n\nlet DateMapper = class DateMapper {\n deserialize(data) {\n // don't convert unexpected data. In normal case, Ajv reject unexpected data.\n // But by default, we have to skip data deserialization and let user to apply\n // the right mapping\n if (isBoolean(data) || data === null || data === undefined) {\n return data;\n }\n\n return new Date(data);\n }\n\n serialize(object) {\n return new Date(object).toISOString();\n }\n\n};\nDateMapper = __decorate([JsonMapper(Date)], DateMapper);\n\n/**\n * Mapper for `Map` type.\n * @jsonmapper\n * @component\n */\n\nlet MapMapper = class MapMapper {\n deserialize(data, ctx) {\n const obj = new Map();\n objectKeys(data).forEach(key => {\n obj.set(key, ctx.next(data[key]));\n });\n return obj;\n }\n\n serialize(data, ctx) {\n const obj = {};\n data.forEach((value, key) => obj[key] = ctx.next(value));\n return obj;\n }\n\n};\nMapMapper = __decorate([JsonMapper(Map)], MapMapper);\n\n/**\n * Mapper for the `String`, `Number` and `Boolean` types.\n * @jsonmapper\n * @component\n */\n\nlet PrimitiveMapper = class PrimitiveMapper {\n deserialize(data, ctx) {\n switch (ctx.type) {\n case String:\n return data === null ? null : \"\" + data;\n\n case Number:\n if ([null, \"null\"].includes(data)) return null;\n const n = +data;\n\n if (isNaN(n)) {\n throw new BadRequest(\"Cast error. Expression value is not a number.\");\n }\n\n return n;\n\n case Boolean:\n if ([\"true\", \"1\", true].includes(data)) return true;\n if ([\"false\", \"0\", false].includes(data)) return false;\n if ([null, \"null\"].includes(data)) return null;\n if (data === undefined) return undefined;\n return !!data;\n }\n }\n\n serialize(object) {\n return object;\n }\n\n};\nPrimitiveMapper = __decorate([JsonMapper(String, Number, Boolean)], PrimitiveMapper);\n\n/**\n * Mapper for the `Set` Type.\n * @jsonmapper\n * @component\n */\n\nlet SetMapper = class SetMapper {\n deserialize(data, ctx) {\n const obj = new Set();\n objectKeys(data).forEach(key => {\n obj.add(ctx.next(data[key]));\n });\n return obj;\n }\n\n serialize(data, ctx) {\n const array = [];\n data.forEach(value => array.push(ctx.next(value)));\n return array;\n }\n\n};\nSetMapper = __decorate([JsonMapper(Set)], SetMapper);\n\n/**\n * Mapper for the `Symbol` type.\n *\n * @jsonmapper\n * @component\n */\n\nlet SymbolMapper = class SymbolMapper {\n deserialize(data) {\n return Symbol.for(data);\n }\n\n serialize(object) {\n return object.toString().replace(\"Symbol(\", \"\").replace(\")\", \"\");\n }\n\n};\nSymbolMapper = __decorate([JsonMapper(Symbol)], SymbolMapper);\n\n/**\n * Call the function before property deserialization.\n *\n * ## Example\n *\n * ```typescript\n * class Model {\n * @OnDeserialize(v => v + 1)\n * property: string;\n * }\n * ```\n *\n * @returns {Function}\n * @decorator\n * @schema\n * @property\n * @param cb\n */\n\nfunction OnDeserialize(cb) {\n return JsonEntityFn(storedJson => {\n storedJson.schema.$hooks.on(\"onDeserialize\", cb);\n });\n}\n\n/**\n * Call the function before property serialization.\n *\n * ## Example\n *\n * ```typescript\n * class Model {\n * @OnSerialize(v => v + 1)\n * property: string;\n * }\n * ```\n *\n * @returns {Function}\n * @decorator\n * @schema\n * @property\n * @param cb\n */\n\nfunction OnSerialize(cb) {\n return JsonEntityFn(storedJson => {\n storedJson.schema.$hooks.on(\"onSerialize\", cb);\n });\n}\n\n/**\n * Call the function after JsonMapper.\n *\n * ## Example\n *\n * ```typescript\n * @AfterDeserialize((data: Model) => { // After deserialize get the instance class\n * if (data.prop1 === 'VALUE' && data.prop2 !== 'VALUE2') {\n * throw BadRequest('MyMessage'); // or throw a ValidationError\n * } else {\n * data.prop2 = 'VALUE2';\n * return data;\n * }\n * })\n * class Model {\n * @Property()\n * prop1: string;\n * @Property()\n * prop2: string;\n * }\n * ```\n *\n * @returns {Function}\n * @decorator\n * @schema\n * @property\n * @param cb\n */\n\nfunction AfterDeserialize(cb) {\n return JsonEntityFn(storedJson => {\n storedJson.schema.$hooks.on(\"afterDeserialize\", cb);\n });\n}\n\n/**\n * Call the function before JsonMapper.\n *\n * ## Example\n *\n * ```typescript\n * @BeforeDeserialize((data: Record<string, unknown>) => { // Before deserialize get the data\n * if (data.prop1 === 'VALUE' && data.prop2 !== 'VALUE2') {\n * throw BadRequest('MyMessage'); // or throw a ValidationError\n * } else {\n * data.prop2 = 'VALUE2';\n * return data;\n * }\n * })\n * class Model {\n * @Property()\n * prop1: string;\n * @Property()\n * prop2: string;\n * }\n * ```\n *\n * @returns {Function}\n * @decorator\n * @schema\n * @property\n * @param cb\n */\n\nfunction BeforeDeserialize(cb) {\n return JsonEntityFn(storedJson => {\n storedJson.schema.$hooks.on(\"beforeDeserialize\", cb);\n });\n}\n\nfunction _extends() {\n _extends = Object.assign || function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n };\n\n return _extends.apply(this, arguments);\n}\n\nfunction _objectWithoutPropertiesLoose(source, excluded) {\n if (source == null) return {};\n var target = {};\n var sourceKeys = Object.keys(source);\n var key, i;\n\n for (i = 0; i < sourceKeys.length; i++) {\n key = sourceKeys[i];\n if (excluded.indexOf(key) >= 0) continue;\n target[key] = source[key];\n }\n\n return target;\n}\n\n/**\n * @ignore\n */\n\nclass JsonMapperContext {\n constructor({\n type,\n collectionType,\n next,\n options\n }) {\n this.type = type;\n this.collectionType = isCollection(collectionType) ? collectionType : undefined;\n this._next = next;\n this.options = options;\n }\n\n next(data) {\n return this._next(data, _extends({}, this.options, {\n type: this.type\n }));\n }\n\n}\n\nfunction alterAfterDeserialize(data, schema, options) {\n var _schema$$hooks;\n\n return schema == null ? void 0 : (_schema$$hooks = schema.$hooks) == null ? void 0 : _schema$$hooks.alter(\"afterDeserialize\", data, [options]);\n}\n\nfunction alterBeforeDeserialize(data, schema, options) {\n var _schema$$hooks;\n\n return schema == null ? void 0 : (_schema$$hooks = schema.$hooks) == null ? void 0 : _schema$$hooks.alter(\"beforeDeserialize\", data, [options]);\n}\n\nconst _excluded$1 = [\"collectionType\"],\n _excluded2$1 = [\"type\"],\n _excluded3 = [\"type\", \"store\"];\n\nfunction isDeserializable(obj, options) {\n if (!!options.collectionType && isNil(obj) || obj === undefined) {\n return false;\n }\n\n return !(isEmpty(options.type) || options.type === Object && !options.collectionType);\n}\n\nfunction alterValue$1(schema, value, options) {\n return schema.$hooks.alter(\"onDeserialize\", value, [options]);\n}\n\nfunction transformCollection(src, options) {\n var _types$get;\n\n const {\n types,\n type = Object,\n collectionType\n } = options;\n const context = new JsonMapperContext({\n type,\n collectionType,\n options,\n next: (data, _ref) => {\n let options = _objectWithoutPropertiesLoose(_ref, _excluded$1);\n\n return deserialize(data, options);\n }\n });\n return types == null ? void 0 : (_types$get = types.get(options.collectionType)) == null ? void 0 : _types$get.deserialize(src, context);\n}\n\nfunction transformType(src, options) {\n var _types$get2;\n\n const {\n types,\n type = Object\n } = options;\n const context = new JsonMapperContext({\n type,\n options,\n next: (data, _ref2) => {\n let options = _objectWithoutPropertiesLoose(_ref2, _excluded2$1);\n\n return deserialize(data, options);\n }\n });\n return types == null ? void 0 : (_types$get2 = types.get(type)) == null ? void 0 : _types$get2.deserialize(src, context);\n}\n/**\n * Transform given plain object to class.\n * @param src\n * @param options\n */\n\n\nfunction plainObjectToClass(src, options) {\n if (isEmpty(src)) {\n return src;\n }\n\n const {\n type,\n store = JsonEntityStore.from(type)\n } = options,\n next = _objectWithoutPropertiesLoose(options, _excluded3);\n\n const propertiesMap = getProperties(store, _extends({}, options, {\n withIgnoredProps: true\n }));\n let keys = objectKeys(src);\n const additionalProperties = propertiesMap.size ? !!store.schema.get(\"additionalProperties\") || options.additionalProperties : true;\n src = alterBeforeDeserialize(src, store.schema, options);\n const out = new type(src);\n propertiesMap.forEach(propStore => {\n const key = options.useAlias ? propStore.parent.schema.getAliasOf(propStore.propertyName) || propStore.propertyName : propStore.propertyName;\n keys = keys.filter(k => k !== key);\n next.type = propStore.computedType;\n\n if (alterIgnore(propStore.itemSchema, options)) {\n return;\n }\n\n let value = alterValue$1(propStore.schema, src[key], _extends({}, options, {\n self: src\n }));\n\n if (propStore.schema.hasGenerics) {\n next.nestedGenerics = propStore.schema.nestedGenerics;\n } else if (propStore.schema.isGeneric && options.nestedGenerics) {\n const [genericTypes = [], ...nestedGenerics] = options.nestedGenerics;\n const genericLabels = propStore.parent.schema.genericLabels || [];\n next.type = genericTypes[genericLabels.indexOf(propStore.schema.genericType)] || Object;\n\n if (next.type instanceof JsonSchema) {\n next.type = next.type.getTarget();\n }\n\n next.nestedGenerics = nestedGenerics;\n }\n\n value = deserialize(value, _extends({}, next, {\n type: value === src[key] ? next.type : undefined,\n collectionType: propStore.collectionType\n }));\n\n if (value !== undefined) {\n out[propStore.propertyName] = value;\n }\n });\n\n if (additionalProperties) {\n keys.forEach(key => {\n out[key] = src[key];\n });\n }\n\n return alterAfterDeserialize(out, store.schema, options);\n}\n\nfunction buildOptions(options) {\n if (options.store instanceof JsonEntityStore) {\n if (options.store.parameter && options.store.parameter.nestedGenerics.length) {\n options.nestedGenerics = options.store.parameter.nestedGenerics;\n }\n\n options.type = options.store.computedType;\n options.collectionType = options.store.collectionType;\n delete options.store;\n }\n\n return _extends({\n groups: false,\n useAlias: true\n }, options, {\n type: options.type ? options.type : undefined,\n types: options.types ? options.types : getJsonMapperTypes()\n });\n}\n/**\n * Transform given source to class base on the given `options.type`.\n *\n * @param src\n * @param options\n */\n\n\nfunction deserialize(src, options = {}) {\n var _options$types2;\n\n options = buildOptions(options);\n\n if (!isDeserializable(src, options)) {\n return src;\n }\n\n if (!options.collectionType && isArray(src)) {\n options.collectionType = Array;\n }\n\n if (options.collectionType) {\n var _options$types;\n\n if (!((_options$types = options.types) != null && _options$types.has(options.collectionType))) {\n throw new Error(`${nameOf(options.collectionType)} is not supported by JsonMapper.`);\n }\n\n return transformCollection(src, options);\n }\n\n if ((_options$types2 = options.types) != null && _options$types2.has(options.type)) {\n return transformType(src, options);\n } // class converter\n\n\n return plainObjectToClass(src, options);\n}\n\nconst _excluded = [\"useAlias\", \"type\"],\n _excluded2 = [\"type\", \"collectionType\", \"groups\"];\n\nfunction alterValue(schema, value, options) {\n return schema.$hooks.alter(\"onSerialize\", value, [options]);\n}\n\nfunction getSchemaProperties(storedJson, obj) {\n const stores = Array.from(getPropertiesStores(storedJson).entries());\n\n if (!stores.length) {\n // fallback to auto discovering field from obj\n objectKeys(obj).forEach(key => {\n const propStore = JsonEntityStore.from(classOf(storedJson.target), key);\n stores.push([key, propStore]);\n });\n }\n\n return stores;\n}\n\nfunction getObjectProperties(obj) {\n return Object.entries(obj).filter(([, value]) => !isFunction(value));\n}\n\nfunction getType(propStore, value) {\n if (isNil(value) || propStore.type === Object || isCollection(propStore.type)) {\n return undefined;\n }\n\n return propStore.type;\n}\n\nfunction classToPlainObject(obj, options) {\n const {\n useAlias = true,\n type\n } = options,\n props = _objectWithoutPropertiesLoose(options, _excluded);\n\n const entity = JsonEntityStore.from(type || obj);\n return getSchemaProperties(entity, obj).reduce((newObj, [key, propStore]) => {\n const schema = propStore.schema;\n\n if (alterIgnore(schema, _extends({\n useAlias\n }, props, {\n self: obj\n }))) {\n return newObj;\n }\n\n let value = alterValue(schema, obj[key], _extends({\n useAlias\n }, props, {\n self: obj\n }));\n value = serialize(value, _extends({\n useAlias,\n type: value === obj[key] ? getType(propStore, value) : undefined,\n collectionType: propStore.collectionType\n }, props));\n\n if (value === undefined) {\n return newObj;\n }\n\n key = useAlias ? propStore.parent.schema.getAliasOf(key) || key : key;\n return _extends({}, newObj, {\n [key]: value\n });\n }, {});\n}\n\nfunction toObject(obj, options) {\n return getObjectProperties(obj).reduce((newObj, [key, value]) => _extends({}, newObj, {\n [key]: serialize(value, options)\n }), {});\n}\n\nfunction serialize(obj, _ref = {}) {\n let {\n type,\n groups = false\n } = _ref,\n options = _objectWithoutPropertiesLoose(_ref, _excluded2);\n\n const types = options.types ? options.types : getJsonMapperTypes(); // prevent Object metadata assignation. TypeScript set Object by default on endpoint.type\n\n type = type === Object ? undefined : type;\n options.groups = groups;\n\n if (isEmpty(obj)) {\n return obj;\n } // FIX custom serialization function from @tsed/mongoose\n\n\n if (typeof obj.toJSON === \"function\" && obj.$isMongooseModelPrototype) {\n return obj.toJSON(options);\n }\n\n if (typeof obj.toJSON === \"function\") {\n return serialize(obj.toJSON(), _extends({}, options, {\n type: classOf(obj)\n }));\n }\n\n if (type && isClass(type)) {\n options.type = type;\n }\n\n if (isCollection(obj) && !options.collectionType) {\n type = classOf(obj);\n options.collectionType = type;\n }\n\n type = classOf(type || obj);\n const context = new JsonMapperContext({\n type,\n options,\n next: data => serialize(data, _extends({}, options, {\n collectionType: undefined,\n type: options.type\n }))\n });\n\n if (types.has(type)) {\n const jsonMapper = types.get(type);\n return jsonMapper.serialize(obj, context);\n }\n\n if (isArray(obj)) {\n var _types$get;\n\n // Serialize Array class like\n return (_types$get = types.get(Array)) == null ? void 0 : _types$get.serialize(obj, context);\n }\n\n return !isClassObject(classOf(type)) ? classToPlainObject(obj, options) : toObject(obj, options);\n}\n\nexport { AfterDeserialize, ArrayMapper, BeforeDeserialize, DateMapper, JsonMapper, JsonMapperContext, MapMapper, OnDeserialize, OnSerialize, PrimitiveMapper, SetMapper, SymbolMapper, classToPlainObject, deserialize, getJsonMapperTypes, plainObjectToClass, registerJsonTypeMapper, serialize };\n//# sourceMappingURL=index.modern.js.map\n","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 {serialize} from \"@tsed/json-mapper\";\nimport {renderView} from \"@tsed/platform-views\";\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 @Constant(\"additionalProperties\")\n private additionalProperties: boolean;\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 /**\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\n const bestContentType = this.getBestContentType(data, ctx);\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 /**\n * Serialize data from endpoint metadata\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 = serialize(data, {\n ...endpoint.getResponseOptions(response.statusCode),\n additionalProperties: this.additionalProperties,\n useAlias: true,\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","JsonMapperTypesContainer","registerJsonTypeMapper","getJsonMapperTypes","PlatformResponseFilter","constructor","types","keys","$onInit","responseFilters","includes","injector","get","getBestContentType","request","bestContentType","accepts","concat","filter","Boolean","transform","has","serialize","renderView","isSerializable","getResponseOptions","additionalProperties","useAlias","__decorate","Inject","InjectorService","Constant","Injectable"],"mappings":"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"}
|