@silexlabs/grapesjs-data-source
Version:
Grapesjs Data Source
185 lines • 7.77 kB
JavaScript
;
/*
* Silex website builder, free/libre no-code tool for makers.
* Copyright (c) 2023 lexoyo and Silex Labs foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.initializePreviewDataLoader = initializePreviewDataLoader;
exports.loadPreviewData = loadPreviewData;
exports.fetchPagePreviewData = fetchPagePreviewData;
exports.getPreviewData = getPreviewData;
exports.clearPreviewData = clearPreviewData;
const types_1 = require("../types");
const dataSourceManager_1 = require("./dataSourceManager");
const dataSourceRegistry_1 = require("./dataSourceRegistry");
const queryBuilder_1 = require("./queryBuilder");
const utils_1 = require("../utils");
// Global loader instance
let globalLoader = null;
/**
* Initialize the preview data loader
*/
function initializePreviewDataLoader(editor) {
globalLoader = {
editor,
currentUpdatePid: 0,
lastQueries: {},
};
}
/**
* Get the global loader (throws if not initialized)
*/
function getLoader() {
if (!globalLoader) {
throw new Error('PreviewDataLoader not initialized. Call initializePreviewDataLoader first.');
}
return globalLoader;
}
/**
* Compare two query objects to see if they are equal
*/
function areQueriesEqual(queries1, queries2) {
const keys1 = Object.keys(queries1).sort();
const keys2 = Object.keys(queries2).sort();
// Check if they have the same number of keys
if (keys1.length !== keys2.length) {
return false;
}
// Check if all keys are the same
if (!keys1.every(key => keys2.includes(key))) {
return false;
}
// Check if all values are the same
return keys1.every(key => queries1[key] === queries2[key]);
}
/**
* Load preview data for the current page
* @param forceRefresh - If true, bypass query comparison and force refresh
*/
function loadPreviewData() {
return __awaiter(this, arguments, void 0, function* (forceRefresh = false) {
const loader = getLoader();
loader.editor.trigger(types_1.DATA_SOURCE_DATA_LOAD_START);
const page = loader.editor.Pages.getSelected();
if (!page)
return;
// Get current queries
const currentQueries = (0, queryBuilder_1.getPageQuery)(page, loader.editor);
// Compare with last queries to see if we need to refresh
const queriesChanged = !areQueriesEqual(loader.lastQueries, currentQueries);
if (!forceRefresh && !queriesChanged) {
// Queries haven't changed, no need to refresh data sources
// But still trigger load end to maintain expected event flow
loader.editor.trigger(types_1.DATA_SOURCE_DATA_LOAD_END, (0, dataSourceManager_1.getPreviewData)());
return;
}
// Update last queries
loader.lastQueries = Object.assign({}, currentQueries);
loader.currentUpdatePid++;
const data = yield fetchPagePreviewData(page);
if (data !== 'interrupted') {
loader.editor.trigger(types_1.DATA_SOURCE_DATA_LOAD_END, data);
}
else {
console.warn(`Preview data update process for PID ${loader.currentUpdatePid} was interrupted.`);
loader.editor.trigger(types_1.DATA_SOURCE_DATA_LOAD_CANCEL, data);
}
});
}
/**
* Fetch preview data for a specific page
* @param page - The page object for which preview data needs to be fetched
* @return The preview data returned by all data sources, or 'interrupted' if cancelled
*/
function fetchPagePreviewData(page) {
return __awaiter(this, void 0, void 0, function* () {
const loader = getLoader();
const myPid = loader.currentUpdatePid;
const queries = (0, queryBuilder_1.getPageQuery)(page, loader.editor);
// Reset preview data
(0, dataSourceManager_1.setPreviewData)({});
try {
const results = yield Promise.all(Object.entries(queries)
.map((_a) => __awaiter(this, [_a], void 0, function* ([dataSourceId, query]) {
if (myPid !== loader.currentUpdatePid)
return;
const ds = (0, dataSourceRegistry_1.getAllDataSources)().find(ds => ds.id === dataSourceId);
if (!ds) {
console.error(`Data source ${dataSourceId} not found`);
return null;
}
if (!ds.isConnected()) {
console.warn(`Data source ${dataSourceId} is not connected.`);
return null;
}
try {
const value = yield ds.fetchValues(query);
const currentData = (0, dataSourceManager_1.getPreviewData)();
(0, dataSourceManager_1.setPreviewData)(Object.assign(Object.assign({}, currentData), { [dataSourceId]: value }));
return { dataSourceId, value };
}
catch (err) {
console.error(`Error fetching preview data for data source ${dataSourceId}:`, err);
loader.editor.runCommand('notifications:add', {
type: 'error',
group: utils_1.NOTIFICATION_GROUP,
message: `Error fetching preview data for data source ${dataSourceId}: ${err}`,
});
return null;
}
})));
if (myPid !== loader.currentUpdatePid)
return 'interrupted';
return results
.filter(result => result !== null)
.reduce((acc, result) => {
const { dataSourceId, value } = result;
acc[dataSourceId] = value;
return acc;
}, {});
}
catch (err) {
console.error('Error while fetching preview data:', err);
loader.editor.runCommand('notifications:add', {
type: 'error',
group: utils_1.NOTIFICATION_GROUP,
message: `Error while fetching preview data: ${err}`,
});
return {};
}
});
}
/**
* Get current preview data
*/
function getPreviewData() {
return (0, dataSourceManager_1.getPreviewData)();
}
/**
* Clear preview data
*/
function clearPreviewData() {
(0, dataSourceManager_1.setPreviewData)({});
}
//# sourceMappingURL=previewDataLoader.js.map