UNPKG

sussudio

Version:

An unofficial VS Code Internal API

410 lines (409 loc) 20 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 { URI } from "../../../base/common/uri.mjs"; import { localize } from "../../../nls.mjs"; import { IEnvironmentService } from "../../environment/common/environment.mjs"; import { IFileService } from "../../files/common/files.mjs"; import { getServiceMachineId } from "../../externalServices/common/serviceMachineId.mjs"; import { IStorageService } from "../../storage/common/storage.mjs"; import { IUriIdentityService } from "../../uriIdentity/common/uriIdentity.mjs"; import { IUserDataSyncBackupStoreService, IUserDataSyncLogService, IUserDataSyncStoreService, UserDataSyncError, USER_DATA_SYNC_SCHEME, CONFIG_SYNC_KEYBINDINGS_PER_PLATFORM } from "./userDataSync.mjs"; import { IUserDataProfilesService } from "../../userDataProfile/common/userDataProfile.mjs"; import { isSyncData } from "./abstractSynchronizer.mjs"; import { parseSnippets } from "./snippetsSync.mjs"; import { parseSettingsSyncContent } from "./settingsSync.mjs"; import { getKeybindingsContentFromSyncContent } from "./keybindingsSync.mjs"; import { IConfigurationService } from "../../configuration/common/configuration.mjs"; import { getTasksContentFromSyncContent } from "./tasksSync.mjs"; import { LocalExtensionsProvider, parseExtensions, stringify as stringifyExtensions } from "./extensionsSync.mjs"; import { LocalGlobalStateProvider, stringify as stringifyGlobalState } from "./globalStateSync.mjs"; import { IInstantiationService } from "../../instantiation/common/instantiation.mjs"; import { parseUserDataProfilesManifest, stringifyLocalProfiles } from "./userDataProfilesManifestSync.mjs"; import { toFormattedString } from "../../../base/common/jsonFormatter.mjs"; let UserDataSyncResourceProviderService = class UserDataSyncResourceProviderService { userDataSyncStoreService; userDataSyncBackupStoreService; logService; environmentService; storageService; fileService; userDataProfilesService; configurationService; instantiationService; _serviceBrand; static NOT_EXISTING_RESOURCE = 'not-existing-resource'; static REMOTE_BACKUP_AUTHORITY = 'remote-backup'; static LOCAL_BACKUP_AUTHORITY = 'local-backup'; extUri; constructor(userDataSyncStoreService, userDataSyncBackupStoreService, logService, uriIdentityService, environmentService, storageService, fileService, userDataProfilesService, configurationService, instantiationService) { this.userDataSyncStoreService = userDataSyncStoreService; this.userDataSyncBackupStoreService = userDataSyncBackupStoreService; this.logService = logService; this.environmentService = environmentService; this.storageService = storageService; this.fileService = fileService; this.userDataProfilesService = userDataProfilesService; this.configurationService = configurationService; this.instantiationService = instantiationService; this.extUri = uriIdentityService.extUri; } async getRemoteSyncedProfiles() { const userData = await this.userDataSyncStoreService.readResource("profiles" /* SyncResource.Profiles */, null, undefined); if (userData.content) { const syncData = this.parseSyncData(userData.content, "profiles" /* SyncResource.Profiles */); return parseUserDataProfilesManifest(syncData); } return []; } async getRemoteSyncResourceHandles(syncResource, profile) { const handles = await this.userDataSyncStoreService.getAllResourceRefs(syncResource, profile?.collection); return handles.map(({ created, ref }) => ({ created, uri: this.toUri({ remote: true, syncResource, profile: profile?.id ?? this.userDataProfilesService.defaultProfile.id, collection: profile?.collection, ref, node: undefined, }) })); } async getLocalSyncResourceHandles(syncResource, profile) { const handles = await this.userDataSyncBackupStoreService.getAllRefs(profile, syncResource); return handles.map(({ created, ref }) => ({ created, uri: this.toUri({ remote: false, syncResource, profile: profile.id, collection: undefined, ref, node: undefined, }) })); } resolveUserDataSyncResource({ uri }) { const resolved = this.resolveUri(uri); const profile = resolved ? this.userDataProfilesService.profiles.find(p => p.id === resolved.profile) : undefined; return resolved && profile ? { profile, syncResource: resolved?.syncResource } : undefined; } async getAssociatedResources({ uri }) { const resolved = this.resolveUri(uri); if (!resolved) { return []; } const profile = this.userDataProfilesService.profiles.find(p => p.id === resolved.profile); switch (resolved.syncResource) { case "settings" /* SyncResource.Settings */: return this.getSettingsAssociatedResources(uri, profile); case "keybindings" /* SyncResource.Keybindings */: return this.getKeybindingsAssociatedResources(uri, profile); case "tasks" /* SyncResource.Tasks */: return this.getTasksAssociatedResources(uri, profile); case "snippets" /* SyncResource.Snippets */: return this.getSnippetsAssociatedResources(uri, profile); case "globalState" /* SyncResource.GlobalState */: return this.getGlobalStateAssociatedResources(uri, profile); case "extensions" /* SyncResource.Extensions */: return this.getExtensionsAssociatedResources(uri, profile); case "profiles" /* SyncResource.Profiles */: return this.getProfilesAssociatedResources(uri, profile); } } async getMachineId({ uri }) { const resolved = this.resolveUri(uri); if (!resolved) { return undefined; } if (resolved.remote) { if (resolved.ref) { const { content } = await this.getUserData(resolved.syncResource, resolved.ref, resolved.collection); if (content) { const syncData = this.parseSyncData(content, resolved.syncResource); return syncData?.machineId; } } return undefined; } return getServiceMachineId(this.environmentService, this.fileService, this.storageService); } async resolveContent(uri) { const resolved = this.resolveUri(uri); if (!resolved) { return null; } if (resolved.node === UserDataSyncResourceProviderService.NOT_EXISTING_RESOURCE) { return null; } if (resolved.ref) { const content = await this.getContentFromStore(resolved.remote, resolved.syncResource, resolved.profile, resolved.collection, resolved.ref); if (resolved.node && content) { return this.resolveNodeContent(resolved.syncResource, content, resolved.node); } return content; } if (!resolved.remote && !resolved.node) { return this.resolveLatestContent(resolved.syncResource, resolved.profile); } return null; } async getContentFromStore(remote, syncResource, profileId, collection, ref) { if (remote) { const { content } = await this.getUserData(syncResource, ref, collection); return content; } const profile = this.userDataProfilesService.profiles.find(p => p.id === profileId); if (profile) { return this.userDataSyncBackupStoreService.resolveContent(profile, syncResource, ref); } return null; } resolveNodeContent(syncResource, content, node) { const syncData = this.parseSyncData(content, syncResource); switch (syncResource) { case "settings" /* SyncResource.Settings */: return this.resolveSettingsNodeContent(syncData, node); case "keybindings" /* SyncResource.Keybindings */: return this.resolveKeybindingsNodeContent(syncData, node); case "tasks" /* SyncResource.Tasks */: return this.resolveTasksNodeContent(syncData, node); case "snippets" /* SyncResource.Snippets */: return this.resolveSnippetsNodeContent(syncData, node); case "globalState" /* SyncResource.GlobalState */: return this.resolveGlobalStateNodeContent(syncData, node); case "extensions" /* SyncResource.Extensions */: return this.resolveExtensionsNodeContent(syncData, node); case "profiles" /* SyncResource.Profiles */: return this.resolveProfileNodeContent(syncData, node); } } async resolveLatestContent(syncResource, profileId) { const profile = this.userDataProfilesService.profiles.find(p => p.id === profileId); if (!profile) { return null; } switch (syncResource) { case "globalState" /* SyncResource.GlobalState */: return this.resolveLatestGlobalStateContent(profile); case "extensions" /* SyncResource.Extensions */: return this.resolveLatestExtensionsContent(profile); case "profiles" /* SyncResource.Profiles */: return this.resolveLatestProfilesContent(profile); case "settings" /* SyncResource.Settings */: return null; case "keybindings" /* SyncResource.Keybindings */: return null; case "tasks" /* SyncResource.Tasks */: return null; case "snippets" /* SyncResource.Snippets */: return null; } } getSettingsAssociatedResources(uri, profile) { const resource = this.extUri.joinPath(uri, 'settings.json'); const comparableResource = profile ? profile.settingsResource : this.extUri.joinPath(uri, UserDataSyncResourceProviderService.NOT_EXISTING_RESOURCE); return [{ resource, comparableResource }]; } resolveSettingsNodeContent(syncData, node) { switch (node) { case 'settings.json': return parseSettingsSyncContent(syncData.content).settings; } return null; } getKeybindingsAssociatedResources(uri, profile) { const resource = this.extUri.joinPath(uri, 'keybindings.json'); const comparableResource = profile ? profile.keybindingsResource : this.extUri.joinPath(uri, UserDataSyncResourceProviderService.NOT_EXISTING_RESOURCE); return [{ resource, comparableResource }]; } resolveKeybindingsNodeContent(syncData, node) { switch (node) { case 'keybindings.json': return getKeybindingsContentFromSyncContent(syncData.content, !!this.configurationService.getValue(CONFIG_SYNC_KEYBINDINGS_PER_PLATFORM), this.logService); } return null; } getTasksAssociatedResources(uri, profile) { const resource = this.extUri.joinPath(uri, 'tasks.json'); const comparableResource = profile ? profile.tasksResource : this.extUri.joinPath(uri, UserDataSyncResourceProviderService.NOT_EXISTING_RESOURCE); return [{ resource, comparableResource }]; } resolveTasksNodeContent(syncData, node) { switch (node) { case 'tasks.json': return getTasksContentFromSyncContent(syncData.content, this.logService); } return null; } async getSnippetsAssociatedResources(uri, profile) { const content = await this.resolveContent(uri); if (content) { const syncData = this.parseSyncData(content, "snippets" /* SyncResource.Snippets */); if (syncData) { const snippets = parseSnippets(syncData); const result = []; for (const snippet of Object.keys(snippets)) { const resource = this.extUri.joinPath(uri, snippet); const comparableResource = profile ? this.extUri.joinPath(profile.snippetsHome, snippet) : this.extUri.joinPath(uri, UserDataSyncResourceProviderService.NOT_EXISTING_RESOURCE); result.push({ resource, comparableResource }); } return result; } } return []; } resolveSnippetsNodeContent(syncData, node) { return parseSnippets(syncData)[node] || null; } getExtensionsAssociatedResources(uri, profile) { const resource = this.extUri.joinPath(uri, 'extensions.json'); const comparableResource = profile ? this.toUri({ remote: false, syncResource: "extensions" /* SyncResource.Extensions */, profile: profile.id, collection: undefined, ref: undefined, node: undefined, }) : this.extUri.joinPath(uri, UserDataSyncResourceProviderService.NOT_EXISTING_RESOURCE); return [{ resource, comparableResource }]; } resolveExtensionsNodeContent(syncData, node) { switch (node) { case 'extensions.json': return stringifyExtensions(parseExtensions(syncData), true); } return null; } async resolveLatestExtensionsContent(profile) { const { localExtensions } = await this.instantiationService.createInstance(LocalExtensionsProvider).getLocalExtensions(profile); return stringifyExtensions(localExtensions, true); } getGlobalStateAssociatedResources(uri, profile) { const resource = this.extUri.joinPath(uri, 'globalState.json'); const comparableResource = profile ? this.toUri({ remote: false, syncResource: "globalState" /* SyncResource.GlobalState */, profile: profile.id, collection: undefined, ref: undefined, node: undefined, }) : this.extUri.joinPath(uri, UserDataSyncResourceProviderService.NOT_EXISTING_RESOURCE); return [{ resource, comparableResource }]; } resolveGlobalStateNodeContent(syncData, node) { switch (node) { case 'globalState.json': return stringifyGlobalState(JSON.parse(syncData.content), true); } return null; } async resolveLatestGlobalStateContent(profile) { const localGlobalState = await this.instantiationService.createInstance(LocalGlobalStateProvider).getLocalGlobalState(profile); return stringifyGlobalState(localGlobalState, true); } getProfilesAssociatedResources(uri, profile) { const resource = this.extUri.joinPath(uri, 'profiles.json'); const comparableResource = this.toUri({ remote: false, syncResource: "profiles" /* SyncResource.Profiles */, profile: this.userDataProfilesService.defaultProfile.id, collection: undefined, ref: undefined, node: undefined, }); return [{ resource, comparableResource }]; } resolveProfileNodeContent(syncData, node) { switch (node) { case 'profiles.json': return toFormattedString(JSON.parse(syncData.content), {}); } return null; } async resolveLatestProfilesContent(profile) { return stringifyLocalProfiles(this.userDataProfilesService.profiles.filter(p => !p.isDefault && !p.isTransient), true); } toUri(syncResourceUriInfo) { const authority = syncResourceUriInfo.remote ? UserDataSyncResourceProviderService.REMOTE_BACKUP_AUTHORITY : UserDataSyncResourceProviderService.LOCAL_BACKUP_AUTHORITY; const paths = [ syncResourceUriInfo.syncResource, syncResourceUriInfo.profile, ]; if (syncResourceUriInfo.collection) { paths.push(`collection:${syncResourceUriInfo.collection}`); } if (syncResourceUriInfo.ref) { paths.push(`ref:${syncResourceUriInfo.ref}`); } if (syncResourceUriInfo.node) { paths.push(syncResourceUriInfo.node); } return this.extUri.joinPath(URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority, path: `/` }), ...paths); } resolveUri(uri) { if (uri.scheme !== USER_DATA_SYNC_SCHEME) { return undefined; } if (uri.authority !== UserDataSyncResourceProviderService.LOCAL_BACKUP_AUTHORITY && uri.authority !== UserDataSyncResourceProviderService.REMOTE_BACKUP_AUTHORITY) { return undefined; } const paths = []; while (uri.path !== '/') { paths.unshift(this.extUri.basename(uri)); uri = this.extUri.dirname(uri); } if (paths.length < 2) { return undefined; } const remote = uri.authority === UserDataSyncResourceProviderService.REMOTE_BACKUP_AUTHORITY; const syncResource = paths.shift(); const profile = paths.shift(); let collection; let ref; let node; while (paths.length) { const path = paths.shift(); if (path.startsWith('collection:')) { collection = path.substring('collection:'.length); } else if (path.startsWith('ref:')) { ref = path.substring('ref:'.length); } else { node = path; } } return { remote, syncResource, profile, collection, ref, node, }; } parseSyncData(content, syncResource) { try { const syncData = JSON.parse(content); if (isSyncData(syncData)) { return syncData; } } catch (error) { this.logService.error(error); } throw new UserDataSyncError(localize('incompatible sync data', "Cannot parse sync data as it is not compatible with the current version."), "IncompatibleRemoteContent" /* UserDataSyncErrorCode.IncompatibleRemoteContent */, syncResource); } async getUserData(syncResource, ref, collection) { const content = await this.userDataSyncStoreService.resolveResourceContent(syncResource, ref, collection); return { ref, content }; } }; UserDataSyncResourceProviderService = __decorate([ __param(0, IUserDataSyncStoreService), __param(1, IUserDataSyncBackupStoreService), __param(2, IUserDataSyncLogService), __param(3, IUriIdentityService), __param(4, IEnvironmentService), __param(5, IStorageService), __param(6, IFileService), __param(7, IUserDataProfilesService), __param(8, IConfigurationService), __param(9, IInstantiationService) ], UserDataSyncResourceProviderService); export { UserDataSyncResourceProviderService };