Ghost/core/bridge.js

115 lines
4.1 KiB
JavaScript
Raw Normal View History

2021-04-27 14:49:48 +03:00
/**
* The Bridge
*
* The bridge is responsible for handing communication from the server to the frontend.
* Data should only be flowing server -> frontend.
* As the architecture improves, the number of cross requires here should go down
* Eventually, the aim is to make this a component that is initialized on boot and is either handed to or actively creates the frontend, if the frontend is desired.
2021-04-27 14:49:48 +03:00
*
* This file is a great place for all the cross-component event handling in lieu of refactoring
* NOTE: You may require anything from shared, the frontend or server here - it is the one place (other than boot) that is allowed :)
2021-04-27 14:49:48 +03:00
*/
const debug = require('@tryghost/debug')('bridge');
2021-04-27 14:49:48 +03:00
const errors = require('@tryghost/errors');
const logging = require('@tryghost/logging');
const tpl = require('@tryghost/tpl');
const themeEngine = require('./frontend/services/theme-engine');
const appService = require('./frontend/services/apps');
const cardAssetService = require('./frontend/services/card-assets');
const commentCountsAssetService = require('./frontend/services/comment-counts-assets');
const adminAuthAssetService = require('./frontend/services/admin-auth-assets');
const routerManager = require('./frontend/services/routing').routerManager;
const settingsCache = require('./shared/settings-cache');
const urlService = require('./server/services/url');
const routeSettings = require('./server/services/route-settings');
// Listen to settings.locale.edited, similar to the member service and models/base/listeners
const events = require('./server/lib/common/events');
const messages = {
activateFailed: 'Unable to activate the theme "{theme}".'
};
class Bridge {
init() {
/**
* When locale changes, we reload theme translations
*/
events.on('settings.locale.edited', (model) => {
debug('Active theme init18n');
this.getActiveTheme().initI18n({locale: model.get('value')});
});
// NOTE: eventually this event should somehow be listened on and handled by the URL Service
// for now this eliminates the need for the frontend routing to listen to
// server events
events.on('settings.timezone.edited', (model) => {
routerManager.handleTimezoneEdit(model);
});
}
getActiveTheme() {
return themeEngine.getActive();
}
async activateTheme(loadedTheme, checkedTheme) {
let settings = {
locale: settingsCache.get('locale')
};
2021-04-27 14:49:48 +03:00
// no need to check the score, activation should be used in combination with validate.check
// Use the two theme objects to set the current active theme
try {
themeEngine.setActive(settings, loadedTheme, checkedTheme);
const cardAssetConfig = this.getCardAssetConfig();
debug('reload card assets config', cardAssetConfig);
await cardAssetService.load(cardAssetConfig);
// TODO: is this in the right place?
// rebuild asset files
await commentCountsAssetService.load();
await adminAuthAssetService.load();
2021-04-27 14:49:48 +03:00
} catch (err) {
logging.error(new errors.InternalServerError({
message: tpl(messages.activateFailed, {theme: loadedTheme.name}),
2021-04-27 14:49:48 +03:00
err: err
}));
}
}
getCardAssetConfig() {
if (this.getActiveTheme()) {
return this.getActiveTheme().config('card_assets');
} else {
return true;
}
}
async reloadFrontend() {
debug('reload frontend');
const siteApp = require('./frontend/web/site');
const routerConfig = {
routeSettings: await routeSettings.loadRouteSettings(),
urlService
};
await siteApp.reload(routerConfig);
// re-initialize apps (register app routers, because we have re-initialized the site routers)
appService.init();
// connect routers and resources again
urlService.queue.start({
event: 'init',
tolerance: 100,
requiredSubscriberCount: 1
});
}
}
const bridge = new Bridge();
module.exports = bridge;