tinybase 5.0.0-beta.0 → 5.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +1 -1
- package/lib/checkpoints.js +1 -1
- package/lib/checkpoints.js.gz +0 -0
- package/lib/cjs/checkpoints.cjs +1 -1
- package/lib/cjs/checkpoints.cjs.gz +0 -0
- package/lib/cjs/indexes.cjs +1 -1
- package/lib/cjs/indexes.cjs.gz +0 -0
- package/lib/cjs/mergeable-store.cjs +1 -0
- package/lib/cjs/mergeable-store.cjs.gz +0 -0
- package/lib/cjs/metrics.cjs +1 -1
- package/lib/cjs/metrics.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-automerge.cjs +1 -1
- package/lib/cjs/persisters/persister-automerge.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-browser.cjs +1 -1
- package/lib/cjs/persisters/persister-browser.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-cr-sqlite-wasm.cjs +1 -1
- package/lib/cjs/persisters/persister-cr-sqlite-wasm.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-electric-sql.cjs +1 -1
- package/lib/cjs/persisters/persister-electric-sql.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-expo-sqlite-next.cjs +1 -1
- package/lib/cjs/persisters/persister-expo-sqlite-next.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-expo-sqlite.cjs +1 -1
- package/lib/cjs/persisters/persister-expo-sqlite.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-file.cjs +1 -1
- package/lib/cjs/persisters/persister-file.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-indexed-db.cjs +1 -1
- package/lib/cjs/persisters/persister-indexed-db.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-libsql.cjs +1 -0
- package/lib/cjs/persisters/persister-libsql.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-partykit-client.cjs +1 -1
- package/lib/cjs/persisters/persister-partykit-client.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-partykit-server.cjs +1 -1
- package/lib/cjs/persisters/persister-partykit-server.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-powersync.cjs +1 -0
- package/lib/cjs/persisters/persister-powersync.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-remote.cjs +1 -1
- package/lib/cjs/persisters/persister-remote.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-sqlite-wasm.cjs +1 -1
- package/lib/cjs/persisters/persister-sqlite-wasm.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-sqlite3.cjs +1 -1
- package/lib/cjs/persisters/persister-sqlite3.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-yjs.cjs +1 -1
- package/lib/cjs/persisters/persister-yjs.cjs.gz +0 -0
- package/lib/cjs/persisters.cjs +1 -1
- package/lib/cjs/persisters.cjs.gz +0 -0
- package/lib/cjs/queries.cjs +1 -1
- package/lib/cjs/queries.cjs.gz +0 -0
- package/lib/cjs/relationships.cjs +1 -1
- package/lib/cjs/relationships.cjs.gz +0 -0
- package/lib/cjs/store.cjs +1 -1
- package/lib/cjs/store.cjs.gz +0 -0
- package/lib/cjs/synchronizers/synchronizer-local.cjs +1 -0
- package/lib/cjs/synchronizers/synchronizer-local.cjs.gz +0 -0
- package/lib/cjs/synchronizers/synchronizer-ws-client.cjs +1 -0
- package/lib/cjs/synchronizers/synchronizer-ws-client.cjs.gz +0 -0
- package/lib/cjs/synchronizers/synchronizer-ws-server.cjs +1 -0
- package/lib/cjs/synchronizers/synchronizer-ws-server.cjs.gz +0 -0
- package/lib/cjs/synchronizers.cjs +1 -0
- package/lib/cjs/synchronizers.cjs.gz +0 -0
- package/lib/cjs/tinybase.cjs +1 -1
- package/lib/cjs/tinybase.cjs.gz +0 -0
- package/lib/cjs/tools.cjs +1 -1
- package/lib/cjs/tools.cjs.gz +0 -0
- package/lib/cjs/ui-react-dom-debug.cjs +1 -1
- package/lib/cjs/ui-react-dom-debug.cjs.gz +0 -0
- package/lib/cjs/ui-react-dom.cjs +1 -1
- package/lib/cjs/ui-react-dom.cjs.gz +0 -0
- package/lib/cjs/ui-react.cjs +1 -1
- package/lib/cjs/ui-react.cjs.gz +0 -0
- package/lib/cjs-es6/checkpoints.cjs +1 -1
- package/lib/cjs-es6/checkpoints.cjs.gz +0 -0
- package/lib/cjs-es6/indexes.cjs +1 -1
- package/lib/cjs-es6/indexes.cjs.gz +0 -0
- package/lib/cjs-es6/mergeable-store.cjs +1 -0
- package/lib/cjs-es6/mergeable-store.cjs.gz +0 -0
- package/lib/cjs-es6/metrics.cjs +1 -1
- package/lib/cjs-es6/metrics.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-automerge.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-automerge.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-browser.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-browser.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-cr-sqlite-wasm.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-cr-sqlite-wasm.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-electric-sql.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-electric-sql.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-expo-sqlite-next.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-expo-sqlite-next.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-expo-sqlite.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-expo-sqlite.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-file.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-file.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-indexed-db.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-indexed-db.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-libsql.cjs +1 -0
- package/lib/cjs-es6/persisters/persister-libsql.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-partykit-client.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-partykit-client.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-partykit-server.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-partykit-server.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-powersync.cjs +1 -0
- package/lib/cjs-es6/persisters/persister-powersync.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-remote.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-remote.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-sqlite-wasm.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-sqlite-wasm.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-sqlite3.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-sqlite3.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-yjs.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-yjs.cjs.gz +0 -0
- package/lib/cjs-es6/persisters.cjs +1 -1
- package/lib/cjs-es6/persisters.cjs.gz +0 -0
- package/lib/cjs-es6/queries.cjs +1 -1
- package/lib/cjs-es6/queries.cjs.gz +0 -0
- package/lib/cjs-es6/relationships.cjs +1 -1
- package/lib/cjs-es6/relationships.cjs.gz +0 -0
- package/lib/cjs-es6/store.cjs +1 -1
- package/lib/cjs-es6/store.cjs.gz +0 -0
- package/lib/cjs-es6/synchronizers/synchronizer-local.cjs +1 -0
- package/lib/cjs-es6/synchronizers/synchronizer-local.cjs.gz +0 -0
- package/lib/cjs-es6/synchronizers/synchronizer-ws-client.cjs +1 -0
- package/lib/cjs-es6/synchronizers/synchronizer-ws-client.cjs.gz +0 -0
- package/lib/cjs-es6/synchronizers/synchronizer-ws-server.cjs +1 -0
- package/lib/cjs-es6/synchronizers/synchronizer-ws-server.cjs.gz +0 -0
- package/lib/cjs-es6/synchronizers.cjs +1 -0
- package/lib/cjs-es6/synchronizers.cjs.gz +0 -0
- package/lib/cjs-es6/tinybase.cjs +1 -1
- package/lib/cjs-es6/tinybase.cjs.gz +0 -0
- package/lib/cjs-es6/tools.cjs +1 -1
- package/lib/cjs-es6/tools.cjs.gz +0 -0
- package/lib/cjs-es6/ui-react-dom-debug.cjs +1 -1
- package/lib/cjs-es6/ui-react-dom-debug.cjs.gz +0 -0
- package/lib/cjs-es6/ui-react-dom.cjs +1 -1
- package/lib/cjs-es6/ui-react-dom.cjs.gz +0 -0
- package/lib/cjs-es6/ui-react.cjs +1 -1
- package/lib/cjs-es6/ui-react.cjs.gz +0 -0
- package/lib/debug/checkpoints.js +254 -235
- package/lib/debug/indexes.js +10 -6
- package/lib/debug/mergeable-store.js +2230 -0
- package/lib/debug/metrics.js +10 -6
- package/lib/debug/persisters/persister-automerge.js +113 -87
- package/lib/debug/persisters/persister-browser.js +95 -57
- package/lib/debug/persisters/persister-cr-sqlite-wasm.js +175 -109
- package/lib/debug/persisters/persister-electric-sql.js +176 -109
- package/lib/debug/persisters/persister-expo-sqlite-next.js +176 -110
- package/lib/debug/persisters/persister-expo-sqlite.js +175 -109
- package/lib/debug/persisters/persister-file.js +94 -57
- package/lib/debug/persisters/persister-indexed-db.js +94 -57
- package/lib/debug/persisters/persister-libsql.js +913 -0
- package/lib/debug/persisters/persister-partykit-client.js +90 -59
- package/lib/debug/persisters/persister-partykit-server.js +19 -26
- package/lib/debug/persisters/persister-powersync.js +928 -0
- package/lib/debug/persisters/persister-remote.js +86 -53
- package/lib/debug/persisters/persister-sqlite-wasm.js +175 -109
- package/lib/debug/persisters/persister-sqlite3.js +175 -109
- package/lib/debug/persisters/persister-yjs.js +111 -84
- package/lib/debug/persisters.js +82 -50
- package/lib/debug/queries.js +18 -12
- package/lib/debug/relationships.js +10 -6
- package/lib/debug/store.js +150 -127
- package/lib/debug/synchronizers/synchronizer-local.js +559 -0
- package/lib/debug/synchronizers/synchronizer-ws-client.js +586 -0
- package/lib/debug/synchronizers/synchronizer-ws-server.js +96 -0
- package/lib/debug/synchronizers.js +519 -0
- package/lib/debug/tinybase.js +1281 -409
- package/lib/debug/tools.js +41 -64
- package/lib/debug/ui-react-dom.js +277 -213
- package/lib/debug/ui-react.js +213 -198
- package/lib/es6/checkpoints.js +1 -1
- package/lib/es6/checkpoints.js.gz +0 -0
- package/lib/es6/indexes.js +1 -1
- package/lib/es6/indexes.js.gz +0 -0
- package/lib/es6/mergeable-store.js +1 -0
- package/lib/es6/mergeable-store.js.gz +0 -0
- package/lib/es6/metrics.js +1 -1
- package/lib/es6/metrics.js.gz +0 -0
- package/lib/es6/persisters/persister-automerge.js +1 -1
- package/lib/es6/persisters/persister-automerge.js.gz +0 -0
- package/lib/es6/persisters/persister-browser.js +1 -1
- package/lib/es6/persisters/persister-browser.js.gz +0 -0
- package/lib/es6/persisters/persister-cr-sqlite-wasm.js +1 -1
- package/lib/es6/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
- package/lib/es6/persisters/persister-electric-sql.js +1 -1
- package/lib/es6/persisters/persister-electric-sql.js.gz +0 -0
- package/lib/es6/persisters/persister-expo-sqlite-next.js +1 -1
- package/lib/es6/persisters/persister-expo-sqlite-next.js.gz +0 -0
- package/lib/es6/persisters/persister-expo-sqlite.js +1 -1
- package/lib/es6/persisters/persister-expo-sqlite.js.gz +0 -0
- package/lib/es6/persisters/persister-file.js +1 -1
- package/lib/es6/persisters/persister-file.js.gz +0 -0
- package/lib/es6/persisters/persister-indexed-db.js +1 -1
- package/lib/es6/persisters/persister-indexed-db.js.gz +0 -0
- package/lib/es6/persisters/persister-libsql.js +1 -0
- package/lib/es6/persisters/persister-libsql.js.gz +0 -0
- package/lib/es6/persisters/persister-partykit-client.js +1 -1
- package/lib/es6/persisters/persister-partykit-client.js.gz +0 -0
- package/lib/es6/persisters/persister-partykit-server.js +1 -1
- package/lib/es6/persisters/persister-partykit-server.js.gz +0 -0
- package/lib/es6/persisters/persister-powersync.js +1 -0
- package/lib/es6/persisters/persister-powersync.js.gz +0 -0
- package/lib/es6/persisters/persister-remote.js +1 -1
- package/lib/es6/persisters/persister-remote.js.gz +0 -0
- package/lib/es6/persisters/persister-sqlite-wasm.js +1 -1
- package/lib/es6/persisters/persister-sqlite-wasm.js.gz +0 -0
- package/lib/es6/persisters/persister-sqlite3.js +1 -1
- package/lib/es6/persisters/persister-sqlite3.js.gz +0 -0
- package/lib/es6/persisters/persister-yjs.js +1 -1
- package/lib/es6/persisters/persister-yjs.js.gz +0 -0
- package/lib/es6/persisters.js +1 -1
- package/lib/es6/persisters.js.gz +0 -0
- package/lib/es6/queries.js +1 -1
- package/lib/es6/queries.js.gz +0 -0
- package/lib/es6/relationships.js +1 -1
- package/lib/es6/relationships.js.gz +0 -0
- package/lib/es6/store.js +1 -1
- package/lib/es6/store.js.gz +0 -0
- package/lib/es6/synchronizers/synchronizer-local.js +1 -0
- package/lib/es6/synchronizers/synchronizer-local.js.gz +0 -0
- package/lib/es6/synchronizers/synchronizer-ws-client.js +1 -0
- package/lib/es6/synchronizers/synchronizer-ws-client.js.gz +0 -0
- package/lib/es6/synchronizers/synchronizer-ws-server.js +1 -0
- package/lib/es6/synchronizers/synchronizer-ws-server.js.gz +0 -0
- package/lib/es6/synchronizers.js +1 -0
- package/lib/es6/synchronizers.js.gz +0 -0
- package/lib/es6/tinybase.js +1 -1
- package/lib/es6/tinybase.js.gz +0 -0
- package/lib/es6/tools.js +1 -1
- package/lib/es6/tools.js.gz +0 -0
- package/lib/es6/ui-react-dom-debug.js +1 -1
- package/lib/es6/ui-react-dom-debug.js.gz +0 -0
- package/lib/es6/ui-react-dom.js +1 -1
- package/lib/es6/ui-react-dom.js.gz +0 -0
- package/lib/es6/ui-react.js +1 -1
- package/lib/es6/ui-react.js.gz +0 -0
- package/lib/indexes.js +1 -1
- package/lib/indexes.js.gz +0 -0
- package/lib/mergeable-store.js +1 -0
- package/lib/mergeable-store.js.gz +0 -0
- package/lib/metrics.js +1 -1
- package/lib/metrics.js.gz +0 -0
- package/lib/persisters/persister-automerge.js +1 -1
- package/lib/persisters/persister-automerge.js.gz +0 -0
- package/lib/persisters/persister-browser.js +1 -1
- package/lib/persisters/persister-browser.js.gz +0 -0
- package/lib/persisters/persister-cr-sqlite-wasm.js +1 -1
- package/lib/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
- package/lib/persisters/persister-electric-sql.js +1 -1
- package/lib/persisters/persister-electric-sql.js.gz +0 -0
- package/lib/persisters/persister-expo-sqlite-next.js +1 -1
- package/lib/persisters/persister-expo-sqlite-next.js.gz +0 -0
- package/lib/persisters/persister-expo-sqlite.js +1 -1
- package/lib/persisters/persister-expo-sqlite.js.gz +0 -0
- package/lib/persisters/persister-file.js +1 -1
- package/lib/persisters/persister-file.js.gz +0 -0
- package/lib/persisters/persister-indexed-db.js +1 -1
- package/lib/persisters/persister-indexed-db.js.gz +0 -0
- package/lib/persisters/persister-libsql.js +1 -0
- package/lib/persisters/persister-libsql.js.gz +0 -0
- package/lib/persisters/persister-partykit-client.js +1 -1
- package/lib/persisters/persister-partykit-client.js.gz +0 -0
- package/lib/persisters/persister-partykit-server.js +1 -1
- package/lib/persisters/persister-partykit-server.js.gz +0 -0
- package/lib/persisters/persister-powersync.js +1 -0
- package/lib/persisters/persister-powersync.js.gz +0 -0
- package/lib/persisters/persister-remote.js +1 -1
- package/lib/persisters/persister-remote.js.gz +0 -0
- package/lib/persisters/persister-sqlite-wasm.js +1 -1
- package/lib/persisters/persister-sqlite-wasm.js.gz +0 -0
- package/lib/persisters/persister-sqlite3.js +1 -1
- package/lib/persisters/persister-sqlite3.js.gz +0 -0
- package/lib/persisters/persister-yjs.js +1 -1
- package/lib/persisters/persister-yjs.js.gz +0 -0
- package/lib/persisters.js +1 -1
- package/lib/persisters.js.gz +0 -0
- package/lib/queries.js +1 -1
- package/lib/queries.js.gz +0 -0
- package/lib/relationships.js +1 -1
- package/lib/relationships.js.gz +0 -0
- package/lib/store.js +1 -1
- package/lib/store.js.gz +0 -0
- package/lib/synchronizers/synchronizer-local.js +1 -0
- package/lib/synchronizers/synchronizer-local.js.gz +0 -0
- package/lib/synchronizers/synchronizer-ws-client.js +1 -0
- package/lib/synchronizers/synchronizer-ws-client.js.gz +0 -0
- package/lib/synchronizers/synchronizer-ws-server.js +1 -0
- package/lib/synchronizers/synchronizer-ws-server.js.gz +0 -0
- package/lib/synchronizers.js +1 -0
- package/lib/synchronizers.js.gz +0 -0
- package/lib/tinybase.js +1 -1
- package/lib/tinybase.js.gz +0 -0
- package/lib/tools.js +1 -1
- package/lib/tools.js.gz +0 -0
- package/lib/types/checkpoints.d.ts +2 -2
- package/lib/types/indexes.d.ts +2 -2
- package/lib/types/mergeable-store.d.ts +214 -0
- package/lib/types/metrics.d.ts +2 -2
- package/lib/types/persisters/persister-automerge.d.ts +11 -7
- package/lib/types/persisters/persister-browser.d.ts +13 -4
- package/lib/types/persisters/persister-cr-sqlite-wasm.d.ts +4 -0
- package/lib/types/persisters/persister-electric-sql.d.ts +4 -0
- package/lib/types/persisters/persister-expo-sqlite-next.d.ts +7 -3
- package/lib/types/persisters/persister-expo-sqlite.d.ts +4 -0
- package/lib/types/persisters/persister-file.d.ts +7 -2
- package/lib/types/persisters/persister-indexed-db.d.ts +4 -0
- package/lib/types/persisters/persister-libsql.d.ts +142 -0
- package/lib/types/persisters/persister-partykit-client.d.ts +4 -0
- package/lib/types/persisters/persister-partykit-server.d.ts +12 -8
- package/lib/types/persisters/persister-powersync.d.ts +157 -0
- package/lib/types/persisters/persister-remote.d.ts +4 -0
- package/lib/types/persisters/persister-sqlite-wasm.d.ts +4 -0
- package/lib/types/persisters/persister-sqlite3.d.ts +4 -0
- package/lib/types/persisters/persister-yjs.d.ts +6 -2
- package/lib/types/persisters.d.ts +125 -48
- package/lib/types/queries.d.ts +2 -2
- package/lib/types/relationships.d.ts +2 -2
- package/lib/types/store.d.ts +275 -187
- package/lib/types/synchronizers/synchronizer-local.d.ts +27 -0
- package/lib/types/synchronizers/synchronizer-ws-client.d.ts +35 -0
- package/lib/types/synchronizers/synchronizer-ws-server.d.ts +36 -0
- package/lib/types/synchronizers.d.ts +132 -0
- package/lib/types/tinybase.d.ts +10 -8
- package/lib/types/tools.d.ts +4 -4
- package/lib/types/ui-react.d.ts +235 -95
- package/lib/types/with-schemas/checkpoints.d.ts +2 -2
- package/lib/types/with-schemas/indexes.d.ts +2 -2
- package/lib/types/with-schemas/internal/queries.d.ts +4 -3
- package/lib/types/with-schemas/internal/store.d.ts +8 -3
- package/lib/types/with-schemas/mergeable-store.d.ts +492 -0
- package/lib/types/with-schemas/metrics.d.ts +2 -2
- package/lib/types/with-schemas/persisters/persister-automerge.d.ts +12 -8
- package/lib/types/with-schemas/persisters/persister-browser.d.ts +17 -8
- package/lib/types/with-schemas/persisters/persister-cr-sqlite-wasm.d.ts +5 -1
- package/lib/types/with-schemas/persisters/persister-electric-sql.d.ts +5 -1
- package/lib/types/with-schemas/persisters/persister-expo-sqlite-next.d.ts +8 -4
- package/lib/types/with-schemas/persisters/persister-expo-sqlite.d.ts +5 -1
- package/lib/types/with-schemas/persisters/persister-file.d.ts +9 -4
- package/lib/types/with-schemas/persisters/persister-indexed-db.d.ts +5 -1
- package/lib/types/with-schemas/persisters/persister-libsql.d.ts +155 -0
- package/lib/types/with-schemas/persisters/persister-partykit-client.d.ts +5 -1
- package/lib/types/with-schemas/persisters/persister-partykit-server.d.ts +15 -11
- package/lib/types/with-schemas/persisters/persister-powersync.d.ts +170 -0
- package/lib/types/with-schemas/persisters/persister-remote.d.ts +5 -1
- package/lib/types/with-schemas/persisters/persister-sqlite-wasm.d.ts +5 -1
- package/lib/types/with-schemas/persisters/persister-sqlite3.d.ts +5 -1
- package/lib/types/with-schemas/persisters/persister-yjs.d.ts +7 -3
- package/lib/types/with-schemas/persisters.d.ts +161 -101
- package/lib/types/with-schemas/queries.d.ts +3 -3
- package/lib/types/with-schemas/relationships.d.ts +2 -2
- package/lib/types/with-schemas/store.d.ts +483 -345
- package/lib/types/with-schemas/synchronizers/synchronizer-local.d.ts +29 -0
- package/lib/types/with-schemas/synchronizers/synchronizer-ws-client.d.ts +41 -0
- package/lib/types/with-schemas/synchronizers/synchronizer-ws-server.d.ts +36 -0
- package/lib/types/with-schemas/synchronizers.d.ts +146 -0
- package/lib/types/with-schemas/tinybase.d.ts +9 -8
- package/lib/types/with-schemas/tools.d.ts +4 -4
- package/lib/types/with-schemas/ui-react.d.ts +259 -102
- package/lib/ui-react-dom.js +1 -1
- package/lib/ui-react-dom.js.gz +0 -0
- package/lib/ui-react.js +1 -1
- package/lib/ui-react.js.gz +0 -0
- package/lib/umd/checkpoints.js +1 -1
- package/lib/umd/checkpoints.js.gz +0 -0
- package/lib/umd/indexes.js +1 -1
- package/lib/umd/indexes.js.gz +0 -0
- package/lib/umd/mergeable-store.js +1 -0
- package/lib/umd/mergeable-store.js.gz +0 -0
- package/lib/umd/metrics.js +1 -1
- package/lib/umd/metrics.js.gz +0 -0
- package/lib/umd/persisters/persister-automerge.js +1 -1
- package/lib/umd/persisters/persister-automerge.js.gz +0 -0
- package/lib/umd/persisters/persister-browser.js +1 -1
- package/lib/umd/persisters/persister-browser.js.gz +0 -0
- package/lib/umd/persisters/persister-cr-sqlite-wasm.js +1 -1
- package/lib/umd/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
- package/lib/umd/persisters/persister-electric-sql.js +1 -1
- package/lib/umd/persisters/persister-electric-sql.js.gz +0 -0
- package/lib/umd/persisters/persister-expo-sqlite-next.js +1 -1
- package/lib/umd/persisters/persister-expo-sqlite-next.js.gz +0 -0
- package/lib/umd/persisters/persister-expo-sqlite.js +1 -1
- package/lib/umd/persisters/persister-expo-sqlite.js.gz +0 -0
- package/lib/umd/persisters/persister-file.js +1 -1
- package/lib/umd/persisters/persister-file.js.gz +0 -0
- package/lib/umd/persisters/persister-indexed-db.js +1 -1
- package/lib/umd/persisters/persister-indexed-db.js.gz +0 -0
- package/lib/umd/persisters/persister-libsql.js +1 -0
- package/lib/umd/persisters/persister-libsql.js.gz +0 -0
- package/lib/umd/persisters/persister-partykit-client.js +1 -1
- package/lib/umd/persisters/persister-partykit-client.js.gz +0 -0
- package/lib/umd/persisters/persister-partykit-server.js +1 -1
- package/lib/umd/persisters/persister-partykit-server.js.gz +0 -0
- package/lib/umd/persisters/persister-powersync.js +1 -0
- package/lib/umd/persisters/persister-powersync.js.gz +0 -0
- package/lib/umd/persisters/persister-remote.js +1 -1
- package/lib/umd/persisters/persister-remote.js.gz +0 -0
- package/lib/umd/persisters/persister-sqlite-wasm.js +1 -1
- package/lib/umd/persisters/persister-sqlite-wasm.js.gz +0 -0
- package/lib/umd/persisters/persister-sqlite3.js +1 -1
- package/lib/umd/persisters/persister-sqlite3.js.gz +0 -0
- package/lib/umd/persisters/persister-yjs.js +1 -1
- package/lib/umd/persisters/persister-yjs.js.gz +0 -0
- package/lib/umd/persisters.js +1 -1
- package/lib/umd/persisters.js.gz +0 -0
- package/lib/umd/queries.js +1 -1
- package/lib/umd/queries.js.gz +0 -0
- package/lib/umd/relationships.js +1 -1
- package/lib/umd/relationships.js.gz +0 -0
- package/lib/umd/store.js +1 -1
- package/lib/umd/store.js.gz +0 -0
- package/lib/umd/synchronizers/synchronizer-local.js +1 -0
- package/lib/umd/synchronizers/synchronizer-local.js.gz +0 -0
- package/lib/umd/synchronizers/synchronizer-ws-client.js +1 -0
- package/lib/umd/synchronizers/synchronizer-ws-client.js.gz +0 -0
- package/lib/umd/synchronizers/synchronizer-ws-server.js +1 -0
- package/lib/umd/synchronizers/synchronizer-ws-server.js.gz +0 -0
- package/lib/umd/synchronizers.js +1 -0
- package/lib/umd/synchronizers.js.gz +0 -0
- package/lib/umd/tinybase.js +1 -1
- package/lib/umd/tinybase.js.gz +0 -0
- package/lib/umd/tools.js +1 -1
- package/lib/umd/tools.js.gz +0 -0
- package/lib/umd/ui-react-dom-debug.js +1 -1
- package/lib/umd/ui-react-dom-debug.js.gz +0 -0
- package/lib/umd/ui-react-dom.js +1 -1
- package/lib/umd/ui-react-dom.js.gz +0 -0
- package/lib/umd/ui-react.js +1 -1
- package/lib/umd/ui-react.js.gz +0 -0
- package/lib/umd-es6/checkpoints.js +1 -1
- package/lib/umd-es6/checkpoints.js.gz +0 -0
- package/lib/umd-es6/indexes.js +1 -1
- package/lib/umd-es6/indexes.js.gz +0 -0
- package/lib/umd-es6/mergeable-store.js +1 -0
- package/lib/umd-es6/mergeable-store.js.gz +0 -0
- package/lib/umd-es6/metrics.js +1 -1
- package/lib/umd-es6/metrics.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-automerge.js +1 -1
- package/lib/umd-es6/persisters/persister-automerge.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-browser.js +1 -1
- package/lib/umd-es6/persisters/persister-browser.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-cr-sqlite-wasm.js +1 -1
- package/lib/umd-es6/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-electric-sql.js +1 -1
- package/lib/umd-es6/persisters/persister-electric-sql.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-expo-sqlite-next.js +1 -1
- package/lib/umd-es6/persisters/persister-expo-sqlite-next.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-expo-sqlite.js +1 -1
- package/lib/umd-es6/persisters/persister-expo-sqlite.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-file.js +1 -1
- package/lib/umd-es6/persisters/persister-file.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-indexed-db.js +1 -1
- package/lib/umd-es6/persisters/persister-indexed-db.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-libsql.js +1 -0
- package/lib/umd-es6/persisters/persister-libsql.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-partykit-client.js +1 -1
- package/lib/umd-es6/persisters/persister-partykit-client.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-partykit-server.js +1 -1
- package/lib/umd-es6/persisters/persister-partykit-server.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-powersync.js +1 -0
- package/lib/umd-es6/persisters/persister-powersync.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-remote.js +1 -1
- package/lib/umd-es6/persisters/persister-remote.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-sqlite-wasm.js +1 -1
- package/lib/umd-es6/persisters/persister-sqlite-wasm.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-sqlite3.js +1 -1
- package/lib/umd-es6/persisters/persister-sqlite3.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-yjs.js +1 -1
- package/lib/umd-es6/persisters/persister-yjs.js.gz +0 -0
- package/lib/umd-es6/persisters.js +1 -1
- package/lib/umd-es6/persisters.js.gz +0 -0
- package/lib/umd-es6/queries.js +1 -1
- package/lib/umd-es6/queries.js.gz +0 -0
- package/lib/umd-es6/relationships.js +1 -1
- package/lib/umd-es6/relationships.js.gz +0 -0
- package/lib/umd-es6/store.js +1 -1
- package/lib/umd-es6/store.js.gz +0 -0
- package/lib/umd-es6/synchronizers/synchronizer-local.js +1 -0
- package/lib/umd-es6/synchronizers/synchronizer-local.js.gz +0 -0
- package/lib/umd-es6/synchronizers/synchronizer-ws-client.js +1 -0
- package/lib/umd-es6/synchronizers/synchronizer-ws-client.js.gz +0 -0
- package/lib/umd-es6/synchronizers/synchronizer-ws-server.js +1 -0
- package/lib/umd-es6/synchronizers/synchronizer-ws-server.js.gz +0 -0
- package/lib/umd-es6/synchronizers.js +1 -0
- package/lib/umd-es6/synchronizers.js.gz +0 -0
- package/lib/umd-es6/tinybase.js +1 -1
- package/lib/umd-es6/tinybase.js.gz +0 -0
- package/lib/umd-es6/tools.js +1 -1
- package/lib/umd-es6/tools.js.gz +0 -0
- package/lib/umd-es6/ui-react-dom-debug.js +1 -1
- package/lib/umd-es6/ui-react-dom-debug.js.gz +0 -0
- package/lib/umd-es6/ui-react-dom.js +1 -1
- package/lib/umd-es6/ui-react-dom.js.gz +0 -0
- package/lib/umd-es6/ui-react.js +1 -1
- package/lib/umd-es6/ui-react.js.gz +0 -0
- package/package.json +68 -48
- package/readme.md +2 -2
package/lib/debug/tinybase.js
CHANGED
|
@@ -29,7 +29,11 @@ const VALUE = 'Value';
|
|
|
29
29
|
const VALUES = VALUE + 's';
|
|
30
30
|
const VALUE_IDS = VALUE + IDS;
|
|
31
31
|
const id = (key) => EMPTY_STRING + key;
|
|
32
|
+
const strStartsWith = (str, prefix) => str.startsWith(prefix);
|
|
33
|
+
const strEndsWith = (str, suffix) => str.endsWith(suffix);
|
|
34
|
+
const strCharCodeAt = (str, position) => str.charCodeAt(position);
|
|
32
35
|
|
|
36
|
+
const promise = Promise;
|
|
33
37
|
const mathMax = Math.max;
|
|
34
38
|
const mathMin = Math.min;
|
|
35
39
|
const isFiniteNumber = isFinite;
|
|
@@ -45,6 +49,7 @@ const slice = (arrayOrString, start, end) => arrayOrString.slice(start, end);
|
|
|
45
49
|
const size = (arrayOrString) => arrayOrString.length;
|
|
46
50
|
const test = (regex, subject) => regex.test(subject);
|
|
47
51
|
const getUndefined = () => void 0;
|
|
52
|
+
const promiseNew = (resolver) => new promise(resolver);
|
|
48
53
|
|
|
49
54
|
const arrayHas = (array, value) => array.includes(value);
|
|
50
55
|
const arrayEvery = (array, cb) => array.every(cb);
|
|
@@ -70,9 +75,8 @@ const arrayShift = (array) => array.shift();
|
|
|
70
75
|
|
|
71
76
|
const object = Object;
|
|
72
77
|
const getPrototypeOf = (obj) => object.getPrototypeOf(obj);
|
|
73
|
-
const
|
|
78
|
+
const objEntries = object.entries;
|
|
74
79
|
const objFrozen = object.isFrozen;
|
|
75
|
-
const objFreeze = object.freeze;
|
|
76
80
|
const isObject = (obj) =>
|
|
77
81
|
!isUndefined(obj) &&
|
|
78
82
|
ifNotUndefined(
|
|
@@ -80,18 +84,46 @@ const isObject = (obj) =>
|
|
|
80
84
|
(objPrototype) =>
|
|
81
85
|
objPrototype == object.prototype ||
|
|
82
86
|
isUndefined(getPrototypeOf(objPrototype)),
|
|
87
|
+
/* istanbul ignore next */
|
|
83
88
|
() => true,
|
|
84
89
|
);
|
|
85
|
-
const
|
|
86
|
-
const
|
|
90
|
+
const objIds = object.keys;
|
|
91
|
+
const objFreeze = object.freeze;
|
|
92
|
+
const objNew = (entries = []) => object.fromEntries(entries);
|
|
93
|
+
const objHas = (obj, id) => id in obj;
|
|
87
94
|
const objDel = (obj, id) => {
|
|
88
95
|
delete obj[id];
|
|
89
96
|
return obj;
|
|
90
97
|
};
|
|
91
|
-
const
|
|
92
|
-
|
|
98
|
+
const objForEach = (obj, cb) =>
|
|
99
|
+
arrayForEach(objEntries(obj), ([id, value]) => cb(value, id));
|
|
100
|
+
const objToArray = (obj, cb) =>
|
|
101
|
+
arrayMap(objEntries(obj), ([id, value]) => cb(value, id));
|
|
93
102
|
const objSize = (obj) => size(objIds(obj));
|
|
94
103
|
const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
|
|
104
|
+
const objEnsure = (obj, id, getDefaultValue) => {
|
|
105
|
+
if (!objHas(obj, id)) {
|
|
106
|
+
obj[id] = getDefaultValue();
|
|
107
|
+
}
|
|
108
|
+
return obj[id];
|
|
109
|
+
};
|
|
110
|
+
const objValidate = (obj, validateChild, onInvalidObj, emptyIsValid = 0) => {
|
|
111
|
+
if (
|
|
112
|
+
isUndefined(obj) ||
|
|
113
|
+
!isObject(obj) ||
|
|
114
|
+
(!emptyIsValid && objIsEmpty(obj)) ||
|
|
115
|
+
objFrozen(obj)
|
|
116
|
+
) {
|
|
117
|
+
onInvalidObj?.();
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
objToArray(obj, (child, id) => {
|
|
121
|
+
if (!validateChild(child, id)) {
|
|
122
|
+
objDel(obj, id);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
return emptyIsValid ? true : !objIsEmpty(obj);
|
|
126
|
+
};
|
|
95
127
|
|
|
96
128
|
const collSizeN = (collSizer) => (coll) =>
|
|
97
129
|
arrayReduce(collValues(coll), (total, coll2) => total + collSizer(coll2), 0);
|
|
@@ -115,35 +147,41 @@ const mapMap = (coll, cb) =>
|
|
|
115
147
|
arrayMap([...(coll?.entries() ?? [])], ([key, value]) => cb(value, key));
|
|
116
148
|
const mapSet = (map, key, value) =>
|
|
117
149
|
isUndefined(value) ? (collDel(map, key), map) : map?.set(key, value);
|
|
118
|
-
const mapEnsure = (map, key, getDefaultValue) => {
|
|
150
|
+
const mapEnsure = (map, key, getDefaultValue, hadExistingValue) => {
|
|
119
151
|
if (!collHas(map, key)) {
|
|
120
152
|
mapSet(map, key, getDefaultValue());
|
|
153
|
+
} else {
|
|
154
|
+
hadExistingValue?.(mapGet(map, key));
|
|
121
155
|
}
|
|
122
156
|
return mapGet(map, key);
|
|
123
157
|
};
|
|
124
158
|
const mapMatch = (map, obj, set, del = mapSet) => {
|
|
125
|
-
|
|
159
|
+
objToArray(obj, (value, id) => set(map, id, value));
|
|
126
160
|
mapForEach(map, (id) => (objHas(obj, id) ? 0 : del(map, id)));
|
|
127
161
|
return map;
|
|
128
162
|
};
|
|
129
|
-
const mapToObj = (map,
|
|
163
|
+
const mapToObj = (map, valueMapper, excludeMapValue, excludeObjValue) => {
|
|
130
164
|
const obj = {};
|
|
131
|
-
collForEach(map, (
|
|
132
|
-
|
|
133
|
-
|
|
165
|
+
collForEach(map, (mapValue, id) => {
|
|
166
|
+
if (!excludeMapValue?.(mapValue, id)) {
|
|
167
|
+
const objValue = valueMapper ? valueMapper(mapValue, id) : mapValue;
|
|
168
|
+
excludeObjValue?.(objValue) ? 0 : (obj[id] = objValue);
|
|
169
|
+
}
|
|
134
170
|
});
|
|
135
171
|
return obj;
|
|
136
172
|
};
|
|
137
|
-
const mapToObj2 = (map,
|
|
173
|
+
const mapToObj2 = (map, valueMapper, excludeMapValue) =>
|
|
138
174
|
mapToObj(
|
|
139
175
|
map,
|
|
140
|
-
(childMap) => mapToObj(childMap,
|
|
176
|
+
(childMap) => mapToObj(childMap, valueMapper, excludeMapValue),
|
|
177
|
+
collIsEmpty,
|
|
141
178
|
objIsEmpty,
|
|
142
179
|
);
|
|
143
|
-
const mapToObj3 = (map,
|
|
180
|
+
const mapToObj3 = (map, valueMapper, excludeMapValue) =>
|
|
144
181
|
mapToObj(
|
|
145
182
|
map,
|
|
146
|
-
(childMap) => mapToObj2(childMap,
|
|
183
|
+
(childMap) => mapToObj2(childMap, valueMapper, excludeMapValue),
|
|
184
|
+
collIsEmpty,
|
|
147
185
|
objIsEmpty,
|
|
148
186
|
);
|
|
149
187
|
const mapClone = (map, mapValue) => {
|
|
@@ -175,12 +213,15 @@ const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
|
|
|
175
213
|
},
|
|
176
214
|
);
|
|
177
215
|
|
|
178
|
-
const getCellOrValueType = (
|
|
179
|
-
const type = getTypeOf(
|
|
180
|
-
return isTypeStringOrBoolean(type) ||
|
|
216
|
+
const getCellOrValueType = (cellOrValue) => {
|
|
217
|
+
const type = getTypeOf(cellOrValue);
|
|
218
|
+
return isTypeStringOrBoolean(type) ||
|
|
219
|
+
(type == NUMBER && isFiniteNumber(cellOrValue))
|
|
181
220
|
? type
|
|
182
221
|
: void 0;
|
|
183
222
|
};
|
|
223
|
+
const isCellOrValueOrNullOrUndefined = (cellOrValue) =>
|
|
224
|
+
isUndefined(cellOrValue) || !isUndefined(getCellOrValueType(cellOrValue));
|
|
184
225
|
const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
|
|
185
226
|
isUndefined(cell)
|
|
186
227
|
? store.delCell(tableId, rowId, cellId, true)
|
|
@@ -356,13 +397,15 @@ const getRowCellFunction = (getRowCell, defaultCellValue) =>
|
|
|
356
397
|
isString(getRowCell)
|
|
357
398
|
? (getCell) => getCell(getRowCell)
|
|
358
399
|
: getRowCell ?? (() => defaultCellValue ?? EMPTY_STRING);
|
|
359
|
-
const getCreateFunction = (getFunction) => {
|
|
360
|
-
const
|
|
400
|
+
const getCreateFunction = (getFunction, initFunction) => {
|
|
401
|
+
const thingsByStore = /* @__PURE__ */ new WeakMap();
|
|
361
402
|
return (store) => {
|
|
362
|
-
if (!
|
|
363
|
-
|
|
403
|
+
if (!thingsByStore.has(store)) {
|
|
404
|
+
thingsByStore.set(store, getFunction(store));
|
|
364
405
|
}
|
|
365
|
-
|
|
406
|
+
const thing = thingsByStore.get(store);
|
|
407
|
+
initFunction?.(thing);
|
|
408
|
+
return thing;
|
|
366
409
|
};
|
|
367
410
|
};
|
|
368
411
|
|
|
@@ -450,241 +493,256 @@ const getListenerFunctions = (getThing) => {
|
|
|
450
493
|
return [addListener, callListeners, delListener, callListener];
|
|
451
494
|
};
|
|
452
495
|
|
|
453
|
-
const createCheckpoints = getCreateFunction(
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
collForEach(
|
|
476
|
-
collForEach(
|
|
477
|
-
|
|
496
|
+
const createCheckpoints = getCreateFunction(
|
|
497
|
+
(store) => {
|
|
498
|
+
let backwardIdsSize = 100;
|
|
499
|
+
let currentId;
|
|
500
|
+
let cellsDelta = mapNew();
|
|
501
|
+
let valuesDelta = mapNew();
|
|
502
|
+
let listening = 1;
|
|
503
|
+
let nextCheckpointId;
|
|
504
|
+
let checkpointsChanged;
|
|
505
|
+
const checkpointIdsListeners = mapNew();
|
|
506
|
+
const checkpointListeners = mapNew();
|
|
507
|
+
const [addListener, callListeners, delListenerImpl] = getListenerFunctions(
|
|
508
|
+
() => checkpoints,
|
|
509
|
+
);
|
|
510
|
+
const deltas = mapNew();
|
|
511
|
+
const labels = mapNew();
|
|
512
|
+
const backwardIds = [];
|
|
513
|
+
const forwardIds = [];
|
|
514
|
+
const updateStore = (oldOrNew, checkpointId) => {
|
|
515
|
+
listening = 0;
|
|
516
|
+
store.transaction(() => {
|
|
517
|
+
const [cellsDelta2, valuesDelta2] = mapGet(deltas, checkpointId);
|
|
518
|
+
collForEach(cellsDelta2, (table, tableId) =>
|
|
519
|
+
collForEach(table, (row, rowId) =>
|
|
520
|
+
collForEach(row, (oldNew, cellId) =>
|
|
521
|
+
setOrDelCell(store, tableId, rowId, cellId, oldNew[oldOrNew]),
|
|
522
|
+
),
|
|
478
523
|
),
|
|
479
|
-
)
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
524
|
+
);
|
|
525
|
+
collForEach(valuesDelta2, (oldNew, valueId) =>
|
|
526
|
+
setOrDelValue(store, valueId, oldNew[oldOrNew]),
|
|
527
|
+
);
|
|
528
|
+
});
|
|
529
|
+
listening = 1;
|
|
530
|
+
};
|
|
531
|
+
const clearCheckpointId = (checkpointId) => {
|
|
532
|
+
mapSet(deltas, checkpointId);
|
|
533
|
+
mapSet(labels, checkpointId);
|
|
534
|
+
callListeners(checkpointListeners, [checkpointId]);
|
|
535
|
+
};
|
|
536
|
+
const clearCheckpointIds = (checkpointIds, to) =>
|
|
537
|
+
arrayForEach(
|
|
538
|
+
arrayClear(checkpointIds, to ?? size(checkpointIds)),
|
|
539
|
+
clearCheckpointId,
|
|
483
540
|
);
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
);
|
|
497
|
-
const trimBackwardsIds = () =>
|
|
498
|
-
clearCheckpointIds(backwardIds, size(backwardIds) - backwardIdsSize);
|
|
499
|
-
const storeChanged = () =>
|
|
500
|
-
ifNotUndefined(currentId, () => {
|
|
501
|
-
arrayPush(backwardIds, currentId);
|
|
502
|
-
trimBackwardsIds();
|
|
503
|
-
clearCheckpointIds(forwardIds);
|
|
504
|
-
currentId = void 0;
|
|
541
|
+
const trimBackwardsIds = () =>
|
|
542
|
+
clearCheckpointIds(backwardIds, size(backwardIds) - backwardIdsSize);
|
|
543
|
+
const storeChanged = () =>
|
|
544
|
+
ifNotUndefined(currentId, () => {
|
|
545
|
+
arrayPush(backwardIds, currentId);
|
|
546
|
+
trimBackwardsIds();
|
|
547
|
+
clearCheckpointIds(forwardIds);
|
|
548
|
+
currentId = void 0;
|
|
549
|
+
checkpointsChanged = 1;
|
|
550
|
+
});
|
|
551
|
+
const storeUnchanged = () => {
|
|
552
|
+
currentId = arrayPop(backwardIds);
|
|
505
553
|
checkpointsChanged = 1;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
storeChanged();
|
|
518
|
-
const table = mapEnsure(cellsDelta, tableId, mapNew);
|
|
519
|
-
const row = mapEnsure(table, rowId, mapNew);
|
|
520
|
-
const oldNew = mapEnsure(row, cellId, () => [oldCell, void 0]);
|
|
521
|
-
oldNew[1] = newCell;
|
|
522
|
-
if (
|
|
523
|
-
oldNew[0] === newCell &&
|
|
524
|
-
collIsEmpty(mapSet(row, cellId)) &&
|
|
525
|
-
collIsEmpty(mapSet(table, rowId)) &&
|
|
526
|
-
collIsEmpty(mapSet(cellsDelta, tableId))
|
|
527
|
-
) {
|
|
528
|
-
storeUnchanged();
|
|
529
|
-
}
|
|
530
|
-
callListenersIfChanged();
|
|
554
|
+
};
|
|
555
|
+
let cellListenerId;
|
|
556
|
+
let valueListenerId;
|
|
557
|
+
const addCheckpointImpl = (label = EMPTY_STRING) => {
|
|
558
|
+
if (isUndefined(currentId)) {
|
|
559
|
+
currentId = EMPTY_STRING + nextCheckpointId++;
|
|
560
|
+
mapSet(deltas, currentId, [cellsDelta, valuesDelta]);
|
|
561
|
+
setCheckpoint(currentId, label);
|
|
562
|
+
cellsDelta = mapNew();
|
|
563
|
+
valuesDelta = mapNew();
|
|
564
|
+
checkpointsChanged = 1;
|
|
531
565
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
oldValue,
|
|
541
|
-
void 0,
|
|
542
|
-
]);
|
|
543
|
-
oldNew[1] = newValue;
|
|
544
|
-
if (
|
|
545
|
-
oldNew[0] === newValue &&
|
|
546
|
-
collIsEmpty(mapSet(valuesDelta, valueId))
|
|
547
|
-
) {
|
|
548
|
-
storeUnchanged();
|
|
549
|
-
}
|
|
550
|
-
callListenersIfChanged();
|
|
566
|
+
return currentId;
|
|
567
|
+
};
|
|
568
|
+
const goBackwardImpl = () => {
|
|
569
|
+
if (!arrayIsEmpty(backwardIds)) {
|
|
570
|
+
arrayUnshift(forwardIds, addCheckpointImpl());
|
|
571
|
+
updateStore(0, currentId);
|
|
572
|
+
currentId = arrayPop(backwardIds);
|
|
573
|
+
checkpointsChanged = 1;
|
|
551
574
|
}
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
callListenersIfChanged();
|
|
630
|
-
return checkpoints;
|
|
631
|
-
};
|
|
632
|
-
const addCheckpointIdsListener = (listener) =>
|
|
633
|
-
addListener(listener, checkpointIdsListeners);
|
|
634
|
-
const addCheckpointListener = (checkpointId, listener) =>
|
|
635
|
-
addListener(listener, checkpointListeners, [checkpointId]);
|
|
636
|
-
const delListener = (listenerId) => {
|
|
637
|
-
delListenerImpl(listenerId);
|
|
638
|
-
return checkpoints;
|
|
639
|
-
};
|
|
640
|
-
const clear = () => {
|
|
641
|
-
clearCheckpointIds(backwardIds);
|
|
642
|
-
clearCheckpointIds(forwardIds);
|
|
643
|
-
if (!isUndefined(currentId)) {
|
|
644
|
-
clearCheckpointId(currentId);
|
|
645
|
-
}
|
|
646
|
-
currentId = void 0;
|
|
647
|
-
nextCheckpointId = 0;
|
|
648
|
-
addCheckpoint();
|
|
649
|
-
return checkpoints;
|
|
650
|
-
};
|
|
651
|
-
const clearForward = () => {
|
|
652
|
-
if (!arrayIsEmpty(forwardIds)) {
|
|
575
|
+
};
|
|
576
|
+
const goForwardImpl = () => {
|
|
577
|
+
if (!arrayIsEmpty(forwardIds)) {
|
|
578
|
+
arrayPush(backwardIds, currentId);
|
|
579
|
+
currentId = arrayShift(forwardIds);
|
|
580
|
+
updateStore(1, currentId);
|
|
581
|
+
checkpointsChanged = 1;
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
const callListenersIfChanged = () => {
|
|
585
|
+
if (checkpointsChanged) {
|
|
586
|
+
callListeners(checkpointIdsListeners);
|
|
587
|
+
checkpointsChanged = 0;
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
const setSize = (size2) => {
|
|
591
|
+
backwardIdsSize = size2;
|
|
592
|
+
trimBackwardsIds();
|
|
593
|
+
return checkpoints;
|
|
594
|
+
};
|
|
595
|
+
const addCheckpoint = (label) => {
|
|
596
|
+
const id = addCheckpointImpl(label);
|
|
597
|
+
callListenersIfChanged();
|
|
598
|
+
return id;
|
|
599
|
+
};
|
|
600
|
+
const setCheckpoint = (checkpointId, label) => {
|
|
601
|
+
if (
|
|
602
|
+
hasCheckpoint(checkpointId) &&
|
|
603
|
+
mapGet(labels, checkpointId) !== label
|
|
604
|
+
) {
|
|
605
|
+
mapSet(labels, checkpointId, label);
|
|
606
|
+
callListeners(checkpointListeners, [checkpointId]);
|
|
607
|
+
}
|
|
608
|
+
return checkpoints;
|
|
609
|
+
};
|
|
610
|
+
const getStore = () => store;
|
|
611
|
+
const getCheckpointIds = () => [
|
|
612
|
+
[...backwardIds],
|
|
613
|
+
currentId,
|
|
614
|
+
[...forwardIds],
|
|
615
|
+
];
|
|
616
|
+
const forEachCheckpoint = (checkpointCallback) =>
|
|
617
|
+
mapForEach(labels, checkpointCallback);
|
|
618
|
+
const hasCheckpoint = (checkpointId) => collHas(deltas, checkpointId);
|
|
619
|
+
const getCheckpoint = (checkpointId) => mapGet(labels, checkpointId);
|
|
620
|
+
const goBackward = () => {
|
|
621
|
+
goBackwardImpl();
|
|
622
|
+
callListenersIfChanged();
|
|
623
|
+
return checkpoints;
|
|
624
|
+
};
|
|
625
|
+
const goForward = () => {
|
|
626
|
+
goForwardImpl();
|
|
627
|
+
callListenersIfChanged();
|
|
628
|
+
return checkpoints;
|
|
629
|
+
};
|
|
630
|
+
const goTo = (checkpointId) => {
|
|
631
|
+
const action = arrayHas(backwardIds, checkpointId)
|
|
632
|
+
? goBackwardImpl
|
|
633
|
+
: arrayHas(forwardIds, checkpointId)
|
|
634
|
+
? goForwardImpl
|
|
635
|
+
: null;
|
|
636
|
+
while (!isUndefined(action) && checkpointId != currentId) {
|
|
637
|
+
action();
|
|
638
|
+
}
|
|
639
|
+
callListenersIfChanged();
|
|
640
|
+
return checkpoints;
|
|
641
|
+
};
|
|
642
|
+
const addCheckpointIdsListener = (listener) =>
|
|
643
|
+
addListener(listener, checkpointIdsListeners);
|
|
644
|
+
const addCheckpointListener = (checkpointId, listener) =>
|
|
645
|
+
addListener(listener, checkpointListeners, [checkpointId]);
|
|
646
|
+
const delListener = (listenerId) => {
|
|
647
|
+
delListenerImpl(listenerId);
|
|
648
|
+
return checkpoints;
|
|
649
|
+
};
|
|
650
|
+
const clear = () => {
|
|
651
|
+
clearCheckpointIds(backwardIds);
|
|
653
652
|
clearCheckpointIds(forwardIds);
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
653
|
+
if (!isUndefined(currentId)) {
|
|
654
|
+
clearCheckpointId(currentId);
|
|
655
|
+
}
|
|
656
|
+
currentId = void 0;
|
|
657
|
+
nextCheckpointId = 0;
|
|
658
|
+
addCheckpoint();
|
|
659
|
+
return checkpoints;
|
|
660
|
+
};
|
|
661
|
+
const clearForward = () => {
|
|
662
|
+
if (!arrayIsEmpty(forwardIds)) {
|
|
663
|
+
clearCheckpointIds(forwardIds);
|
|
664
|
+
callListeners(checkpointIdsListeners);
|
|
665
|
+
}
|
|
666
|
+
return checkpoints;
|
|
667
|
+
};
|
|
668
|
+
const destroy = () => {
|
|
669
|
+
store.delListener(cellListenerId);
|
|
670
|
+
store.delListener(valueListenerId);
|
|
671
|
+
};
|
|
672
|
+
const getListenerStats = () => ({
|
|
673
|
+
checkpointIds: collSize2(checkpointIdsListeners),
|
|
674
|
+
checkpoint: collSize2(checkpointListeners),
|
|
675
|
+
});
|
|
676
|
+
const _registerListeners = () => {
|
|
677
|
+
cellListenerId = store.addCellListener(
|
|
678
|
+
null,
|
|
679
|
+
null,
|
|
680
|
+
null,
|
|
681
|
+
(_store, tableId, rowId, cellId, newCell, oldCell) => {
|
|
682
|
+
if (listening) {
|
|
683
|
+
storeChanged();
|
|
684
|
+
const table = mapEnsure(cellsDelta, tableId, mapNew);
|
|
685
|
+
const row = mapEnsure(table, rowId, mapNew);
|
|
686
|
+
const oldNew = mapEnsure(row, cellId, () => [oldCell, void 0]);
|
|
687
|
+
oldNew[1] = newCell;
|
|
688
|
+
if (
|
|
689
|
+
oldNew[0] === newCell &&
|
|
690
|
+
collIsEmpty(mapSet(row, cellId)) &&
|
|
691
|
+
collIsEmpty(mapSet(table, rowId)) &&
|
|
692
|
+
collIsEmpty(mapSet(cellsDelta, tableId))
|
|
693
|
+
) {
|
|
694
|
+
storeUnchanged();
|
|
695
|
+
}
|
|
696
|
+
callListenersIfChanged();
|
|
697
|
+
}
|
|
698
|
+
},
|
|
699
|
+
);
|
|
700
|
+
valueListenerId = store.addValueListener(
|
|
701
|
+
null,
|
|
702
|
+
(_store, valueId, newValue, oldValue) => {
|
|
703
|
+
if (listening) {
|
|
704
|
+
storeChanged();
|
|
705
|
+
const oldNew = mapEnsure(valuesDelta, valueId, () => [
|
|
706
|
+
oldValue,
|
|
707
|
+
void 0,
|
|
708
|
+
]);
|
|
709
|
+
oldNew[1] = newValue;
|
|
710
|
+
if (
|
|
711
|
+
oldNew[0] === newValue &&
|
|
712
|
+
collIsEmpty(mapSet(valuesDelta, valueId))
|
|
713
|
+
) {
|
|
714
|
+
storeUnchanged();
|
|
715
|
+
}
|
|
716
|
+
callListenersIfChanged();
|
|
717
|
+
}
|
|
718
|
+
},
|
|
719
|
+
);
|
|
720
|
+
};
|
|
721
|
+
const checkpoints = {
|
|
722
|
+
setSize,
|
|
723
|
+
addCheckpoint,
|
|
724
|
+
setCheckpoint,
|
|
725
|
+
getStore,
|
|
726
|
+
getCheckpointIds,
|
|
727
|
+
forEachCheckpoint,
|
|
728
|
+
hasCheckpoint,
|
|
729
|
+
getCheckpoint,
|
|
730
|
+
goBackward,
|
|
731
|
+
goForward,
|
|
732
|
+
goTo,
|
|
733
|
+
addCheckpointIdsListener,
|
|
734
|
+
addCheckpointListener,
|
|
735
|
+
delListener,
|
|
736
|
+
clear,
|
|
737
|
+
clearForward,
|
|
738
|
+
destroy,
|
|
739
|
+
getListenerStats,
|
|
740
|
+
_registerListeners,
|
|
741
|
+
};
|
|
742
|
+
return objFreeze(checkpoints.clear());
|
|
743
|
+
},
|
|
744
|
+
(checkpoints) => checkpoints._registerListeners(),
|
|
745
|
+
);
|
|
688
746
|
|
|
689
747
|
const defaultSorter = (sortKey1, sortKey2) =>
|
|
690
748
|
(sortKey1 ?? 0) < (sortKey2 ?? 0) ? -1 : 1;
|
|
@@ -1060,6 +1118,24 @@ const createMetrics = getCreateFunction((store) => {
|
|
|
1060
1118
|
|
|
1061
1119
|
const scheduleRunning = mapNew();
|
|
1062
1120
|
const scheduleActions = mapNew();
|
|
1121
|
+
const getStoreFunctions = (supportsMergeableStore, store) =>
|
|
1122
|
+
!supportsMergeableStore || isUndefined(store.getMergeableContent)
|
|
1123
|
+
? [
|
|
1124
|
+
0,
|
|
1125
|
+
store.getContent,
|
|
1126
|
+
store.getTransactionChanges,
|
|
1127
|
+
([changedTables, changedValues]) =>
|
|
1128
|
+
!objIsEmpty(changedTables) || !objIsEmpty(changedValues),
|
|
1129
|
+
store.setContent,
|
|
1130
|
+
]
|
|
1131
|
+
: [
|
|
1132
|
+
1,
|
|
1133
|
+
store.getMergeableContent,
|
|
1134
|
+
store.getTransactionMergeableChanges,
|
|
1135
|
+
([[changedTables], [changedValues]]) =>
|
|
1136
|
+
!objIsEmpty(changedTables) || !objIsEmpty(changedValues),
|
|
1137
|
+
store.setDefaultContent,
|
|
1138
|
+
];
|
|
1063
1139
|
const createCustomPersister = (
|
|
1064
1140
|
store,
|
|
1065
1141
|
getPersisted,
|
|
@@ -1067,18 +1143,25 @@ const createCustomPersister = (
|
|
|
1067
1143
|
addPersisterListener,
|
|
1068
1144
|
delPersisterListener,
|
|
1069
1145
|
onIgnoredError,
|
|
1070
|
-
|
|
1146
|
+
supportsMergeableStore,
|
|
1147
|
+
extra = {},
|
|
1071
1148
|
scheduleId = [],
|
|
1072
1149
|
) => {
|
|
1073
|
-
let listenerId;
|
|
1074
1150
|
let loadSave = 0;
|
|
1075
1151
|
let loads = 0;
|
|
1076
1152
|
let saves = 0;
|
|
1077
|
-
let listening = 0;
|
|
1078
1153
|
let action;
|
|
1079
|
-
let
|
|
1154
|
+
let autoLoadHandle;
|
|
1155
|
+
let autoSaveListenerId;
|
|
1080
1156
|
mapEnsure(scheduleRunning, scheduleId, () => 0);
|
|
1081
1157
|
mapEnsure(scheduleActions, scheduleId, () => []);
|
|
1158
|
+
const [
|
|
1159
|
+
isMergeableStore,
|
|
1160
|
+
getContent,
|
|
1161
|
+
getChanges,
|
|
1162
|
+
hasChanges,
|
|
1163
|
+
setDefaultContent,
|
|
1164
|
+
] = getStoreFunctions(supportsMergeableStore, store);
|
|
1082
1165
|
const run = async () => {
|
|
1083
1166
|
/* istanbul ignore else */
|
|
1084
1167
|
if (!mapGet(scheduleRunning, scheduleId)) {
|
|
@@ -1110,48 +1193,54 @@ const createCustomPersister = (
|
|
|
1110
1193
|
}
|
|
1111
1194
|
return persister;
|
|
1112
1195
|
};
|
|
1196
|
+
const setContentOrChanges = (contentOrChanges) => {
|
|
1197
|
+
(isMergeableStore && isArray(contentOrChanges?.[0])
|
|
1198
|
+
? contentOrChanges?.[2] === 1
|
|
1199
|
+
? store.applyMergeableChanges
|
|
1200
|
+
: store.setMergeableContent
|
|
1201
|
+
: contentOrChanges?.[2] === 1
|
|
1202
|
+
? store.applyChanges
|
|
1203
|
+
: store.setContent)(contentOrChanges);
|
|
1204
|
+
};
|
|
1113
1205
|
const persister = {
|
|
1114
|
-
load: async (
|
|
1206
|
+
load: async (initialContent) =>
|
|
1115
1207
|
await loadLock(async () => {
|
|
1116
1208
|
try {
|
|
1117
|
-
|
|
1118
|
-
} catch {
|
|
1119
|
-
|
|
1209
|
+
setContentOrChanges(await getPersisted());
|
|
1210
|
+
} catch (error) {
|
|
1211
|
+
onIgnoredError?.(error);
|
|
1212
|
+
if (initialContent) {
|
|
1213
|
+
setDefaultContent(initialContent);
|
|
1214
|
+
}
|
|
1120
1215
|
}
|
|
1121
1216
|
}),
|
|
1122
|
-
startAutoLoad: async (
|
|
1123
|
-
persister.stopAutoLoad();
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
)
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
store.setContent(getContent?.() ?? (await getPersisted()));
|
|
1137
|
-
} catch (error) {
|
|
1138
|
-
onIgnoredError?.(error);
|
|
1139
|
-
}
|
|
1140
|
-
});
|
|
1141
|
-
}
|
|
1217
|
+
startAutoLoad: async (initialContent) => {
|
|
1218
|
+
await persister.stopAutoLoad().load(initialContent);
|
|
1219
|
+
autoLoadHandle = addPersisterListener(
|
|
1220
|
+
async (getContent2, getChanges2) => {
|
|
1221
|
+
const changes = getChanges2?.();
|
|
1222
|
+
await loadLock(async () => {
|
|
1223
|
+
try {
|
|
1224
|
+
setContentOrChanges(
|
|
1225
|
+
changes ?? getContent2?.() ?? (await getPersisted()),
|
|
1226
|
+
);
|
|
1227
|
+
} catch (error) {
|
|
1228
|
+
onIgnoredError?.(error);
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1142
1231
|
},
|
|
1143
1232
|
);
|
|
1144
1233
|
return persister;
|
|
1145
1234
|
},
|
|
1146
1235
|
stopAutoLoad: () => {
|
|
1147
|
-
if (
|
|
1148
|
-
delPersisterListener(
|
|
1149
|
-
|
|
1150
|
-
listening = 0;
|
|
1236
|
+
if (autoLoadHandle) {
|
|
1237
|
+
delPersisterListener(autoLoadHandle);
|
|
1238
|
+
autoLoadHandle = void 0;
|
|
1151
1239
|
}
|
|
1152
1240
|
return persister;
|
|
1153
1241
|
},
|
|
1154
|
-
|
|
1242
|
+
isAutoLoading: () => !isUndefined(autoLoadHandle),
|
|
1243
|
+
save: async (getChanges2) => {
|
|
1155
1244
|
/* istanbul ignore else */
|
|
1156
1245
|
if (loadSave != 1) {
|
|
1157
1246
|
loadSave = 2;
|
|
@@ -1160,7 +1249,7 @@ const createCustomPersister = (
|
|
|
1160
1249
|
}
|
|
1161
1250
|
await persister.schedule(async () => {
|
|
1162
1251
|
try {
|
|
1163
|
-
await setPersisted(
|
|
1252
|
+
await setPersisted(getContent, getChanges2);
|
|
1164
1253
|
} catch (error) {
|
|
1165
1254
|
/* istanbul ignore next */
|
|
1166
1255
|
onIgnoredError?.(error);
|
|
@@ -1172,21 +1261,20 @@ const createCustomPersister = (
|
|
|
1172
1261
|
},
|
|
1173
1262
|
startAutoSave: async () => {
|
|
1174
1263
|
await persister.stopAutoSave().save();
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
},
|
|
1182
|
-
);
|
|
1264
|
+
autoSaveListenerId = store.addDidFinishTransactionListener(() => {
|
|
1265
|
+
const changes = getChanges();
|
|
1266
|
+
if (hasChanges(changes)) {
|
|
1267
|
+
persister.save(() => changes);
|
|
1268
|
+
}
|
|
1269
|
+
});
|
|
1183
1270
|
return persister;
|
|
1184
1271
|
},
|
|
1185
1272
|
stopAutoSave: () => {
|
|
1186
|
-
ifNotUndefined(
|
|
1187
|
-
|
|
1273
|
+
ifNotUndefined(autoSaveListenerId, store.delListener);
|
|
1274
|
+
autoSaveListenerId = void 0;
|
|
1188
1275
|
return persister;
|
|
1189
1276
|
},
|
|
1277
|
+
isAutoSaving: () => !isUndefined(autoSaveListenerId),
|
|
1190
1278
|
schedule: async (...actions) => {
|
|
1191
1279
|
arrayPush(mapGet(scheduleActions, scheduleId), ...actions);
|
|
1192
1280
|
await run();
|
|
@@ -1195,13 +1283,325 @@ const createCustomPersister = (
|
|
|
1195
1283
|
getStore: () => store,
|
|
1196
1284
|
destroy: () => persister.stopAutoLoad().stopAutoSave(),
|
|
1197
1285
|
getStats: () => ({loads, saves}),
|
|
1286
|
+
...extra,
|
|
1198
1287
|
};
|
|
1199
|
-
if (getThing) {
|
|
1200
|
-
persister[getThing] = () => thing;
|
|
1201
|
-
}
|
|
1202
1288
|
return objFreeze(persister);
|
|
1203
1289
|
};
|
|
1204
1290
|
|
|
1291
|
+
const textEncoder = new globalThis.TextEncoder();
|
|
1292
|
+
const getHash = (value) => {
|
|
1293
|
+
let hash = 2166136261;
|
|
1294
|
+
arrayForEach(textEncoder.encode(value), (char) => {
|
|
1295
|
+
hash ^= char;
|
|
1296
|
+
hash +=
|
|
1297
|
+
(hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
1298
|
+
});
|
|
1299
|
+
return hash >>> 0;
|
|
1300
|
+
};
|
|
1301
|
+
|
|
1302
|
+
const stampCloneWithHash = ([value, time, hash]) => [value, time, hash];
|
|
1303
|
+
const stampCloneWithoutHash = ([value, time]) => newStamp(value, time);
|
|
1304
|
+
const newStamp = (value, time) => (time ? [value, time] : [value]);
|
|
1305
|
+
const getStampHash = (stamp) => stamp[2];
|
|
1306
|
+
const hashIdAndHash = (id, hash) => getHash(id + ':' + hash);
|
|
1307
|
+
const replaceTimeHash = (oldTime, newTime) =>
|
|
1308
|
+
newTime > oldTime ? (oldTime ? getHash(oldTime) : 0) ^ getHash(newTime) : 0;
|
|
1309
|
+
const getLatestTime = (time1, time2) =>
|
|
1310
|
+
((time1 ?? '') > (time2 ?? '') ? time1 : time2) ?? '';
|
|
1311
|
+
const stampUpdate = (stamp, hash, time) => {
|
|
1312
|
+
stamp[2] = hash >>> 0;
|
|
1313
|
+
if (time > stamp[1]) {
|
|
1314
|
+
stamp[1] = time;
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
const stampNewObj = (time = EMPTY_STRING) => newStamp(objNew(), time);
|
|
1318
|
+
const stampNewMap = (time = EMPTY_STRING) => [mapNew(), time, 0];
|
|
1319
|
+
const stampMapToObjWithHash = (
|
|
1320
|
+
[map, time, hash],
|
|
1321
|
+
mapper = stampCloneWithHash,
|
|
1322
|
+
) => [mapToObj(map, mapper), time, hash];
|
|
1323
|
+
const stampMapToObjWithoutHash = (
|
|
1324
|
+
[map, time],
|
|
1325
|
+
mapper = stampCloneWithoutHash,
|
|
1326
|
+
) => newStamp(mapToObj(map, mapper), time);
|
|
1327
|
+
const stampValidate = (stamp, validateThing) =>
|
|
1328
|
+
isArray(stamp) &&
|
|
1329
|
+
size(stamp) == 3 &&
|
|
1330
|
+
isString(stamp[1]) &&
|
|
1331
|
+
getTypeOf(stamp[2]) == NUMBER &&
|
|
1332
|
+
isFiniteNumber(stamp[2]) &&
|
|
1333
|
+
validateThing(stamp[0]);
|
|
1334
|
+
|
|
1335
|
+
const MASK6 = 63;
|
|
1336
|
+
const SHIFT36 = 2 ** 36;
|
|
1337
|
+
const SHIFT30 = 2 ** 30;
|
|
1338
|
+
const SHIFT24 = 2 ** 24;
|
|
1339
|
+
const SHIFT18 = 2 ** 18;
|
|
1340
|
+
const SHIFT12 = 2 ** 12;
|
|
1341
|
+
const SHIFT6 = 2 ** 6;
|
|
1342
|
+
const toB64 = (num) => String.fromCharCode(48 + (num & MASK6));
|
|
1343
|
+
const fromB64 = (str, pos) => strCharCodeAt(str, pos) - 48;
|
|
1344
|
+
const encodeHlc = (logicalTime42, counter24, clientHash30) =>
|
|
1345
|
+
toB64(logicalTime42 / SHIFT36) +
|
|
1346
|
+
toB64(logicalTime42 / SHIFT30) +
|
|
1347
|
+
toB64(logicalTime42 / SHIFT24) +
|
|
1348
|
+
toB64(logicalTime42 / SHIFT18) +
|
|
1349
|
+
toB64(logicalTime42 / SHIFT12) +
|
|
1350
|
+
toB64(logicalTime42 / SHIFT6) +
|
|
1351
|
+
toB64(logicalTime42) +
|
|
1352
|
+
toB64(counter24 / SHIFT18) +
|
|
1353
|
+
toB64(counter24 / SHIFT12) +
|
|
1354
|
+
toB64(counter24 / SHIFT6) +
|
|
1355
|
+
toB64(counter24) +
|
|
1356
|
+
toB64(clientHash30 / SHIFT24) +
|
|
1357
|
+
toB64(clientHash30 / SHIFT18) +
|
|
1358
|
+
toB64(clientHash30 / SHIFT12) +
|
|
1359
|
+
toB64(clientHash30 / SHIFT6) +
|
|
1360
|
+
toB64(clientHash30);
|
|
1361
|
+
const decodeHlc = (hlc16) => [
|
|
1362
|
+
fromB64(hlc16, 0) * SHIFT36 +
|
|
1363
|
+
fromB64(hlc16, 1) * SHIFT30 +
|
|
1364
|
+
fromB64(hlc16, 2) * SHIFT24 +
|
|
1365
|
+
fromB64(hlc16, 3) * SHIFT18 +
|
|
1366
|
+
fromB64(hlc16, 4) * SHIFT12 +
|
|
1367
|
+
fromB64(hlc16, 5) * SHIFT6 +
|
|
1368
|
+
fromB64(hlc16, 6),
|
|
1369
|
+
fromB64(hlc16, 7) * SHIFT18 +
|
|
1370
|
+
fromB64(hlc16, 8) * SHIFT12 +
|
|
1371
|
+
fromB64(hlc16, 9) * SHIFT6 +
|
|
1372
|
+
fromB64(hlc16, 10),
|
|
1373
|
+
fromB64(hlc16, 11) * SHIFT24 +
|
|
1374
|
+
fromB64(hlc16, 12) * SHIFT18 +
|
|
1375
|
+
fromB64(hlc16, 13) * SHIFT12 +
|
|
1376
|
+
fromB64(hlc16, 14) * SHIFT6 +
|
|
1377
|
+
fromB64(hlc16, 15),
|
|
1378
|
+
];
|
|
1379
|
+
const getHlcFunctions = (uniqueId) => {
|
|
1380
|
+
let logicalTime = 0;
|
|
1381
|
+
let lastCounter = -1;
|
|
1382
|
+
const uniqueIdHash = getHash(uniqueId);
|
|
1383
|
+
const getHlc = () => {
|
|
1384
|
+
seenHlc();
|
|
1385
|
+
return encodeHlc(logicalTime, ++lastCounter, uniqueIdHash);
|
|
1386
|
+
};
|
|
1387
|
+
const seenHlc = (hlc) => {
|
|
1388
|
+
const previousLogicalTime = logicalTime;
|
|
1389
|
+
const [remoteLogicalTime, remoteCounter] =
|
|
1390
|
+
isUndefined(hlc) || hlc == '' ? [0, 0] : decodeHlc(hlc);
|
|
1391
|
+
logicalTime = mathMax(
|
|
1392
|
+
previousLogicalTime,
|
|
1393
|
+
remoteLogicalTime,
|
|
1394
|
+
globalThis.HLC_TIME ?? Date.now(),
|
|
1395
|
+
);
|
|
1396
|
+
lastCounter =
|
|
1397
|
+
logicalTime == previousLogicalTime
|
|
1398
|
+
? logicalTime == remoteLogicalTime
|
|
1399
|
+
? mathMax(lastCounter, remoteCounter)
|
|
1400
|
+
: lastCounter
|
|
1401
|
+
: logicalTime == remoteLogicalTime
|
|
1402
|
+
? remoteCounter
|
|
1403
|
+
: -1;
|
|
1404
|
+
};
|
|
1405
|
+
return [getHlc, seenHlc];
|
|
1406
|
+
};
|
|
1407
|
+
|
|
1408
|
+
const RESPONSE = 0;
|
|
1409
|
+
const GET_CONTENT_HASHES = 1;
|
|
1410
|
+
const CONTENT_HASHES = 2;
|
|
1411
|
+
const CONTENT_DIFF = 3;
|
|
1412
|
+
const GET_TABLE_DIFF = 4;
|
|
1413
|
+
const GET_ROW_DIFF = 5;
|
|
1414
|
+
const GET_CELL_DIFF = 6;
|
|
1415
|
+
const GET_VALUE_DIFF = 7;
|
|
1416
|
+
const createCustomSynchronizer = (
|
|
1417
|
+
store,
|
|
1418
|
+
send,
|
|
1419
|
+
onReceive,
|
|
1420
|
+
destroyImpl,
|
|
1421
|
+
requestTimeoutSeconds,
|
|
1422
|
+
onIgnoredError,
|
|
1423
|
+
extra = {},
|
|
1424
|
+
) => {
|
|
1425
|
+
let persisterListener;
|
|
1426
|
+
let sends = 0;
|
|
1427
|
+
let receives = 0;
|
|
1428
|
+
const [getHlc] = getHlcFunctions(store.getId());
|
|
1429
|
+
const pendingRequests = mapNew();
|
|
1430
|
+
onReceive((fromClientId, requestId, messageType, messageBody) => {
|
|
1431
|
+
{
|
|
1432
|
+
receives++;
|
|
1433
|
+
}
|
|
1434
|
+
if (messageType == RESPONSE) {
|
|
1435
|
+
ifNotUndefined(
|
|
1436
|
+
mapGet(pendingRequests, requestId),
|
|
1437
|
+
([toClientId, handleResponse]) =>
|
|
1438
|
+
isUndefined(toClientId) || toClientId == fromClientId
|
|
1439
|
+
? handleResponse(messageBody, fromClientId)
|
|
1440
|
+
: /* istanbul ignore next */
|
|
1441
|
+
0,
|
|
1442
|
+
);
|
|
1443
|
+
} else if (messageType == CONTENT_HASHES && persister.isAutoLoading()) {
|
|
1444
|
+
getChangesFromOtherStore(fromClientId, messageBody).then((changes) => {
|
|
1445
|
+
persisterListener?.(void 0, () => changes);
|
|
1446
|
+
});
|
|
1447
|
+
} else if (messageType == CONTENT_DIFF && persister.isAutoLoading()) {
|
|
1448
|
+
persisterListener?.(void 0, () => messageBody);
|
|
1449
|
+
} else {
|
|
1450
|
+
ifNotUndefined(
|
|
1451
|
+
messageType == GET_CONTENT_HASHES && persister.isAutoSaving()
|
|
1452
|
+
? store.getMergeableContentHashes()
|
|
1453
|
+
: messageType == GET_TABLE_DIFF
|
|
1454
|
+
? store.getMergeableTableDiff(messageBody)
|
|
1455
|
+
: messageType == GET_ROW_DIFF
|
|
1456
|
+
? store.getMergeableRowDiff(messageBody)
|
|
1457
|
+
: messageType == GET_CELL_DIFF
|
|
1458
|
+
? store.getMergeableCellDiff(messageBody)
|
|
1459
|
+
: messageType == GET_VALUE_DIFF
|
|
1460
|
+
? store.getMergeableValueDiff(messageBody)
|
|
1461
|
+
: void 0,
|
|
1462
|
+
(response) => {
|
|
1463
|
+
{
|
|
1464
|
+
sends++;
|
|
1465
|
+
}
|
|
1466
|
+
send(fromClientId, requestId, RESPONSE, response);
|
|
1467
|
+
},
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
});
|
|
1471
|
+
const request = async (toClientId, messageType, messageBody = EMPTY_STRING) =>
|
|
1472
|
+
promiseNew((resolve, reject) => {
|
|
1473
|
+
const requestId = getHlc();
|
|
1474
|
+
const timeout = setTimeout(() => {
|
|
1475
|
+
collDel(pendingRequests, requestId);
|
|
1476
|
+
reject(
|
|
1477
|
+
`No response from ${toClientId ?? 'anyone'} to '${messageType}'`,
|
|
1478
|
+
);
|
|
1479
|
+
}, requestTimeoutSeconds * 1e3);
|
|
1480
|
+
mapSet(pendingRequests, requestId, [
|
|
1481
|
+
toClientId,
|
|
1482
|
+
(response, fromClientId) => {
|
|
1483
|
+
clearTimeout(timeout);
|
|
1484
|
+
collDel(pendingRequests, requestId);
|
|
1485
|
+
resolve([response, fromClientId]);
|
|
1486
|
+
},
|
|
1487
|
+
]);
|
|
1488
|
+
{
|
|
1489
|
+
sends++;
|
|
1490
|
+
}
|
|
1491
|
+
send(toClientId, requestId, messageType, messageBody);
|
|
1492
|
+
});
|
|
1493
|
+
const mergeTablesStamps = (tablesStamp, [tableStamps2, tablesTime2]) => {
|
|
1494
|
+
objForEach(tableStamps2, ([rowStamps2, tableTime2], tableId) => {
|
|
1495
|
+
const tableStamp = objEnsure(tablesStamp[0], tableId, stampNewObj);
|
|
1496
|
+
objForEach(rowStamps2, ([cellStamps2, rowTime2], rowId) => {
|
|
1497
|
+
const rowStamp = objEnsure(tableStamp[0], rowId, stampNewObj);
|
|
1498
|
+
objForEach(
|
|
1499
|
+
cellStamps2,
|
|
1500
|
+
([cell2, cellTime2], cellId) =>
|
|
1501
|
+
(rowStamp[0][cellId] = newStamp(cell2, cellTime2)),
|
|
1502
|
+
);
|
|
1503
|
+
rowStamp[1] = getLatestTime(rowStamp[1], rowTime2);
|
|
1504
|
+
});
|
|
1505
|
+
tableStamp[1] = getLatestTime(tableStamp[1], tableTime2);
|
|
1506
|
+
});
|
|
1507
|
+
tablesStamp[1] = getLatestTime(tablesStamp[1], tablesTime2);
|
|
1508
|
+
};
|
|
1509
|
+
const getChangesFromOtherStore = async (
|
|
1510
|
+
otherClientId = null,
|
|
1511
|
+
otherContentHashes,
|
|
1512
|
+
) => {
|
|
1513
|
+
if (isUndefined(otherContentHashes)) {
|
|
1514
|
+
[otherContentHashes, otherClientId] = await request(
|
|
1515
|
+
otherClientId,
|
|
1516
|
+
GET_CONTENT_HASHES,
|
|
1517
|
+
);
|
|
1518
|
+
}
|
|
1519
|
+
const [otherTablesHash, otherValuesHash] = otherContentHashes;
|
|
1520
|
+
const [tablesHash, valuesHash] = store.getMergeableContentHashes();
|
|
1521
|
+
let tablesChanges = stampNewObj();
|
|
1522
|
+
if (tablesHash != otherTablesHash) {
|
|
1523
|
+
const [newTables, differentTableHashes] = (
|
|
1524
|
+
await request(
|
|
1525
|
+
otherClientId,
|
|
1526
|
+
GET_TABLE_DIFF,
|
|
1527
|
+
store.getMergeableTableHashes(),
|
|
1528
|
+
)
|
|
1529
|
+
)[0];
|
|
1530
|
+
tablesChanges = newTables;
|
|
1531
|
+
if (!objIsEmpty(differentTableHashes)) {
|
|
1532
|
+
const [newRows, differentRowHashes] = (
|
|
1533
|
+
await request(
|
|
1534
|
+
otherClientId,
|
|
1535
|
+
GET_ROW_DIFF,
|
|
1536
|
+
store.getMergeableRowHashes(differentTableHashes),
|
|
1537
|
+
)
|
|
1538
|
+
)[0];
|
|
1539
|
+
mergeTablesStamps(tablesChanges, newRows);
|
|
1540
|
+
if (!objIsEmpty(differentRowHashes)) {
|
|
1541
|
+
const newCells = (
|
|
1542
|
+
await request(
|
|
1543
|
+
otherClientId,
|
|
1544
|
+
GET_CELL_DIFF,
|
|
1545
|
+
store.getMergeableCellHashes(differentRowHashes),
|
|
1546
|
+
)
|
|
1547
|
+
)[0];
|
|
1548
|
+
mergeTablesStamps(tablesChanges, newCells);
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
return [
|
|
1553
|
+
tablesChanges,
|
|
1554
|
+
valuesHash == otherValuesHash
|
|
1555
|
+
? stampNewObj()
|
|
1556
|
+
: (
|
|
1557
|
+
await request(
|
|
1558
|
+
otherClientId,
|
|
1559
|
+
GET_VALUE_DIFF,
|
|
1560
|
+
store.getMergeableValuesHashes(),
|
|
1561
|
+
)
|
|
1562
|
+
)[0],
|
|
1563
|
+
1,
|
|
1564
|
+
];
|
|
1565
|
+
};
|
|
1566
|
+
const getPersisted = async () => {
|
|
1567
|
+
const changes = await getChangesFromOtherStore();
|
|
1568
|
+
return !objIsEmpty(changes[0][0]) || !objIsEmpty(changes[1][0])
|
|
1569
|
+
? changes
|
|
1570
|
+
: void 0;
|
|
1571
|
+
};
|
|
1572
|
+
const setPersisted = async (getContent, getChanges) => {
|
|
1573
|
+
{
|
|
1574
|
+
sends++;
|
|
1575
|
+
}
|
|
1576
|
+
if (getChanges) {
|
|
1577
|
+
send(null, null, CONTENT_DIFF, getChanges());
|
|
1578
|
+
} else {
|
|
1579
|
+
send(null, null, CONTENT_HASHES, store.getMergeableContentHashes());
|
|
1580
|
+
}
|
|
1581
|
+
};
|
|
1582
|
+
const addPersisterListener = (listener) => (persisterListener = listener);
|
|
1583
|
+
const delPersisterListener = () => (persisterListener = void 0);
|
|
1584
|
+
const startSync = async (initialContent) =>
|
|
1585
|
+
await (await persister.startAutoLoad(initialContent)).startAutoSave();
|
|
1586
|
+
const stopSync = () => persister.stopAutoLoad().stopAutoSave();
|
|
1587
|
+
const destroy = () => {
|
|
1588
|
+
destroyImpl();
|
|
1589
|
+
return persister.stopSync();
|
|
1590
|
+
};
|
|
1591
|
+
const getSynchronizerStats = () => ({sends, receives});
|
|
1592
|
+
const persister = createCustomPersister(
|
|
1593
|
+
store,
|
|
1594
|
+
getPersisted,
|
|
1595
|
+
setPersisted,
|
|
1596
|
+
addPersisterListener,
|
|
1597
|
+
delPersisterListener,
|
|
1598
|
+
onIgnoredError,
|
|
1599
|
+
true,
|
|
1600
|
+
{startSync, stopSync, destroy, getSynchronizerStats, ...extra},
|
|
1601
|
+
);
|
|
1602
|
+
return persister;
|
|
1603
|
+
};
|
|
1604
|
+
|
|
1205
1605
|
const createQueries = getCreateFunction((store) => {
|
|
1206
1606
|
const createStore = store.createStore;
|
|
1207
1607
|
const preStore = createStore();
|
|
@@ -1629,7 +2029,7 @@ const createQueries = getCreateFunction((store) => {
|
|
|
1629
2029
|
destroy,
|
|
1630
2030
|
getListenerStats,
|
|
1631
2031
|
};
|
|
1632
|
-
|
|
2032
|
+
objToArray(
|
|
1633
2033
|
{
|
|
1634
2034
|
[TABLE]: [1, 1],
|
|
1635
2035
|
[TABLE + CELL_IDS]: [0, 1],
|
|
@@ -1856,24 +2256,12 @@ const pairNewMap = () => [mapNew(), mapNew()];
|
|
|
1856
2256
|
const pairClone = (array) => [...array];
|
|
1857
2257
|
const pairIsEqual = ([entry1, entry2]) => entry1 === entry2;
|
|
1858
2258
|
|
|
1859
|
-
const
|
|
2259
|
+
const jsonStringWithMap = (obj) =>
|
|
1860
2260
|
JSON.stringify(obj, (_key, value) =>
|
|
1861
2261
|
isInstanceOf(value, Map) ? object.fromEntries([...value]) : value,
|
|
1862
2262
|
);
|
|
1863
2263
|
const jsonParse = JSON.parse;
|
|
1864
2264
|
|
|
1865
|
-
const validate = (obj, validateChild, onInvalidObj) => {
|
|
1866
|
-
if (isUndefined(obj) || !isObject(obj) || objIsEmpty(obj) || objFrozen(obj)) {
|
|
1867
|
-
onInvalidObj?.();
|
|
1868
|
-
return false;
|
|
1869
|
-
}
|
|
1870
|
-
objMap(obj, (child, id2) => {
|
|
1871
|
-
if (!validateChild(child, id2)) {
|
|
1872
|
-
objDel(obj, id2);
|
|
1873
|
-
}
|
|
1874
|
-
});
|
|
1875
|
-
return !objIsEmpty(obj);
|
|
1876
|
-
};
|
|
1877
2265
|
const idsChanged = (changedIds, id2, addedOrRemoved) =>
|
|
1878
2266
|
mapSet(
|
|
1879
2267
|
changedIds,
|
|
@@ -1883,11 +2271,10 @@ const idsChanged = (changedIds, id2, addedOrRemoved) =>
|
|
|
1883
2271
|
const createStore = () => {
|
|
1884
2272
|
let hasTablesSchema;
|
|
1885
2273
|
let hasValuesSchema;
|
|
1886
|
-
let cellsTouched = false;
|
|
1887
|
-
let valuesTouched = false;
|
|
1888
2274
|
let hadTables = false;
|
|
1889
2275
|
let hadValues = false;
|
|
1890
2276
|
let transactions = 0;
|
|
2277
|
+
let internalListeners = [];
|
|
1891
2278
|
const changedTableIds = mapNew();
|
|
1892
2279
|
const changedTableCellIds = mapNew();
|
|
1893
2280
|
const changedRowCount = mapNew();
|
|
@@ -1934,13 +2321,13 @@ const createStore = () => {
|
|
|
1934
2321
|
const [addListener, callListeners, delListenerImpl, callListenerImpl] =
|
|
1935
2322
|
getListenerFunctions(() => store);
|
|
1936
2323
|
const validateTablesSchema = (tableSchema) =>
|
|
1937
|
-
|
|
1938
|
-
|
|
2324
|
+
objValidate(tableSchema, (tableSchema2) =>
|
|
2325
|
+
objValidate(tableSchema2, validateCellOrValueSchema),
|
|
1939
2326
|
);
|
|
1940
2327
|
const validateValuesSchema = (valuesSchema) =>
|
|
1941
|
-
|
|
2328
|
+
objValidate(valuesSchema, validateCellOrValueSchema);
|
|
1942
2329
|
const validateCellOrValueSchema = (schema) => {
|
|
1943
|
-
if (!
|
|
2330
|
+
if (!objValidate(schema, (_child, id2) => arrayHas([TYPE, DEFAULT], id2))) {
|
|
1944
2331
|
return false;
|
|
1945
2332
|
}
|
|
1946
2333
|
const type = schema[TYPE];
|
|
@@ -1953,18 +2340,18 @@ const createStore = () => {
|
|
|
1953
2340
|
return true;
|
|
1954
2341
|
};
|
|
1955
2342
|
const validateTables = (tables) =>
|
|
1956
|
-
|
|
2343
|
+
objValidate(tables, validateTable, cellInvalid);
|
|
1957
2344
|
const validateTable = (table, tableId) =>
|
|
1958
2345
|
(!hasTablesSchema ||
|
|
1959
2346
|
collHas(tablesSchemaMap, tableId) ||
|
|
1960
2347
|
cellInvalid(tableId)) &&
|
|
1961
|
-
|
|
2348
|
+
objValidate(
|
|
1962
2349
|
table,
|
|
1963
2350
|
(row, rowId) => validateRow(tableId, rowId, row),
|
|
1964
2351
|
() => cellInvalid(tableId),
|
|
1965
2352
|
);
|
|
1966
2353
|
const validateRow = (tableId, rowId, row, skipDefaults) =>
|
|
1967
|
-
|
|
2354
|
+
objValidate(
|
|
1968
2355
|
skipDefaults ? row : addDefaultsToRow(row, tableId, rowId),
|
|
1969
2356
|
(cell, cellId) =>
|
|
1970
2357
|
ifNotUndefined(
|
|
@@ -1991,7 +2378,7 @@ const createStore = () => {
|
|
|
1991
2378
|
? cellInvalid(tableId, rowId, cellId, cell)
|
|
1992
2379
|
: cell;
|
|
1993
2380
|
const validateValues = (values, skipDefaults) =>
|
|
1994
|
-
|
|
2381
|
+
objValidate(
|
|
1995
2382
|
skipDefaults ? values : addDefaultsToValues(values),
|
|
1996
2383
|
(value, valueId) =>
|
|
1997
2384
|
ifNotUndefined(
|
|
@@ -2254,16 +2641,20 @@ const createStore = () => {
|
|
|
2254
2641
|
addedOrRemoved,
|
|
2255
2642
|
);
|
|
2256
2643
|
};
|
|
2257
|
-
const cellChanged = (tableId, rowId, cellId, oldCell, newCell) =>
|
|
2258
|
-
|
|
2644
|
+
const cellChanged = (tableId, rowId, cellId, oldCell, newCell) => {
|
|
2645
|
+
mapEnsure(
|
|
2259
2646
|
mapEnsure(mapEnsure(changedCells, tableId, mapNew), rowId, mapNew),
|
|
2260
2647
|
cellId,
|
|
2261
2648
|
() => [oldCell, 0],
|
|
2262
|
-
)[1] = newCell
|
|
2649
|
+
)[1] = newCell;
|
|
2650
|
+
internalListeners[3]?.(tableId, rowId, cellId, newCell);
|
|
2651
|
+
};
|
|
2263
2652
|
const valueIdsChanged = (valueId, addedOrRemoved) =>
|
|
2264
2653
|
idsChanged(changedValueIds, valueId, addedOrRemoved);
|
|
2265
|
-
const valueChanged = (valueId, oldValue, newValue) =>
|
|
2266
|
-
|
|
2654
|
+
const valueChanged = (valueId, oldValue, newValue) => {
|
|
2655
|
+
mapEnsure(changedValues, valueId, () => [oldValue, 0])[1] = newValue;
|
|
2656
|
+
internalListeners[4]?.(valueId, newValue);
|
|
2657
|
+
};
|
|
2267
2658
|
const cellInvalid = (tableId, rowId, cellId, invalidCell, defaultedCell) => {
|
|
2268
2659
|
arrayPush(
|
|
2269
2660
|
mapEnsure(
|
|
@@ -2529,44 +2920,6 @@ const createStore = () => {
|
|
|
2529
2920
|
transaction(() => actions(...arrayMap(args, id)));
|
|
2530
2921
|
return store;
|
|
2531
2922
|
};
|
|
2532
|
-
const getTransactionChanges = () => [
|
|
2533
|
-
mapToObj(
|
|
2534
|
-
changedCells,
|
|
2535
|
-
(table, tableId) =>
|
|
2536
|
-
mapGet(changedTableIds, tableId) === -1
|
|
2537
|
-
? null
|
|
2538
|
-
: mapToObj(
|
|
2539
|
-
table,
|
|
2540
|
-
(row, rowId) =>
|
|
2541
|
-
mapGet(mapGet(changedRowIds, tableId), rowId) === -1
|
|
2542
|
-
? null
|
|
2543
|
-
: mapToObj(
|
|
2544
|
-
row,
|
|
2545
|
-
([, newCell]) => newCell ?? null,
|
|
2546
|
-
(_, changedCell) => pairIsEqual(changedCell),
|
|
2547
|
-
),
|
|
2548
|
-
objIsEmpty,
|
|
2549
|
-
),
|
|
2550
|
-
objIsEmpty,
|
|
2551
|
-
),
|
|
2552
|
-
mapToObj(
|
|
2553
|
-
changedValues,
|
|
2554
|
-
([, newValue]) => newValue ?? null,
|
|
2555
|
-
(_, changedValue) => pairIsEqual(changedValue),
|
|
2556
|
-
),
|
|
2557
|
-
];
|
|
2558
|
-
const getTransactionLog = () => ({
|
|
2559
|
-
cellsTouched,
|
|
2560
|
-
valuesTouched,
|
|
2561
|
-
changedCells: mapToObj3(changedCells, pairClone, pairIsEqual),
|
|
2562
|
-
invalidCells: mapToObj3(invalidCells),
|
|
2563
|
-
changedValues: mapToObj(changedValues, pairClone, pairIsEqual),
|
|
2564
|
-
invalidValues: mapToObj(invalidValues),
|
|
2565
|
-
changedTableIds: mapToObj(changedTableIds),
|
|
2566
|
-
changedRowIds: mapToObj2(changedRowIds),
|
|
2567
|
-
changedCellIds: mapToObj3(changedCellIds),
|
|
2568
|
-
changedValueIds: mapToObj(changedValueIds),
|
|
2569
|
-
});
|
|
2570
2923
|
const getContent = () => [getTables(), getValues()];
|
|
2571
2924
|
const getTables = () => mapToObj3(tablesMap);
|
|
2572
2925
|
const getTableIds = () => mapKeys(tablesMap);
|
|
@@ -2610,12 +2963,13 @@ const createStore = () => {
|
|
|
2610
2963
|
collHas(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), id(cellId));
|
|
2611
2964
|
const hasValues = () => !collIsEmpty(valuesMap);
|
|
2612
2965
|
const hasValue = (valueId) => collHas(valuesMap, id(valueId));
|
|
2613
|
-
const getTablesJson = () =>
|
|
2614
|
-
const getValuesJson = () =>
|
|
2615
|
-
const getJson = () =>
|
|
2616
|
-
const getTablesSchemaJson = () =>
|
|
2617
|
-
const getValuesSchemaJson = () =>
|
|
2618
|
-
const getSchemaJson = () =>
|
|
2966
|
+
const getTablesJson = () => jsonStringWithMap(tablesMap);
|
|
2967
|
+
const getValuesJson = () => jsonStringWithMap(valuesMap);
|
|
2968
|
+
const getJson = () => jsonStringWithMap([tablesMap, valuesMap]);
|
|
2969
|
+
const getTablesSchemaJson = () => jsonStringWithMap(tablesSchemaMap);
|
|
2970
|
+
const getValuesSchemaJson = () => jsonStringWithMap(valuesSchemaMap);
|
|
2971
|
+
const getSchemaJson = () =>
|
|
2972
|
+
jsonStringWithMap([tablesSchemaMap, valuesSchemaMap]);
|
|
2619
2973
|
const setContent = ([tables, values]) =>
|
|
2620
2974
|
fluentTransaction(() => {
|
|
2621
2975
|
(objIsEmpty(tables) ? delTables : setTables)(tables);
|
|
@@ -2659,7 +3013,7 @@ const createStore = () => {
|
|
|
2659
3013
|
(tableId2, rowId2) => {
|
|
2660
3014
|
if (validateRow(tableId2, rowId2, partialRow, 1)) {
|
|
2661
3015
|
const table = getOrCreateTable(tableId2);
|
|
2662
|
-
|
|
3016
|
+
objToArray(partialRow, (cell, cellId) =>
|
|
2663
3017
|
setCellIntoDefaultRow(tableId2, table, rowId2, cellId, cell),
|
|
2664
3018
|
);
|
|
2665
3019
|
}
|
|
@@ -2697,7 +3051,7 @@ const createStore = () => {
|
|
|
2697
3051
|
const setPartialValues = (partialValues) =>
|
|
2698
3052
|
fluentTransaction(() =>
|
|
2699
3053
|
validateValues(partialValues, 1)
|
|
2700
|
-
?
|
|
3054
|
+
? objToArray(partialValues, (value, valueId) =>
|
|
2701
3055
|
setValidValue(valueId, value),
|
|
2702
3056
|
)
|
|
2703
3057
|
: 0,
|
|
@@ -2714,20 +3068,20 @@ const createStore = () => {
|
|
|
2714
3068
|
),
|
|
2715
3069
|
valueId,
|
|
2716
3070
|
);
|
|
2717
|
-
const
|
|
3071
|
+
const applyChanges = (changes) =>
|
|
2718
3072
|
fluentTransaction(() => {
|
|
2719
|
-
|
|
3073
|
+
objToArray(changes[0], (table, tableId) =>
|
|
2720
3074
|
isUndefined(table)
|
|
2721
3075
|
? delTable(tableId)
|
|
2722
|
-
:
|
|
3076
|
+
: objToArray(table, (row, rowId) =>
|
|
2723
3077
|
isUndefined(row)
|
|
2724
3078
|
? delRow(tableId, rowId)
|
|
2725
|
-
:
|
|
3079
|
+
: objToArray(row, (cell, cellId) =>
|
|
2726
3080
|
setOrDelCell(store, tableId, rowId, cellId, cell),
|
|
2727
3081
|
),
|
|
2728
3082
|
),
|
|
2729
3083
|
);
|
|
2730
|
-
|
|
3084
|
+
objToArray(changes[1], (value, valueId) =>
|
|
2731
3085
|
setOrDelValue(store, valueId, value),
|
|
2732
3086
|
);
|
|
2733
3087
|
});
|
|
@@ -2854,31 +3208,66 @@ const createStore = () => {
|
|
|
2854
3208
|
transactions++;
|
|
2855
3209
|
}
|
|
2856
3210
|
if (transactions == 1) {
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
void 0,
|
|
2860
|
-
getTransactionChanges,
|
|
2861
|
-
getTransactionLog,
|
|
2862
|
-
);
|
|
3211
|
+
internalListeners[0]?.();
|
|
3212
|
+
callListeners(startTransactionListeners, void 0);
|
|
2863
3213
|
}
|
|
2864
3214
|
return store;
|
|
2865
3215
|
};
|
|
3216
|
+
const getTransactionChanges = () => [
|
|
3217
|
+
mapToObj(
|
|
3218
|
+
changedCells,
|
|
3219
|
+
(table, tableId) =>
|
|
3220
|
+
mapGet(changedTableIds, tableId) === -1
|
|
3221
|
+
? void 0
|
|
3222
|
+
: mapToObj(
|
|
3223
|
+
table,
|
|
3224
|
+
(row, rowId) =>
|
|
3225
|
+
mapGet(mapGet(changedRowIds, tableId), rowId) === -1
|
|
3226
|
+
? void 0
|
|
3227
|
+
: mapToObj(
|
|
3228
|
+
row,
|
|
3229
|
+
([, newCell]) => newCell,
|
|
3230
|
+
(changedCell) => pairIsEqual(changedCell),
|
|
3231
|
+
),
|
|
3232
|
+
collIsEmpty,
|
|
3233
|
+
objIsEmpty,
|
|
3234
|
+
),
|
|
3235
|
+
collIsEmpty,
|
|
3236
|
+
objIsEmpty,
|
|
3237
|
+
),
|
|
3238
|
+
mapToObj(
|
|
3239
|
+
changedValues,
|
|
3240
|
+
([, newValue]) => newValue,
|
|
3241
|
+
(changedValue) => pairIsEqual(changedValue),
|
|
3242
|
+
),
|
|
3243
|
+
1,
|
|
3244
|
+
];
|
|
3245
|
+
const getTransactionLog = () => [
|
|
3246
|
+
!collIsEmpty(changedCells),
|
|
3247
|
+
!collIsEmpty(changedValues),
|
|
3248
|
+
mapToObj3(changedCells, pairClone, pairIsEqual),
|
|
3249
|
+
mapToObj3(invalidCells),
|
|
3250
|
+
mapToObj(changedValues, pairClone, pairIsEqual),
|
|
3251
|
+
mapToObj(invalidValues),
|
|
3252
|
+
mapToObj(changedTableIds),
|
|
3253
|
+
mapToObj2(changedRowIds),
|
|
3254
|
+
mapToObj3(changedCellIds),
|
|
3255
|
+
mapToObj(changedValueIds),
|
|
3256
|
+
];
|
|
2866
3257
|
const finishTransaction = (doRollback) => {
|
|
2867
3258
|
if (transactions > 0) {
|
|
2868
3259
|
transactions--;
|
|
2869
3260
|
if (transactions == 0) {
|
|
2870
|
-
cellsTouched = !collIsEmpty(changedCells);
|
|
2871
|
-
valuesTouched = !collIsEmpty(changedValues);
|
|
2872
3261
|
transactions = 1;
|
|
2873
3262
|
callInvalidCellListeners(1);
|
|
2874
|
-
if (
|
|
3263
|
+
if (!collIsEmpty(changedCells)) {
|
|
2875
3264
|
callTabularListenersForChanges(1);
|
|
2876
3265
|
}
|
|
2877
3266
|
callInvalidValueListeners(1);
|
|
2878
|
-
if (
|
|
3267
|
+
if (!collIsEmpty(changedValues)) {
|
|
2879
3268
|
callValuesListenersForChanges(1);
|
|
2880
3269
|
}
|
|
2881
|
-
if (doRollback?.(
|
|
3270
|
+
if (doRollback?.(store)) {
|
|
2882
3271
|
collForEach(changedCells, (table, tableId) =>
|
|
2883
3272
|
collForEach(table, (row, rowId) =>
|
|
2884
3273
|
collForEach(row, ([oldCell], cellId) =>
|
|
@@ -2886,34 +3275,26 @@ const createStore = () => {
|
|
|
2886
3275
|
),
|
|
2887
3276
|
),
|
|
2888
3277
|
);
|
|
3278
|
+
collClear(changedCells);
|
|
2889
3279
|
collForEach(changedValues, ([oldValue], valueId) =>
|
|
2890
3280
|
setOrDelValue(store, valueId, oldValue),
|
|
2891
3281
|
);
|
|
2892
|
-
|
|
3282
|
+
collClear(changedValues);
|
|
2893
3283
|
}
|
|
2894
|
-
callListeners(
|
|
2895
|
-
finishTransactionListeners[0],
|
|
2896
|
-
void 0,
|
|
2897
|
-
getTransactionChanges,
|
|
2898
|
-
getTransactionLog,
|
|
2899
|
-
);
|
|
3284
|
+
callListeners(finishTransactionListeners[0], void 0);
|
|
2900
3285
|
transactions = -1;
|
|
2901
3286
|
callInvalidCellListeners(0);
|
|
2902
|
-
if (
|
|
3287
|
+
if (!collIsEmpty(changedCells)) {
|
|
2903
3288
|
callTabularListenersForChanges(0);
|
|
2904
3289
|
}
|
|
2905
3290
|
callInvalidValueListeners(0);
|
|
2906
|
-
if (
|
|
3291
|
+
if (!collIsEmpty(changedValues)) {
|
|
2907
3292
|
callValuesListenersForChanges(0);
|
|
2908
3293
|
}
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
getTransactionChanges,
|
|
2913
|
-
getTransactionLog,
|
|
2914
|
-
);
|
|
3294
|
+
internalListeners[1]?.();
|
|
3295
|
+
callListeners(finishTransactionListeners[1], void 0);
|
|
3296
|
+
internalListeners[2]?.();
|
|
2915
3297
|
transactions = 0;
|
|
2916
|
-
cellsTouched = valuesTouched = false;
|
|
2917
3298
|
hadTables = hasTables();
|
|
2918
3299
|
hadValues = hasValues();
|
|
2919
3300
|
arrayForEach(
|
|
@@ -3038,6 +3419,20 @@ const createStore = () => {
|
|
|
3038
3419
|
collSize2(startTransactionListeners) +
|
|
3039
3420
|
pairCollSize2(finishTransactionListeners),
|
|
3040
3421
|
});
|
|
3422
|
+
const setInternalListeners = (
|
|
3423
|
+
preStartTransaction,
|
|
3424
|
+
preFinishTransaction,
|
|
3425
|
+
postFinishTransaction,
|
|
3426
|
+
cellChanged2,
|
|
3427
|
+
valueChanged2,
|
|
3428
|
+
) =>
|
|
3429
|
+
(internalListeners = [
|
|
3430
|
+
preStartTransaction,
|
|
3431
|
+
preFinishTransaction,
|
|
3432
|
+
postFinishTransaction,
|
|
3433
|
+
cellChanged2,
|
|
3434
|
+
valueChanged2,
|
|
3435
|
+
]);
|
|
3041
3436
|
const store = {
|
|
3042
3437
|
getContent,
|
|
3043
3438
|
getTables,
|
|
@@ -3078,7 +3473,7 @@ const createStore = () => {
|
|
|
3078
3473
|
setValues,
|
|
3079
3474
|
setPartialValues,
|
|
3080
3475
|
setValue,
|
|
3081
|
-
|
|
3476
|
+
applyChanges,
|
|
3082
3477
|
setTablesJson,
|
|
3083
3478
|
setValuesJson,
|
|
3084
3479
|
setJson,
|
|
@@ -3096,6 +3491,8 @@ const createStore = () => {
|
|
|
3096
3491
|
delSchema,
|
|
3097
3492
|
transaction,
|
|
3098
3493
|
startTransaction,
|
|
3494
|
+
getTransactionChanges,
|
|
3495
|
+
getTransactionLog,
|
|
3099
3496
|
finishTransaction,
|
|
3100
3497
|
forEachTable,
|
|
3101
3498
|
forEachTableCell,
|
|
@@ -3113,8 +3510,9 @@ const createStore = () => {
|
|
|
3113
3510
|
createStore,
|
|
3114
3511
|
addListener,
|
|
3115
3512
|
callListeners,
|
|
3513
|
+
setInternalListeners,
|
|
3116
3514
|
};
|
|
3117
|
-
|
|
3515
|
+
objToArray(
|
|
3118
3516
|
{
|
|
3119
3517
|
[HAS + TABLES]: [0, hasTablesListeners, [], () => [hasTables()]],
|
|
3120
3518
|
[TABLES]: [0, tablesListeners],
|
|
@@ -3187,10 +3585,484 @@ const createStore = () => {
|
|
|
3187
3585
|
return objFreeze(store);
|
|
3188
3586
|
};
|
|
3189
3587
|
|
|
3588
|
+
const LISTENER_ARGS = {
|
|
3589
|
+
HasTable: 1,
|
|
3590
|
+
Table: 1,
|
|
3591
|
+
TableCellIds: 1,
|
|
3592
|
+
HasTableCell: 2,
|
|
3593
|
+
RowCount: 1,
|
|
3594
|
+
RowIds: 1,
|
|
3595
|
+
SortedRowIds: 5,
|
|
3596
|
+
HasRow: 2,
|
|
3597
|
+
Row: 2,
|
|
3598
|
+
CellIds: 2,
|
|
3599
|
+
HasCell: 3,
|
|
3600
|
+
Cell: 3,
|
|
3601
|
+
HasValue: 1,
|
|
3602
|
+
Value: 1,
|
|
3603
|
+
InvalidCell: 3,
|
|
3604
|
+
InvalidValue: 1,
|
|
3605
|
+
};
|
|
3606
|
+
const newContentStampMap = (time = EMPTY_STRING) => [
|
|
3607
|
+
stampNewMap(time),
|
|
3608
|
+
stampNewMap(time),
|
|
3609
|
+
];
|
|
3610
|
+
const validateMergeableContent = (mergeableContent) =>
|
|
3611
|
+
isArray(mergeableContent) &&
|
|
3612
|
+
size(mergeableContent) == 2 &&
|
|
3613
|
+
stampValidate(mergeableContent[0], (tableStamps) =>
|
|
3614
|
+
objValidate(
|
|
3615
|
+
tableStamps,
|
|
3616
|
+
(tableStamp) =>
|
|
3617
|
+
stampValidate(tableStamp, (rowStamps) =>
|
|
3618
|
+
objValidate(
|
|
3619
|
+
rowStamps,
|
|
3620
|
+
(rowStamp) =>
|
|
3621
|
+
stampValidate(rowStamp, (cellStamps) =>
|
|
3622
|
+
objValidate(
|
|
3623
|
+
cellStamps,
|
|
3624
|
+
(cellStamp) =>
|
|
3625
|
+
stampValidate(cellStamp, isCellOrValueOrNullOrUndefined),
|
|
3626
|
+
void 0,
|
|
3627
|
+
1,
|
|
3628
|
+
),
|
|
3629
|
+
),
|
|
3630
|
+
void 0,
|
|
3631
|
+
1,
|
|
3632
|
+
),
|
|
3633
|
+
),
|
|
3634
|
+
void 0,
|
|
3635
|
+
1,
|
|
3636
|
+
),
|
|
3637
|
+
) &&
|
|
3638
|
+
stampValidate(mergeableContent[1], (values) =>
|
|
3639
|
+
objValidate(
|
|
3640
|
+
values,
|
|
3641
|
+
(value) => stampValidate(value, isCellOrValueOrNullOrUndefined),
|
|
3642
|
+
void 0,
|
|
3643
|
+
1,
|
|
3644
|
+
),
|
|
3645
|
+
);
|
|
3646
|
+
const createMergeableStore = (id) => {
|
|
3647
|
+
let listeningToRawStoreChanges = 1;
|
|
3648
|
+
let contentStampMap = newContentStampMap();
|
|
3649
|
+
let defaultingContent = 0;
|
|
3650
|
+
const touchedCells = mapNew();
|
|
3651
|
+
const touchedValues = setNew();
|
|
3652
|
+
const [getHlc, seenHlc] = getHlcFunctions(id);
|
|
3653
|
+
const store = createStore();
|
|
3654
|
+
const disableListeningToRawStoreChanges = (actions) => {
|
|
3655
|
+
const wasListening = listeningToRawStoreChanges;
|
|
3656
|
+
listeningToRawStoreChanges = 0;
|
|
3657
|
+
actions();
|
|
3658
|
+
listeningToRawStoreChanges = wasListening;
|
|
3659
|
+
return mergeableStore;
|
|
3660
|
+
};
|
|
3661
|
+
const mergeContentOrChanges = (contentOrChanges, isContent = 0) => {
|
|
3662
|
+
const tablesChanges = {};
|
|
3663
|
+
const valuesChanges = {};
|
|
3664
|
+
const [
|
|
3665
|
+
[tablesObj, incomingTablesTime = EMPTY_STRING, incomingTablesHash = 0],
|
|
3666
|
+
values,
|
|
3667
|
+
] = contentOrChanges;
|
|
3668
|
+
const [tablesStampMap, valuesStampMap] = contentStampMap;
|
|
3669
|
+
const [tableStampMaps, oldTablesTime, oldTablesHash] = tablesStampMap;
|
|
3670
|
+
let tablesHash = isContent ? incomingTablesHash : oldTablesHash;
|
|
3671
|
+
let tablesTime = incomingTablesTime;
|
|
3672
|
+
objForEach(
|
|
3673
|
+
tablesObj,
|
|
3674
|
+
(
|
|
3675
|
+
[rowsObj, incomingTableTime = EMPTY_STRING, incomingTableHash = 0],
|
|
3676
|
+
tableId,
|
|
3677
|
+
) => {
|
|
3678
|
+
const tableStampMap = mapEnsure(tableStampMaps, tableId, stampNewMap);
|
|
3679
|
+
const [rowStampMaps, oldTableTime, oldTableHash] = tableStampMap;
|
|
3680
|
+
let tableHash = isContent ? incomingTableHash : oldTableHash;
|
|
3681
|
+
let tableTime = incomingTableTime;
|
|
3682
|
+
objForEach(rowsObj, (row, rowId) => {
|
|
3683
|
+
const [rowTime, oldRowHash, rowHash] = mergeCellsOrValues(
|
|
3684
|
+
row,
|
|
3685
|
+
mapEnsure(rowStampMaps, rowId, stampNewMap),
|
|
3686
|
+
objEnsure(objEnsure(tablesChanges, tableId, objNew), rowId, objNew),
|
|
3687
|
+
isContent,
|
|
3688
|
+
);
|
|
3689
|
+
tableHash ^= isContent
|
|
3690
|
+
? 0
|
|
3691
|
+
: (oldRowHash ? hashIdAndHash(rowId, oldRowHash) : 0) ^
|
|
3692
|
+
hashIdAndHash(rowId, rowHash);
|
|
3693
|
+
tableTime = getLatestTime(tableTime, rowTime);
|
|
3694
|
+
});
|
|
3695
|
+
tableHash ^= isContent
|
|
3696
|
+
? 0
|
|
3697
|
+
: replaceTimeHash(oldTableTime, incomingTableTime);
|
|
3698
|
+
stampUpdate(tableStampMap, tableHash, incomingTableTime);
|
|
3699
|
+
tablesHash ^= isContent
|
|
3700
|
+
? 0
|
|
3701
|
+
: (oldTableHash ? hashIdAndHash(tableId, oldTableHash) : 0) ^
|
|
3702
|
+
hashIdAndHash(tableId, tableStampMap[2]);
|
|
3703
|
+
tablesTime = getLatestTime(tablesTime, tableTime);
|
|
3704
|
+
},
|
|
3705
|
+
);
|
|
3706
|
+
tablesHash ^= isContent
|
|
3707
|
+
? 0
|
|
3708
|
+
: replaceTimeHash(oldTablesTime, incomingTablesTime);
|
|
3709
|
+
stampUpdate(tablesStampMap, tablesHash, incomingTablesTime);
|
|
3710
|
+
const [valuesTime] = mergeCellsOrValues(
|
|
3711
|
+
values,
|
|
3712
|
+
valuesStampMap,
|
|
3713
|
+
valuesChanges,
|
|
3714
|
+
isContent,
|
|
3715
|
+
);
|
|
3716
|
+
seenHlc(getLatestTime(tablesTime, valuesTime));
|
|
3717
|
+
return [tablesChanges, valuesChanges, 1];
|
|
3718
|
+
};
|
|
3719
|
+
const mergeCellsOrValues = (
|
|
3720
|
+
things,
|
|
3721
|
+
thingsStampMap,
|
|
3722
|
+
thingsChanges,
|
|
3723
|
+
isContent,
|
|
3724
|
+
) => {
|
|
3725
|
+
const [
|
|
3726
|
+
thingsObj,
|
|
3727
|
+
incomingThingsTime = EMPTY_STRING,
|
|
3728
|
+
incomingThingsHash = 0,
|
|
3729
|
+
] = things;
|
|
3730
|
+
const [thingStampMaps, oldThingsTime, oldThingsHash] = thingsStampMap;
|
|
3731
|
+
let thingsTime = incomingThingsTime;
|
|
3732
|
+
let thingsHash = isContent ? incomingThingsHash : oldThingsHash;
|
|
3733
|
+
objForEach(
|
|
3734
|
+
thingsObj,
|
|
3735
|
+
([thing, thingTime, incomingThingHash = 0], thingId) => {
|
|
3736
|
+
const thingStampMap = mapEnsure(thingStampMaps, thingId, () => [
|
|
3737
|
+
void 0,
|
|
3738
|
+
EMPTY_STRING,
|
|
3739
|
+
0,
|
|
3740
|
+
]);
|
|
3741
|
+
const [, oldThingTime, oldThingHash] = thingStampMap;
|
|
3742
|
+
if (!oldThingTime || thingTime > oldThingTime) {
|
|
3743
|
+
stampUpdate(
|
|
3744
|
+
thingStampMap,
|
|
3745
|
+
isContent
|
|
3746
|
+
? incomingThingHash
|
|
3747
|
+
: getHash(jsonStringWithMap(thing ?? null) + ':' + thingTime),
|
|
3748
|
+
thingTime,
|
|
3749
|
+
);
|
|
3750
|
+
thingStampMap[0] = thing;
|
|
3751
|
+
thingsChanges[thingId] = thing;
|
|
3752
|
+
thingsHash ^= isContent
|
|
3753
|
+
? 0
|
|
3754
|
+
: hashIdAndHash(thingId, oldThingHash) ^
|
|
3755
|
+
hashIdAndHash(thingId, thingStampMap[2]);
|
|
3756
|
+
thingsTime = getLatestTime(thingsTime, thingTime);
|
|
3757
|
+
}
|
|
3758
|
+
},
|
|
3759
|
+
);
|
|
3760
|
+
thingsHash ^= isContent
|
|
3761
|
+
? 0
|
|
3762
|
+
: replaceTimeHash(oldThingsTime, incomingThingsTime);
|
|
3763
|
+
stampUpdate(thingsStampMap, thingsHash, incomingThingsTime);
|
|
3764
|
+
return [thingsTime, oldThingsHash, thingsStampMap[2]];
|
|
3765
|
+
};
|
|
3766
|
+
const preStartTransaction = () => {};
|
|
3767
|
+
const preFinishTransaction = () => {};
|
|
3768
|
+
const postFinishTransaction = () => {
|
|
3769
|
+
collClear(touchedCells);
|
|
3770
|
+
collClear(touchedValues);
|
|
3771
|
+
};
|
|
3772
|
+
const cellChanged = (tableId, rowId, cellId, newCell) => {
|
|
3773
|
+
setAdd(
|
|
3774
|
+
mapEnsure(mapEnsure(touchedCells, tableId, mapNew), rowId, setNew),
|
|
3775
|
+
cellId,
|
|
3776
|
+
);
|
|
3777
|
+
if (listeningToRawStoreChanges) {
|
|
3778
|
+
mergeContentOrChanges([
|
|
3779
|
+
[
|
|
3780
|
+
{
|
|
3781
|
+
[tableId]: [
|
|
3782
|
+
{
|
|
3783
|
+
[rowId]: [
|
|
3784
|
+
{
|
|
3785
|
+
[cellId]: [
|
|
3786
|
+
newCell,
|
|
3787
|
+
defaultingContent ? EMPTY_STRING : getHlc(),
|
|
3788
|
+
],
|
|
3789
|
+
},
|
|
3790
|
+
],
|
|
3791
|
+
},
|
|
3792
|
+
],
|
|
3793
|
+
},
|
|
3794
|
+
],
|
|
3795
|
+
[{}],
|
|
3796
|
+
1,
|
|
3797
|
+
]);
|
|
3798
|
+
}
|
|
3799
|
+
};
|
|
3800
|
+
const valueChanged = (valueId, newValue) => {
|
|
3801
|
+
setAdd(touchedValues, valueId);
|
|
3802
|
+
if (listeningToRawStoreChanges) {
|
|
3803
|
+
mergeContentOrChanges([
|
|
3804
|
+
[{}],
|
|
3805
|
+
[{[valueId]: [newValue, defaultingContent ? EMPTY_STRING : getHlc()]}],
|
|
3806
|
+
1,
|
|
3807
|
+
]);
|
|
3808
|
+
}
|
|
3809
|
+
};
|
|
3810
|
+
const getId = () => id;
|
|
3811
|
+
const getMergeableContent = () => [
|
|
3812
|
+
stampMapToObjWithHash(contentStampMap[0], (tableStampMap) =>
|
|
3813
|
+
stampMapToObjWithHash(tableStampMap, (rowStampMap) =>
|
|
3814
|
+
stampMapToObjWithHash(rowStampMap),
|
|
3815
|
+
),
|
|
3816
|
+
),
|
|
3817
|
+
stampMapToObjWithHash(contentStampMap[1]),
|
|
3818
|
+
];
|
|
3819
|
+
const getMergeableContentHashes = () => [
|
|
3820
|
+
contentStampMap[0][2],
|
|
3821
|
+
contentStampMap[1][2],
|
|
3822
|
+
];
|
|
3823
|
+
const getMergeableTableHashes = () =>
|
|
3824
|
+
mapToObj(contentStampMap[0][0], getStampHash);
|
|
3825
|
+
const getMergeableTableDiff = (otherTableHashes) => {
|
|
3826
|
+
const newTables = stampNewObj(contentStampMap[0][1]);
|
|
3827
|
+
const differentTableHashes = {};
|
|
3828
|
+
mapForEach(
|
|
3829
|
+
contentStampMap[0][0],
|
|
3830
|
+
(tableId, [tableStampMap, tableTime, hash]) =>
|
|
3831
|
+
objHas(otherTableHashes, tableId)
|
|
3832
|
+
? hash != otherTableHashes[tableId]
|
|
3833
|
+
? (differentTableHashes[tableId] = hash)
|
|
3834
|
+
: 0
|
|
3835
|
+
: (newTables[0][tableId] = stampMapToObjWithoutHash(
|
|
3836
|
+
[tableStampMap, tableTime],
|
|
3837
|
+
(rowStampMap) => stampMapToObjWithoutHash(rowStampMap),
|
|
3838
|
+
)),
|
|
3839
|
+
);
|
|
3840
|
+
return [newTables, differentTableHashes];
|
|
3841
|
+
};
|
|
3842
|
+
const getMergeableRowHashes = (otherTableHashes) => {
|
|
3843
|
+
const rowHashes = {};
|
|
3844
|
+
objForEach(otherTableHashes, (otherTableHash, tableId) =>
|
|
3845
|
+
ifNotUndefined(
|
|
3846
|
+
mapGet(contentStampMap[0][0], tableId),
|
|
3847
|
+
([rowStampMaps, , tableHash]) =>
|
|
3848
|
+
tableHash != otherTableHash
|
|
3849
|
+
? mapForEach(
|
|
3850
|
+
rowStampMaps,
|
|
3851
|
+
(rowId, [, , rowHash]) =>
|
|
3852
|
+
(objEnsure(rowHashes, tableId, objNew)[rowId] = rowHash),
|
|
3853
|
+
)
|
|
3854
|
+
: 0,
|
|
3855
|
+
),
|
|
3856
|
+
);
|
|
3857
|
+
return rowHashes;
|
|
3858
|
+
};
|
|
3859
|
+
const getMergeableRowDiff = (otherTableRowHashes) => {
|
|
3860
|
+
const newRows = stampNewObj(contentStampMap[0][1]);
|
|
3861
|
+
const differentRowHashes = {};
|
|
3862
|
+
objForEach(otherTableRowHashes, (otherRowHashes, tableId) =>
|
|
3863
|
+
mapForEach(
|
|
3864
|
+
mapGet(contentStampMap[0][0], tableId)?.[0],
|
|
3865
|
+
(rowId, [rowStampMap, rowTime, hash]) =>
|
|
3866
|
+
objHas(otherRowHashes, rowId)
|
|
3867
|
+
? hash !== otherRowHashes[rowId]
|
|
3868
|
+
? (objEnsure(differentRowHashes, tableId, objNew)[rowId] = hash)
|
|
3869
|
+
: 0
|
|
3870
|
+
: (objEnsure(newRows[0], tableId, stampNewObj)[0][rowId] =
|
|
3871
|
+
stampMapToObjWithoutHash([rowStampMap, rowTime])),
|
|
3872
|
+
),
|
|
3873
|
+
);
|
|
3874
|
+
return [newRows, differentRowHashes];
|
|
3875
|
+
};
|
|
3876
|
+
const getMergeableCellHashes = (otherTableRowHashes) => {
|
|
3877
|
+
const cellHashes = {};
|
|
3878
|
+
objForEach(otherTableRowHashes, (otherRowHashes, tableId) =>
|
|
3879
|
+
ifNotUndefined(mapGet(contentStampMap[0][0], tableId), ([rowStampMaps]) =>
|
|
3880
|
+
objForEach(otherRowHashes, (otherRowHash, rowId) =>
|
|
3881
|
+
ifNotUndefined(
|
|
3882
|
+
mapGet(rowStampMaps, rowId),
|
|
3883
|
+
([cellStampMaps, , rowHash]) =>
|
|
3884
|
+
rowHash !== otherRowHash
|
|
3885
|
+
? mapForEach(
|
|
3886
|
+
cellStampMaps,
|
|
3887
|
+
(cellId, [, , cellHash]) =>
|
|
3888
|
+
(objEnsure(
|
|
3889
|
+
objEnsure(cellHashes, tableId, objNew),
|
|
3890
|
+
rowId,
|
|
3891
|
+
objNew,
|
|
3892
|
+
)[cellId] = cellHash),
|
|
3893
|
+
)
|
|
3894
|
+
: 0,
|
|
3895
|
+
),
|
|
3896
|
+
),
|
|
3897
|
+
),
|
|
3898
|
+
);
|
|
3899
|
+
return cellHashes;
|
|
3900
|
+
};
|
|
3901
|
+
const getMergeableCellDiff = (otherTableRowCellHashes) => {
|
|
3902
|
+
const [[tableStampMaps, tablesTime]] = contentStampMap;
|
|
3903
|
+
const tablesObj = {};
|
|
3904
|
+
objForEach(otherTableRowCellHashes, (otherRowCellHashes, tableId) =>
|
|
3905
|
+
objForEach(otherRowCellHashes, (otherCellHashes, rowId) =>
|
|
3906
|
+
ifNotUndefined(
|
|
3907
|
+
mapGet(tableStampMaps, tableId),
|
|
3908
|
+
([rowStampMaps, tableTime]) =>
|
|
3909
|
+
ifNotUndefined(
|
|
3910
|
+
mapGet(rowStampMaps, rowId),
|
|
3911
|
+
([cellStampMaps, rowTime]) =>
|
|
3912
|
+
mapForEach(cellStampMaps, (cellId, [cell, cellTime, hash]) =>
|
|
3913
|
+
hash !== otherCellHashes[cellId]
|
|
3914
|
+
? (objEnsure(
|
|
3915
|
+
objEnsure(tablesObj, tableId, () =>
|
|
3916
|
+
stampNewObj(tableTime),
|
|
3917
|
+
)[0],
|
|
3918
|
+
rowId,
|
|
3919
|
+
() => stampNewObj(rowTime),
|
|
3920
|
+
)[0][cellId] = [cell, cellTime])
|
|
3921
|
+
: 0,
|
|
3922
|
+
),
|
|
3923
|
+
),
|
|
3924
|
+
),
|
|
3925
|
+
),
|
|
3926
|
+
);
|
|
3927
|
+
return newStamp(tablesObj, tablesTime);
|
|
3928
|
+
};
|
|
3929
|
+
const getMergeableValuesHashes = () =>
|
|
3930
|
+
mapToObj(contentStampMap[1][0], getStampHash);
|
|
3931
|
+
const getMergeableValueDiff = (relativeTo) => {
|
|
3932
|
+
const [, [valueStampMaps, valuesTime]] = contentStampMap;
|
|
3933
|
+
const values = mapToObj(
|
|
3934
|
+
valueStampMaps,
|
|
3935
|
+
stampCloneWithoutHash,
|
|
3936
|
+
([, , hash], valueId) => hash == relativeTo?.[valueId],
|
|
3937
|
+
);
|
|
3938
|
+
return newStamp(values, valuesTime);
|
|
3939
|
+
};
|
|
3940
|
+
const setMergeableContent = (mergeableContent) =>
|
|
3941
|
+
disableListeningToRawStoreChanges(() =>
|
|
3942
|
+
validateMergeableContent(mergeableContent)
|
|
3943
|
+
? store.transaction(() => {
|
|
3944
|
+
store.delTables().delValues();
|
|
3945
|
+
contentStampMap = newContentStampMap();
|
|
3946
|
+
store.applyChanges(mergeContentOrChanges(mergeableContent, 1));
|
|
3947
|
+
})
|
|
3948
|
+
: 0,
|
|
3949
|
+
);
|
|
3950
|
+
const setDefaultContent = (content) => {
|
|
3951
|
+
store.transaction(() => {
|
|
3952
|
+
defaultingContent = 1;
|
|
3953
|
+
store.setContent(content);
|
|
3954
|
+
defaultingContent = 0;
|
|
3955
|
+
});
|
|
3956
|
+
return mergeableStore;
|
|
3957
|
+
};
|
|
3958
|
+
const getTransactionMergeableChanges = () => {
|
|
3959
|
+
const [[tableStampMaps, tablesTime], [valueStampMaps, valuesTime]] =
|
|
3960
|
+
contentStampMap;
|
|
3961
|
+
const tablesObj = {};
|
|
3962
|
+
collForEach(touchedCells, (touchedTable, tableId) =>
|
|
3963
|
+
ifNotUndefined(
|
|
3964
|
+
mapGet(tableStampMaps, tableId),
|
|
3965
|
+
([rowStampMaps, tableTime]) => {
|
|
3966
|
+
const tableObj = {};
|
|
3967
|
+
collForEach(touchedTable, (touchedRow, rowId) =>
|
|
3968
|
+
ifNotUndefined(
|
|
3969
|
+
mapGet(rowStampMaps, rowId),
|
|
3970
|
+
([cellStampMaps, rowTime]) => {
|
|
3971
|
+
const rowObj = {};
|
|
3972
|
+
collForEach(touchedRow, (cellId) => {
|
|
3973
|
+
ifNotUndefined(
|
|
3974
|
+
mapGet(cellStampMaps, cellId),
|
|
3975
|
+
([cell, time]) => (rowObj[cellId] = newStamp(cell, time)),
|
|
3976
|
+
);
|
|
3977
|
+
});
|
|
3978
|
+
tableObj[rowId] = newStamp(rowObj, rowTime);
|
|
3979
|
+
},
|
|
3980
|
+
),
|
|
3981
|
+
);
|
|
3982
|
+
tablesObj[tableId] = newStamp(tableObj, tableTime);
|
|
3983
|
+
},
|
|
3984
|
+
),
|
|
3985
|
+
);
|
|
3986
|
+
const valuesObj = {};
|
|
3987
|
+
collForEach(touchedValues, (valueId) =>
|
|
3988
|
+
ifNotUndefined(
|
|
3989
|
+
mapGet(valueStampMaps, valueId),
|
|
3990
|
+
([value, time]) => (valuesObj[valueId] = newStamp(value, time)),
|
|
3991
|
+
),
|
|
3992
|
+
);
|
|
3993
|
+
return [
|
|
3994
|
+
newStamp(tablesObj, tablesTime),
|
|
3995
|
+
newStamp(valuesObj, valuesTime),
|
|
3996
|
+
1,
|
|
3997
|
+
];
|
|
3998
|
+
};
|
|
3999
|
+
const applyMergeableChanges = (mergeableChanges) =>
|
|
4000
|
+
disableListeningToRawStoreChanges(() =>
|
|
4001
|
+
store.applyChanges(mergeContentOrChanges(mergeableChanges)),
|
|
4002
|
+
);
|
|
4003
|
+
const merge = (mergeableStore2) => {
|
|
4004
|
+
const mergeableChanges = getMergeableContent();
|
|
4005
|
+
const mergeableChanges2 = mergeableStore2.getMergeableContent();
|
|
4006
|
+
mergeableStore2.applyMergeableChanges(mergeableChanges);
|
|
4007
|
+
return applyMergeableChanges(mergeableChanges2);
|
|
4008
|
+
};
|
|
4009
|
+
const mergeableStore = {
|
|
4010
|
+
getId,
|
|
4011
|
+
getMergeableContent,
|
|
4012
|
+
getMergeableContentHashes,
|
|
4013
|
+
getMergeableTableHashes,
|
|
4014
|
+
getMergeableTableDiff,
|
|
4015
|
+
getMergeableRowHashes,
|
|
4016
|
+
getMergeableRowDiff,
|
|
4017
|
+
getMergeableCellHashes,
|
|
4018
|
+
getMergeableCellDiff,
|
|
4019
|
+
getMergeableValuesHashes,
|
|
4020
|
+
getMergeableValueDiff,
|
|
4021
|
+
setMergeableContent,
|
|
4022
|
+
setDefaultContent,
|
|
4023
|
+
getTransactionMergeableChanges,
|
|
4024
|
+
applyMergeableChanges,
|
|
4025
|
+
merge,
|
|
4026
|
+
};
|
|
4027
|
+
store.setInternalListeners(
|
|
4028
|
+
preStartTransaction,
|
|
4029
|
+
preFinishTransaction,
|
|
4030
|
+
postFinishTransaction,
|
|
4031
|
+
cellChanged,
|
|
4032
|
+
valueChanged,
|
|
4033
|
+
);
|
|
4034
|
+
objToArray(
|
|
4035
|
+
store,
|
|
4036
|
+
(method, name) =>
|
|
4037
|
+
(mergeableStore[name] = // fluent methods
|
|
4038
|
+
strStartsWith(name, 'set') ||
|
|
4039
|
+
strStartsWith(name, 'del') ||
|
|
4040
|
+
strStartsWith(name, 'apply') ||
|
|
4041
|
+
strEndsWith(name, 'Transaction') ||
|
|
4042
|
+
name == 'callListener'
|
|
4043
|
+
? (...args) => {
|
|
4044
|
+
method(...args);
|
|
4045
|
+
return mergeableStore;
|
|
4046
|
+
}
|
|
4047
|
+
: strStartsWith(name, 'add') && strEndsWith(name, 'Listener')
|
|
4048
|
+
? (...args) => {
|
|
4049
|
+
const listenerArg = LISTENER_ARGS[slice(name, 3, -8)] ?? 0;
|
|
4050
|
+
const listener = args[listenerArg];
|
|
4051
|
+
args[listenerArg] = (_store, ...args2) =>
|
|
4052
|
+
listener(mergeableStore, ...args2);
|
|
4053
|
+
return method(...args);
|
|
4054
|
+
}
|
|
4055
|
+
: method),
|
|
4056
|
+
);
|
|
4057
|
+
return objFreeze(mergeableStore);
|
|
4058
|
+
};
|
|
4059
|
+
|
|
3190
4060
|
export {
|
|
3191
4061
|
createCheckpoints,
|
|
3192
4062
|
createCustomPersister,
|
|
4063
|
+
createCustomSynchronizer,
|
|
3193
4064
|
createIndexes,
|
|
4065
|
+
createMergeableStore,
|
|
3194
4066
|
createMetrics,
|
|
3195
4067
|
createQueries,
|
|
3196
4068
|
createRelationships,
|