@toeverything/y-indexeddb
Advanced tools
Comparing version 0.7.0-canary.18 to 0.7.0-canary.19
@@ -14,5 +14,8 @@ import { Doc } from 'yjs'; | ||
export declare const getMilestones: (id: string, dbName?: string) => Promise<null | WorkspaceMilestone['milestone']>; | ||
export declare const createIndexedDBProvider: (id: string, doc: Doc, dbName?: string) => IndexedDBProvider; | ||
/** | ||
* We use `doc.guid` as the unique key, please make sure it not changes. | ||
*/ | ||
export declare const createIndexedDBProvider: (doc: Doc, dbName?: string, migrate?: boolean) => IndexedDBProvider; | ||
export * from './shared'; | ||
export * from './utils'; | ||
//# sourceMappingURL=index.d.ts.map |
import { openDB as S } from "idb"; | ||
import { mergeUpdates as T, Doc as V, applyUpdate as h, encodeStateVector as I, encodeStateAsUpdate as y, UndoManager as z, diffUpdate as J } from "yjs"; | ||
const j = 1, E = "affine-local"; | ||
import { mergeUpdates as V, Doc as W, applyUpdate as h, encodeStateVector as I, encodeStateAsUpdate as y, UndoManager as z, diffUpdate as J } from "yjs"; | ||
const j = 1, v = "affine-local"; | ||
function P(t) { | ||
t.createObjectStore("workspace", { keyPath: "id" }), t.createObjectStore("milestone", { keyPath: "id" }); | ||
} | ||
let H; | ||
let T; | ||
async function K(t) { | ||
return new Promise((r) => { | ||
const i = indexedDB.open(t); | ||
return new Promise((i) => { | ||
const c = indexedDB.open(t); | ||
let a = !0; | ||
i.onsuccess = function() { | ||
i.result.close(), a || indexedDB.deleteDatabase(t), r(a); | ||
}, i.onupgradeneeded = function() { | ||
c.onsuccess = function() { | ||
c.result.close(), a || indexedDB.deleteDatabase(t), i(a); | ||
}, c.onupgradeneeded = function() { | ||
a = !1; | ||
@@ -19,10 +19,10 @@ }; | ||
} | ||
async function Q(t, r, i = E) { | ||
async function Q(t, i, c = v) { | ||
do | ||
if (!H || localStorage.getItem(`${i}-migration`) !== "true") { | ||
if (!T || localStorage.getItem(`${c}-migration`) !== "true") { | ||
try { | ||
H = await indexedDB.databases(); | ||
T = await indexedDB.databases(); | ||
} catch { | ||
if (await K(r)) { | ||
await S(r, 1).then(async (a) => { | ||
if (await K(i)) { | ||
await S(i, 1).then(async (a) => { | ||
if (!a.objectStoreNames.contains("updates")) | ||
@@ -33,5 +33,5 @@ return; | ||
return; | ||
const n = T(s), u = t.transaction("workspace", "readwrite").objectStore("workspace"); | ||
await u.get(r) || (console.log("upgrading the database"), await u.put({ | ||
id: r, | ||
const n = V(s), u = t.transaction("workspace", "readwrite").objectStore("workspace"); | ||
await u.get(i) || (console.log("upgrading the database"), await u.put({ | ||
id: i, | ||
updates: [ | ||
@@ -49,3 +49,3 @@ { | ||
await Promise.all( | ||
H.map((a) => { | ||
T.map((a) => { | ||
if (a.name && a.version === 1) { | ||
@@ -60,3 +60,3 @@ const w = a.name, s = a.version; | ||
return; | ||
const f = T(d), g = t.transaction("workspace", "readwrite").objectStore("workspace"); | ||
const f = V(d), g = t.transaction("workspace", "readwrite").objectStore("workspace"); | ||
await g.get(w) || (console.log("upgrading the database"), await g.put({ | ||
@@ -75,3 +75,3 @@ id: w, | ||
}) | ||
), localStorage.setItem(`${i}-migration`, "true"); | ||
), localStorage.setItem(`${c}-migration`, "true"); | ||
break; | ||
@@ -81,9 +81,9 @@ } | ||
} | ||
async function ee(t, r = E) { | ||
const s = await (await S(r, j, { | ||
async function ee(t, i = v) { | ||
const s = await (await S(i, j, { | ||
upgrade: P | ||
})).transaction("workspace", "readonly").objectStore("workspace").get(t); | ||
return s ? T(s.updates.map(({ update: n }) => n)) : !1; | ||
return s ? V(s.updates.map(({ update: n }) => n)) : !1; | ||
} | ||
const v = Symbol("indexeddb-provider-origin"), M = Symbol("snapshot-origin"); | ||
const E = Symbol("indexeddb-provider-origin"), M = Symbol("snapshot-origin"); | ||
let $ = 500; | ||
@@ -100,5 +100,5 @@ const L = (t) => (t.preventDefault(), t.returnValue = "Data is not saved. Are you sure you want to leave?"), U = async (t) => { | ||
} | ||
function ae(t, r, i) { | ||
const a = new V(); | ||
h(a, r, M); | ||
function ae(t, i, c) { | ||
const a = new W(); | ||
h(a, i, M); | ||
const w = I(t), s = I(a), n = y( | ||
@@ -109,3 +109,3 @@ t, | ||
[...a.share.keys()].map((f) => { | ||
const g = i(f); | ||
const g = c(f); | ||
if (g === "Text") | ||
@@ -140,18 +140,18 @@ return a.getText(f); | ||
} | ||
const ne = async (t, r, i, a = E) => { | ||
const ne = async (t, i, c, a = v) => { | ||
const n = (await S(a, j, { | ||
upgrade: P | ||
})).transaction("milestone", "readwrite").objectStore("milestone"), u = await n.get("id"), d = y(r); | ||
u ? (u.milestone[i] = d, await n.put(u)) : await n.put({ | ||
})).transaction("milestone", "readwrite").objectStore("milestone"), u = await n.get("id"), d = y(i); | ||
u ? (u.milestone[c] = d, await n.put(u)) : await n.put({ | ||
id: t, | ||
milestone: { | ||
[i]: d | ||
[c]: d | ||
} | ||
}); | ||
}, re = async (t, r = E) => { | ||
const s = await (await S(r, j, { | ||
}, re = async (t, i = v) => { | ||
const s = await (await S(i, j, { | ||
upgrade: P | ||
})).transaction("milestone", "readonly").objectStore("milestone").get(t); | ||
return s ? s.milestone : null; | ||
}, se = (t, r, i = E) => { | ||
}, se = (t, i = v, c = !0) => { | ||
let a, w, s = !0, n = !1; | ||
@@ -163,5 +163,5 @@ const u = S(i, j, { | ||
return d.get(e); | ||
const c = async function(l, b) { | ||
const r = async function(l, m) { | ||
const D = await u; | ||
if (!n || b === v) | ||
if (!n || m === E) | ||
return; | ||
@@ -177,9 +177,9 @@ const k = D.transaction("workspace", "readwrite").objectStore("workspace"); | ||
}), p.updates.length > $) { | ||
const F = p.updates.map(({ update: C }) => C), B = new V(); | ||
B.transact(() => { | ||
F.forEach((C) => { | ||
h(B, C, v); | ||
const F = p.updates.map(({ update: H }) => H), C = new W(); | ||
C.transact(() => { | ||
F.forEach((H) => { | ||
h(C, H, E); | ||
}); | ||
}, v); | ||
const N = y(B); | ||
}, E); | ||
const N = y(C); | ||
p = { | ||
@@ -197,36 +197,38 @@ id: o, | ||
}; | ||
return d.set(e, c), c; | ||
return d.set(e, r), r; | ||
}, A = (o, e) => { | ||
if (f.has(e)) | ||
return f.get(e); | ||
const c = async function() { | ||
const r = async function() { | ||
(await u).close(); | ||
}; | ||
return f.set(e, c), c; | ||
}, W = (o, e) => { | ||
return f.set(e, r), r; | ||
}, _ = (o, e) => { | ||
if (g.has(e)) | ||
return g.get(e); | ||
const c = async function(l) { | ||
l.removed.forEach((b) => { | ||
O(b.guid, b); | ||
}), l.loaded.forEach((b) => { | ||
_(b.guid, b); | ||
const r = async function(l) { | ||
l.removed.forEach((m) => { | ||
B(m.guid, m); | ||
}), l.loaded.forEach((m) => { | ||
O(m.guid, m); | ||
}); | ||
}; | ||
return g.set(e, c), c; | ||
return g.set(e, r), r; | ||
}; | ||
function _(o, e) { | ||
e.on("update", x(o, e)), e.on("destroy", A(o, e)), e.on("subdocs", W(o, e)); | ||
} | ||
function O(o, e) { | ||
e.subdocs.forEach((c) => { | ||
O(c.guid, c); | ||
}), e.off("update", x(o, e)), e.off("destroy", A(o, e)), e.off("subdocs", W(o, e)); | ||
e.on("update", x(o, e)), e.on("destroy", A(o, e)), e.on("subdocs", _(o, e)), e.subdocs.forEach((r) => { | ||
O(r.guid, r); | ||
}); | ||
} | ||
function B(o, e) { | ||
e.subdocs.forEach((r) => { | ||
B(r.guid, r); | ||
}), e.off("update", x(o, e)), e.off("destroy", A(o, e)), e.off("subdocs", _(o, e)); | ||
} | ||
async function q(o, e) { | ||
const c = await u, m = c.transaction("workspace", "readwrite").objectStore("workspace"), l = await m.get(o); | ||
const r = await u, b = r.transaction("workspace", "readwrite").objectStore("workspace"), l = await b.get(o); | ||
if (n) | ||
if (!l) | ||
await U( | ||
c.put("workspace", { | ||
r.put("workspace", { | ||
id: o, | ||
@@ -242,8 +244,8 @@ updates: [ | ||
else { | ||
const b = l.updates.map(({ update: p }) => p), D = new V(); | ||
const m = l.updates.map(({ update: p }) => p), D = new W(); | ||
D.transact(() => { | ||
b.forEach((p) => { | ||
m.forEach((p) => { | ||
h(D, p); | ||
}); | ||
}, v); | ||
}, E); | ||
const k = J( | ||
@@ -254,3 +256,3 @@ y(e), | ||
await U( | ||
m.put({ | ||
b.put({ | ||
...l, | ||
@@ -266,6 +268,6 @@ updates: [ | ||
), e.transact(() => { | ||
b.forEach((p) => { | ||
m.forEach((p) => { | ||
h(e, p); | ||
}); | ||
}, v); | ||
}, E); | ||
} | ||
@@ -277,12 +279,12 @@ } | ||
return; | ||
G.whenSynced = new Promise((c, m) => { | ||
s = !0, a = c, w = m; | ||
}), n = !0, _(t, r); | ||
G.whenSynced = new Promise((r, b) => { | ||
s = !0, a = r, w = b; | ||
}), n = !0, O(t.guid, t); | ||
const o = await u; | ||
if (await Q(o, t, i), !n) | ||
if (c && await Q(o, t.guid, i), !n) | ||
return; | ||
const e = []; | ||
for (e.push([t, r]); e.length > 0; ) { | ||
const [c, m] = e.pop(); | ||
await q(c, m), m.subdocs.forEach((l) => { | ||
for (e.push([t.guid, t]); e.length > 0; ) { | ||
const [r, b] = e.pop(); | ||
await q(r, b), b.subdocs.forEach((l) => { | ||
e.push([l.guid, l]); | ||
@@ -294,3 +296,3 @@ }); | ||
disconnect() { | ||
n = !1, s && w(new R()), O(t, r); | ||
n = !1, s && w(new R()), B(t.guid, t); | ||
}, | ||
@@ -300,3 +302,3 @@ async cleanup() { | ||
throw new X(); | ||
await (await u).delete("workspace", t); | ||
await (await u).delete("workspace", t.guid); | ||
}, | ||
@@ -312,3 +314,3 @@ whenSynced: Promise.resolve(), | ||
X as CleanupWhenConnectingError, | ||
E as DEFAULT_DB_NAME, | ||
v as DEFAULT_DB_NAME, | ||
R as EarlyDisconnectError, | ||
@@ -315,0 +317,0 @@ se as createIndexedDBProvider, |
@@ -9,3 +9,3 @@ import type { IDBPDatabase } from 'idb/build/entry'; | ||
export declare function tryMigrate(db: IDBPDatabase<BlockSuiteBinaryDB>, id: string, dbName?: string): Promise<void>; | ||
export declare function downloadBinary(id: string, dbName?: string): Promise<UpdateMessage['update'] | false>; | ||
export declare function downloadBinary(guid: string, dbName?: string): Promise<UpdateMessage['update'] | false>; | ||
//# sourceMappingURL=utils.d.ts.map |
{ | ||
"name": "@toeverything/y-indexeddb", | ||
"type": "module", | ||
"version": "0.7.0-canary.18", | ||
"version": "0.7.0-canary.19", | ||
"description": "IndexedDB database adapter for Yjs", | ||
@@ -43,6 +43,6 @@ "repository": "toeverything/AFFiNE", | ||
"devDependencies": { | ||
"@blocksuite/blocks": "0.0.0-20230613142146-d72d4600-nightly", | ||
"@blocksuite/store": "0.0.0-20230613142146-d72d4600-nightly", | ||
"@blocksuite/blocks": "0.0.0-20230626181619-90507cfc-nightly", | ||
"@blocksuite/store": "0.0.0-20230626181619-90507cfc-nightly", | ||
"vite": "^4.3.9", | ||
"vite-plugin-dts": "^2.3.0", | ||
"vite-plugin-dts": "2.3.0", | ||
"y-indexeddb": "^9.0.11" | ||
@@ -49,0 +49,0 @@ }, |
# @toeverything/y-indexeddb | ||
## Features | ||
- persistence data in indexeddb | ||
- sub-documents support | ||
- fully TypeScript | ||
## Usage | ||
@@ -8,6 +14,10 @@ | ||
import * as Y from 'yjs'; | ||
const yDoc = new Y.Doc(); | ||
const yDoc = new Y.Doc({ | ||
// we use `guid` as unique key | ||
guid: 'my-doc', | ||
}); | ||
// sync yDoc with indexedDB | ||
const provider = createIndexedDBProvider('docName', yDoc); | ||
const provider = createIndexedDBProvider(yDoc); | ||
provider.connect(); | ||
@@ -20,3 +30,3 @@ await provider.whenSynced.then(() => { | ||
// dowload binary data from indexedDB for once | ||
downloadBinary('docName').then(blob => { | ||
downloadBinary(yDoc.guid).then(blob => { | ||
if (blob !== false) { | ||
@@ -23,0 +33,0 @@ Y.applyUpdate(yDoc, blob); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
72046
400
35