import * as path from 'node:path'; import * as vscode from 'vscode'; import type { ModelService } from '../model/service'; import { log } from '../util/log'; import type { SyncFeature } from './index'; import { liveBridge } from './liveBridge'; // Kept in step with SYNC_COMMANDS in ./index (which lives in the other bundle). const COMMANDS = [ 'archify.sync.signIn', 'archify.sync.signOut', 'archify.sync.share', 'archify.sync.invite', 'archify.sync.join', 'archify.sync.publish', 'archify.sync.versions', 'archify.sync.stop', 'archify.sync.menu', 'archify.sync.setServer', ] as const; /** * Archify Sync is optional. This registers its commands and the URI handler, * and loads dist/sync.js (Yjs, the WebSocket) only when it is needed: a model * in the workspace is shared, someone signed in on this machine, or a sync * command or link runs. Without that, nothing else happens. */ export function registerSync(context: vscode.ExtensionContext, models: ModelService): vscode.Disposable[] { let feature: Promise | undefined; const load = (): Promise => (feature ??= (async () => { // A runtime path, so esbuild leaves the sync bundle out of this one. const bundle = path.join(__dirname, 'sync.js'); const mod = require(bundle) as typeof import('./index'); const sync = new mod.SyncFeature(context, models, log(), liveBridge); context.subscriptions.push(sync); await sync.start(); return sync; })()); void (async () => { const used = context.globalState.get('archifySync.used') === true; const shared = used || (await vscode.workspace.findFiles('**/.archify-sync', '{**/node_modules/**,**/.git/**}', 1)).length > 0; if (shared) load().catch((error) => log().error(`sync: did not start: ${String(error)}`)); })(); return [ liveBridge, ...COMMANDS.map((id) => vscode.commands.registerCommand(id, async (...args: unknown[]) => (await load()).run(id, ...args)), ), vscode.window.registerUriHandler({ handleUri: async (uri) => (await load()).handleUri(uri) }), ]; }