tinybase 9.1.0-beta.0 → 9.1.0-beta.1
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/@types/common/index.d.ts +17 -2
- package/@types/common/with-schemas/index.d.ts +18 -2
- package/@types/store/index.d.ts +37 -7
- package/@types/store/with-schemas/index.d.ts +38 -7
- package/@types/ui-react/index.d.ts +6 -2
- package/@types/ui-react/with-schemas/index.d.ts +7 -2
- package/@types/ui-solid/index.d.ts +9 -2
- package/@types/ui-solid/with-schemas/index.d.ts +10 -2
- package/@types/ui-svelte/index.d.ts +50 -2
- package/@types/ui-svelte/with-schemas/index.d.ts +88 -25
- package/index.js +34 -6
- package/mergeable-store/index.js +34 -6
- package/mergeable-store/with-schemas/index.js +34 -6
- package/min/index.js +1 -1
- package/min/index.js.gz +0 -0
- package/min/mergeable-store/index.js +1 -1
- package/min/mergeable-store/index.js.gz +0 -0
- package/min/mergeable-store/with-schemas/index.js +1 -1
- package/min/mergeable-store/with-schemas/index.js.gz +0 -0
- package/min/omni/index.js +1 -1
- package/min/omni/index.js.gz +0 -0
- package/min/omni/with-schemas/index.js +1 -1
- package/min/omni/with-schemas/index.js.gz +0 -0
- package/min/store/index.js +1 -1
- package/min/store/index.js.gz +0 -0
- package/min/store/with-schemas/index.js +1 -1
- package/min/store/with-schemas/index.js.gz +0 -0
- package/min/ui-react/index.js +1 -1
- package/min/ui-react/index.js.gz +0 -0
- package/min/ui-react/with-schemas/index.js +1 -1
- package/min/ui-react/with-schemas/index.js.gz +0 -0
- package/min/ui-react-dom/index.js +1 -1
- package/min/ui-react-dom/index.js.gz +0 -0
- package/min/ui-react-dom/with-schemas/index.js +1 -1
- package/min/ui-react-dom/with-schemas/index.js.gz +0 -0
- package/min/ui-react-dom-charts/index.js +1 -1
- package/min/ui-react-dom-charts/index.js.gz +0 -0
- package/min/ui-react-dom-charts/with-schemas/index.js +1 -1
- package/min/ui-react-dom-charts/with-schemas/index.js.gz +0 -0
- package/min/ui-react-inspector/index.js +1 -1
- package/min/ui-react-inspector/index.js.gz +0 -0
- package/min/ui-react-inspector/with-schemas/index.js +1 -1
- package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
- package/min/ui-solid/index.js +1 -1
- package/min/ui-solid/index.js.gz +0 -0
- package/min/ui-solid/with-schemas/index.js +1 -1
- package/min/ui-solid/with-schemas/index.js.gz +0 -0
- package/min/ui-solid-dom/index.js +1 -1
- package/min/ui-solid-dom/index.js.gz +0 -0
- package/min/ui-solid-dom/with-schemas/index.js +1 -1
- package/min/ui-solid-dom/with-schemas/index.js.gz +0 -0
- package/min/ui-solid-inspector/index.js +1 -1
- package/min/ui-solid-inspector/index.js.gz +0 -0
- package/min/ui-solid-inspector/with-schemas/index.js +1 -1
- package/min/ui-solid-inspector/with-schemas/index.js.gz +0 -0
- package/min/ui-svelte/index.js +1 -1
- package/min/ui-svelte/index.js.gz +0 -0
- package/min/ui-svelte/with-schemas/index.js +1 -1
- package/min/ui-svelte/with-schemas/index.js.gz +0 -0
- package/min/ui-svelte-dom/index.js +1 -1
- package/min/ui-svelte-dom/index.js.gz +0 -0
- package/min/ui-svelte-dom/with-schemas/index.js +1 -1
- package/min/ui-svelte-dom/with-schemas/index.js.gz +0 -0
- package/min/ui-svelte-inspector/index.js +1 -1
- package/min/ui-svelte-inspector/index.js.gz +0 -0
- package/min/ui-svelte-inspector/with-schemas/index.js +1 -1
- package/min/ui-svelte-inspector/with-schemas/index.js.gz +0 -0
- package/min/with-schemas/index.js +1 -1
- package/min/with-schemas/index.js.gz +0 -0
- package/omni/index.js +34 -6
- package/omni/with-schemas/index.js +34 -6
- package/package.json +3 -3
- package/releases.md +1 -1
- package/store/index.js +34 -6
- package/store/with-schemas/index.js +34 -6
- package/ui-react/index.js +36 -6
- package/ui-react/with-schemas/index.js +36 -6
- package/ui-react-dom/index.js +24 -4
- package/ui-react-dom/with-schemas/index.js +24 -4
- package/ui-react-dom-charts/index.js +24 -4
- package/ui-react-dom-charts/with-schemas/index.js +24 -4
- package/ui-react-inspector/index.js +58 -10
- package/ui-react-inspector/with-schemas/index.js +58 -10
- package/ui-solid/index.js +32 -2
- package/ui-solid/with-schemas/index.js +32 -2
- package/ui-solid-dom/index.js +17 -1
- package/ui-solid-dom/with-schemas/index.js +17 -1
- package/ui-solid-inspector/index.js +51 -7
- package/ui-solid-inspector/with-schemas/index.js +51 -7
- package/ui-svelte/index.js +73 -31
- package/ui-svelte/with-schemas/index.js +73 -31
- package/ui-svelte-dom/index.js +35 -14
- package/ui-svelte-dom/with-schemas/index.js +35 -14
- package/ui-svelte-inspector/index.js +69 -20
- package/ui-svelte-inspector/with-schemas/index.js +69 -20
- package/with-schemas/index.js +34 -6
package/omni/index.js
CHANGED
|
@@ -2206,13 +2206,36 @@ const createStore = () => {
|
|
|
2206
2206
|
listener,
|
|
2207
2207
|
mutator,
|
|
2208
2208
|
) => {
|
|
2209
|
-
|
|
2209
|
+
const [descending, offset, limit, sorter] = otherArgs;
|
|
2210
|
+
let sortedRowIds = getSortedRowIds(
|
|
2211
|
+
tableId,
|
|
2212
|
+
cellId,
|
|
2213
|
+
descending,
|
|
2214
|
+
offset,
|
|
2215
|
+
limit,
|
|
2216
|
+
sorter,
|
|
2217
|
+
);
|
|
2210
2218
|
return addListener(
|
|
2211
2219
|
() => {
|
|
2212
|
-
const newSortedRowIds = getSortedRowIds(
|
|
2220
|
+
const newSortedRowIds = getSortedRowIds(
|
|
2221
|
+
tableId,
|
|
2222
|
+
cellId,
|
|
2223
|
+
descending,
|
|
2224
|
+
offset,
|
|
2225
|
+
limit,
|
|
2226
|
+
sorter,
|
|
2227
|
+
);
|
|
2213
2228
|
if (!arrayIsEqual(newSortedRowIds, sortedRowIds)) {
|
|
2214
2229
|
sortedRowIds = newSortedRowIds;
|
|
2215
|
-
listener(
|
|
2230
|
+
listener(
|
|
2231
|
+
store,
|
|
2232
|
+
tableId,
|
|
2233
|
+
cellId,
|
|
2234
|
+
descending,
|
|
2235
|
+
offset,
|
|
2236
|
+
limit,
|
|
2237
|
+
sortedRowIds,
|
|
2238
|
+
);
|
|
2216
2239
|
}
|
|
2217
2240
|
},
|
|
2218
2241
|
sortedRowIdsListeners[mutator ? 1 : 0],
|
|
@@ -2266,6 +2289,7 @@ const createStore = () => {
|
|
|
2266
2289
|
descending,
|
|
2267
2290
|
offset = 0,
|
|
2268
2291
|
limit,
|
|
2292
|
+
sorter = defaultSorter,
|
|
2269
2293
|
) =>
|
|
2270
2294
|
isObject(tableIdOrArgs)
|
|
2271
2295
|
? getSortedRowIds(
|
|
@@ -2274,16 +2298,19 @@ const createStore = () => {
|
|
|
2274
2298
|
tableIdOrArgs.descending,
|
|
2275
2299
|
tableIdOrArgs.offset,
|
|
2276
2300
|
tableIdOrArgs.limit,
|
|
2301
|
+
tableIdOrArgs.sorter,
|
|
2277
2302
|
)
|
|
2278
2303
|
: arrayMap(
|
|
2279
2304
|
slice(
|
|
2280
2305
|
arraySort(
|
|
2281
2306
|
mapMap(mapGet(tablesMap, id(tableIdOrArgs)), (row, rowId) => [
|
|
2282
|
-
isUndefined(cellId)
|
|
2307
|
+
isUndefined(cellId)
|
|
2308
|
+
? rowId
|
|
2309
|
+
: decodeIfJson(mapGet(row, id(cellId))),
|
|
2283
2310
|
rowId,
|
|
2284
2311
|
]),
|
|
2285
2312
|
([cell1], [cell2]) =>
|
|
2286
|
-
|
|
2313
|
+
sorter(cell1, cell2) * (descending ? -1 : 1),
|
|
2287
2314
|
),
|
|
2288
2315
|
offset,
|
|
2289
2316
|
isUndefined(limit) ? limit : offset + limit,
|
|
@@ -2761,6 +2788,7 @@ const createStore = () => {
|
|
|
2761
2788
|
tableIdOrArgs.descending ?? false,
|
|
2762
2789
|
tableIdOrArgs.offset ?? 0,
|
|
2763
2790
|
tableIdOrArgs.limit,
|
|
2791
|
+
tableIdOrArgs.sorter,
|
|
2764
2792
|
],
|
|
2765
2793
|
cellIdOrListener,
|
|
2766
2794
|
descendingOrMutator,
|
|
@@ -2768,7 +2796,7 @@ const createStore = () => {
|
|
|
2768
2796
|
: addSortedRowIdsListenerImpl(
|
|
2769
2797
|
tableIdOrArgs,
|
|
2770
2798
|
cellIdOrListener,
|
|
2771
|
-
[descendingOrMutator, offset, limit],
|
|
2799
|
+
[descendingOrMutator, offset, limit, void 0],
|
|
2772
2800
|
listener,
|
|
2773
2801
|
mutator,
|
|
2774
2802
|
);
|
|
@@ -2206,13 +2206,36 @@ const createStore = () => {
|
|
|
2206
2206
|
listener,
|
|
2207
2207
|
mutator,
|
|
2208
2208
|
) => {
|
|
2209
|
-
|
|
2209
|
+
const [descending, offset, limit, sorter] = otherArgs;
|
|
2210
|
+
let sortedRowIds = getSortedRowIds(
|
|
2211
|
+
tableId,
|
|
2212
|
+
cellId,
|
|
2213
|
+
descending,
|
|
2214
|
+
offset,
|
|
2215
|
+
limit,
|
|
2216
|
+
sorter,
|
|
2217
|
+
);
|
|
2210
2218
|
return addListener(
|
|
2211
2219
|
() => {
|
|
2212
|
-
const newSortedRowIds = getSortedRowIds(
|
|
2220
|
+
const newSortedRowIds = getSortedRowIds(
|
|
2221
|
+
tableId,
|
|
2222
|
+
cellId,
|
|
2223
|
+
descending,
|
|
2224
|
+
offset,
|
|
2225
|
+
limit,
|
|
2226
|
+
sorter,
|
|
2227
|
+
);
|
|
2213
2228
|
if (!arrayIsEqual(newSortedRowIds, sortedRowIds)) {
|
|
2214
2229
|
sortedRowIds = newSortedRowIds;
|
|
2215
|
-
listener(
|
|
2230
|
+
listener(
|
|
2231
|
+
store,
|
|
2232
|
+
tableId,
|
|
2233
|
+
cellId,
|
|
2234
|
+
descending,
|
|
2235
|
+
offset,
|
|
2236
|
+
limit,
|
|
2237
|
+
sortedRowIds,
|
|
2238
|
+
);
|
|
2216
2239
|
}
|
|
2217
2240
|
},
|
|
2218
2241
|
sortedRowIdsListeners[mutator ? 1 : 0],
|
|
@@ -2266,6 +2289,7 @@ const createStore = () => {
|
|
|
2266
2289
|
descending,
|
|
2267
2290
|
offset = 0,
|
|
2268
2291
|
limit,
|
|
2292
|
+
sorter = defaultSorter,
|
|
2269
2293
|
) =>
|
|
2270
2294
|
isObject(tableIdOrArgs)
|
|
2271
2295
|
? getSortedRowIds(
|
|
@@ -2274,16 +2298,19 @@ const createStore = () => {
|
|
|
2274
2298
|
tableIdOrArgs.descending,
|
|
2275
2299
|
tableIdOrArgs.offset,
|
|
2276
2300
|
tableIdOrArgs.limit,
|
|
2301
|
+
tableIdOrArgs.sorter,
|
|
2277
2302
|
)
|
|
2278
2303
|
: arrayMap(
|
|
2279
2304
|
slice(
|
|
2280
2305
|
arraySort(
|
|
2281
2306
|
mapMap(mapGet(tablesMap, id(tableIdOrArgs)), (row, rowId) => [
|
|
2282
|
-
isUndefined(cellId)
|
|
2307
|
+
isUndefined(cellId)
|
|
2308
|
+
? rowId
|
|
2309
|
+
: decodeIfJson(mapGet(row, id(cellId))),
|
|
2283
2310
|
rowId,
|
|
2284
2311
|
]),
|
|
2285
2312
|
([cell1], [cell2]) =>
|
|
2286
|
-
|
|
2313
|
+
sorter(cell1, cell2) * (descending ? -1 : 1),
|
|
2287
2314
|
),
|
|
2288
2315
|
offset,
|
|
2289
2316
|
isUndefined(limit) ? limit : offset + limit,
|
|
@@ -2761,6 +2788,7 @@ const createStore = () => {
|
|
|
2761
2788
|
tableIdOrArgs.descending ?? false,
|
|
2762
2789
|
tableIdOrArgs.offset ?? 0,
|
|
2763
2790
|
tableIdOrArgs.limit,
|
|
2791
|
+
tableIdOrArgs.sorter,
|
|
2764
2792
|
],
|
|
2765
2793
|
cellIdOrListener,
|
|
2766
2794
|
descendingOrMutator,
|
|
@@ -2768,7 +2796,7 @@ const createStore = () => {
|
|
|
2768
2796
|
: addSortedRowIdsListenerImpl(
|
|
2769
2797
|
tableIdOrArgs,
|
|
2770
2798
|
cellIdOrListener,
|
|
2771
|
-
[descendingOrMutator, offset, limit],
|
|
2799
|
+
[descendingOrMutator, offset, limit, void 0],
|
|
2772
2800
|
listener,
|
|
2773
2801
|
mutator,
|
|
2774
2802
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tinybase",
|
|
3
|
-
"version": "9.1.0-beta.
|
|
3
|
+
"version": "9.1.0-beta.1",
|
|
4
4
|
"author": "jamesgpearce",
|
|
5
5
|
"repository": "github:tinyplex/tinybase",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"sideEffects": false,
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"@automerge/automerge-repo": "^2.5.6",
|
|
27
|
-
"@cloudflare/workers-types": "^5.
|
|
27
|
+
"@cloudflare/workers-types": "^5.20260704.1",
|
|
28
28
|
"@electric-sql/pglite": "^0.5.4",
|
|
29
29
|
"@libsql/client": "^0.17.4",
|
|
30
30
|
"@powersync/common": "^1.57.0",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"bun": "^1.3.14",
|
|
36
36
|
"effect": "^3.21.4",
|
|
37
37
|
"electric-sql": "^0.12.1",
|
|
38
|
-
"expo": "^57.0.
|
|
38
|
+
"expo": "^57.0.2",
|
|
39
39
|
"expo-sqlite": "^57.0.0",
|
|
40
40
|
"partykit": "^0.0.115",
|
|
41
41
|
"partysocket": "^1.3.0",
|
package/releases.md
CHANGED
|
@@ -13,7 +13,7 @@ console.log(valuesSubsetDatabasePersisterConfig.values.load);
|
|
|
13
13
|
// -> ['selectedPet', 'open']
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
<p>When a subset is configured, unlisted <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> are not saved, and unlisted columns in the <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> database table are left untouched.</p><h2 id="websocket-synchronization-fixes">WebSocket <a href="https://tinybase.org/guides/synchronization/">Synchronization</a> Fixes</h2><p>WebSocket Synchronizers can now fragment large synchronization payloads and reassemble them on receipt. This helps deployments behind infrastructure with WebSocket message size limits, such as Cloudflare Workers and Durable Objects (<a href="https://github.com/tinyplex/tinybase/issues/261">#261</a>).</p><p>The createWsSynchronizer and <a href="https://tinybase.org/api/synchronizer-ws-server/functions/creation/createwsserver/"><code>createWsServer</code></a> functions now accept an optional fragment size argument. Incomplete fragment buffers expire using the existing request timeout, which can also now be set on createWsServer. Durable Object servers can override the getFragmentSize and <a href="https://tinybase.org/api/synchronizer-ws-server-durable-object/classes/creation/wsserverdurableobject/methods/getter/getrequesttimeoutseconds/"><code>getRequestTimeoutSeconds</code></a> methods to set the same behavior for messages they send.</p><p>The WebSocket <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> documentation now also clarifies that <a href="https://tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> paths come from WebSocket URL paths, not <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a>, so clients that need separate synchronization groups should connect to different URL paths (<a href="https://github.com/tinyplex/tinybase/issues/206">#206</a>).</p><p>When a persisted <a href="https://tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> path starts after having no connected clients, it now loads its persisted <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> before starting synchronization. This means the first client to reconnect is sent only the data it is missing, instead of receiving the whole persisted <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> as a fresh change (<a href="https://github.com/tinyplex/tinybase/issues/205">#205</a>).</p><h2 id="schema-default-synchronization-fixes">Schema Default <a href="https://tinybase.org/guides/synchronization/">Synchronization</a> Fixes</h2><p>Schema defaults inserted automatically into MergeableStores now use neutral timestamps, so defaulted <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> and Cells no longer overwrite newer synced data from another peer. Explicit writes of default values still receive normal timestamps (<a href="https://github.com/tinyplex/tinybase/issues/167">#167</a>).</p><h2 id="powersync-persistence-fixes">PowerSync <a href="https://tinybase.org/guides/persistence/">Persistence</a> Fixes</h2><p>The PowerSync <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> now updates existing tabular rows before inserting missing ones, instead of replacing whole rows during upserts. This avoids flooding PowerSync upload queues with replacement writes when schema validation causes loaded data to be written back unchanged on startup (<a href="https://github.com/tinyplex/tinybase/issues/262">#262</a>).</p><h2 id="custom-persister-loading-fixes">Custom <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> Loading Fixes</h2><p>Custom Persisters can now return <code>undefined</code> from <code>getPersisted</code> to indicate that there is no persisted content. Loading then uses <code>initialContent</code> if it was provided, or otherwise leaves the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> unchanged without invoking the ignored error handler (<a href="https://github.com/tinyplex/tinybase/issues/161">#161</a>).</p><h2 id="durable-object-persistence-fixes">Durable Object <a href="https://tinybase.org/guides/persistence/">Persistence</a> Fixes</h2><p>The Durable Object SQL Storage <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>'s fragmented mode now stores table row data as one SQL row per TinyBase <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a>, instead of one SQL row per <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a>. This reduces the number of SQLite writes for wide Rows while preserving the fragmented mode's protection from Cloudflare's 2MB row limit. Existing cell-level fragmented data is still loaded and is cleaned up when the <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> is next saved (<a href="https://github.com/tinyplex/tinybase/issues/268">#268</a>).</p><h2 id="query-transaction-fixes">Query Transaction Fixes</h2><p>Grouped queries, including those with having clauses, now correctly return their current result when a query definition is added during an active <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> transaction (<a href="https://github.com/tinyplex/tinybase/issues/259">#259</a>).</p><h2 id="query-documentation-clarifications">Query <a href="https://tinybase.org/guides/how-tinybase-is-built/documentation/">Documentation</a> Clarifications</h2><p>The <a href="https://tinybase.org/guides/using-queries/tinyql/">TinyQL</a> documentation now explicitly describes that a <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> only appears in a query result when at least one selected <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> or calculated value is defined. If all selected values for a <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> resolve to <code>undefined</code>, no <a href="https://tinybase.org/api/queries/type-aliases/result/resultrow/"><code>ResultRow</code></a> is created for that <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> (<a href="https://github.com/tinyplex/tinybase/issues/183">#183</a>).</p><h2 id="type-fixes">Type Fixes</h2><p>The schema-aware <a href="https://tinybase.org/api/mergeable-store/type-aliases/mergeable/mergeablecontent/"><code>MergeableContent</code></a>, <a href="https://tinybase.org/api/mergeable-store/type-aliases/mergeable/mergeablechanges/"><code>MergeableChanges</code></a>, persisted content, and <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> listener types now validate content being set or loaded in the same way as <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> setters. This catches invalid <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> or <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> and values in custom Persisters and <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> setters (<a href="https://github.com/tinyplex/tinybase/issues/178">#178</a>).</p><h2 id="breaking-change">Breaking Change</h2><p>This release is a major version because the Durable Object SQL Storage <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>'s fragmented mode uses a new storage layout. TinyBase v9.0 can read the old cell-level fragmented data written by earlier releases, but once it saves the new row-level fragmented data, older TinyBase versions are not designed to read that data back. Apps using fragmented Durable Object SQL storage should not roll those Durable Objects back to an earlier TinyBase version after v9.0 has written to them.</p><h2 id="thank-you">Thank You</h2><p>Thanks to everyone whose reports and fixes shaped this release:</p><p><a href="https://github.com/dheerajvs">Dheeraj</a>, <a href="https://github.com/jakubriedl">Jakub Riedl</a>, <a href="https://github.com/patrykwegrzyn">Patryk Wegrzyn</a>, <a href="https://github.com/dsrominiyi">Damilola Romniyi</a>, <a href="https://github.com/a11rew">Andrew Glago</a>, <a href="https://github.com/wattroll">wattroll</a>, <a href="https://github.com/willhoney7">Will Honey</a>, and <a href="https://github.com/danielberndt">Daniel Berndt</a>.</p><p>Couldn't do it without you!</p><hr><h1 id="v8-5">v8.5</h1><h2 id="react-chart-components">React Chart Components</h2><p>This release adds the new <a href="https://tinybase.org/api/ui-react-dom-charts/"><code>ui-react-dom-charts</code></a> module, providing reactive SVG chart components for React apps.</p><p>The <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/linechart/"><code>LineChart</code></a> component and <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/barchart/"><code>BarChart</code></a> component can render data directly from a <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>, or from a <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> <a href="https://tinybase.org/api/queries/type-aliases/result/resulttable/"><code>ResultTable</code></a>, using the same Provider context patterns as the rest of the React UI modules. For more complex charts, the <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/cartesianchart/"><code>CartesianChart</code></a> component can compose multiple <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/lineseries/"><code>LineSeries</code></a> component children and <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/barseries/"><code>BarSeries</code></a> component children in one SVG.</p><p><img src="https://tinybase.org/shots/styled-chart-react-demo.png" alt="LineChart component (React)" title="[`LineChart`](/api/ui-react-dom-charts/functions/store-components/linechart/)
|
|
16
|
+
<p>When a subset is configured, unlisted <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> are not saved, and unlisted columns in the <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> database table are left untouched.</p><h2 id="websocket-synchronization-fixes">WebSocket <a href="https://tinybase.org/guides/synchronization/">Synchronization</a> Fixes</h2><p>WebSocket Synchronizers can now fragment large synchronization payloads and reassemble them on receipt. This helps deployments behind infrastructure with WebSocket message size limits, such as Cloudflare Workers and Durable Objects (<a href="https://github.com/tinyplex/tinybase/issues/261">#261</a>).</p><p>The createWsSynchronizer and <a href="https://tinybase.org/api/synchronizer-ws-server/functions/creation/createwsserver/"><code>createWsServer</code></a> functions now accept an optional fragment size argument. Incomplete fragment buffers expire using the existing request timeout, which can also now be set on createWsServer. Durable Object servers can override the getFragmentSize and <a href="https://tinybase.org/api/synchronizer-ws-server-durable-object/classes/creation/wsserverdurableobject/methods/getter/getrequesttimeoutseconds/"><code>getRequestTimeoutSeconds</code></a> methods to set the same behavior for messages they send.</p><p>The WebSocket <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> documentation now also clarifies that <a href="https://tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> paths come from WebSocket URL paths, not <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a>, so clients that need separate synchronization groups should connect to different URL paths (<a href="https://github.com/tinyplex/tinybase/issues/206">#206</a>).</p><p>When a persisted <a href="https://tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> path starts after having no connected clients, it now loads its persisted <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> before starting synchronization. This means the first client to reconnect is sent only the data it is missing, instead of receiving the whole persisted <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> as a fresh change (<a href="https://github.com/tinyplex/tinybase/issues/205">#205</a>).</p><h2 id="schema-default-synchronization-fixes">Schema Default <a href="https://tinybase.org/guides/synchronization/">Synchronization</a> Fixes</h2><p>Schema defaults inserted automatically into MergeableStores now use neutral timestamps, so defaulted <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> and Cells no longer overwrite newer synced data from another peer. Explicit writes of default values still receive normal timestamps (<a href="https://github.com/tinyplex/tinybase/issues/167">#167</a>).</p><h2 id="powersync-persistence-fixes">PowerSync <a href="https://tinybase.org/guides/persistence/">Persistence</a> Fixes</h2><p>The PowerSync <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> now updates existing tabular rows before inserting missing ones, instead of replacing whole rows during upserts. This avoids flooding PowerSync upload queues with replacement writes when schema validation causes loaded data to be written back unchanged on startup (<a href="https://github.com/tinyplex/tinybase/issues/262">#262</a>).</p><h2 id="custom-persister-loading-fixes">Custom <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> Loading Fixes</h2><p>Custom Persisters can now return <code>undefined</code> from <code>getPersisted</code> to indicate that there is no persisted content. Loading then uses <code>initialContent</code> if it was provided, or otherwise leaves the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> unchanged without invoking the ignored error handler (<a href="https://github.com/tinyplex/tinybase/issues/161">#161</a>).</p><h2 id="durable-object-persistence-fixes">Durable Object <a href="https://tinybase.org/guides/persistence/">Persistence</a> Fixes</h2><p>The Durable Object SQL Storage <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>'s fragmented mode now stores table row data as one SQL row per TinyBase <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a>, instead of one SQL row per <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a>. This reduces the number of SQLite writes for wide Rows while preserving the fragmented mode's protection from Cloudflare's 2MB row limit. Existing cell-level fragmented data is still loaded and is cleaned up when the <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> is next saved (<a href="https://github.com/tinyplex/tinybase/issues/268">#268</a>).</p><h2 id="query-transaction-fixes">Query Transaction Fixes</h2><p>Grouped queries, including those with having clauses, now correctly return their current result when a query definition is added during an active <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> transaction (<a href="https://github.com/tinyplex/tinybase/issues/259">#259</a>).</p><h2 id="query-documentation-clarifications">Query <a href="https://tinybase.org/guides/how-tinybase-is-built/documentation/">Documentation</a> Clarifications</h2><p>The <a href="https://tinybase.org/guides/using-queries/tinyql/">TinyQL</a> documentation now explicitly describes that a <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> only appears in a query result when at least one selected <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> or calculated value is defined. If all selected values for a <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> resolve to <code>undefined</code>, no <a href="https://tinybase.org/api/queries/type-aliases/result/resultrow/"><code>ResultRow</code></a> is created for that <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> (<a href="https://github.com/tinyplex/tinybase/issues/183">#183</a>).</p><h2 id="type-fixes">Type Fixes</h2><p>The schema-aware <a href="https://tinybase.org/api/mergeable-store/type-aliases/mergeable/mergeablecontent/"><code>MergeableContent</code></a>, <a href="https://tinybase.org/api/mergeable-store/type-aliases/mergeable/mergeablechanges/"><code>MergeableChanges</code></a>, persisted content, and <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> listener types now validate content being set or loaded in the same way as <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> setters. This catches invalid <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> or <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> and values in custom Persisters and <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> setters (<a href="https://github.com/tinyplex/tinybase/issues/178">#178</a>).</p><h2 id="breaking-change">Breaking Change</h2><p>This release is a major version because the Durable Object SQL Storage <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>'s fragmented mode uses a new storage layout. TinyBase v9.0 can read the old cell-level fragmented data written by earlier releases, but once it saves the new row-level fragmented data, older TinyBase versions are not designed to read that data back. Apps using fragmented Durable Object SQL storage should not roll those Durable Objects back to an earlier TinyBase version after v9.0 has written to them.</p><h2 id="thank-you">Thank You</h2><p>Thanks to everyone whose reports and fixes shaped this release:</p><p><a href="https://github.com/dheerajvs">Dheeraj</a>, <a href="https://github.com/jakubriedl">Jakub Riedl</a>, <a href="https://github.com/patrykwegrzyn">Patryk Wegrzyn</a>, <a href="https://github.com/dsrominiyi">Damilola Romniyi</a>, <a href="https://github.com/a11rew">Andrew Glago</a>, <a href="https://github.com/wattroll">wattroll</a>, <a href="https://github.com/willhoney7">Will Honey</a>, and <a href="https://github.com/danielberndt">Daniel Berndt</a>.</p><p>Could not do it without you!</p><hr><h1 id="v8-5">v8.5</h1><h2 id="react-chart-components">React Chart Components</h2><p>This release adds the new <a href="https://tinybase.org/api/ui-react-dom-charts/"><code>ui-react-dom-charts</code></a> module, providing reactive SVG chart components for React apps.</p><p>The <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/linechart/"><code>LineChart</code></a> component and <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/barchart/"><code>BarChart</code></a> component can render data directly from a <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>, or from a <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> <a href="https://tinybase.org/api/queries/type-aliases/result/resulttable/"><code>ResultTable</code></a>, using the same Provider context patterns as the rest of the React UI modules. For more complex charts, the <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/cartesianchart/"><code>CartesianChart</code></a> component can compose multiple <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/lineseries/"><code>LineSeries</code></a> component children and <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/barseries/"><code>BarSeries</code></a> component children in one SVG.</p><p><img src="https://tinybase.org/shots/styled-chart-react-demo.png" alt="LineChart component (React)" title="[`LineChart`](/api/ui-react-dom-charts/functions/store-components/linechart/)
|
|
17
17
|
component (React)"></p><p>A chart can be bound to a <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> with just the <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> and the <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> to use for the x and y values:</p>
|
|
18
18
|
|
|
19
19
|
```jsx
|
package/store/index.js
CHANGED
|
@@ -1314,13 +1314,36 @@ const createStore = () => {
|
|
|
1314
1314
|
listener,
|
|
1315
1315
|
mutator,
|
|
1316
1316
|
) => {
|
|
1317
|
-
|
|
1317
|
+
const [descending, offset, limit, sorter] = otherArgs;
|
|
1318
|
+
let sortedRowIds = getSortedRowIds(
|
|
1319
|
+
tableId,
|
|
1320
|
+
cellId,
|
|
1321
|
+
descending,
|
|
1322
|
+
offset,
|
|
1323
|
+
limit,
|
|
1324
|
+
sorter,
|
|
1325
|
+
);
|
|
1318
1326
|
return addListener(
|
|
1319
1327
|
() => {
|
|
1320
|
-
const newSortedRowIds = getSortedRowIds(
|
|
1328
|
+
const newSortedRowIds = getSortedRowIds(
|
|
1329
|
+
tableId,
|
|
1330
|
+
cellId,
|
|
1331
|
+
descending,
|
|
1332
|
+
offset,
|
|
1333
|
+
limit,
|
|
1334
|
+
sorter,
|
|
1335
|
+
);
|
|
1321
1336
|
if (!arrayIsEqual(newSortedRowIds, sortedRowIds)) {
|
|
1322
1337
|
sortedRowIds = newSortedRowIds;
|
|
1323
|
-
listener(
|
|
1338
|
+
listener(
|
|
1339
|
+
store,
|
|
1340
|
+
tableId,
|
|
1341
|
+
cellId,
|
|
1342
|
+
descending,
|
|
1343
|
+
offset,
|
|
1344
|
+
limit,
|
|
1345
|
+
sortedRowIds,
|
|
1346
|
+
);
|
|
1324
1347
|
}
|
|
1325
1348
|
},
|
|
1326
1349
|
sortedRowIdsListeners[mutator ? 1 : 0],
|
|
@@ -1374,6 +1397,7 @@ const createStore = () => {
|
|
|
1374
1397
|
descending,
|
|
1375
1398
|
offset = 0,
|
|
1376
1399
|
limit,
|
|
1400
|
+
sorter = defaultSorter,
|
|
1377
1401
|
) =>
|
|
1378
1402
|
isObject(tableIdOrArgs)
|
|
1379
1403
|
? getSortedRowIds(
|
|
@@ -1382,16 +1406,19 @@ const createStore = () => {
|
|
|
1382
1406
|
tableIdOrArgs.descending,
|
|
1383
1407
|
tableIdOrArgs.offset,
|
|
1384
1408
|
tableIdOrArgs.limit,
|
|
1409
|
+
tableIdOrArgs.sorter,
|
|
1385
1410
|
)
|
|
1386
1411
|
: arrayMap(
|
|
1387
1412
|
slice(
|
|
1388
1413
|
arraySort(
|
|
1389
1414
|
mapMap(mapGet(tablesMap, id(tableIdOrArgs)), (row, rowId) => [
|
|
1390
|
-
isUndefined(cellId)
|
|
1415
|
+
isUndefined(cellId)
|
|
1416
|
+
? rowId
|
|
1417
|
+
: decodeIfJson(mapGet(row, id(cellId))),
|
|
1391
1418
|
rowId,
|
|
1392
1419
|
]),
|
|
1393
1420
|
([cell1], [cell2]) =>
|
|
1394
|
-
|
|
1421
|
+
sorter(cell1, cell2) * (descending ? -1 : 1),
|
|
1395
1422
|
),
|
|
1396
1423
|
offset,
|
|
1397
1424
|
isUndefined(limit) ? limit : offset + limit,
|
|
@@ -1869,6 +1896,7 @@ const createStore = () => {
|
|
|
1869
1896
|
tableIdOrArgs.descending ?? false,
|
|
1870
1897
|
tableIdOrArgs.offset ?? 0,
|
|
1871
1898
|
tableIdOrArgs.limit,
|
|
1899
|
+
tableIdOrArgs.sorter,
|
|
1872
1900
|
],
|
|
1873
1901
|
cellIdOrListener,
|
|
1874
1902
|
descendingOrMutator,
|
|
@@ -1876,7 +1904,7 @@ const createStore = () => {
|
|
|
1876
1904
|
: addSortedRowIdsListenerImpl(
|
|
1877
1905
|
tableIdOrArgs,
|
|
1878
1906
|
cellIdOrListener,
|
|
1879
|
-
[descendingOrMutator, offset, limit],
|
|
1907
|
+
[descendingOrMutator, offset, limit, void 0],
|
|
1880
1908
|
listener,
|
|
1881
1909
|
mutator,
|
|
1882
1910
|
);
|
|
@@ -1314,13 +1314,36 @@ const createStore = () => {
|
|
|
1314
1314
|
listener,
|
|
1315
1315
|
mutator,
|
|
1316
1316
|
) => {
|
|
1317
|
-
|
|
1317
|
+
const [descending, offset, limit, sorter] = otherArgs;
|
|
1318
|
+
let sortedRowIds = getSortedRowIds(
|
|
1319
|
+
tableId,
|
|
1320
|
+
cellId,
|
|
1321
|
+
descending,
|
|
1322
|
+
offset,
|
|
1323
|
+
limit,
|
|
1324
|
+
sorter,
|
|
1325
|
+
);
|
|
1318
1326
|
return addListener(
|
|
1319
1327
|
() => {
|
|
1320
|
-
const newSortedRowIds = getSortedRowIds(
|
|
1328
|
+
const newSortedRowIds = getSortedRowIds(
|
|
1329
|
+
tableId,
|
|
1330
|
+
cellId,
|
|
1331
|
+
descending,
|
|
1332
|
+
offset,
|
|
1333
|
+
limit,
|
|
1334
|
+
sorter,
|
|
1335
|
+
);
|
|
1321
1336
|
if (!arrayIsEqual(newSortedRowIds, sortedRowIds)) {
|
|
1322
1337
|
sortedRowIds = newSortedRowIds;
|
|
1323
|
-
listener(
|
|
1338
|
+
listener(
|
|
1339
|
+
store,
|
|
1340
|
+
tableId,
|
|
1341
|
+
cellId,
|
|
1342
|
+
descending,
|
|
1343
|
+
offset,
|
|
1344
|
+
limit,
|
|
1345
|
+
sortedRowIds,
|
|
1346
|
+
);
|
|
1324
1347
|
}
|
|
1325
1348
|
},
|
|
1326
1349
|
sortedRowIdsListeners[mutator ? 1 : 0],
|
|
@@ -1374,6 +1397,7 @@ const createStore = () => {
|
|
|
1374
1397
|
descending,
|
|
1375
1398
|
offset = 0,
|
|
1376
1399
|
limit,
|
|
1400
|
+
sorter = defaultSorter,
|
|
1377
1401
|
) =>
|
|
1378
1402
|
isObject(tableIdOrArgs)
|
|
1379
1403
|
? getSortedRowIds(
|
|
@@ -1382,16 +1406,19 @@ const createStore = () => {
|
|
|
1382
1406
|
tableIdOrArgs.descending,
|
|
1383
1407
|
tableIdOrArgs.offset,
|
|
1384
1408
|
tableIdOrArgs.limit,
|
|
1409
|
+
tableIdOrArgs.sorter,
|
|
1385
1410
|
)
|
|
1386
1411
|
: arrayMap(
|
|
1387
1412
|
slice(
|
|
1388
1413
|
arraySort(
|
|
1389
1414
|
mapMap(mapGet(tablesMap, id(tableIdOrArgs)), (row, rowId) => [
|
|
1390
|
-
isUndefined(cellId)
|
|
1415
|
+
isUndefined(cellId)
|
|
1416
|
+
? rowId
|
|
1417
|
+
: decodeIfJson(mapGet(row, id(cellId))),
|
|
1391
1418
|
rowId,
|
|
1392
1419
|
]),
|
|
1393
1420
|
([cell1], [cell2]) =>
|
|
1394
|
-
|
|
1421
|
+
sorter(cell1, cell2) * (descending ? -1 : 1),
|
|
1395
1422
|
),
|
|
1396
1423
|
offset,
|
|
1397
1424
|
isUndefined(limit) ? limit : offset + limit,
|
|
@@ -1869,6 +1896,7 @@ const createStore = () => {
|
|
|
1869
1896
|
tableIdOrArgs.descending ?? false,
|
|
1870
1897
|
tableIdOrArgs.offset ?? 0,
|
|
1871
1898
|
tableIdOrArgs.limit,
|
|
1899
|
+
tableIdOrArgs.sorter,
|
|
1872
1900
|
],
|
|
1873
1901
|
cellIdOrListener,
|
|
1874
1902
|
descendingOrMutator,
|
|
@@ -1876,7 +1904,7 @@ const createStore = () => {
|
|
|
1876
1904
|
: addSortedRowIdsListenerImpl(
|
|
1877
1905
|
tableIdOrArgs,
|
|
1878
1906
|
cellIdOrListener,
|
|
1879
|
-
[descendingOrMutator, offset, limit],
|
|
1907
|
+
[descendingOrMutator, offset, limit, void 0],
|
|
1880
1908
|
listener,
|
|
1881
1909
|
mutator,
|
|
1882
1910
|
);
|
package/ui-react/index.js
CHANGED
|
@@ -536,33 +536,56 @@ const useSortedRowIdsImpl = (
|
|
|
536
536
|
descending,
|
|
537
537
|
offset,
|
|
538
538
|
limit,
|
|
539
|
+
sorter,
|
|
539
540
|
storeOrStoreId,
|
|
540
|
-
) =>
|
|
541
|
-
|
|
541
|
+
) => {
|
|
542
|
+
const sortedRowIdsArgs = useMemo(
|
|
543
|
+
() => ({
|
|
544
|
+
tableId,
|
|
545
|
+
cellId,
|
|
546
|
+
descending: descending ?? false,
|
|
547
|
+
offset: offset ?? 0,
|
|
548
|
+
limit,
|
|
549
|
+
sorter,
|
|
550
|
+
}),
|
|
551
|
+
[tableId, cellId, descending, offset, limit, sorter],
|
|
552
|
+
);
|
|
553
|
+
return useListenable(
|
|
542
554
|
SORTED_ROW_IDS,
|
|
543
555
|
useStoreOrStoreById(storeOrStoreId),
|
|
544
556
|
1 /* Array */,
|
|
545
|
-
|
|
557
|
+
isUndefined(sorter)
|
|
558
|
+
? [tableId, cellId, descending, offset, limit]
|
|
559
|
+
: [sortedRowIdsArgs],
|
|
546
560
|
);
|
|
561
|
+
};
|
|
547
562
|
const useSortedRowIdsListenerImpl = (
|
|
548
563
|
tableId,
|
|
549
564
|
cellId,
|
|
550
565
|
descending,
|
|
551
566
|
offset,
|
|
552
567
|
limit,
|
|
568
|
+
sorter,
|
|
553
569
|
listener,
|
|
554
570
|
listenerDeps,
|
|
555
571
|
mutator,
|
|
556
572
|
storeOrStoreId,
|
|
557
|
-
) =>
|
|
573
|
+
) => {
|
|
574
|
+
const sortedRowIdsArgs = useMemo(
|
|
575
|
+
() => ({tableId, cellId, descending, offset, limit, sorter}),
|
|
576
|
+
[tableId, cellId, descending, offset, limit, sorter],
|
|
577
|
+
);
|
|
558
578
|
useListener(
|
|
559
579
|
SORTED_ROW_IDS,
|
|
560
580
|
useStoreOrStoreById(storeOrStoreId),
|
|
561
581
|
listener,
|
|
562
582
|
listenerDeps,
|
|
563
|
-
|
|
583
|
+
isUndefined(sorter)
|
|
584
|
+
? [tableId, cellId, descending, offset, limit]
|
|
585
|
+
: [sortedRowIdsArgs],
|
|
564
586
|
mutator,
|
|
565
587
|
);
|
|
588
|
+
};
|
|
566
589
|
const useCreateStore = (create, createDeps = EMPTY_ARRAY) =>
|
|
567
590
|
useMemo(create, createDeps);
|
|
568
591
|
const useStoreIds = () => useThingIds(OFFSET_STORE);
|
|
@@ -632,6 +655,7 @@ const useSortedRowIds = (
|
|
|
632
655
|
descending,
|
|
633
656
|
offset,
|
|
634
657
|
limit,
|
|
658
|
+
sorterOrStoreOrStoreId,
|
|
635
659
|
storeOrStoreId,
|
|
636
660
|
) =>
|
|
637
661
|
useSortedRowIdsImpl(
|
|
@@ -642,6 +666,7 @@ const useSortedRowIds = (
|
|
|
642
666
|
tableIdOrArgs.descending ?? false,
|
|
643
667
|
tableIdOrArgs.offset ?? 0,
|
|
644
668
|
tableIdOrArgs.limit,
|
|
669
|
+
tableIdOrArgs.sorter,
|
|
645
670
|
cellIdOrStoreOrStoreId,
|
|
646
671
|
]
|
|
647
672
|
: [
|
|
@@ -650,7 +675,10 @@ const useSortedRowIds = (
|
|
|
650
675
|
descending,
|
|
651
676
|
offset,
|
|
652
677
|
limit,
|
|
653
|
-
|
|
678
|
+
isFunction(sorterOrStoreOrStoreId) ? sorterOrStoreOrStoreId : void 0,
|
|
679
|
+
isFunction(sorterOrStoreOrStoreId)
|
|
680
|
+
? storeOrStoreId
|
|
681
|
+
: sorterOrStoreOrStoreId,
|
|
654
682
|
]),
|
|
655
683
|
);
|
|
656
684
|
const useHasRow = (tableId, rowId, storeOrStoreId) =>
|
|
@@ -1057,6 +1085,7 @@ const useSortedRowIdsListener = (
|
|
|
1057
1085
|
tableIdOrArgs.descending ?? false,
|
|
1058
1086
|
tableIdOrArgs.offset ?? 0,
|
|
1059
1087
|
tableIdOrArgs.limit,
|
|
1088
|
+
tableIdOrArgs.sorter,
|
|
1060
1089
|
cellIdOrListener,
|
|
1061
1090
|
descendingOrListenerDeps,
|
|
1062
1091
|
offsetOrMutator,
|
|
@@ -1068,6 +1097,7 @@ const useSortedRowIdsListener = (
|
|
|
1068
1097
|
descendingOrListenerDeps,
|
|
1069
1098
|
offsetOrMutator,
|
|
1070
1099
|
limitOrStoreOrStoreId,
|
|
1100
|
+
void 0,
|
|
1071
1101
|
listener,
|
|
1072
1102
|
listenerDeps,
|
|
1073
1103
|
mutator,
|
|
@@ -536,33 +536,56 @@ const useSortedRowIdsImpl = (
|
|
|
536
536
|
descending,
|
|
537
537
|
offset,
|
|
538
538
|
limit,
|
|
539
|
+
sorter,
|
|
539
540
|
storeOrStoreId,
|
|
540
|
-
) =>
|
|
541
|
-
|
|
541
|
+
) => {
|
|
542
|
+
const sortedRowIdsArgs = useMemo(
|
|
543
|
+
() => ({
|
|
544
|
+
tableId,
|
|
545
|
+
cellId,
|
|
546
|
+
descending: descending ?? false,
|
|
547
|
+
offset: offset ?? 0,
|
|
548
|
+
limit,
|
|
549
|
+
sorter,
|
|
550
|
+
}),
|
|
551
|
+
[tableId, cellId, descending, offset, limit, sorter],
|
|
552
|
+
);
|
|
553
|
+
return useListenable(
|
|
542
554
|
SORTED_ROW_IDS,
|
|
543
555
|
useStoreOrStoreById(storeOrStoreId),
|
|
544
556
|
1 /* Array */,
|
|
545
|
-
|
|
557
|
+
isUndefined(sorter)
|
|
558
|
+
? [tableId, cellId, descending, offset, limit]
|
|
559
|
+
: [sortedRowIdsArgs],
|
|
546
560
|
);
|
|
561
|
+
};
|
|
547
562
|
const useSortedRowIdsListenerImpl = (
|
|
548
563
|
tableId,
|
|
549
564
|
cellId,
|
|
550
565
|
descending,
|
|
551
566
|
offset,
|
|
552
567
|
limit,
|
|
568
|
+
sorter,
|
|
553
569
|
listener,
|
|
554
570
|
listenerDeps,
|
|
555
571
|
mutator,
|
|
556
572
|
storeOrStoreId,
|
|
557
|
-
) =>
|
|
573
|
+
) => {
|
|
574
|
+
const sortedRowIdsArgs = useMemo(
|
|
575
|
+
() => ({tableId, cellId, descending, offset, limit, sorter}),
|
|
576
|
+
[tableId, cellId, descending, offset, limit, sorter],
|
|
577
|
+
);
|
|
558
578
|
useListener(
|
|
559
579
|
SORTED_ROW_IDS,
|
|
560
580
|
useStoreOrStoreById(storeOrStoreId),
|
|
561
581
|
listener,
|
|
562
582
|
listenerDeps,
|
|
563
|
-
|
|
583
|
+
isUndefined(sorter)
|
|
584
|
+
? [tableId, cellId, descending, offset, limit]
|
|
585
|
+
: [sortedRowIdsArgs],
|
|
564
586
|
mutator,
|
|
565
587
|
);
|
|
588
|
+
};
|
|
566
589
|
const useCreateStore = (create, createDeps = EMPTY_ARRAY) =>
|
|
567
590
|
useMemo(create, createDeps);
|
|
568
591
|
const useStoreIds = () => useThingIds(OFFSET_STORE);
|
|
@@ -632,6 +655,7 @@ const useSortedRowIds = (
|
|
|
632
655
|
descending,
|
|
633
656
|
offset,
|
|
634
657
|
limit,
|
|
658
|
+
sorterOrStoreOrStoreId,
|
|
635
659
|
storeOrStoreId,
|
|
636
660
|
) =>
|
|
637
661
|
useSortedRowIdsImpl(
|
|
@@ -642,6 +666,7 @@ const useSortedRowIds = (
|
|
|
642
666
|
tableIdOrArgs.descending ?? false,
|
|
643
667
|
tableIdOrArgs.offset ?? 0,
|
|
644
668
|
tableIdOrArgs.limit,
|
|
669
|
+
tableIdOrArgs.sorter,
|
|
645
670
|
cellIdOrStoreOrStoreId,
|
|
646
671
|
]
|
|
647
672
|
: [
|
|
@@ -650,7 +675,10 @@ const useSortedRowIds = (
|
|
|
650
675
|
descending,
|
|
651
676
|
offset,
|
|
652
677
|
limit,
|
|
653
|
-
|
|
678
|
+
isFunction(sorterOrStoreOrStoreId) ? sorterOrStoreOrStoreId : void 0,
|
|
679
|
+
isFunction(sorterOrStoreOrStoreId)
|
|
680
|
+
? storeOrStoreId
|
|
681
|
+
: sorterOrStoreOrStoreId,
|
|
654
682
|
]),
|
|
655
683
|
);
|
|
656
684
|
const useHasRow = (tableId, rowId, storeOrStoreId) =>
|
|
@@ -1057,6 +1085,7 @@ const useSortedRowIdsListener = (
|
|
|
1057
1085
|
tableIdOrArgs.descending ?? false,
|
|
1058
1086
|
tableIdOrArgs.offset ?? 0,
|
|
1059
1087
|
tableIdOrArgs.limit,
|
|
1088
|
+
tableIdOrArgs.sorter,
|
|
1060
1089
|
cellIdOrListener,
|
|
1061
1090
|
descendingOrListenerDeps,
|
|
1062
1091
|
offsetOrMutator,
|
|
@@ -1068,6 +1097,7 @@ const useSortedRowIdsListener = (
|
|
|
1068
1097
|
descendingOrListenerDeps,
|
|
1069
1098
|
offsetOrMutator,
|
|
1070
1099
|
limitOrStoreOrStoreId,
|
|
1100
|
+
void 0,
|
|
1071
1101
|
listener,
|
|
1072
1102
|
listenerDeps,
|
|
1073
1103
|
mutator,
|