mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-22 02:11:44 +03:00
5582d030e3
closes #11999
- When the routes.yaml file changes (manually or through API) we need
to store a checksum to be able to optimize routes reloads in the future
- Added mechanism to detect differences between stored and current routes.yaml hash value
- Added routes.yaml sync on server boot
- Added routes.yaml handling in controllers
- Added routes hash synchronization method in core settings. It lives in core settings
as it needs access to model layer. To avoid coupling with the frontend settings it accepts
a function which has to resolve to a routes hash
- Added note about settings validation side-effect. It mutates input!
- Added async check for currently loaded routes hash
- Extended frontend settings loader with async loader. The default behavior of the loader is
to load settings syncronously for reasons spelled in 0ac19dcf84
To avoid blocking the eventloop added async loading method
- Refactored frontend setting loader for reusability of settings file path
- Added integrity check test for routes.yaml file
90 lines
2.7 KiB
JavaScript
90 lines
2.7 KiB
JavaScript
const fs = require('fs-extra');
|
|
const path = require('path');
|
|
const debug = require('ghost-ignition').debug('frontend:services:settings:settings-loader');
|
|
const {i18n} = require('../../../server/lib/common');
|
|
const errors = require('@tryghost/errors');
|
|
const config = require('../../../shared/config');
|
|
const yamlParser = require('./yaml-parser');
|
|
const validate = require('./validate');
|
|
|
|
const getSettingFilePath = (setting) => {
|
|
// we only support the `yaml` file extension. `yml` will be ignored.
|
|
const fileName = `${setting}.yaml`;
|
|
const contentPath = config.getContentPath('settings');
|
|
const filePath = path.join(contentPath, fileName);
|
|
|
|
return {
|
|
fileName,
|
|
contentPath,
|
|
filePath
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Functionally same as loadSettingsSync with exception of loading
|
|
* settigs asyncronously. This method is used at new places to read settings
|
|
* to prevent blocking the eventloop
|
|
*
|
|
* @param {String} setting the requested settings as defined in setting knownSettings
|
|
* @returns {Object} settingsFile
|
|
*/
|
|
const loadSettings = async (setting) => {
|
|
const {fileName, contentPath, filePath} = getSettingFilePath(setting);
|
|
|
|
try {
|
|
const file = await fs.readFile(filePath, 'utf8');
|
|
debug('settings file found for', setting);
|
|
|
|
const object = yamlParser(file, fileName);
|
|
return validate(object);
|
|
} catch (err) {
|
|
if (errors.utils.isIgnitionError(err)) {
|
|
throw err;
|
|
}
|
|
|
|
throw new errors.GhostError({
|
|
message: i18n.t('errors.services.settings.loader', {
|
|
setting: setting,
|
|
path: contentPath
|
|
}),
|
|
context: filePath,
|
|
err: err
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Reads the desired settings YAML file and passes the
|
|
* file to the YAML parser which then returns a JSON object.
|
|
* NOTE: loading happens syncronously
|
|
*
|
|
* @param {String} setting the requested settings as defined in setting knownSettings
|
|
* @returns {Object} settingsFile
|
|
*/
|
|
module.exports = function loadSettingsSync(setting) {
|
|
const {fileName, contentPath, filePath} = getSettingFilePath(setting);
|
|
|
|
try {
|
|
const file = fs.readFileSync(filePath, 'utf8');
|
|
debug('settings file found for', setting);
|
|
|
|
const object = yamlParser(file, fileName);
|
|
return validate(object);
|
|
} catch (err) {
|
|
if (errors.utils.isIgnitionError(err)) {
|
|
throw err;
|
|
}
|
|
|
|
throw new errors.GhostError({
|
|
message: i18n.t('errors.services.settings.loader', {
|
|
setting: setting,
|
|
path: contentPath
|
|
}),
|
|
context: filePath,
|
|
err: err
|
|
});
|
|
}
|
|
};
|
|
|
|
module.exports.loadSettings = loadSettings;
|