UNPKG

@craftercms/studio-ui

Version:

Services, components, models & utils to build CrafterCMS authoring extensions.

251 lines (249 loc) 8.88 kB
/* * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ import { camelize } from './string'; import { stringify } from 'query-string'; export function pluckProps(source, ...props) { let omitNull = false; const object = {}; if (!source) { return object; } if (typeof props[0] === 'boolean') { omitNull = true; props.shift(); } props.forEach((_prop_) => { const prop = String(_prop_); const propName = prop.substr(prop.lastIndexOf('.') + 1); const value = retrieveProperty(source, prop); if (nnou(value) || !omitNull) { object[propName] = value; } }); return object; } export function reversePluckProps(source, ...props) { const object = {}; if (!source) { return object; } for (let key in source) { if (!props.includes(key) && source.hasOwnProperty(key)) { object[key] = source[key]; } } return object; } export function camelizeProps(obj) { return Object.entries(obj).reduce((camelized, [key, value]) => { camelized[camelize(key)] = value; return camelized; }, {}); } export function createLookupTable(list, idProp = 'id') { const table = {}; list.forEach((item) => { table[retrieveProperty(item, idProp)] = item; }); return table; } export function flattenHierarchical(root, childrenProp = 'children') { return (Array.isArray(root) ? root : [root]).flatMap((node) => { var _a; return Boolean(node) ? [node, ...flattenHierarchical((_a = node[childrenProp]) !== null && _a !== void 0 ? _a : [], childrenProp)] : null; }); } export function hierarchicalToLookupTable(root, childrenProp = 'children', idProp = 'id') { return createLookupTable(normalizeProp(flattenHierarchical(root, childrenProp), idProp, childrenProp), idProp); } // TODO: Types here could be better. export function normalizeProp(list, idProp = 'id', normalizeTargetProp = 'children') { return list.map((item) => { var _a; return Object.assign(Object.assign({}, item), { [normalizeTargetProp]: (_a = item[normalizeTargetProp]) === null || _a === void 0 ? void 0 : _a.map((child) => child[idProp]) }); }); } export function retrieveProperty(object, prop) { return object == null ? null : !prop ? object : prop.split('.').reduce((value, prop) => value[prop], object); } export function deleteProperty(object, prop) { delete object[prop]; return object; } export function setProperty(object, prop, value) { if (object) { const props = prop.split('.'); const propToSet = props.pop(); let target = retrieveProperty(object, props.join('.')); if (!target) { setProperty(object, props.join('.'), {}); target = retrieveProperty(object, props.join('.')); } target[propToSet] = value; } return object; } let UND; // Not Null Or Undefined (nnou) export function nnou(object) { return object !== null && object !== UND; } export const notNullOrUndefined = nnou; // Null Or Undefined (nou) export function nou(object) { return object === null || object === UND; } export const nullOrUndefined = nou; export function createEntityState(merge = {}) { return Object.assign({ byId: null, error: null, isFetching: null }, merge); } export function resolveEntityCollectionFetch(collection) { return createEntityState({ byId: createLookupTable(collection) }); } export function ref(ref) { return ref.current; } export function isPlainObject(obj) { return typeof obj === 'object' && obj !== null && obj.constructor === Object; } /** @deprecated Use extend(target, source) */ export function extendDeep(target, source) { return extend(target, source, { deep: true }); } /** @deprecated Use extend(target, source, { existingOnly: true }) */ export function extendDeepExistingProps(target, source) { return extend(target, source, { existingOnly: true }); } export function extend(target, source, options) { options = Object.assign({ existingOnly: false, deep: true }, options); if (!options.deep) { return Object.assign(target, source); } for (let prop in source) { if (source.hasOwnProperty(prop) && (!options.existingOnly || (options.existingOnly && prop in target))) { if (prop in target && isPlainObject(target[prop]) && isPlainObject(source[prop])) { extend(target[prop], source[prop]); } else { target[prop] = source[prop]; } } } return target; } export function toQueryString(args, options) { if (!args) { return ''; } options = Object.assign({ prefix: '?' }, options); return `${options.prefix}${stringify(args, options)}`; } export function applyDeserializedXMLTransforms(target, options) { var _a; const { arrays, lookupTables, renameTable } = options; const newObject = {}; for (let prop in target) { if (target.hasOwnProperty(prop)) { let newName = (_a = renameTable === null || renameTable === void 0 ? void 0 : renameTable[prop]) !== null && _a !== void 0 ? _a : prop; if (arrays === null || arrays === void 0 ? void 0 : arrays.includes(newName)) { if (typeof target[prop] === 'string') { newObject[newName] = []; } else if ( // @ts-ignore target[prop]._preserve === 'true' ) { newObject[newName] = target[prop]; delete newObject[newName]._preserve; } else { const keys = Object.keys(target[prop]); const childName = keys[0]; newObject[newName] = Array.isArray(target[prop][childName]) ? target[prop][childName] : [target[prop][childName]]; newObject[newName] = newObject[newName].map((item) => typeof item === 'object' ? applyDeserializedXMLTransforms(item, options) : item ); } } else if (lookupTables === null || lookupTables === void 0 ? void 0 : lookupTables.includes(newName)) { if (typeof target[prop] === 'string') { newObject[newName] = {}; } else { const keys = Object.keys(target[prop]); const childName = keys[0]; if (Array.isArray(target[prop][childName])) { // Assume single key as in `{ lookupTableKeyName: { childName: [{}, {}, {}] } }` const tempArray = target[prop][childName] .filter(Boolean) .map((item) => applyDeserializedXMLTransforms(item, options)); newObject[newName] = createLookupTable(tempArray); } else { // Assume multiple keys that will be used as the index newObject[newName] = {}; keys.forEach((key) => { newObject[newName][key] = applyDeserializedXMLTransforms(target[prop][key], options); }); } } } else { newObject[newName] = typeof target[prop] === 'object' ? applyDeserializedXMLTransforms(target[prop], options) : target[prop]; } } } return newObject; } export function deepCopy(target) { return JSON.parse(JSON.stringify(target)); } export const foo = {}; export function isApiResponse(source) { source = source !== null && source !== void 0 ? source : {}; return ( Object.prototype.hasOwnProperty.call(source, 'code') && Object.prototype.hasOwnProperty.call(source, 'message') ); } export function isAjaxError(source) { source = source !== null && source !== void 0 ? source : {}; return ( Object.prototype.hasOwnProperty.call(source, 'message') && Object.prototype.hasOwnProperty.call(source, 'status') && Object.prototype.hasOwnProperty.call(source, 'name') ); }