diff --git a/services/accountsanjuggler/controllers/AccountController.api.ts b/services/accountsanjuggler/controllers/AccountController.api.ts deleted file mode 100644 index e2f5337..0000000 --- a/services/accountsanjuggler/controllers/AccountController.api.ts +++ /dev/null @@ -1,108 +0,0 @@ -export const def = { - basePath: '/', - paths: { - '/accounts': { - get: { - 'x-operation-name': 'getAccount', - parameters: [ - { - name: 'id', - in: 'query', - description: 'The account id.', - required: true, - type: 'string', - format: 'JSON' - }, - { - name: 'filter', - in: 'query', - description: 'The criteria used to narrow down the number of accounts returned.', - required: false, - type: 'string', - format: 'JSON' - } - ], - responses: { - 200: { - schema: { - accountNumber: { - type: 'string', - description: 'The account number.', - }, - customerNumber: { - type: 'string', - description: 'The customer number.', - }, - type: { - type: 'string', - description: 'The type of account ("savings" or "chequing").', - }, - balance: { - type: 'number', - description: 'The balance of the account.', - }, - minimumBalance: { - type: 'number', - description: 'The minimum balance for the account.', - }, - avgBalance: { - type: 'number', - description: 'The average balance of the account.', - }, - }, - }, - }, - }, - }, - - '/accounts/create': { - post: { - 'x-operation-name': 'createAccount', - parameters: [ - { - name: 'accountInstance', - in: 'body', - description: 'The account instance.', - required: true, - type: 'object', - format: 'JSON' - } - ], - responses: { - 200: { - schema: { - id: { - type: 'string', - description: 'The account id.', - }, - customerNumber: { - type: 'string', - description: 'The customer number.', - }, - balance: { - type: 'number', - description: 'The balance of the account.', - }, - branch: { - type: 'string', - description: 'The bank branch.', - }, - type: { - type: 'string', - description: 'The type of account ("savings" or "chequing").', - }, - minimumBalance: { - type: 'number', - description: 'The minimum balance for the account.', - }, - avgBalance: { - type: 'number', - description: 'The average balance of the account.', - }, - }, - }, - }, - }, - } - }, -}; diff --git a/services/accountsanjuggler/controllers/AccountController.ts b/services/accountsanjuggler/controllers/AccountController.ts deleted file mode 100644 index e1f6bb5..0000000 --- a/services/accountsanjuggler/controllers/AccountController.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { api } from 'loopback-next/packages/core'; -import { def } from './AccountController.api'; -import { newRepository, AccountRepository } from '../repositories/account'; -import { Account } from '../repositories/account/models/Account'; -import { repository } from "loopback-next/packages/repository/src/decorators/repository"; -import { Filter, Order } from "loopback-next/packages/repository/src/query"; -import {MySQLDs, MySqlConn} from '../repositories/account/datasources/mysql'; - -@api(def) -@repository('newRepository') -export class AccountController { - repository: newRepository; - - constructor() { - this.repository = new newRepository(MySQLDs, Account); - } - - async getAccount(accountNumber) { - console.log('inside getAccount'); - if (accountNumber) { - return await this.repository.find({where: {id: accountNumber}}); - } else { - return await this.repository.find({}); - } - - } - async createAccount(accountInstance) { - console.log('inside createAccount'); - return await this.repository.create(accountInstance); - } - -} diff --git a/services/accountsanjuggler/repositories/account/datasources/local-fs/data.json b/services/accountsanjuggler/repositories/account/datasources/local-fs/data.json deleted file mode 100644 index 91fbc61..0000000 --- a/services/accountsanjuggler/repositories/account/datasources/local-fs/data.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "ids": { - "Account": 4 - }, - "models": { - "Account": { - "CHK52321122": "{\"id\":\"CHK52321122\",\"customerNumber\":\"000343223\",\"balance\":85.84,\"branch\":\"Foster City\",\"type\":\"Checking\",\"avgBalance\":398.93,\"minimumBalance\":10}", - "CHK54520000": "{\"id\":\"CHK54520000\",\"customerNumber\":\"003499223\",\"balance\":99.99,\"branch\":\"Foster City\",\"type\":\"Checking\",\"avgBalance\":500.93,\"minimumBalance\":10}", - "CHK52321199": "{\"id\":\"CHK52321199\",\"customerNumber\":\"000343223\",\"balance\":109.89,\"branch\":\"Foster City\",\"type\":\"Checking\",\"avgBalance\":100.93,\"minimumBalance\":10}", - "CHK99999999": "{\"id\":\"CHK99999999\",\"customerNumber\":\"0002444422\",\"balance\":100.89,\"branch\":\"Foster City\",\"type\":\"Checking\",\"avgBalance\":100.93,\"minimumBalance\":10}" - } - } -} \ No newline at end of file diff --git a/services/accountsanjuggler/repositories/account/datasources/mysql.ts b/services/accountsanjuggler/repositories/account/datasources/mysql.ts deleted file mode 100644 index 138f129..0000000 --- a/services/accountsanjuggler/repositories/account/datasources/mysql.ts +++ /dev/null @@ -1,46 +0,0 @@ -import mysql = require('mysql'); -import { Connector } from "loopback-next/packages/repository/src/connector"; -import { DataSource } from "loopback-next/packages/repository/src/datasource"; - - -export class MySqlConn implements Connector { - constructor(config: Object) { - let connection = mysql.createConnection(config); -} - name: 'mysql'; - interfaces?: string[]; - connect() { - return new Promise(function(resolve, reject) { - this.connection.connect(function(err) { - if (err !== null) return reject(err); - resolve(err); - }) - }) - } - disconnect(){ - return new Promise(function(resolve, reject) { - this.connection.end(function(err) { - if (err !== null) return reject(err); - resolve(err); - }) - }) - } - ping(){ - return new Promise(function(resolve, reject) { - this.connection.ping(function(err) { - if (err !== null) return reject(err); - resolve(err); - }) - }) - } -} - -let mysqlConnInstance = new MySqlConn(require('./datasource.json')); - -export class MySQLDs implements DataSource { - name: 'mysqlDs' - connector: MySqlConn -} - - - diff --git a/services/accountsanjuggler/repositories/account/index.ts b/services/accountsanjuggler/repositories/account/index.ts deleted file mode 100644 index c6d97e7..0000000 --- a/services/accountsanjuggler/repositories/account/index.ts +++ /dev/null @@ -1,124 +0,0 @@ -import {Class, ObjectType, AnyObject, Options} from 'loopback-next/packages/repository/src/common-types'; -import {Filter, Where, Operators, Condition, Order, Inclusion} from 'loopback-next/packages/repository/src/query'; -import {DataSource} from 'loopback-next/packages/repository/src/datasource'; -import {EntityCrudRepository, CrudRepository, CrudRepositoryImpl} from 'loopback-next/packages/repository/src/repository'; -import {Account} from './models/Account'; -const modelDefinition = require('./models/account/model-definition'); -const mysqlDriver = require('mysql'); -let conn = mysqlDriver.createConnection(require('./datasources/mysql.json')); - - -export class AccountRepository implements EntityCrudRepository { - - constructor() { - if (conn.state !== 'authenticated') { - this.connect().then(function(res) { - console.log('Connection success ', res); - }, function(err) { - console.log('err connecting', err); - }); - } - } - - connect() { - return new Promise(function(resolve, reject) { - conn.connect(function(err) { - if (err !== null) return reject(err); - resolve(err); - }) - }) - } - disconnect(){ - return new Promise(function(resolve, reject) { - conn.end(function(err) { - if (err !== null) return reject(err); - resolve(err); - }) - }) - } - ping(){ - return new Promise(function(resolve, reject) { - conn.ping(function(err) { - if (err !== null) return reject(err); - resolve(err); - }) - }) - } - - save(entity: ObjectType, options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - create(dataObject: ObjectType, options?: AnyObject): Promise { - let sqlStmt = 'INSERT INTO ' + Account.name + ' VALUES '; - var vals = []; - for (var prop in dataObject) { - vals.push(dataObject[prop]); - } - sqlStmt += '(' + vals.join(',') + ')' + ';'; - console.log('insert stmt ', sqlStmt); - return new Promise(function(resolve, reject) { - conn.query(sqlStmt, function(err, count, fields) { - if (err !== null) return reject(err); - resolve(count.affectedRows); - }); - }); - } - update(entity: ObjectType, options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - delete(entity: ObjectType, options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - findById(id: string, filter?: Filter, options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - updateById(id: string, data: ObjectType, options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - replaceById(id: string, data: ObjectType, options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - deleteById(id: string, options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - exists(id: string, options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - createAll(entities: ObjectType[], options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - find(filter?: Filter, options?: AnyObject): Promise { - let sqlStmt = 'SELECT * FROM ' + Account.name; - if(filter.where) { - let sql = '?? = ?'; - let formattedSql = ''; - for (var key in filter.where) { - formattedSql = mysqlDriver.format(sql, [key, filter.where[key]]); - } - sqlStmt += ' WHERE ' + formattedSql; - } - console.log('sql ', sqlStmt); - return new Promise(function(resolve, reject) { - conn.query(sqlStmt, function(err, results, fields) { - if (err !== null) return reject(err); - resolve(results as Account[]); - }); - }); - } - updateAll(dataObject: ObjectType, where?: Where, options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - deleteAll(where?: Where, options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - count(where?: Where, options?: AnyObject): Promise { - throw new Error("Method not implemented."); - } - -}; - -export class newRepository extends CrudRepositoryImpl { - constructor(dataSource: DataSource, model: Account) { - super(dataSource, Account); - } -} diff --git a/services/accountsanjuggler/repositories/account/models/Account.ts b/services/accountsanjuggler/repositories/account/models/Account.ts deleted file mode 100644 index dcbe230..0000000 --- a/services/accountsanjuggler/repositories/account/models/Account.ts +++ /dev/null @@ -1,19 +0,0 @@ -import {model} from 'loopback-next/packages/repository/src/decorators/model'; -import {Entity} from 'loopback-next/packages/repository/src/model'; - -@model(require('./account/model-definition')) -export class Account extends Entity { - getId(): any { - const definition = (this.constructor as typeof Entity).definition; - const idProps = definition.idProperties(); - if (idProps.length === 1) { - return this[idProps[0].name]; - } - const idObj = {} as any; - for (const idProp of idProps) { - idObj[idProp.name] = this[idProp.name]; - } - return idObj; - } - -} \ No newline at end of file diff --git a/services/accountsanjuggler/bin/get-account b/services/accountsansjuggler/bin/get-account similarity index 100% rename from services/accountsanjuggler/bin/get-account rename to services/accountsansjuggler/bin/get-account diff --git a/services/accountsansjuggler/controllers/AccountController.api.ts b/services/accountsansjuggler/controllers/AccountController.api.ts new file mode 100644 index 0000000..feafa1e --- /dev/null +++ b/services/accountsansjuggler/controllers/AccountController.api.ts @@ -0,0 +1,114 @@ +export const def = { + basePath: '/', + paths: { + '/accounts': { + get: { + 'x-operation-name': 'getAccount', + parameters: [ + { + name: 'filter', + in: 'query', + description: 'The criteria used to narrow down the number of accounts returned.', + required: true, + type: 'object' + } + ], + responses: { + 200: { + schema: { + type: 'array', + items: '#/definitions/Account' + }, + }, + }, + }, + }, + '/accounts/create': { + post: { + 'x-operation-name': 'createAccount', + parameters: [ + { + name: 'accountInstance', + in: 'body', + description: 'The account instance to create.', + required: true, + type: 'object' + }, + ], + responses: { + 200: { + schema: { + accountInstance: "#/definitions/Account" + }, + }, + }, + }, + }, + '/accounts/update': { + post: { + 'x-operation-name': 'updateById', + parameters: [ + { + name: 'id', + in: 'query', + description: 'The id of the model instance to be updated', + required: true, + type: 'string' + }, + { + name: 'data', + in: 'body', + description: 'An object of model property name/value pairs', + required: true, + type: 'object' + } + ], + responses: { + 200: { + schema: { + type: 'object', + description: 'update information', + properties: { + count: { + type: 'number', + description: 'number of records updated' + } + } + }, + }, + }, + } + }, + '/accounts/delete': { + delete: { + 'x-operation-name': 'deleteAccount', + parameters: [ + { + name: 'id', + in: 'query', + description: 'The id for the model instance to be deleted.', + required: true, + type:'object' + } + ], + responses: { + 200: { + schema: { + type: 'object', + description: 'delete information', + properties: { + count: { + type: 'number', + description: 'number of records deleted' + } + } + }, + }, + }, + } + } + }, + definitions: { + Account: require('../repositories/account/models/account/model-definition') + } +}; diff --git a/services/accountsansjuggler/controllers/AccountController.ts b/services/accountsansjuggler/controllers/AccountController.ts new file mode 100644 index 0000000..e71b0c9 --- /dev/null +++ b/services/accountsansjuggler/controllers/AccountController.ts @@ -0,0 +1,29 @@ +import { api } from 'loopback-next/packages/core'; +import { def } from './AccountController.api'; +import { newRepository } from '../repositories/account'; +import { inject } from 'loopback-next/packages/context'; + +@api(def) +export class AccountController { + @inject('repositories.account') + private repository: newRepository; + + constructor() {} + + async getAccount(filter) { + return await this.repository.find(JSON.parse(filter)); + } + + async createAccount(accountInstance) { + return await this.repository.create(accountInstance); + } + + async updateAccount(id, data) { + return await this.repository.updateById(id, data); + } + + async deleteAccount(id) { + return await this.repository.deleteById(id); +} + +} diff --git a/services/accountsanjuggler/index.ts b/services/accountsansjuggler/index.ts similarity index 88% rename from services/accountsanjuggler/index.ts rename to services/accountsansjuggler/index.ts index a4cf656..06a6745 100644 --- a/services/accountsanjuggler/index.ts +++ b/services/accountsansjuggler/index.ts @@ -1,5 +1,6 @@ import { Application, Server } from 'loopback-next/packages/core'; import { AccountController } from './controllers/AccountController'; +import { newRepository } from './repositories/account'; class AccountMicroservice extends Application { private _startTime: Date; @@ -8,6 +9,7 @@ class AccountMicroservice extends Application { super(); const app = this; app.controller(AccountController); + app.bind('repositories.account').toClass(newRepository); app.bind('servers.http.enabled').to(true); app.bind('servers.https.enabled').to(true); } @@ -34,4 +36,4 @@ async function main(): Promise { main().catch(err => { console.log('Cannot start the app.', err); process.exit(1); -}); \ No newline at end of file +}); diff --git a/services/accountsanjuggler/package.json b/services/accountsansjuggler/package.json similarity index 91% rename from services/accountsanjuggler/package.json rename to services/accountsansjuggler/package.json index 8e84a6c..bd8e908 100644 --- a/services/accountsanjuggler/package.json +++ b/services/accountsansjuggler/package.json @@ -4,8 +4,8 @@ "description": "The Account microservice.", "main": "index.ts", "dependencies": { + "debug": "^2.6.8", "lodash": "^4.17.4", - "loopback-datasource-juggler": "^3.4.1", "mysql": "^2.13.0" }, "devDependencies": { diff --git a/services/accountsanjuggler/repositories/account/datasources/mysql.json b/services/accountsansjuggler/repositories/account/datasources/mysql.json similarity index 100% rename from services/accountsanjuggler/repositories/account/datasources/mysql.json rename to services/accountsansjuggler/repositories/account/datasources/mysql.json diff --git a/services/accountsansjuggler/repositories/account/datasources/mysqlds.ts b/services/accountsansjuggler/repositories/account/datasources/mysqlds.ts new file mode 100644 index 0000000..9ae7e5b --- /dev/null +++ b/services/accountsansjuggler/repositories/account/datasources/mysqlds.ts @@ -0,0 +1,180 @@ +const debug = require('debug')('accountsansjuggler'); +const mysql = require('mysql'); +import { CrudConnector, EntityData } from "loopback-next/packages/repository/src/crud-connector"; +import { + Class, + DataSource, + Entity, + Filter, + ObjectType, + Options, + Where +} from 'loopback-next/packages/repository'; + +export class MySqlConn implements CrudConnector { + private connection + + constructor(config: Object) { + this.connection = mysql.createConnection(config); + if (this.connection.state !== 'authenticated') { + this.connect().then(function(res) { + debug('Connection success ', res); + }, function(err) { + debug('err connecting', err); + }); +} +} + name: 'mysql'; + interfaces?: string[]; + connect() { + let self = this; + return new Promise(function(resolve, reject) { + self.connection.connect(function(err) { + if (err !== null) return reject(err); + resolve(err); + }) + }) + } + disconnect(){ + let self = this; + return new Promise(function(resolve, reject) { + self.connection.end(function(err) { + if (err !== null) return reject(err); + resolve(err); + }) + }) + } + ping(){ + let self = this; + return new Promise(function(resolve, reject) { + self.connection.ping(function(err) { + if (err !== null) return reject(err); + resolve(err); + }) + }) + } + + public updateAll(modelClass: Class, data: EntityData, where: Where, options: Options): Promise { + throw new Error('Not implemented yet.'); + } + + public create(modelClass: Class, entity: EntityData, options: Options): Promise { + let self = this; + let sqlStmt = 'INSERT INTO ' + modelClass.name + ' VALUES '; + var vals = []; + for (var prop in entity) { + vals.push(entity[prop]); + } + sqlStmt += '(' + vals.join(',') + ')' + ';'; + debug('insert stmt ', sqlStmt); + return new Promise(function(resolve, reject) { + self.connection.query(sqlStmt, function(err, count, fields) { + if (err !== null) return reject(err); + resolve(count.affectedRows); + }); + }); + } + + public save(modelClass: Class, entity: EntityData, options: Options): Promise { + throw new Error('Not implemented yet.'); + } + + public find(modelClass: Class, filter: Filter, options: Options): Promise { + let self = this; + let sqlStmt = 'SELECT * FROM ' + modelClass.name; + if(filter.where) { + let sql = '?? = ?'; + let formattedSql = ''; + for (var key in filter.where) { + formattedSql = mysql.format(sql, [key, filter.where[key]]); + } + sqlStmt += ' WHERE ' + formattedSql; + } + debug('Find ', sqlStmt); + return new Promise(function(resolve, reject) { + self.connection.query(sqlStmt, function(err, results, fields) { + if (err !== null) return reject(err); + resolve(results as Account[]); + }); + }); + } + + public findById(modelClass: Class, id: Number, options: Options): Promise { + throw new Error('Not implemented yet.'); + } + + public update(modelClass: Class, entity: EntityData, options: Options): Promise { + throw new Error('Not implemented yet.'); + } + + public delete(modelClass: Class, entity: EntityData, options: Options): Promise { + throw new Error('Not implemented yet.'); + } + + public createAll(modelClass: Class, entities: EntityData[], options: Options): Promise { + throw new Error('Not implemented yet.'); + } + + public updateById(modelClass: Class, id: Number, data: EntityData, options: Options): Promise { + let self = this; + let sqlStmt = 'UPDATE ' + modelClass.name + ' SET '; + var vals = []; + for (var prop in data) { + vals.push(prop + '=' + data[prop]); + } + sqlStmt += vals.join(',') + ' WHERE ' + '`id`=' + id + ';'; + + debug('updateById ', sqlStmt); + return new Promise(function(resolve, reject) { + self.connection.query(sqlStmt, function(err, count, fields) { + if (err !== null) return reject(err); + resolve(count.affectedRows); + }); + }); + } + + public replaceById(modelClass: Class, id: Number, data: EntityData, options: Options): Promise { + throw new Error('Not implemented yet.'); + } + + public deleteAll(modelClass: Class, where: Where, options: Options): Promise { + throw new Error('Not implemented yet.'); + } + + public deleteById(modelClass: Class, id: Number, options: Options): Promise { + let self = this; + let sqlStmt = 'DELETE FROM ' + modelClass.name + ' WHERE `id`=' + id + ';'; + + debug('deleteById ', sqlStmt); + return new Promise(function(resolve, reject) { + self.connection.query(sqlStmt, function(err, count, fields) { + if (err !== null) return reject(err); + resolve(count.affectedRows); + }); + }); + } + + public count(modelClass: Class, where: Where, options: Options): Promise { + throw new Error('Not implemented yet.'); + } + + public exists(modelClass: Class, id: Number, options: Options): Promise { + throw new Error('Not implemented yet.'); + } +} + + + +export class MySQLDs implements DataSource { + name: 'mysqlDs' + connector: MySqlConn + settings: Object + + constructor() { + this.settings = require('./mysql.json'); + this.connector = new MySqlConn(this.settings); + } +} + + + diff --git a/services/accountsansjuggler/repositories/account/index.ts b/services/accountsansjuggler/repositories/account/index.ts new file mode 100644 index 0000000..b0b9014 --- /dev/null +++ b/services/accountsansjuggler/repositories/account/index.ts @@ -0,0 +1,12 @@ +import { CrudRepositoryImpl } from 'loopback-next/packages/repository'; +import { MySQLDs } from './datasources/mysqlds'; +import { Account } from './models/Account'; + + +export class newRepository extends CrudRepositoryImpl { + constructor() { + let ds = new MySQLDs(); + super(ds, Account); + } +} + diff --git a/services/accountsansjuggler/repositories/account/models/Account.ts b/services/accountsansjuggler/repositories/account/models/Account.ts new file mode 100644 index 0000000..56a3fb6 --- /dev/null +++ b/services/accountsansjuggler/repositories/account/models/Account.ts @@ -0,0 +1,7 @@ +import {model} from 'loopback-next/packages/repository/'; +import {Entity} from 'loopback-next/packages/repository'; + +@model(require('./account/model-definition')) +export class Account extends Entity { + +} diff --git a/services/accountsanjuggler/repositories/account/models/account/model-definition.js b/services/accountsansjuggler/repositories/account/models/account/model-definition.js similarity index 100% rename from services/accountsanjuggler/repositories/account/models/account/model-definition.js rename to services/accountsansjuggler/repositories/account/models/account/model-definition.js diff --git a/services/accountsanjuggler/tsconfig.json b/services/accountsansjuggler/tsconfig.json similarity index 100% rename from services/accountsanjuggler/tsconfig.json rename to services/accountsansjuggler/tsconfig.json