cic-kit 0.0.36 → 0.0.38

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.
@@ -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
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cic-kit",
3
- "version": "0.0.36",
3
+ "version": "0.0.38",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",