Skip to content

Commit 7bc3ad4

Browse files
committed
persist method
1 parent 26e70e9 commit 7bc3ad4

File tree

6 files changed

+424
-66
lines changed

6 files changed

+424
-66
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
This Vuex-ORM plugin let's you sync the data against a GraphQL API via Apollo.
88

9+
**Warning:** This plugin is still under development, use with care.
10+
911

1012
## Usage
1113

dist/vuex-orm-apollo.esm.js

Lines changed: 191 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8109,6 +8109,22 @@ var Logger = /** @class */ (function () {
81098109
console.log.apply(console, ['[Vuex-ORM-Apollo]'].concat(messages));
81108110
}
81118111
};
8112+
// TODO also accept gql parsed queries
8113+
Logger.prototype.logQuery = function (query) {
8114+
if (this.enabled) {
8115+
try {
8116+
this.group('Sending query:');
8117+
console.log(this.prettify(query));
8118+
this.groupEnd();
8119+
}
8120+
catch (e) {
8121+
console.error('[Vuex-ORM-Apollo] There is a syntax error in the query!', e, query);
8122+
}
8123+
}
8124+
};
8125+
Logger.prototype.prettify = function (query) {
8126+
return printer_1(parser_1(query));
8127+
};
81128128
return Logger;
81138129
}());
81148130

