UNPKG

@sussudio/platform

Version:

Internal APIs for VS Code's service injection the base services.

151 lines (150 loc) 4.7 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? (desc = Object.getOwnPropertyDescriptor(target, key)) : desc, d; if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function') r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if ((d = decorators[i])) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); }; }; import { ThrottledDelayer } from '@sussudio/base/common/async.mjs'; import { VSBuffer } from '@sussudio/base/common/buffer.mjs'; import { isUndefined, isUndefinedOrNull } from '@sussudio/base/common/types.mjs'; import { IEnvironmentService } from '../../environment/common/environment.mjs'; import { IFileService } from '../../files/common/files.mjs'; import { ILogService } from '../../log/common/log.mjs'; export class FileStorage { storagePath; logService; fileService; storage = Object.create(null); lastSavedStorageContents = ''; flushDelayer = new ThrottledDelayer(100 /* buffer saves over a short time */); initializing = undefined; closing = undefined; constructor(storagePath, logService, fileService) { this.storagePath = storagePath; this.logService = logService; this.fileService = fileService; } init() { if (!this.initializing) { this.initializing = this.doInit(); } return this.initializing; } async doInit() { try { this.lastSavedStorageContents = (await this.fileService.readFile(this.storagePath)).value.toString(); this.storage = JSON.parse(this.lastSavedStorageContents); } catch (error) { if (error.fileOperationResult !== 1 /* FileOperationResult.FILE_NOT_FOUND */) { this.logService.error(error); } } } getItem(key, defaultValue) { const res = this.storage[key]; if (isUndefinedOrNull(res)) { return defaultValue; } return res; } setItem(key, data) { this.setItems([{ key, data }]); } setItems(items) { let save = false; for (const { key, data } of items) { // Shortcut for data that did not change if (this.storage[key] === data) { continue; } // Remove items when they are undefined or null if (isUndefinedOrNull(data)) { if (!isUndefined(this.storage[key])) { this.storage[key] = undefined; save = true; } } // Otherwise add an item else { this.storage[key] = data; save = true; } } if (save) { this.save(); } } removeItem(key) { // Only update if the key is actually present (not undefined) if (!isUndefined(this.storage[key])) { this.storage[key] = undefined; this.save(); } } async save() { if (this.closing) { return; // already about to close } return this.flushDelayer.trigger(() => this.doSave()); } async doSave() { if (!this.initializing) { return; // if we never initialized, we should not save our state } // Make sure to wait for init to finish first await this.initializing; // Return early if the database has not changed const serializedDatabase = JSON.stringify(this.storage, null, 4); if (serializedDatabase === this.lastSavedStorageContents) { return; } // Write to disk try { await this.fileService.writeFile(this.storagePath, VSBuffer.fromString(serializedDatabase)); this.lastSavedStorageContents = serializedDatabase; } catch (error) { this.logService.error(error); } } async close() { if (!this.closing) { this.closing = this.flushDelayer.trigger(() => this.doSave(), 0 /* as soon as possible */); } return this.closing; } } let StateService = class StateService { fileStorage; constructor(environmentService, logService, fileService) { this.fileStorage = new FileStorage(environmentService.stateResource, logService, fileService); } async init() { await this.fileStorage.init(); } getItem(key, defaultValue) { return this.fileStorage.getItem(key, defaultValue); } }; StateService = __decorate( [__param(0, IEnvironmentService), __param(1, ILogService), __param(2, IFileService)], StateService, ); export { StateService };