@neetru/sdk 3.0.2 → 3.1.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.
Files changed (98) hide show
  1. package/CHANGELOG.md +554 -530
  2. package/dist/auth.cjs +219 -54
  3. package/dist/auth.cjs.map +1 -1
  4. package/dist/auth.d.cts +1 -2
  5. package/dist/auth.d.ts +1 -2
  6. package/dist/auth.mjs +219 -54
  7. package/dist/auth.mjs.map +1 -1
  8. package/dist/catalog.cjs +50 -2
  9. package/dist/catalog.cjs.map +1 -1
  10. package/dist/catalog.d.cts +1 -2
  11. package/dist/catalog.d.ts +1 -2
  12. package/dist/catalog.mjs +50 -2
  13. package/dist/catalog.mjs.map +1 -1
  14. package/dist/checkout.cjs +52 -3
  15. package/dist/checkout.cjs.map +1 -1
  16. package/dist/checkout.d.cts +1 -2
  17. package/dist/checkout.d.ts +1 -2
  18. package/dist/checkout.mjs +52 -3
  19. package/dist/checkout.mjs.map +1 -1
  20. package/dist/db-react.cjs +18 -6
  21. package/dist/db-react.cjs.map +1 -1
  22. package/dist/db-react.d.cts +35 -13
  23. package/dist/db-react.d.ts +35 -13
  24. package/dist/db-react.mjs +18 -6
  25. package/dist/db-react.mjs.map +1 -1
  26. package/dist/db.cjs +164 -56
  27. package/dist/db.cjs.map +1 -1
  28. package/dist/db.d.cts +1 -2
  29. package/dist/db.d.ts +1 -2
  30. package/dist/db.mjs +164 -56
  31. package/dist/db.mjs.map +1 -1
  32. package/dist/entitlements.cjs +50 -2
  33. package/dist/entitlements.cjs.map +1 -1
  34. package/dist/entitlements.d.cts +1 -2
  35. package/dist/entitlements.d.ts +1 -2
  36. package/dist/entitlements.mjs +50 -2
  37. package/dist/entitlements.mjs.map +1 -1
  38. package/dist/errors.cjs.map +1 -1
  39. package/dist/errors.d.cts +3 -1
  40. package/dist/errors.d.ts +3 -1
  41. package/dist/errors.mjs.map +1 -1
  42. package/dist/firestore-compat.cjs +411 -0
  43. package/dist/firestore-compat.cjs.map +1 -0
  44. package/dist/firestore-compat.d.cts +319 -0
  45. package/dist/firestore-compat.d.ts +319 -0
  46. package/dist/firestore-compat.mjs +383 -0
  47. package/dist/firestore-compat.mjs.map +1 -0
  48. package/dist/index.cjs +266 -66
  49. package/dist/index.cjs.map +1 -1
  50. package/dist/index.d.cts +9 -4
  51. package/dist/index.d.ts +9 -4
  52. package/dist/index.mjs +265 -67
  53. package/dist/index.mjs.map +1 -1
  54. package/dist/mocks.cjs.map +1 -1
  55. package/dist/mocks.d.cts +1 -2
  56. package/dist/mocks.d.ts +1 -2
  57. package/dist/mocks.mjs.map +1 -1
  58. package/dist/notifications.cjs +50 -2
  59. package/dist/notifications.cjs.map +1 -1
  60. package/dist/notifications.d.cts +1 -2
  61. package/dist/notifications.d.ts +1 -2
  62. package/dist/notifications.mjs +50 -2
  63. package/dist/notifications.mjs.map +1 -1
  64. package/dist/react.cjs +268 -2
  65. package/dist/react.cjs.map +1 -1
  66. package/dist/react.d.cts +135 -3
  67. package/dist/react.d.ts +135 -3
  68. package/dist/react.mjs +266 -3
  69. package/dist/react.mjs.map +1 -1
  70. package/dist/support.cjs +50 -2
  71. package/dist/support.cjs.map +1 -1
  72. package/dist/support.d.cts +1 -2
  73. package/dist/support.d.ts +1 -2
  74. package/dist/support.mjs +50 -2
  75. package/dist/support.mjs.map +1 -1
  76. package/dist/telemetry.cjs +65 -4
  77. package/dist/telemetry.cjs.map +1 -1
  78. package/dist/telemetry.d.cts +1 -2
  79. package/dist/telemetry.d.ts +1 -2
  80. package/dist/telemetry.mjs +65 -4
  81. package/dist/telemetry.mjs.map +1 -1
  82. package/dist/{types-D7zVkO3n.d.ts → types-B3XFHD4A.d.ts} +640 -2
  83. package/dist/{types-Dc4bjrrt.d.cts → types-DePdSU3P.d.cts} +640 -2
  84. package/dist/usage.cjs +50 -2
  85. package/dist/usage.cjs.map +1 -1
  86. package/dist/usage.d.cts +1 -2
  87. package/dist/usage.d.ts +1 -2
  88. package/dist/usage.mjs +50 -2
  89. package/dist/usage.mjs.map +1 -1
  90. package/dist/webhooks.cjs +83 -2
  91. package/dist/webhooks.cjs.map +1 -1
  92. package/dist/webhooks.d.cts +1 -2
  93. package/dist/webhooks.d.ts +1 -2
  94. package/dist/webhooks.mjs +83 -3
  95. package/dist/webhooks.mjs.map +1 -1
  96. package/package.json +156 -151
  97. package/dist/collection-ref-BDdfD87k.d.cts +0 -581
  98. package/dist/collection-ref-BDdfD87k.d.ts +0 -581
