@silexlabs/grapesjs-data-source
Version:
Grapesjs Data Source
215 lines • 9.29 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getContext = getContext;
exports.fieldToToken = fieldToToken;
exports.getCompletion = getCompletion;
const dataSourceManager_1 = require("./dataSourceManager");
const state_1 = require("./state");
const token_1 = require("./token");
const utils_1 = require("../utils");
/**
* Get the context of a component
* This includes all parents states, data sources queryable values, values provided in the options
*/
function getContext(component, manager, currentStateId, hideLoopData = false) {
if (!component) {
console.error('Component is required for context');
throw new Error('Component is required for context');
}
// Get all queryable values from all data sources
const queryable = manager.cachedQueryables
.map((field) => {
if (!field.dataSourceId)
throw new Error(`Type ${field.id} has no data source`);
return fieldToToken(field);
});
// Get all states in the component scope
const states = [];
const loopProperties = [];
let parent = component;
while (parent) {
// Get explicitely set states
states
.push(...((0, state_1.getStateIds)(parent, true, parent === component ? currentStateId : undefined)
.map((stateId) => {
var _a;
return ({
type: 'state',
storedStateId: stateId,
previewIndex: 8888,
label: ((_a = (0, state_1.getState)(parent, stateId, true)) === null || _a === void 0 ? void 0 : _a.label) || stateId,
componentId: (0, state_1.getOrCreatePersistantId)(parent),
exposed: true,
});
})));
// Get states from loops
if (parent !== component || !hideLoopData) { // If it is a loop on the parent or if we don't hide the loop data
const loopDataState = (0, state_1.getState)(parent, '__data', false);
if (loopDataState) {
try {
const loopDataField = (0, token_1.getExpressionResultType)(loopDataState.expression, parent);
if (loopDataField) {
const displayName = (label) => { var _a; return `${(_a = parent.getName()) !== null && _a !== void 0 ? _a : 'Unknown'}'s ${loopDataField.label} ${label}`; };
if (loopDataField.kind === 'list') {
loopProperties.push({
type: 'state',
storedStateId: '__data',
componentId: (0, state_1.getOrCreatePersistantId)(parent),
previewIndex: loopDataField.previewIndex,
exposed: false,
forceKind: 'object', // FIXME: this may be a scalar
label: `Loop item (${loopDataField.label})`,
}, {
type: 'property',
propType: 'field',
fieldId: 'forloop.index0',
label: displayName('forloop.index0'),
kind: 'scalar',
typeIds: ['number'],
}, {
type: 'property',
propType: 'field',
fieldId: 'forloop.index',
label: displayName('forloop.index'),
kind: 'scalar',
typeIds: ['number'],
});
}
else {
console.warn('Loop item is not a list for component', parent, 'and state', loopDataState);
}
}
else {
console.warn('Loop item type not found for component', parent, 'and state', loopDataState);
}
}
catch (_a) {
console.error('Error while getting loop item for component', parent, 'and state', loopDataState);
}
}
}
// Go up to parent
parent = parent.parent();
}
// Get filters which accept no input
const filters = manager.filters
.filter(filter => {
try {
return filter.validate(null);
}
catch (e) {
console.warn('Filter validate error:', e, { filter });
return false;
}
});
// Add a fixed value
const fixedValue = (0, utils_1.getFixedToken)('');
// Return the context
return [
...queryable,
...states,
...loopProperties,
...filters,
fixedValue,
];
}
/**
* Create a property token from a field
*/
function fieldToToken(field) {
var _a;
if (!field)
throw new Error('Field is required for token');
if (!field.dataSourceId)
throw new Error(`Field ${field.id} has no data source`);
return Object.assign({ type: 'property', propType: 'field', fieldId: field.id, label: field.label, typeIds: field.typeIds, dataSourceId: field.dataSourceId, kind: field.kind }, (_a = (0, token_1.getTokenOptions)(field)) !== null && _a !== void 0 ? _a : {});
}
function getType(typeId, dataSourceId, componentId) {
const manager = (0, dataSourceManager_1.getManager)();
if (dataSourceId) {
// Get the data source
const dataSource = manager.dataSources
.find((dataSource) => !dataSourceId || dataSource.id === dataSourceId);
if (!dataSource)
throw new Error(`Data source not found ${dataSourceId}`);
// Get its types
const types = dataSource === null || dataSource === void 0 ? void 0 : dataSource.getTypes();
// Return the requested type
const type = types.find((type) => type.id === typeId);
if (!type) {
manager.editor.runCommand('notifications:add', {
type: 'error',
group: utils_1.NOTIFICATION_GROUP,
message: `Type not found ${dataSourceId !== null && dataSourceId !== void 0 ? dataSourceId : ''}.${typeId}`,
componentId,
});
throw new Error(`Type not found ${dataSourceId !== null && dataSourceId !== void 0 ? dataSourceId : ''}.${typeId}`);
}
return type;
}
else {
// No data source id: search in standard types
const standardType = dataSourceManager_1.STANDARD_TYPES.find(type => type.id === typeId.toLowerCase());
if (standardType)
return standardType;
// No data source id: search in all types
const type = (0, dataSourceManager_1.getTypes)().find(type => type.id === typeId);
if (!type)
throw new Error(`Unknown type ${typeId}`);
return type;
}
}
/**
* Auto complete an expression
* @returns a list of possible tokens to add to the expression
*/
function getCompletion(options) {
const { component, expression, manager, rootType, currentStateId, hideLoopData } = options;
if (!component)
throw new Error('Component is required for completion');
if (!expression)
throw new Error('Expression is required for completion');
if (expression.length === 0) {
if (rootType) {
const type = getType(rootType, null, component.getId());
if (!type) {
console.warn('Root type not found', rootType);
return [];
}
return type.fields
.map((field) => fieldToToken(field));
}
return getContext(component, manager, currentStateId, hideLoopData);
}
const field = (0, token_1.getExpressionResultType)(expression, component);
if (!field) {
console.warn('Result type not found for expression', expression);
return [];
}
return []
// Add fields if the kind is object
.concat(field.kind === 'object' ? field.typeIds
// Find possible types
.map((typeId) => { var _a; return getType(typeId, (_a = field.dataSourceId) !== null && _a !== void 0 ? _a : null, component.getId()); })
// Add all of their fields
.flatMap((type) => { var _a; return (_a = type === null || type === void 0 ? void 0 : type.fields) !== null && _a !== void 0 ? _a : []; })
// To token
.flatMap((fieldOfField) => {
// const t: Type | null = this.findType(field.typeIds, field.dataSourceId)
// if(!t) throw new Error(`Type ${field.typeIds} not found`)
return fieldOfField.typeIds.map((typeId) => (Object.assign(Object.assign({}, fieldToToken(fieldOfField)), { typeIds: [typeId] })));
}) : [])
// Add filters
.concat(manager.filters
// Match input type
.filter((filter) => {
try {
return filter.validate(field);
}
catch (e) {
console.warn('Filter validate error:', e, { filter, field });
return false;
}
}));
}
//# sourceMappingURL=completion.js.map