mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-01 01:29:31 +08:00
feat(nbstore): improve nbstore (#9512)
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
import { type BlobRecord, BlobStorageBase, share } from '@affine/nbstore';
|
||||
|
||||
import { NativeDBConnection } from './db';
|
||||
|
||||
export class SqliteBlobStorage extends BlobStorageBase {
|
||||
override connection = share(
|
||||
new NativeDBConnection(this.peer, this.spaceType, this.spaceId)
|
||||
);
|
||||
|
||||
get db() {
|
||||
return this.connection.inner;
|
||||
}
|
||||
|
||||
override async get(key: string) {
|
||||
return this.db.getBlob(key);
|
||||
}
|
||||
|
||||
override async set(blob: BlobRecord) {
|
||||
await this.db.setBlob(blob);
|
||||
}
|
||||
|
||||
override async delete(key: string, permanently: boolean) {
|
||||
await this.db.deleteBlob(key, permanently);
|
||||
}
|
||||
|
||||
override async release() {
|
||||
await this.db.releaseBlobs();
|
||||
}
|
||||
|
||||
override async list() {
|
||||
return this.db.listBlobs();
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import { DocStorage as NativeDocStorage } from '@affine/native';
|
||||
import { AutoReconnectConnection, type SpaceType } from '@affine/nbstore';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
import { logger } from '../logger';
|
||||
import { getSpaceDBPath } from '../workspace/meta';
|
||||
|
||||
export class NativeDBConnection extends AutoReconnectConnection<NativeDocStorage> {
|
||||
constructor(
|
||||
private readonly peer: string,
|
||||
private readonly type: SpaceType,
|
||||
private readonly id: string
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async getDBPath() {
|
||||
return await getSpaceDBPath(this.peer, this.type, this.id);
|
||||
}
|
||||
|
||||
override get shareId(): string {
|
||||
return `sqlite:${this.peer}:${this.type}:${this.id}`;
|
||||
}
|
||||
|
||||
override async doConnect() {
|
||||
const dbPath = await this.getDBPath();
|
||||
await fs.ensureDir(path.dirname(dbPath));
|
||||
const conn = new NativeDocStorage(dbPath);
|
||||
await conn.connect();
|
||||
logger.info('[nbstore] connection established', this.shareId);
|
||||
return conn;
|
||||
}
|
||||
|
||||
override doDisconnect(conn: NativeDocStorage) {
|
||||
conn
|
||||
.close()
|
||||
.then(() => {
|
||||
logger.info('[nbstore] connection closed', this.shareId);
|
||||
})
|
||||
.catch(err => {
|
||||
logger.error('[nbstore] connection close failed', this.shareId, err);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
import {
|
||||
type DocClocks,
|
||||
type DocRecord,
|
||||
DocStorageBase,
|
||||
type DocUpdate,
|
||||
share,
|
||||
} from '@affine/nbstore';
|
||||
|
||||
import { NativeDBConnection } from './db';
|
||||
|
||||
export class SqliteDocStorage extends DocStorageBase {
|
||||
override connection = share(
|
||||
new NativeDBConnection(this.peer, this.spaceType, this.spaceId)
|
||||
);
|
||||
|
||||
get db() {
|
||||
return this.connection.inner;
|
||||
}
|
||||
|
||||
override async pushDocUpdate(update: DocUpdate) {
|
||||
const timestamp = await this.db.pushUpdate(update.docId, update.bin);
|
||||
|
||||
return { docId: update.docId, timestamp };
|
||||
}
|
||||
|
||||
override async deleteDoc(docId: string) {
|
||||
await this.db.deleteDoc(docId);
|
||||
}
|
||||
|
||||
override async getDocTimestamps(after?: Date) {
|
||||
const clocks = await this.db.getDocClocks(after);
|
||||
|
||||
return clocks.reduce((ret, cur) => {
|
||||
ret[cur.docId] = cur.timestamp;
|
||||
return ret;
|
||||
}, {} as DocClocks);
|
||||
}
|
||||
|
||||
override async getDocTimestamp(docId: string) {
|
||||
return this.db.getDocClock(docId);
|
||||
}
|
||||
|
||||
protected override async getDocSnapshot(docId: string) {
|
||||
const snapshot = await this.db.getDocSnapshot(docId);
|
||||
|
||||
if (!snapshot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
docId,
|
||||
bin: snapshot.data,
|
||||
timestamp: snapshot.timestamp,
|
||||
};
|
||||
}
|
||||
|
||||
protected override async setDocSnapshot(
|
||||
snapshot: DocRecord
|
||||
): Promise<boolean> {
|
||||
return this.db.setDocSnapshot({
|
||||
docId: snapshot.docId,
|
||||
data: Buffer.from(snapshot.bin),
|
||||
timestamp: new Date(snapshot.timestamp),
|
||||
});
|
||||
}
|
||||
|
||||
protected override async getDocUpdates(docId: string) {
|
||||
return this.db.getDocUpdates(docId).then(updates =>
|
||||
updates.map(update => ({
|
||||
docId,
|
||||
bin: update.data,
|
||||
timestamp: update.createdAt,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
protected override markUpdatesMerged(docId: string, updates: DocRecord[]) {
|
||||
return this.db.markUpdatesMerged(
|
||||
docId,
|
||||
updates.map(update => update.timestamp)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,128 +1,43 @@
|
||||
import {
|
||||
type BlobRecord,
|
||||
type DocClock,
|
||||
type DocUpdate,
|
||||
} from '@affine/nbstore';
|
||||
import path from 'node:path';
|
||||
|
||||
import { ensureStorage, getStorage } from './storage';
|
||||
import { DocStoragePool } from '@affine/native';
|
||||
import { parseUniversalId } from '@affine/nbstore';
|
||||
import type { NativeDBApis } from '@affine/nbstore/sqlite';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
export const nbstoreHandlers = {
|
||||
connect: async (id: string) => {
|
||||
await ensureStorage(id);
|
||||
},
|
||||
|
||||
close: async (id: string) => {
|
||||
const store = getStorage(id);
|
||||
|
||||
if (store) {
|
||||
store.disconnect();
|
||||
// The store may be shared with other tabs, so we don't delete it from cache
|
||||
// the underlying connection will handle the close correctly
|
||||
// STORE_CACHE.delete(`${spaceType}:${spaceId}`);
|
||||
}
|
||||
},
|
||||
|
||||
pushDocUpdate: async (id: string, update: DocUpdate) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('doc').pushDocUpdate(update);
|
||||
},
|
||||
|
||||
getDoc: async (id: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('doc').getDoc(docId);
|
||||
},
|
||||
|
||||
deleteDoc: async (id: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('doc').deleteDoc(docId);
|
||||
},
|
||||
|
||||
getDocTimestamps: async (id: string, after?: Date) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('doc').getDocTimestamps(after);
|
||||
},
|
||||
|
||||
getDocTimestamp: async (id: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('doc').getDocTimestamp(docId);
|
||||
},
|
||||
|
||||
setBlob: async (id: string, blob: BlobRecord) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('blob').set(blob);
|
||||
},
|
||||
|
||||
getBlob: async (id: string, key: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('blob').get(key);
|
||||
},
|
||||
|
||||
deleteBlob: async (id: string, key: string, permanently: boolean) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('blob').delete(key, permanently);
|
||||
},
|
||||
|
||||
listBlobs: async (id: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('blob').list();
|
||||
},
|
||||
|
||||
releaseBlobs: async (id: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('blob').release();
|
||||
},
|
||||
|
||||
getPeerRemoteClocks: async (id: string, peer: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerRemoteClocks(peer);
|
||||
},
|
||||
|
||||
getPeerRemoteClock: async (id: string, peer: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerRemoteClock(peer, docId);
|
||||
},
|
||||
|
||||
setPeerRemoteClock: async (id: string, peer: string, clock: DocClock) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').setPeerRemoteClock(peer, clock);
|
||||
},
|
||||
|
||||
getPeerPulledRemoteClocks: async (id: string, peer: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerPulledRemoteClocks(peer);
|
||||
},
|
||||
|
||||
getPeerPulledRemoteClock: async (id: string, peer: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerPulledRemoteClock(peer, docId);
|
||||
},
|
||||
|
||||
setPeerPulledRemoteClock: async (
|
||||
id: string,
|
||||
peer: string,
|
||||
clock: DocClock
|
||||
) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').setPeerPulledRemoteClock(peer, clock);
|
||||
},
|
||||
|
||||
getPeerPushedClocks: async (id: string, peer: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerPushedClocks(peer);
|
||||
},
|
||||
|
||||
getPeerPushedClock: async (id: string, peer: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerPushedClock(peer, docId);
|
||||
},
|
||||
|
||||
setPeerPushedClock: async (id: string, peer: string, clock: DocClock) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').setPeerPushedClock(peer, clock);
|
||||
},
|
||||
|
||||
clearClocks: async (id: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').clearClocks();
|
||||
import { getSpaceDBPath } from '../workspace/meta';
|
||||
|
||||
const POOL = new DocStoragePool();
|
||||
|
||||
export const nbstoreHandlers: NativeDBApis = {
|
||||
connect: async (universalId: string) => {
|
||||
const { peer, type, id } = parseUniversalId(universalId);
|
||||
const dbPath = await getSpaceDBPath(peer, type, id);
|
||||
await fs.ensureDir(path.dirname(dbPath));
|
||||
await POOL.connect(universalId, dbPath);
|
||||
},
|
||||
disconnect: POOL.disconnect.bind(POOL),
|
||||
pushUpdate: POOL.pushUpdate.bind(POOL),
|
||||
getDocSnapshot: POOL.getDocSnapshot.bind(POOL),
|
||||
setDocSnapshot: POOL.setDocSnapshot.bind(POOL),
|
||||
getDocUpdates: POOL.getDocUpdates.bind(POOL),
|
||||
markUpdatesMerged: POOL.markUpdatesMerged.bind(POOL),
|
||||
deleteDoc: POOL.deleteDoc.bind(POOL),
|
||||
getDocClocks: POOL.getDocClocks.bind(POOL),
|
||||
getDocClock: POOL.getDocClock.bind(POOL),
|
||||
getBlob: POOL.getBlob.bind(POOL),
|
||||
setBlob: POOL.setBlob.bind(POOL),
|
||||
deleteBlob: POOL.deleteBlob.bind(POOL),
|
||||
releaseBlobs: POOL.releaseBlobs.bind(POOL),
|
||||
listBlobs: POOL.listBlobs.bind(POOL),
|
||||
getPeerRemoteClocks: POOL.getPeerRemoteClocks.bind(POOL),
|
||||
getPeerRemoteClock: POOL.getPeerRemoteClock.bind(POOL),
|
||||
setPeerRemoteClock: POOL.setPeerRemoteClock.bind(POOL),
|
||||
getPeerPulledRemoteClocks: POOL.getPeerPulledRemoteClocks.bind(POOL),
|
||||
getPeerPulledRemoteClock: POOL.getPeerPulledRemoteClock.bind(POOL),
|
||||
setPeerPulledRemoteClock: POOL.setPeerPulledRemoteClock.bind(POOL),
|
||||
getPeerPushedClocks: POOL.getPeerPushedClocks.bind(POOL),
|
||||
getPeerPushedClock: POOL.getPeerPushedClock.bind(POOL),
|
||||
setPeerPushedClock: POOL.setPeerPushedClock.bind(POOL),
|
||||
clearClocks: POOL.clearClocks.bind(POOL),
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
export { nbstoreHandlers } from './handlers';
|
||||
export * from './storage';
|
||||
export { dbEvents as dbEventsV1, dbHandlers as dbHandlersV1 } from './v1';
|
||||
export { universalId } from '@affine/nbstore';
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
import { parseUniversalId, SpaceStorage } from '@affine/nbstore';
|
||||
import { applyUpdate, Doc as YDoc } from 'yjs';
|
||||
|
||||
import { logger } from '../logger';
|
||||
import { SqliteBlobStorage } from './blob';
|
||||
import { NativeDBConnection } from './db';
|
||||
import { SqliteDocStorage } from './doc';
|
||||
import { SqliteSyncStorage } from './sync';
|
||||
|
||||
export class SqliteSpaceStorage extends SpaceStorage {
|
||||
get connection() {
|
||||
const docStore = this.get('doc');
|
||||
|
||||
if (!docStore) {
|
||||
throw new Error('doc store not found');
|
||||
}
|
||||
|
||||
const connection = docStore.connection;
|
||||
|
||||
if (!(connection instanceof NativeDBConnection)) {
|
||||
throw new Error('doc store connection is not a Sqlite connection');
|
||||
}
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
async getDBPath() {
|
||||
return this.connection.getDBPath();
|
||||
}
|
||||
|
||||
async getWorkspaceName() {
|
||||
const docStore = this.tryGet('doc');
|
||||
|
||||
if (!docStore) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const doc = await docStore.getDoc(docStore.spaceId);
|
||||
if (!doc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const ydoc = new YDoc();
|
||||
applyUpdate(ydoc, doc.bin);
|
||||
return ydoc.getMap('meta').get('name') as string;
|
||||
}
|
||||
|
||||
async checkpoint() {
|
||||
await this.connection.inner.checkpoint();
|
||||
}
|
||||
}
|
||||
|
||||
const STORE_CACHE = new Map<string, SqliteSpaceStorage>();
|
||||
|
||||
process.on('beforeExit', () => {
|
||||
STORE_CACHE.forEach(store => {
|
||||
store.destroy().catch(err => {
|
||||
logger.error('[nbstore] destroy store failed', err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
export function getStorage(universalId: string) {
|
||||
return STORE_CACHE.get(universalId);
|
||||
}
|
||||
|
||||
export async function ensureStorage(universalId: string) {
|
||||
const { peer, type, id } = parseUniversalId(universalId);
|
||||
let store = STORE_CACHE.get(universalId);
|
||||
|
||||
if (!store) {
|
||||
const opts = {
|
||||
peer,
|
||||
type,
|
||||
id,
|
||||
};
|
||||
|
||||
store = new SqliteSpaceStorage([
|
||||
new SqliteDocStorage(opts),
|
||||
new SqliteBlobStorage(opts),
|
||||
new SqliteSyncStorage(opts),
|
||||
]);
|
||||
|
||||
store.connect();
|
||||
|
||||
await store.waitForConnected();
|
||||
|
||||
STORE_CACHE.set(universalId, store);
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
import {
|
||||
BasicSyncStorage,
|
||||
type DocClock,
|
||||
type DocClocks,
|
||||
share,
|
||||
} from '@affine/nbstore';
|
||||
|
||||
import { NativeDBConnection } from './db';
|
||||
|
||||
export class SqliteSyncStorage extends BasicSyncStorage {
|
||||
override connection = share(
|
||||
new NativeDBConnection(this.peer, this.spaceType, this.spaceId)
|
||||
);
|
||||
|
||||
get db() {
|
||||
return this.connection.inner;
|
||||
}
|
||||
|
||||
override async getPeerRemoteClocks(peer: string) {
|
||||
const records = await this.db.getPeerRemoteClocks(peer);
|
||||
return records.reduce((clocks, { docId, timestamp }) => {
|
||||
clocks[docId] = timestamp;
|
||||
return clocks;
|
||||
}, {} as DocClocks);
|
||||
}
|
||||
|
||||
override async getPeerRemoteClock(peer: string, docId: string) {
|
||||
return this.db.getPeerRemoteClock(peer, docId);
|
||||
}
|
||||
|
||||
override async setPeerRemoteClock(peer: string, clock: DocClock) {
|
||||
await this.db.setPeerRemoteClock(peer, clock.docId, clock.timestamp);
|
||||
}
|
||||
|
||||
override async getPeerPulledRemoteClock(peer: string, docId: string) {
|
||||
return this.db.getPeerPulledRemoteClock(peer, docId);
|
||||
}
|
||||
|
||||
override async getPeerPulledRemoteClocks(peer: string) {
|
||||
const records = await this.db.getPeerPulledRemoteClocks(peer);
|
||||
return records.reduce((clocks, { docId, timestamp }) => {
|
||||
clocks[docId] = timestamp;
|
||||
return clocks;
|
||||
}, {} as DocClocks);
|
||||
}
|
||||
|
||||
override async setPeerPulledRemoteClock(peer: string, clock: DocClock) {
|
||||
await this.db.setPeerPulledRemoteClock(peer, clock.docId, clock.timestamp);
|
||||
}
|
||||
|
||||
override async getPeerPushedClocks(peer: string) {
|
||||
const records = await this.db.getPeerPushedClocks(peer);
|
||||
return records.reduce((clocks, { docId, timestamp }) => {
|
||||
clocks[docId] = timestamp;
|
||||
return clocks;
|
||||
}, {} as DocClocks);
|
||||
}
|
||||
|
||||
override async getPeerPushedClock(peer: string, docId: string) {
|
||||
return this.db.getPeerPushedClock(peer, docId);
|
||||
}
|
||||
|
||||
override async setPeerPushedClock(peer: string, clock: DocClock) {
|
||||
await this.db.setPeerPushedClock(peer, clock.docId, clock.timestamp);
|
||||
}
|
||||
|
||||
override async clearClocks() {
|
||||
await this.db.clearClocks();
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
50A285D72D112A5E000D5A6D /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 50A285D62D112A5E000D5A6D /* Localizable.xcstrings */; };
|
||||
50A285D82D112A5E000D5A6D /* InfoPlist.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 50A285D52D112A5E000D5A6D /* InfoPlist.xcstrings */; };
|
||||
50A285DC2D112B24000D5A6D /* Intelligents in Frameworks */ = {isa = PBXBuildFile; productRef = 50A285DB2D112B24000D5A6D /* Intelligents */; };
|
||||
9D52FC432D26CDBF00105D0A /* JSValueContainerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52FC422D26CDB600105D0A /* JSValueContainerExt.swift */; };
|
||||
9D6A85332CCF6DA700DAB35F /* HashcashPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D6A85322CCF6DA700DAB35F /* HashcashPlugin.swift */; };
|
||||
9D90BE252CCB9876006677DB /* CookieManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D90BE172CCB9876006677DB /* CookieManager.swift */; };
|
||||
9D90BE262CCB9876006677DB /* CookiePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D90BE182CCB9876006677DB /* CookiePlugin.swift */; };
|
||||
@@ -23,8 +24,8 @@
|
||||
9D90BE2B2CCB9876006677DB /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 9D90BE1F2CCB9876006677DB /* config.xml */; };
|
||||
9D90BE2D2CCB9876006677DB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9D90BE222CCB9876006677DB /* Main.storyboard */; };
|
||||
9D90BE2E2CCB9876006677DB /* public in Resources */ = {isa = PBXBuildFile; fileRef = 9D90BE232CCB9876006677DB /* public */; };
|
||||
9DFCD1462D27D1D70028C92B /* libaffine_mobile_native.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DFCD1452D27D1D70028C92B /* libaffine_mobile_native.a */; };
|
||||
C4C413792CBE705D00337889 /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; };
|
||||
C4C97C6E2D0304D100BC2AD1 /* libaffine_mobile_native.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C4C97C6D2D0304D100BC2AD1 /* libaffine_mobile_native.a */; };
|
||||
C4C97C7C2D030BE000BC2AD1 /* affine_mobile_native.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C97C6F2D0307B700BC2AD1 /* affine_mobile_native.swift */; };
|
||||
C4C97C7D2D030BE000BC2AD1 /* affine_mobile_nativeFFI.h in Sources */ = {isa = PBXBuildFile; fileRef = C4C97C702D0307B700BC2AD1 /* affine_mobile_nativeFFI.h */; };
|
||||
C4C97C7E2D030BE000BC2AD1 /* affine_mobile_nativeFFI.modulemap in Sources */ = {isa = PBXBuildFile; fileRef = C4C97C712D0307B700BC2AD1 /* affine_mobile_nativeFFI.modulemap */; };
|
||||
@@ -39,6 +40,7 @@
|
||||
50802D5E2D112F7D00694021 /* Intelligents */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Intelligents; sourceTree = "<group>"; };
|
||||
50A285D52D112A5E000D5A6D /* InfoPlist.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = InfoPlist.xcstrings; sourceTree = "<group>"; };
|
||||
50A285D62D112A5E000D5A6D /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
|
||||
9D52FC422D26CDB600105D0A /* JSValueContainerExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSValueContainerExt.swift; sourceTree = "<group>"; };
|
||||
9D6A85322CCF6DA700DAB35F /* HashcashPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashcashPlugin.swift; sourceTree = "<group>"; };
|
||||
9D90BE172CCB9876006677DB /* CookieManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CookieManager.swift; sourceTree = "<group>"; };
|
||||
9D90BE182CCB9876006677DB /* CookiePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CookiePlugin.swift; sourceTree = "<group>"; };
|
||||
@@ -50,10 +52,10 @@
|
||||
9D90BE202CCB9876006677DB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9D90BE212CCB9876006677DB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
9D90BE232CCB9876006677DB /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
|
||||
9DFCD1452D27D1D70028C92B /* libaffine_mobile_native.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libaffine_mobile_native.a; sourceTree = "<group>"; };
|
||||
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C4C97C6B2D03027900BC2AD1 /* libaffine_mobile_native.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaffine_mobile_native.a; path = "../../../../../target/aarch64-apple-ios-sim/release/libaffine_mobile_native.a"; sourceTree = "<group>"; };
|
||||
C4C97C6D2D0304D100BC2AD1 /* libaffine_mobile_native.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libaffine_mobile_native.a; sourceTree = "<group>"; };
|
||||
C4C97C6B2D03027900BC2AD1 /* libaffine_mobile_native.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaffine_mobile_native.a; path = "../../../../../target/aarch64-apple-ios-sim/debug/libaffine_mobile_native.a"; sourceTree = "<group>"; };
|
||||
C4C97C6F2D0307B700BC2AD1 /* affine_mobile_native.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = affine_mobile_native.swift; sourceTree = "<group>"; };
|
||||
C4C97C702D0307B700BC2AD1 /* affine_mobile_nativeFFI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = affine_mobile_nativeFFI.h; sourceTree = "<group>"; };
|
||||
C4C97C712D0307B700BC2AD1 /* affine_mobile_nativeFFI.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = affine_mobile_nativeFFI.modulemap; sourceTree = "<group>"; };
|
||||
@@ -70,8 +72,8 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C4C97C6E2D0304D100BC2AD1 /* libaffine_mobile_native.a in Frameworks */,
|
||||
50A285DC2D112B24000D5A6D /* Intelligents in Frameworks */,
|
||||
9DFCD1462D27D1D70028C92B /* libaffine_mobile_native.a in Frameworks */,
|
||||
50802D612D112F8700694021 /* Intelligents in Frameworks */,
|
||||
C4C413792CBE705D00337889 /* Pods_App.framework in Frameworks */,
|
||||
);
|
||||
@@ -84,8 +86,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C4C97C6B2D03027900BC2AD1 /* libaffine_mobile_native.a */,
|
||||
C4C97C6D2D0304D100BC2AD1 /* libaffine_mobile_native.a */,
|
||||
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */,
|
||||
9DFCD1452D27D1D70028C92B /* libaffine_mobile_native.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -154,6 +156,7 @@
|
||||
9D90BE242CCB9876006677DB /* App */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9D52FC422D26CDB600105D0A /* JSValueContainerExt.swift */,
|
||||
9D90BE1A2CCB9876006677DB /* Plugins */,
|
||||
9D90BE1C2CCB9876006677DB /* AppDelegate.swift */,
|
||||
507513692D1924C600AD60C0 /* RootViewController.swift */,
|
||||
@@ -325,6 +328,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9D52FC432D26CDBF00105D0A /* JSValueContainerExt.swift in Sources */,
|
||||
5075136E2D1925BC00AD60C0 /* IntelligentsPlugin.swift in Sources */,
|
||||
5075136A2D1924C600AD60C0 /* RootViewController.swift in Sources */,
|
||||
C4C97C7C2D030BE000BC2AD1 /* affine_mobile_native.swift in Sources */,
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// JSValueContainerExt.swift
|
||||
// App
|
||||
//
|
||||
// Created by EYHN on 2025/1/2.
|
||||
//
|
||||
import Capacitor
|
||||
|
||||
enum RequestParamError: Error {
|
||||
case request(key: String)
|
||||
}
|
||||
|
||||
extension JSValueContainer {
|
||||
public func getStringEnsure(_ key: String) throws -> String {
|
||||
guard let str = self.getString(key) else {
|
||||
throw RequestParamError.request(key: key)
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
public func getIntEnsure(_ key: String) throws -> Int {
|
||||
guard let int = self.getInt(key) else {
|
||||
throw RequestParamError.request(key: key)
|
||||
}
|
||||
return int
|
||||
}
|
||||
|
||||
public func getDoubleEnsure(_ key: String) throws -> Double {
|
||||
guard let doub = self.getDouble(key) else {
|
||||
throw RequestParamError.request(key: key)
|
||||
}
|
||||
return doub
|
||||
}
|
||||
|
||||
public func getBoolEnsure(_ key: String) throws -> Bool {
|
||||
guard let bool = self.getBool(key) else {
|
||||
throw RequestParamError.request(key: key)
|
||||
}
|
||||
return bool
|
||||
}
|
||||
|
||||
public func getArrayEnsure(_ key: String) throws -> JSArray {
|
||||
guard let arr = self.getArray(key) else {
|
||||
throw RequestParamError.request(key: key)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
public func getArrayEnsure<T>(_ key: String, _ ofType: T.Type) throws -> [T] {
|
||||
guard let arr = self.getArray(key, ofType) else {
|
||||
throw RequestParamError.request(key: key)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
}
|
||||
@@ -3,400 +3,475 @@ import Foundation
|
||||
|
||||
@objc(NbStorePlugin)
|
||||
public class NbStorePlugin: CAPPlugin, CAPBridgedPlugin {
|
||||
private let docStoragePool: DocStoragePool = .init(noPointer: DocStoragePool.NoPointer())
|
||||
|
||||
public let identifier = "NbStorePlugin"
|
||||
public let jsName = "NbStoreDocStorage"
|
||||
public let pluginMethods: [CAPPluginMethod] = [
|
||||
CAPPluginMethod(name: "getSpaceDBPath", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "connect", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "close", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "isClosed", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "checkpoint", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "validate", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setSpaceId", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "pushUpdate", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getDocSnapshot", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setDocSnapshot", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getDocUpdates", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "markUpdatesMerged", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "deleteDoc", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getDocClocks", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getDocClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getBlob", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setBlob", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "deleteBlob", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "releaseBlobs", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "listBlobs", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getPeerRemoteClocks", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getPeerRemoteClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setPeerRemoteClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getPeerPulledRemoteClocks", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getPeerPulledRemoteClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setPeerPulledRemoteClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getPeerPushedClocks", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setPeerPushedClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "clearClocks", returnType: CAPPluginReturnPromise),
|
||||
]
|
||||
|
||||
@objc func getSpaceDBPath(_ call: CAPPluginCall) {
|
||||
let peer = call.getString("peer") ?? ""
|
||||
let spaceType = call.getString("spaceType") ?? ""
|
||||
let id = call.getString("id") ?? ""
|
||||
|
||||
do {
|
||||
let path = try getDbPath(peer: peer, spaceType: spaceType, id: id)
|
||||
call.resolve(["path": path])
|
||||
} catch {
|
||||
call.reject("Failed to get space DB path", nil, error)
|
||||
private let docStoragePool: DocStoragePool = newDocStoragePool()
|
||||
|
||||
public let identifier = "NbStorePlugin"
|
||||
public let jsName = "NbStoreDocStorage"
|
||||
public let pluginMethods: [CAPPluginMethod] = [
|
||||
CAPPluginMethod(name: "connect", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "disconnect", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setSpaceId", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "pushUpdate", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getDocSnapshot", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setDocSnapshot", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getDocUpdates", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "markUpdatesMerged", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "deleteDoc", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getDocClocks", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getDocClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getBlob", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setBlob", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "deleteBlob", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "releaseBlobs", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "listBlobs", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getPeerRemoteClocks", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getPeerRemoteClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setPeerRemoteClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getPeerPulledRemoteClocks", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getPeerPulledRemoteClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setPeerPulledRemoteClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getPeerPushedClocks", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "setPeerPushedClock", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "clearClocks", returnType: CAPPluginReturnPromise),
|
||||
]
|
||||
|
||||
@objc func connect(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let spaceId = try call.getStringEnsure("spaceId")
|
||||
let spaceType = try call.getStringEnsure("spaceType")
|
||||
let peer = try call.getStringEnsure("peer")
|
||||
guard let documentDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
|
||||
call.reject("Failed to get document file urls")
|
||||
return
|
||||
}
|
||||
let peerDir = documentDir.appending(path: "workspaces")
|
||||
.appending(path: spaceType)
|
||||
.appending(path:
|
||||
peer
|
||||
.replacing(#/[\/!@#$%^&*()+~`"':;,?<>|]/#, with: "_")
|
||||
.replacing(/_+/, with: "_")
|
||||
.replacing(/_+$/, with: ""))
|
||||
try FileManager.default.createDirectory(atPath: peerDir.path(), withIntermediateDirectories: true)
|
||||
let db = peerDir.appending(path: spaceId + ".db")
|
||||
try await docStoragePool.connect(universalId: id, path: db.path())
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to connect storage, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func connect(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
try? await docStoragePool.connect(universalId: id)
|
||||
}
|
||||
|
||||
@objc func disconnect(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
try await docStoragePool.disconnect(universalId: id)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to disconnect, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func close(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
try? await docStoragePool.close(universalId: id)
|
||||
}
|
||||
|
||||
@objc func setSpaceId(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let spaceId = try call.getStringEnsure("spaceId")
|
||||
try await docStoragePool.setSpaceId(universalId: id, spaceId: spaceId)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to set space id, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func isClosed(_ call: CAPPluginCall) {
|
||||
let id = call.getString("id") ?? ""
|
||||
call.resolve(["isClosed": docStoragePool.isClosed(universalId: id)])
|
||||
}
|
||||
|
||||
@objc func pushUpdate(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
let data = try call.getStringEnsure("data")
|
||||
let timestamp = try await docStoragePool.pushUpdate(universalId: id, docId: docId, update: data)
|
||||
call.resolve(["timestamp": timestamp])
|
||||
} catch {
|
||||
call.reject("Failed to push update, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func checkpoint(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
try? await docStoragePool.checkpoint(universalId: id)
|
||||
}
|
||||
|
||||
@objc func validate(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let validate = (try? await docStoragePool.validate(universalId: id)) ?? false
|
||||
call.resolve(["isValidate": validate])
|
||||
}
|
||||
|
||||
@objc func setSpaceId(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let spaceId = call.getString("spaceId") ?? ""
|
||||
do {
|
||||
try await docStoragePool.setSpaceId(universalId: id, spaceId: spaceId)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to set space id", nil, error)
|
||||
}
|
||||
|
||||
@objc func getDocSnapshot(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
|
||||
if let record = try await docStoragePool.getDocSnapshot(universalId: id, docId: docId) {
|
||||
call.resolve([
|
||||
"docId": record.docId,
|
||||
"bin": record.bin,
|
||||
"timestamp": record.timestamp,
|
||||
])
|
||||
} else {
|
||||
call.resolve()
|
||||
}
|
||||
} catch {
|
||||
call.reject("Failed to get doc snapshot, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func pushUpdate(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
let data = call.getString("data") ?? ""
|
||||
do {
|
||||
let timestamp = try await docStoragePool.pushUpdate(universalId: id, docId: docId, update: data)
|
||||
call.resolve(["timestamp": timestamp.timeIntervalSince1970])
|
||||
|
||||
} catch {
|
||||
call.reject("Failed to push update", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func setDocSnapshot(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
let bin = try call.getStringEnsure("bin")
|
||||
let timestamp = try call.getIntEnsure("timestamp")
|
||||
let success = try await docStoragePool.setDocSnapshot(
|
||||
universalId: id,
|
||||
snapshot: DocRecord(docId: docId, bin: bin, timestamp: Int64(timestamp))
|
||||
)
|
||||
call.resolve(["success": success])
|
||||
} catch {
|
||||
call.reject("Failed to set doc snapshot, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getDocSnapshot(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
do {
|
||||
if let record = try await docStoragePool.getDocSnapshot(universalId: id, docId: docId) {
|
||||
call.resolve([
|
||||
"docId": record.docId,
|
||||
"data": record.data,
|
||||
"timestamp": record.timestamp.timeIntervalSince1970,
|
||||
])
|
||||
} else {
|
||||
call.resolve()
|
||||
}
|
||||
} catch {
|
||||
call.reject("Failed to get doc snapshot", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getDocUpdates(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
let updates = try await docStoragePool.getDocUpdates(universalId: id, docId: docId)
|
||||
let mapped = updates.map { [
|
||||
"docId": $0.docId,
|
||||
"timestamp": $0.timestamp,
|
||||
"bin": $0.bin,
|
||||
] }
|
||||
call.resolve(["updates": mapped])
|
||||
} catch {
|
||||
call.reject("Failed to get doc updates, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func setDocSnapshot(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
let data = call.getString("data") ?? ""
|
||||
let timestamp = Date()
|
||||
do {
|
||||
let success = try await docStoragePool.setDocSnapshot(
|
||||
universalId: id,
|
||||
snapshot: DocRecord(docId: docId, data: data, timestamp: timestamp)
|
||||
)
|
||||
call.resolve(["success": success])
|
||||
} catch {
|
||||
call.reject("Failed to set doc snapshot", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func markUpdatesMerged(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
let times = try call.getArrayEnsure("timestamps", Int64.self)
|
||||
|
||||
let count = try await docStoragePool.markUpdatesMerged(universalId: id, docId: docId, updates: times)
|
||||
call.resolve(["count": count])
|
||||
} catch {
|
||||
call.reject("Failed to mark updates merged, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getDocUpdates(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
do {
|
||||
let updates = try await docStoragePool.getDocUpdates(universalId: id, docId: docId)
|
||||
let mapped = updates.map { [
|
||||
"docId": $0.docId,
|
||||
"createdAt": $0.createdAt.timeIntervalSince1970,
|
||||
"data": $0.data,
|
||||
] }
|
||||
call.resolve(["updates": mapped])
|
||||
} catch {
|
||||
call.reject("Failed to get doc updates", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func deleteDoc(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
|
||||
try await docStoragePool.deleteDoc(universalId: id, docId: docId)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to delete doc, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func markUpdatesMerged(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
let times = call.getArray("timestamps", Double.self) ?? []
|
||||
let dateArray = times.map { Date(timeIntervalSince1970: $0) }
|
||||
do {
|
||||
let count = try await docStoragePool.markUpdatesMerged(universalId: id, docId: docId, updates: dateArray)
|
||||
call.resolve(["count": count])
|
||||
} catch {
|
||||
call.reject("Failed to mark updates merged", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func deleteDoc(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
do {
|
||||
try await docStoragePool.deleteDoc(universalId: id, docId: docId)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to delete doc", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getDocClocks(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
}
|
||||
|
||||
@objc func getDocClocks(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let after = call.getInt("after")
|
||||
do {
|
||||
let docClocks = try await docStoragePool.getDocClocks(
|
||||
universalId: id,
|
||||
after: after != nil ? Date(timeIntervalSince1970: TimeInterval(after!)) : nil
|
||||
)
|
||||
let mapped = docClocks.map { [
|
||||
"docId": $0.docId,
|
||||
"timestamp": $0.timestamp.timeIntervalSince1970,
|
||||
] }
|
||||
call.resolve(["clocks": mapped])
|
||||
} catch {
|
||||
call.reject("Failed to get doc clocks", nil, error)
|
||||
}
|
||||
|
||||
let docClocks = try await docStoragePool.getDocClocks(
|
||||
universalId: id,
|
||||
after: after != nil ? Int64(after!) : nil
|
||||
)
|
||||
let mapped = docClocks.map { [
|
||||
"docId": $0.docId,
|
||||
"timestamp": $0.timestamp,
|
||||
] }
|
||||
call.resolve(["clocks": mapped])
|
||||
} catch {
|
||||
call.reject("Failed to get doc clocks, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getDocClock(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
do {
|
||||
if let docClock = try await docStoragePool.getDocClock(universalId: id, docId: docId) {
|
||||
call.resolve([
|
||||
"docId": docClock.docId,
|
||||
"timestamp": docClock.timestamp.timeIntervalSince1970,
|
||||
])
|
||||
} else {
|
||||
call.resolve()
|
||||
}
|
||||
} catch {
|
||||
call.reject("Failed to get doc clock for docId: \(docId)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getBlob(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let key = call.getString("key") ?? ""
|
||||
if let blob = try? await docStoragePool.getBlob(universalId: id, key: key) {
|
||||
call.resolve(["blob": blob])
|
||||
}
|
||||
|
||||
@objc func getDocClock(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
if let docClock = try await docStoragePool.getDocClock(universalId: id, docId: docId) {
|
||||
call.resolve([
|
||||
"docId": docClock.docId,
|
||||
"timestamp": docClock.timestamp,
|
||||
])
|
||||
} else {
|
||||
call.resolve()
|
||||
call.resolve()
|
||||
}
|
||||
} catch {
|
||||
call.reject("Failed to get doc clock, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func setBlob(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let key = call.getString("key") ?? ""
|
||||
let data = call.getString("data") ?? ""
|
||||
let mime = call.getString("mime") ?? ""
|
||||
try? await docStoragePool.setBlob(universalId: id, blob: SetBlob(key: key, data: data, mime: mime))
|
||||
}
|
||||
|
||||
@objc func getBlob(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let key = try call.getStringEnsure("key")
|
||||
if let blob = try await docStoragePool.getBlob(universalId: id, key: key) {
|
||||
call.resolve(["blob":[
|
||||
"key": blob.key,
|
||||
"data": blob.data,
|
||||
"mime": blob.mime,
|
||||
"size": blob.size,
|
||||
"createdAt": blob.createdAt
|
||||
]])
|
||||
} else {
|
||||
call.resolve()
|
||||
}
|
||||
} catch {
|
||||
call.reject("Failed to get blob, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func deleteBlob(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let key = call.getString("key") ?? ""
|
||||
}
|
||||
|
||||
@objc func setBlob(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let key = try call.getStringEnsure("key")
|
||||
let data = try call.getStringEnsure("data")
|
||||
let mime = try call.getStringEnsure("mime")
|
||||
try await docStoragePool.setBlob(universalId: id, blob: SetBlob(key: key, data: data, mime: mime))
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to set blob, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc func deleteBlob(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let key = try call.getStringEnsure("key")
|
||||
let permanently = call.getBool("permanently") ?? false
|
||||
try? await docStoragePool.deleteBlob(universalId: id, key: key, permanently: permanently)
|
||||
try await docStoragePool.deleteBlob(universalId: id, key: key, permanently: permanently)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to delete blob, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func releaseBlobs(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
try? await docStoragePool.releaseBlobs(universalId: id)
|
||||
}
|
||||
|
||||
@objc func releaseBlobs(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
try await docStoragePool.releaseBlobs(universalId: id)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to release blobs, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func listBlobs(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
if let blobs = try? await docStoragePool.listBlobs(universalId: id) {
|
||||
let mapped = blobs.map { [
|
||||
"key": $0.key,
|
||||
"size": $0.size,
|
||||
"mime": $0.mime,
|
||||
"createdAt": $0.createdAt.timeIntervalSince1970,
|
||||
] }
|
||||
call.resolve(["blobs": mapped])
|
||||
} else {
|
||||
call.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func listBlobs(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let blobs = try await docStoragePool.listBlobs(universalId: id)
|
||||
let mapped = blobs.map { [
|
||||
"key": $0.key,
|
||||
"size": $0.size,
|
||||
"mime": $0.mime,
|
||||
"createdAt": $0.createdAt,
|
||||
] }
|
||||
call.resolve(["blobs": mapped])
|
||||
} catch {
|
||||
call.reject("Failed to list blobs, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getPeerRemoteClocks(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let peer = call.getString("peer") ?? ""
|
||||
do {
|
||||
let clocks = try await docStoragePool.getPeerRemoteClocks(universalId: id, peer: peer)
|
||||
let mapped = clocks.map { [
|
||||
"docId": $0.docId,
|
||||
"timestamp": $0.timestamp.timeIntervalSince1970,
|
||||
] }
|
||||
call.resolve(["clocks": mapped])
|
||||
|
||||
} catch {
|
||||
call.reject("Failed to get peer remote clocks", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getPeerRemoteClocks(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let peer = try call.getStringEnsure("peer")
|
||||
|
||||
let clocks = try await docStoragePool.getPeerRemoteClocks(universalId: id, peer: peer)
|
||||
let mapped = clocks.map { [
|
||||
"docId": $0.docId,
|
||||
"timestamp": $0.timestamp,
|
||||
] }
|
||||
call.resolve(["clocks": mapped])
|
||||
} catch {
|
||||
call.reject("Failed to get peer remote clocks, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getPeerRemoteClock(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let peer = call.getString("peer") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
do {
|
||||
let clock = try await docStoragePool.getPeerRemoteClock(universalId: id, peer: peer, docId: docId)
|
||||
call.resolve([
|
||||
"docId": clock.docId,
|
||||
"timestamp": clock.timestamp.timeIntervalSince1970,
|
||||
])
|
||||
|
||||
} catch {
|
||||
call.reject("Failed to get peer remote clock", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getPeerRemoteClock(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let peer = try call.getStringEnsure("peer")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
|
||||
let clock = try await docStoragePool.getPeerRemoteClock(universalId: id, peer: peer, docId: docId)
|
||||
call.resolve([
|
||||
"docId": clock.docId,
|
||||
"timestamp": clock.timestamp,
|
||||
])
|
||||
|
||||
} catch {
|
||||
call.reject("Failed to get peer remote clock, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func setPeerRemoteClock(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let peer = call.getString("peer") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
let timestamp = call.getDouble("timestamp") ?? 0
|
||||
do {
|
||||
try await docStoragePool.setPeerRemoteClock(
|
||||
universalId: id,
|
||||
peer: peer,
|
||||
docId: docId,
|
||||
clock: Date(timeIntervalSince1970: timestamp)
|
||||
)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to set peer remote clock", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func setPeerRemoteClock(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let peer = try call.getStringEnsure("peer")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
let timestamp = try call.getIntEnsure("timestamp")
|
||||
try await docStoragePool.setPeerRemoteClock(
|
||||
universalId: id,
|
||||
peer: peer,
|
||||
docId: docId,
|
||||
clock: Int64(timestamp)
|
||||
)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to set peer remote clock, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getPeerPulledRemoteClocks(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let peer = call.getString("peer") ?? ""
|
||||
do {
|
||||
let clocks = try await docStoragePool.getPeerPulledRemoteClocks(universalId: id, peer: peer)
|
||||
let mapped = clocks.map { [
|
||||
"docId": $0.docId,
|
||||
"timestamp": $0.timestamp.timeIntervalSince1970,
|
||||
] }
|
||||
call.resolve(["clocks": mapped])
|
||||
|
||||
} catch {
|
||||
call.reject("Failed to get peer pulled remote clocks", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getPeerPulledRemoteClocks(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let peer = try call.getStringEnsure("peer")
|
||||
|
||||
let clocks = try await docStoragePool.getPeerPulledRemoteClocks(universalId: id, peer: peer)
|
||||
let mapped = clocks.map { [
|
||||
"docId": $0.docId,
|
||||
"timestamp": $0.timestamp,
|
||||
] }
|
||||
call.resolve(["clocks": mapped])
|
||||
} catch {
|
||||
call.reject("Failed to get peer pulled remote clocks, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getPeerPulledRemoteClock(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let peer = call.getString("peer") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
do {
|
||||
let clock = try await docStoragePool.getPeerPulledRemoteClock(universalId: id, peer: peer, docId: docId)
|
||||
call.resolve([
|
||||
"docId": clock.docId,
|
||||
"timestamp": clock.timestamp.timeIntervalSince1970,
|
||||
])
|
||||
|
||||
} catch {
|
||||
call.reject("Failed to get peer pulled remote clock", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getPeerPulledRemoteClock(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let peer = try call.getStringEnsure("peer")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
|
||||
let clock = try await docStoragePool.getPeerPulledRemoteClock(universalId: id, peer: peer, docId: docId)
|
||||
call.resolve([
|
||||
"docId": clock.docId,
|
||||
"timestamp": clock.timestamp,
|
||||
])
|
||||
|
||||
} catch {
|
||||
call.reject("Failed to get peer pulled remote clock, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func setPeerPulledRemoteClock(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let peer = call.getString("peer") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
let timestamp = call.getDouble("timestamp") ?? 0
|
||||
do {
|
||||
try await docStoragePool.setPeerPulledRemoteClock(
|
||||
universalId: id,
|
||||
peer: peer,
|
||||
docId: docId,
|
||||
clock: Date(timeIntervalSince1970: timestamp)
|
||||
)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to set peer pulled remote clock", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func setPeerPulledRemoteClock(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let peer = try call.getStringEnsure("peer")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
let timestamp = try call.getIntEnsure("timestamp")
|
||||
|
||||
try await docStoragePool.setPeerPulledRemoteClock(
|
||||
universalId: id,
|
||||
peer: peer,
|
||||
docId: docId,
|
||||
clock: Int64(timestamp)
|
||||
)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to set peer pulled remote clock, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getPeerPushedClocks(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let peer = call.getString("peer") ?? ""
|
||||
do {
|
||||
let clocks = try await docStoragePool.getPeerPushedClocks(universalId: id, peer: peer)
|
||||
let mapped = clocks.map { [
|
||||
"docId": $0.docId,
|
||||
"timestamp": $0.timestamp.timeIntervalSince1970,
|
||||
] }
|
||||
call.resolve(["clocks": mapped])
|
||||
|
||||
} catch {
|
||||
call.reject("Failed to get peer pushed clocks", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getPeerPushedClocks(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let peer = try call.getStringEnsure("peer")
|
||||
let clocks = try await docStoragePool.getPeerPushedClocks(universalId: id, peer: peer)
|
||||
let mapped = clocks.map { [
|
||||
"docId": $0.docId,
|
||||
"timestamp": $0.timestamp,
|
||||
] }
|
||||
call.resolve(["clocks": mapped])
|
||||
|
||||
} catch {
|
||||
call.reject("Failed to get peer pushed clocks, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func setPeerPushedClock(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
let peer = call.getString("peer") ?? ""
|
||||
let docId = call.getString("docId") ?? ""
|
||||
let timestamp = call.getDouble("timestamp") ?? 0
|
||||
do {
|
||||
try await docStoragePool.setPeerPushedClock(
|
||||
universalId: id,
|
||||
peer: peer,
|
||||
docId: docId,
|
||||
clock: Date(timeIntervalSince1970: timestamp)
|
||||
)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to set peer pushed clock", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func setPeerPushedClock(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
let peer = try call.getStringEnsure("peer")
|
||||
let docId = try call.getStringEnsure("docId")
|
||||
let timestamp = try call.getIntEnsure("timestamp")
|
||||
|
||||
try await docStoragePool.setPeerPushedClock(
|
||||
universalId: id,
|
||||
peer: peer,
|
||||
docId: docId,
|
||||
clock: Int64(timestamp)
|
||||
)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to set peer pushed clock, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func clearClocks(_ call: CAPPluginCall) async {
|
||||
let id = call.getString("id") ?? ""
|
||||
do {
|
||||
try await docStoragePool.clearClocks(universalId: id)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to clear clocks", nil, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func clearClocks(_ call: CAPPluginCall) {
|
||||
Task {
|
||||
do {
|
||||
let id = try call.getStringEnsure("id")
|
||||
try await docStoragePool.clearClocks(universalId: id)
|
||||
call.resolve()
|
||||
} catch {
|
||||
call.reject("Failed to clear clocks, \(error)", nil, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,65 +492,25 @@ private struct FfiConverterString: FfiConverter {
|
||||
}
|
||||
}
|
||||
|
||||
#if swift(>=5.8)
|
||||
@_documentation(visibility: private)
|
||||
#endif
|
||||
private struct FfiConverterTimestamp: FfiConverterRustBuffer {
|
||||
typealias SwiftType = Date
|
||||
|
||||
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Date {
|
||||
let seconds: Int64 = try readInt(&buf)
|
||||
let nanoseconds: UInt32 = try readInt(&buf)
|
||||
if seconds >= 0 {
|
||||
let delta = Double(seconds) + (Double(nanoseconds) / 1.0e9)
|
||||
return Date(timeIntervalSince1970: delta)
|
||||
} else {
|
||||
let delta = Double(seconds) - (Double(nanoseconds) / 1.0e9)
|
||||
return Date(timeIntervalSince1970: delta)
|
||||
}
|
||||
}
|
||||
|
||||
public static func write(_ value: Date, into buf: inout [UInt8]) {
|
||||
var delta = value.timeIntervalSince1970
|
||||
var sign: Int64 = 1
|
||||
if delta < 0 {
|
||||
// The nanoseconds portion of the epoch offset must always be
|
||||
// positive, to simplify the calculation we will use the absolute
|
||||
// value of the offset.
|
||||
sign = -1
|
||||
delta = -delta
|
||||
}
|
||||
if delta.rounded(.down) > Double(Int64.max) {
|
||||
fatalError("Timestamp overflow, exceeds max bounds supported by Uniffi")
|
||||
}
|
||||
let seconds = Int64(delta)
|
||||
let nanoseconds = UInt32((delta - Double(seconds)) * 1.0e9)
|
||||
writeInt(&buf, sign * seconds)
|
||||
writeInt(&buf, nanoseconds)
|
||||
}
|
||||
}
|
||||
|
||||
public protocol DocStoragePoolProtocol: AnyObject {
|
||||
func checkpoint(universalId: String) async throws
|
||||
|
||||
func clearClocks(universalId: String) async throws
|
||||
|
||||
func close(universalId: String) async throws
|
||||
|
||||
/**
|
||||
* Initialize the database and run migrations.
|
||||
*/
|
||||
func connect(universalId: String) async throws
|
||||
func connect(universalId: String, path: String) async throws
|
||||
|
||||
func deleteBlob(universalId: String, key: String, permanently: Bool) async throws
|
||||
|
||||
func deleteDoc(universalId: String, docId: String) async throws
|
||||
|
||||
func disconnect(universalId: String) async throws
|
||||
|
||||
func getBlob(universalId: String, key: String) async throws -> Blob?
|
||||
|
||||
func getDocClock(universalId: String, docId: String) async throws -> DocClock?
|
||||
|
||||
func getDocClocks(universalId: String, after: Date?) async throws -> [DocClock]
|
||||
func getDocClocks(universalId: String, after: Int64?) async throws -> [DocClock]
|
||||
|
||||
func getDocSnapshot(universalId: String, docId: String) async throws -> DocRecord?
|
||||
|
||||
@@ -566,13 +526,11 @@ public protocol DocStoragePoolProtocol: AnyObject {
|
||||
|
||||
func getPeerRemoteClocks(universalId: String, peer: String) async throws -> [DocClock]
|
||||
|
||||
func isClosed(universalId: String) -> Bool
|
||||
|
||||
func listBlobs(universalId: String) async throws -> [ListedBlob]
|
||||
|
||||
func markUpdatesMerged(universalId: String, docId: String, updates: [Date]) async throws -> UInt32
|
||||
func markUpdatesMerged(universalId: String, docId: String, updates: [Int64]) async throws -> UInt32
|
||||
|
||||
func pushUpdate(universalId: String, docId: String, update: String) async throws -> Date
|
||||
func pushUpdate(universalId: String, docId: String, update: String) async throws -> Int64
|
||||
|
||||
func releaseBlobs(universalId: String) async throws
|
||||
|
||||
@@ -580,15 +538,13 @@ public protocol DocStoragePoolProtocol: AnyObject {
|
||||
|
||||
func setDocSnapshot(universalId: String, snapshot: DocRecord) async throws -> Bool
|
||||
|
||||
func setPeerPulledRemoteClock(universalId: String, peer: String, docId: String, clock: Date) async throws
|
||||
func setPeerPulledRemoteClock(universalId: String, peer: String, docId: String, clock: Int64) async throws
|
||||
|
||||
func setPeerPushedClock(universalId: String, peer: String, docId: String, clock: Date) async throws
|
||||
func setPeerPushedClock(universalId: String, peer: String, docId: String, clock: Int64) async throws
|
||||
|
||||
func setPeerRemoteClock(universalId: String, peer: String, docId: String, clock: Date) async throws
|
||||
func setPeerRemoteClock(universalId: String, peer: String, docId: String, clock: Int64) async throws
|
||||
|
||||
func setSpaceId(universalId: String, spaceId: String) async throws
|
||||
|
||||
func validate(universalId: String) async throws -> Bool
|
||||
}
|
||||
|
||||
open class DocStoragePool:
|
||||
@@ -640,23 +596,6 @@ open class DocStoragePool:
|
||||
try! rustCall { uniffi_affine_mobile_native_fn_free_docstoragepool(pointer, $0) }
|
||||
}
|
||||
|
||||
open func checkpoint(universalId: String) async throws {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
rustFutureFunc: {
|
||||
uniffi_affine_mobile_native_fn_method_docstoragepool_checkpoint(
|
||||
self.uniffiClonePointer(),
|
||||
FfiConverterString.lower(universalId)
|
||||
)
|
||||
},
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_void,
|
||||
completeFunc: ffi_affine_mobile_native_rust_future_complete_void,
|
||||
freeFunc: ffi_affine_mobile_native_rust_future_free_void,
|
||||
liftFunc: { $0 },
|
||||
errorHandler: FfiConverterTypeUniffiError.lift
|
||||
)
|
||||
}
|
||||
|
||||
open func clearClocks(universalId: String) async throws {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
@@ -674,33 +613,16 @@ open class DocStoragePool:
|
||||
)
|
||||
}
|
||||
|
||||
open func close(universalId: String) async throws {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
rustFutureFunc: {
|
||||
uniffi_affine_mobile_native_fn_method_docstoragepool_close(
|
||||
self.uniffiClonePointer(),
|
||||
FfiConverterString.lower(universalId)
|
||||
)
|
||||
},
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_void,
|
||||
completeFunc: ffi_affine_mobile_native_rust_future_complete_void,
|
||||
freeFunc: ffi_affine_mobile_native_rust_future_free_void,
|
||||
liftFunc: { $0 },
|
||||
errorHandler: FfiConverterTypeUniffiError.lift
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the database and run migrations.
|
||||
*/
|
||||
open func connect(universalId: String) async throws {
|
||||
open func connect(universalId: String, path: String) async throws {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
rustFutureFunc: {
|
||||
uniffi_affine_mobile_native_fn_method_docstoragepool_connect(
|
||||
self.uniffiClonePointer(),
|
||||
FfiConverterString.lower(universalId)
|
||||
FfiConverterString.lower(universalId), FfiConverterString.lower(path)
|
||||
)
|
||||
},
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_void,
|
||||
@@ -745,6 +667,23 @@ open class DocStoragePool:
|
||||
)
|
||||
}
|
||||
|
||||
open func disconnect(universalId: String) async throws {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
rustFutureFunc: {
|
||||
uniffi_affine_mobile_native_fn_method_docstoragepool_disconnect(
|
||||
self.uniffiClonePointer(),
|
||||
FfiConverterString.lower(universalId)
|
||||
)
|
||||
},
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_void,
|
||||
completeFunc: ffi_affine_mobile_native_rust_future_complete_void,
|
||||
freeFunc: ffi_affine_mobile_native_rust_future_free_void,
|
||||
liftFunc: { $0 },
|
||||
errorHandler: FfiConverterTypeUniffiError.lift
|
||||
)
|
||||
}
|
||||
|
||||
open func getBlob(universalId: String, key: String) async throws -> Blob? {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
@@ -779,13 +718,13 @@ open class DocStoragePool:
|
||||
)
|
||||
}
|
||||
|
||||
open func getDocClocks(universalId: String, after: Date?) async throws -> [DocClock] {
|
||||
open func getDocClocks(universalId: String, after: Int64?) async throws -> [DocClock] {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
rustFutureFunc: {
|
||||
uniffi_affine_mobile_native_fn_method_docstoragepool_get_doc_clocks(
|
||||
self.uniffiClonePointer(),
|
||||
FfiConverterString.lower(universalId), FfiConverterOptionTimestamp.lower(after)
|
||||
FfiConverterString.lower(universalId), FfiConverterOptionInt64.lower(after)
|
||||
)
|
||||
},
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer,
|
||||
@@ -915,13 +854,6 @@ open class DocStoragePool:
|
||||
)
|
||||
}
|
||||
|
||||
open func isClosed(universalId: String) -> Bool {
|
||||
return try! FfiConverterBool.lift(try! rustCall {
|
||||
uniffi_affine_mobile_native_fn_method_docstoragepool_is_closed(self.uniffiClonePointer(),
|
||||
FfiConverterString.lower(universalId), $0)
|
||||
})
|
||||
}
|
||||
|
||||
open func listBlobs(universalId: String) async throws -> [ListedBlob] {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
@@ -939,13 +871,13 @@ open class DocStoragePool:
|
||||
)
|
||||
}
|
||||
|
||||
open func markUpdatesMerged(universalId: String, docId: String, updates: [Date]) async throws -> UInt32 {
|
||||
open func markUpdatesMerged(universalId: String, docId: String, updates: [Int64]) async throws -> UInt32 {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
rustFutureFunc: {
|
||||
uniffi_affine_mobile_native_fn_method_docstoragepool_mark_updates_merged(
|
||||
self.uniffiClonePointer(),
|
||||
FfiConverterString.lower(universalId), FfiConverterString.lower(docId), FfiConverterSequenceTimestamp.lower(updates)
|
||||
FfiConverterString.lower(universalId), FfiConverterString.lower(docId), FfiConverterSequenceInt64.lower(updates)
|
||||
)
|
||||
},
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_u32,
|
||||
@@ -956,7 +888,7 @@ open class DocStoragePool:
|
||||
)
|
||||
}
|
||||
|
||||
open func pushUpdate(universalId: String, docId: String, update: String) async throws -> Date {
|
||||
open func pushUpdate(universalId: String, docId: String, update: String) async throws -> Int64 {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
rustFutureFunc: {
|
||||
@@ -965,10 +897,10 @@ open class DocStoragePool:
|
||||
FfiConverterString.lower(universalId), FfiConverterString.lower(docId), FfiConverterString.lower(update)
|
||||
)
|
||||
},
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer,
|
||||
completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer,
|
||||
freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer,
|
||||
liftFunc: FfiConverterTimestamp.lift,
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_i64,
|
||||
completeFunc: ffi_affine_mobile_native_rust_future_complete_i64,
|
||||
freeFunc: ffi_affine_mobile_native_rust_future_free_i64,
|
||||
liftFunc: FfiConverterInt64.lift,
|
||||
errorHandler: FfiConverterTypeUniffiError.lift
|
||||
)
|
||||
}
|
||||
@@ -1024,13 +956,13 @@ open class DocStoragePool:
|
||||
)
|
||||
}
|
||||
|
||||
open func setPeerPulledRemoteClock(universalId: String, peer: String, docId: String, clock: Date) async throws {
|
||||
open func setPeerPulledRemoteClock(universalId: String, peer: String, docId: String, clock: Int64) async throws {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
rustFutureFunc: {
|
||||
uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pulled_remote_clock(
|
||||
self.uniffiClonePointer(),
|
||||
FfiConverterString.lower(universalId), FfiConverterString.lower(peer), FfiConverterString.lower(docId), FfiConverterTimestamp.lower(clock)
|
||||
FfiConverterString.lower(universalId), FfiConverterString.lower(peer), FfiConverterString.lower(docId), FfiConverterInt64.lower(clock)
|
||||
)
|
||||
},
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_void,
|
||||
@@ -1041,13 +973,13 @@ open class DocStoragePool:
|
||||
)
|
||||
}
|
||||
|
||||
open func setPeerPushedClock(universalId: String, peer: String, docId: String, clock: Date) async throws {
|
||||
open func setPeerPushedClock(universalId: String, peer: String, docId: String, clock: Int64) async throws {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
rustFutureFunc: {
|
||||
uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pushed_clock(
|
||||
self.uniffiClonePointer(),
|
||||
FfiConverterString.lower(universalId), FfiConverterString.lower(peer), FfiConverterString.lower(docId), FfiConverterTimestamp.lower(clock)
|
||||
FfiConverterString.lower(universalId), FfiConverterString.lower(peer), FfiConverterString.lower(docId), FfiConverterInt64.lower(clock)
|
||||
)
|
||||
},
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_void,
|
||||
@@ -1058,13 +990,13 @@ open class DocStoragePool:
|
||||
)
|
||||
}
|
||||
|
||||
open func setPeerRemoteClock(universalId: String, peer: String, docId: String, clock: Date) async throws {
|
||||
open func setPeerRemoteClock(universalId: String, peer: String, docId: String, clock: Int64) async throws {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
rustFutureFunc: {
|
||||
uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_remote_clock(
|
||||
self.uniffiClonePointer(),
|
||||
FfiConverterString.lower(universalId), FfiConverterString.lower(peer), FfiConverterString.lower(docId), FfiConverterTimestamp.lower(clock)
|
||||
FfiConverterString.lower(universalId), FfiConverterString.lower(peer), FfiConverterString.lower(docId), FfiConverterInt64.lower(clock)
|
||||
)
|
||||
},
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_void,
|
||||
@@ -1091,23 +1023,6 @@ open class DocStoragePool:
|
||||
errorHandler: FfiConverterTypeUniffiError.lift
|
||||
)
|
||||
}
|
||||
|
||||
open func validate(universalId: String) async throws -> Bool {
|
||||
return
|
||||
try await uniffiRustCallAsync(
|
||||
rustFutureFunc: {
|
||||
uniffi_affine_mobile_native_fn_method_docstoragepool_validate(
|
||||
self.uniffiClonePointer(),
|
||||
FfiConverterString.lower(universalId)
|
||||
)
|
||||
},
|
||||
pollFunc: ffi_affine_mobile_native_rust_future_poll_i8,
|
||||
completeFunc: ffi_affine_mobile_native_rust_future_complete_i8,
|
||||
freeFunc: ffi_affine_mobile_native_rust_future_free_i8,
|
||||
liftFunc: FfiConverterBool.lift,
|
||||
errorHandler: FfiConverterTypeUniffiError.lift
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#if swift(>=5.8)
|
||||
@@ -1162,11 +1077,11 @@ public struct Blob {
|
||||
public var data: String
|
||||
public var mime: String
|
||||
public var size: Int64
|
||||
public var createdAt: Date
|
||||
public var createdAt: Int64
|
||||
|
||||
// Default memberwise initializers are never public by default, so we
|
||||
// declare one manually.
|
||||
public init(key: String, data: String, mime: String, size: Int64, createdAt: Date) {
|
||||
public init(key: String, data: String, mime: String, size: Int64, createdAt: Int64) {
|
||||
self.key = key
|
||||
self.data = data
|
||||
self.mime = mime
|
||||
@@ -1215,7 +1130,7 @@ public struct FfiConverterTypeBlob: FfiConverterRustBuffer {
|
||||
data: FfiConverterString.read(from: &buf),
|
||||
mime: FfiConverterString.read(from: &buf),
|
||||
size: FfiConverterInt64.read(from: &buf),
|
||||
createdAt: FfiConverterTimestamp.read(from: &buf)
|
||||
createdAt: FfiConverterInt64.read(from: &buf)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1224,7 +1139,7 @@ public struct FfiConverterTypeBlob: FfiConverterRustBuffer {
|
||||
FfiConverterString.write(value.data, into: &buf)
|
||||
FfiConverterString.write(value.mime, into: &buf)
|
||||
FfiConverterInt64.write(value.size, into: &buf)
|
||||
FfiConverterTimestamp.write(value.createdAt, into: &buf)
|
||||
FfiConverterInt64.write(value.createdAt, into: &buf)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1244,11 +1159,11 @@ public func FfiConverterTypeBlob_lower(_ value: Blob) -> RustBuffer {
|
||||
|
||||
public struct DocClock {
|
||||
public var docId: String
|
||||
public var timestamp: Date
|
||||
public var timestamp: Int64
|
||||
|
||||
// Default memberwise initializers are never public by default, so we
|
||||
// declare one manually.
|
||||
public init(docId: String, timestamp: Date) {
|
||||
public init(docId: String, timestamp: Int64) {
|
||||
self.docId = docId
|
||||
self.timestamp = timestamp
|
||||
}
|
||||
@@ -1279,13 +1194,13 @@ public struct FfiConverterTypeDocClock: FfiConverterRustBuffer {
|
||||
return
|
||||
try DocClock(
|
||||
docId: FfiConverterString.read(from: &buf),
|
||||
timestamp: FfiConverterTimestamp.read(from: &buf)
|
||||
timestamp: FfiConverterInt64.read(from: &buf)
|
||||
)
|
||||
}
|
||||
|
||||
public static func write(_ value: DocClock, into buf: inout [UInt8]) {
|
||||
FfiConverterString.write(value.docId, into: &buf)
|
||||
FfiConverterTimestamp.write(value.timestamp, into: &buf)
|
||||
FfiConverterInt64.write(value.timestamp, into: &buf)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1305,14 +1220,14 @@ public func FfiConverterTypeDocClock_lower(_ value: DocClock) -> RustBuffer {
|
||||
|
||||
public struct DocRecord {
|
||||
public var docId: String
|
||||
public var data: String
|
||||
public var timestamp: Date
|
||||
public var bin: String
|
||||
public var timestamp: Int64
|
||||
|
||||
// Default memberwise initializers are never public by default, so we
|
||||
// declare one manually.
|
||||
public init(docId: String, data: String, timestamp: Date) {
|
||||
public init(docId: String, bin: String, timestamp: Int64) {
|
||||
self.docId = docId
|
||||
self.data = data
|
||||
self.bin = bin
|
||||
self.timestamp = timestamp
|
||||
}
|
||||
}
|
||||
@@ -1322,7 +1237,7 @@ extension DocRecord: Equatable, Hashable {
|
||||
if lhs.docId != rhs.docId {
|
||||
return false
|
||||
}
|
||||
if lhs.data != rhs.data {
|
||||
if lhs.bin != rhs.bin {
|
||||
return false
|
||||
}
|
||||
if lhs.timestamp != rhs.timestamp {
|
||||
@@ -1333,7 +1248,7 @@ extension DocRecord: Equatable, Hashable {
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(docId)
|
||||
hasher.combine(data)
|
||||
hasher.combine(bin)
|
||||
hasher.combine(timestamp)
|
||||
}
|
||||
}
|
||||
@@ -1346,15 +1261,15 @@ public struct FfiConverterTypeDocRecord: FfiConverterRustBuffer {
|
||||
return
|
||||
try DocRecord(
|
||||
docId: FfiConverterString.read(from: &buf),
|
||||
data: FfiConverterString.read(from: &buf),
|
||||
timestamp: FfiConverterTimestamp.read(from: &buf)
|
||||
bin: FfiConverterString.read(from: &buf),
|
||||
timestamp: FfiConverterInt64.read(from: &buf)
|
||||
)
|
||||
}
|
||||
|
||||
public static func write(_ value: DocRecord, into buf: inout [UInt8]) {
|
||||
FfiConverterString.write(value.docId, into: &buf)
|
||||
FfiConverterString.write(value.data, into: &buf)
|
||||
FfiConverterTimestamp.write(value.timestamp, into: &buf)
|
||||
FfiConverterString.write(value.bin, into: &buf)
|
||||
FfiConverterInt64.write(value.timestamp, into: &buf)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1374,15 +1289,15 @@ public func FfiConverterTypeDocRecord_lower(_ value: DocRecord) -> RustBuffer {
|
||||
|
||||
public struct DocUpdate {
|
||||
public var docId: String
|
||||
public var createdAt: Date
|
||||
public var data: String
|
||||
public var timestamp: Int64
|
||||
public var bin: String
|
||||
|
||||
// Default memberwise initializers are never public by default, so we
|
||||
// declare one manually.
|
||||
public init(docId: String, createdAt: Date, data: String) {
|
||||
public init(docId: String, timestamp: Int64, bin: String) {
|
||||
self.docId = docId
|
||||
self.createdAt = createdAt
|
||||
self.data = data
|
||||
self.timestamp = timestamp
|
||||
self.bin = bin
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1391,10 +1306,10 @@ extension DocUpdate: Equatable, Hashable {
|
||||
if lhs.docId != rhs.docId {
|
||||
return false
|
||||
}
|
||||
if lhs.createdAt != rhs.createdAt {
|
||||
if lhs.timestamp != rhs.timestamp {
|
||||
return false
|
||||
}
|
||||
if lhs.data != rhs.data {
|
||||
if lhs.bin != rhs.bin {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -1402,8 +1317,8 @@ extension DocUpdate: Equatable, Hashable {
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(docId)
|
||||
hasher.combine(createdAt)
|
||||
hasher.combine(data)
|
||||
hasher.combine(timestamp)
|
||||
hasher.combine(bin)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1415,15 +1330,15 @@ public struct FfiConverterTypeDocUpdate: FfiConverterRustBuffer {
|
||||
return
|
||||
try DocUpdate(
|
||||
docId: FfiConverterString.read(from: &buf),
|
||||
createdAt: FfiConverterTimestamp.read(from: &buf),
|
||||
data: FfiConverterString.read(from: &buf)
|
||||
timestamp: FfiConverterInt64.read(from: &buf),
|
||||
bin: FfiConverterString.read(from: &buf)
|
||||
)
|
||||
}
|
||||
|
||||
public static func write(_ value: DocUpdate, into buf: inout [UInt8]) {
|
||||
FfiConverterString.write(value.docId, into: &buf)
|
||||
FfiConverterTimestamp.write(value.createdAt, into: &buf)
|
||||
FfiConverterString.write(value.data, into: &buf)
|
||||
FfiConverterInt64.write(value.timestamp, into: &buf)
|
||||
FfiConverterString.write(value.bin, into: &buf)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1445,11 +1360,11 @@ public struct ListedBlob {
|
||||
public var key: String
|
||||
public var size: Int64
|
||||
public var mime: String
|
||||
public var createdAt: Date
|
||||
public var createdAt: Int64
|
||||
|
||||
// Default memberwise initializers are never public by default, so we
|
||||
// declare one manually.
|
||||
public init(key: String, size: Int64, mime: String, createdAt: Date) {
|
||||
public init(key: String, size: Int64, mime: String, createdAt: Int64) {
|
||||
self.key = key
|
||||
self.size = size
|
||||
self.mime = mime
|
||||
@@ -1492,7 +1407,7 @@ public struct FfiConverterTypeListedBlob: FfiConverterRustBuffer {
|
||||
key: FfiConverterString.read(from: &buf),
|
||||
size: FfiConverterInt64.read(from: &buf),
|
||||
mime: FfiConverterString.read(from: &buf),
|
||||
createdAt: FfiConverterTimestamp.read(from: &buf)
|
||||
createdAt: FfiConverterInt64.read(from: &buf)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1500,7 +1415,7 @@ public struct FfiConverterTypeListedBlob: FfiConverterRustBuffer {
|
||||
FfiConverterString.write(value.key, into: &buf)
|
||||
FfiConverterInt64.write(value.size, into: &buf)
|
||||
FfiConverterString.write(value.mime, into: &buf)
|
||||
FfiConverterTimestamp.write(value.createdAt, into: &buf)
|
||||
FfiConverterInt64.write(value.createdAt, into: &buf)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1588,21 +1503,11 @@ public func FfiConverterTypeSetBlob_lower(_ value: SetBlob) -> RustBuffer {
|
||||
}
|
||||
|
||||
public enum UniffiError {
|
||||
case GetUserDocumentDirectoryFailed
|
||||
case CreateAffineDirFailed(String
|
||||
)
|
||||
case EmptyDocStoragePath
|
||||
case EmptySpaceId
|
||||
case SqlxError(String
|
||||
case Err(String
|
||||
)
|
||||
case Base64DecodingError(String
|
||||
)
|
||||
case InvalidUniversalId(String
|
||||
)
|
||||
case InvalidSpaceType(String
|
||||
)
|
||||
case ConcatSpaceDirFailed(String
|
||||
)
|
||||
case TimestampDecodingError
|
||||
}
|
||||
|
||||
#if swift(>=5.8)
|
||||
@@ -1614,65 +1519,29 @@ public struct FfiConverterTypeUniffiError: FfiConverterRustBuffer {
|
||||
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UniffiError {
|
||||
let variant: Int32 = try readInt(&buf)
|
||||
switch variant {
|
||||
case 1: return .GetUserDocumentDirectoryFailed
|
||||
case 2: return try .CreateAffineDirFailed(
|
||||
case 1: return try .Err(
|
||||
FfiConverterString.read(from: &buf)
|
||||
)
|
||||
case 3: return .EmptyDocStoragePath
|
||||
case 4: return .EmptySpaceId
|
||||
case 5: return try .SqlxError(
|
||||
FfiConverterString.read(from: &buf)
|
||||
)
|
||||
case 6: return try .Base64DecodingError(
|
||||
FfiConverterString.read(from: &buf)
|
||||
)
|
||||
case 7: return try .InvalidUniversalId(
|
||||
FfiConverterString.read(from: &buf)
|
||||
)
|
||||
case 8: return try .InvalidSpaceType(
|
||||
FfiConverterString.read(from: &buf)
|
||||
)
|
||||
case 9: return try .ConcatSpaceDirFailed(
|
||||
case 2: return try .Base64DecodingError(
|
||||
FfiConverterString.read(from: &buf)
|
||||
)
|
||||
case 3: return .TimestampDecodingError
|
||||
default: throw UniffiInternalError.unexpectedEnumCase
|
||||
}
|
||||
}
|
||||
|
||||
public static func write(_ value: UniffiError, into buf: inout [UInt8]) {
|
||||
switch value {
|
||||
case .GetUserDocumentDirectoryFailed:
|
||||
case let .Err(v1):
|
||||
writeInt(&buf, Int32(1))
|
||||
|
||||
case let .CreateAffineDirFailed(v1):
|
||||
writeInt(&buf, Int32(2))
|
||||
FfiConverterString.write(v1, into: &buf)
|
||||
|
||||
case .EmptyDocStoragePath:
|
||||
writeInt(&buf, Int32(3))
|
||||
|
||||
case .EmptySpaceId:
|
||||
writeInt(&buf, Int32(4))
|
||||
|
||||
case let .SqlxError(v1):
|
||||
writeInt(&buf, Int32(5))
|
||||
FfiConverterString.write(v1, into: &buf)
|
||||
|
||||
case let .Base64DecodingError(v1):
|
||||
writeInt(&buf, Int32(6))
|
||||
writeInt(&buf, Int32(2))
|
||||
FfiConverterString.write(v1, into: &buf)
|
||||
|
||||
case let .InvalidUniversalId(v1):
|
||||
writeInt(&buf, Int32(7))
|
||||
FfiConverterString.write(v1, into: &buf)
|
||||
|
||||
case let .InvalidSpaceType(v1):
|
||||
writeInt(&buf, Int32(8))
|
||||
FfiConverterString.write(v1, into: &buf)
|
||||
|
||||
case let .ConcatSpaceDirFailed(v1):
|
||||
writeInt(&buf, Int32(9))
|
||||
FfiConverterString.write(v1, into: &buf)
|
||||
case .TimestampDecodingError:
|
||||
writeInt(&buf, Int32(3))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1688,8 +1557,8 @@ extension UniffiError: Foundation.LocalizedError {
|
||||
#if swift(>=5.8)
|
||||
@_documentation(visibility: private)
|
||||
#endif
|
||||
private struct FfiConverterOptionTimestamp: FfiConverterRustBuffer {
|
||||
typealias SwiftType = Date?
|
||||
private struct FfiConverterOptionInt64: FfiConverterRustBuffer {
|
||||
typealias SwiftType = Int64?
|
||||
|
||||
public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
|
||||
guard let value = value else {
|
||||
@@ -1697,13 +1566,13 @@ private struct FfiConverterOptionTimestamp: FfiConverterRustBuffer {
|
||||
return
|
||||
}
|
||||
writeInt(&buf, Int8(1))
|
||||
FfiConverterTimestamp.write(value, into: &buf)
|
||||
FfiConverterInt64.write(value, into: &buf)
|
||||
}
|
||||
|
||||
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
|
||||
switch try readInt(&buf) as Int8 {
|
||||
case 0: return nil
|
||||
case 1: return try FfiConverterTimestamp.read(from: &buf)
|
||||
case 1: return try FfiConverterInt64.read(from: &buf)
|
||||
default: throw UniffiInternalError.unexpectedOptionalTag
|
||||
}
|
||||
}
|
||||
@@ -1784,23 +1653,23 @@ private struct FfiConverterOptionTypeDocRecord: FfiConverterRustBuffer {
|
||||
#if swift(>=5.8)
|
||||
@_documentation(visibility: private)
|
||||
#endif
|
||||
private struct FfiConverterSequenceTimestamp: FfiConverterRustBuffer {
|
||||
typealias SwiftType = [Date]
|
||||
private struct FfiConverterSequenceInt64: FfiConverterRustBuffer {
|
||||
typealias SwiftType = [Int64]
|
||||
|
||||
public static func write(_ value: [Date], into buf: inout [UInt8]) {
|
||||
public static func write(_ value: [Int64], into buf: inout [UInt8]) {
|
||||
let len = Int32(value.count)
|
||||
writeInt(&buf, len)
|
||||
for item in value {
|
||||
FfiConverterTimestamp.write(item, into: &buf)
|
||||
FfiConverterInt64.write(item, into: &buf)
|
||||
}
|
||||
}
|
||||
|
||||
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [Date] {
|
||||
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [Int64] {
|
||||
let len: Int32 = try readInt(&buf)
|
||||
var seq = [Date]()
|
||||
var seq = [Int64]()
|
||||
seq.reserveCapacity(Int(len))
|
||||
for _ in 0 ..< len {
|
||||
try seq.append(FfiConverterTimestamp.read(from: &buf))
|
||||
try seq.append(FfiConverterInt64.read(from: &buf))
|
||||
}
|
||||
return seq
|
||||
}
|
||||
@@ -1928,16 +1797,6 @@ private func uniffiFutureContinuationCallback(handle: UInt64, pollResult: Int8)
|
||||
}
|
||||
}
|
||||
|
||||
public func getDbPath(peer: String, spaceType: String, id: String) throws -> String {
|
||||
return try FfiConverterString.lift(rustCallWithError(FfiConverterTypeUniffiError.lift) {
|
||||
uniffi_affine_mobile_native_fn_func_get_db_path(
|
||||
FfiConverterString.lower(peer),
|
||||
FfiConverterString.lower(spaceType),
|
||||
FfiConverterString.lower(id), $0
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public func hashcashMint(resource: String, bits: UInt32) -> String {
|
||||
return try! FfiConverterString.lift(try! rustCall {
|
||||
uniffi_affine_mobile_native_fn_func_hashcash_mint(
|
||||
@@ -1947,6 +1806,13 @@ public func hashcashMint(resource: String, bits: UInt32) -> String {
|
||||
})
|
||||
}
|
||||
|
||||
public func newDocStoragePool() -> DocStoragePool {
|
||||
return try! FfiConverterTypeDocStoragePool.lift(try! rustCall {
|
||||
uniffi_affine_mobile_native_fn_func_new_doc_storage_pool($0
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
private enum InitializationResult {
|
||||
case ok
|
||||
case contractVersionMismatch
|
||||
@@ -1963,22 +1829,16 @@ private var initializationResult: InitializationResult = {
|
||||
if bindings_contract_version != scaffolding_contract_version {
|
||||
return InitializationResult.contractVersionMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_func_get_db_path() != 65350 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_func_hashcash_mint() != 23633 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_checkpoint() != 36299 {
|
||||
if uniffi_affine_mobile_native_checksum_func_new_doc_storage_pool() != 32882 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_clear_clocks() != 51151 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_close() != 46846 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_connect() != 57961 {
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_connect() != 19047 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_delete_blob() != 53695 {
|
||||
@@ -1987,13 +1847,16 @@ private var initializationResult: InitializationResult = {
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_delete_doc() != 4005 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_disconnect() != 20410 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_blob() != 56927 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_clock() != 48394 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_clocks() != 23822 {
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_clocks() != 46082 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_snapshot() != 31220 {
|
||||
@@ -2017,16 +1880,13 @@ private var initializationResult: InitializationResult = {
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_remote_clocks() != 14523 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_is_closed() != 40091 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_list_blobs() != 6777 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_mark_updates_merged() != 26982 {
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_mark_updates_merged() != 42713 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_push_update() != 54572 {
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_push_update() != 20688 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_release_blobs() != 2203 {
|
||||
@@ -2038,21 +1898,18 @@ private var initializationResult: InitializationResult = {
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_doc_snapshot() != 5287 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_pulled_remote_clock() != 40733 {
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_pulled_remote_clock() != 33923 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_pushed_clock() != 15697 {
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_pushed_clock() != 16565 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_remote_clock() != 57108 {
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_remote_clock() != 46506 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_space_id() != 21955 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if uniffi_affine_mobile_native_checksum_method_docstoragepool_validate() != 17232 {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
|
||||
return InitializationResult.ok
|
||||
}()
|
||||
|
||||
@@ -261,24 +261,14 @@ void*_Nonnull uniffi_affine_mobile_native_fn_clone_docstoragepool(void*_Nonnull
|
||||
void uniffi_affine_mobile_native_fn_free_docstoragepool(void*_Nonnull ptr, RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_CHECKPOINT
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_CHECKPOINT
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_checkpoint(void*_Nonnull ptr, RustBuffer universal_id
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_CLEAR_CLOCKS
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_CLEAR_CLOCKS
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_clear_clocks(void*_Nonnull ptr, RustBuffer universal_id
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_CLOSE
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_CLOSE
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_close(void*_Nonnull ptr, RustBuffer universal_id
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_CONNECT
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_CONNECT
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_connect(void*_Nonnull ptr, RustBuffer universal_id
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_connect(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer path
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_DELETE_BLOB
|
||||
@@ -291,6 +281,11 @@ uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_delete_blob(void*_
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_delete_doc(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer doc_id
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_DISCONNECT
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_DISCONNECT
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_disconnect(void*_Nonnull ptr, RustBuffer universal_id
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_GET_BLOB
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_GET_BLOB
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_get_blob(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer key
|
||||
@@ -341,11 +336,6 @@ uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_remote_cl
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_remote_clocks(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_IS_CLOSED
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_IS_CLOSED
|
||||
int8_t uniffi_affine_mobile_native_fn_method_docstoragepool_is_closed(void*_Nonnull ptr, RustBuffer universal_id, RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_LIST_BLOBS
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_LIST_BLOBS
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_list_blobs(void*_Nonnull ptr, RustBuffer universal_id
|
||||
@@ -378,17 +368,17 @@ uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_doc_snapshot(v
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_PULLED_REMOTE_CLOCK
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_PULLED_REMOTE_CLOCK
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pulled_remote_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, RustBuffer clock
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pulled_remote_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, int64_t clock
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_PUSHED_CLOCK
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_PUSHED_CLOCK
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pushed_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, RustBuffer clock
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pushed_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, int64_t clock
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_REMOTE_CLOCK
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_REMOTE_CLOCK
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_remote_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, RustBuffer clock
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_remote_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, int64_t clock
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_SPACE_ID
|
||||
@@ -396,19 +386,15 @@ uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_remote_cl
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_space_id(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer space_id
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_VALIDATE
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_VALIDATE
|
||||
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_validate(void*_Nonnull ptr, RustBuffer universal_id
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_FUNC_GET_DB_PATH
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_FUNC_GET_DB_PATH
|
||||
RustBuffer uniffi_affine_mobile_native_fn_func_get_db_path(RustBuffer peer, RustBuffer space_type, RustBuffer id, RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_FUNC_HASHCASH_MINT
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_FUNC_HASHCASH_MINT
|
||||
RustBuffer uniffi_affine_mobile_native_fn_func_hashcash_mint(RustBuffer resource, uint32_t bits, RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_FUNC_NEW_DOC_STORAGE_POOL
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_FUNC_NEW_DOC_STORAGE_POOL
|
||||
void*_Nonnull uniffi_affine_mobile_native_fn_func_new_doc_storage_pool(RustCallStatus *_Nonnull out_status
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_FFI_AFFINE_MOBILE_NATIVE_RUSTBUFFER_ALLOC
|
||||
@@ -689,12 +675,6 @@ void ffi_affine_mobile_native_rust_future_free_void(uint64_t handle
|
||||
#ifndef UNIFFI_FFIDEF_FFI_AFFINE_MOBILE_NATIVE_RUST_FUTURE_COMPLETE_VOID
|
||||
#define UNIFFI_FFIDEF_FFI_AFFINE_MOBILE_NATIVE_RUST_FUTURE_COMPLETE_VOID
|
||||
void ffi_affine_mobile_native_rust_future_complete_void(uint64_t handle, RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_FUNC_GET_DB_PATH
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_FUNC_GET_DB_PATH
|
||||
uint16_t uniffi_affine_mobile_native_checksum_func_get_db_path(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_FUNC_HASHCASH_MINT
|
||||
@@ -703,9 +683,9 @@ uint16_t uniffi_affine_mobile_native_checksum_func_hashcash_mint(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_CHECKPOINT
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_CHECKPOINT
|
||||
uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_checkpoint(void
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_FUNC_NEW_DOC_STORAGE_POOL
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_FUNC_NEW_DOC_STORAGE_POOL
|
||||
uint16_t uniffi_affine_mobile_native_checksum_func_new_doc_storage_pool(void
|
||||
|
||||
);
|
||||
#endif
|
||||
@@ -713,12 +693,6 @@ uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_checkpoint(v
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_CLEAR_CLOCKS
|
||||
uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_clear_clocks(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_CLOSE
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_CLOSE
|
||||
uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_close(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_CONNECT
|
||||
@@ -737,6 +711,12 @@ uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_delete_blob(
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_DELETE_DOC
|
||||
uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_delete_doc(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_DISCONNECT
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_DISCONNECT
|
||||
uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_disconnect(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_GET_BLOB
|
||||
@@ -797,12 +777,6 @@ uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_rem
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_GET_PEER_REMOTE_CLOCKS
|
||||
uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_remote_clocks(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_IS_CLOSED
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_IS_CLOSED
|
||||
uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_is_closed(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_LIST_BLOBS
|
||||
@@ -863,12 +837,6 @@ uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_rem
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_SET_SPACE_ID
|
||||
uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_set_space_id(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_VALIDATE
|
||||
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_VALIDATE
|
||||
uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_validate(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_FFI_AFFINE_MOBILE_NATIVE_UNIFFI_CONTRACT_VERSION
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import { type BlobRecord, BlobStorageBase, share } from '@affine/nbstore';
|
||||
|
||||
import { NativeDBConnection } from './db';
|
||||
|
||||
export class SqliteBlobStorage extends BlobStorageBase {
|
||||
override connection = share(
|
||||
new NativeDBConnection(this.peer, this.spaceType, this.spaceId)
|
||||
);
|
||||
|
||||
get db() {
|
||||
return this.connection.inner;
|
||||
}
|
||||
|
||||
override async get(key: string) {
|
||||
return this.db.getBlob(key);
|
||||
}
|
||||
|
||||
override async set(blob: BlobRecord) {
|
||||
await this.db.setBlob(blob);
|
||||
}
|
||||
|
||||
override async delete(key: string, permanently: boolean) {
|
||||
await this.db.deleteBlob(key, permanently);
|
||||
}
|
||||
|
||||
override async release() {
|
||||
await this.db.releaseBlobs();
|
||||
}
|
||||
|
||||
override async list() {
|
||||
return this.db.listBlobs();
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
import type { DocStorage } from '@affine/native';
|
||||
import {
|
||||
AutoReconnectConnection,
|
||||
isValidSpaceType,
|
||||
type SpaceType,
|
||||
universalId,
|
||||
} from '@affine/nbstore';
|
||||
|
||||
import { NativeDocStorage, NbStoreDocStorage } from './plugin';
|
||||
|
||||
export class NativeDBConnection extends AutoReconnectConnection<DocStorage> {
|
||||
private readonly universalId: string;
|
||||
|
||||
constructor(
|
||||
private readonly peer: string,
|
||||
private readonly type: SpaceType,
|
||||
private readonly id: string
|
||||
) {
|
||||
super();
|
||||
if (!isValidSpaceType(type)) {
|
||||
throw new TypeError(`Invalid space type: ${type}`);
|
||||
}
|
||||
this.universalId = universalId({
|
||||
peer: peer,
|
||||
type: type,
|
||||
id: id,
|
||||
});
|
||||
}
|
||||
|
||||
async getDBPath() {
|
||||
const { path } = await NbStoreDocStorage.getSpaceDBPath({
|
||||
peer: this.peer,
|
||||
spaceType: this.type,
|
||||
id: this.id,
|
||||
});
|
||||
return path;
|
||||
}
|
||||
|
||||
override get shareId(): string {
|
||||
return `sqlite:${this.peer}:${this.type}:${this.id}`;
|
||||
}
|
||||
|
||||
override async doConnect() {
|
||||
const conn = new NativeDocStorage(this.universalId);
|
||||
await conn.connect();
|
||||
console.info('[nbstore] connection established', this.shareId);
|
||||
return conn;
|
||||
}
|
||||
|
||||
override doDisconnect(conn: NativeDocStorage) {
|
||||
conn
|
||||
.close()
|
||||
.then(() => {
|
||||
console.info('[nbstore] connection closed', this.shareId);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('[nbstore] connection close failed', this.shareId, err);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -27,17 +27,13 @@ export interface DocClock {
|
||||
}
|
||||
|
||||
export interface NbStorePlugin {
|
||||
getSpaceDBPath: (options: {
|
||||
peer: string;
|
||||
spaceType: string;
|
||||
connect: (options: {
|
||||
id: string;
|
||||
}) => Promise<{ path: string }>;
|
||||
create: (options: { id: string; path: string }) => Promise<void>;
|
||||
connect: (options: { id: string }) => Promise<void>;
|
||||
close: (options: { id: string }) => Promise<void>;
|
||||
isClosed: (options: { id: string }) => Promise<{ isClosed: boolean }>;
|
||||
checkpoint: (options: { id: string }) => Promise<void>;
|
||||
validate: (options: { id: string }) => Promise<{ isValidate: boolean }>;
|
||||
spaceId: string;
|
||||
spaceType: string;
|
||||
peer: string;
|
||||
}) => Promise<void>;
|
||||
disconnect: (options: { id: string }) => Promise<void>;
|
||||
|
||||
setSpaceId: (options: { id: string; spaceId: string }) => Promise<void>;
|
||||
pushUpdate: (options: {
|
||||
@@ -49,7 +45,7 @@ export interface NbStorePlugin {
|
||||
| {
|
||||
docId: string;
|
||||
// base64 encoded data
|
||||
data: string;
|
||||
bin: string;
|
||||
timestamp: number;
|
||||
}
|
||||
| undefined
|
||||
@@ -57,23 +53,24 @@ export interface NbStorePlugin {
|
||||
setDocSnapshot: (options: {
|
||||
id: string;
|
||||
docId: string;
|
||||
data: string;
|
||||
bin: string;
|
||||
timestamp: number;
|
||||
}) => Promise<{ success: boolean }>;
|
||||
getDocUpdates: (options: { id: string; docId: string }) => Promise<
|
||||
{
|
||||
getDocUpdates: (options: { id: string; docId: string }) => Promise<{
|
||||
updates: {
|
||||
docId: string;
|
||||
createdAt: number;
|
||||
timestamp: number;
|
||||
// base64 encoded data
|
||||
data: string;
|
||||
}[]
|
||||
>;
|
||||
bin: string;
|
||||
}[];
|
||||
}>;
|
||||
markUpdatesMerged: (options: {
|
||||
id: string;
|
||||
docId: string;
|
||||
timestamps: number[];
|
||||
}) => Promise<{ count: number }>;
|
||||
deleteDoc: (options: { id: string; docId: string }) => Promise<void>;
|
||||
getDocClocks: (options: { id: string; after: number }) => Promise<
|
||||
getDocClocks: (options: { id: string; after?: number | null }) => Promise<
|
||||
{
|
||||
docId: string;
|
||||
timestamp: number;
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
import {
|
||||
type DocClocks,
|
||||
type DocRecord,
|
||||
DocStorageBase,
|
||||
type DocUpdate,
|
||||
share,
|
||||
} from '@affine/nbstore';
|
||||
|
||||
import { NativeDBConnection } from './db';
|
||||
|
||||
export class SqliteDocStorage extends DocStorageBase {
|
||||
override connection = share(
|
||||
new NativeDBConnection(this.peer, this.spaceType, this.spaceId)
|
||||
);
|
||||
|
||||
get db() {
|
||||
return this.connection.inner;
|
||||
}
|
||||
|
||||
override async pushDocUpdate(update: DocUpdate) {
|
||||
const timestamp = await this.db.pushUpdate(update.docId, update.bin);
|
||||
|
||||
return { docId: update.docId, timestamp };
|
||||
}
|
||||
|
||||
override async deleteDoc(docId: string) {
|
||||
await this.db.deleteDoc(docId);
|
||||
}
|
||||
|
||||
override async getDocTimestamps(after?: Date) {
|
||||
const clocks = await this.db.getDocClocks(after);
|
||||
|
||||
return clocks.reduce((ret, cur) => {
|
||||
ret[cur.docId] = cur.timestamp;
|
||||
return ret;
|
||||
}, {} as DocClocks);
|
||||
}
|
||||
|
||||
override async getDocTimestamp(docId: string) {
|
||||
return this.db.getDocClock(docId);
|
||||
}
|
||||
|
||||
protected override async getDocSnapshot(docId: string) {
|
||||
const snapshot = await this.db.getDocSnapshot(docId);
|
||||
|
||||
if (!snapshot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
docId,
|
||||
bin: snapshot.data,
|
||||
timestamp: snapshot.timestamp,
|
||||
};
|
||||
}
|
||||
|
||||
protected override async setDocSnapshot(
|
||||
snapshot: DocRecord
|
||||
): Promise<boolean> {
|
||||
return this.db.setDocSnapshot({
|
||||
docId: snapshot.docId,
|
||||
data: Buffer.from(snapshot.bin),
|
||||
timestamp: new Date(snapshot.timestamp),
|
||||
});
|
||||
}
|
||||
|
||||
protected override async getDocUpdates(docId: string) {
|
||||
return this.db.getDocUpdates(docId).then(updates =>
|
||||
updates.map(update => ({
|
||||
docId,
|
||||
bin: update.data,
|
||||
timestamp: update.createdAt,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
protected override markUpdatesMerged(docId: string, updates: DocRecord[]) {
|
||||
return this.db.markUpdatesMerged(
|
||||
docId,
|
||||
updates.map(update => update.timestamp)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
import {
|
||||
type BlobRecord,
|
||||
type DocClock,
|
||||
type DocUpdate,
|
||||
} from '@affine/nbstore';
|
||||
|
||||
import { ensureStorage, getStorage } from './storage';
|
||||
|
||||
export const nbstoreHandlers = {
|
||||
connect: async (id: string) => {
|
||||
await ensureStorage(id);
|
||||
},
|
||||
|
||||
close: async (id: string) => {
|
||||
const store = getStorage(id);
|
||||
|
||||
if (store) {
|
||||
store.disconnect();
|
||||
// The store may be shared with other tabs, so we don't delete it from cache
|
||||
// the underlying connection will handle the close correctly
|
||||
// STORE_CACHE.delete(`${spaceType}:${spaceId}`);
|
||||
}
|
||||
},
|
||||
|
||||
pushDocUpdate: async (id: string, update: DocUpdate) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('doc').pushDocUpdate(update);
|
||||
},
|
||||
|
||||
getDoc: async (id: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('doc').getDoc(docId);
|
||||
},
|
||||
|
||||
deleteDoc: async (id: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('doc').deleteDoc(docId);
|
||||
},
|
||||
|
||||
getDocTimestamps: async (id: string, after?: Date) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('doc').getDocTimestamps(after);
|
||||
},
|
||||
|
||||
getDocTimestamp: async (id: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('doc').getDocTimestamp(docId);
|
||||
},
|
||||
|
||||
setBlob: async (id: string, blob: BlobRecord) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('blob').set(blob);
|
||||
},
|
||||
|
||||
getBlob: async (id: string, key: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('blob').get(key);
|
||||
},
|
||||
|
||||
deleteBlob: async (id: string, key: string, permanently: boolean) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('blob').delete(key, permanently);
|
||||
},
|
||||
|
||||
listBlobs: async (id: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('blob').list();
|
||||
},
|
||||
|
||||
releaseBlobs: async (id: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('blob').release();
|
||||
},
|
||||
|
||||
getPeerRemoteClocks: async (id: string, peer: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerRemoteClocks(peer);
|
||||
},
|
||||
|
||||
getPeerRemoteClock: async (id: string, peer: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerRemoteClock(peer, docId);
|
||||
},
|
||||
|
||||
setPeerRemoteClock: async (id: string, peer: string, clock: DocClock) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').setPeerRemoteClock(peer, clock);
|
||||
},
|
||||
|
||||
getPeerPulledRemoteClocks: async (id: string, peer: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerPulledRemoteClocks(peer);
|
||||
},
|
||||
|
||||
getPeerPulledRemoteClock: async (id: string, peer: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerPulledRemoteClock(peer, docId);
|
||||
},
|
||||
|
||||
setPeerPulledRemoteClock: async (
|
||||
id: string,
|
||||
peer: string,
|
||||
clock: DocClock
|
||||
) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').setPeerPulledRemoteClock(peer, clock);
|
||||
},
|
||||
|
||||
getPeerPushedClocks: async (id: string, peer: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerPushedClocks(peer);
|
||||
},
|
||||
|
||||
getPeerPushedClock: async (id: string, peer: string, docId: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').getPeerPushedClock(peer, docId);
|
||||
},
|
||||
|
||||
setPeerPushedClock: async (id: string, peer: string, clock: DocClock) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').setPeerPushedClock(peer, clock);
|
||||
},
|
||||
|
||||
clearClocks: async (id: string) => {
|
||||
const store = await ensureStorage(id);
|
||||
return store.get('sync').clearClocks();
|
||||
},
|
||||
};
|
||||
@@ -1,5 +1,304 @@
|
||||
import {
|
||||
base64ToUint8Array,
|
||||
uint8ArrayToBase64,
|
||||
} from '@affine/core/modules/workspace-engine';
|
||||
import {
|
||||
type BlobRecord,
|
||||
type DocClock,
|
||||
type DocRecord,
|
||||
type ListedBlobRecord,
|
||||
parseUniversalId,
|
||||
} from '@affine/nbstore';
|
||||
import { type NativeDBApis } from '@affine/nbstore/sqlite';
|
||||
import { registerPlugin } from '@capacitor/core';
|
||||
|
||||
import type { NbStorePlugin } from './definitions';
|
||||
|
||||
export * from './definitions';
|
||||
export { nbstoreHandlers } from './handlers';
|
||||
export { NbStoreDocStorage } from './plugin';
|
||||
export * from './storage';
|
||||
export { universalId } from '@affine/nbstore';
|
||||
|
||||
export const NbStore = registerPlugin<NbStorePlugin>('NbStoreDocStorage');
|
||||
|
||||
export const NbStoreNativeDBApis: NativeDBApis = {
|
||||
connect: async function (id: string): Promise<void> {
|
||||
const { peer, type, id: spaceId } = parseUniversalId(id);
|
||||
return await NbStore.connect({ id, spaceId, spaceType: type, peer });
|
||||
},
|
||||
disconnect: function (id: string): Promise<void> {
|
||||
return NbStore.disconnect({ id });
|
||||
},
|
||||
pushUpdate: async function (
|
||||
id: string,
|
||||
docId: string,
|
||||
update: Uint8Array
|
||||
): Promise<Date> {
|
||||
const { timestamp } = await NbStore.pushUpdate({
|
||||
id,
|
||||
docId,
|
||||
data: await uint8ArrayToBase64(update),
|
||||
});
|
||||
return new Date(timestamp);
|
||||
},
|
||||
getDocSnapshot: async function (
|
||||
id: string,
|
||||
docId: string
|
||||
): Promise<DocRecord | null> {
|
||||
const snapshot = await NbStore.getDocSnapshot({ id, docId });
|
||||
return snapshot
|
||||
? {
|
||||
bin: base64ToUint8Array(snapshot.bin),
|
||||
docId: snapshot.docId,
|
||||
timestamp: new Date(snapshot.timestamp),
|
||||
}
|
||||
: null;
|
||||
},
|
||||
setDocSnapshot: async function (
|
||||
id: string,
|
||||
snapshot: DocRecord
|
||||
): Promise<boolean> {
|
||||
const { success } = await NbStore.setDocSnapshot({
|
||||
id,
|
||||
docId: snapshot.docId,
|
||||
bin: await uint8ArrayToBase64(snapshot.bin),
|
||||
timestamp: snapshot.timestamp.getTime(),
|
||||
});
|
||||
return success;
|
||||
},
|
||||
getDocUpdates: async function (
|
||||
id: string,
|
||||
docId: string
|
||||
): Promise<DocRecord[]> {
|
||||
const { updates } = await NbStore.getDocUpdates({ id, docId });
|
||||
return updates.map(update => ({
|
||||
bin: base64ToUint8Array(update.bin),
|
||||
docId: update.docId,
|
||||
timestamp: new Date(update.timestamp),
|
||||
}));
|
||||
},
|
||||
markUpdatesMerged: async function (
|
||||
id: string,
|
||||
docId: string,
|
||||
updates: Date[]
|
||||
): Promise<number> {
|
||||
const { count } = await NbStore.markUpdatesMerged({
|
||||
id,
|
||||
docId,
|
||||
timestamps: updates.map(t => t.getTime()),
|
||||
});
|
||||
return count;
|
||||
},
|
||||
deleteDoc: async function (id: string, docId: string): Promise<void> {
|
||||
await NbStore.deleteDoc({
|
||||
id,
|
||||
docId,
|
||||
});
|
||||
},
|
||||
getDocClocks: async function (
|
||||
id: string,
|
||||
after?: Date | undefined | null
|
||||
): Promise<DocClock[]> {
|
||||
const clocks = await NbStore.getDocClocks({
|
||||
id,
|
||||
after: after?.getTime(),
|
||||
});
|
||||
return clocks.map(c => ({
|
||||
docId: c.docId,
|
||||
timestamp: new Date(c.timestamp),
|
||||
}));
|
||||
},
|
||||
getDocClock: async function (
|
||||
id: string,
|
||||
docId: string
|
||||
): Promise<DocClock | null> {
|
||||
const clock = await NbStore.getDocClock({
|
||||
id,
|
||||
docId,
|
||||
});
|
||||
return clock
|
||||
? {
|
||||
timestamp: new Date(clock.timestamp),
|
||||
docId: clock.docId,
|
||||
}
|
||||
: null;
|
||||
},
|
||||
getBlob: async function (
|
||||
id: string,
|
||||
key: string
|
||||
): Promise<BlobRecord | null> {
|
||||
const record = await NbStore.getBlob({
|
||||
id,
|
||||
key,
|
||||
});
|
||||
return record
|
||||
? {
|
||||
data: base64ToUint8Array(record.data),
|
||||
key: record.key,
|
||||
mime: record.mime,
|
||||
createdAt: new Date(record.createdAt),
|
||||
}
|
||||
: null;
|
||||
},
|
||||
setBlob: async function (id: string, blob: BlobRecord): Promise<void> {
|
||||
await NbStore.setBlob({
|
||||
id,
|
||||
data: await uint8ArrayToBase64(blob.data),
|
||||
key: blob.key,
|
||||
mime: blob.mime,
|
||||
});
|
||||
},
|
||||
deleteBlob: async function (
|
||||
id: string,
|
||||
key: string,
|
||||
permanently: boolean
|
||||
): Promise<void> {
|
||||
await NbStore.deleteBlob({
|
||||
id,
|
||||
key,
|
||||
permanently,
|
||||
});
|
||||
},
|
||||
releaseBlobs: async function (id: string): Promise<void> {
|
||||
await NbStore.releaseBlobs({
|
||||
id,
|
||||
});
|
||||
},
|
||||
listBlobs: async function (id: string): Promise<ListedBlobRecord[]> {
|
||||
const listed = await NbStore.listBlobs({
|
||||
id,
|
||||
});
|
||||
return listed.map(b => ({
|
||||
key: b.key,
|
||||
mime: b.mime,
|
||||
size: b.size,
|
||||
createdAt: new Date(b.createdAt),
|
||||
}));
|
||||
},
|
||||
getPeerRemoteClocks: async function (
|
||||
id: string,
|
||||
peer: string
|
||||
): Promise<DocClock[]> {
|
||||
const clocks = await NbStore.getPeerRemoteClocks({
|
||||
id,
|
||||
peer,
|
||||
});
|
||||
|
||||
return clocks.map(c => ({
|
||||
docId: c.docId,
|
||||
timestamp: new Date(c.timestamp),
|
||||
}));
|
||||
},
|
||||
getPeerRemoteClock: async function (
|
||||
id: string,
|
||||
peer: string,
|
||||
docId: string
|
||||
): Promise<DocClock> {
|
||||
const clock = await NbStore.getPeerRemoteClock({
|
||||
id,
|
||||
peer,
|
||||
docId,
|
||||
});
|
||||
return {
|
||||
docId: clock.docId,
|
||||
timestamp: new Date(clock.timestamp),
|
||||
};
|
||||
},
|
||||
setPeerRemoteClock: async function (
|
||||
id: string,
|
||||
peer: string,
|
||||
docId: string,
|
||||
clock: Date
|
||||
): Promise<void> {
|
||||
await NbStore.setPeerRemoteClock({
|
||||
id,
|
||||
peer,
|
||||
docId,
|
||||
clock: clock.getTime(),
|
||||
});
|
||||
},
|
||||
getPeerPulledRemoteClocks: async function (
|
||||
id: string,
|
||||
peer: string
|
||||
): Promise<DocClock[]> {
|
||||
const clocks = await NbStore.getPeerPulledRemoteClocks({
|
||||
id,
|
||||
peer,
|
||||
});
|
||||
return clocks.map(c => ({
|
||||
docId: c.docId,
|
||||
timestamp: new Date(c.timestamp),
|
||||
}));
|
||||
},
|
||||
getPeerPulledRemoteClock: async function (
|
||||
id: string,
|
||||
peer: string,
|
||||
docId: string
|
||||
): Promise<DocClock> {
|
||||
const clock = await NbStore.getPeerPulledRemoteClock({
|
||||
id,
|
||||
peer,
|
||||
docId,
|
||||
});
|
||||
return {
|
||||
docId: clock.docId,
|
||||
timestamp: new Date(clock.timestamp),
|
||||
};
|
||||
},
|
||||
setPeerPulledRemoteClock: async function (
|
||||
id: string,
|
||||
peer: string,
|
||||
docId: string,
|
||||
clock: Date
|
||||
): Promise<void> {
|
||||
await NbStore.setPeerPulledRemoteClock({
|
||||
id,
|
||||
peer,
|
||||
docId,
|
||||
clock: clock.getTime(),
|
||||
});
|
||||
},
|
||||
getPeerPushedClocks: async function (
|
||||
id: string,
|
||||
peer: string
|
||||
): Promise<DocClock[]> {
|
||||
const clocks = await NbStore.getPeerPushedClocks({
|
||||
id,
|
||||
peer,
|
||||
});
|
||||
return clocks.map(c => ({
|
||||
docId: c.docId,
|
||||
timestamp: new Date(c.timestamp),
|
||||
}));
|
||||
},
|
||||
getPeerPushedClock: async function (
|
||||
id: string,
|
||||
peer: string,
|
||||
docId: string
|
||||
): Promise<DocClock> {
|
||||
const clock = await NbStore.getPeerPushedClock({
|
||||
id,
|
||||
peer,
|
||||
docId,
|
||||
});
|
||||
return {
|
||||
docId: clock.docId,
|
||||
timestamp: new Date(clock.timestamp),
|
||||
};
|
||||
},
|
||||
setPeerPushedClock: async function (
|
||||
id: string,
|
||||
peer: string,
|
||||
docId: string,
|
||||
clock: Date
|
||||
): Promise<void> {
|
||||
await NbStore.setPeerPushedClock({
|
||||
id,
|
||||
peer,
|
||||
docId,
|
||||
clock: clock.getTime(),
|
||||
});
|
||||
},
|
||||
clearClocks: async function (id: string): Promise<void> {
|
||||
await NbStore.clearClocks({
|
||||
id,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,312 +0,0 @@
|
||||
import {
|
||||
base64ToUint8Array,
|
||||
uint8ArrayToBase64,
|
||||
} from '@affine/core/modules/workspace-engine';
|
||||
import {
|
||||
type Blob,
|
||||
type DocClock,
|
||||
type DocRecord,
|
||||
type DocStorage,
|
||||
type DocUpdate,
|
||||
type ListedBlob,
|
||||
} from '@affine/native';
|
||||
import { registerPlugin } from '@capacitor/core';
|
||||
|
||||
import type { NbStorePlugin } from './definitions';
|
||||
|
||||
export const NbStoreDocStorage =
|
||||
registerPlugin<NbStorePlugin>('NbStoreDocStorage');
|
||||
|
||||
export interface SetBlob {
|
||||
key: string;
|
||||
data: Uint8Array;
|
||||
mime: string;
|
||||
}
|
||||
|
||||
export class NativeDocStorage implements DocStorage {
|
||||
constructor(private readonly universalId: string) {}
|
||||
|
||||
/** Initialize the database and run migrations. */
|
||||
connect(): Promise<void> {
|
||||
return NbStoreDocStorage.connect({
|
||||
id: this.universalId,
|
||||
});
|
||||
}
|
||||
|
||||
close(): Promise<void> {
|
||||
return NbStoreDocStorage.close({
|
||||
id: this.universalId,
|
||||
});
|
||||
}
|
||||
|
||||
get isClosed(): Promise<boolean> {
|
||||
return NbStoreDocStorage.isClosed({
|
||||
id: this.universalId,
|
||||
}).then(result => result.isClosed);
|
||||
}
|
||||
/**
|
||||
* Flush the WAL file to the database file.
|
||||
* See https://www.sqlite.org/pragma.html#pragma_wal_checkpoint:~:text=PRAGMA%20schema.wal_checkpoint%3B
|
||||
*/
|
||||
checkpoint(): Promise<void> {
|
||||
return NbStoreDocStorage.checkpoint({
|
||||
id: this.universalId,
|
||||
});
|
||||
}
|
||||
|
||||
validate(): Promise<boolean> {
|
||||
return NbStoreDocStorage.validate({
|
||||
id: this.universalId,
|
||||
}).then(result => result.isValidate);
|
||||
}
|
||||
|
||||
setSpaceId(spaceId: string): Promise<void> {
|
||||
return NbStoreDocStorage.setSpaceId({
|
||||
id: this.universalId,
|
||||
spaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async pushUpdate(docId: string, update: Uint8Array): Promise<Date> {
|
||||
return NbStoreDocStorage.pushUpdate({
|
||||
id: this.universalId,
|
||||
docId,
|
||||
data: await uint8ArrayToBase64(update),
|
||||
}).then(result => new Date(result.timestamp));
|
||||
}
|
||||
|
||||
getDocSnapshot(docId: string): Promise<DocRecord | null> {
|
||||
return NbStoreDocStorage.getDocSnapshot({
|
||||
id: this.universalId,
|
||||
docId,
|
||||
}).then(result => {
|
||||
if (result) {
|
||||
return {
|
||||
...result,
|
||||
data: base64ToUint8Array(result.data),
|
||||
timestamp: new Date(result.timestamp),
|
||||
};
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
async setDocSnapshot(snapshot: DocRecord): Promise<boolean> {
|
||||
return NbStoreDocStorage.setDocSnapshot({
|
||||
id: this.universalId,
|
||||
docId: snapshot.docId,
|
||||
data: await uint8ArrayToBase64(snapshot.data),
|
||||
}).then(result => result.success);
|
||||
}
|
||||
|
||||
getDocUpdates(docId: string): Promise<Array<DocUpdate>> {
|
||||
return NbStoreDocStorage.getDocUpdates({
|
||||
id: this.universalId,
|
||||
docId,
|
||||
}).then(result =>
|
||||
result.map(update => ({
|
||||
...update,
|
||||
data: base64ToUint8Array(update.data),
|
||||
createdAt: new Date(update.createdAt),
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
markUpdatesMerged(docId: string, updates: Array<Date>): Promise<number> {
|
||||
return NbStoreDocStorage.markUpdatesMerged({
|
||||
id: this.universalId,
|
||||
docId,
|
||||
timestamps: updates.map(date => date.getTime()),
|
||||
}).then(result => result.count);
|
||||
}
|
||||
|
||||
deleteDoc(docId: string): Promise<void> {
|
||||
return NbStoreDocStorage.deleteDoc({
|
||||
id: this.universalId,
|
||||
docId,
|
||||
});
|
||||
}
|
||||
|
||||
getDocClocks(after: Date): Promise<Array<DocClock>> {
|
||||
return NbStoreDocStorage.getDocClocks({
|
||||
id: this.universalId,
|
||||
after: after.getTime(),
|
||||
}).then(result =>
|
||||
result.map(clock => ({
|
||||
...clock,
|
||||
timestamp: new Date(clock.timestamp),
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
getDocClock(docId: string): Promise<DocClock | null> {
|
||||
return NbStoreDocStorage.getDocClock({
|
||||
id: this.universalId,
|
||||
docId,
|
||||
}).then(result => {
|
||||
if (result) {
|
||||
return {
|
||||
...result,
|
||||
timestamp: new Date(result.timestamp),
|
||||
};
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
getBlob(key: string): Promise<Blob | null> {
|
||||
return NbStoreDocStorage.getBlob({
|
||||
id: this.universalId,
|
||||
key,
|
||||
}).then(result => {
|
||||
if (result) {
|
||||
return {
|
||||
...result,
|
||||
data: base64ToUint8Array(result.data),
|
||||
createdAt: new Date(result.createdAt),
|
||||
};
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
async setBlob(blob: SetBlob): Promise<void> {
|
||||
return NbStoreDocStorage.setBlob({
|
||||
id: this.universalId,
|
||||
key: blob.key,
|
||||
data: await uint8ArrayToBase64(blob.data),
|
||||
mime: blob.mime,
|
||||
});
|
||||
}
|
||||
|
||||
deleteBlob(key: string, permanently: boolean): Promise<void> {
|
||||
return NbStoreDocStorage.deleteBlob({
|
||||
id: this.universalId,
|
||||
key,
|
||||
permanently,
|
||||
});
|
||||
}
|
||||
|
||||
releaseBlobs(): Promise<void> {
|
||||
return NbStoreDocStorage.releaseBlobs({
|
||||
id: this.universalId,
|
||||
});
|
||||
}
|
||||
|
||||
async listBlobs(): Promise<Array<ListedBlob>> {
|
||||
return (
|
||||
await NbStoreDocStorage.listBlobs({
|
||||
id: this.universalId,
|
||||
})
|
||||
).map(blob => ({
|
||||
...blob,
|
||||
createdAt: new Date(blob.createdAt),
|
||||
}));
|
||||
}
|
||||
|
||||
getPeerRemoteClocks(peer: string): Promise<Array<DocClock>> {
|
||||
return NbStoreDocStorage.getPeerRemoteClocks({
|
||||
id: this.universalId,
|
||||
peer,
|
||||
}).then(result =>
|
||||
result.map(clock => ({
|
||||
...clock,
|
||||
timestamp: new Date(clock.timestamp),
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
getPeerRemoteClock(peer: string, docId: string): Promise<DocClock> {
|
||||
return NbStoreDocStorage.getPeerRemoteClock({
|
||||
id: this.universalId,
|
||||
peer,
|
||||
docId,
|
||||
}).then(result => ({
|
||||
...result,
|
||||
timestamp: new Date(result.timestamp),
|
||||
}));
|
||||
}
|
||||
|
||||
setPeerRemoteClock(peer: string, docId: string, clock: Date): Promise<void> {
|
||||
return NbStoreDocStorage.setPeerRemoteClock({
|
||||
id: this.universalId,
|
||||
peer,
|
||||
docId,
|
||||
clock: clock.getTime(),
|
||||
});
|
||||
}
|
||||
|
||||
getPeerPulledRemoteClocks(peer: string): Promise<Array<DocClock>> {
|
||||
return NbStoreDocStorage.getPeerPulledRemoteClocks({
|
||||
id: this.universalId,
|
||||
peer,
|
||||
}).then(result =>
|
||||
result.map(clock => ({
|
||||
...clock,
|
||||
timestamp: new Date(clock.timestamp),
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
getPeerPulledRemoteClock(peer: string, docId: string): Promise<DocClock> {
|
||||
return NbStoreDocStorage.getPeerPulledRemoteClock({
|
||||
id: this.universalId,
|
||||
peer,
|
||||
docId,
|
||||
}).then(result => ({
|
||||
...result,
|
||||
timestamp: new Date(result.timestamp),
|
||||
}));
|
||||
}
|
||||
|
||||
setPeerPulledRemoteClock(
|
||||
peer: string,
|
||||
docId: string,
|
||||
clock: Date
|
||||
): Promise<void> {
|
||||
return NbStoreDocStorage.setPeerPulledRemoteClock({
|
||||
id: this.universalId,
|
||||
peer,
|
||||
docId,
|
||||
clock: clock.getTime(),
|
||||
});
|
||||
}
|
||||
|
||||
getPeerPushedClocks(peer: string): Promise<Array<DocClock>> {
|
||||
return NbStoreDocStorage.getPeerPushedClocks({
|
||||
id: this.universalId,
|
||||
peer,
|
||||
}).then(result =>
|
||||
result.map(clock => ({
|
||||
...clock,
|
||||
timestamp: new Date(clock.timestamp),
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
getPeerPushedClock(peer: string, docId: string): Promise<DocClock> {
|
||||
return NbStoreDocStorage.getPeerPushedClock({
|
||||
id: this.universalId,
|
||||
peer,
|
||||
docId,
|
||||
}).then(result => ({
|
||||
...result,
|
||||
timestamp: new Date(result.timestamp),
|
||||
}));
|
||||
}
|
||||
|
||||
setPeerPushedClock(peer: string, docId: string, clock: Date): Promise<void> {
|
||||
return NbStoreDocStorage.setPeerPushedClock({
|
||||
id: this.universalId,
|
||||
peer,
|
||||
docId,
|
||||
clock: clock.getTime(),
|
||||
});
|
||||
}
|
||||
|
||||
clearClocks(): Promise<void> {
|
||||
return NbStoreDocStorage.clearClocks({
|
||||
id: this.universalId,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
import { parseUniversalId, SpaceStorage } from '@affine/nbstore';
|
||||
import { applyUpdate, Doc as YDoc } from 'yjs';
|
||||
|
||||
import { SqliteBlobStorage } from './blob';
|
||||
import { NativeDBConnection } from './db';
|
||||
import { SqliteDocStorage } from './doc';
|
||||
import { SqliteSyncStorage } from './sync';
|
||||
|
||||
export class SqliteSpaceStorage extends SpaceStorage {
|
||||
get connection() {
|
||||
const docStore = this.get('doc');
|
||||
|
||||
if (!docStore) {
|
||||
throw new Error('doc store not found');
|
||||
}
|
||||
|
||||
const connection = docStore.connection;
|
||||
|
||||
if (!(connection instanceof NativeDBConnection)) {
|
||||
throw new Error('doc store connection is not a Sqlite connection');
|
||||
}
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
async getDBPath() {
|
||||
return this.connection.getDBPath();
|
||||
}
|
||||
|
||||
async getWorkspaceName() {
|
||||
const docStore = this.tryGet('doc');
|
||||
|
||||
if (!docStore) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const doc = await docStore.getDoc(docStore.spaceId);
|
||||
if (!doc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const ydoc = new YDoc();
|
||||
applyUpdate(ydoc, doc.bin);
|
||||
return ydoc.getMap('meta').get('name') as string;
|
||||
}
|
||||
|
||||
async checkpoint() {
|
||||
await this.connection.inner.checkpoint();
|
||||
}
|
||||
}
|
||||
|
||||
const STORE_CACHE = new Map<string, SqliteSpaceStorage>();
|
||||
|
||||
export function getStorage(universalId: string) {
|
||||
return STORE_CACHE.get(universalId);
|
||||
}
|
||||
|
||||
export async function ensureStorage(universalId: string) {
|
||||
const { peer, type, id } = parseUniversalId(universalId);
|
||||
let store = STORE_CACHE.get(universalId);
|
||||
|
||||
if (!store) {
|
||||
const opts = {
|
||||
peer,
|
||||
type,
|
||||
id,
|
||||
};
|
||||
|
||||
store = new SqliteSpaceStorage([
|
||||
new SqliteDocStorage(opts),
|
||||
new SqliteBlobStorage(opts),
|
||||
new SqliteSyncStorage(opts),
|
||||
]);
|
||||
|
||||
store.connect();
|
||||
|
||||
await store.waitForConnected();
|
||||
|
||||
STORE_CACHE.set(universalId, store);
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
import {
|
||||
BasicSyncStorage,
|
||||
type DocClock,
|
||||
type DocClocks,
|
||||
share,
|
||||
} from '@affine/nbstore';
|
||||
|
||||
import { NativeDBConnection } from './db';
|
||||
|
||||
export class SqliteSyncStorage extends BasicSyncStorage {
|
||||
override connection = share(
|
||||
new NativeDBConnection(this.peer, this.spaceType, this.spaceId)
|
||||
);
|
||||
|
||||
get db() {
|
||||
return this.connection.inner;
|
||||
}
|
||||
|
||||
override async getPeerRemoteClocks(peer: string) {
|
||||
const records = await this.db.getPeerRemoteClocks(peer);
|
||||
return records.reduce((clocks, { docId, timestamp }) => {
|
||||
clocks[docId] = timestamp;
|
||||
return clocks;
|
||||
}, {} as DocClocks);
|
||||
}
|
||||
|
||||
override async getPeerRemoteClock(peer: string, docId: string) {
|
||||
return this.db.getPeerRemoteClock(peer, docId);
|
||||
}
|
||||
|
||||
override async setPeerRemoteClock(peer: string, clock: DocClock) {
|
||||
await this.db.setPeerRemoteClock(peer, clock.docId, clock.timestamp);
|
||||
}
|
||||
|
||||
override async getPeerPulledRemoteClock(peer: string, docId: string) {
|
||||
return this.db.getPeerPulledRemoteClock(peer, docId);
|
||||
}
|
||||
|
||||
override async getPeerPulledRemoteClocks(peer: string) {
|
||||
const records = await this.db.getPeerPulledRemoteClocks(peer);
|
||||
return records.reduce((clocks, { docId, timestamp }) => {
|
||||
clocks[docId] = timestamp;
|
||||
return clocks;
|
||||
}, {} as DocClocks);
|
||||
}
|
||||
|
||||
override async setPeerPulledRemoteClock(peer: string, clock: DocClock) {
|
||||
await this.db.setPeerPulledRemoteClock(peer, clock.docId, clock.timestamp);
|
||||
}
|
||||
|
||||
override async getPeerPushedClocks(peer: string) {
|
||||
const records = await this.db.getPeerPushedClocks(peer);
|
||||
return records.reduce((clocks, { docId, timestamp }) => {
|
||||
clocks[docId] = timestamp;
|
||||
return clocks;
|
||||
}, {} as DocClocks);
|
||||
}
|
||||
|
||||
override async getPeerPushedClock(peer: string, docId: string) {
|
||||
return this.db.getPeerPushedClock(peer, docId);
|
||||
}
|
||||
|
||||
override async setPeerPushedClock(peer: string, clock: DocClock) {
|
||||
await this.db.setPeerPushedClock(peer, clock.docId, clock.timestamp);
|
||||
}
|
||||
|
||||
override async clearClocks() {
|
||||
await this.db.clearClocks();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user