@tsed/platform-response-filter 7.0.0-alpha.2 → 7.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/lib/cjs/decorators/responseFilter.js +23 -0
  2. package/lib/cjs/decorators/responseFilter.js.map +1 -0
  3. package/lib/cjs/domain/ResponseFiltersContainer.js +16 -0
  4. package/lib/cjs/domain/ResponseFiltersContainer.js.map +1 -0
  5. package/lib/cjs/errors/TemplateRenderError.js +23 -0
  6. package/lib/cjs/errors/TemplateRenderError.js.map +1 -0
  7. package/lib/cjs/index.js +15 -0
  8. package/lib/cjs/index.js.map +1 -0
  9. package/lib/cjs/interfaces/ResponseFilterMethods.js +3 -0
  10. package/lib/cjs/interfaces/ResponseFilterMethods.js.map +1 -0
  11. package/lib/cjs/services/PlatformResponseFilter.js +94 -0
  12. package/lib/cjs/services/PlatformResponseFilter.js.map +1 -0
  13. package/lib/cjs/utils/getContentType.js +28 -0
  14. package/lib/cjs/utils/getContentType.js.map +1 -0
  15. package/lib/cjs/utils/renderView.js +17 -0
  16. package/lib/cjs/utils/renderView.js.map +1 -0
  17. package/lib/esm/decorators/responseFilter.js +19 -0
  18. package/lib/esm/decorators/responseFilter.js.map +1 -0
  19. package/lib/esm/domain/ResponseFiltersContainer.js +12 -0
  20. package/lib/esm/domain/ResponseFiltersContainer.js.map +1 -0
  21. package/lib/esm/errors/TemplateRenderError.js +19 -0
  22. package/lib/esm/errors/TemplateRenderError.js.map +1 -0
  23. package/lib/esm/index.js +12 -0
  24. package/lib/esm/index.js.map +1 -0
  25. package/lib/esm/interfaces/ResponseFilterMethods.js +2 -0
  26. package/lib/esm/interfaces/ResponseFilterMethods.js.map +1 -0
  27. package/lib/esm/services/PlatformResponseFilter.js +91 -0
  28. package/lib/esm/services/PlatformResponseFilter.js.map +1 -0
  29. package/lib/esm/utils/getContentType.js +24 -0
  30. package/lib/esm/utils/getContentType.js.map +1 -0
  31. package/lib/esm/utils/renderView.js +13 -0
  32. package/lib/esm/utils/renderView.js.map +1 -0
  33. package/lib/{decorators → types/decorators}/responseFilter.d.ts +0 -0
  34. package/lib/{domain → types/domain}/ResponseFiltersContainer.d.ts +0 -0
  35. package/lib/types/errors/TemplateRenderError.d.ts +14 -0
  36. package/lib/{index.d.ts → types/index.d.ts} +2 -0
  37. package/lib/{interfaces → types/interfaces}/ResponseFilterMethods.d.ts +0 -0
  38. package/lib/{services → types/services}/PlatformResponseFilter.d.ts +1 -1
  39. package/lib/{utils → types/utils}/getContentType.d.ts +0 -0
  40. package/lib/types/utils/renderView.d.ts +2 -0
  41. package/package.json +23 -20
  42. package/tsconfig.compile.esm.json +23 -0
  43. package/lib/index.js +0 -566
  44. package/lib/index.js.map +0 -1
  45. package/lib/index.modern.js +0 -562
  46. 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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"}
@@ -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
@@ -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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"}