UNPKG

canner

Version:

Build CMS in few lines of code for different data sources

312 lines (282 loc) 6.81 kB
// @flow import {pick, update, set, get} from 'lodash'; import { isCreateArray, isCreateNestedArrayInArray, isCreateNestedArrayInObject, isCreateAndConnect, isDeleteArray, isDeleteNestedArrayInArray, isDeleteNestedArrayInObject, isDisconnectAndDelete, isUpdateArray, isUpdateObject, isUpdateConnect, isSwapRootArray, isSwapArrayInArray, isSwapArrayInObject, isConnect, isDisconnect, isArrayAction } from './isAction'; import type {UpdateType, Action, ActionType} from './types'; export function generateAction(arg: { id: string, updateType: UpdateType, value: any, rootValue: any, relation: Object, transformGqlPayload?: Function }): Action<ActionType> { if (isCreateArray(arg)) { const {key} = splitId(arg.id, arg.rootValue); return { type: 'CREATE_ARRAY', payload: { key, id: arg.value.id, value: arg.value } } } if (isCreateNestedArrayInArray(arg)) { const {key, id, index, paths} = splitId(arg.id, arg.rootValue); const item = get(arg.rootValue, [key, index]); update(item, paths, arr => arr.concat(arg.value)); return { type: 'UPDATE_ARRAY', payload: { key, id, value: pick(item, paths.slice(0, 1)) } } } if (isCreateNestedArrayInObject(arg)) { const {key, id, paths} = splitId(arg.id, arg.rootValue); const item = get(arg.rootValue, [key]); update(item, paths, arr => arr ? arr.concat(arg.value) : [arg.value]); return { type: 'UPDATE_OBJECT', payload: { key, id, value: pick(item, paths.slice(0, 1)) } } } if (isCreateAndConnect(arg)) { const {key, id, path} = splitId(arg.id, arg.rootValue); return { type: 'CREATE_AND_CONNECT', payload: { key, id, path, value: arg.value, relation: arg.relation } } } if (isDeleteArray(arg)) { const {key, id} = splitId(arg.id, arg.rootValue); return { type: 'DELETE_ARRAY', payload: { key, id, value: {} } } } if (isDeleteNestedArrayInArray(arg)) { const {key, id, index, paths} = splitId(arg.id, arg.rootValue); const prePaths = paths.slice(0, -1); const deleteIndex = paths.slice(-1)[0]; const item = get(arg.rootValue, [key, index]); update(item, prePaths, arr => { arr.splice(deleteIndex, 1); return arr; }); return { type: 'UPDATE_ARRAY', payload: { key, id, value: pick(item, paths.slice(0, 1)) } } } if (isDeleteNestedArrayInObject(arg)) { const {key, id, paths} = splitId(arg.id, arg.rootValue); const prePaths = paths.slice(0, -1); const deleteIndex = paths.slice(-1)[0]; const item = get(arg.rootValue, [key]); update(item, prePaths, arr => { arr.splice(deleteIndex, 1); return arr; }); return { type: 'UPDATE_OBJECT', payload: { key, id, value: pick(item, paths.slice(0, 1)) } } } if (isDisconnectAndDelete(arg)) { const {key, id, path} = splitId(arg.id, arg.rootValue); return { type: 'DISCONNECT_AND_DELETE', payload: { key, id, path, value: arg.value, relation: arg.relation } }; } if (isUpdateArray(arg)) { const {key, id, paths, index} = splitId(arg.id, arg.rootValue); const item = get(arg.rootValue, [key, index]); set(item, paths, arg.value); return { type: 'UPDATE_ARRAY', payload: { key, id, value: pick(item, paths.slice(0, 1)) } }; } if (isUpdateConnect(arg)) { /** * unsupport action */ } if (isUpdateObject(arg)) { const {key, id, paths} = splitId(arg.id, arg.rootValue); const item = get(arg.rootValue, key); set(item, paths, arg.value); return { type: 'UPDATE_OBJECT', payload: { key, id, value: pick(item, paths.slice(0, 1)) } }; } if (isSwapRootArray(arg)) { /** * Swap root array is not allowed, */ } if (isSwapArrayInArray(arg)) { const {key, id, index, paths} = splitId(arg.id, arg.rootValue); // $FlowFixMe const {firstId, secondId} = arg.id; const nestedArrPath = paths.slice(0, -1); const item = get(arg.rootValue, [key, index]); const firstIndex = firstId.split('/').slice(-1)[0]; const secondIndex = secondId.split('/').slice(-1)[0]; update(item, nestedArrPath, arr => { let newArr = arr.slice(); newArr[firstIndex] = arr[secondIndex]; newArr[secondIndex] = arr[firstIndex]; return newArr; }) return { type: 'UPDATE_ARRAY', payload: { key, id, value: pick(item, paths.slice(0, 1)) } } } if (isSwapArrayInObject(arg)) { const {key, id, paths} = splitId(arg.id, arg.rootValue); // $FlowFixMe const {firstId, secondId} = arg.id; const nestedArrPath = paths.slice(0, -1); const item = get(arg.rootValue, [key]); const firstIndex = firstId.split('/').slice(-1)[0]; const secondIndex = secondId.split('/').slice(-1)[0]; update(item, nestedArrPath, arr => { let newArr = arr.slice(); newArr[firstIndex] = arr[secondIndex]; newArr[secondIndex] = arr[firstIndex]; return newArr; }) return { type: 'UPDATE_OBJECT', payload: { key, id, value: pick(item, paths.slice(0, 1)) } } } if (isConnect(arg)) { const {key, id, path} = splitId(arg.id, arg.rootValue); return { type: 'CONNECT', payload: { key, id, path, value: arg.value, relation: arg.relation, transformGqlPayload: arg.transformGqlPayload } }; } if (isDisconnect(arg)) { const {key, id, path} = splitId(arg.id, arg.rootValue); return { type: 'DISCONNECT', payload: { key, id, path, value: arg.value, relation: arg.relation } }; } return { type: 'NOOP', payload: { key: '', value: {} } } } function splitId(id, rootValue) { if (typeof id === 'string') { if (isArrayAction(rootValue, id)) { const [key, index, ...path] = id.split('/'); const item = rootValue[key][index]; return { key, id: item && item.id, index, paths: path, path: path.join('/') }; } else { const [key, ...path] = id.split('/'); return { key, path: path.join('/'), paths: path, id: '', index: '' }; } } return splitId(id.firstId, rootValue); }