cic-kit 0.0.37 → 0.0.39
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/dist/cmp/firebase/FirestoreStore.d.ts +4 -0
- package/dist/index.cjs +37 -37
- package/dist/index.mjs +7581 -7581
- package/docs/FirestoreStore-start.md +248 -0
- package/package.json +1 -1
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# FirestoreStore.start + useStoreWatch
|
|
2
|
+
|
|
3
|
+
Guida pratica su come usare `useStoreWatch` e `FirestoreStore.start()` in modo corretto, con focus su realtime, query options e lifecycle.
|
|
4
|
+
|
|
5
|
+
## Obiettivo
|
|
6
|
+
|
|
7
|
+
Questi due pezzi lavorano insieme:
|
|
8
|
+
|
|
9
|
+
- `useStoreWatch` decide *quando* attivare o fermare i listener (`start`/`stop`) in base a login e lifecycle Vue.
|
|
10
|
+
- `FirestoreStore.start` decide *cosa* ascoltare in realtime (query Firestore) e come sincronizzare `items` locali.
|
|
11
|
+
|
|
12
|
+
## Mappa rapida
|
|
13
|
+
|
|
14
|
+
- `useStoreWatch(...)`:
|
|
15
|
+
- monta una `watch` su `_Auth?.isLoggedIn`
|
|
16
|
+
- su ogni cambio login avvia/ferma gli store passati
|
|
17
|
+
- su unmount chiude tutti i listener
|
|
18
|
+
- `store.start(opts)`:
|
|
19
|
+
- valida le opzioni query
|
|
20
|
+
- evita restart se la query e uguale alla precedente
|
|
21
|
+
- crea `onSnapshot` e mantiene aggiornato `store.items`
|
|
22
|
+
- `store.stop()`:
|
|
23
|
+
- chiude listener realtime
|
|
24
|
+
- resetta stato interno del live (`prevStartQuery`, `isFirstRun`)
|
|
25
|
+
|
|
26
|
+
## useStoreWatch: comportamento reale
|
|
27
|
+
|
|
28
|
+
Signature:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
useStoreWatch(
|
|
32
|
+
stores: readonly {
|
|
33
|
+
store: AnyFirestoreStoreReactive
|
|
34
|
+
getOpts?: GetProps
|
|
35
|
+
getAuthOpts?: GetProps
|
|
36
|
+
checkLogin?: boolean
|
|
37
|
+
}[],
|
|
38
|
+
defaultCheckLogin: boolean = true
|
|
39
|
+
)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Regole:
|
|
43
|
+
|
|
44
|
+
- Se `logged === true`: usa `store.start(getAuthOpts ?? getOpts)`.
|
|
45
|
+
- Se `logged === false`:
|
|
46
|
+
- se `checkLogin` (o default) e `true`: `store.stop()`
|
|
47
|
+
- se `checkLogin` e `false`: `store.start(getOpts)`
|
|
48
|
+
|
|
49
|
+
Precedenze:
|
|
50
|
+
|
|
51
|
+
- `checkLogin` sul singolo store ha priorita su `defaultCheckLogin`.
|
|
52
|
+
- `getAuthOpts` ha priorita su `getOpts` quando utente loggato.
|
|
53
|
+
|
|
54
|
+
Lifecycle:
|
|
55
|
+
|
|
56
|
+
- `onBeforeMount`: attiva watch login con `{ immediate: true }`.
|
|
57
|
+
- `onBeforeUnmount`: stoppa watch login + `stop()` su tutti gli store.
|
|
58
|
+
|
|
59
|
+
## start() vs get(): differenza fondamentale
|
|
60
|
+
|
|
61
|
+
- `start(opts)` = realtime listener continuo (`onSnapshot`).
|
|
62
|
+
- `get(opts)` = fetch one-shot (`getDocs`) senza ascolto continuo.
|
|
63
|
+
|
|
64
|
+
Usa `start` per UI che deve aggiornarsi live (es. calendario).
|
|
65
|
+
Usa `get` per operazioni puntuali o viste statiche (es. edit dettaglio singolo).
|
|
66
|
+
|
|
67
|
+
## GetProps: cosa puoi passare a start()
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
interface GetProps {
|
|
71
|
+
ids?: string[]
|
|
72
|
+
lastByCreate?: number
|
|
73
|
+
lastByUpdate?: number
|
|
74
|
+
query?: QueryConstraint | QueryConstraint[]
|
|
75
|
+
limit?: number
|
|
76
|
+
orderBy?: { fieldPath: string | FieldPath; directionStr?: OrderByDirection }
|
|
77
|
+
forceLocalSet?: boolean
|
|
78
|
+
localSet?: boolean
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Significato pratico:
|
|
83
|
+
|
|
84
|
+
- `ids`: filtra per document id (`documentId()`).
|
|
85
|
+
- `query`: vincoli Firestore custom (`where`, ecc).
|
|
86
|
+
- `orderBy` + `limit`: ordinamento e limite.
|
|
87
|
+
- `lastByCreate` / `lastByUpdate`: shortcut per ultimi N in ordine desc su timestamp standard.
|
|
88
|
+
- `forceLocalSet`: svuota cache `items` + LocalStorage al primo snapshot e risincronizza.
|
|
89
|
+
- `localSet`: abilita/disabilita sync LocalStorage (se supportato dal model).
|
|
90
|
+
|
|
91
|
+
## Validazioni importanti (validateQueryGetOpts)
|
|
92
|
+
|
|
93
|
+
Combinazioni non permesse:
|
|
94
|
+
|
|
95
|
+
- `ids` insieme a `query`
|
|
96
|
+
- `ids.length > 10` in `start` (limite `in` query)
|
|
97
|
+
- `lastByCreate` insieme a `lastByUpdate`
|
|
98
|
+
- `lastByCreate` o `lastByUpdate` insieme a `limit`/`orderBy`
|
|
99
|
+
|
|
100
|
+
Quando una regola fallisce:
|
|
101
|
+
|
|
102
|
+
- viene mostrato `toast.logError(...)`
|
|
103
|
+
- `start()` esce subito senza aprire listener
|
|
104
|
+
|
|
105
|
+
## Come start() costruisce e gestisce il listener
|
|
106
|
+
|
|
107
|
+
Flusso interno:
|
|
108
|
+
|
|
109
|
+
1. log debug (`debugLog`).
|
|
110
|
+
2. validazione opzioni.
|
|
111
|
+
3. calcolo `currentQueryKey` da `ids/query/limit/orderBy`.
|
|
112
|
+
4. se store e gia live e la chiave query e uguale: non fa nulla.
|
|
113
|
+
5. altrimenti `stop()` del listener precedente.
|
|
114
|
+
6. costruzione constraints (`buildConstraintsFromGetProps`).
|
|
115
|
+
7. apertura `onSnapshot(...)`.
|
|
116
|
+
8. aggiornamento incrementale di `items` su `docChanges()`.
|
|
117
|
+
|
|
118
|
+
### Dedup query (anti restart inutile)
|
|
119
|
+
|
|
120
|
+
`start()` salva una chiave (`prevStartQuery`) della query attiva.
|
|
121
|
+
Se richiami `start()` con stessi parametri mentre e gia live, evita restart.
|
|
122
|
+
|
|
123
|
+
## onSnapshot: come aggiorna store.items
|
|
124
|
+
|
|
125
|
+
Su ogni change:
|
|
126
|
+
|
|
127
|
+
- `removed`:
|
|
128
|
+
- esegue `localSet(true)` sull'istanza se presente
|
|
129
|
+
- rimuove da `items`
|
|
130
|
+
- `added` / `modified`:
|
|
131
|
+
- crea model instance (`makeModel`)
|
|
132
|
+
- passa da `onGetBeforeStoreSet`
|
|
133
|
+
- upsert in `items`
|
|
134
|
+
- sync LocalStorage se `canLocalSave(localSet)`
|
|
135
|
+
|
|
136
|
+
## isFirstRun + onStartFirstRun
|
|
137
|
+
|
|
138
|
+
Al primo payload snapshot:
|
|
139
|
+
|
|
140
|
+
- `isFirstRun` passa da `true` a `false`
|
|
141
|
+
- viene chiamato `onStartFirstRun(snapDocs, forceLocalSet)`
|
|
142
|
+
- se `forceLocalSet === true`:
|
|
143
|
+
- `items = {}`
|
|
144
|
+
- `localClear()`
|
|
145
|
+
|
|
146
|
+
`onStartFirstRun` e pensato per override in store custom se vuoi logica extra all'avvio realtime.
|
|
147
|
+
|
|
148
|
+
## stop(): cosa resetta
|
|
149
|
+
|
|
150
|
+
Quando chiami `stop()`:
|
|
151
|
+
|
|
152
|
+
- chiude unsubscribe Firestore (`snapshotFnStop()`).
|
|
153
|
+
- mette `snapshotFnStop = null`.
|
|
154
|
+
- resetta `prevStartQuery = null`.
|
|
155
|
+
- resetta `isFirstRun = true`.
|
|
156
|
+
|
|
157
|
+
Quindi il prossimo `start()` riparte pulito.
|
|
158
|
+
|
|
159
|
+
## buildConstraintsFromGetProps: strategia di costruzione query
|
|
160
|
+
|
|
161
|
+
Ordine logico:
|
|
162
|
+
|
|
163
|
+
1. `ids` (con `documentId() ==` oppure `in`) oppure `query`.
|
|
164
|
+
2. se `lastByCreate`: aggiunge `orderBy(createdAt, desc)` + `limit(N)` e termina.
|
|
165
|
+
3. se `lastByUpdate`: aggiunge `orderBy(updatedAt, desc)` + `limit(N)` e termina.
|
|
166
|
+
4. opzionale `orderBy`.
|
|
167
|
+
5. opzionale `limit`.
|
|
168
|
+
|
|
169
|
+
Nota:
|
|
170
|
+
|
|
171
|
+
- quando usi `query` con piu `where`, eventuali indici composti Firestore sono responsabilita del progetto.
|
|
172
|
+
|
|
173
|
+
## Pattern d'uso consigliati
|
|
174
|
+
|
|
175
|
+
### 1) Store protetto da login (default)
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
useStoreWatch([
|
|
179
|
+
{
|
|
180
|
+
store: appointmentStore,
|
|
181
|
+
getAuthOpts: {
|
|
182
|
+
query: where("user_id", "==", uid),
|
|
183
|
+
orderBy: { fieldPath: "date_time", directionStr: "asc" },
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
]);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 2) Store pubblico anche da guest
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
useStoreWatch([
|
|
193
|
+
{
|
|
194
|
+
store: publicStore,
|
|
195
|
+
checkLogin: false,
|
|
196
|
+
getOpts: { limit: 50 },
|
|
197
|
+
},
|
|
198
|
+
]);
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### 3) Query per intervallo temporale
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
useStoreWatch([
|
|
205
|
+
{
|
|
206
|
+
store: appointmentStore,
|
|
207
|
+
getAuthOpts: {
|
|
208
|
+
query: [
|
|
209
|
+
where("date_time", ">=", fromTs),
|
|
210
|
+
where("date_time", "<", toTs),
|
|
211
|
+
],
|
|
212
|
+
orderBy: { fieldPath: "date_time", directionStr: "asc" },
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
]);
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 4) Stop del watch in viste che non servono realtime
|
|
219
|
+
|
|
220
|
+
Se una vista non ha bisogno di aggiornamenti live, non usare `useStoreWatch` li dentro.
|
|
221
|
+
Fai `get()` puntuale o `getOne()` su id specifico.
|
|
222
|
+
|
|
223
|
+
## Relazione con LocalStorage
|
|
224
|
+
|
|
225
|
+
Il sync locale dipende dal model:
|
|
226
|
+
|
|
227
|
+
- `localSet` funziona solo se il model espone `localStorageKey()`.
|
|
228
|
+
- `forceLocalSet` forza reset + riscrittura.
|
|
229
|
+
|
|
230
|
+
Se il model non supporta local storage, il realtime funziona comunque su `items`.
|
|
231
|
+
|
|
232
|
+
## Checklist operativa
|
|
233
|
+
|
|
234
|
+
1. Model con `collectionName` (o store con `collectionPath`).
|
|
235
|
+
2. Query valida secondo regole `validateQueryGetOpts`.
|
|
236
|
+
3. Usa `getAuthOpts` quando cambia filtro tra guest/logged.
|
|
237
|
+
4. Evita di richiamare `start` con query equivalenti in loop.
|
|
238
|
+
5. Ricordati che `useStoreWatch` fa gia cleanup automatico su unmount.
|
|
239
|
+
|
|
240
|
+
## Quando usare cosa
|
|
241
|
+
|
|
242
|
+
- `useStoreWatch`:
|
|
243
|
+
- viste Vue che vivono a componente e devono allinearsi a login lifecycle.
|
|
244
|
+
- `store.start()` manuale:
|
|
245
|
+
- casi avanzati controllati da un manager/composable custom.
|
|
246
|
+
- `store.get()` / `getOne()`:
|
|
247
|
+
- fetch una tantum, nessun realtime continuo.
|
|
248
|
+
|