-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Account service without juggler #51
Conversation
230dd41
to
c63c953
Compare
"required": true | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing newline
cdb602c
to
d3d6a79
Compare
fe897d2
to
8cb7ab4
Compare
|
||
async deleteAccount(id) { | ||
return await this.repository.deleteById(id); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please fix the indentation.
@@ -0,0 +1,2 @@ | |||
#!/usr/bin/env bash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A better name for accountsanjuggler
?
Where | ||
} from 'loopback-next/packages/repository'; | ||
|
||
export class MySqlConn implements CrudConnector { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please refactor it into a new file.
}) | ||
}) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please format the code with correct indentation. If you use VSCode, try prettier javascript formatter
.
730cc20
to
0c8ba95
Compare
@@ -0,0 +1,229 @@ | |||
const debug = require("debug")("accountsansjuggler"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we change the debug tag to account-without-juggler
instead?
expect(getResult).to.not.be.empty(); | ||
expect(getResult).have.lengthOf(1); | ||
expect(getResult[0].id).to.be.equal(testAcc.id); | ||
expect(JSON.parse(JSON.stringify(getResult[0])).balance).to.be.equal(2000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getResult[0].toObject().balance
should work.
"extends": [ | ||
"./tslint.json" | ||
], | ||
// This configuration files enabled rules which require type checking |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these comments needed?
@@ -0,0 +1,72 @@ | |||
{ | |||
// See https://palantir.github.io/tslint/rules/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these comments were copied from loopback-next. I added this particular comment in loopback-next to make it easier for people that are not familiar with tslint to find a reference of all rules.
What are your objections against having these comments in place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. Disregard my comments in that case.
super(); | ||
const app = this; | ||
app.controller(AccountController); | ||
app.bind('repositories.account').toClass(accountRepository); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to introduce app.repository
API to take care of this.
app.repository(accountRepository);
The argument should be strongly typed to a base Repository interface, which is something that we cannot achieve via bind().toClass()
, at least not now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@raymondfeng thoughts on the above API to take care of this action?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can land and create an issue (feature) for the sugar API mentioned by @bajtos. This PR is huge already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@b-admike Please link to the follow up issue here for posterity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Related issue: loopbackio/loopback-next#425
"main": "index.ts", | ||
"dependencies": { | ||
"@loopback/testlab": "^4.0.0-alpha.5", | ||
"@types/mocha": "^2.2.41", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think both testlab
and mocha
should go to devDependencies
, shouldn't it? Why do you actually need @types/mocha
?
connect() { | ||
let self = this; | ||
return new Promise<void>(function(resolve, reject) { | ||
self.connection.connect(function(err: any) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you considered using https://www.npmjs.com/package/mysql-promise or https://www.npmjs.com/package/promise-mysql, instead of this manual way of adding promise support?
sqlStmt += "(" + vals.join(",") + ")" + ";"; | ||
debug("insert stmt ", sqlStmt); | ||
return new Promise<Account>(function(resolve, reject) { | ||
self.connection.query(sqlStmt, function(err: any, count: any) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you considered using https://www.npmjs.com/package/@types/mysql to get better type information? (I don't know how it will work with promise-wrapped mysql packages though.)
options: Options | ||
): Promise<EntityData> { | ||
let self = this; | ||
let sqlStmt = "INSERT INTO " + modelClass.name + " VALUES "; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should escape modelCass.name
in order to prevent SQL script injection. (Class names probably cannot be changed so much as to cause security problem, but I can imagine there may be valid class names that cannot be used in SQL without escaping.)
let sqlStmt = "UPDATE " + modelClass.name + " SET "; | ||
var vals = []; | ||
for (var prop in data) { | ||
vals.push(prop + "=" + data[prop]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SQL injection.
for (var prop in data) { | ||
vals.push(prop + "=" + data[prop]); | ||
} | ||
sqlStmt += vals.join(",") + " WHERE " + "`id`=" + id + ";"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SQL injection - pass id
as a parameter, let the driver to escape it.
options: Options | ||
): Promise<boolean> { | ||
let self = this; | ||
let sqlStmt = "DELETE FROM " + modelClass.name + " WHERE `id`=" + id + ";"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SQL injection - pass id as a parameter, let the driver to escape it.
@@ -0,0 +1,73 @@ | |||
import { AccountController } from "../../controllers/AccountController"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use single quotes for string delimiters in LoopBack code (and in Node.js code in general). This comment applies to all other JS/TS source files in this pull request too.
@@ -0,0 +1,72 @@ | |||
{ | |||
// See https://palantir.github.io/tslint/rules/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these comments were copied from loopback-next. I added this particular comment in loopback-next to make it easier for people that are not familiar with tslint to find a reference of all rules.
What are your objections against having these comments in place?
ef60536
to
19964a3
Compare
private connection: any; | ||
|
||
constructor(config: Object) { | ||
db.configure(config, require("mysql2")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we using the mysql2
driver?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is not what our module (loopback-connector-mysql) uses though. Should we not test this with the same driver that our module currently uses?
|
||
@api(def) | ||
export class AccountController { | ||
@inject('repositories.account') private repository: accountRepository; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move into constructor so that repository can be replaced by constructor injection
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did only a part of the review for now, you can change it up and ping me again.
super(); | ||
const app = this; | ||
app.controller(AccountController); | ||
app.bind('repositories.account').toClass(accountRepository); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can land and create an issue (feature) for the sugar API mentioned by @bajtos. This PR is huge already.
"host":"localhost", | ||
"user":"root", | ||
"password": "dis-mysql", | ||
"database": "test-db", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's make it simpler for future users
password: "password" // password
database: "loopback-next-example" // name of example
should be consistent across all examples
@@ -0,0 +1,201 @@ | |||
const debug = require("debug")("account-without-juggler"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const debug = require('debug')('loopback:repositories:account:datasources:connections:mysql');
Single quote everything in this file too
} from "loopback-next/packages/repository"; | ||
|
||
export class MySqlConn implements CrudConnector { | ||
private connection: any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
: Connection, let's get away from any
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't have that exported in Repository, but I was trying to make it of type IConnection
from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/mysql/index.d.ts#L39-#L83, but the return types for connect
and disconnect
don't align with ours (Promise<void>
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not prefix with I. You can create your own type or interface: See https://github.com/strongloop/loopback-next/blob/master/packages/core/src/internal-types.ts. If we need to create a proxy to normalize the interfaces, so be it. cc @raymondfeng
private connection: any; | ||
|
||
constructor(config: Object) { | ||
db.configure(config, require("mysql2")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move the require up to the top of the file
return this.connection.ping(); | ||
} | ||
|
||
public updateAll( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public is default, remove for consistency
My review isn't relevant due to age, don't let it hold this PR up.
1974c36
to
bd999bf
Compare
@ssh24 @superkhau feedback applied, PTAL |
in: 'query', | ||
description: 'The id for the model instance to be deleted.', | ||
required: true, | ||
type:'object', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, indent off by one space here
and id -> ID or identifier
properties: { | ||
count: { | ||
type: 'number', | ||
description: 'number of records deleted', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number
properties: { | ||
count: { | ||
type: 'number', | ||
description: 'number of records updated', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number
and period at the end of your sentence
{ | ||
name: 'data', | ||
in: 'body', | ||
description: 'An object of model property name/value pairs', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Period at the end for your description
{ | ||
name: 'id', | ||
in: 'query', | ||
description: 'The id of the model instance to be updated', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Period at the end for your description.
200: { | ||
schema: { | ||
type: 'object', | ||
description: 'update information', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Full sentence description here pls.
200: { | ||
schema: { | ||
type: 'object', | ||
description: 'delete information', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better desc here too
@api(def) | ||
export class AccountController { | ||
constructor( | ||
@inject('repositories.account') private repository: accountRepository |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't type be AccountRepository?
import { Account } from './models/Account'; | ||
|
||
|
||
export class accountRepository extends CrudRepositoryImpl<Account, string> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be AccountRepository
"check-type", | ||
"check-typecast", | ||
"check-preblock" | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you separate out this linting stuff into another PR?
eee0a2a
to
4867443
Compare
@superkhau PTAL |
0dbd6b9
to
2496c42
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, we can refactor anything else that needs updating later.
super(); | ||
const app = this; | ||
app.controller(AccountController); | ||
app.bind('repositories.account').toClass(accountRepository); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@b-admike Please link to the follow up issue here for posterity.
"host":"localhost", | ||
"user":"root", | ||
"password": "password", | ||
"database": "account-service", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the name of the example to distinguish from other databases the user may have locally before.
const mysql = require('mysql'); | ||
const db = require('mysql-promise')(); | ||
import { CrudConnector } from 'loopback-next/packages/repository/src/crud-connector'; | ||
import { IError, IConnection } from '@types/mysql'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not use I for interfaces, should just be Error + Connection
this.settings = require("./mysql.json"); | ||
this.connector = new MySqlConn(this.settings); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
single quotes in the whole file pls
settings: Object; | ||
|
||
constructor() { | ||
this.settings = require("./mysql.json"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move to top of file
|
||
export class AccountRepository extends CrudRepositoryImpl<Account, string> { | ||
constructor() { | ||
const ds = new MySQLDs(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MySqlDs
export class Account extends Entity { | ||
static definition = new ModelDefinition("Account", require("./account/model-definition").properties); | ||
static modelName = "Account"; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto for single quotes
"required": true | ||
} | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
single quotes and keys don't need quotes
function createAccountController() { | ||
accCtrl = new AccountController(); | ||
accCtrl.repository = new accountRepository(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No abbreviations with var names pls
Please update the README with working instructions before landing too |
2496c42
to
7b654da
Compare
@slnode test please |
connect to https://github.com/strongloop-internal/scrum-apex/issues/215
connect to https://github.com/strongloop-internal/scrum-apex/issues/228