Allow external configurations - start

This commit is contained in:
Elio Struyf
2022-12-22 18:03:04 +01:00
parent 1764965aa7
commit cc2c6dc217
4 changed files with 165 additions and 36 deletions

View File

@@ -79,6 +79,14 @@
"configuration": {
"title": "Front Matter: use frontmatter.json for shared team settings",
"properties": {
"frontMatter.extends": {
"type": "array",
"markdownDescription": "Specify the list of paths/URLs to extend the Front Matter CMS config. [Check in the docs](https://frontmatter.codes/docs/settings#frontmatter.extends)",
"default": [],
"items": {
"type": "string"
}
},
"frontMatter.content.autoUpdateDate": {
"type": "boolean",
"default": false,

View File

@@ -0,0 +1,43 @@
const packageJson = require('../package.json');
for (const key of Object.keys(packageJson.contributes.configuration.properties)) {
const type = packageJson.contributes.configuration.properties[key].type;
if (type.includes('object') || type.includes('array')) {
console.log(`${key} - ${packageJson.contributes.configuration.properties[key].type}`);
}
}
// TO IGNORE
// frontMatter.extends - array
// frontMatter.dashboard.mediaSnippet - array
// TO PROCESS AS A WHOLE OBJECT
// frontMatter.content.draftField - object
// frontMatter.content.supportedFileTypes - array
// frontMatter.global.notifications - array
// frontMatter.global.disabledNotificaitons - array
// frontMatter.media.supportedMimeTypes - array
// frontMatter.taxonomy.commaSeparatedFields - array
// MERGE ARRAYS
// frontMatter.taxonomy.categories - array
// frontMatter.taxonomy.tags - array
// frontMatter.taxonomy.noPropertyValueQuotes - array
// PROCESS ITEM BY ITEM
// frontMatter.content.pageFolders - array - path
// frontMatter.content.placeholders - array - id
// frontMatter.content.sorting - array - id
// frontMatter.custom.scripts - array - id
// frontMatter.data.files - array - id
// frontMatter.data.folders - array - id
// frontMatter.data.types - array - id
// frontMatter.global.modes - array - id
// frontMatter.taxonomy.fieldGroups - array - id
// frontMatter.taxonomy.customTaxonomy - array - id
// frontMatter.taxonomy.contentTypes - array,null - name
// frontMatter.content.snippets - object

View File

@@ -2,6 +2,8 @@ export const EXTENSION_NAME = "Front Matter";
export const CONFIG_KEY = "frontMatter";
export const SETTING_EXTENDS = "extends";
export const SETTING_GLOBAL_NOTIFICATIONS = "global.notifications";
export const SETTING_GLOBAL_NOTIFICATIONS_DISABLED = "global.disabledNotifications";
export const SETTING_GLOBAL_MODES = "global.modes";

View File

@@ -3,8 +3,8 @@ import { Telemetry } from './Telemetry';
import { Notifications } from './Notifications';
import { commands, Uri, workspace, window } from 'vscode';
import * as vscode from 'vscode';
import { ContentFolder, ContentType, CustomPlaceholder, CustomTaxonomy, DataFile, DataFolder, DataType, TaxonomyType } from '../models';
import { SETTING_TAXONOMY_TAGS, SETTING_TAXONOMY_CATEGORIES, CONFIG_KEY, CONTEXT, ExtensionState, SETTING_TAXONOMY_CUSTOM, TelemetryEvent, COMMAND_NAME, SETTING_TAXONOMY_CONTENT_TYPES, SETTING_CONTENT_PAGE_FOLDERS, SETTING_CONTENT_SNIPPETS, SETTING_CONTENT_PLACEHOLDERS, SETTING_CUSTOM_SCRIPTS, SETTING_DATA_FILES, SETTING_DATA_TYPES, SETTING_DATA_FOLDERS } from '../constants';
import { ContentType, CustomTaxonomy, TaxonomyType } from '../models';
import { SETTING_TAXONOMY_TAGS, SETTING_TAXONOMY_CATEGORIES, CONFIG_KEY, CONTEXT, ExtensionState, SETTING_TAXONOMY_CUSTOM, TelemetryEvent, COMMAND_NAME, SETTING_TAXONOMY_CONTENT_TYPES, SETTING_CONTENT_PAGE_FOLDERS, SETTING_CONTENT_SNIPPETS, SETTING_CONTENT_PLACEHOLDERS, SETTING_CUSTOM_SCRIPTS, SETTING_DATA_FILES, SETTING_DATA_TYPES, SETTING_DATA_FOLDERS, SETTING_EXTENDS } from '../constants';
import { Folders } from '../commands/Folders';
import { join, basename, dirname, parse } from 'path';
import { existsSync } from 'fs';
@@ -13,6 +13,7 @@ import { debounceCallback } from './DebounceCallback';
import { Logger } from './Logger';
import * as jsoncParser from 'jsonc-parser';
import { existsAsync, readFileAsync, writeFileAsync } from '../utils';
import fetch from 'node-fetch';
export class Settings {
public static globalFile = "frontmatter.json";
@@ -432,6 +433,9 @@ export class Settings {
Settings.globalConfig = undefined;
}
// Check if the config got external configs
await Settings.processExternalConfig();
// Read the files from the config folder
let configFiles = await workspace.findFiles(`**/${Settings.globalConfigFolder}/**/*.json`);
if (configFiles.length === 0) {
@@ -440,7 +444,6 @@ export class Settings {
// Sort the files by fsPath
configFiles = configFiles.sort((a, b) => a.fsPath.localeCompare(b.fsPath));
for await (const configFile of configFiles) {
await Settings.processConfigFile(configFile);
}
@@ -453,6 +456,70 @@ export class Settings {
Settings.readConfigPromise = undefined;
}
/**
* Process the external configs
*/
private static async processExternalConfig() {
const extendsConfigName = `${CONFIG_KEY}.${SETTING_EXTENDS}`;
if (!Settings.globalConfig || !Settings.globalConfig[extendsConfigName]) {
return;
}
const originalConfig = Object.assign({}, Settings.globalConfig);
const extendsConfig: string[] = Settings.globalConfig[extendsConfigName];
for (const externalConfig of extendsConfig) {
if (externalConfig.endsWith(`.json`)) {
let config: any = undefined;
if (externalConfig.startsWith('https://')) {
try {
const response = await fetch(externalConfig);
if (response.ok) {
config = await response.json();
}
} catch (e) {
Logger.error(`Error fetching external config "${externalConfig}".`);
}
} else {
const configPath = join(Folders.getWorkspaceFolder()?.fsPath || '', externalConfig);
if (await existsAsync(configPath)) {
const configTxt = await readFileAsync(configPath, 'utf8');
config = jsoncParser.parse(configTxt);
} else {
Logger.error(`External config "${externalConfig}" not found.`);
}
}
// Check if the config contains data and loop through it
if (config) {
// We need to loop through the config to make sure the objects and arrays are merged
for (const key in config) {
if (config.hasOwnProperty(key)) {
const value = config[key];
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
if (typeof originalConfig[key] === 'undefined') {
Settings.globalConfig[key] = value;
}
} else if (typeof value === 'object' && value !== null) {
// Check if array
if (Array.isArray(value)) {
for (const item of value) {
Settings.updateGlobalConfigSetting(key.replace(`${CONFIG_KEY}.`, ''), item);
}
} else {
for (const itemKey in value) {
// Process the object key/item
}
}
}
}
}
}
}
}
}
/**
* Process the config file
* @param configFile
@@ -482,45 +549,54 @@ export class Settings {
Settings.globalConfig = {};
}
// Array settings
if (Settings.isEqualOrStartsWith(relSettingName, SETTING_CUSTOM_SCRIPTS)) {
const crntValue = Settings.globalConfig[`${CONFIG_KEY}.${SETTING_CUSTOM_SCRIPTS}`] || [];
Settings.globalConfig[`${CONFIG_KEY}.${SETTING_CUSTOM_SCRIPTS}`] = [...crntValue, configJson];
}
// Content types
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_TAXONOMY_CONTENT_TYPES)) {
Settings.updateGlobalConfigArraySetting(SETTING_TAXONOMY_CONTENT_TYPES, "name", configJson);
}
// Data files
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_DATA_FILES)) {
Settings.updateGlobalConfigArraySetting(SETTING_DATA_FILES, "id", configJson);
}
// Data folders
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_DATA_FOLDERS)) {
Settings.updateGlobalConfigArraySetting(SETTING_DATA_FOLDERS, "id", configJson);
}
// Data types
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_DATA_TYPES)) {
Settings.updateGlobalConfigArraySetting(SETTING_DATA_TYPES, "id", configJson);
}
// Page folders
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_CONTENT_PAGE_FOLDERS)) {
Settings.updateGlobalConfigArraySetting(SETTING_CONTENT_PAGE_FOLDERS, "path", configJson);
}
// Placeholders
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_CONTENT_PLACEHOLDERS)) {
Settings.updateGlobalConfigArraySetting(SETTING_CONTENT_PLACEHOLDERS, "id", configJson);
}
// Object settings
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_CONTENT_SNIPPETS)) {
Settings.updateGlobalConfigObjectByNameSetting(SETTING_CONTENT_SNIPPETS, configFilePath, configJson, filePath);
}
Settings.updateGlobalConfigSetting(relSettingName, configJson, configFilePath, filePath);
} catch (e) {
Logger.error(`Error reading config file: ${configFile.fsPath}`);
Logger.error((e as Error).message);
}
}
/**
* Update the global config array/object settings
* @param relSettingName
* @param configJson
*/
private static updateGlobalConfigSetting<T>(relSettingName: string, configJson: any, configFilePath?: string, filePath?: string): void {
// Array settings
if (Settings.isEqualOrStartsWith(relSettingName, SETTING_CUSTOM_SCRIPTS)) {
const crntValue = Settings.globalConfig[`${CONFIG_KEY}.${SETTING_CUSTOM_SCRIPTS}`] || [];
Settings.globalConfig[`${CONFIG_KEY}.${SETTING_CUSTOM_SCRIPTS}`] = [...crntValue, configJson];
}
// Content types
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_TAXONOMY_CONTENT_TYPES)) {
Settings.updateGlobalConfigArraySetting(SETTING_TAXONOMY_CONTENT_TYPES, "name", configJson);
}
// Data files
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_DATA_FILES)) {
Settings.updateGlobalConfigArraySetting(SETTING_DATA_FILES, "id", configJson);
}
// Data folders
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_DATA_FOLDERS)) {
Settings.updateGlobalConfigArraySetting(SETTING_DATA_FOLDERS, "id", configJson);
}
// Data types
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_DATA_TYPES)) {
Settings.updateGlobalConfigArraySetting(SETTING_DATA_TYPES, "id", configJson);
}
// Page folders
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_CONTENT_PAGE_FOLDERS)) {
Settings.updateGlobalConfigArraySetting(SETTING_CONTENT_PAGE_FOLDERS, "path", configJson);
}
// Placeholders
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_CONTENT_PLACEHOLDERS)) {
Settings.updateGlobalConfigArraySetting(SETTING_CONTENT_PLACEHOLDERS, "id", configJson);
}
// Snippets
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_CONTENT_SNIPPETS) && configFilePath && filePath) {
Settings.updateGlobalConfigObjectByNameSetting(SETTING_CONTENT_SNIPPETS, configFilePath, configJson, filePath);
}
}
/**
* Check if the setting name is equal or starts with the reference setting name
* @param value