Skip to content

Commit

Permalink
Add first function, bumps version to 0.2.4
Browse files Browse the repository at this point in the history
  • Loading branch information
nhat-phan committed Jan 15, 2018
1 parent bb22366 commit 9c71362
Show file tree
Hide file tree
Showing 20 changed files with 123 additions and 8 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
If you are Laravel Eloquent lover and want to use it in `Node JS` you will love `Najs Eloquent`. `Najs Eloquent` is
Laravel Eloquent, written in `Typescript` (with some helpers you can use it in Javascript for sure).

Current version - `0.2.3` - is targeted to Mongodb only (using ORM Mongoose as a backer). Because MongoDB is not RDB
Current version - `0.2.4` - is targeted to Mongodb only (using ORM Mongoose as a backer). Because MongoDB is not RDB
some features of Laravel Eloquent are removed such as relationship or scope. In the way to `1.0.0`, the `Najs Eloquent`
will support full Eloquent's features with difference kinds of DB like `MySql`, `PostgreSQL` or `SqlLite`
(use `knex` as a query builder).

You can take a look on fully setup example in [najs-eloquent-example](https://github.com/najs-framework/najs-eloquent-example) repository.
You can take a look on fully setup example in [najs-eloquent-example](https://github.com/najs-framework/najs-eloquent-example) repository or try it in [Playground](http://35.196.114.98/ide.html).

# Installation

Expand Down Expand Up @@ -81,7 +81,7 @@ register(CustomClass, 'MongooseProvider')

# Example

Please checkout fully setup example in [najs-eloquent-example](https://github.com/najs-framework/najs-eloquent-example) repository.
Please checkout fully setup example in [najs-eloquent-example](https://github.com/najs-framework/najs-eloquent-example) repository or try it in [Playground](http://35.196.114.98/ide.html).

# Usage

Expand Down
3 changes: 2 additions & 1 deletion dist/lib/eloquent/EloquentBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class EloquentBase {
return collect_js_1.default(dataset.map(item => this.newInstance(item)));
}
fill(data) {
const fillableAttributes = lodash_1.pick(data, this.getFillable());
const fillable = this.getFillable();
const fillableAttributes = fillable.length > 0 ? lodash_1.pick(data, fillable) : data;
for (const key in fillableAttributes) {
if (this.isFillable(key)) {
this.setAttribute(key, fillableAttributes[key]);
Expand Down
1 change: 1 addition & 0 deletions dist/lib/eloquent/EloquentMongoose.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export declare abstract class EloquentMongoose<T> extends EloquentBase<Document
static get(fields: string[]): Promise<any>;
static get(...fields: Array<string | string[]>): Promise<any>;
static find(id: any): Promise<any>;
static first(): Promise<any>;
static pluck(value: string): Promise<Object>;
static pluck(value: string, key: string): Promise<Object>;
static count(): Promise<number>;
Expand Down
3 changes: 3 additions & 0 deletions dist/lib/eloquent/EloquentMongoose.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ class EloquentMongoose extends EloquentBase_1.EloquentBase {
}
return this.prototype.newQuery(this.softDeletes).find();
}
static first() {
return this.prototype.newQuery(this.softDeletes).first();
}
static pluck(value, key) {
return this.prototype.newQuery(this.softDeletes).pluck(value, key);
}
Expand Down
1 change: 1 addition & 0 deletions dist/lib/interfaces/IQueryFetchResult.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export interface IQueryFetchResult<T = {}> {
get(): Promise<Collection<T>>;
all(): Promise<Collection<T>>;
find(): Promise<T | null>;
first(): Promise<T | null>;
count(): Promise<number>;
pluck(value: string): Promise<Object>;
pluck(value: string, key: string): Promise<Object>;
Expand Down
1 change: 1 addition & 0 deletions dist/lib/query-builders/MongooseQueryBuilder.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export declare class MongooseQueryBuilder<T = {}> extends QueryBuilder implement
get(): Promise<Collection<any>>;
all(): Promise<Collection<any>>;
find(): Promise<any | null>;
first(): Promise<any | null>;
pluck(value: string): Promise<Object>;
pluck(value: string, key: string): Promise<Object>;
count(): Promise<number>;
Expand Down
5 changes: 5 additions & 0 deletions dist/lib/query-builders/MongooseQueryBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ class MongooseQueryBuilder extends QueryBuilder_1.QueryBuilder {
return null;
});
}
first() {
return __awaiter(this, void 0, void 0, function* () {
return this.find();
});
}
pluck(value, key) {
return __awaiter(this, void 0, void 0, function* () {
this.selectedFields = [];
Expand Down
1 change: 1 addition & 0 deletions dist/lib/specs/EloquentMongooseSpec.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export declare type EloquentMongooseSpec<Attr, Class> = {
get(...fields: Array<string | string[]>): Promise<Collection<EloquentMongoose<Attr> & Attr & Class>>;
find(): Promise<EloquentMongoose<Attr> & Attr & Class>;
find(id: any): Promise<EloquentMongoose<Attr> & Attr & Class>;
first(): Promise<EloquentMongoose<Attr> & Attr & Class>;
pluck(value: string): Promise<Object>;
pluck(value: string, key: string): Promise<Object>;
count(): Promise<Number>;
Expand Down
9 changes: 9 additions & 0 deletions dist/test/eloquent/EloquentBase.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,15 @@ describe('Eloquent', function () {
});
expect(user.toJson()).toEqual({ first_name: 'john' });
});
it('could fill any attributes by default except start with _', function () {
const user = new User();
user['guarded'] = [];
user.fill({
not_config: 'filled',
_test: 'will not filled'
});
expect(user.toJson()).toEqual({ not_config: 'filled' });
});
});
describe('forceFill()', function () {
it('fills data even they are not fillable', function () {
Expand Down
28 changes: 27 additions & 1 deletion dist/test/eloquent/EloquentMongoose.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,24 @@ describe('EloquentMongoose', function () {
yield util_1.delete_collection(mongoose, 'softdelete2s');
});
});
it('can be initialized with static function', function () {
it('can be initialized with static function .all()', function () {
return __awaiter(this, void 0, void 0, function* () {
const users = yield User.all();
expect(users.count()).toEqual(0);
});
});
it('can be initialized with static function .find()', function () {
return __awaiter(this, void 0, void 0, function* () {
const user = yield User.find();
expect(user).toBeNull();
});
});
it('can be initialized with static function .first()', function () {
return __awaiter(this, void 0, void 0, function* () {
const user = yield User.first();
expect(user).toBeNull();
});
});
describe('ActiveRecord', function () {
describe('save()', function () {
it('can create a document', function () {
Expand Down Expand Up @@ -536,6 +548,20 @@ describe('EloquentMongoose', function () {
findSpy.restore();
});
});
describe('first()', function () {
it('creates MongooseQueryBuilder with model from prototype.getModelName(), and calls .first()', function () {
const getModelNameSpy = Sinon.spy(User.prototype, 'getModelName');
expect(User.first()).toBeInstanceOf(Promise);
expect(getModelNameSpy.called).toBe(true);
getModelNameSpy.restore();
});
it('passes all params to MongooseQueryBuilder.first()', function () {
const firstSpy = Sinon.spy(MongooseQueryBuilder_1.MongooseQueryBuilder.prototype, 'first');
User.first();
expect(firstSpy.calledWith()).toBe(true);
firstSpy.restore();
});
});
describe('pluck()', function () {
it('creates MongooseQueryBuilder with model from prototype.getModelName(), and calls .pluck()', function () {
const getModelNameSpy = Sinon.spy(User.prototype, 'getModelName');
Expand Down
10 changes: 10 additions & 0 deletions dist/test/query-builders/MongooseQueryBuilder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,16 @@ describe('MongooseQueryBuilder', function () {
});
});
});
describe('first()', function () {
it('just an alias of find', function () {
return __awaiter(this, void 0, void 0, function* () {
const query = new MongooseQueryBuilder_1.MongooseQueryBuilder('User');
const findSpy = Sinon.spy(query, 'find');
yield query.first();
expect(findSpy.called).toBe(true);
});
});
});
describe('pluck()', function () {
it('plucks all data of collection and returns an Object', function () {
return __awaiter(this, void 0, void 0, function* () {
Expand Down
3 changes: 2 additions & 1 deletion lib/eloquent/EloquentBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ export abstract class EloquentBase<NativeRecord extends Object = {}> implements
}

fill(data: Object): this {
const fillableAttributes = pick(data, this.getFillable())
const fillable = this.getFillable()
const fillableAttributes = fillable.length > 0 ? pick(data, fillable) : data
for (const key in fillableAttributes) {
if (this.isFillable(key)) {
this.setAttribute(key, fillableAttributes[key])
Expand Down
4 changes: 4 additions & 0 deletions lib/eloquent/EloquentMongoose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,10 @@ export abstract class EloquentMongoose<T> extends EloquentBase<Document & T> {
return this.prototype.newQuery(this.softDeletes).find()
}

static first(): Promise<any> {
return this.prototype.newQuery(this.softDeletes).first()
}

static pluck(value: string): Promise<Object>
static pluck(value: string, key: string): Promise<Object>
static pluck(value: string, key?: string): Promise<Object> {
Expand Down
1 change: 1 addition & 0 deletions lib/interfaces/IQueryFetchResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export interface IQueryFetchResult<T = {}> {
get(): Promise<Collection<T>>
all(): Promise<Collection<T>>
find(): Promise<T | null>
first(): Promise<T | null>
count(): Promise<number>

pluck(value: string): Promise<Object>
Expand Down
4 changes: 4 additions & 0 deletions lib/query-builders/MongooseQueryBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ export class MongooseQueryBuilder<T = {}> extends QueryBuilder
return null
}

async first(): Promise<any | null> {
return this.find()
}

async pluck(value: string): Promise<Object>
async pluck(value: string, key: string): Promise<Object>
async pluck(value: string, key?: string): Promise<Object> {
Expand Down
2 changes: 2 additions & 0 deletions lib/specs/EloquentMongooseSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ export type EloquentMongooseSpec<Attr, Class> = {
find(): Promise<EloquentMongoose<Attr> & Attr & Class>
find(id: any): Promise<EloquentMongoose<Attr> & Attr & Class>

first(): Promise<EloquentMongoose<Attr> & Attr & Class>

pluck(value: string): Promise<Object>
pluck(value: string, key: string): Promise<Object>

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "najs-eloquent",
"version": "0.2.3",
"version": "0.2.4",
"scripts": {
"build": "npm run build-ts && npm run tslint && npm run copy-js-files",
"copy-js-files": "chmod u+x ./script/copy-js-files.sh && ./script/copy-js-files.sh",
Expand Down
10 changes: 10 additions & 0 deletions test/eloquent/EloquentBase.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,16 @@ describe('Eloquent', function() {
})
expect(user.toJson()).toEqual({ first_name: 'john' })
})

it('could fill any attributes by default except start with _', function() {
const user = new User()
user['guarded'] = []
user.fill({
not_config: 'filled',
_test: 'will not filled'
})
expect(user.toJson()).toEqual({ not_config: 'filled' })
})
})

describe('forceFill()', function() {
Expand Down
28 changes: 27 additions & 1 deletion test/eloquent/EloquentMongoose.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,21 @@ describe('EloquentMongoose', function() {
await delete_collection(mongoose, 'softdelete2s')
})

it('can be initialized with static function', async function() {
it('can be initialized with static function .all()', async function() {
const users = await User.all()
expect(users.count()).toEqual(0)
})

it('can be initialized with static function .find()', async function() {
const user = await User.find()
expect(user).toBeNull()
})

it('can be initialized with static function .first()', async function() {
const user = await User.first()
expect(user).toBeNull()
})

describe('ActiveRecord', function() {
describe('save()', function() {
it('can create a document', async function() {
Expand Down Expand Up @@ -606,6 +616,22 @@ describe('EloquentMongoose', function() {
})
})

describe('first()', function() {
it('creates MongooseQueryBuilder with model from prototype.getModelName(), and calls .first()', function() {
const getModelNameSpy = Sinon.spy(User.prototype, 'getModelName')
expect(User.first()).toBeInstanceOf(Promise)
expect(getModelNameSpy.called).toBe(true)
getModelNameSpy.restore()
})

it('passes all params to MongooseQueryBuilder.first()', function() {
const firstSpy = Sinon.spy(MongooseQueryBuilder.prototype, 'first')
User.first()
expect(firstSpy.calledWith()).toBe(true)
firstSpy.restore()
})
})

describe('pluck()', function() {
it('creates MongooseQueryBuilder with model from prototype.getModelName(), and calls .pluck()', function() {
const getModelNameSpy = Sinon.spy(User.prototype, 'getModelName')
Expand Down
9 changes: 9 additions & 0 deletions test/query-builders/MongooseQueryBuilder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,15 @@ describe('MongooseQueryBuilder', function() {
})
})

describe('first()', function() {
it('just an alias of find', async function() {
const query = new MongooseQueryBuilder('User')
const findSpy = Sinon.spy(query, 'find')
await query.first()
expect(findSpy.called).toBe(true)
})
})

describe('pluck()', function() {
it('plucks all data of collection and returns an Object', async function() {
const query = new MongooseQueryBuilder('User')
Expand Down

0 comments on commit 9c71362

Please sign in to comment.