UNPKG

json-api-nestjs

Version:
222 lines 9.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JsonApiTransformerService = void 0; const tslib_1 = require("tslib"); const common_1 = require("@nestjs/common"); const core_1 = require("@nestjs/core"); const nestjs_shared_1 = require("../../../utils/nestjs-shared"); const constants_1 = require("../../../constants"); const route_path_factory_1 = require("@nestjs/core/router/route-path-factory"); (0, common_1.Injectable)(); class JsonApiTransformerService { applicationConfig; entityMapProps; currentEntity; _urlPath; _currentMapProps; get currentMapProps() { if (!this._currentMapProps) { const result = this.entityMapProps.get(this.currentEntity); if (!result) throw new Error('Not found map for ' + this.currentEntity.name); this._currentMapProps = result; } return this._currentMapProps; } get urlPath() { if (this._urlPath) return [...this._urlPath]; this._urlPath = ['']; const prefix = this.applicationConfig.getGlobalPrefix(); const version = this.applicationConfig.getVersioning(); const routePathFactory = new route_path_factory_1.RoutePathFactory(this.applicationConfig); if (prefix) { this._urlPath.push(this.applicationConfig.getGlobalPrefix()); } if (version && version.type === common_1.VersioningType.URI) { const firstVersion = Array.isArray(version.defaultVersion) ? version.defaultVersion[0] : version.defaultVersion; if (firstVersion) { this._urlPath.push(`${routePathFactory.getVersionPrefix(version)}${firstVersion.toString()}`); } } return [...this._urlPath]; } transformData(data, query) { if (Array.isArray(data)) { const resultData = { data: data.map((item) => this.transformItem(item, this.currentMapProps, query)), }; if (query.include) { resultData.included = this.extractIncluded(data, query); } return resultData; } const resultData = { data: this.transformItem(data, this.currentMapProps, query), }; if (query.include) { resultData.included = this.extractIncluded([data], query); } return resultData; } transformItem(item, mapProps, query) { const { fields } = query; const target = Reflect.get(fields || {}, 'target'); return { id: item[mapProps.primaryColumnName].toString(), type: mapProps.typeName, attributes: this.extractAttributes(item, mapProps.props.filter((i) => { if (i === mapProps.primaryColumnName) { return false; } if (!target) { return true; } return target.includes(i); })), links: { self: this.getLink(mapProps.typeName, item[mapProps.primaryColumnName]), }, relationships: this.transformRelationships(item, mapProps, query), }; } transformRel(item, rel) { const relProps = Reflect.get(this.currentMapProps.relationProperty, rel); const relationMapPops = this.entityMapProps.get(relProps.entityClass); if (!relationMapPops) throw new Error('Not found props map for ' + relProps.entityClass); const props = item[rel]; if (Array.isArray(props)) { return props.map((i) => ({ type: relationMapPops.typeName, id: i[relationMapPops.primaryColumnName].toString(), })); } else { return props ? { type: relationMapPops.typeName, id: props[relationMapPops.primaryColumnName].toString(), } : null; } } transformRelationships(item, mapProps, query) { const { include } = query; const includeMap = new Map((include || []).map((i) => [i, true])); return mapProps.relations.reduce((acum, i) => { acum[i] = { links: { self: this.getLink(mapProps.typeName, item[mapProps.primaryColumnName], 'relationships', i), }, }; if (includeMap.has(i)) { const relationMapPops = this.entityMapProps.get(mapProps.relationProperty[i].entityClass); if (!relationMapPops) throw new Error('Not found props map for ' + mapProps.relationProperty[i].entityClass.name); if (mapProps.relationProperty[i].isArray) { if (item[i] && Array.isArray(item[i]) && item[i].length > 0) { // @ts-expect-error incorrect parse acum[i]['data'] = item[i].map((rel) => ({ id: rel[relationMapPops.primaryColumnName].toString(), type: relationMapPops.typeName, })); } else { // @ts-expect-error incorrect parse acum[i]['data'] = []; } } else { // @ts-expect-error incorrect parse acum[i]['data'] = item[i] ? { id: item[i][relationMapPops.primaryColumnName].toString(), type: relationMapPops.typeName, } : null; } } return acum; }, {}); } extractAttributes(item, fields) { const mapFields = fields.reduce((acum, field) => { acum[field.toString()] = true; return acum; }, {}); return nestjs_shared_1.ObjectTyped.entries(item).reduce((acum, [name, value]) => { if (name in mapFields && mapFields[name.toString()]) { // @ts-expect-error assign key to object entity acum[name] = value; } return acum; }, {}); } extractIncluded(data, query) { const includeArray = []; const { include } = query; if (!include) return []; for (const relationPropsFromInclude of include) { const relationProps = this.currentMapProps.relationProperty[relationPropsFromInclude]; if (!relationProps) continue; const relationMapProp = this.entityMapProps.get(relationProps.entityClass); if (!relationMapProp) throw new Error('Not found props for relation ' + relationPropsFromInclude + 'in' + this.currentEntity.name); const { fields } = query; const selectFieldForInclude = Reflect.get(fields || {}, relationPropsFromInclude); const queryForInclude = { ...query, fields: { target: selectFieldForInclude && Array.isArray(selectFieldForInclude) && selectFieldForInclude.length > 0 ? selectFieldForInclude : null, }, include: null, }; for (const dataItem of data) { const propRel = dataItem[relationPropsFromInclude]; if (!propRel) continue; if (Array.isArray(propRel)) { for (const i of propRel) { includeArray.push(this.transformItem(i, relationMapProp, queryForInclude)); } } else { includeArray.push(this.transformItem(propRel, relationMapProp, queryForInclude)); } } } return includeArray; } getLink(...partOfUrl) { const urlPath = this.urlPath; urlPath.push(...partOfUrl); return urlPath.join('/'); } } exports.JsonApiTransformerService = JsonApiTransformerService; tslib_1.__decorate([ (0, common_1.Inject)(core_1.ApplicationConfig), tslib_1.__metadata("design:type", core_1.ApplicationConfig) ], JsonApiTransformerService.prototype, "applicationConfig", void 0); tslib_1.__decorate([ (0, common_1.Inject)(constants_1.ENTITY_MAP_PROPS), tslib_1.__metadata("design:type", Map) ], JsonApiTransformerService.prototype, "entityMapProps", void 0); tslib_1.__decorate([ (0, common_1.Inject)(constants_1.CURRENT_ENTITY), tslib_1.__metadata("design:type", Object) ], JsonApiTransformerService.prototype, "currentEntity", void 0); //# sourceMappingURL=json-api-transformer.service.js.map