@anfenn/zync 0.1.21 → 0.1.22
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 +53 -23
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,13 +27,14 @@ Unopinionated, bullet-proof, offline-first sync middleware for Zustand.
|
|
|
27
27
|
npm install @anfenn/zync
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
### Zustand store creation:
|
|
30
|
+
### Zustand store creation (store.ts):
|
|
31
31
|
|
|
32
32
|
```ts
|
|
33
|
-
import { SyncAction, UseStoreWithSync, persistWithSync } from '@anfenn/zync';
|
|
33
|
+
import { SyncAction, type UseStoreWithSync, persistWithSync } from '@anfenn/zync';
|
|
34
34
|
import { create } from 'zustand';
|
|
35
35
|
import { createJSONStorage } from 'zustand/middleware';
|
|
36
36
|
import { useShallow } from 'zustand/react/shallow';
|
|
37
|
+
import { factApi, type Fact } from './api';
|
|
37
38
|
|
|
38
39
|
type Store = {
|
|
39
40
|
facts: Fact[];
|
|
@@ -57,14 +58,14 @@ export const useStore = create<any>()(
|
|
|
57
58
|
}));
|
|
58
59
|
|
|
59
60
|
// Never call queueToSync() inside Zustand set() due to itself calling set(), so may cause lost state changes
|
|
60
|
-
queueToSync(SyncAction.CreateOrUpdate, item._localId
|
|
61
|
+
queueToSync(SyncAction.CreateOrUpdate, 'facts', item._localId);
|
|
61
62
|
},
|
|
62
63
|
updateFact: (localId: string, changes: Partial<Fact>) => {
|
|
63
64
|
set((state: Store) => ({
|
|
64
65
|
facts: state.facts.map((item) => (item._localId === localId ? { ...item, ...changes } : item)),
|
|
65
66
|
}));
|
|
66
67
|
|
|
67
|
-
queueToSync(SyncAction.CreateOrUpdate,
|
|
68
|
+
queueToSync(SyncAction.CreateOrUpdate, 'facts', localId);
|
|
68
69
|
},
|
|
69
70
|
removeFact: (localId: string) => {
|
|
70
71
|
queueToSync(SyncAction.Remove, 'facts', localId);
|
|
@@ -79,7 +80,7 @@ export const useStore = create<any>()(
|
|
|
79
80
|
|
|
80
81
|
name: 'store',
|
|
81
82
|
storage: createJSONStorage(() => localStorage),
|
|
82
|
-
// storage: createJSONStorage(() => createIndexedDBStorage({ dbName: 'my-app', storeName: 'store' })),
|
|
83
|
+
// OR storage: createJSONStorage(() => createIndexedDBStorage({ dbName: 'my-app', storeName: 'store' })),
|
|
83
84
|
},
|
|
84
85
|
{
|
|
85
86
|
// State-to-API map to enable syncing. Must implement the full CRUD API:
|
|
@@ -109,30 +110,59 @@ export const useFacts = () =>
|
|
|
109
110
|
### In your component:
|
|
110
111
|
|
|
111
112
|
```ts
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
// syncState.
|
|
123
|
-
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
|
|
113
|
+
import { useEffect } from 'react';
|
|
114
|
+
import { nextLocalId } from '@anfenn/zync';
|
|
115
|
+
import { useFacts, useStore } from './store';
|
|
116
|
+
|
|
117
|
+
function App() {
|
|
118
|
+
// Your state
|
|
119
|
+
const { facts, addFact } = useFacts();
|
|
120
|
+
|
|
121
|
+
// Zync's internal sync state
|
|
122
|
+
const syncState = useStore((state) => state.syncState);
|
|
123
|
+
// syncState.status // 'hydrating' | 'syncing' | 'idle'
|
|
124
|
+
// syncState.error
|
|
125
|
+
// syncState.enabled
|
|
126
|
+
// syncState.firstLoadDone
|
|
127
|
+
// syncState.pendingChanges
|
|
128
|
+
// syncState.lastPulled
|
|
129
|
+
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
// Zync's control api
|
|
132
|
+
useStore.sync.enable(true); // Defaults to false, enable to start syncing
|
|
133
|
+
//useStore.sync.startFirstLoad(); // Batch loads from server
|
|
134
|
+
}, []);
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<>
|
|
138
|
+
<div>Sync Status: {syncState.status}</div>
|
|
139
|
+
<button
|
|
140
|
+
onClick={() =>
|
|
141
|
+
addFact({
|
|
142
|
+
_localId: nextLocalId(),
|
|
143
|
+
title: 'New fact ' + Date.now(),
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
>
|
|
147
|
+
Add Fact
|
|
148
|
+
</button>
|
|
149
|
+
{
|
|
150
|
+
facts.map((fact) => (
|
|
151
|
+
<div key={fact._localId}>{fact.title}</div>
|
|
152
|
+
))
|
|
153
|
+
}
|
|
154
|
+
</>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
127
157
|
```
|
|
128
158
|
|
|
129
|
-
### In your
|
|
159
|
+
### In your api.ts:
|
|
130
160
|
|
|
131
161
|
_(Supabase example, but could be fetch, GraphQL, etc.)_
|
|
132
162
|
|
|
133
163
|
```ts
|
|
134
|
-
import { ApiFunctions } from '@anfenn/zync';
|
|
135
|
-
import { supabase } from './supabase';
|
|
164
|
+
import type { ApiFunctions } from '@anfenn/zync';
|
|
165
|
+
import { supabase } from './supabase'; // Please include your own :)
|
|
136
166
|
|
|
137
167
|
export type Fact = {
|
|
138
168
|
_localId: string;
|