src/vs/platform/userDataSync/common/userDataSync.ts

666 LOC · 643 covered · 23 uncovered · 34 ranges · 771 concepts · 11 introducers · 444 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

1 > /*--------------------------------------------------------------------------------------------- userDataSync.ts ×15
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { distinct } from '../../../base/common/arrays.js';
7 > import { VSBufferReadableStream } from '../../../base/common/buffer.js';
8 > import { IStringDictionary } from '../../../base/common/collections.js';
9 > import { Event } from '../../../base/common/event.js';
10 > import { FormattingOptions } from '../../../base/common/jsonFormatter.js';
11 > import { IJSONSchema } from '../../../base/common/jsonSchema.js';
12 > import { IDisposable } from '../../../base/common/lifecycle.js';
13 > import { IExtUri } from '../../../base/common/resources.js';
14 > import { isObject, isString } from '../../../base/common/types.js';
15 > import { URI } from '../../../base/common/uri.js';
16 > import { IHeaders } from '../../../base/parts/request/common/request.js';
17 > import { localize } from '../../../nls.js';
18 > import { allSettings, ConfigurationScope, Extensions as ConfigurationExtensions, IConfigurationRegistry, IRegisteredConfigurationPropertySchema, getAllConfigurationProperties, parseScope } from '../../configuration/common/configurationRegistry.js';
19 > import { IEnvironmentService } from '../../environment/common/environment.js';
20 > import { EXTENSION_IDENTIFIER_PATTERN, IExtensionIdentifier } from '../../extensionManagement/common/extensionManagement.js';
21 > import { IExtensionManifest } from '../../extensions/common/extensions.js';
22 > import { createDecorator } from '../../instantiation/common/instantiation.js';
23 > import { Extensions as JSONExtensions, IJSONContributionRegistry } from '../../jsonschemas/common/jsonContributionRegistry.js';
24 > import { ILogService } from '../../log/common/log.js';
25 > import { Registry } from '../../registry/common/platform.js';
26 > import { StorageScope } from '../../storage/common/storage.js';
27 > import { IUserDataProfile, UseDefaultProfileFlags } from '../../userDataProfile/common/userDataProfile.js';
28 > import { IUserDataSyncMachine } from './userDataSyncMachines.js';
29 >
30 > export function getDisallowedIgnoredSettings(): string[] {
31 > const allSettings = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).getConfigurationProperties(); userDataSync.ts ×4
32 > return Object.keys(allSettings).filter(setting => !!allSettings[setting].disallowSyncIgnore);
33 > }
35 > export function getDefaultIgnoredSettings(excludeExtensions: boolean = false): string[] {
36 > const allSettings = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).getConfigurationProperties(); userDataSync.ts ×4
37 > const ignoredSettings = getIgnoredSettings(allSettings, excludeExtensions);
38 > const disallowedSettings = getDisallowedIgnoredSettings();
39 > return distinct([...ignoredSettings, ...disallowedSettings]);
40 > }
42 > export function getIgnoredSettingsForExtension(manifest: IExtensionManifest): string[] {
43 if (!manifest.contributes?.configuration) {
44 return [];
45 }
46 const configurations = Array.isArray(manifest.contributes.configuration) ? manifest.contributes.configuration : [manifest.contributes.configuration];
47 if (!configurations.length) {
48 return [];
49 }
50 const properties = getAllConfigurationProperties(configurations);
51 return getIgnoredSettings(properties, false);
52 }
54 > function getIgnoredSettings(properties: IStringDictionary<IRegisteredConfigurationPropertySchema>, excludeExtensions: boolean): string[] { userDataSync.ts ×4
55 > const ignoredSettings = new Set<string>();
56 > for (const key in properties) {
57 > if (excludeExtensions && !!properties[key].source) {
58 continue;
59 }
60 > const scope = isString(properties[key].scope) ? parseScope(properties[key].scope) : properties[key].scope; userDataSync.ts ×4
61 > if (properties[key].ignoreSync
62 > || scope === ConfigurationScope.MACHINE
63 > || scope === ConfigurationScope.MACHINE_OVERRIDABLE
64 > ) {
65 > ignoredSettings.add(key);
66 > }
67 > }
68 > return [...ignoredSettings.values()];
69 > }
71 > export const USER_DATA_SYNC_CONFIGURATION_SCOPE = 'settingsSync';
72 >
73 > export interface IUserDataSyncConfiguration {
74 > keybindingsPerPlatform?: boolean;
75 > ignoredExtensions?: string[];
76 > ignoredSettings?: string[];
77 > }
78 >
79 > export const CONFIG_SYNC_KEYBINDINGS_PER_PLATFORM = 'settingsSync.keybindingsPerPlatform';
80 >
81 > export function registerConfiguration(): IDisposable {
82 > const ignoredSettingsSchemaId = 'vscode://schemas/ignoredSettings'; userDataSyncStoreService.ts ×36
83 > const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
84 > configurationRegistry.registerConfiguration({
85 > id: 'settingsSync',
86 > order: 30,
87 > title: localize('settings sync', "Settings Sync"),
88 > type: 'object',
89 > properties: {
90 > [CONFIG_SYNC_KEYBINDINGS_PER_PLATFORM]: {
91 > type: 'boolean',
92 > description: localize('settingsSync.keybindingsPerPlatform', "Synchronize keybindings for each platform."),
93 > default: true,
94 > scope: ConfigurationScope.APPLICATION,
95 > tags: ['sync', 'usesOnlineServices']
96 > },
97 > 'settingsSync.ignoredExtensions': {
98 > 'type': 'array',
99 > 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`."),
100 > items: [{
101 > type: 'string',
102 > pattern: EXTENSION_IDENTIFIER_PATTERN,
103 > errorMessage: localize('app.extension.identifier.errorMessage', "Expected format '${publisher}.${name}'. Example: 'vscode.csharp'.")
104 > }],
105 > 'default': [],
106 > 'scope': ConfigurationScope.APPLICATION,
107 > uniqueItems: true,
108 > disallowSyncIgnore: true,
109 > tags: ['sync', 'usesOnlineServices']
110 > },
111 > 'settingsSync.ignoredSettings': {
112 > 'type': 'array',
113 > description: localize('settingsSync.ignoredSettings', "Configure settings to be ignored while synchronizing."),
114 > 'default': [],
115 > 'scope': ConfigurationScope.APPLICATION,
116 > $ref: ignoredSettingsSchemaId,
117 > additionalProperties: true,
118 > uniqueItems: true,
119 > disallowSyncIgnore: true,
120 > tags: ['sync', 'usesOnlineServices']
121 > }
122 > }
123 > });
124 > const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
125 > const registerIgnoredSettingsSchema = () => {
126 > const disallowedIgnoredSettings = getDisallowedIgnoredSettings(); configurationService.ts ×1
127 > const defaultIgnoredSettings = getDefaultIgnoredSettings();
128 > const settings = Object.keys(allSettings.properties).filter(setting => !defaultIgnoredSettings.includes(setting));
129 > const ignoredSettings = defaultIgnoredSettings.filter(setting => !disallowedIgnoredSettings.includes(setting));
130 > const ignoredSettingsSchema: IJSONSchema = {
131 > items: {
132 > type: 'string',
133 > enum: [...settings, ...ignoredSettings.map(setting => `-${setting}`)]
134 > },
135 > };
136 > jsonRegistry.registerSchema(ignoredSettingsSchemaId, ignoredSettingsSchema);
137 > };
138 > return configurationRegistry.onDidUpdateConfiguration(() => registerIgnoredSettingsSchema()); userDataSyncStoreService.ts ×36
139 > }
141 > // #region User Data Sync Store
142 >
143 > export const NON_EXISTING_RESOURCE_REF = '0';
144 >
145 > export interface IUserData {
146 > ref: string;
147 > content: string | null;
148 > }
149 >
150 > export type IAuthenticationProvider = { id: string; scopes: string[] };
151 >
152 > export interface IUserDataSyncStore {
153 > readonly url: URI;
154 > readonly type: UserDataSyncStoreType;
155 > readonly defaultUrl: URI;
156 > readonly stableUrl: URI;
157 > readonly insidersUrl: URI;
158 > readonly canSwitch: boolean;
159 > readonly authenticationProviders: IAuthenticationProvider[];
160 > }
161 >
162 > export function isAuthenticationProvider(thing: any): thing is IAuthenticationProvider {
163 return thing
164 && isObject(thing)
165 && isString(thing.id)
166 && Array.isArray(thing.scopes);
167 }
169 > export const enum SyncResource {
170 > Settings = 'settings',
171 > Keybindings = 'keybindings',
172 > Snippets = 'snippets',
173 > Prompts = 'prompts',
174 > Tasks = 'tasks',
175 > Mcp = 'mcp',
176 > Extensions = 'extensions',
177 > GlobalState = 'globalState',
178 > Profiles = 'profiles',
179 > WorkspaceState = 'workspaceState',
180 > }
181 > export const ALL_SYNC_RESOURCES: SyncResource[] = [SyncResource.Settings, SyncResource.Keybindings, SyncResource.Snippets, SyncResource.Prompts, SyncResource.Tasks, SyncResource.Extensions, SyncResource.GlobalState, SyncResource.Profiles, SyncResource.Mcp];
182 >
183 > export function getPathSegments(collection: string | undefined, ...paths: string[]): string[] {
184 > return collection ? [collection, ...paths] : paths; abstractSynchronizer.ts ×7
185 > }
187 > export function getLastSyncResourceUri(collection: string | undefined, syncResource: SyncResource, environmentService: IEnvironmentService, extUri: IExtUri): URI {
188 > return extUri.joinPath(environmentService.userDataSyncHome, ...getPathSegments(collection, syncResource, `lastSync${syncResource}.json`)); abstractSynchronizer.ts ×7
189 > }
191 > export type IUserDataResourceManifest = Record<ServerResource, string>;
192 >
193 > export interface IUserDataCollectionManifest {
194 > [collectionId: string]: {
195 > readonly latest?: IUserDataResourceManifest;
196 > };
197 > }
198 >
199 > export interface IUserDataManifest {
200 > readonly latest?: IUserDataResourceManifest;
201 > readonly session: string;
202 > readonly ref: string;
203 > readonly collections?: IUserDataCollectionManifest;
204 > }
205 >
206 > export function isUserDataManifest(thing: any): thing is IUserDataManifest {
207 > return thing userDataSyncService.ts ×22
208 > && isString(thing.session) userDataSyncService.ts ×2
209 > && isString(thing.ref)
210 > && (isObject(thing.latest) || thing.latest === undefined)
211 > && (isObject(thing.collections) || thing.collections === undefined);
214 > export interface IUserDataSyncActivityData {
215 > resources?: {
216 > [resourceId: string]: { created: number; content: string }[];
217 > };
218 > collections?: {
219 > [collectionId: string]: {
220 > resources?: {
221 > [resourceId: string]: { created: number; content: string }[];
222 > } | undefined;
223 > };
224 > };
225 > }
226 >
227 > export interface IUserDataSyncLatestData {
228 > resources?: IStringDictionary<IUserData>;
229 > collections?: {
230 > [collectionId: string]: {
231 > resources?: IStringDictionary<IUserData>;
232 > };
233 > };
234 > }
235 >
236 > export interface IResourceRefHandle {
237 > ref: string;
238 > created: number;
239 > }
240 >
241 > export type ServerResource = SyncResource | 'machines' | 'editSessions' | 'workspaceState';
242 > export type UserDataSyncStoreType = 'insiders' | 'stable';
243 >
244 > export const IUserDataSyncStoreManagementService = createDecorator<IUserDataSyncStoreManagementService>('IUserDataSyncStoreManagementService');
245 > export interface IUserDataSyncStoreManagementService {
246 > readonly _serviceBrand: undefined;
247 > readonly onDidChangeUserDataSyncStore: Event<void>;
248 > readonly userDataSyncStore: IUserDataSyncStore | undefined;
249 > switch(type: UserDataSyncStoreType): Promise<void>;
250 > getPreviousUserDataSyncStore(): Promise<IUserDataSyncStore | undefined>;
251 > }
252 >
253 > export const IUserDataSyncStoreService = createDecorator<IUserDataSyncStoreService>('IUserDataSyncStoreService');
254 > export interface IUserDataSyncStoreService {
255 > readonly _serviceBrand: undefined;
256 > readonly onDidChangeDonotMakeRequestsUntil: Event<void>;
257 > readonly donotMakeRequestsUntil: Date | undefined;
258 >
259 > readonly onTokenFailed: Event<UserDataSyncErrorCode>;
260 > readonly onTokenSucceed: Event<void>;
261 > setAuthToken(token: string, type: string): void;
262 >
263 > manifest(oldValue: IUserDataManifest | null, headers?: IHeaders): Promise<IUserDataManifest | null>;
264 > readResource(resource: ServerResource, oldValue: IUserData | null, collection?: string, headers?: IHeaders): Promise<IUserData>;
265 > writeResource(resource: ServerResource, content: string, ref: string | null, collection?: string, headers?: IHeaders): Promise<string>;
266 > deleteResource(resource: ServerResource, ref: string | null, collection?: string): Promise<void>;
267 > getAllResourceRefs(resource: ServerResource, collection?: string): Promise<IResourceRefHandle[]>;
268 > resolveResourceContent(resource: ServerResource, ref: string, collection?: string, headers?: IHeaders): Promise<string | null>;
269 >
270 > getAllCollections(headers?: IHeaders): Promise<string[]>;
271 > createCollection(headers?: IHeaders): Promise<string>;
272 > deleteCollection(collection?: string, headers?: IHeaders): Promise<void>;
273 >
274 > getLatestData(headers?: IHeaders): Promise<IUserDataSyncLatestData | null>;
275 > getActivityData(): Promise<VSBufferReadableStream>;
276 >
277 > clear(): Promise<void>;
278 > }
279 >
280 > export const IUserDataSyncLocalStoreService = createDecorator<IUserDataSyncLocalStoreService>('IUserDataSyncLocalStoreService');
281 > export interface IUserDataSyncLocalStoreService {
282 > readonly _serviceBrand: undefined;
283 > writeResource(resource: ServerResource, content: string, cTime: Date, collection?: string, root?: URI): Promise<void>;
284 > getAllResourceRefs(resource: ServerResource, collection?: string, root?: URI): Promise<IResourceRefHandle[]>;
285 > resolveResourceContent(resource: ServerResource, ref: string, collection?: string, root?: URI): Promise<string | null>;
286 > }
287 >
288 > //#endregion
289 >
290 > // #region User Data Sync Headers
291 >
292 > export const HEADER_OPERATION_ID = 'x-operation-id';
293 > export const HEADER_EXECUTION_ID = 'X-Execution-Id';
294 >
295 > export function createSyncHeaders(executionId: string): IHeaders {
296 > const headers: IHeaders = {}; userDataSyncService.ts ×22
297 > headers[HEADER_EXECUTION_ID] = executionId;
298 > return headers;
299 > }
301 > //#endregion
302 >
303 > // #region User Data Sync Error
304 >
305 > export const enum UserDataSyncErrorCode {
306 > // Client Errors (>= 400 )
307 > Unauthorized = 'Unauthorized', /* 401 */
308 > Forbidden = 'Forbidden', /* 403 */
309 > NotFound = 'NotFound', /* 404 */
310 > MethodNotFound = 'MethodNotFound', /* 405 */
311 > Conflict = 'Conflict', /* 409 */
312 > Gone = 'Gone', /* 410 */
313 > PreconditionFailed = 'PreconditionFailed', /* 412 */
314 > TooLarge = 'TooLarge', /* 413 */
315 > UpgradeRequired = 'UpgradeRequired', /* 426 */
316 > PreconditionRequired = 'PreconditionRequired', /* 428 */
317 > TooManyRequests = 'RemoteTooManyRequests', /* 429 */
318 > TooManyRequestsAndRetryAfter = 'TooManyRequestsAndRetryAfter', /* 429 + Retry-After */
319 >
320 > // Local Errors
321 > RequestFailed = 'RequestFailed',
322 > RequestCanceled = 'RequestCanceled',
323 > RequestTimeout = 'RequestTimeout',
324 > RequestProtocolNotSupported = 'RequestProtocolNotSupported',
325 > RequestPathNotEscaped = 'RequestPathNotEscaped',
326 > RequestHeadersNotObject = 'RequestHeadersNotObject',
327 > NoCollection = 'NoCollection',
328 > NoRef = 'NoRef',
329 > EmptyResponse = 'EmptyResponse',
330 > TurnedOff = 'TurnedOff',
331 > SessionExpired = 'SessionExpired',
332 > ServiceChanged = 'ServiceChanged',
333 > DefaultServiceChanged = 'DefaultServiceChanged',
334 > LocalTooManyProfiles = 'LocalTooManyProfiles',
335 > LocalTooManyRequests = 'LocalTooManyRequests',
336 > LocalPreconditionFailed = 'LocalPreconditionFailed',
337 > LocalInvalidContent = 'LocalInvalidContent',
338 > LocalError = 'LocalError',
339 > IncompatibleLocalContent = 'IncompatibleLocalContent',
340 > IncompatibleRemoteContent = 'IncompatibleRemoteContent',
341 >
342 > Unknown = 'Unknown',
343 > }
344 >
345 > export class UserDataSyncError extends Error {
346 >
347 > constructor(
348 > message: string, userDataSync.ts ×1
349 > readonly code: UserDataSyncErrorCode,
350 > readonly resource?: SyncResource,
351 > readonly operationId?: string
352 > ) {
353 > super(message);
354 > this.name = `${this.code} (UserDataSyncError) syncResource:${this.resource || 'unknown'} operationId:${this.operationId || 'unknown'}`;
355 > }
357 > }
358 >
359 > export class UserDataSyncStoreError extends UserDataSyncError {
360 > constructor(message: string, readonly url: string, code: UserDataSyncErrorCode, readonly serverCode: number | undefined, operationId: string | undefined) {
361 > super(message, code, undefined, operationId); userDataSync.ts ×1
362 > }
364 >
365 > export class UserDataAutoSyncError extends UserDataSyncError {
366 > constructor(message: string, code: UserDataSyncErrorCode) {
367 > super(message, code); userDataAutoSyncService.ts ×1
368 > }
370 >
371 > export namespace UserDataSyncError {
372 >
373 > export function toUserDataSyncError(error: Error): UserDataSyncError {
374 > if (error instanceof UserDataSyncError) { userDataSync.ts ×3
375 > return error;
376 > }
377 const match = /^(.+) \(UserDataSyncError\) syncResource:(.+) operationId:(.+)$/.exec(error.name);
378 > if (match && match[1]) { userDataSync.ts ×3
379 const syncResource = match[2] === 'unknown' ? undefined : match[2] as SyncResource;
380 const operationId = match[3] === 'unknown' ? undefined : match[3];
381 return new UserDataSyncError(error.message, <UserDataSyncErrorCode>match[1], syncResource, operationId);
382 }
383 return new UserDataSyncError(error.message, UserDataSyncErrorCode.Unknown);
386 > }
387 >
388 > //#endregion
389 >
390 > // #region User Data Synchroniser
391 >
392 > export interface ISyncUserDataProfile {
393 > readonly id: string;
394 > readonly collection: string;
395 > readonly name: string;
396 > readonly icon?: string;
397 > readonly useDefaultFlags?: UseDefaultProfileFlags;
398 > }
399 >
400 > export type ISyncExtension = ILocalSyncExtension | IRemoteSyncExtension;
401 >
402 > export interface ILocalSyncExtension {
403 > identifier: IExtensionIdentifier;
404 > pinned: boolean;
405 > version: string;
406 > preRelease: boolean;
407 > disabled?: boolean;
408 > installed?: boolean;
409 > isApplicationScoped?: boolean;
410 > state?: IStringDictionary<any>;
411 > }
412 >
413 > export interface IRemoteSyncExtension {
414 > identifier: IExtensionIdentifier;
415 > version: string;
416 > pinned?: boolean;
417 > preRelease?: boolean;
418 > disabled?: boolean;
419 > installed?: boolean;
420 > isApplicationScoped?: boolean;
421 > state?: IStringDictionary<any>;
422 > }
423 >
424 > export interface IStorageValue {
425 > version: number;
426 > value: string;
427 > scope?: StorageScope;
428 > }
429 >
430 > export interface IGlobalState {
431 > storage: IStringDictionary<IStorageValue>;
432 > }
433 >
434 > export interface IWorkspaceState {
435 > folders: IWorkspaceStateFolder[];
436 > storage: IStringDictionary<string>;
437 > version: number;
438 > }
439 >
440 > export interface IWorkspaceStateFolder {
441 > resourceUri: string;
442 > workspaceFolderIdentity: string;
443 > }
444 >
445 > export const enum SyncStatus {
446 > Uninitialized = 'uninitialized',
447 > Idle = 'idle',
448 > Syncing = 'syncing',
449 > HasConflicts = 'hasConflicts',
450 > }
451 >
452 > export interface ISyncResourceHandle {
453 > created: number;
454 > uri: URI;
455 > }
456 >
457 > export interface IRemoteUserData {
458 > ref: string;
459 > syncData: ISyncData | null;
460 > }
461 >
462 > export interface ISyncData {
463 > version: number;
464 > machineId?: string;
465 > content: string;
466 > }
467 >
468 > export const enum Change {
469 > None,
470 > Added,
471 > Modified,
472 > Deleted,
473 > }
474 >
475 > export const enum MergeState {
476 > Preview = 'preview',
477 > Conflict = 'conflict',
478 > Accepted = 'accepted',
479 > }
480 >
481 > export interface IResourcePreview {
482 > readonly baseResource: URI;
483 > readonly remoteResource: URI;
484 > readonly localResource: URI;
485 > readonly previewResource: URI;
486 > readonly acceptedResource: URI;
487 > readonly localChange: Change;
488 > readonly remoteChange: Change;
489 > readonly mergeState: MergeState;
490 > }
491 >
492 > export interface IUserDataSyncResource {
493 > readonly syncResource: SyncResource;
494 > readonly profile: IUserDataProfile;
495 > }
496 >
497 > export interface IUserDataSyncResourceConflicts extends IUserDataSyncResource {
498 > readonly conflicts: IResourcePreview[];
499 > }
500 >
501 > export interface IUserDataSyncResourcePreview extends IUserDataSyncResource {
502 > readonly isLastSyncFromCurrentMachine: boolean;
503 > readonly resourcePreviews: IResourcePreview[];
504 > }
505 >
506 > export interface IUserDataSyncResourceError extends IUserDataSyncResource {
507 > readonly error: UserDataSyncError;
508 > }
509 >
510 > export interface IUserDataSyncResourceInitializer {
511 > initialize(userData: IUserData): Promise<void>;
512 > }
513 >
514 > export interface IUserDataSynchroniser {
515 >
516 > readonly resource: SyncResource;
517 > readonly status: SyncStatus;
518 > readonly onDidChangeStatus: Event<SyncStatus>;
519 >
520 > readonly conflicts: IUserDataSyncResourceConflicts;
521 > readonly onDidChangeConflicts: Event<IUserDataSyncResourceConflicts>;
522 >
523 > readonly onDidChangeLocal: Event<void>;
524 >
525 > sync(refOrUserData: string | IUserData | null, preview: boolean, userDataSyncConfiguration: IUserDataSyncConfiguration, headers: IHeaders): Promise<IUserDataSyncResourcePreview | null>;
526 > accept(resource: URI, content?: string | null): Promise<IUserDataSyncResourcePreview | null>;
527 > apply(force: boolean, headers: IHeaders): Promise<IUserDataSyncResourcePreview | null>;
528 > stop(): Promise<void>;
529 >
530 > hasPreviouslySynced(): Promise<boolean>;
531 > hasLocalData(): Promise<boolean>;
532 > resetLocal(): Promise<void>;
533 >
534 > resolveContent(resource: URI): Promise<string | null>;
535 > replace(content: string): Promise<boolean>;
536 > }
537 >
538 > //#endregion
539 >
540 > // #region keys synced only in web
541 >
542 > export const SYNC_SERVICE_URL_TYPE = 'sync.store.url.type';
543 > export function getEnablementKey(resource: SyncResource) { return `sync.enable.${resource}`; }
544 >
545 > // #endregion
546 >
547 > // #region User Data Sync Services
548 > export const IUserDataSyncEnablementService = createDecorator<IUserDataSyncEnablementService>('IUserDataSyncEnablementService');
549 > export interface IUserDataSyncEnablementService {
550 > _serviceBrand: undefined;
551 >
552 > readonly onDidChangeEnablement: Event<boolean>;
553 > isEnabled(): boolean;
554 > canToggleEnablement(): boolean;
555 > setEnablement(enabled: boolean): void;
556 >
557 > readonly onDidChangeResourceEnablement: Event<[SyncResource, boolean]>;
558 > isResourceEnabled(resource: SyncResource, defaultValue?: boolean): boolean;
559 > setResourceEnablement(resource: SyncResource, enabled: boolean): void;
560 >
561 > getResourceSyncStateVersion(resource: SyncResource): string | undefined;
562 >
563 > /**
564 > * Checks if resource enabled was explicitly configured before,
565 > * ignoring its default enablement value used in {@link isResourceEnabled}.
566 > */
567 > isResourceEnablementConfigured(resource: SyncResource): boolean;
568 > }
569 >
570 > export interface IUserDataSyncTask {
571 > readonly manifest: IUserDataManifest | null;
572 > run(): Promise<void>;
573 > stop(): Promise<void>;
574 > }
575 >
576 > export interface IUserDataManualSyncTask {
577 > readonly id: string;
578 > merge(): Promise<void>;
579 > apply(): Promise<void>;
580 > stop(): Promise<void>;
581 > }
582 >
583 > export const IUserDataSyncService = createDecorator<IUserDataSyncService>('IUserDataSyncService');
584 > export interface IUserDataSyncService {
585 > _serviceBrand: undefined;
586 >
587 > readonly status: SyncStatus;
588 > readonly onDidChangeStatus: Event<SyncStatus>;
589 >
590 > readonly conflicts: IUserDataSyncResourceConflicts[];
591 > readonly onDidChangeConflicts: Event<IUserDataSyncResourceConflicts[]>;
592 >
593 > readonly onDidChangeLocal: Event<SyncResource>;
594 > readonly onSyncErrors: Event<IUserDataSyncResourceError[]>;
595 >
596 > readonly lastSyncTime: number | undefined;
597 > readonly onDidChangeLastSyncTime: Event<number>;
598 >
599 > readonly onDidResetRemote: Event<void>;
600 > readonly onDidResetLocal: Event<void>;
601 >
602 > createSyncTask(manifest: IUserDataManifest | null, disableCache?: boolean): Promise<IUserDataSyncTask>;
603 > createManualSyncTask(): Promise<IUserDataManualSyncTask>;
604 > resolveContent(resource: URI): Promise<string | null>;
605 > accept(syncResource: IUserDataSyncResource, resource: URI, content: string | null | undefined, apply: boolean | { force: boolean }): Promise<void>;
606 >
607 > reset(): Promise<void>;
608 > resetRemote(): Promise<void>;
609 > cleanUpRemoteData(): Promise<void>;
610 > resetLocal(): Promise<void>;
611 > hasLocalData(): Promise<boolean>;
612 > hasPreviouslySynced(): Promise<boolean>;
613 >
614 > replace(syncResourceHandle: ISyncResourceHandle): Promise<void>;
615 >
616 > saveRemoteActivityData(location: URI): Promise<void>;
617 > extractActivityData(activityDataResource: URI, location: URI): Promise<void>;
618 > }
619 >
620 > export const IUserDataSyncResourceProviderService = createDecorator<IUserDataSyncResourceProviderService>('IUserDataSyncResourceProviderService');
621 > export interface IUserDataSyncResourceProviderService {
622 > _serviceBrand: undefined;
623 > getRemoteSyncedProfiles(): Promise<ISyncUserDataProfile[]>;
624 > getLocalSyncedProfiles(location?: URI): Promise<ISyncUserDataProfile[]>;
625 > getRemoteSyncResourceHandles(syncResource: SyncResource, profile?: ISyncUserDataProfile): Promise<ISyncResourceHandle[]>;
626 > getLocalSyncResourceHandles(syncResource: SyncResource, profile?: ISyncUserDataProfile, location?: URI): Promise<ISyncResourceHandle[]>;
627 > getAssociatedResources(syncResourceHandle: ISyncResourceHandle): Promise<{ resource: URI; comparableResource: URI }[]>;
628 > getMachineId(syncResourceHandle: ISyncResourceHandle): Promise<string | undefined>;
629 > getLocalSyncedMachines(location?: URI): Promise<IUserDataSyncMachine[]>;
630 > resolveContent(resource: URI): Promise<string | null>;
631 > resolveUserDataSyncResource(syncResourceHandle: ISyncResourceHandle): IUserDataSyncResource | undefined;
632 > }
633 >
634 > export type SyncOptions = { immediately?: boolean; skipIfSyncedRecently?: boolean; disableCache?: boolean };
635 >
636 > export const IUserDataAutoSyncService = createDecorator<IUserDataAutoSyncService>('IUserDataAutoSyncService');
637 > export interface IUserDataAutoSyncService {
638 > _serviceBrand: undefined;
639 > readonly onError: Event<UserDataSyncError>;
640 > turnOn(): Promise<void>;
641 > turnOff(everywhere: boolean): Promise<void>;
642 > triggerSync(sources: string[], options?: SyncOptions): Promise<void>;
643 > }
644 >
645 > export const IUserDataSyncUtilService = createDecorator<IUserDataSyncUtilService>('IUserDataSyncUtilService');
646 > export interface IUserDataSyncUtilService {
647 > readonly _serviceBrand: undefined;
648 > resolveUserBindings(userbindings: string[]): Promise<IStringDictionary<string>>;
649 > resolveFormattingOptions(resource: URI): Promise<FormattingOptions>;
650 > resolveDefaultCoreIgnoredSettings(): Promise<string[]>;
651 > }
652 >
653 > export const IUserDataSyncLogService = createDecorator<IUserDataSyncLogService>('IUserDataSyncLogService');
654 > export interface IUserDataSyncLogService extends ILogService { }
655 >
656 > export interface IConflictSetting {
657 > key: string;
658 > localValue: any | undefined;
659 > remoteValue: any | undefined;
660 > }
661 >
662 > //#endregion
663 >
664 > export const USER_DATA_SYNC_LOG_ID = 'userDataSync';
665 > export const USER_DATA_SYNC_SCHEME = 'vscode-userdata-sync';
666 > export const PREVIEW_DIR_NAME = 'preview';