@nkzw/fate-indexeddb 1.12.1 → 1.13.0
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/README.md +28 -1
- package/lib/index.d.mts +1 -3
- package/lib/index.mjs +1 -2
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -874,12 +874,16 @@ function PostComments({
|
|
|
874
874
|
|
|
875
875
|
`useView` and `useLiveListView` can read deferred values too. This works with every transport. GraphQL currently fetches deferred fields with separate queries, rather than streaming `@defer` responses.
|
|
876
876
|
|
|
877
|
+
For GraphQL servers with incremental delivery enabled, [streaming batched reads](/docs/integrations/graphql.md#streaming-batched-reads) allows deferred follow-up requests to resolve independently within one HTTP response. This does not change when a deferred field is read or require different React hooks.
|
|
878
|
+
|
|
877
879
|
## List Views
|
|
878
880
|
|
|
879
881
|
### Pagination with `useListView`
|
|
880
882
|
|
|
881
883
|
You can wrap a list of references using `useListView` to enable connection-style lists with pagination support.
|
|
882
884
|
|
|
885
|
+
Run the regular example with `vp run dev` (tRPC) or `vp run dev:graphql` (GraphQL), then open **Pagination** from its header (`http://localhost:6001/pagination/preview`). The demo uses the existing posts, client, and router to exercise independent view ranges, navigation, refreshes, and optimistic insertion and rollback. Reading and pagination work without signing in; insertions require an example account and successful insertions create real posts in its database. Browser network throttling makes pending work easier to observe.
|
|
886
|
+
|
|
883
887
|
For example, you can define a `CommentView` and reuse it inside of a `CommentConnectionView`:
|
|
884
888
|
|
|
885
889
|
```tsx
|
|
@@ -956,7 +960,11 @@ const CommentConnectionView = {
|
|
|
956
960
|
|
|
957
961
|
When `loadNext` runs, fate sends the next cursor as `after` and keeps the page size in `first`. When `loadPrevious` runs, fate sends the previous cursor as `before` and uses `last` for the page size. This lets the server distinguish forward and backward pagination while keeping the component API small.
|
|
958
962
|
|
|
959
|
-
|
|
963
|
+
Each logical view has its own requested window, identified by the view, connection, and original arguments. Calling `loadNext` or `loadPrevious` expands that window. Fate retains the loaded range with the cached connection, so returning to the same view after a remount restores its range. Fetching or paginating the same data through a different view does not expand the original view. Failed page loads leave the window unchanged and can be retried. Multiple readers of the same logical view share its pagination progress.
|
|
964
|
+
|
|
965
|
+
Queries share cached entities and compatible pages, but `first` and `last` still bound an ordinary request's result. A smaller preview refresh does not truncate pages already loaded by another reader. Partial refreshes update the fetched portion and retain cached continuation pages. A complete server result, including an empty result, can remove stale membership. These rules apply to nested connections and root lists.
|
|
966
|
+
|
|
967
|
+
Explicit mutation insertions remain visible beyond the initial page size and survive background refreshes. Insertions not yet reconciled with a server list remain local overrides, including across empty responses. Once the server has included an inserted entry, a later authoritative response covering that entry can remove it. Explicit deletions and relationship replacements also remove entries.
|
|
960
968
|
|
|
961
969
|
Additional arguments on a root request are scoped to that root list:
|
|
962
970
|
|
|
@@ -2215,6 +2223,25 @@ Queries made together are batched into one GraphQL operation. Mutations run sepa
|
|
|
2215
2223
|
|
|
2216
2224
|
[Deferred fields](/docs/guide/deferred-views.md) load when a component reads them. This uses ordinary GraphQL queries; incremental `@defer` responses are not supported yet.
|
|
2217
2225
|
|
|
2226
|
+
### Streaming Batched Reads
|
|
2227
|
+
|
|
2228
|
+
For a server that supports GraphQL `@defer` and the `v0.2` incremental delivery protocol, enable streaming when creating your client:
|
|
2229
|
+
|
|
2230
|
+
```tsx
|
|
2231
|
+
const fate = createFateClient({
|
|
2232
|
+
streaming: true,
|
|
2233
|
+
url: 'https://api.example.com/graphql',
|
|
2234
|
+
});
|
|
2235
|
+
```
|
|
2236
|
+
|
|
2237
|
+
Reads still share one HTTP request. Each read is wrapped in its own labeled `@defer` fragment and resolves when that operation's complete result arrives. Separate requests under separate Suspense boundaries can render independently, while one request continues to wait for all the data it declares.
|
|
2238
|
+
|
|
2239
|
+
The transport negotiates `multipart/mixed;incrementalSpec=v0.2` and also accepts complete JSON responses. Mutations continue to use ordinary JSON responses. Streaming is disabled by default; enable it only after configuring your server and verifying that your proxy forwards response chunks promptly. Unsupported directives and incompatible multipart protocols produce errors rather than silently retrying requests.
|
|
2240
|
+
|
|
2241
|
+
With GraphQL Yoga, install `@graphql-yoga/plugin-defer-stream` and add `useDeferStream()` to the server's plugins. Keep client timeouts and error boundaries in place: completed reads remain available if another operation fails or the connection ends, while unfinished reads reject. Canceling one read keeps the connection alive for its siblings; the connection is released when no reads still need it.
|
|
2242
|
+
|
|
2243
|
+
This mode delivers complete operation results through the existing normalized cache. Field-level patches and item-by-item `@stream` updates are not supported. Existing fate `defer()` selections remain lazy identity-based follow-up reads, which can themselves share a streaming batch.
|
|
2244
|
+
|
|
2218
2245
|
### Refetch Fields
|
|
2219
2246
|
|
|
2220
2247
|
For servers without `nodes(ids:)`, configure a query field for each refetchable entity type:
|
package/lib/index.d.mts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { PersistenceStorage } from "@nkzw/fate/persistence";
|
|
2
|
-
//#region src/index.d.ts
|
|
3
2
|
export type IndexedDBStorageOptions = Readonly<{
|
|
4
3
|
name?: string;
|
|
5
4
|
}>;
|
|
6
|
-
export declare function createIndexedDBStorage({ name }?: IndexedDBStorageOptions): PersistenceStorage;
|
|
7
|
-
//#endregion
|
|
5
|
+
export declare function createIndexedDBStorage({ name }?: IndexedDBStorageOptions): PersistenceStorage;
|
package/lib/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { openDB } from "idb";
|
|
2
|
-
|
|
2
|
+
// src/index.ts
|
|
3
3
|
function createIndexedDBStorage({ name = "fate" } = {}) {
|
|
4
4
|
let connectionLeases = 0;
|
|
5
5
|
let connection;
|
|
@@ -122,5 +122,4 @@ function createIndexedDBStorage({ name = "fate" } = {}) {
|
|
|
122
122
|
}
|
|
123
123
|
};
|
|
124
124
|
}
|
|
125
|
-
//#endregion
|
|
126
125
|
export { createIndexedDBStorage };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nkzw/fate-indexeddb",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "Optional IndexedDB persistence adapter for fate.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
"idb": "^8.0.4"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@nkzw/fate": "1.
|
|
22
|
+
"@nkzw/fate": "1.13.0",
|
|
23
23
|
"fake-indexeddb": "^6.2.6",
|
|
24
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@1.
|
|
25
|
-
"vite-plus": "1.
|
|
24
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.4.0",
|
|
25
|
+
"vite-plus": "1.4.0"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@nkzw/fate": "^1.5.1"
|