Add sync API to plugin SDK
This commit is contained in:
parent
0cbab61826
commit
cdc0b373d8
|
|
@ -21,6 +21,27 @@ export interface PluginEvent<TPayload = Record<string, unknown>> {
|
||||||
payload: TPayload;
|
payload: TPayload;
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
}
|
}
|
||||||
|
export interface SyncStatus {
|
||||||
|
configured: boolean;
|
||||||
|
serverUrl: string;
|
||||||
|
deviceId: string;
|
||||||
|
deviceName: string;
|
||||||
|
connected: boolean;
|
||||||
|
revoked: boolean;
|
||||||
|
tokenStored: boolean;
|
||||||
|
unpushedOps: number;
|
||||||
|
lastSyncAt: string;
|
||||||
|
syncInterval: number;
|
||||||
|
lastError: string;
|
||||||
|
statusLabel: string;
|
||||||
|
}
|
||||||
|
export interface SyncNowResult {
|
||||||
|
pushed: number;
|
||||||
|
pulled: number;
|
||||||
|
serverSequence: number;
|
||||||
|
conflicts?: unknown[];
|
||||||
|
applyErrors?: string[];
|
||||||
|
}
|
||||||
export interface VerstakPluginAPI {
|
export interface VerstakPluginAPI {
|
||||||
readonly pluginId: string;
|
readonly pluginId: string;
|
||||||
settings: {
|
settings: {
|
||||||
|
|
@ -65,6 +86,14 @@ export interface VerstakPluginAPI {
|
||||||
openResource(request: OpenResourceRequest): Promise<OpenResourceResult>;
|
openResource(request: OpenResourceRequest): Promise<OpenResourceResult>;
|
||||||
editResource(request: OpenResourceRequest): Promise<OpenResourceResult>;
|
editResource(request: OpenResourceRequest): Promise<OpenResourceResult>;
|
||||||
};
|
};
|
||||||
|
sync: {
|
||||||
|
status(): Promise<SyncStatus>;
|
||||||
|
configure(serverUrl: string, username: string, password: string): Promise<void>;
|
||||||
|
disconnect(): Promise<void>;
|
||||||
|
testConnection(serverUrl: string, username: string, password: string): Promise<void>;
|
||||||
|
setInterval(minutes: number): Promise<void>;
|
||||||
|
now(): Promise<SyncNowResult>;
|
||||||
|
};
|
||||||
dispose?: () => void;
|
dispose?: () => void;
|
||||||
}
|
}
|
||||||
export declare function createPluginAPI(_pluginId: string): VerstakPluginAPI;
|
export declare function createPluginAPI(_pluginId: string): VerstakPluginAPI;
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"plugin-api.d.ts","sourceRoot":"","sources":["../src/plugin-api.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EACT,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACxD,MAAM,MAAM,oBAAoB,GAAG,CACjC,IAAI,EAAE,iBAAiB,EACvB,WAAW,EAAE,wBAAwB,KAClC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAChC,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,QAAQ,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,QAAQ,EAAE;QACR,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;QAChC,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QACvD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;QAC5D,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACnD,CAAC;IAEF,YAAY,EAAE;QACZ,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1C,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;YAAE,SAAS,EAAE,OAAO,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC5G,IAAI,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;KACpC,CAAC;IAEF,QAAQ,EAAE;QACR,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QACjF,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;KACpF,CAAC;IAEF,MAAM,EAAE;QACN,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7E,SAAS,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,KAAK,IAAI,GAC9C,OAAO,CAAC,WAAW,CAAC,CAAC;KACzB,CAAC;IAEF,KAAK,EAAE;QACL;;;;WAIG;QACH,IAAI,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QACjD,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;QACtD,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAChD,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5F,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,gBAAgB,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACjG,KAAK,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;KACnD,CAAC;IAEF,SAAS,EAAE;QACT,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;QACxE,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;KACzE,CAAC;IAEF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAEnE"}
|
{"version":3,"file":"plugin-api.d.ts","sourceRoot":"","sources":["../src/plugin-api.ts"],"names":[],"mappings":"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"}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"plugin-api.js","sourceRoot":"","sources":["../src/plugin-api.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,8EAA8E;AAC9E,gDAAgD;AA+FhD,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;AACtF,CAAC"}
|
{"version":3,"file":"plugin-api.js","sourceRoot":"","sources":["../src/plugin-api.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,8EAA8E;AAC9E,gDAAgD;AA+HhD,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;AACtF,CAAC"}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAetF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CASnF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,SAAgB,GAAG,gBAAgB,CAsL9E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAgCxF;AAGD,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,EAAE,EAAE,CAAC"}
|
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAetF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CASnF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,SAAgB,GAAG,gBAAgB,CA2M9E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAgCxF;AAGD,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,EAAE,EAAE,CAAC"}
|
||||||
|
|
@ -8,7 +8,7 @@ export function createTestManifest(overrides) {
|
||||||
id: 'test.plugin',
|
id: 'test.plugin',
|
||||||
name: 'Test Plugin',
|
name: 'Test Plugin',
|
||||||
version: '0.1.0',
|
version: '0.1.0',
|
||||||
apiVersion: '1',
|
apiVersion: '0.1.0',
|
||||||
description: 'A test plugin for platform verification',
|
description: 'A test plugin for platform verification',
|
||||||
source: 'local',
|
source: 'local',
|
||||||
provides: ['test.capability'],
|
provides: ['test.capability'],
|
||||||
|
|
@ -229,6 +229,27 @@ export function createMockPluginAPI(pluginId = 'test.plugin') {
|
||||||
request: { ...request, mode: 'edit' },
|
request: { ...request, mode: 'edit' },
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
|
sync: {
|
||||||
|
status: vi.fn(async () => ({
|
||||||
|
configured: false,
|
||||||
|
serverUrl: '',
|
||||||
|
deviceId: '',
|
||||||
|
deviceName: '',
|
||||||
|
connected: false,
|
||||||
|
revoked: false,
|
||||||
|
tokenStored: false,
|
||||||
|
unpushedOps: 0,
|
||||||
|
lastSyncAt: '',
|
||||||
|
syncInterval: 0,
|
||||||
|
lastError: '',
|
||||||
|
statusLabel: 'disabled',
|
||||||
|
})),
|
||||||
|
configure: vi.fn(async () => { }),
|
||||||
|
disconnect: vi.fn(async () => { }),
|
||||||
|
testConnection: vi.fn(async () => { }),
|
||||||
|
setInterval: vi.fn(async () => { }),
|
||||||
|
now: vi.fn(async () => ({ pushed: 0, pulled: 0, serverSequence: 0 })),
|
||||||
|
},
|
||||||
dispose: vi.fn(),
|
dispose: vi.fn(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -36,7 +36,7 @@
|
||||||
"apiVersion": {
|
"apiVersion": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Verstak Platform API version this plugin targets",
|
"description": "Verstak Platform API version this plugin targets",
|
||||||
"pattern": "^\\d+$"
|
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.]+)?$"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { describe, expect, test } from 'vitest';
|
import { describe, expect, test } from 'vitest';
|
||||||
|
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
||||||
import manifestSchema from '../schemas/manifest.json';
|
import manifestSchema from '../schemas/manifest.json';
|
||||||
import type { OpenResourceRequest, PluginManifest } from './types';
|
import type { OpenResourceRequest, PluginManifest } from './types';
|
||||||
import { createMockPluginAPI } from './test-utils';
|
import { createMockPluginAPI } from './test-utils';
|
||||||
|
|
@ -24,6 +25,9 @@ describe('VerstakPluginAPI contract', () => {
|
||||||
expect(typeof api.files.trash).toBe('function');
|
expect(typeof api.files.trash).toBe('function');
|
||||||
expect(typeof api.workbench.openResource).toBe('function');
|
expect(typeof api.workbench.openResource).toBe('function');
|
||||||
expect(typeof api.workbench.editResource).toBe('function');
|
expect(typeof api.workbench.editResource).toBe('function');
|
||||||
|
expect(typeof api.sync.status).toBe('function');
|
||||||
|
expect(typeof api.sync.configure).toBe('function');
|
||||||
|
expect(typeof api.sync.now).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('manifest schema accepts files permissions used by platform-test', () => {
|
test('manifest schema accepts files permissions used by platform-test', () => {
|
||||||
|
|
@ -35,13 +39,46 @@ describe('VerstakPluginAPI contract', () => {
|
||||||
expect(permissionEnum).toContain('workbench.open');
|
expect(permissionEnum).toContain('workbench.open');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('official plugin manifests comply with SDK apiVersion and permission schema', () => {
|
||||||
|
const pluginsDir = new URL('../../verstak-official-plugins/plugins/', import.meta.url);
|
||||||
|
if (!existsSync(pluginsDir)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiVersionPattern = new RegExp((manifestSchema as any).properties.apiVersion.pattern);
|
||||||
|
const permissionEnum = ((manifestSchema as any).properties.permissions.items.enum || []) as string[];
|
||||||
|
const problems: string[] = [];
|
||||||
|
|
||||||
|
for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
|
||||||
|
if (!entry.isDirectory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const manifestPath = new URL(`${entry.name}/plugin.json`, pluginsDir);
|
||||||
|
if (!existsSync(manifestPath)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as PluginManifest;
|
||||||
|
if (!apiVersionPattern.test(manifest.apiVersion)) {
|
||||||
|
problems.push(`${manifest.id}: apiVersion ${manifest.apiVersion} does not match SDK schema`);
|
||||||
|
}
|
||||||
|
for (const permission of manifest.permissions) {
|
||||||
|
if (!permissionEnum.includes(permission)) {
|
||||||
|
problems.push(`${manifest.id}: permission ${permission} is not in SDK schema`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(problems).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
test('manifest types accept open provider contributions', () => {
|
test('manifest types accept open provider contributions', () => {
|
||||||
const manifest: PluginManifest = {
|
const manifest: PluginManifest = {
|
||||||
schemaVersion: 1,
|
schemaVersion: 1,
|
||||||
id: 'verstak.default-editor',
|
id: 'verstak.default-editor',
|
||||||
name: 'Default Editor',
|
name: 'Default Editor',
|
||||||
version: '0.1.0',
|
version: '0.1.0',
|
||||||
apiVersion: '1',
|
apiVersion: '0.1.0',
|
||||||
provides: ['editor.text', 'editor.text.markdown'],
|
provides: ['editor.text', 'editor.text.markdown'],
|
||||||
permissions: ['ui.register', 'files.read', 'files.write', 'workbench.open'],
|
permissions: ['ui.register', 'files.read', 'files.write', 'workbench.open'],
|
||||||
contributes: {
|
contributes: {
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,29 @@ export interface PluginEvent<TPayload = Record<string, unknown>> {
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SyncStatus {
|
||||||
|
configured: boolean;
|
||||||
|
serverUrl: string;
|
||||||
|
deviceId: string;
|
||||||
|
deviceName: string;
|
||||||
|
connected: boolean;
|
||||||
|
revoked: boolean;
|
||||||
|
tokenStored: boolean;
|
||||||
|
unpushedOps: number;
|
||||||
|
lastSyncAt: string;
|
||||||
|
syncInterval: number;
|
||||||
|
lastError: string;
|
||||||
|
statusLabel: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SyncNowResult {
|
||||||
|
pushed: number;
|
||||||
|
pulled: number;
|
||||||
|
serverSequence: number;
|
||||||
|
conflicts?: unknown[];
|
||||||
|
applyErrors?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface VerstakPluginAPI {
|
export interface VerstakPluginAPI {
|
||||||
readonly pluginId: string;
|
readonly pluginId: string;
|
||||||
|
|
||||||
|
|
@ -95,6 +118,15 @@ export interface VerstakPluginAPI {
|
||||||
editResource(request: OpenResourceRequest): Promise<OpenResourceResult>;
|
editResource(request: OpenResourceRequest): Promise<OpenResourceResult>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sync: {
|
||||||
|
status(): Promise<SyncStatus>;
|
||||||
|
configure(serverUrl: string, username: string, password: string): Promise<void>;
|
||||||
|
disconnect(): Promise<void>;
|
||||||
|
testConnection(serverUrl: string, username: string, password: string): Promise<void>;
|
||||||
|
setInterval(minutes: number): Promise<void>;
|
||||||
|
now(): Promise<SyncNowResult>;
|
||||||
|
};
|
||||||
|
|
||||||
dispose?: () => void;
|
dispose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export function createTestManifest(overrides?: Partial<PluginManifest>): PluginM
|
||||||
id: 'test.plugin',
|
id: 'test.plugin',
|
||||||
name: 'Test Plugin',
|
name: 'Test Plugin',
|
||||||
version: '0.1.0',
|
version: '0.1.0',
|
||||||
apiVersion: '1',
|
apiVersion: '0.1.0',
|
||||||
description: 'A test plugin for platform verification',
|
description: 'A test plugin for platform verification',
|
||||||
source: 'local',
|
source: 'local',
|
||||||
provides: ['test.capability'],
|
provides: ['test.capability'],
|
||||||
|
|
@ -220,6 +220,27 @@ export function createMockPluginAPI(pluginId = 'test.plugin'): VerstakPluginAPI
|
||||||
request: { ...request, mode: 'edit' as const },
|
request: { ...request, mode: 'edit' as const },
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
|
sync: {
|
||||||
|
status: vi.fn(async () => ({
|
||||||
|
configured: false,
|
||||||
|
serverUrl: '',
|
||||||
|
deviceId: '',
|
||||||
|
deviceName: '',
|
||||||
|
connected: false,
|
||||||
|
revoked: false,
|
||||||
|
tokenStored: false,
|
||||||
|
unpushedOps: 0,
|
||||||
|
lastSyncAt: '',
|
||||||
|
syncInterval: 0,
|
||||||
|
lastError: '',
|
||||||
|
statusLabel: 'disabled',
|
||||||
|
})),
|
||||||
|
configure: vi.fn(async () => {}),
|
||||||
|
disconnect: vi.fn(async () => {}),
|
||||||
|
testConnection: vi.fn(async () => {}),
|
||||||
|
setInterval: vi.fn(async () => {}),
|
||||||
|
now: vi.fn(async () => ({ pushed: 0, pulled: 0, serverSequence: 0 })),
|
||||||
|
},
|
||||||
dispose: vi.fn(),
|
dispose: vi.fn(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue