UNPKG

@silexlabs/grapesjs-data-source

Version:
333 lines 13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getFilterFromToken = getFilterFromToken; exports.fromStored = fromStored; exports.tokenToField = tokenToField; exports.propertyToField = propertyToField; exports.expressionToFields = expressionToFields; exports.getExpressionResultType = getExpressionResultType; exports.getTokenOptions = getTokenOptions; exports.optionsToOptionsForm = optionsToOptionsForm; exports.getOptionObject = getOptionObject; exports.buildArgs = buildArgs; const dataSourceManager_1 = require("./dataSourceManager"); const utils_1 = require("../utils"); const state_1 = require("./state"); const lit_1 = require("lit"); /** * Add missing methonds to the filter * When filters are stored they lose their methods * @throws Error if the filter is not found */ function getFilterFromToken(token, filters) { if (token.type !== 'filter') throw new Error('Token is not a filter'); const filter = filters.find(filter => filter.id === token.id); if (!filter) { console.error('Filter not found', token); throw new Error(`Filter ${token.id} not found`); } return Object.assign(Object.assign(Object.assign({}, token), filter), { // Keep the options as they are stored options: token.options }); } /** * Get the token from its stored form * @throws Error if the token type is not found */ function fromStored(token, componentId) { var _a; // Handle invalid tokens - return null or throw a descriptive error if (!token || typeof token !== 'object') { console.error('Invalid token: not an object', token); throw new Error('Invalid token: expected an object'); } if (!token.type) { console.error('Invalid token: missing type property', token); throw new Error('Invalid token: missing type property'); } switch (token.type) { case 'filter': { if (token.optionsForm) return token; const original = (0, dataSourceManager_1.getFilters)().find(filter => filter.id === token.id); if (!original) { console.error('Filter not found', token); throw new Error(`Filter ${token.id} not found`); } return Object.assign(Object.assign(Object.assign({}, original), token), { type: 'filter' }); } case 'property': { if (token.optionsForm) return token; const field = propertyToField(token, componentId); if (!field) { console.error('Field not found for token', token); throw new Error(`Field ${token.fieldId} not found`); } return Object.assign(Object.assign(Object.assign({}, (_a = getTokenOptions(field)) !== null && _a !== void 0 ? _a : {}), token), { type: 'property', propType: 'field' }); } case 'state': return token; default: console.error('Unknown token type (reading type)', token); throw new Error('Unknown token type'); } } /** * Get the type corresponding to a token */ function tokenToField(token, prev, component) { var _a, _b, _c; switch (token.type) { case 'filter': { try { const filter = getFilterFromToken(token, (0, dataSourceManager_1.getFilters)()); try { if (filter.validate(prev)) { return filter.output(prev, (_a = filter.options) !== null && _a !== void 0 ? _a : {}); } } catch (e) { console.warn('Filter validate error:', e, { token, prev }); return null; } return null; } catch (_d) { // FIXME: notify user console.error('Error while getting filter result type', { token, prev, component }); return null; } } case 'property': try { return propertyToField(token, component.getId()); } catch (_e) { // FIXME: notify user console.error('Error while getting property result type', { token, component }); return null; } case 'state': { const parent = (0, state_1.getParentByPersistentId)(token.componentId, component); if (!parent) { console.warn('Component not found for state', token); const manager = (0, dataSourceManager_1.getManager)(); manager.editor.runCommand('notifications:add', { type: 'error', group: utils_1.NOTIFICATION_GROUP, message: `Component not found for state: ${token.storedStateId}`, componentId: component.getId(), }); return null; } const expression = (_b = (0, state_1.getState)(parent, token.storedStateId, token.exposed)) === null || _b === void 0 ? void 0 : _b.expression; if (!expression) { console.warn('State is not defined on component', { component: parent, token }); const manager = (0, dataSourceManager_1.getManager)(); manager.editor.runCommand('notifications:add', { type: 'error', group: utils_1.NOTIFICATION_GROUP, message: `State '${token.storedStateId}' is not defined on component '${parent.getName() || parent.get('id')}'`, componentId: parent.getId(), }); return null; } try { const field = getExpressionResultType(expression, parent); return field ? Object.assign(Object.assign({}, field), { kind: (_c = token.forceKind) !== null && _c !== void 0 ? _c : field.kind }) : null; } catch (_f) { // FIXME: notify user console.error('Error while getting expression result type in tokenToField', { expression, parent, component, token, prev }); return null; } } default: console.error('Unknown token type (reading type)', token); throw new Error('Unknown token type'); } } /** * Get the type corresponding to a property * @throws Error if the type is not found */ function propertyToField(property, componentId) { var _a, _b; const manager = (0, dataSourceManager_1.getManager)(); const allTypes = manager.cachedTypes.length > 0 ? manager.cachedTypes : []; const typeNames = []; // Check each typeId and handle missing types for (const typeId of property.typeIds) { const type = allTypes.find(type => type.id === typeId && (!property.dataSourceId || type.dataSourceId === property.dataSourceId)); if (!type) { // Show notification for missing type, similar to main branch DataTree.getType manager.editor.runCommand('notifications:add', { type: 'error', group: utils_1.NOTIFICATION_GROUP, message: `Type not found ${(_a = property.dataSourceId) !== null && _a !== void 0 ? _a : ''}.${typeId}`, componentId, }); console.error(`Type not found ${(_b = property.dataSourceId) !== null && _b !== void 0 ? _b : ''}.${typeId}`); // Continue processing other types instead of throwing } else { typeNames.push(type.label); } } const args = property.options ? Object.entries(property.options).map(([name, value]) => ({ typeId: 'JSON', // FIXME: Why is this hardcoded? name, defaultValue: value, // FIXME: Why is this value, it should keep the initial default })) : undefined; return { id: property.fieldId, label: typeNames.length > 0 ? typeNames.join(', ') : property.label, typeIds: property.typeIds, kind: property.kind, dataSourceId: property.dataSourceId, arguments: args, previewIndex: property.previewIndex, }; } /** * Evaluate the types of each token in an expression */ function expressionToFields(expression, component) { // Resolve type of the expression 1 step at a time let prev = null; const unknownField = { id: 'unknown', label: 'unknown', typeIds: [], kind: 'scalar', }; return expression.map((token) => { try { const field = tokenToField(fromStored(token, component.getId()), prev, component); if (!field) { console.warn('Type not found for token in expressionToFields', { token, expression }); return unknownField; } prev = field; return field; } catch (_a) { // FIXME: notify user console.error('Error while getting expression result type in expressionToFields', { expression, component, token, prev }); return unknownField; } }); } /** * Evaluate an expression to a type * This is used to validate expressions and for autocompletion * @throws Error if the token type is not found */ function getExpressionResultType(expression, component) { // Resolve type of the expression 1 step at a time return expression.reduce((prev, token) => { return tokenToField(fromStored(token, component.getId()), prev, component); }, null); } /** * Get the options of a token */ function getTokenOptions(field) { if (field.arguments && field.arguments.length > 0) { return { optionsForm: optionsToOptionsForm(field.arguments.map((arg) => ({ name: arg.name, value: arg.defaultValue }))), options: field.arguments.reduce((options, arg) => { options[arg.name] = arg.defaultValue; return options; }, {}), }; } return null; } /** * Get the options of a token or a field */ function optionsToOptionsForm(arr) { return (selected, input, options) => { return (0, lit_1.html) ` ${arr.map((obj) => { var _a, _b; const value = (_b = (_a = options[obj.name]) !== null && _a !== void 0 ? _a : obj.value) !== null && _b !== void 0 ? _b : ''; return (0, lit_1.html) `<label>${obj.name}</label><input type="text" name=${obj.name} .value=${value}>`; })} `; }; } /** * Utility function to shallow compare two objects * Used to compare options of tree items */ function getOptionObject(option1, option2) { // Handle the case where one or both are undefined or empty if (!option1 && !option2) return { error: false, result: undefined }; if (isEmpty(option1) && isEmpty(option2)) return { error: false, result: undefined }; // Handle the case where one is undefined or empty and the other is not if (!option1 || !option2) return { error: true, result: undefined }; if (isEmpty(option1) || isEmpty(option2)) return { error: true, result: undefined }; const keys1 = Object.keys(option1); const keys2 = Object.keys(option2); if (keys1.length !== keys2.length) { return { error: true, result: undefined }; } for (const key of keys1) { if (option1[key] !== option2[key]) { return { error: true, result: undefined }; } } return { error: false, result: option1 }; } function isJson(str) { if (typeof str !== 'string') return false; if (str.length === 0) return false; try { JSON.parse(str); } catch (_a) { return false; } return true; } function isEmpty(value) { if (value === null || typeof value === 'undefined') return true; const isString = typeof value === 'string'; const isJsonString = isString && isJson(value); if (isString && !isJsonString) return value === ''; const json = isJsonString ? JSON.parse(value) : value; if (json === null) return true; if (Array.isArray(json)) return json.length === 0; if (typeof json === 'object') return Object.values(json).filter(v => !!v).length === 0; return false; } function buildArgs(options) { const args = options ? `(${Object .keys(options) .map(key => ({ key, value: options[key] })) .filter(({ value }) => !isEmpty(value)) .map(({ key, value }) => { //return typeof value === 'string' && !isJson(value) ? `${key}: "${value}"` : `${key}: ${value}` return `${key}: ${value}`; }) .join(', ')})` : ''; // Valid args for GraphQL canot be just () const validArgs = args === '()' ? '' : args; return validArgs; } //# sourceMappingURL=token.js.map