From e20d6c7174bb837e53bb2fc89e39f3f73ee18798 Mon Sep 17 00:00:00 2001 From: HodzicAdem Date: Thu, 11 Jul 2019 21:16:57 +0200 Subject: [PATCH 1/2] feat(ever-api): adding support for multiple databases --- backend/api/src/@pyro/db-server/db-service.ts | 21 +- .../src/@pyro/db-server/typeorm-service.ts | 361 ++++++++++++++++++ backend/api/src/app.module.ts | 27 +- backend/api/src/main.ts | 9 +- backend/api/src/nest-bootstrap.ts | 2 + .../api/src/services/admins/AdminsService.ts | 24 +- .../src/services/carriers/CarriersService.ts | 62 +-- .../src/services/devices/DevicesService.ts | 18 +- backend/api/src/services/inversify.config.ts | 74 +++- .../invites/InvitesRequestsService.ts | 13 +- .../src/services/invites/InvitesService.ts | 17 +- .../api/src/services/orders/OrdersService.ts | 13 +- .../products/ProductsCategoriesService.ts | 46 ++- .../src/services/products/ProductsService.ts | 18 +- backend/api/src/services/services.app.ts | 50 ++- .../api/src/services/users/UsersService.ts | 14 +- .../services/warehouses/WarehousesService.ts | 14 +- package.json | 1 + shared/core-angular/typeorm-placeholder.ts | 14 + shared/core/@pyro/db/db-create-object.ts | 2 +- shared/core/@pyro/db/db-object.ts | 38 +- shared/core/@pyro/db/db-raw-object.ts | 2 +- shared/core/@pyro/db/types.ts | 2 +- shared/core/entities/Admin.ts | 6 +- shared/core/entities/Carrier.ts | 2 +- shared/core/entities/Product.ts | 4 +- shared/core/entities/ProductsCategory.ts | 4 +- shared/core/entities/Warehouse.ts | 2 +- .../core/routers/IProductsCategoryRouter.ts | 16 +- yarn.lock | 24 +- 30 files changed, 752 insertions(+), 148 deletions(-) create mode 100644 backend/api/src/@pyro/db-server/typeorm-service.ts diff --git a/backend/api/src/@pyro/db-server/db-service.ts b/backend/api/src/@pyro/db-server/db-service.ts index f63e33f6e..0dd3de8a3 100644 --- a/backend/api/src/@pyro/db-server/db-service.ts +++ b/backend/api/src/@pyro/db-server/db-service.ts @@ -222,17 +222,18 @@ export abstract class DBService> if (lastValue == null) { throw new Error(".remove(objectId) error - Object don't exist"); } else { - this.existence.next({ - id: objectId, - value: null, - lastValue, - type: ExistenceEventType.Removed - }); + const callId = uuid(); - this.log.info( - { callId, objectId, lastValue }, - '.remove(objectId) removed object' - ); + this.log.info({ callId }, '.removeAll() called!'); + + try { + await this.Model.remove({}).exec(); + } catch (err) { + this.log.error({ callId, err }, '.removeAll() thrown error!'); + throw err; + } + + this.log.info({ callId }, '.removeAll() removed all!'); } } diff --git a/backend/api/src/@pyro/db-server/typeorm-service.ts b/backend/api/src/@pyro/db-server/typeorm-service.ts new file mode 100644 index 000000000..342eae547 --- /dev/null +++ b/backend/api/src/@pyro/db-server/typeorm-service.ts @@ -0,0 +1,361 @@ +import { IDbService } from './i-db-service'; +import { Model, Document } from 'mongoose'; +import { Subject, Observable, from, of } from 'rxjs'; +import { ExistenceEvent, ExistenceEventType } from './existence'; +import { DBObject } from '@pyro/db'; +import { inject, injectable, optional, interfaces } from 'inversify'; +import { Repository, getRepository } from 'typeorm'; +import * as uuid from 'uuid'; +import * as Logger from 'bunyan'; +import * as _ from 'lodash'; + +import { RawObject } from '@pyro/db/db-raw-object'; +import { createEverLogger } from '../../helpers/Log'; +import { filter, map, share, concat, tap, exhaustMap } from 'rxjs/operators'; + +@injectable() +export class TypeORMService> + implements IDbService { + DBObject: { new (arg: T['CreateObjectTYPE']): T; modelName: string }; + + // TODO: Refactor IDbService so Model is not of type Model + Model: Model; + existence: Subject>; + protected readonly log: Logger = createEverLogger({ name: 'adminService' }); + + constructor( + @optional() + private _repository: Repository + ) { + this.existence = new Subject>(); + } + + async create(createObject: T['CreateObjectTYPE']): Promise { + const callId = uuid(); + + this.log.info({ callId, createObject }, '.create(createObject) called'); + + let object; + + try { + object = this._repository.create(createObject); + this._repository.save(object); + } catch (error) { + this.log.error( + { callId, createObject, error }, + '.create(createObject) thrown error!' + ); + throw error; + } + + this.existence.next({ + id: object.id, + value: object, + lastValue: null, + type: ExistenceEventType.Created + }); + + this.log.info( + { callId, createObject, object }, + '.create(createObject) created object' + ); + + return object as T; + } + async remove(objectId: string): Promise { + const callId = uuid(); + + this.log.info({ callId }, '.removeAll() called!'); + + try { + const object = await this._repository.findByIds([objectId]); + await this.repository.remove(object[0]); + } catch (err) { + this.log.error({ callId, err }, '.remove() thrown error!'); + throw err; + } + + this.log.info({ callId }, '.removeAll() removed all!'); + } + async removeMultiple(conditions: any): Promise { + const callId = uuid(); + + this.log.info( + { callId, conditions }, + '.removeMultiple(conditions) called' + ); + + let lastValues: T[]; + + try { + lastValues = await this._repository.find(conditions); + await this._repository.remove(lastValues); + } catch (err) { + this.log.error( + { callId, conditions, err }, + '.removeMultiple(conditions) thrown error!' + ); + throw err; + } + + lastValues.forEach((lastValue) => { + this.existence.next({ + id: lastValue.id, + lastValue, + value: null, + type: ExistenceEventType.Removed + }); + }); + + this.log.info( + { + callId, + conditions, + lastValues + }, + '.removeMultiple(conditions) removed objects' + ); + } + async removeAll(): Promise { + const callId = uuid(); + + this.log.info({ callId }, '.removeAll() called!'); + + try { + const objects = await this._repository.find(); + await this._repository.remove(objects); + } catch (err) { + this.log.error({ callId, err }, '.removeAll() thrown error!'); + throw err; + } + + this.log.info({ callId }, '.removeAll() removed all!'); + } + get(id: string): Observable { + const callId = uuid(); + + this.log.info({ objectId: id, callId }, '.get(id) called'); + + return from(this.getCurrent(id)).pipe( + concat( + this.existence.pipe( + filter((existenceEvent) => id === existenceEvent.id), + map((existenceEvent) => existenceEvent.value), + share() + ) + ), + tap({ + next: (obj) => { + this.log.info( + { + objectId: id, + object: obj, + callId + }, + '.get(id) emitted next value' + ); + }, + error: (err) => { + this.log.error( + { + objectId: id, + err, + callId + }, + '.get(id), emitted error!' + ); + } + }) + ); + } + async getCurrent(id: string): Promise { + const callId = uuid(); + + this.log.info({ objectId: id, callId }, '.getCurrent(id) called'); + + const obj = await this._repository.findByIds([id])[0]; + + return obj as RawObject; + } + getMultiple(ids: string[]): Observable { + const callId = uuid(); + + this.log.info({ objectIds: ids, callId }, '.getMultiple(ids) called'); + + return of(null).pipe( + concat( + this.existence.pipe( + filter((event) => _.includes(ids, event.id)), + share() + ) + ), + exhaustMap(() => this.getCurrentMultiple(ids)), + tap({ + next: (objects) => { + this.log.info( + { objectIds: ids, objects, callId }, + '.getMultiple(ids) emitted next value' + ); + }, + error: (err) => { + this.log.error( + { objectIds: ids, err, callId }, + '.getMultiple(ids), emitted error!' + ); + } + }) + ); + } + async getCurrentMultiple(ids: string[]): Promise { + const callId = uuid(); + + this.log.info( + { objectIds: ids, callId }, + '.getCurrentMultiple(ids) called' + ); + + const objs = await this._repository.findByIds(ids); + + return objs; + } + find(conditions: any): Promise { + return this._repository.find({ ...conditions }); + } + findOne(conditions: any): Promise { + return this._repository.findOne(conditions); + } + + async update(id: string, updateObj: any): Promise { + const callId = uuid(); + this.log.info( + { callId, id, updateObj }, + '.update(id, updateObj) called' + ); + + let beforeUpdateObject: T | null; + + let updatedObject: T; + + try { + beforeUpdateObject = await this.getCurrent(id); + + if (beforeUpdateObject != null) { + // const obj = (await this.Model.findByIdAndUpdate( + // id, + // updateObj as any, + // { new: true } + // ) + // .lean() + // .exec()) as RawObject; + let tempObject = await this._repository.update(id, { + ...updateObj + }); + updatedObject = tempObject as RawObject; + } else { + throw new Error( + `There is no such object with the id ${beforeUpdateObject}` + ); + } + } catch (err) { + this.log.error( + { callId, id, updateObj, err }, + '.update(id, updateObj) thrown error!' + ); + throw err; + } + + this.existence.next({ + id: id, + value: updatedObject, + lastValue: beforeUpdateObject, + type: ExistenceEventType.Updated + }); + + this.log.info( + { + callId, + id, + updateObj, + updatedValue: updatedObject, + lastValue: beforeUpdateObject + }, + '.update(objectId, updateObj) updated object' + ); + + return updatedObject; + } + async updateMultiple(findObj: any, updateObj: any): Promise { + const callId = uuid(); + this.log.info( + { callId, findObj, updateObj }, + '.updateMultiple(findObj, updateObj) called' + ); + + let lastValues: any[]; + let updatedObjects: any[]; + + try { + lastValues = await this.find(findObj); + + lastValues.forEach((obj) => { + obj = { ...obj, ...updateObj }; + obj.save(); + updatedObjects.push(obj); + }); + } catch (err) { + this.log.error( + { callId, findObj, updateObj, err }, + '.updateMultiple(findObj, updateObj) thrown error!' + ); + throw err; + } + + lastValues.forEach((lastValue) => { + const newValue = _.find( + updatedObjects, + (obj) => obj.id === lastValue.id + ) as T; + + this.existence.next({ + id: lastValue.id, + lastValue, + value: newValue, + type: ExistenceEventType.Updated + }); + }); + + this.log.info( + { + callId, + findObj, + updateObj, + lastValues, + updatedObjects + }, + '.updateMultiple(objectId, updateObj) updated objects' + ); + + return updatedObjects as T[]; + } + async updateMultipleByIds(ids: string[], updateObj: any): Promise { + const promises = ids.map((id) => this.update(id, updateObj)); + return Promise.all(promises); + } + count(conditions: any): Promise { + return this._repository.count(conditions); + } + + public set repository(repo: Repository) { + this._repository = repo; + } +} + +export const typeORMServiceFactory = (context: interfaces.Context) => { + return >(repository: Repository) => { + const service = context.container.get>( + TypeORMService + ); + service.repository = repository; + return service; + }; +}; diff --git a/backend/api/src/app.module.ts b/backend/api/src/app.module.ts index 84c12518e..52d1aebf1 100644 --- a/backend/api/src/app.module.ts +++ b/backend/api/src/app.module.ts @@ -58,7 +58,7 @@ export const CommandHandlers = [GetAboutUsHandler]; // Add here all CQRS event handlers export const EventHandlers = []; -const entities = ServicesApp.getEntities(); +// const entities = ServicesApp.getEntities(); @Module({ controllers: [TestController], @@ -71,20 +71,23 @@ const entities = ServicesApp.getEntities(); AdminsModule, ConfigModule, // configure TypeORM Connection which will be possible to use inside NestJS (e.g. resolvers) - TypeOrmModule.forRoot({ - type: 'mongodb', - host: 'localhost', - database: 'test', - entities, - synchronize: true, - useNewUrlParser: true, - autoReconnect: true, - logging: true - }), + // TypeOrmModule.forRoot({ + // type: 'mysql', + // host: 'localhost', + // port: 3306, + // database: 'test', + // username: 'ever', + // password: 'ever', + // entities, + // synchronize: true, + // // useNewUrlParser: true, + // // autoReconnect: true, + // logging: true + // }), // define which repositories shall be registered in the current scope (each entity will have own repository). // Thanks to that we can inject the XXXXRepository to the NestJS using the @InjectRepository() decorator // NOTE: this could be used inside NestJS only, not inside our services - TypeOrmModule.forFeature(entities), + // TypeOrmModule.forFeature(entities), SubscriptionsModule.forRoot(env.GQLPORT_SUBSCRIPTIONS), GraphQLModule.forRoot({ typePaths: ['./**/*.graphql'], diff --git a/backend/api/src/main.ts b/backend/api/src/main.ts index 37e3aea48..6c2cf421d 100644 --- a/backend/api/src/main.ts +++ b/backend/api/src/main.ts @@ -42,7 +42,7 @@ process.on('uncaughtException', (err) => { try { console.error("Can't write to log!!!!!!"); console.error(logWritingErr); - } catch (consoleWritingError) { } + } catch (consoleWritingError) {} } console.error(err); @@ -55,7 +55,7 @@ process.on('unhandledRejection', (err, promise) => { try { console.error("Can't write to log!!!!!!"); console.error(logWritingErr); - } catch (consoleWritingError) { } + } catch (consoleWritingError) {} } console.error(err); @@ -64,10 +64,11 @@ process.on('unhandledRejection', (err, promise) => { (mongoose as any).Promise = BluebirdPromise; (async () => { - // needs TypeORM connection to be ready before we initialize Services - await ServicesApp.CreateTypeORMConnection(); + await ServicesApp.createTypeORMConnection(); + // needs TypeORM connection to be ready before we initialize Services const app = servicesContainer.get(ServicesApp); + await app.start(); // load NestJS modules dynamically, because needs all services to be initialized before diff --git a/backend/api/src/nest-bootstrap.ts b/backend/api/src/nest-bootstrap.ts index b3e88eb35..4e262d7ca 100644 --- a/backend/api/src/nest-bootstrap.ts +++ b/backend/api/src/nest-bootstrap.ts @@ -36,6 +36,8 @@ export async function bootstrapNest(): Promise { SwaggerModule.setup('api', app, document); + console.log(`APP IS LISTENING ON PORT ${port}`); + await app.listen(port + ''); if (module.hot) { diff --git a/backend/api/src/services/admins/AdminsService.ts b/backend/api/src/services/admins/AdminsService.ts index eeddc7aa3..013819be5 100644 --- a/backend/api/src/services/admins/AdminsService.ts +++ b/backend/api/src/services/admins/AdminsService.ts @@ -1,4 +1,4 @@ -import { DBService } from '@pyro/db-server'; +import { DBService, IDbService } from '@pyro/db-server'; import Admin from '@modules/server.common/entities/Admin'; import { createEverLogger } from '../../helpers/Log'; import { AuthService, AuthServiceFactory } from '../auth'; @@ -12,6 +12,7 @@ import { asyncListener, observableListener } from '@pyro/io'; import { inject, injectable } from 'inversify'; import { first, map, switchMap } from 'rxjs/operators'; import { Repository } from 'typeorm'; +import { FindObject } from '@pyro/db/db-find-object'; // TODO: Rename! "Admin" is not a great name, but currently "Users" mean "Customers"... /** @@ -26,12 +27,16 @@ export class AdminsService extends DBService implements IAdminRouter { private readonly authService: AuthService; + private databaseService: IDbService; + constructor( @inject('Factory') authServiceFactory: AuthServiceFactory, // TypeORM Repository - temporary here, will be moved into DBService later @inject('AdminRepository') - private readonly _adminRepository: Repository + private readonly _adminRepository: Repository, + @inject('DatabaseService') + private databaseServiceFactory: (type) => IDbService ) { super(); @@ -45,6 +50,8 @@ export class AdminsService extends DBService implements IAdminRouter { console.log(e); }); + this.databaseService = this.databaseServiceFactory('Admin'); + this.authService = authServiceFactory({ role: 'admin', Entity: Admin, @@ -65,12 +72,13 @@ export class AdminsService extends DBService implements IAdminRouter { @asyncListener() async getByEmail(email: Admin['email']): Promise { - return super.findOne({ email, isDeleted: { $eq: false } }); + return this.databaseService.findOne({ email }); + // return super.findOne({ email, isDeleted: { $eq: false } }); } @asyncListener() async register(input: IAdminRegistrationInput): Promise { - const admin = await this.create({ + const admin = await this.databaseService.create({ ...input.admin, ...(input.password ? { @@ -139,4 +147,12 @@ export class AdminsService extends DBService implements IAdminRouter { throw Error(`Admin with id '${adminId}' does not exists!`); } } + + async count(findObj: FindObject): Promise { + return this.databaseService.count(findObj); + } + + async find(conditions: any): Promise { + return this.databaseService.find(conditions); + } } diff --git a/backend/api/src/services/carriers/CarriersService.ts b/backend/api/src/services/carriers/CarriersService.ts index e561eaddc..f6a15db41 100644 --- a/backend/api/src/services/carriers/CarriersService.ts +++ b/backend/api/src/services/carriers/CarriersService.ts @@ -2,7 +2,7 @@ import * as Logger from 'bunyan'; import CarrierStatus from '../../modules/server.common/enums/CarrierStatus'; import Carrier from '../../modules/server.common/entities/Carrier'; import { createEverLogger } from '../../helpers/Log'; -import { DBService } from '@pyro/db-server'; +import { DBService, IDbService } from '@pyro/db-server'; import { inject, injectable } from 'inversify'; import ICarrierRouter, { ICarrierLoginResponse, @@ -17,11 +17,12 @@ import { import IService from '../IService'; import GeoLocation from '../../modules/server.common/entities/GeoLocation'; import IGeoLocation from '../../modules/server.common/interfaces/IGeoLocation'; -import { concat, of, Observable } from 'rxjs'; +import { concat, of, Observable, from } from 'rxjs'; import { exhaustMap, filter, first, map, switchMap } from 'rxjs/operators'; import { env } from '../../env'; import { AuthService, AuthServiceFactory } from '../auth'; import IPagingOptions from '@modules/server.common/interfaces/IPagingOptions'; +import { Repository } from 'typeorm'; @injectable() @routerName('carrier') @@ -33,22 +34,36 @@ export class CarriersService extends DBService }); private readonly authService: AuthService; + private databaseService: IDbService; constructor( @inject('Factory') - private readonly authServiceFactory: AuthServiceFactory + private readonly authServiceFactory: AuthServiceFactory, + @inject('CarrierRepository') + private readonly _carrierRepository: Repository, + @inject('DatabaseService') + private databaseServiceFactory: (type) => IDbService ) { super(); + _carrierRepository + .count() + .then((c) => { + console.log('Cariers count: ' + c); + }) + .catch((e) => { + console.log(e); + }); this.authService = this.authServiceFactory({ role: 'carrier', Entity: Carrier, saltRounds: env.CARRIER_PASSWORD_BCRYPT_SALT_ROUNDS }); + this.databaseService = this.databaseServiceFactory('Carrier'); } @observableListener() get(id: Carrier['id']) { - return super.get(id).pipe( + return from(this.databaseService.get(id)).pipe( map(async (carrier) => { await this.throwIfNotExists(id); return carrier; @@ -67,24 +82,20 @@ export class CarriersService extends DBService } protected async _getAllActive() { - return super.find({ isActive: true, isDeleted: { $eq: false } }); + return this.databaseService.find({ isActive: true, isDeleted: false }); } async getMultipleByIds( carrierIds: string[] ): Promise> { - const carriers = await this.find({ - _id: { $in: carrierIds }, - isDeleted: { $eq: false } - }); - - const carriersIdsToReturn = carriers.map((c) => c.id); - return this.getMultiple(carriersIdsToReturn); + return this.databaseService + .getMultiple(carrierIds) + .pipe(map((arr) => arr.filter((elem) => !elem.isDeleted))); } @asyncListener() async register(input: ICarrierRegistrationInput) { - const carrier = await super.create({ + const carrier = await this.databaseService.create({ ...input.carrier, ...(input.password ? { @@ -130,7 +141,7 @@ export class CarriersService extends DBService status: CarrierStatus ): Promise { await this.throwIfNotExists(carrierId); - return super.update(carrierId, { status }); + return this.databaseService.update(carrierId, { status }); } @asyncListener() @@ -139,7 +150,7 @@ export class CarriersService extends DBService isActive: boolean ): Promise { await this.throwIfNotExists(carrierId); - return super.update(carrierId, { isActive }); + return this.databaseService.update(carrierId, { isActive }); } @asyncListener() @@ -149,7 +160,7 @@ export class CarriersService extends DBService geoLocation: GeoLocation ): Promise { await this.throwIfNotExists(carrierId); - return super.update(carrierId, { geoLocation }); + return this.databaseService.update(carrierId, { geoLocation }); } @asyncListener() @@ -158,7 +169,7 @@ export class CarriersService extends DBService updateObject: Partial ): Promise { await this.throwIfNotExists(id); - return super.update(id, updateObject); + return this.databaseService.update(id, updateObject); } async increaseNumberOfDeliveries( @@ -167,13 +178,13 @@ export class CarriersService extends DBService ): Promise { await this.throwIfNotExists(carrierId); - return super.update(carrierId, { - $inc: { numberOfDeliveries: n } + return this.databaseService.update(carrierId, { + numberOfDeliveries: n }); } async throwIfNotExists(carrierId: string) { - const carrier = await super + const carrier = await this.databaseService .get(carrierId) .pipe(first()) .toPromise(); @@ -189,15 +200,10 @@ export class CarriersService extends DBService sortObj[pagingOptions.sort.field] = pagingOptions.sort.sortBy; } - return this.Model.find({ + return this.databaseService.find({ ...findInput, - isDeleted: { $eq: false } - }) - .sort(sortObj) - .skip(pagingOptions.skip) - .limit(pagingOptions.limit) - .lean() - .exec(); + isDeleted: false + }); } } diff --git a/backend/api/src/services/devices/DevicesService.ts b/backend/api/src/services/devices/DevicesService.ts index d80f4e10d..ce0721a1e 100644 --- a/backend/api/src/services/devices/DevicesService.ts +++ b/backend/api/src/services/devices/DevicesService.ts @@ -1,4 +1,4 @@ -import { injectable } from 'inversify'; +import { injectable, inject } from 'inversify'; import { IDeviceCreateObject } from '@modules/server.common/interfaces/IDevice'; import Device from '@modules/server.common/entities/Device'; import { DBService } from '@pyro/db-server'; @@ -9,6 +9,7 @@ import IDeviceRouter from '@modules/server.common/routers/IDeviceRouter'; import ILanguage from '@modules/server.common/interfaces/ILanguage'; import IService from '../IService'; import { first, switchMap, map } from 'rxjs/operators'; +import { Repository } from 'typeorm'; @injectable() @routerName('device') @@ -18,6 +19,21 @@ export class DevicesService extends DBService protected readonly log = createEverLogger({ name: 'devicesService' }); + constructor( + @inject('DeviceRepository') + private readonly _deviceRepository: Repository + ) { + super(); + _deviceRepository + .count() + .then((c) => { + console.log('Devices count: ' + c); + }) + .catch((e) => { + console.log(e); + }); + } + @observableListener() get(id: string): Observable { return super.get(id).pipe( diff --git a/backend/api/src/services/inversify.config.ts b/backend/api/src/services/inversify.config.ts index 5509e48e4..0a622b7af 100644 --- a/backend/api/src/services/inversify.config.ts +++ b/backend/api/src/services/inversify.config.ts @@ -1,5 +1,5 @@ import 'reflect-metadata'; -import { Container, interfaces, ContainerModule } from 'inversify'; +import { Container, interfaces, ContainerModule, injectable } from 'inversify'; import * as _ from 'lodash'; import { IRoutersManager, RoutersManager, RouterSymbol } from '@pyro/io'; import { CarriersOrdersService, CarriersService } from './carriers'; @@ -39,6 +39,20 @@ import Admin from '@modules/server.common/entities/Admin'; import Device from '@modules/server.common/entities/Device'; import { FakeOrdersService } from './fake-data/FakeOrdersService'; import { CurrenciesService } from './currency/CurrencyService'; +import Product from '@modules/server.common/entities/Product'; +import { ObjectLiteralExpression } from 'ts-morph'; +import Carrier from '@modules/server.common/entities/Carrier'; +import Currency from '@modules/server.common/entities/Currency'; +import Invite from '@modules/server.common/entities/Invite'; +import InviteRequest from '@modules/server.common/entities/InviteRequest'; +import Order from '@modules/server.common/entities/Order'; +import ProductCategory from '@modules/server.common/entities/ProductsCategory'; +import User from '@modules/server.common/entities/User'; +import Warehouse from '@modules/server.common/entities/Warehouse'; +import { + TypeORMService, + typeORMServiceFactory +} from '@pyro/db-server/typeorm-service'; function getRepository(t: any): any { const conn = getConnection('typeorm'); @@ -46,18 +60,33 @@ function getRepository(t: any): any { } const bindings = new ContainerModule((bind: interfaces.Bind) => { - bind>('AdminRepository') - .toDynamicValue(() => { - return getRepository(Admin); - }) - .inRequestScope(); - - bind>('DeviceRepository') - .toDynamicValue(() => { - return getRepository(Device); - }) - .inRequestScope(); + const database = 'mysql' || process.env.DB; + + console.log(`Database is ${database}`); + + [ + Admin, + Carrier, + Device, + Invite, + InviteRequest, + Order, + Product, + ProductCategory, + User, + Warehouse + ].forEach((el: any) => { + const { modelName } = el; + bind>(`${el.modelName}Repository`) + .toDynamicValue(() => { + return getRepository(el.modelName); + }) + .inRequestScope(); + // bind>( + // `TypeORMService<${modelName}>` + // ).toConstantValue(TypeORMService) + }); _.each( [ ConfigService, @@ -106,8 +135,10 @@ const bindings = new ContainerModule((bind: interfaces.Bind) => { ); bind(AuthService).toSelf(); + bind(TypeORMService).toSelf(); bind('Factory').toFactory(authServiceFactory); + bind('Factory').toFactory(typeORMServiceFactory); bind('RoutersManager') .to(RoutersManager) @@ -116,6 +147,25 @@ const bindings = new ContainerModule((bind: interfaces.Bind) => { bind(ServicesApp) .toSelf() .inSingletonScope(); + + // [TypeORMService].forEach((Service) => { + // bind(Service).to(Service); + // }); + + bind('DatabaseService').toFactory((context) => { + return (model) => { + if (database === 'mongo') { + return context.container.get>( + TypeORMService + ); + } + const repo = context.container.get>( + `${model}Repository` + ); + return typeORMServiceFactory(context)(repo); + // return context.container.get('Factory')(model); + }; + }); }); const container = new Container(); diff --git a/backend/api/src/services/invites/InvitesRequestsService.ts b/backend/api/src/services/invites/InvitesRequestsService.ts index a775299ee..a60e1f4cc 100644 --- a/backend/api/src/services/invites/InvitesRequestsService.ts +++ b/backend/api/src/services/invites/InvitesRequestsService.ts @@ -22,6 +22,7 @@ import { IGeoLocationCreateObject } from '@modules/server.common/interfaces/IGeo import { Country } from '@modules/server.common/entities/GeoLocation'; import IPagingOptions from '@modules/server.common/interfaces/IPagingOptions'; import * as faker from 'faker'; +import { Repository } from 'typeorm'; @injectable() @routerName('invite-request') @@ -36,7 +37,9 @@ export class InvitesRequestsService extends DBService constructor( @inject(InvitesService) protected invitesService: InvitesService, - @inject(DevicesService) protected devicesService: DevicesService + @inject(DevicesService) protected devicesService: DevicesService, + @inject('InviteRequestRepository') + private readonly _inviteRequestRepository: Repository ) { super(); @@ -69,6 +72,14 @@ export class InvitesRequestsService extends DBService ); } }); + _inviteRequestRepository + .count() + .then((c) => { + console.log('InviteRequests count: ' + c); + }) + .catch((e) => { + console.log(e); + }); } @observableListener() diff --git a/backend/api/src/services/invites/InvitesService.ts b/backend/api/src/services/invites/InvitesService.ts index 11f6de555..8d2d52026 100644 --- a/backend/api/src/services/invites/InvitesService.ts +++ b/backend/api/src/services/invites/InvitesService.ts @@ -1,5 +1,5 @@ import * as Logger from 'bunyan'; -import { injectable } from 'inversify'; +import { injectable, inject } from 'inversify'; import Utils from '../../modules/server.common/utils'; import { createEverLogger } from '../../helpers/Log'; import Invite from '../../modules/server.common/entities/Invite'; @@ -29,6 +29,7 @@ import { IInviteRequestCreateObject } from '@modules/server.common/interfaces/II import * as faker from 'faker'; import { Country } from '@modules/server.common/entities/GeoLocation'; import IPagingOptions from '@modules/server.common/interfaces/IPagingOptions'; +import { Repository } from 'typeorm'; @injectable() @routerName('invite') @@ -44,13 +45,25 @@ export class InvitesService extends DBService private static readonly InviteWorkingDistance = 50000; - constructor() { + constructor( + @inject('InviteRepository') + private readonly _inviteRepository: Repository + ) { super(); this._invitedStreetLocations = of(null).pipe( concat(this.existence), exhaustMap(() => this._getInvitedStreetLocations()) ); + + _inviteRepository + .count() + .then((c) => { + console.log('Invites count: ' + c); + }) + .catch((e) => { + console.log(e); + }); } @observableListener() diff --git a/backend/api/src/services/orders/OrdersService.ts b/backend/api/src/services/orders/OrdersService.ts index bb2bd4e0b..98a1a9079 100644 --- a/backend/api/src/services/orders/OrdersService.ts +++ b/backend/api/src/services/orders/OrdersService.ts @@ -31,6 +31,7 @@ import OrderStatus from '@modules/server.common/enums/OrderStatus'; import User from '@modules/server.common/entities/User'; import { ProductsService } from '../../services/products'; import { Observable } from 'rxjs'; +import { Repository } from 'typeorm'; // TODO: this and other Stripe related things should be inside separate Payments Service const stripe: Stripe = new Stripe(env.STRIPE_SECRET_KEY); @@ -82,9 +83,19 @@ export class OrdersService extends DBService @inject(new LazyServiceIdentifer(() => WarehousesService)) protected _storesService: WarehousesService, @inject(new LazyServiceIdentifer(() => ProductsService)) - protected _productsService: ProductsService + protected _productsService: ProductsService, + @inject('OrderRepository') + private readonly _orderRepository: Repository ) { super(); + _orderRepository + .count() + .then((c) => { + console.log('Orders count: ' + c); + }) + .catch((e) => { + console.log(e); + }); } async generateOrdersPerEachCustomer(customers: any[]): Promise { diff --git a/backend/api/src/services/products/ProductsCategoriesService.ts b/backend/api/src/services/products/ProductsCategoriesService.ts index 34c173b56..586f24add 100644 --- a/backend/api/src/services/products/ProductsCategoriesService.ts +++ b/backend/api/src/services/products/ProductsCategoriesService.ts @@ -1,35 +1,51 @@ import * as Logger from 'bunyan'; -import { injectable } from 'inversify'; +import { injectable, inject } from 'inversify'; import { createEverLogger } from '../../helpers/Log'; import { DBService } from '@pyro/db-server'; import IProductsCategoryRouter from '../../modules/server.common/routers/IProductsCategoryRouter'; import { Observable } from 'rxjs'; import { asyncListener, observableListener, routerName } from '@pyro/io'; import IService from '../IService'; -import ProductsCategory from '../../modules/server.common/entities/ProductsCategory'; +import ProductCategory from '../../modules/server.common/entities/ProductsCategory'; import { UpdateObject } from '@pyro/db/db-update-object'; import { CreateObject } from '@pyro/db/db-create-object'; import { first, switchMap, map } from 'rxjs/operators'; +import { Repository } from 'typeorm'; @injectable() @routerName('products-category') -export class ProductsCategoriesService extends DBService +export class ProductsCategoriesService extends DBService implements IProductsCategoryRouter, IService { - public readonly DBObject = ProductsCategory; + public readonly DBObject = ProductCategory; protected readonly log: Logger = createEverLogger({ name: 'productsCategoriesService' }); + constructor( + @inject('ProductCategoryRepository') + private readonly _productCategoryRepository: Repository + ) { + super(); + _productCategoryRepository + .count() + .then((c) => { + console.log('Product Categories count: ' + c); + }) + .catch((e) => { + console.log(e); + }); + } + /** * Get Product Category by Id * - * @param {ProductsCategory['id']} id - * @returns {(Observable)} + * @param {ProductCategory['id']} id + * @returns {(Observable)} * @memberof ProductsCategoriesService */ @observableListener() - get(id: ProductsCategory['id']): Observable { + get(id: ProductCategory['id']): Observable { return super.get(id).pipe( map(async (category) => { await this.throwIfNotExists(id); @@ -42,14 +58,14 @@ export class ProductsCategoriesService extends DBService /** * Create new Product Category * - * @param {CreateObject} category - * @returns {Promise} + * @param {CreateObject} category + * @returns {Promise} * @memberof ProductsCategoriesService */ @asyncListener() async create( - category: CreateObject - ): Promise { + category: CreateObject + ): Promise { return super.create(category); } @@ -57,15 +73,15 @@ export class ProductsCategoriesService extends DBService * Updates existed Product Category * * @param {string} id - * @param {UpdateObject} updateObject - * @returns {Promise} + * @param {UpdateObject} updateObject + * @returns {Promise} * @memberof ProductsCategoriesService */ @asyncListener() async update( id: string, - updateObject: UpdateObject - ): Promise { + updateObject: UpdateObject + ): Promise { await this.throwIfNotExists(id); return super.update(id, updateObject); } diff --git a/backend/api/src/services/products/ProductsService.ts b/backend/api/src/services/products/ProductsService.ts index f91c4bab8..082b42a7e 100644 --- a/backend/api/src/services/products/ProductsService.ts +++ b/backend/api/src/services/products/ProductsService.ts @@ -1,5 +1,5 @@ import * as Logger from 'bunyan'; -import { injectable } from 'inversify'; +import { injectable, inject } from 'inversify'; import { createEverLogger } from '../../helpers/Log'; import Product from '../../modules/server.common/entities/Product'; import { DBService } from '@pyro/db-server'; @@ -17,6 +17,7 @@ import { CreateObject } from '@pyro/db/db-create-object'; import { UpdateObject } from '@pyro/db/db-update-object'; import { first, switchMap, map } from 'rxjs/operators'; import IPagingOptions from '@modules/server.common/interfaces/IPagingOptions'; +import { Repository } from 'typeorm'; @injectable() @routerName('product') @@ -28,6 +29,21 @@ export class ProductsService extends DBService name: 'productsService' }); + constructor( + @inject('ProductRepository') + private readonly _productRepository: Repository + ) { + super(); + _productRepository + .count() + .then((c) => { + console.log('Products count: ' + c); + }) + .catch((e) => { + console.log(e); + }); + } + @observableListener() get(id: Product['id']): Observable { return super.get(id).pipe( diff --git a/backend/api/src/services/services.app.ts b/backend/api/src/services/services.app.ts index 1d6a76c26..e21aff1ef 100644 --- a/backend/api/src/services/services.app.ts +++ b/backend/api/src/services/services.app.ts @@ -34,7 +34,7 @@ import Invite from '@modules/server.common/entities/Invite'; import InviteRequest from '@modules/server.common/entities/InviteRequest'; import Order from '@modules/server.common/entities/Order'; import Product from '@modules/server.common/entities/Product'; -import ProductsCategory from '@modules/server.common/entities/ProductsCategory'; +import ProductCategory from '@modules/server.common/entities/ProductsCategory'; import User from '@modules/server.common/entities/User'; import Warehouse from '@modules/server.common/entities/Warehouse'; import { ConfigService } from '../config/config.service'; @@ -80,11 +80,12 @@ export class ServicesApp { https.globalAgent.maxSockets = maxSockets; http.globalAgent.maxSockets = maxSockets; - this._configDB(); + this._configMongoDB(); } async start() { - await this._connectDB(); + await this._onDBConnect(); + console.log('end'); } static getEntities() { @@ -96,30 +97,36 @@ export class ServicesApp { InviteRequest, Order, Product, - ProductsCategory, + ProductCategory, User, Warehouse ]; return entities; } - static async CreateTypeORMConnection() { + static async createTypeORMConnection() { // list of entities for which Repositories will be greated in TypeORM const entities = ServicesApp.getEntities(); const conn = await createConnection({ name: 'typeorm', // TODO: put this into settings (it's mongo only during testing of TypeORM integration!) - type: 'mongodb', - url: env.DB_URI, + // type: 'mongodb', + // url: env.DB_URI, + type: 'mysql', + host: 'localhost', + port: 3306, + database: 'test', + username: 'ever', + password: 'ever', entities, synchronize: true, - useNewUrlParser: true, - autoReconnect: true, - reconnectTries: Number.MAX_VALUE, - poolSize: ServicesApp._poolSize, - connectTimeoutMS: ServicesApp._connectTimeoutMS, - logging: true + // useNewUrlParser: true, + // autoReconnect: true, + // reconnectTries: Number.MAX_VALUE, + // poolSize: ServicesApp._poolSize, + // connectTimeoutMS: ServicesApp._connectTimeoutMS, + logging: false }); console.log( @@ -146,7 +153,7 @@ export class ServicesApp { } } - private _configDB() { + private _configMongoDB() { this.db.on('error', (err) => this.log.error(err)); this.db.on('disconnected', () => { @@ -173,7 +180,7 @@ export class ServicesApp { .on('SIGTERM', this._gracefulExit); } - private async _connectDB() { + private async _connectToMongo() { try { mongoose.connect( env.DB_URI, @@ -200,10 +207,17 @@ export class ServicesApp { } private async _onDBConnect() { - await this._registerModels(); + if (process.env.DB === 'mongo') { + console.log('registering models'); + await this._registerModels(); + } + console.log('start admin'); await this._registerEntityAdministrator(); + console.log('start passport'); this._passportSetup(); + console.log('start express'); await this._startExpress(); + console.log('start socket'); this._startSocketIO(); } @@ -219,12 +233,14 @@ export class ServicesApp { const adminEmail = 'admin@ever.co'; // TODO: put to config const adminPassword = 'admin'; // TODO: put to config + console.log('Counting admins'); const adminCollectionCount = await this._adminsService.count({ email: adminEmail }); + console.log('Finished Counting admins'); if (adminCollectionCount === 0) { - this._adminsService.register({ + await this._adminsService.register({ admin: { email: adminEmail, name: 'Admin', diff --git a/backend/api/src/services/users/UsersService.ts b/backend/api/src/services/users/UsersService.ts index cfe80ff42..d39c7500a 100644 --- a/backend/api/src/services/users/UsersService.ts +++ b/backend/api/src/services/users/UsersService.ts @@ -45,6 +45,7 @@ import _ = require('lodash'); import * as faker from 'faker'; import { WarehousesService } from '../../services/warehouses'; import IPagingOptions from '@modules/server.common/interfaces/IPagingOptions'; +import { Repository } from 'typeorm'; // TODO: this and other Stripe related things should be inside separate Payments Service const stripe: Stripe = new Stripe(env.STRIPE_SECRET_KEY); @@ -83,10 +84,21 @@ export class UsersService extends DBService @inject(new LazyServiceIdentifer(() => DevicesService)) protected devicesService: DevicesService, @inject(new LazyServiceIdentifer(() => WarehousesService)) - protected _storesService: WarehousesService + protected _storesService: WarehousesService, + @inject('UserRepository') + private readonly _userRepository: Repository ) { super(); + _userRepository + .count() + .then((c) => { + console.log('Users count: ' + c); + }) + .catch((e) => { + console.log(e); + }); + // TODO: too many hardcoded constants used below. Refactor! this.watchedFiles = _.zipObject( ['aboutUs', 'privacy', 'termsOfUse'], diff --git a/backend/api/src/services/warehouses/WarehousesService.ts b/backend/api/src/services/warehouses/WarehousesService.ts index 8450bde64..d64179292 100644 --- a/backend/api/src/services/warehouses/WarehousesService.ts +++ b/backend/api/src/services/warehouses/WarehousesService.ts @@ -25,6 +25,7 @@ import { env } from '../../env'; import { AuthService, AuthServiceFactory } from '../auth'; import { v1 as uuid } from 'uuid'; import IPagingOptions from '@modules/server.common/interfaces/IPagingOptions'; +import { Repository } from 'typeorm'; /** * Warehouses Service @@ -49,7 +50,9 @@ export class WarehousesService extends DBService @inject(ProductsService) private readonly productsService: ProductsService, @inject('Factory') - private readonly authServiceFactory: AuthServiceFactory + private readonly authServiceFactory: AuthServiceFactory, + @inject('WarehouseRepository') + private readonly _warehouseRepository: Repository ) { super(); this.authService = this.authServiceFactory({ @@ -57,6 +60,15 @@ export class WarehousesService extends DBService Entity: Warehouse, saltRounds: env.USER_PASSWORD_BCRYPT_SALT_ROUNDS }); + + _warehouseRepository + .count() + .then((c) => { + console.log('Warehouses count: ' + c); + }) + .catch((e) => { + console.log(e); + }); } /** diff --git a/package.json b/package.json index 9df95aa0d..d4394efd4 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "@ngx-translate/http-loader": "^4.0.0", "angular2-logger": "^0.7.0", "fstream": "^1.0.12", + "mysql": "^2.17.1", "npm": "^6.9.0", "rxjs": "^6.5.1", "rxjs-compat": "^6.5.1", diff --git a/shared/core-angular/typeorm-placeholder.ts b/shared/core-angular/typeorm-placeholder.ts index d196f4c50..7b7fbf6ee 100644 --- a/shared/core-angular/typeorm-placeholder.ts +++ b/shared/core-angular/typeorm-placeholder.ts @@ -9,3 +9,17 @@ export function Column(options?: any): Function { export function PrimaryColumn(options?: any): Function { return () => {}; } + +export function PrimaryGeneratedColumn(options?: any): Function { + return () => {}; +} + +export function CreateDateColumn(options?: any): Function { + return () => {}; +} + +export function UpdateDateColumn(options?: any): Function { + return () => {}; +} + +export class Repository {} diff --git a/shared/core/@pyro/db/db-create-object.ts b/shared/core/@pyro/db/db-create-object.ts index 267b9f0dd..48bcaf18a 100644 --- a/shared/core/@pyro/db/db-create-object.ts +++ b/shared/core/@pyro/db/db-create-object.ts @@ -2,7 +2,7 @@ import { PyroObjectId } from './object-id'; import { DBObject } from '@pyro/db/db-object'; export interface DBCreateObject { - _id?: PyroObjectId; + _id?: PyroObjectId | string; } export type CreateObject> = T['CreateObjectTYPE']; diff --git a/shared/core/@pyro/db/db-object.ts b/shared/core/@pyro/db/db-object.ts index 2a89d89d4..180b80844 100644 --- a/shared/core/@pyro/db/db-object.ts +++ b/shared/core/@pyro/db/db-object.ts @@ -5,7 +5,13 @@ import { PyroObjectId } from './object-id'; import * as mongoose from 'mongoose'; import { toDate } from '../../utils'; import * as _ from 'lodash'; -import { Column, PrimaryColumn } from 'typeorm'; +import { + Column, + PrimaryColumn, + CreateDateColumn, + UpdateDateColumn, + PrimaryGeneratedColumn +} from 'typeorm'; export interface DBObjectClass extends Function { modelName?: string; @@ -26,21 +32,21 @@ export abstract class DBObject< constructor(obj: RawObject) { _.assign(this, obj); - if ( - mongoose != null && - mongoose.Types != null && - mongoose.Types.ObjectId != null - ) { - if (obj && obj['_id']) { - this['_id'] = mongoose.Types.ObjectId.createFromHexString( - obj['_id'].toString() - ); - } - } + // if ( + // mongoose != null && + // mongoose.Types != null && + // mongoose.Types.ObjectId != null + // ) { + // if (obj && obj['_id']) { + // this['_id'] = mongoose.Types.ObjectId.createFromHexString( + // obj['_id'].toString() + // ); + // } + // } } - @PrimaryColumn() - _id: PyroObjectId; + @PrimaryGeneratedColumn() + _id: string; /** * Time when entity was created @@ -49,7 +55,7 @@ export abstract class DBObject< * @type {(Date | string)} * @memberof DBObject */ - @Column() + @CreateDateColumn() _createdAt: Date | string; /** @@ -58,7 +64,7 @@ export abstract class DBObject< * @type {(Date | string)} * @memberof DBObject */ - @Column() + @UpdateDateColumn() _updatedAt: Date | string; get createdAt(): Date { diff --git a/shared/core/@pyro/db/db-raw-object.ts b/shared/core/@pyro/db/db-raw-object.ts index 10d03a715..256e69aab 100644 --- a/shared/core/@pyro/db/db-raw-object.ts +++ b/shared/core/@pyro/db/db-raw-object.ts @@ -6,7 +6,7 @@ import { DBObject } from '@pyro/db/db-object'; * Data Transfer Object (DTO) */ export interface DBRawObject extends DBCreateObject { - _id: PyroObjectId; + _id: string | PyroObjectId; _createdAt: Date | string; _updatedAt: Date | string; } diff --git a/shared/core/@pyro/db/types.ts b/shared/core/@pyro/db/types.ts index 536012fc2..e22366cf0 100644 --- a/shared/core/@pyro/db/types.ts +++ b/shared/core/@pyro/db/types.ts @@ -39,7 +39,7 @@ export const Types = { const op = { ...options }; op.type = String; - op.ref = (multi ? Type[0] : Type).modelName; + op.ref = typeof (multi ? Type[0] : Type); Schema(multi ? [op] : op)(target, propertyKey); }; diff --git a/shared/core/entities/Admin.ts b/shared/core/entities/Admin.ts index 3fbf47fd7..85bbfcd88 100644 --- a/shared/core/entities/Admin.ts +++ b/shared/core/entities/Admin.ts @@ -64,7 +64,7 @@ class Admin extends DBObject implements IAdmin { * @memberof Admin */ @Types.Boolean(false) - @Column() + @Column({ default: false }) isDeleted: boolean; /** @@ -78,7 +78,7 @@ class Admin extends DBObject implements IAdmin { required: false, validate: new RegExp(`^[a-z ,.'-]+$`, 'i') }) - @Column() + @Column({ default: '' }) firstName?: string; /** @@ -92,7 +92,7 @@ class Admin extends DBObject implements IAdmin { required: false, validate: new RegExp(`^[a-z ,.'-]+$`, 'i') }) - @Column() + @Column({ default: '' }) lastName?: string; } diff --git a/shared/core/entities/Carrier.ts b/shared/core/entities/Carrier.ts index 1d54343c1..15694a2b2 100644 --- a/shared/core/entities/Carrier.ts +++ b/shared/core/entities/Carrier.ts @@ -185,7 +185,7 @@ class Carrier extends DBObject email: string; @Schema([String]) - @Column() + @Column('simple-array') skippedOrderIds: string[]; /** diff --git a/shared/core/entities/Product.ts b/shared/core/entities/Product.ts index 27e294007..678d9d02d 100644 --- a/shared/core/entities/Product.ts +++ b/shared/core/entities/Product.ts @@ -8,7 +8,7 @@ import IProduct, { IProductImage, IProductTitle } from '../interfaces/IProduct'; -import ProductsCategory from './ProductsCategory'; +import ProductCategory from './ProductsCategory'; import { IProductsCategory } from '../interfaces/IProductsCategory'; import { Entity, Column } from 'typeorm'; @@ -86,7 +86,7 @@ class Product extends DBObject * @type {IProductsCategory[]} * @memberof Product */ - @Types.Ref([ProductsCategory]) + @Types.Ref([ProductCategory]) categories: IProductsCategory[]; @Types.Boolean(false) diff --git a/shared/core/entities/ProductsCategory.ts b/shared/core/entities/ProductsCategory.ts index 19f42e77c..cde55895d 100644 --- a/shared/core/entities/ProductsCategory.ts +++ b/shared/core/entities/ProductsCategory.ts @@ -15,7 +15,7 @@ import { Entity, Column } from 'typeorm'; */ @ModelName('ProductCategory') @Entity({ name: 'productcategories' }) -class ProductsCategory +class ProductCategory extends DBObject implements IProductsCategory { /** @@ -45,4 +45,4 @@ class ProductsCategory isDeleted: boolean; } -export default ProductsCategory; +export default ProductCategory; diff --git a/shared/core/entities/Warehouse.ts b/shared/core/entities/Warehouse.ts index e0b5fbf22..712cbc9f0 100644 --- a/shared/core/entities/Warehouse.ts +++ b/shared/core/entities/Warehouse.ts @@ -177,7 +177,7 @@ class Warehouse extends DBObject * @memberof Warehouse */ @Schema([Number]) - @Column() + @Column('simple-array') forwardOrdersUsing: ForwardOrdersMethod[]; /** diff --git a/shared/core/routers/IProductsCategoryRouter.ts b/shared/core/routers/IProductsCategoryRouter.ts index 01438fc14..b9d76eaca 100644 --- a/shared/core/routers/IProductsCategoryRouter.ts +++ b/shared/core/routers/IProductsCategoryRouter.ts @@ -1,21 +1,21 @@ import { Observable } from 'rxjs'; -import ProductsCategory from '../entities/ProductsCategory'; +import ProductCategory from '../entities/ProductsCategory'; import { CreateObject } from '@pyro/db/db-create-object'; import { UpdateObject } from '@pyro/db/db-update-object'; interface IProductsCategoryRouter { - get(id: ProductsCategory['id']): Observable; + get(id: ProductCategory['id']): Observable; create( - createInput: CreateObject - ): Promise; + createInput: CreateObject + ): Promise; update( - id: ProductsCategory['id'], - updateInput: UpdateObject - ): Promise; + id: ProductCategory['id'], + updateInput: UpdateObject + ): Promise; - remove(id: ProductsCategory['id']): Promise; + remove(id: ProductCategory['id']): Promise; } export default IProductsCategoryRouter; diff --git a/yarn.lock b/yarn.lock index 101119f22..64d53fcae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1472,6 +1472,11 @@ better-assert@~1.0.0: dependencies: callsite "1.0.0" +bignumber.js@7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" + integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== + bin-links@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-1.1.2.tgz#fb74bd54bae6b7befc6c6221f25322ac830d9757" @@ -5387,6 +5392,16 @@ mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" +mysql@^2.17.1: + version "2.17.1" + resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.17.1.tgz#62bba4a039a9b2f73638cd1652ce50fc6f682899" + integrity sha512-7vMqHQ673SAk5C8fOzTG2LpPcf3bNt0oL3sFpxPEEFp1mdlDcrLK0On7z8ZYKaaHrHwNcQ/MTUz7/oobZ2OyyA== + dependencies: + bignumber.js "7.2.1" + readable-stream "2.3.6" + safe-buffer "5.1.2" + sqlstring "2.3.1" + mz@^2.4.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -6696,7 +6711,7 @@ read@1, read@~1.0.1, read@~1.0.7: dependencies: mute-stream "~0.0.4" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2: +"readable-stream@1 || 2", readable-stream@2.3.6, readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2: version "2.3.6" resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: @@ -7087,7 +7102,7 @@ rxjs@^6.5.1: dependencies: tslib "^1.9.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -7439,6 +7454,11 @@ sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" +sqlstring@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40" + integrity sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A= + sshpk@^1.7.0: version "1.14.2" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" From d4877fc57bbbede459890071252ee3351ba6c819 Mon Sep 17 00:00:00 2001 From: Ruslan Konviser Date: Sat, 11 Jan 2020 19:14:06 +0200 Subject: [PATCH 2/2] fix: use ProductCategory, not ProductsCategory --- backend/api/src/services/products/ProductsCategoriesService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/api/src/services/products/ProductsCategoriesService.ts b/backend/api/src/services/products/ProductsCategoriesService.ts index b730ef778..103ea27f5 100644 --- a/backend/api/src/services/products/ProductsCategoriesService.ts +++ b/backend/api/src/services/products/ProductsCategoriesService.ts @@ -6,11 +6,11 @@ import IProductsCategoryRouter from '@modules/server.common/routers/IProductsCat import { Observable } from 'rxjs'; import { asyncListener, observableListener, routerName } from '@pyro/io'; import IService from '../IService'; -import ProductsCategory from '@modules/server.common/entities/ProductsCategory'; import { UpdateObject } from '@pyro/db/db-update-object'; import { CreateObject } from '@pyro/db/db-create-object'; import { first, switchMap, map } from 'rxjs/operators'; import { Repository } from 'typeorm'; +import ProductCategory from '@modules/server.common/entities/ProductsCategory'; @injectable() @routerName('products-category')