@@ -0,0 +1,319 @@
1
+ import { G as NeetruDb, n as DbCollectionRef, F as FieldSentinel, t as DbQuery } from './types-DePdSU3P.cjs';
2
+ import 'drizzle-orm/node-postgres';
3
+ import './errors.cjs';
4
+
5
+ /**
6
+ * @neetru/sdk/firestore-compat — camada de COMPATIBILIDADE (transicional).
7
+ *
8
+ * ⚠️ **STATUS: compat / transitional.** Este módulo espelha a superfície
9
+ * modular do Firebase Firestore (`doc`, `collection`, `query`, `where`,
10
+ * `getDocs`, `setDoc`, `onSnapshot`, `writeBatch`, `runTransaction`,
11
+ * `serverTimestamp`, `Timestamp`, `FieldValue`, …) para que produtos que
12
+ * migram do Firebase **não precisem reescrever as chamadas à mão**.
13
+ *
14
+ * Ele NÃO é a API nativa do SDK e NÃO compete com `client.db` (NeetruDb).
15
+ * É um auxílio de migração: troque os imports de `firebase/firestore` por
16
+ * `@neetru/sdk/firestore-compat`, valide, e depois migre incrementalmente
17
+ * para a superfície nativa `client.db.collection(...)` quando fizer sentido.
18
+ *
19
+ * Esta implementação foi desenhada a partir dos shims reais que os produtos
20
+ * `neetru-gestovendas` (`src/neetru/firestore.ts`) e `neetru-pdvagiliza`
21
+ * (`src/lib/neetru/firestore-compat.ts`) escreveram à mão — espelha
22
+ * exatamente a superfície que eles precisam para poder **deletar os shims**.
23
+ *
24
+ * ### Backing
25
+ * Tudo flui por `client.db` (`NeetruDb`). As funções recebem ou um `NeetruDb`
26
+ * (o `client.db`) ou o `NeetruClient` inteiro como primeiro argumento — ambos
27
+ * são aceitos por `getFirestore(...)`/`collection(...)`/`doc(...)`.
28
+ *
29
+ * ### Diferenças deliberadas vs Firebase
30
+ * - `serverTimestamp()` e `increment()`/`arrayUnion()`/`arrayRemove()` retornam
31
+ * sentinels do SDK (`@neetru/sdk` `serverTimestamp`/`increment`) — resolvidos
32
+ * SERVER-SIDE pelo Core (não pelo relógio spoofável do cliente).
33
+ * - `Timestamp` é uma classe leve (sem proto de Firebase) com `toDate()`,
34
+ * `toMillis()`, `seconds`, `nanoseconds` e `Timestamp.now()/fromDate()/fromMillis()`.
35
+ * - `onSnapshot` usa o realtime nativo do `client.db` (`onSnapshot`/`doc().onSnapshot`)
36
+ * quando o transporte oferece; caso contrário entrega o snapshot inicial e
37
+ * reage às mudanças locais (offline-first do SDK).
38
+ *
39
+ * @module
40
+ */
41
+
42
+ /**
43
+ * Aceita tanto o `NeetruDb` (`client.db`) quanto o `NeetruClient` inteiro.
44
+ * Produtos legados chamam `getFirestore(client)` ou `getFirestore(client.db)`;
45
+ * ambos resolvem para o `NeetruDb` subjacente.
46
+ */
47
+ type FirestoreLike = NeetruDb | {
48
+ db: NeetruDb;
49
+ };
50
+ /** Marker brand reconhecível em runtime — `getFirestore()` devolve isto. */
51
+ interface Firestore {
52
+ readonly __neetruFirestore: true;
53
+ readonly db: NeetruDb;
54
+ }
55
+ /**
56
+ * Equivalente compat de `getFirestore(app)`. Aceita o `NeetruClient` ou o
57
+ * `client.db` (`NeetruDb`) e devolve um handle `Firestore` opaco.
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * import { getFirestore } from '@neetru/sdk/firestore-compat';
62
+ * const db = getFirestore(client); // ou getFirestore(client.db)
63
+ * ```
64
+ */
65
+ declare function getFirestore(handle: FirestoreLike): Firestore;
66
+ /** Operadores `where` suportados (subset do Firestore + ops do SDK). */
67
+ type WhereFilterOp = '==' | '!=' | '<' | '<=' | '>' | '>=' | 'in' | 'not-in' | 'array-contains' | 'array-contains-any';
68
+ interface CollectionReference<T = Record<string, unknown>> {
69
+ readonly type: 'collection';
70
+ readonly __kind: 'collection';
71
+ readonly id: string;
72
+ readonly path: string;
73
+ readonly db: NeetruDb;
74
+ /** Handle nativo do SDK — atalho para a superfície `client.db`. */
75
+ readonly ref: DbCollectionRef<T>;
76
+ }
77
+ interface DocumentReference<T = Record<string, unknown>> {
78
+ readonly type: 'document';
79
+ readonly __kind: 'document';
80
+ readonly id: string;
81
+ readonly path: string;
82
+ readonly collection: string;
83
+ readonly db: NeetruDb;
84
+ /** Marcador de tipo (phantom) — preserva `T` para inferência do caller. */
85
+ readonly __doc?: T;
86
+ }
87
+ /** Aceita tanto `Firestore` quanto `NeetruDb`/`NeetruClient` direto. */
88
+ type DbArg = Firestore | FirestoreLike;
89
+ /**
90
+ * `collection(db, name)` — referência a uma coleção.
91
+ *
92
+ * Aceita `db` como `Firestore` (de `getFirestore`), `NeetruClient` ou `client.db`.
93
+ */
94
+ declare function collection<T = Record<string, unknown>>(db: DbArg, name: string): CollectionReference<T>;
95
+ /**
96
+ * `doc(...)` — referência a um documento. Suporta as 3 assinaturas legadas:
97
+ * doc(db, 'collection', 'id') → coleção + id
98
+ * doc(collectionRef, 'id') → id dentro de uma CollectionReference
99
+ * doc(db, 'collection/id') → path com barra (id auto-gerado se id ausente)
100
+ *
101
+ * Quando o `id` é omitido, gera um id v4 (espelha `doc(collectionRef)` do Firebase
102
+ * que cria uma ref com id automático antes do `setDoc`).
103
+ */
104
+ declare function doc<T = Record<string, unknown>>(dbOrCollection: DbArg | CollectionReference<T>, ...path: string[]): DocumentReference<T>;
105
+ type QueryConstraintType = 'where' | 'orderBy' | 'limit';
106
+ interface QueryConstraint {
107
+ readonly __constraint: QueryConstraintType;
108
+ }
109
+ interface WhereConstraint extends QueryConstraint {
110
+ readonly __constraint: 'where';
111
+ readonly field: string;
112
+ readonly op: WhereFilterOp;
113
+ readonly value: unknown;
114
+ }
115
+ interface OrderByConstraint extends QueryConstraint {
116
+ readonly __constraint: 'orderBy';
117
+ readonly field: string;
118
+ readonly direction: 'asc' | 'desc';
119
+ }
120
+ interface LimitConstraint extends QueryConstraint {
121
+ readonly __constraint: 'limit';
122
+ readonly value: number;
123
+ }
124
+ interface Query<T = Record<string, unknown>> {
125
+ readonly type: 'query';
126
+ readonly __kind: 'query';
127
+ readonly path: string;
128
+ readonly collection: string;
129
+ readonly db: NeetruDb;
130
+ readonly ref: DbCollectionRef<T>;
131
+ readonly constraints: QueryConstraint[];
132
+ }
133
+ /**
134
+ * `query(collectionRef, ...constraints)` — combina `where`/`orderBy`/`limit`.
135
+ * Aceita também uma `Query` como fonte (encadeamento de constraints).
136
+ */
137
+ declare function query<T = Record<string, unknown>>(source: CollectionReference<T> | Query<T>, ...constraints: QueryConstraint[]): Query<T>;
138
+ declare function where(field: string, op: WhereFilterOp, value: unknown): WhereConstraint;
139
+ declare function orderBy(field: string, direction?: 'asc' | 'desc'): OrderByConstraint;
140
+ declare function limit(value: number): LimitConstraint;
141
+ /**
142
+ * Converte os constraints de uma `Query` compat para o `DbQuery` nativo do SDK.
143
+ *
144
+ * Exportado para que os hooks React (`@neetru/sdk/react`) possam reusar a mesma
145
+ * tradução — fonte única de verdade da conversão de constraints.
146
+ */
147
+ declare function toDbQuery(constraints: QueryConstraint[]): DbQuery;
148
+ declare class DocumentSnapshot<T = Record<string, unknown>> {
149
+ readonly id: string;
150
+ private readonly _data;
151
+ readonly ref?: DocumentReference<T> | undefined;
152
+ constructor(id: string, _data: T | null, ref?: DocumentReference<T> | undefined);
153
+ exists(): boolean;
154
+ data(): T | undefined;
155
+ /** Compat: `snap.get('field')` lê um campo top-level. */
156
+ get(field: string): unknown;
157
+ }
158
+ interface QueryDocumentSnapshot<T = Record<string, unknown>> {
159
+ readonly id: string;
160
+ data(): T;
161
+ exists(): boolean;
162
+ get(field: string): unknown;
163
+ readonly ref: DocumentReference<T>;
164
+ }
165
+ declare class QuerySnapshot<T = Record<string, unknown>> {
166
+ readonly docs: Array<QueryDocumentSnapshot<T>>;
167
+ readonly empty: boolean;
168
+ readonly size: number;
169
+ constructor(rows: Array<{
170
+ id: string;
171
+ data: Record<string, unknown>;
172
+ }>, db?: NeetruDb, collectionName?: string);
173
+ forEach(cb: (doc: QueryDocumentSnapshot<T>) => void): void;
174
+ }
175
+ declare function getDoc<T = Record<string, unknown>>(ref: DocumentReference<T>): Promise<DocumentSnapshot<T>>;
176
+ declare function getDocs<T = Record<string, unknown>>(source: CollectionReference<T> | Query<T>): Promise<QuerySnapshot<T>>;
177
+ interface SetOptions {
178
+ merge?: boolean;
179
+ mergeFields?: string[];
180
+ }
181
+ declare function setDoc<T = Record<string, unknown>>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>, options?: SetOptions): Promise<void>;
182
+ declare function addDoc<T = Record<string, unknown>>(source: CollectionReference<T>, data: Partial<T> | Record<string, unknown>): Promise<DocumentReference<T>>;
183
+ declare function updateDoc<T = Record<string, unknown>>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>): Promise<void>;
184
+ declare function deleteDoc(ref: DocumentReference): Promise<void>;
185
+ declare class WriteBatch {
186
+ private readonly db;
187
+ private ops;
188
+ constructor(db: NeetruDb);
189
+ set<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>, _options?: SetOptions): this;
190
+ update<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>): this;
191
+ delete(ref: DocumentReference): this;
192
+ commit(): Promise<void>;
193
+ }
194
+ declare function writeBatch(db: DbArg): WriteBatch;
195
+ /**
196
+ * Handle de transação compat. O SDK não expõe transações multi-doc atômicas
197
+ * com lock server-side, então emulamos a forma do Firebase: `tx.get` lê do
198
+ * `client.db`, e `tx.set/update/delete` enfileiram escritas que são aplicadas
199
+ * no fim do callback.
200
+ *
201
+ * ⚠️ **LIMITAÇÃO CONHECIDA — sem isolamento server-side (lost-update silencioso):**
202
+ *
203
+ * Diferente do Firestore nativo (que usa serializable snapshot isolation com
204
+ * contention detection), este shim executa reads e writes em rounds separados
205
+ * sem garantia de atomicidade:
206
+ *
207
+ * 1. `tx.get(ref)` faz um read imediato via `client.db`.
208
+ * 2. As escritas (`tx.set/update/delete`) são **enfileiradas** — não bloqueiam
209
+ * outros writers.
210
+ * 3. No fim do callback, `batch.commit()` aplica as escritas. Se outro processo
211
+ * tiver modificado o mesmo documento entre o read e o commit, a escrita
212
+ * será um **lost-update silencioso** (sem erro, sem retry automático).
213
+ *
214
+ * **Quando isso importa:** counters, saldos, estoques — qualquer dado
215
+ * que precise de leitura-modificação-escrita atômica.
216
+ *
217
+ * **Alternativas seguras:**
218
+ * - Use **Server Actions no Core** (`src/lib/actions/`) que rodam dentro
219
+ * de transações Firestore Admin SDK reais (com locks server-side).
220
+ * - Use `increment()` sentinel para contadores numéricos — server-side atomic.
221
+ * - Use `arrayUnion()`/`arrayRemove()` para sets (também server-side atomic).
222
+ *
223
+ * Esta emulação é aceitável para migrações transitórias e para operações
224
+ * onde a probabilidade de concorrência é baixa (ex: dados de um único usuário
225
+ * sem write concorrente). **Não use para dados financeiros ou de inventário.**
226
+ */
227
+ interface Transaction {
228
+ get<T>(ref: DocumentReference<T>): Promise<DocumentSnapshot<T>>;
229
+ set<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>, options?: SetOptions): Transaction;
230
+ update<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>): Transaction;
231
+ delete(ref: DocumentReference): Transaction;
232
+ }
233
+ declare function runTransaction<R>(db: DbArg, updateFunction: (transaction: Transaction) => Promise<R>): Promise<R>;
234
+ type Unsubscribe = () => void;
235
+ type DocOnNext<T> = (snap: DocumentSnapshot<T>) => void;
236
+ type QueryOnNext<T> = (snap: QuerySnapshot<T>) => void;
237
+ type OnError = (err: Error) => void;
238
+ declare function onSnapshot<T>(ref: DocumentReference<T>, onNext: DocOnNext<T>, onError?: OnError): Unsubscribe;
239
+ declare function onSnapshot<T>(source: Query<T> | CollectionReference<T>, onNext: QueryOnNext<T>, onError?: OnError): Unsubscribe;
240
+ /**
241
+ * Reimplementação compat de `Timestamp` do Firestore. Sem proto do Firebase.
242
+ * Cobre `seconds`, `nanoseconds`, `toDate()`, `toMillis()`, `isEqual()`,
243
+ * `valueOf()`, `toJSON()` + estáticos `now()`, `fromDate()`, `fromMillis()`.
244
+ */
245
+ declare class Timestamp {
246
+ readonly seconds: number;
247
+ readonly nanoseconds: number;
248
+ constructor(seconds: number, nanoseconds: number);
249
+ static now(): Timestamp;
250
+ static fromDate(date: Date): Timestamp;
251
+ static fromMillis(millis: number): Timestamp;
252
+ toDate(): Date;
253
+ toMillis(): number;
254
+ isEqual(other: Timestamp): boolean;
255
+ valueOf(): string;
256
+ toJSON(): {
257
+ seconds: number;
258
+ nanoseconds: number;
259
+ };
260
+ toString(): string;
261
+ }
262
+ /**
263
+ * Sentinel de `arrayUnion`/`arrayRemove`. O SDK ainda não tem sentinel de array
264
+ * server-side, então emitimos um marker namespaceado que o Core reconhece
265
+ * (mesma família de `__neetru__`). Se o backing não suportar, o produto deve
266
+ * preferir read-modify-write via Server Action. Documentado como compat.
267
+ */
268
+ interface ArrayUnionSentinel {
269
+ readonly __neetru__: 'arrayUnion';
270
+ readonly elements: unknown[];
271
+ }
272
+ interface ArrayRemoveSentinel {
273
+ readonly __neetru__: 'arrayRemove';
274
+ readonly elements: unknown[];
275
+ }
276
+ /**
277
+ * Sentinel de campo a deletar (compat `deleteField()`).
278
+ */
279
+ interface DeleteFieldSentinel {
280
+ readonly __neetru__: 'deleteField';
281
+ }
282
+ /**
283
+ * `serverTimestamp()` — delega ao sentinel do SDK (resolvido SERVER-SIDE).
284
+ * NÃO retorna mais ISO/Date do cliente (que era spoofável).
285
+ */
286
+ declare function serverTimestamp(): FieldSentinel;
287
+ /**
288
+ * `increment(n)` — incremento atômico server-side (delega ao sentinel do SDK).
289
+ */
290
+ declare function increment(n: number): FieldSentinel;
291
+ /** `arrayUnion(...elements)` — sentinel compat (resolvido pelo Core). */
292
+ declare function arrayUnion(...elements: unknown[]): ArrayUnionSentinel;
293
+ /** `arrayRemove(...elements)` — sentinel compat (resolvido pelo Core). */
294
+ declare function arrayRemove(...elements: unknown[]): ArrayRemoveSentinel;
295
+ /** `deleteField()` — sentinel compat para remover um campo. */
296
+ declare function deleteField(): DeleteFieldSentinel;
297
+ /**
298
+ * Namespace estático `FieldValue` — espelha `firebase/firestore`'s `FieldValue`.
299
+ * Os métodos delegam às funções modulares acima.
300
+ *
301
+ * @example
302
+ * ```ts
303
+ * import { FieldValue } from '@neetru/sdk/firestore-compat';
304
+ * await updateDoc(ref, {
305
+ * tags: FieldValue.arrayUnion('novo'),
306
+ * counter: FieldValue.increment(1),
307
+ * updatedAt: FieldValue.serverTimestamp(),
308
+ * });
309
+ * ```
310
+ */
311
+ declare const FieldValue: {
312
+ readonly serverTimestamp: typeof serverTimestamp;
313
+ readonly increment: typeof increment;
314
+ readonly arrayUnion: typeof arrayUnion;
315
+ readonly arrayRemove: typeof arrayRemove;
316
+ readonly delete: typeof deleteField;
317
+ };
318
+
319
+ export { type ArrayRemoveSentinel, type ArrayUnionSentinel, type CollectionReference, type DeleteFieldSentinel, type DocumentReference, DocumentSnapshot, FieldValue, type Firestore, type FirestoreLike, type Query, type QueryConstraint, type QueryConstraintType, type QueryDocumentSnapshot, QuerySnapshot, type SetOptions, Timestamp, type Transaction, type Unsubscribe, type WhereFilterOp, WriteBatch, addDoc, arrayRemove, arrayUnion, collection, deleteDoc, deleteField, doc, getDoc, getDocs, getFirestore, increment, limit, onSnapshot, orderBy, query, runTransaction, serverTimestamp, setDoc, toDbQuery, updateDoc, where, writeBatch };
@@ -0,0 +1,319 @@
1
+ import { G as NeetruDb, n as DbCollectionRef, F as FieldSentinel, t as DbQuery } from './types-B3XFHD4A.js';
2
+ import 'drizzle-orm/node-postgres';
3
+ import './errors.js';
4
+
5
+ /**
6
+ * @neetru/sdk/firestore-compat — camada de COMPATIBILIDADE (transicional).
7
+ *
8
+ * ⚠️ **STATUS: compat / transitional.** Este módulo espelha a superfície
9
+ * modular do Firebase Firestore (`doc`, `collection`, `query`, `where`,
10
+ * `getDocs`, `setDoc`, `onSnapshot`, `writeBatch`, `runTransaction`,
11
+ * `serverTimestamp`, `Timestamp`, `FieldValue`, …) para que produtos que
12
+ * migram do Firebase **não precisem reescrever as chamadas à mão**.
13
+ *
14
+ * Ele NÃO é a API nativa do SDK e NÃO compete com `client.db` (NeetruDb).
15
+ * É um auxílio de migração: troque os imports de `firebase/firestore` por
16
+ * `@neetru/sdk/firestore-compat`, valide, e depois migre incrementalmente
17
+ * para a superfície nativa `client.db.collection(...)` quando fizer sentido.
18
+ *
19
+ * Esta implementação foi desenhada a partir dos shims reais que os produtos
20
+ * `neetru-gestovendas` (`src/neetru/firestore.ts`) e `neetru-pdvagiliza`
21
+ * (`src/lib/neetru/firestore-compat.ts`) escreveram à mão — espelha
22
+ * exatamente a superfície que eles precisam para poder **deletar os shims**.
23
+ *
24
+ * ### Backing
25
+ * Tudo flui por `client.db` (`NeetruDb`). As funções recebem ou um `NeetruDb`
26
+ * (o `client.db`) ou o `NeetruClient` inteiro como primeiro argumento — ambos
27
+ * são aceitos por `getFirestore(...)`/`collection(...)`/`doc(...)`.
28
+ *
29
+ * ### Diferenças deliberadas vs Firebase
30
+ * - `serverTimestamp()` e `increment()`/`arrayUnion()`/`arrayRemove()` retornam
31
+ * sentinels do SDK (`@neetru/sdk` `serverTimestamp`/`increment`) — resolvidos
32
+ * SERVER-SIDE pelo Core (não pelo relógio spoofável do cliente).
33
+ * - `Timestamp` é uma classe leve (sem proto de Firebase) com `toDate()`,
34
+ * `toMillis()`, `seconds`, `nanoseconds` e `Timestamp.now()/fromDate()/fromMillis()`.
35
+ * - `onSnapshot` usa o realtime nativo do `client.db` (`onSnapshot`/`doc().onSnapshot`)
36
+ * quando o transporte oferece; caso contrário entrega o snapshot inicial e
37
+ * reage às mudanças locais (offline-first do SDK).
38
+ *
39
+ * @module
40
+ */
41
+
42
+ /**
43
+ * Aceita tanto o `NeetruDb` (`client.db`) quanto o `NeetruClient` inteiro.
44
+ * Produtos legados chamam `getFirestore(client)` ou `getFirestore(client.db)`;
45
+ * ambos resolvem para o `NeetruDb` subjacente.
46
+ */
47
+ type FirestoreLike = NeetruDb | {
48
+ db: NeetruDb;
49
+ };
50
+ /** Marker brand reconhecível em runtime — `getFirestore()` devolve isto. */
51
+ interface Firestore {
52
+ readonly __neetruFirestore: true;
53
+ readonly db: NeetruDb;
54
+ }
55
+ /**
56
+ * Equivalente compat de `getFirestore(app)`. Aceita o `NeetruClient` ou o
57
+ * `client.db` (`NeetruDb`) e devolve um handle `Firestore` opaco.
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * import { getFirestore } from '@neetru/sdk/firestore-compat';
62
+ * const db = getFirestore(client); // ou getFirestore(client.db)
63
+ * ```
64
+ */
65
+ declare function getFirestore(handle: FirestoreLike): Firestore;
66
+ /** Operadores `where` suportados (subset do Firestore + ops do SDK). */
67
+ type WhereFilterOp = '==' | '!=' | '<' | '<=' | '>' | '>=' | 'in' | 'not-in' | 'array-contains' | 'array-contains-any';
68
+ interface CollectionReference<T = Record<string, unknown>> {
69
+ readonly type: 'collection';
70
+ readonly __kind: 'collection';
71
+ readonly id: string;
72
+ readonly path: string;
73
+ readonly db: NeetruDb;
74
+ /** Handle nativo do SDK — atalho para a superfície `client.db`. */
75
+ readonly ref: DbCollectionRef<T>;
76
+ }
77
+ interface DocumentReference<T = Record<string, unknown>> {
78
+ readonly type: 'document';
79
+ readonly __kind: 'document';
80
+ readonly id: string;
81
+ readonly path: string;
82
+ readonly collection: string;
83
+ readonly db: NeetruDb;
84
+ /** Marcador de tipo (phantom) — preserva `T` para inferência do caller. */
85
+ readonly __doc?: T;
86
+ }
87
+ /** Aceita tanto `Firestore` quanto `NeetruDb`/`NeetruClient` direto. */
88
+ type DbArg = Firestore | FirestoreLike;
89
+ /**
90
+ * `collection(db, name)` — referência a uma coleção.
91
+ *
92
+ * Aceita `db` como `Firestore` (de `getFirestore`), `NeetruClient` ou `client.db`.
93
+ */
94
+ declare function collection<T = Record<string, unknown>>(db: DbArg, name: string): CollectionReference<T>;
95
+ /**
96
+ * `doc(...)` — referência a um documento. Suporta as 3 assinaturas legadas:
97
+ * doc(db, 'collection', 'id') → coleção + id
98
+ * doc(collectionRef, 'id') → id dentro de uma CollectionReference
99
+ * doc(db, 'collection/id') → path com barra (id auto-gerado se id ausente)
100
+ *
101
+ * Quando o `id` é omitido, gera um id v4 (espelha `doc(collectionRef)` do Firebase
102
+ * que cria uma ref com id automático antes do `setDoc`).
103
+ */
104
+ declare function doc<T = Record<string, unknown>>(dbOrCollection: DbArg | CollectionReference<T>, ...path: string[]): DocumentReference<T>;
105
+ type QueryConstraintType = 'where' | 'orderBy' | 'limit';
106
+ interface QueryConstraint {
107
+ readonly __constraint: QueryConstraintType;
108
+ }
109
+ interface WhereConstraint extends QueryConstraint {
110
+ readonly __constraint: 'where';
111
+ readonly field: string;
112
+ readonly op: WhereFilterOp;
113
+ readonly value: unknown;
114
+ }
115
+ interface OrderByConstraint extends QueryConstraint {
116
+ readonly __constraint: 'orderBy';
117
+ readonly field: string;
118
+ readonly direction: 'asc' | 'desc';
119
+ }
120
+ interface LimitConstraint extends QueryConstraint {
121
+ readonly __constraint: 'limit';
122
+ readonly value: number;
123
+ }
124
+ interface Query<T = Record<string, unknown>> {
125
+ readonly type: 'query';
126
+ readonly __kind: 'query';
127
+ readonly path: string;
128
+ readonly collection: string;
129
+ readonly db: NeetruDb;
130
+ readonly ref: DbCollectionRef<T>;
131
+ readonly constraints: QueryConstraint[];
132
+ }
133
+ /**
134
+ * `query(collectionRef, ...constraints)` — combina `where`/`orderBy`/`limit`.
135
+ * Aceita também uma `Query` como fonte (encadeamento de constraints).
136
+ */
137
+ declare function query<T = Record<string, unknown>>(source: CollectionReference<T> | Query<T>, ...constraints: QueryConstraint[]): Query<T>;
138
+ declare function where(field: string, op: WhereFilterOp, value: unknown): WhereConstraint;
139
+ declare function orderBy(field: string, direction?: 'asc' | 'desc'): OrderByConstraint;
140
+ declare function limit(value: number): LimitConstraint;
141
+ /**
142
+ * Converte os constraints de uma `Query` compat para o `DbQuery` nativo do SDK.
143
+ *
144
+ * Exportado para que os hooks React (`@neetru/sdk/react`) possam reusar a mesma
145
+ * tradução — fonte única de verdade da conversão de constraints.
146
+ */
147
+ declare function toDbQuery(constraints: QueryConstraint[]): DbQuery;
148
+ declare class DocumentSnapshot<T = Record<string, unknown>> {
149
+ readonly id: string;
150
+ private readonly _data;
151
+ readonly ref?: DocumentReference<T> | undefined;
152
+ constructor(id: string, _data: T | null, ref?: DocumentReference<T> | undefined);
153
+ exists(): boolean;
154
+ data(): T | undefined;
155
+ /** Compat: `snap.get('field')` lê um campo top-level. */
156
+ get(field: string): unknown;
157
+ }
158
+ interface QueryDocumentSnapshot<T = Record<string, unknown>> {
159
+ readonly id: string;
160
+ data(): T;
161
+ exists(): boolean;
162
+ get(field: string): unknown;
163
+ readonly ref: DocumentReference<T>;
164
+ }
165
+ declare class QuerySnapshot<T = Record<string, unknown>> {
166
+ readonly docs: Array<QueryDocumentSnapshot<T>>;
167
+ readonly empty: boolean;
168
+ readonly size: number;
169
+ constructor(rows: Array<{
170
+ id: string;
171
+ data: Record<string, unknown>;
172
+ }>, db?: NeetruDb, collectionName?: string);
173
+ forEach(cb: (doc: QueryDocumentSnapshot<T>) => void): void;
174
+ }
175
+ declare function getDoc<T = Record<string, unknown>>(ref: DocumentReference<T>): Promise<DocumentSnapshot<T>>;
176
+ declare function getDocs<T = Record<string, unknown>>(source: CollectionReference<T> | Query<T>): Promise<QuerySnapshot<T>>;
177
+ interface SetOptions {
178
+ merge?: boolean;
179
+ mergeFields?: string[];
180
+ }
181
+ declare function setDoc<T = Record<string, unknown>>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>, options?: SetOptions): Promise<void>;
182
+ declare function addDoc<T = Record<string, unknown>>(source: CollectionReference<T>, data: Partial<T> | Record<string, unknown>): Promise<DocumentReference<T>>;
183
+ declare function updateDoc<T = Record<string, unknown>>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>): Promise<void>;
184
+ declare function deleteDoc(ref: DocumentReference): Promise<void>;
185
+ declare class WriteBatch {
186
+ private readonly db;
187
+ private ops;
188
+ constructor(db: NeetruDb);
189
+ set<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>, _options?: SetOptions): this;
190
+ update<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>): this;
191
+ delete(ref: DocumentReference): this;
192
+ commit(): Promise<void>;
193
+ }
194
+ declare function writeBatch(db: DbArg): WriteBatch;
195
+ /**
196
+ * Handle de transação compat. O SDK não expõe transações multi-doc atômicas
197
+ * com lock server-side, então emulamos a forma do Firebase: `tx.get` lê do
198
+ * `client.db`, e `tx.set/update/delete` enfileiram escritas que são aplicadas
199
+ * no fim do callback.
200
+ *
201
+ * ⚠️ **LIMITAÇÃO CONHECIDA — sem isolamento server-side (lost-update silencioso):**
202
+ *
203
+ * Diferente do Firestore nativo (que usa serializable snapshot isolation com
204
+ * contention detection), este shim executa reads e writes em rounds separados
205
+ * sem garantia de atomicidade:
206
+ *
207
+ * 1. `tx.get(ref)` faz um read imediato via `client.db`.
208
+ * 2. As escritas (`tx.set/update/delete`) são **enfileiradas** — não bloqueiam
209
+ * outros writers.
210
+ * 3. No fim do callback, `batch.commit()` aplica as escritas. Se outro processo
211
+ * tiver modificado o mesmo documento entre o read e o commit, a escrita
212
+ * será um **lost-update silencioso** (sem erro, sem retry automático).
213
+ *
214
+ * **Quando isso importa:** counters, saldos, estoques — qualquer dado
215
+ * que precise de leitura-modificação-escrita atômica.
216
+ *
217
+ * **Alternativas seguras:**
218
+ * - Use **Server Actions no Core** (`src/lib/actions/`) que rodam dentro
219
+ * de transações Firestore Admin SDK reais (com locks server-side).
220
+ * - Use `increment()` sentinel para contadores numéricos — server-side atomic.
221
+ * - Use `arrayUnion()`/`arrayRemove()` para sets (também server-side atomic).
222
+ *
223
+ * Esta emulação é aceitável para migrações transitórias e para operações
224
+ * onde a probabilidade de concorrência é baixa (ex: dados de um único usuário
225
+ * sem write concorrente). **Não use para dados financeiros ou de inventário.**
226
+ */
227
+ interface Transaction {
228
+ get<T>(ref: DocumentReference<T>): Promise<DocumentSnapshot<T>>;
229
+ set<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>, options?: SetOptions): Transaction;
230
+ update<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>): Transaction;
231
+ delete(ref: DocumentReference): Transaction;
232
+ }
233
+ declare function runTransaction<R>(db: DbArg, updateFunction: (transaction: Transaction) => Promise<R>): Promise<R>;
234
+ type Unsubscribe = () => void;
235
+ type DocOnNext<T> = (snap: DocumentSnapshot<T>) => void;
236
+ type QueryOnNext<T> = (snap: QuerySnapshot<T>) => void;
237
+ type OnError = (err: Error) => void;
238
+ declare function onSnapshot<T>(ref: DocumentReference<T>, onNext: DocOnNext<T>, onError?: OnError): Unsubscribe;
239
+ declare function onSnapshot<T>(source: Query<T> | CollectionReference<T>, onNext: QueryOnNext<T>, onError?: OnError): Unsubscribe;
240
+ /**
241
+ * Reimplementação compat de `Timestamp` do Firestore. Sem proto do Firebase.
242
+ * Cobre `seconds`, `nanoseconds`, `toDate()`, `toMillis()`, `isEqual()`,
243
+ * `valueOf()`, `toJSON()` + estáticos `now()`, `fromDate()`, `fromMillis()`.
244
+ */
245
+ declare class Timestamp {
246
+ readonly seconds: number;
247
+ readonly nanoseconds: number;
248
+ constructor(seconds: number, nanoseconds: number);
249
+ static now(): Timestamp;
250
+ static fromDate(date: Date): Timestamp;
251
+ static fromMillis(millis: number): Timestamp;
252
+ toDate(): Date;
253
+ toMillis(): number;
254
+ isEqual(other: Timestamp): boolean;
255
+ valueOf(): string;
256
+ toJSON(): {
257
+ seconds: number;
258
+ nanoseconds: number;
259
+ };
260
+ toString(): string;
261
+ }
262
+ /**
263
+ * Sentinel de `arrayUnion`/`arrayRemove`. O SDK ainda não tem sentinel de array
264
+ * server-side, então emitimos um marker namespaceado que o Core reconhece
265
+ * (mesma família de `__neetru__`). Se o backing não suportar, o produto deve
266
+ * preferir read-modify-write via Server Action. Documentado como compat.
267
+ */
268
+ interface ArrayUnionSentinel {
269
+ readonly __neetru__: 'arrayUnion';
270
+ readonly elements: unknown[];
271
+ }
272
+ interface ArrayRemoveSentinel {
273
+ readonly __neetru__: 'arrayRemove';
274
+ readonly elements: unknown[];
275
+ }
276
+ /**
277
+ * Sentinel de campo a deletar (compat `deleteField()`).
278
+ */
279
+ interface DeleteFieldSentinel {
280
+ readonly __neetru__: 'deleteField';
281
+ }
282
+ /**
283
+ * `serverTimestamp()` — delega ao sentinel do SDK (resolvido SERVER-SIDE).
284
+ * NÃO retorna mais ISO/Date do cliente (que era spoofável).
285
+ */
286
+ declare function serverTimestamp(): FieldSentinel;
287
+ /**
288
+ * `increment(n)` — incremento atômico server-side (delega ao sentinel do SDK).
289
+ */
290
+ declare function increment(n: number): FieldSentinel;
291
+ /** `arrayUnion(...elements)` — sentinel compat (resolvido pelo Core). */
292
+ declare function arrayUnion(...elements: unknown[]): ArrayUnionSentinel;
293
+ /** `arrayRemove(...elements)` — sentinel compat (resolvido pelo Core). */
294
+ declare function arrayRemove(...elements: unknown[]): ArrayRemoveSentinel;
295
+ /** `deleteField()` — sentinel compat para remover um campo. */
296
+ declare function deleteField(): DeleteFieldSentinel;
297
+ /**
298
+ * Namespace estático `FieldValue` — espelha `firebase/firestore`'s `FieldValue`.
299
+ * Os métodos delegam às funções modulares acima.
300
+ *
301
+ * @example
302
+ * ```ts
303
+ * import { FieldValue } from '@neetru/sdk/firestore-compat';
304
+ * await updateDoc(ref, {
305
+ * tags: FieldValue.arrayUnion('novo'),
306
+ * counter: FieldValue.increment(1),
307
+ * updatedAt: FieldValue.serverTimestamp(),
308
+ * });
309
+ * ```
310
+ */
311
+ declare const FieldValue: {
312
+ readonly serverTimestamp: typeof serverTimestamp;
313
+ readonly increment: typeof increment;
314
+ readonly arrayUnion: typeof arrayUnion;
315
+ readonly arrayRemove: typeof arrayRemove;
316
+ readonly delete: typeof deleteField;
317
+ };
318
+
319
+ export { type ArrayRemoveSentinel, type ArrayUnionSentinel, type CollectionReference, type DeleteFieldSentinel, type DocumentReference, DocumentSnapshot, FieldValue, type Firestore, type FirestoreLike, type Query, type QueryConstraint, type QueryConstraintType, type QueryDocumentSnapshot, QuerySnapshot, type SetOptions, Timestamp, type Transaction, type Unsubscribe, type WhereFilterOp, WriteBatch, addDoc, arrayRemove, arrayUnion, collection, deleteDoc, deleteField, doc, getDoc, getDocs, getFirestore, increment, limit, onSnapshot, orderBy, query, runTransaction, serverTimestamp, setDoc, toDbQuery, updateDoc, where, writeBatch };