Skip to content

Commit f33859c

Browse files
committed
Convenience methods
1 parent 1f556d5 commit f33859c

File tree

7 files changed

+168
-45
lines changed

7 files changed

+168
-45
lines changed

dist/vuex-orm-apollo.esm.js

+72-3
Original file line numberDiff line numberDiff line change
@@ -9765,7 +9765,7 @@ var Model = /** @class */ (function () {
97659765
return found;
97669766
};
97679767
Model.prototype.getRecordWithId = function (id) {
9768-
return this.baseModel.getters('query')().withAllRecursive().where('id', id).first();
9768+
return this.baseModel.query().withAllRecursive().where('id', id).first();
97699769
};
97709770
Model.prototype.fieldIsNumber = function (field) {
97719771
if (!field)
@@ -9926,13 +9926,82 @@ var VuexORMApollo = /** @class */ (function () {
99269926
* This method will setup following Vuex action: fetch, persist, push, destroy, mutate
99279927
*/
99289928
VuexORMApollo.prototype.setupMethods = function () {
9929+
// Register store actions
99299930
this.context.components.subActions.fetch = this.fetch.bind(this);
99309931
this.context.components.subActions.persist = this.persist.bind(this);
99319932
this.context.components.subActions.push = this.push.bind(this);
99329933
this.context.components.subActions.destroy = this.destroy.bind(this);
99339934
this.context.components.subActions.mutate = this.customMutation.bind(this);
9935+
// Register static model convenience methods
9936+
this.context.components.Model.fetch = function (filter, bypassCache) {
9937+
if (bypassCache === void 0) { bypassCache = false; }
9938+
return __awaiter(this, void 0, void 0, function () {
9939+
var filterObj;
9940+
return __generator(this, function (_a) {
9941+
filterObj = filter;
9942+
if (typeof filterObj !== 'object')
9943+
filterObj = { id: filter };
9944+
return [2 /*return*/, this.dispatch('fetch', { filter: filterObj, bypassCache: bypassCache })];
9945+
});
9946+
});
9947+
};
9948+
this.context.components.Model.mutate = function (params) {
9949+
return __awaiter(this, void 0, void 0, function () {
9950+
return __generator(this, function (_a) {
9951+
return [2 /*return*/, this.dispatch('mutate', params)];
9952+
});
9953+
});
9954+
};
9955+
// Register model convenience methods
9956+
this.context.components.Model.prototype.$mutate = function (params) {
9957+
return __awaiter(this, void 0, void 0, function () {
9958+
return __generator(this, function (_a) {
9959+
if (!params['id'])
9960+
params['id'] = this.id;
9961+
return [2 /*return*/, this.$dispatch('mutate', params)];
9962+
});
9963+
});
9964+
};
9965+
this.context.components.Model.prototype.$persist = function () {
9966+
return __awaiter(this, void 0, void 0, function () {
9967+
return __generator(this, function (_a) {
9968+
return [2 /*return*/, this.$dispatch('persist', { id: this.id })];
9969+
});
9970+
});
9971+
};
9972+
this.context.components.Model.prototype.$push = function () {
9973+
return __awaiter(this, void 0, void 0, function () {
9974+
return __generator(this, function (_a) {
9975+
return [2 /*return*/, this.$dispatch('push', { data: this })];
9976+
});
9977+
});
9978+
};
9979+
this.context.components.Model.prototype.$destroy = function () {
9980+
return __awaiter(this, void 0, void 0, function () {
9981+
return __generator(this, function (_a) {
9982+
return [2 /*return*/, this.$dispatch('destroy', { id: this.id })];
9983+
});
9984+
});
9985+
};
9986+
this.context.components.Model.prototype.$deleteAndDestroy = function () {
9987+
return __awaiter(this, void 0, void 0, function () {
9988+
return __generator(this, function (_a) {
9989+
switch (_a.label) {
9990+
case 0: return [4 /*yield*/, this.$delete()];
9991+
case 1:
9992+
_a.sent();
9993+
return [2 /*return*/, this.$destroy()];
9994+
}
9995+
});
9996+
});
9997+
};
99349998
// this.components.subActions.destroyAll = this.destroyAll.bind(this);
99359999
};
10000+
/**
10001+
* Helper to dispatch actions on the store
10002+
*/
10003+
VuexORMApollo.prototype.dispatch = function (params) {
10004+
};
993610005
/**
993710006
* Will be called, when dispatch('entities/something/fetch') is called.
993810007
*
@@ -9998,7 +10067,7 @@ var VuexORMApollo = /** @class */ (function () {
999810067
// in this case this.mutate has inserted a new record instead of updating the existing one.
999910068
// We can see that because $isPersisted is still false then.
1000010069
this.context.logger.log('Dropping deprecated record with ID', oldRecord.id);
10001-
return [4 /*yield*/, model.baseModel.dispatch('delete', { where: oldRecord.id })];
10070+
return [4 /*yield*/, model.baseModel.delete({ where: oldRecord.id })];
1000210071
case 2:
1000310072
_c.sent();
1000410073
_c.label = 3;
@@ -10121,7 +10190,7 @@ var VuexORMApollo = /** @class */ (function () {
1012110190
}
1012210191
else {
1012310192
this.context.logger.log("Couldn't find the record of type", model.pluralName, 'in', insertedData, '. Fallback to find()');
10124-
return [2 /*return*/, model.baseModel.getters('query')().last()];
10193+
return [2 /*return*/, model.baseModel.query().last()];
1012510194
}
1012610195
_a.label = 3;
1012710196
case 3: return [2 /*return*/, true];

docs/guide/fetch/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ When fetching all returned records replace the respective existing records in th
6464
You can also fetch single records via ID:
6565

6666
```javascript
67+
await Comment.fetch(42);
68+
// or
6769
await Comment.fetch({ id: 42 });
6870
// or
6971
await Comment.dispatch('fetch', { filter: { id: 42 }})

src/interfaces.ts

+5
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,8 @@ export interface Field {
3434
localKey?: string;
3535
foreignKey?: string;
3636
}
37+
38+
export class PatchedModel extends ORMModel {
39+
static async fetch(filter: any, bypassCache = false): Promise<any> { return; };
40+
static async mutate(params: any): Promise<any> { return; };
41+
}

src/vuex-orm-apollo.ts

+46-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Model from './model';
22
import { ApolloClient, FetchPolicy } from 'apollo-client';
33
import { HttpLink } from 'apollo-link-http';
44
import { InMemoryCache } from 'apollo-cache-inmemory';
5-
import { Data, ActionParams, Arguments, DispatchFunction } from './interfaces';
5+
import {Data, ActionParams, Arguments, DispatchFunction, PatchedModel} from './interfaces';
66
import QueryBuilder from './queryBuilder';
77
import { upcaseFirstLetter } from './utils';
88
import Context from './context';
@@ -67,15 +67,60 @@ export default class VuexORMApollo {
6767
* This method will setup following Vuex action: fetch, persist, push, destroy, mutate
6868
*/
6969
private setupMethods () {
70+
// Register store actions
7071
this.context.components.subActions.fetch = this.fetch.bind(this);
7172
this.context.components.subActions.persist = this.persist.bind(this);
7273
this.context.components.subActions.push = this.push.bind(this);
7374
this.context.components.subActions.destroy = this.destroy.bind(this);
7475
this.context.components.subActions.mutate = this.customMutation.bind(this);
7576

77+
78+
// Register static model convenience methods
79+
(this.context.components.Model as (typeof PatchedModel)).fetch = async function(filter: any, bypassCache = false) {
80+
let filterObj = filter;
81+
if (typeof filterObj !== 'object') filterObj = { id: filter };
82+
return this.dispatch('fetch', { filter: filterObj, bypassCache });
83+
};
84+
85+
(this.context.components.Model as (typeof PatchedModel)).mutate = async function(params: any) {
86+
return this.dispatch('mutate', params);
87+
};
88+
89+
90+
// Register model convenience methods
91+
this.context.components.Model.prototype.$mutate = async function(params: any) {
92+
if (!params['id']) params['id'] = this.id;
93+
return this.$dispatch('mutate', params);
94+
};
95+
96+
this.context.components.Model.prototype.$persist = async function() {
97+
return this.$dispatch('persist', { id: this.id });
98+
};
99+
100+
this.context.components.Model.prototype.$push = async function() {
101+
return this.$dispatch('push', { data: this });
102+
};
103+
104+
this.context.components.Model.prototype.$destroy = async function() {
105+
return this.$dispatch('destroy', { id: this.id });
106+
};
107+
108+
this.context.components.Model.prototype.$deleteAndDestroy = async function() {
109+
await this.$delete();
110+
return this.$destroy();
111+
};
112+
76113
// this.components.subActions.destroyAll = this.destroyAll.bind(this);
77114
}
78115

116+
117+
/**
118+
* Helper to dispatch actions on the store
119+
*/
120+
public dispatch(params: ActionParams) {
121+
122+
}
123+
79124
/**
80125
* Will be called, when dispatch('entities/something/fetch') is called.
81126
*

test/integration/VuexORMApollo.spec.js

+30-29
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,18 @@ class Comment extends ORMModel {
7171
}
7272

7373
describe('VuexORMApollo', () => {
74-
beforeEach(() => {
74+
beforeEach(async () => {
7575
[store, vuexOrmApollo] = createStore([{ model: User }, { model: Post }, { model: Video }, { model: Comment }]);
7676

77-
store.dispatch('entities/users/insert', { data: { id: 1, name: 'Charlie Brown' }});
78-
store.dispatch('entities/users/insert', { data: { id: 2, name: 'Peppermint Patty' }});
79-
store.dispatch('entities/posts/insert', { data: { id: 1, otherId: 9, userId: 1, title: 'Example post 1', content: 'Foo' }});
80-
store.dispatch('entities/posts/insert', { data: { id: 2, otherId: 10, userId: 1, title: 'Example post 2', content: 'Bar' }});
81-
store.dispatch('entities/videos/insert', { data: { id: 1, otherId: 11, userId: 1, title: 'Example video', content: 'Video' }});
82-
store.dispatch('entities/comments/insert', { data: { id: 1, userId: 1, subjectId: 1, subjectType: 'videos', content: 'Example comment 1' }});
83-
store.dispatch('entities/comments/insert', { data: { id: 2, userId: 2, subjectId: 1, subjectType: 'posts', content: 'Example comment 2' }});
84-
store.dispatch('entities/comments/insert', { data: { id: 3, userId: 2, subjectId: 2, subjectType: 'posts', content: 'Example comment 3' }});
77+
await User.insert({ data: { id: 1, name: 'Charlie Brown' }});
78+
await User.insert({ data: { id: 1, name: 'Charlie Brown' }});
79+
await User.insert({ data: { id: 2, name: 'Peppermint Patty' }});
80+
await Post.insert({ data: { id: 1, otherId: 9, userId: 1, title: 'Example post 1', content: 'Foo' }});
81+
await Post.insert({ data: { id: 2, otherId: 10, userId: 1, title: 'Example post 2', content: 'Bar' }});
82+
await Video.insert({ data: { id: 1, otherId: 11, userId: 1, title: 'Example video', content: 'Video' }});
83+
await Comment.insert({ data: { id: 1, userId: 1, subjectId: 1, subjectType: 'videos', content: 'Example comment 1' }});
84+
await Comment.insert({ data: { id: 2, userId: 2, subjectId: 1, subjectType: 'posts', content: 'Example comment 2' }});
85+
await Comment.insert({ data: { id: 3, userId: 2, subjectId: 2, subjectType: 'posts', content: 'Example comment 3' }});
8586
});
8687

8788
describe('fetch', () => {
@@ -114,7 +115,7 @@ describe('VuexORMApollo', () => {
114115
};
115116

116117
let request = await sendWithMockFetch(response, async () => {
117-
await store.dispatch('entities/posts/fetch', { filter: { id: 42 } });
118+
await Post.fetch(42);
118119
});
119120
expect(request).not.toEqual(null);
120121

@@ -165,17 +166,17 @@ query Post($id: ID!) {
165166
};
166167

167168
let request = await sendWithMockFetch(response, async () => {
168-
await store.dispatch('entities/users/fetch', { filter: { id: 1 } });
169+
await User.fetch(1);
169170
});
170171
expect(request).not.toEqual(null);
171172

172173
request = await sendWithMockFetch(response, async () => {
173-
await store.dispatch('entities/users/fetch', { filter: { id: 1 } });
174+
await User.fetch(1);
174175
}, true);
175176
expect(request).toEqual(null);
176177

177178
request = await sendWithMockFetch(response, async () => {
178-
await store.dispatch('entities/users/fetch', { filter: { id: 1 }, bypassCache: true });
179+
await User.fetch(1, true);
179180
});
180181
expect(request).not.toEqual(null);
181182
});
@@ -192,7 +193,7 @@ query Post($id: ID!) {
192193
};
193194

194195
const request = await sendWithMockFetch(response, async () => {
195-
await store.dispatch('entities/users/fetch', { filter: { id: 1 } });
196+
await User.fetch(1);
196197
});
197198

198199
expect(request.variables).toEqual({ id: 1 });
@@ -226,7 +227,7 @@ query User($id: ID!) {
226227
};
227228

228229
const request = await sendWithMockFetch(response, async () => {
229-
await store.dispatch('entities/users/fetch', { filter: { active: true } });
230+
await User.fetch({ active: true });
230231
});
231232

232233
expect(request.variables).toEqual({ active: true });
@@ -263,7 +264,7 @@ query Users($active: Boolean!) {
263264
};
264265

265266
const request = await sendWithMockFetch(response, async () => {
266-
await store.dispatch('entities/users/fetch');
267+
await User.fetch();
267268
});
268269

269270
expect(request.variables).toEqual({});
@@ -314,7 +315,8 @@ query Users {
314315
};
315316

316317
const request = await sendWithMockFetch(response, async () => {
317-
await store.dispatch('entities/posts/persist', { id: 1 });
318+
const post = Post.find(1);
319+
await post.$persist();
318320
});
319321

320322
expect(request.variables).toEqual({
@@ -378,7 +380,7 @@ mutation CreatePost($post: PostInput!) {
378380
const user = User.find(1);
379381
user.name = 'Snoopy';
380382

381-
await store.dispatch('entities/users/push', { data: user });
383+
await user.$push();
382384
});
383385

384386
expect(request.variables).toEqual({ id: 1, user: { id: 1, name: 'Snoopy' } });
@@ -408,7 +410,8 @@ mutation UpdateUser($id: ID!, $user: UserInput!) {
408410
};
409411

410412
const request = await sendWithMockFetch(response, async () => {
411-
await store.dispatch('entities/users/destroy', { id: 1 });
413+
const user = User.find(1);
414+
await user.$destroy();
412415
});
413416

414417
expect(request.variables).toEqual({ id: 1 });
@@ -450,16 +453,14 @@ mutation DeleteUser($id: ID!) {
450453
};
451454

452455
const request = await sendWithMockFetch(response, async () => {
453-
await store.dispatch('entities/posts/mutate', { mutation: 'upvotePost', post, captchaToken: '15' });
456+
await post.$mutate({ mutation: 'upvotePost', captchaToken: '15' });
454457
});
455458

456459
expect(request.variables.captchaToken).toEqual('15');
457-
expect(request.variables.post.title).toEqual(post.title);
458-
expect(request.variables.post.otherId).toEqual(post.otherId);
459-
expect(request.variables.post.userId).toEqual(1);
460+
expect(request.variables.id).toEqual(post.id);
460461
expect(request.query).toEqual(`
461-
mutation UpvotePost($post: PostInput!, $captchaToken: String!) {
462-
upvotePost(post: $post, captchaToken: $captchaToken) {
462+
mutation UpvotePost($captchaToken: String!, $id: ID!) {
463+
upvotePost(captchaToken: $captchaToken, id: $id) {
463464
id
464465
content
465466
title
@@ -488,7 +489,7 @@ mutation UpvotePost($post: PostInput!, $captchaToken: String!) {
488489

489490
describe('$isPersisted', () => {
490491
it('is false for newly created records', async () => {
491-
const insertedData = await store.dispatch('entities/users/insert', { data: { name: 'Snoopy' }} );
492+
const insertedData = await User.insert({ data: { name: 'Snoopy' }} );
492493
let user = insertedData.users[0];
493494
expect(user.$isPersisted).toBeFalsy();
494495

@@ -497,7 +498,7 @@ mutation UpvotePost($post: PostInput!, $captchaToken: String!) {
497498
});
498499

499500
it('is true for persisted records', async () => {
500-
const insertedData = await store.dispatch('entities/users/insert', { data: { name: 'Snoopy' }} );
501+
const insertedData = await User.insert({ data: { name: 'Snoopy' }} );
501502
let user = insertedData.users[0];
502503
const response = {
503504
data: {
@@ -516,7 +517,7 @@ mutation UpvotePost($post: PostInput!, $captchaToken: String!) {
516517
expect(user.$isPersisted).toBeFalsy();
517518

518519
await sendWithMockFetch(response, async () => {
519-
user = await store.dispatch('entities/users/persist', { id: 1 });
520+
user = await user.$persist();
520521
});
521522

522523
expect(user.$isPersisted).toBeTruthy();
@@ -553,7 +554,7 @@ mutation UpvotePost($post: PostInput!, $captchaToken: String!) {
553554
};
554555

555556
await sendWithMockFetch(response, async () => {
556-
await store.dispatch('entities/users/fetch', { filter: { id: 1 } });
557+
await User.fetch(1);
557558
});
558559

559560
const user = User.find(1);

test/unit/Model.spec.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ class Profile extends ORMModel {
2929
}
3030
}
3131

32-
beforeEach(() => {
32+
beforeEach(async () => {
3333
[store, vuexOrmApollo] = createStore([{ model: User }, { model: Profile }]);
34-
store.dispatch('entities/profiles/insert', { data: { id: 1, userId: 1 }});
35-
store.dispatch('entities/users/insert', { data: { id: 1, name: 'Foo Bar', profile: { id: 1 } }});
34+
await Profile.insert({ data: { id: 1, userId: 1 }});
35+
await User.insert({ data: { id: 1, name: 'Foo Bar', profile: { id: 1 } }});
3636

3737
model = vuexOrmApollo.context.getModel('user');
3838
});

0 commit comments

Comments
 (0)