@sussudio/platform
Version:
Internal APIs for VS Code's service injection the base services.
199 lines (198 loc) • 8.66 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { distinct } from '@sussudio/base/common/arrays.mjs';
import { isObject, isString } from '@sussudio/base/common/types.mjs';
import { localize } from 'vscode-nls.mjs';
import {
allSettings,
Extensions as ConfigurationExtensions,
} from '../../configuration/common/configurationRegistry.mjs';
import { EXTENSION_IDENTIFIER_PATTERN } from '../../extensionManagement/common/extensionManagement.mjs';
import { createDecorator } from '../../instantiation/common/instantiation.mjs';
import { Extensions as JSONExtensions } from '../../jsonschemas/common/jsonContributionRegistry.mjs';
import { Registry } from '../../registry/common/platform.mjs';
export const CONFIGURATION_SYNC_STORE_KEY = 'configurationSync.store';
export function getDisallowedIgnoredSettings() {
const allSettings = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties();
return Object.keys(allSettings).filter((setting) => !!allSettings[setting].disallowSyncIgnore);
}
export function getDefaultIgnoredSettings() {
const allSettings = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties();
const ignoreSyncSettings = Object.keys(allSettings).filter((setting) => !!allSettings[setting].ignoreSync);
const machineSettings = Object.keys(allSettings).filter(
(setting) =>
allSettings[setting].scope === 2 /* ConfigurationScope.MACHINE */ ||
allSettings[setting].scope === 6 /* ConfigurationScope.MACHINE_OVERRIDABLE */,
);
const disallowedSettings = getDisallowedIgnoredSettings();
return distinct([CONFIGURATION_SYNC_STORE_KEY, ...ignoreSyncSettings, ...machineSettings, ...disallowedSettings]);
}
export const USER_DATA_SYNC_CONFIGURATION_SCOPE = 'settingsSync';
export const CONFIG_SYNC_KEYBINDINGS_PER_PLATFORM = 'settingsSync.keybindingsPerPlatform';
export function registerConfiguration() {
const ignoredSettingsSchemaId = 'vscode://schemas/ignoredSettings';
const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration);
configurationRegistry.registerConfiguration({
id: 'settingsSync',
order: 30,
title: localize('settings sync', 'Settings Sync'),
type: 'object',
properties: {
[CONFIG_SYNC_KEYBINDINGS_PER_PLATFORM]: {
type: 'boolean',
description: localize('settingsSync.keybindingsPerPlatform', 'Synchronize keybindings for each platform.'),
default: true,
scope: 1 /* ConfigurationScope.APPLICATION */,
tags: ['sync', 'usesOnlineServices'],
},
'settingsSync.ignoredExtensions': {
type: 'array',
markdownDescription: localize(
'settingsSync.ignoredExtensions',
'List of extensions to be ignored while synchronizing. The identifier of an extension is always `${publisher}.${name}`. For example: `vscode.csharp`.',
),
items: [
{
type: 'string',
pattern: EXTENSION_IDENTIFIER_PATTERN,
errorMessage: localize(
'app.extension.identifier.errorMessage',
"Expected format '${publisher}.${name}'. Example: 'vscode.csharp'.",
),
},
],
default: [],
scope: 1 /* ConfigurationScope.APPLICATION */,
uniqueItems: true,
disallowSyncIgnore: true,
tags: ['sync', 'usesOnlineServices'],
},
'settingsSync.ignoredSettings': {
type: 'array',
description: localize('settingsSync.ignoredSettings', 'Configure settings to be ignored while synchronizing.'),
default: [],
scope: 1 /* ConfigurationScope.APPLICATION */,
$ref: ignoredSettingsSchemaId,
additionalProperties: true,
uniqueItems: true,
disallowSyncIgnore: true,
tags: ['sync', 'usesOnlineServices'],
},
},
});
const jsonRegistry = Registry.as(JSONExtensions.JSONContribution);
const registerIgnoredSettingsSchema = () => {
const disallowedIgnoredSettings = getDisallowedIgnoredSettings();
const defaultIgnoredSettings = getDefaultIgnoredSettings().filter((s) => s !== CONFIGURATION_SYNC_STORE_KEY);
const settings = Object.keys(allSettings.properties).filter(
(setting) => defaultIgnoredSettings.indexOf(setting) === -1,
);
const ignoredSettings = defaultIgnoredSettings.filter(
(setting) => disallowedIgnoredSettings.indexOf(setting) === -1,
);
const ignoredSettingsSchema = {
items: {
type: 'string',
enum: [...settings, ...ignoredSettings.map((setting) => `-${setting}`)],
},
};
jsonRegistry.registerSchema(ignoredSettingsSchemaId, ignoredSettingsSchema);
};
return configurationRegistry.onDidUpdateConfiguration(() => registerIgnoredSettingsSchema());
}
export function isAuthenticationProvider(thing) {
return thing && isObject(thing) && isString(thing.id) && Array.isArray(thing.scopes);
}
export const ALL_SYNC_RESOURCES = [
'settings' /* SyncResource.Settings */,
'keybindings' /* SyncResource.Keybindings */,
'snippets' /* SyncResource.Snippets */,
'tasks' /* SyncResource.Tasks */,
'extensions' /* SyncResource.Extensions */,
'globalState' /* SyncResource.GlobalState */,
'profiles' /* SyncResource.Profiles */,
];
export function getPathSegments(collection, ...paths) {
return collection ? [collection, ...paths] : paths;
}
export function getLastSyncResourceUri(collection, syncResource, environmentService, extUri) {
return extUri.joinPath(
environmentService.userDataSyncHome,
...getPathSegments(collection, syncResource, `lastSync${syncResource}.json`),
);
}
export const IUserDataSyncStoreManagementService = createDecorator('IUserDataSyncStoreManagementService');
export const IUserDataSyncStoreService = createDecorator('IUserDataSyncStoreService');
export const IUserDataSyncBackupStoreService = createDecorator('IUserDataSyncBackupStoreService');
//#endregion
// #region User Data Sync Headers
export const HEADER_OPERATION_ID = 'x-operation-id';
export const HEADER_EXECUTION_ID = 'X-Execution-Id';
export function createSyncHeaders(executionId) {
const headers = {};
headers[HEADER_EXECUTION_ID] = executionId;
return headers;
}
export class UserDataSyncError extends Error {
code;
resource;
operationId;
constructor(message, code, resource, operationId) {
super(message);
this.code = code;
this.resource = resource;
this.operationId = operationId;
this.name = `${this.code} (UserDataSyncError) syncResource:${this.resource || 'unknown'} operationId:${
this.operationId || 'unknown'
}`;
}
}
export class UserDataSyncStoreError extends UserDataSyncError {
url;
serverCode;
constructor(message, url, code, serverCode, operationId) {
super(message, code, undefined, operationId);
this.url = url;
this.serverCode = serverCode;
}
}
export class UserDataAutoSyncError extends UserDataSyncError {
constructor(message, code) {
super(message, code);
}
}
(function (UserDataSyncError) {
function toUserDataSyncError(error) {
if (error instanceof UserDataSyncError) {
return error;
}
const match = /^(.+) \(UserDataSyncError\) syncResource:(.+) operationId:(.+)$/.exec(error.name);
if (match && match[1]) {
const syncResource = match[2] === 'unknown' ? undefined : match[2];
const operationId = match[3] === 'unknown' ? undefined : match[3];
return new UserDataSyncError(error.message, match[1], syncResource, operationId);
}
return new UserDataSyncError(error.message, 'Unknown' /* UserDataSyncErrorCode.Unknown */);
}
UserDataSyncError.toUserDataSyncError = toUserDataSyncError;
})(UserDataSyncError || (UserDataSyncError = {}));
//#endregion
// #region keys synced only in web
export const SYNC_SERVICE_URL_TYPE = 'sync.store.url.type';
export function getEnablementKey(resource) {
return `sync.enable.${resource}`;
}
// #endregion
// #region User Data Sync Services
export const IUserDataSyncEnablementService = createDecorator('IUserDataSyncEnablementService');
export const IUserDataSyncService = createDecorator('IUserDataSyncService');
export const IUserDataSyncResourceProviderService = createDecorator('IUserDataSyncResourceProviderService');
export const IUserDataAutoSyncService = createDecorator('IUserDataAutoSyncService');
export const IUserDataSyncUtilService = createDecorator('IUserDataSyncUtilService');
export const IUserDataSyncLogService = createDecorator('IUserDataSyncLogService');
//#endregion
export const USER_DATA_SYNC_SCHEME = 'vscode-userdata-sync';
export const PREVIEW_DIR_NAME = 'preview';
export const EXTENSIONS_SYNC_CONTEXT_KEY = 'extensionsSync';