import {extensions, workspace, window, Uri} from 'vscode'; import {posix} from 'path'; import {CONFIG_FILE_NAME, USER_CONFIG_FILE_NAME, MATERIAL_THEME_EXT_ID} from '../env'; type MaterialThemeConfig = { accents: Record; accentsProperties: Record; changelog?: { lastversion?: string }; }; type InstallationType = { firstInstall: boolean; update: boolean; }; export interface IExtensionManager { getPackageJSON: () => Record; getConfig: () => MaterialThemeConfig; getInstallationType: () => {}; updateConfig: (config: Partial) => Promise; } class ExtensionManager implements IExtensionManager { installationType: InstallationType; private readonly configFileUri: Uri; private readonly userConfigFileUri: Uri; private configJSON: MaterialThemeConfig; constructor() { const extensionFolderUri = Uri.file(extensions.getExtension(MATERIAL_THEME_EXT_ID).extensionPath); this.configFileUri = extensionFolderUri.with({path: posix.join(extensionFolderUri.path, CONFIG_FILE_NAME)}); this.userConfigFileUri = extensionFolderUri.with({path: posix.join(extensionFolderUri.path, USER_CONFIG_FILE_NAME)}); this.init(); } getPackageJSON(): Record { return extensions.getExtension(MATERIAL_THEME_EXT_ID).packageJSON; } getConfig(): MaterialThemeConfig { return this.configJSON; } getInstallationType(): InstallationType { return this.installationType; } async updateConfig(config: Partial): Promise { const newConfig = {...this.configJSON, ...config}; await workspace.fs.writeFile(this.configFileUri, Buffer.from(JSON.stringify(newConfig), 'utf-8')); } private isVersionUpdate(userConfig: MaterialThemeConfig): boolean { const splitVersion = (input: string): {major: number; minor: number; patch: number} => { const [major, minor, patch] = input.split('.').map(i => parseInt(i, 10)); return {major, minor, patch}; }; const packageJSON = this.getPackageJSON(); const versionCurrent = splitVersion(packageJSON.version); const versionOld = splitVersion(userConfig.changelog.lastversion); const update = ( versionCurrent.major > versionOld.major || versionCurrent.minor > versionOld.minor || versionCurrent.patch > versionOld.patch ); return update; } private async getUserConfig(): Promise { try { const configBuffer = await workspace.fs.readFile(this.userConfigFileUri); const configContent = Buffer.from(configBuffer).toString('utf8'); return JSON.parse(configContent) as MaterialThemeConfig; } catch {} } private async init(): Promise { try { const packageJSON = this.getPackageJSON(); const userConfig = await this.getUserConfig(); this.installationType = { update: userConfig && this.isVersionUpdate(userConfig), firstInstall: !userConfig }; const configBuffer = await workspace.fs.readFile(this.configFileUri); const configContent = Buffer.from(configBuffer).toString('utf8'); this.configJSON = JSON.parse(configContent) as MaterialThemeConfig; const userConfigUpdate = {...this.configJSON, changelog: {lastversion: packageJSON.version}}; await workspace.fs.writeFile( this.userConfigFileUri, Buffer.from(JSON.stringify(userConfigUpdate), 'utf-8') ); } catch (error) { this.configJSON = {accentsProperties: {}, accents: {}}; window .showErrorMessage(`Material Theme: there was an error while loading the configuration. Please retry or open an issue: ${String(error)}`); } } } export const extensionManager = new ExtensionManager();