UNPKG

canner

Version:

Build CMS in few lines of code for different data sources

328 lines (279 loc) 8.37 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = actionsToVariables; exports.removeTypename = removeTypename; exports.addTypename = addTypename; exports.parseArrayToSet = parseArrayToSet; exports.genJsonPath = genJsonPath; exports.findSchema = findSchema; exports.addPath = addPath; exports.genRelationField = genRelationField; var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread")); var _lodash = require("lodash"); /** * change actions to variables which is the argument of graphql mutation */ function actionsToVariables(actions, schema) { var variables = { payload: {}, where: {} }; actions.forEach(function (action) { var _action$payload = action.payload, _action$payload$path = _action$payload.path, path = _action$payload$path === void 0 ? '' : _action$payload$path, value = _action$payload.value, id = _action$payload.id, relation = _action$payload.relation, key = _action$payload.key, transformGqlPayload = _action$payload.transformGqlPayload; var relationField = genRelationField(schema, key); var schemaWithPath = addPath(schema[key], ''); var jsonPath = findSchema(schemaWithPath, function (s) { return s.type === 'json'; }).map(function (v) { return v.path; }); value = parseArrayToSet(value, relationField, jsonPath, path ? "".concat(key, "/").concat(path) : key); switch (action.type) { case 'CREATE_ARRAY': { // remove null relation var ensureValue = (0, _lodash.pickBy)(value, function (v, k) { return v !== null && relationField.indexOf(k) === -1; }); (0, _lodash.merge)(variables.payload, ensureValue); break; } case 'UPDATE_ARRAY': case 'UPDATE_OBJECT': { (0, _lodash.merge)(variables.payload, value); (0, _lodash.merge)(variables.where, { id: id }); break; } case 'CONNECT': { if (relation && relation.type === 'toMany') { (0, _lodash.update)(variables.payload, path.split('/').concat('connect'), function (arr) { var connectValue = { id: value.id }; /* transformGqlPayload is a experimental usage */ if (transformGqlPayload) { connectValue = transformGqlPayload(connectValue, action); } if (!arr || !arr.concat) { return [connectValue]; } return arr.concat(connectValue); }); } else { (0, _lodash.set)(variables.payload, path.split('/').concat('connect'), { id: value.id }); } if (id) { (0, _lodash.merge)(variables.where, { id: id }); } break; } case 'CREATE_AND_CONNECT': { if (relation && relation.type === 'toMany') { (0, _lodash.update)(variables.payload, path.split('/').concat('create'), function (arr) { return (arr || []).concat(value); }); } else { (0, _lodash.set)(variables.payload, path.split('/').concat('create'), value); } (0, _lodash.merge)(variables.where, { id: id }); break; } case 'DISCONNECT': if (relation && relation.type === 'toMany') { (0, _lodash.update)(variables.payload, path.split('/').concat('disconnect'), function (arr) { return (arr || []).concat({ id: value.id }); }); } else { (0, _lodash.set)(variables.payload, path.split('/').concat('disconnect'), true); } if (id) { (0, _lodash.merge)(variables.where, { id: id }); } break; case 'DISCONNECT_AND_DELETE': if (relation && relation.type === 'toMany') { (0, _lodash.update)(variables.payload, path.split('/').concat('delete'), function (arr) { return (arr || []).concat(value); }); } else { (0, _lodash.set)(variables.payload, path.split('/').concat('delete'), true); } (0, _lodash.merge)(variables.where, { id: id }); break; case 'DELETE_ARRAY': (0, _lodash.merge)(variables.where, { id: id }); break; default: break; } }); variables.payload = removeTypename(variables.payload); if ((0, _lodash.isPlainObject)(variables.payload)) { delete variables.payload.id; } return variables; } /** * add typename: null in every object */ function removeTypename(payload) { if ((0, _lodash.isPlainObject)(payload)) { var newPayload = (0, _objectSpread2.default)({}, payload); delete newPayload.__typename; return (0, _lodash.mapValues)(newPayload, function (value) { return removeTypename(value); }); } else if (Array.isArray(payload)) { return payload.map(function (item) { return removeTypename(item); }); } return payload; } function addTypename(payload) { if ((0, _lodash.isArray)(payload)) { return payload.map(function (item) { return addTypename(item); }); } if ((0, _lodash.isPlainObject)(payload)) { return (0, _lodash.mapValues)(payload, function (item, key) { return key === '__typename' ? item : addTypename(item); }); } else { return payload; } } /** * * In canner graphql interface, * an array value should become a object with `set` keyword. * * for examples: * origin payload = { * hobbies: ['basketball', 'swim'] * name: 'James' * } * will become * { * hobbies: { * set: ['basketball', 'swim'] * }, * name: 'James' * } * */ function parseArrayToSet(payload, relationField, jsonPath, path) { if (jsonPath.indexOf(path) >= 0) { return payload; } if ((0, _lodash.isArray)(payload) && relationField.indexOf(path) === -1) { return { set: payload.map(function (v) { return parseArrayToSet(v, relationField, jsonPath, path); }) }; } else if ((0, _lodash.isPlainObject)(payload)) { return (0, _lodash.mapValues)(payload, function (v, k) { return parseArrayToSet(v, relationField, jsonPath, path ? "".concat(path, "/").concat(k) : k); }); } else { return payload; } } function genJsonPath(schema, key) { var keySchema = schema[key]; var items = {}; if (keySchema.type === 'object') { items = keySchema.items; } else if (keySchema.type === 'array') { items = keySchema.items.items; } else { return []; } return Object.keys(items).filter(function (field) { return items[field].type === 'relation'; }); } function findSchema(schema, filter) { var copy = []; if (filter(schema)) { copy.push(schema); } var items = schema.items; if (items) { if (typeof items.type === 'string') { copy = copy.concat(findSchema(items, filter)); } else { Object.keys(items).forEach(function (key) { return copy = copy.concat(findSchema(items[key], filter)); }); } } return copy; } function addPath(schema, path) { var items = schema.items, keyName = schema.keyName; var schemaPath = path; if (keyName) { schemaPath = path ? "".concat(path, "/").concat(keyName) : keyName; } schema.path = schemaPath; if (items) { if (typeof items.type !== 'string') { Object.keys(items).forEach(function (key) { return addPath(schema.items[key], schema.path); }); } else { addPath(items, schema.path); } } return schema; } /** * find the relation field in first level relation */ function genRelationField(schema, key) { var keySchema = schema[key]; var items = {}; if (keySchema.type === 'object') { items = keySchema.items; } else if (keySchema.type === 'array') { items = keySchema.items.items; } else { return []; } return Object.keys(items).filter(function (field) { return items[field].type === 'relation'; }); }