@@ -8150,6 +8166,7 @@ var __generator = (undefined && undefined.__generator) || function (thisArg, bod
81508166
var inflection$1 = require('inflection');
81518167
/**
81528168
* Plugin class
8169+
* TODO: Refactor to smaller classes
81538170
*/
81548171
var VuexORMApollo = /** @class */ (function () {
81558172
/**
@@ -8170,7 +8187,7 @@ var VuexORMApollo = /** @class */ (function () {
81708187
this.debugMode = options.debug;
81718188
this.logger = new Logger(this.debugMode);
81728189
this.collectModels();
8173-
this.setupFetch();
8190+
this.setupMethods();
81748191
this.httpLink = new HttpLink({
81758192
uri: '/graphql'
81768193
});
@@ -8202,21 +8219,25 @@ var VuexORMApollo = /** @class */ (function () {
82028219
});
82038220
};
82048221
/**
8205-
* This method will setup the fetch action for all entities.
8222+
* This method will setup following Vuex action: fetch, persist, push, destroy
82068223
*/
8207-
VuexORMApollo.prototype.setupFetch = function () {
8224+
VuexORMApollo.prototype.setupMethods = function () {
82088225
this.components.subActions.fetch = this.fetch.bind(this);
8226+
this.components.subActions.persist = this.persist.bind(this);
8227+
this.components.subActions.push = this.push.bind(this);
8228+
//this.components.subActions.destroy = this.destroy.bind(this);
8229+
//this.components.subActions.destroyAll = this.destroyAll.bind(this);
82098230
};
82108231
/**
82118232
* Will be called, when dispatch('entities/something/fetch') is called.
82128233
*
8213-
* @param {Filter} filter
8234+
* @param {Arguments} args
82148235
* @param {any} state
82158236
* @param {any} dispatch
82168237
* @returns {Promise<void>}
82178238
*/
82188239
VuexORMApollo.prototype.fetch = function (_a) {
8219-
var filter = _a.filter, state = _a.state, dispatch = _a.dispatch;
8240+
var state = _a.state, dispatch = _a.dispatch, filter = _a.filter;
82208241
return __awaiter(this, void 0, void 0, function () {
82218242
var query, data;
82228243
return __generator(this, function (_b) {
@@ -8236,10 +8257,70 @@ var VuexORMApollo = /** @class */ (function () {
82368257
});
82378258
});
82388259
};
8260+
/**
8261+
* Will be called, when dispatch('entities/something/persist') is called.
8262+
*
8263+
* @param {any} state
8264+
* @param {any} dispatch
8265+
* @param {any} id
8266+
* @returns {Promise<void>}
8267+
*/
8268+
VuexORMApollo.prototype.persist = function (_a, _b) {
8269+
var state = _a.state, dispatch = _a.dispatch;
8270+
var id = _b.id;
8271+
return __awaiter(this, void 0, void 0, function () {
8272+
var model, name, data, signature, query, newData, _c;
8273+
return __generator(this, function (_d) {
8274+
switch (_d.label) {
8275+
case 0:
8276+
model = this.getModel(state.$name);
8277+
name = "create" + VuexORMApollo.capitalizeFirstLetter(model.singularName);
8278+
data = model.baseModel.getters('find', { id: id })();
8279+
console.log('state', state);
8280+
console.log('model', model);
8281+
console.log('data', data);
8282+
signature = VuexORMApollo.buildArguments({ contract: { __type: 'Contract' } }, true);
8283+
query = "\n mutation " + name + signature + " {\n " + this.buildField(model, false, { contract: { __type: 'Contract' } }, true, undefined, name) + "\n }\n ";
8284+
this.logger.logQuery(query);
8285+
delete data.id;
8286+
return [4 /*yield*/, this.apolloClient.mutate({
8287+
"mutation": src(query),
8288+
"variables": (_c = {}, _c[model.singularName] = this.transformOutgoingData(data), _c)
8289+
})];
8290+
case 1:
8291+
newData = _d.sent();
8292+
// Insert incoming data into the store
8293+
this.storeData(newData, dispatch);
8294+
return [2 /*return*/, newData];
8295+
}
8296+
});
8297+
});
8298+
};
8299+
VuexORMApollo.prototype.push = function (_a, _b) {
8300+
var state = _a.state, dispatch = _a.dispatch;
8301+
var id = _b.id;
8302+
return __awaiter(this, void 0, void 0, function () {
8303+
return __generator(this, function (_c) {
8304+
return [2 /*return*/];
8305+
});
8306+
});
8307+
};
8308+
VuexORMApollo.prototype.transformOutgoingData = function (data) {
8309+
var returnValue = {};
8310+
Object.keys(data).forEach(function (key) {
8311+
var value = data[key];
8312+
// Ignore IDs and connections
8313+
if (!(value instanceof Array || key === 'id')) {
8314+
returnValue[key] = value;
8315+
}
8316+
});
8317+
return returnValue;
8318+
};
82398319
/**
82408320
* Transforms a set of incoming data to the format vuex-orm requires.
82418321
*
82428322
* @param {Data | Array<Data>} data
8323+
* @param {boolean} recursiveCall
82438324
* @returns {Data}
82448325
*/
82458326
VuexORMApollo.prototype.transformIncomingData = function (data, recursiveCall) {
@@ -8291,43 +8372,44 @@ var VuexORMApollo = /** @class */ (function () {
82918372
model.getRelations().forEach(function (field, name) {
82928373
if (!rootModel || name !== rootModel.singularName && name !== rootModel.pluralName) {
82938374
var multiple = field.constructor.name !== 'BelongsTo';
8294-
relationQueries.push(_this.buildField(name, multiple, undefined, rootModel || model));
8375+
relationQueries.push(_this.buildField(name, multiple, undefined, false, rootModel || model));
82958376
}
82968377
});
82978378
return relationQueries;
82988379
};
82998380
/**
83008381
* Builds a field for the GraphQL query and a specific model
8301-
* @param {Model} rootModel
8302-
* @param {string} modelName
8382+
* @param {Model|string} model
83038383
* @param {boolean} multiple
8304-
* @param {Filter} filter
8384+
* @param {Arguments} args
8385+
* @param {boolean} withVars
8386+
* @param {Model} rootModel
8387+
* @param {string} name
83058388
* @returns {string}
83068389
*/
8307-
VuexORMApollo.prototype.buildField = function (modelName, multiple, filter, rootModel) {
8390+
VuexORMApollo.prototype.buildField = function (model, multiple, args, withVars, rootModel, name) {
83088391
if (multiple === void 0) { multiple = true; }
8309-
var model = this.getModel(modelName);
8310-
var params = '';
8311-
if (filter && filter.id) {
8312-
params = "(id: " + filter.id + ")";
8313-
}
8392+
if (withVars === void 0) { withVars = false; }
8393+
model = this.getModel(model);
8394+
var params = VuexORMApollo.buildArguments(args, false, withVars);
8395+
var fields = "\n " + model.getQueryFields().join(' ') + "\n " + this.buildRelationsQuery(model, rootModel) + "\n ";
83148396
if (multiple) {
8315-
return "" + model.pluralName + params + " {\n nodes {\n " + model.getQueryFields().join(', ') + "\n " + this.buildRelationsQuery(model, rootModel) + "\n }\n }";
8397+
return "\n " + (name ? name : model.pluralName) + params + " {\n nodes {\n " + fields + "\n }\n }\n ";
83168398
}
83178399
else {
8318-
return "" + model.singularName + params + " {\n " + model.getQueryFields().join(', ') + "\n " + this.buildRelationsQuery(model, rootModel) + "\n }";
8400+
return "\n " + (name ? name : model.singularName) + params + " {\n " + fields + "\n }\n ";
83198401
}
83208402
};
83218403
/**
8322-
* Create a GraphQL query for the given model and filter options.
8404+
* Create a GraphQL query for the given model and arguments.
83238405
*
83248406
* @param {string} modelName
8325-
* @param {Filter} filter
8407+
* @param {Arguments} args
83268408
* @returns {any}
83278409
*/
8328-
VuexORMApollo.prototype.buildQuery = function (modelName, filter) {
8329-
var multiple = !(filter && filter.id);
8330-
var query = "{ " + this.buildField(modelName, multiple, filter) + " }";
8410+
VuexORMApollo.prototype.buildQuery = function (modelName, args) {
8411+
var multiple = !(args && args.get('id'));
8412+
var query = "{ " + this.buildField(modelName, multiple, args) + " }";
83318413
return src(query);
83328414
};
83338415
/**
@@ -8363,15 +8445,97 @@ var VuexORMApollo = /** @class */ (function () {
83638445
/**
83648446
* Returns a model by name
83658447
*
8366-
* @param {string} modelName
8448+
* @param {Model|string} model
83678449
* @returns {Model}
83688450
*/
8369-
VuexORMApollo.prototype.getModel = function (modelName) {
8370-
var model = this.models.get(inflection$1.singularize(modelName));
8371-
if (!model)
8372-
throw new Error("No such model " + modelName + "!");
8451+
VuexORMApollo.prototype.getModel = function (model) {
8452+
if (!(model instanceof Model)) {
8453+
model = this.models.get(inflection$1.singularize(model));
8454+
if (!model)
8455+
throw new Error("No such model " + model + "!");
8456+
}
83738457
return model;
83748458
};
8459+
/**
8460+
* Capitalizes the first letter of the given string.
8461+
*
8462+
* @param {string} string
8463+
* @returns {string}
8464+
*/
8465+
VuexORMApollo.capitalizeFirstLetter = function (string) {
8466+
return string.charAt(0).toUpperCase() + string.slice(1);
8467+
};
8468+
/**
8469+
* Generates the arguments string for a graphql query based on a given map.
8470+
*
8471+
* There are three types of arguments:
8472+
*
8473+
* 1) Signatures with attributes (signature = true)
8474+
* mutation createUser($name: String!)
8475+
*
8476+
* 2) Signatures with object (signature = true, args = { user: { __type: 'User' }})
8477+
* mutation createUser($user: User!)
8478+
*
8479+
* 3) Field with values (signature = false, valuesAsVariables = false)
8480+
* user(id: 15)
8481+
*
8482+
* 4) Field with variables (signature = false, valuesAsVariables = true)
8483+
* user(id: $id)
8484+
*
8485+
* 5) Field with object value (signature = false, valuesAsVariables = false, args = { user: { __type: 'User' }})
8486+
* createUser(user: {...})
8487+
*
8488+
* @param {Arguments | undefined} args
8489+
* @param {boolean} signature When true, then this method generates a query signature instead of key/value pairs
8490+
* @param {boolean} valuesAsVariables When true and abstract = false, then this method generates filter arguments with
8491+
* variables instead of values
8492+
* TODO: Query with variables too?
8493+
* @returns {String}
8494+
*/
8495+
VuexORMApollo.buildArguments = function (args, signature, valuesAsVariables) {
8496+
if (signature === void 0) { signature = false; }
8497+
if (valuesAsVariables === void 0) { valuesAsVariables = false; }
8498+
var returnValue = '';
8499+
var any = false;
8500+
if (args) {
8501+
Object.keys(args).forEach(function (key) {
8502+
var value = args[key];
8503+
// Ignore ids and connections
8504+
if (!(value instanceof Array || key === 'id')) {
8505+
any = true;
8506+
var typeOrValue = '';
8507+
if (signature) {
8508+
if (typeof value === 'object' && value.__type) {
8509+
// Case 2 (User!)
8510+
typeOrValue = value.__type + 'Input!';
8511+
}
8512+
else {
8513+
// Case 1 (String!)
8514+
typeOrValue = typeof value === 'number' ? 'Number!' : 'String!';
8515+
}
8516+
}
8517+
else if (valuesAsVariables) {
8518+
// Case 6 (user: $user)
8519+
typeOrValue = "$" + key;
8520+
}
8521+
else {
8522+
if (typeof value === 'object' && value.__type) {
8523+
// Case 3 ({name: 'Helga Hufflepuff"})
8524+
typeOrValue = value;
8525+
}
8526+
else {
8527+
// Case 3 ("someValue")
8528+
typeOrValue = typeof value === 'number' ? value : "\"" + value + "\"";
8529+
}
8530+
}
8531+
returnValue = returnValue + " " + ((signature ? '$' : '') + key) + ": " + typeOrValue;
8532+
}
8533+
});
8534+
if (any)
8535+
returnValue = "(" + returnValue + ")";
8536+
}
8537+
return returnValue;
8538+
};
83758539
return VuexORMApollo;
83768540
}());
83778541

0 commit comments

Comments
 (0)