UNPKG

sussudio

Version:

An unofficial VS Code Internal API

127 lines (126 loc) 5.3 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Emitter, Event } from "../../../base/common/event.mjs"; import { Disposable } from "../../../base/common/lifecycle.mjs"; import { revive } from "../../../base/common/marshalling.mjs"; import { reviveIdentifier } from "../../workspace/common/workspace.mjs"; export class StorageDatabaseChannel extends Disposable { logService; storageMainService; static STORAGE_CHANGE_DEBOUNCE_TIME = 100; onDidChangeApplicationStorageEmitter = this._register(new Emitter()); mapProfileToOnDidChangeProfileStorageEmitter = new Map(); constructor(logService, storageMainService) { super(); this.logService = logService; this.storageMainService = storageMainService; this.registerStorageChangeListeners(storageMainService.applicationStorage, this.onDidChangeApplicationStorageEmitter); } //#region Storage Change Events registerStorageChangeListeners(storage, emitter) { // Listen for changes in provided storage to send to listeners // that are listening. Use a debouncer to reduce IPC traffic. this._register(Event.debounce(storage.onDidChangeStorage, (prev, cur) => { if (!prev) { prev = [cur]; } else { prev.push(cur); } return prev; }, StorageDatabaseChannel.STORAGE_CHANGE_DEBOUNCE_TIME)(events => { if (events.length) { emitter.fire(this.serializeStorageChangeEvents(events, storage)); } })); } serializeStorageChangeEvents(events, storage) { const changed = new Map(); const deleted = new Set(); events.forEach(event => { const existing = storage.get(event.key); if (typeof existing === 'string') { changed.set(event.key, existing); } else { deleted.add(event.key); } }); return { changed: Array.from(changed.entries()), deleted: Array.from(deleted.values()) }; } listen(_, event, arg) { switch (event) { case 'onDidChangeStorage': { const profile = arg.profile ? revive(arg.profile) : undefined; // Without profile: application scope if (!profile) { return this.onDidChangeApplicationStorageEmitter.event; } // With profile: profile scope for the profile let profileStorageChangeEmitter = this.mapProfileToOnDidChangeProfileStorageEmitter.get(profile.id); if (!profileStorageChangeEmitter) { profileStorageChangeEmitter = this._register(new Emitter()); this.registerStorageChangeListeners(this.storageMainService.profileStorage(profile), profileStorageChangeEmitter); this.mapProfileToOnDidChangeProfileStorageEmitter.set(profile.id, profileStorageChangeEmitter); } return profileStorageChangeEmitter.event; } } throw new Error(`Event not found: ${event}`); } //#endregion async call(_, command, arg) { const profile = arg.profile ? revive(arg.profile) : undefined; const workspace = reviveIdentifier(arg.workspace); // Get storage to be ready const storage = await this.withStorageInitialized(profile, workspace); // handle call switch (command) { case 'getItems': { return Array.from(storage.items.entries()); } case 'updateItems': { const items = arg; if (items.insert) { for (const [key, value] of items.insert) { storage.set(key, value); } } items.delete?.forEach(key => storage.delete(key)); break; } case 'isUsed': { const path = arg.payload; if (typeof path === 'string') { return this.storageMainService.isUsed(path); } } default: throw new Error(`Call not found: ${command}`); } } async withStorageInitialized(profile, workspace) { let storage; if (workspace) { storage = this.storageMainService.workspaceStorage(workspace); } else if (profile) { storage = this.storageMainService.profileStorage(profile); } else { storage = this.storageMainService.applicationStorage; } try { await storage.init(); } catch (error) { this.logService.error(`StorageIPC#init: Unable to init ${workspace ? 'workspace' : profile ? 'profile' : 'application'} storage due to ${error}`); } return storage; } }