Very popular JavaScript ORM library:
http://bookshelfjs.org/
+1
My attempt at a bookshelf typescript definition is not quite production ready, but can be used: https://github.com/arcticwaters/DefinitelyTyped/tree/master/bookshelf
There's a bit more work to be done before it's ready for a pull request. I'm hoping to test it against a small script I'm working to see if its viable. So far, so good.
@arcticwaters :+1: Excellent.
+1
Is this the correct way to be using Bookshelf + TypeScript?
// config.ts
import * as bookshelf from 'bookshelf';
let DBConfig = {
client: 'mysql',
debug: true,
connection: {...}
};
export default bookshelf(require('knex')(DBConfig));
// User.ts
import bookshelf from "./config";
import {promisify} from 'bluebird';
import {compare} from 'bcrypt';
let compareAsync = promisify(compare);
export class User extends bookshelf.Model<User> {
get tableName() { return 'users'; }
constructor(params: any) {
super(params);
}
static login(email: string, password: string) {
if (!email || !password) {
throw new Error('Email and password are both required');
}
return new this({
email: email.toLowerCase().trim()
}).fetch({require: true}).tap(function(user) {
return compareAsync(password, user.get('password'))
.then(function(res) {
if (!res) throw new Error('Invalid password');
});
});
}
};
Yup, that should work. You might want to use some of that typescript sugar too
user => compareAsync(...)
One thing to note: depending on how ts gets compiled to js, exporting the bookshelf object can be problematic. Sometimes importing creates a new instance which will open a new connection and connection pool and you might get weird errors like one bookself user class is not the same as the other bookshelf user class. Sometimes the import doesn't compile correctly at all and you try and import null. Again depends on how you're compiling to js. One, albeit messy, workaround pass it around in a global variable:
let bookshelf = (global as any).bookshelf as Bookshelf;
Thanks @arcticwaters . Is there a way that I could check to see if there are multiple connections/connection pools open to determine if I am having this error?
One way is to just test the imported instances are the same. Import config.ts in one file and store it in a global. Then import it in a second file and check for equality using ==. Or you may be able to check the number of active connections from the database side if it logs connections. You may have to limit the number of connections to 1 per pool though to test this way. Of course, you could always inspect the compiled js.
How does this look? Thanks for the help.
// compiled config.js
"use strict";
var bookshelf = require('bookshelf');
var DBConfig = {
client: 'mysql',
debug: true,
connection: {...}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = bookshelf(require('knex')(DBConfig));
For anyone with additional questions about TypeScript + Bookshelf with ES6 classes, see https://github.com/tgriesser/bookshelf/issues/756
Not sure how much more help I can be from this end; I'm not sure what problem you're trying to solve. Both your code examples looks fine to me. I've just tried to point out requirements of the bindings (really bookshelf itself), that may bite you if the stars align a certain way :wink:.
It's really the underlying typescript -> javascript conversion and how you tie your javascript files together that _may_ cause problems. I'm not an expert in all the tools you could use to tie javascript files together, so my only advice is to check the generated javascript if you're having problems.
@AlexLeung Hello, I used your code base but found a problem.
When I used User.where({ email: 'xxx' }).count();, the return value of where() method is only a {}. It said the definition of count() is not found.
have same problem as mentioned by @imWildCat
If I am using the registry plugin which adds a Bookshelf.model function, what is the best way to add this function to the types for Typescript?
@imWildCat @yusufsyaifudin or anyone else who sees "{}" as the return type for methods like ".where":
You need to add the type parameter like this: Account.where<Account>(/* ... */). By default the type parameter for that seems to be `{}.
Unfortunately the type system in typescript isn't strong enough to associate instance typing to static methods which is why you need to specify the type "twice": Account.where<Account>. In your case, since there's no lower bound on the type, it defaults to {} when left unspecified. The documentation today appears to say it should be where<T extends Model<any> | knex.QueryBuilder>, but I probably found a undocumented case where that wasn't strictly true. I don't recall the details.
@colegleason I don't know of a good way to do it. You might be stuck with the universal typescript help button: cast Bookshelf to any, then call what you want on it.
Hi everyone!
Has anyone managed to use the registry plugin with TypeScript?
Hello.
I think we need define of bookshelf plugin.
So, first, I would like to define pagination plugin.
I think two plans.
@types/bookshelf@types/bookshelf-pagination.Which should I do?
Let me know if you have any ideas, please!
Why not just use https://github.com/typeorm/typeorm at this point?
typeorm is good orm.
But, I have to use bookshelf for adding function to old application.
Most helpful comment
have same problem as mentioned by @imWildCat