Several people edit one model at once through a server you run yourself (archify-vscode-ext-sync); the files stay ordinary files on each disk. Sign-in through the browser, offline-first with later merge, teammates' cursors in the Source view and text editors, and a Shared section on the model page with people, versions, Compare and Restore. Without a server nothing changes: the sync code is a separate bundle that loads only when a model is shared, after a sign-in, or when a sync command or invite link is used.
61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
// What the extension and the Archify Sync server agree on. Mirrors
|
|
// `packages/protocol` (generated from Rust) in archify-vscode-ext-sync; keep
|
|
// both in step when the protocol changes.
|
|
|
|
export const PROTOCOL_VERSION = 1;
|
|
/** Root map of a space's Yjs document: model-root-relative POSIX path → Y.Text. */
|
|
export const FILES_MAP = 'files';
|
|
/** The link file in a model root: names server and space, holds no secrets. */
|
|
export const LINK_FILE = '.archify-sync';
|
|
|
|
export type OrgRole = 'admin' | 'member';
|
|
export type SpaceRole = 'owner' | 'editor';
|
|
export type VersionKind = 'snapshot' | 'publish' | 'restore';
|
|
|
|
export interface ApiError { error: string; message: string }
|
|
export interface Account { id: string; organisation_id: string; name: string; display_name: string; role: OrgRole }
|
|
export interface TokenResponse { access_token: string; expires_in: number; refresh_token: string; account: Account }
|
|
export interface ServerInfo { name: string; version: string; protocol: number; set_up: boolean }
|
|
export interface Space { id: string; name: string; role: SpaceRole; created_at: string }
|
|
export interface Member { account_id: string; name: string; display_name: string; role: SpaceRole }
|
|
export interface Invite { token: string; url: string; expires_at: string }
|
|
export interface JoinResponse { space: Space }
|
|
export interface Version {
|
|
id: number;
|
|
major: number;
|
|
minor: number;
|
|
kind: VersionKind;
|
|
name: string | null;
|
|
created_by: string | null;
|
|
created_at: string;
|
|
restored_from: number | null;
|
|
}
|
|
export interface VersionFiles { version: Version; files: { path: string; text: string }[] }
|
|
|
|
/** The contents of `.archify-sync`. */
|
|
export interface Link {
|
|
server: string;
|
|
space: string;
|
|
name?: string;
|
|
}
|
|
|
|
export function parseLink(text: string): Link | undefined {
|
|
try {
|
|
const value = JSON.parse(text) as Partial<Link>;
|
|
if (typeof value.server === 'string' && typeof value.space === 'string' && /^[0-9a-f-]{36}$/i.test(value.space)) {
|
|
return { server: value.server.replace(/\/+$/, ''), space: value.space, name: typeof value.name === 'string' ? value.name : undefined };
|
|
}
|
|
} catch {
|
|
// not a link
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
export function formatLink(link: Link): string {
|
|
return `${JSON.stringify({ server: link.server, space: link.space, name: link.name }, null, 2)}\n`;
|
|
}
|
|
|
|
export function versionLabel(v: Version): string {
|
|
return `${v.major}.${v.minor}`;
|
|
}
|