@neetru/sdk 3.1.6 → 3.1.9

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 (77) hide show
  1. package/dist/auth.cjs +65 -22
  2. package/dist/auth.cjs.map +1 -1
  3. package/dist/auth.d.cts +1 -1
  4. package/dist/auth.d.ts +1 -1
  5. package/dist/auth.mjs +65 -22
  6. package/dist/auth.mjs.map +1 -1
  7. package/dist/catalog.cjs.map +1 -1
  8. package/dist/catalog.d.cts +1 -1
  9. package/dist/catalog.d.ts +1 -1
  10. package/dist/catalog.mjs.map +1 -1
  11. package/dist/checkout.cjs.map +1 -1
  12. package/dist/checkout.d.cts +1 -1
  13. package/dist/checkout.d.ts +1 -1
  14. package/dist/checkout.mjs.map +1 -1
  15. package/dist/db-react.d.cts +1 -1
  16. package/dist/db-react.d.ts +1 -1
  17. package/dist/db.cjs +55 -16
  18. package/dist/db.cjs.map +1 -1
  19. package/dist/db.d.cts +1 -1
  20. package/dist/db.d.ts +1 -1
  21. package/dist/db.mjs +55 -16
  22. package/dist/db.mjs.map +1 -1
  23. package/dist/entitlements.cjs.map +1 -1
  24. package/dist/entitlements.d.cts +1 -1
  25. package/dist/entitlements.d.ts +1 -1
  26. package/dist/entitlements.mjs.map +1 -1
  27. package/dist/errors.cjs.map +1 -1
  28. package/dist/errors.d.cts +8 -8
  29. package/dist/errors.d.ts +8 -8
  30. package/dist/errors.mjs.map +1 -1
  31. package/dist/firestore-compat.cjs +4 -9
  32. package/dist/firestore-compat.cjs.map +1 -1
  33. package/dist/firestore-compat.d.cts +2 -2
  34. package/dist/firestore-compat.d.ts +2 -2
  35. package/dist/firestore-compat.mjs +4 -9
  36. package/dist/firestore-compat.mjs.map +1 -1
  37. package/dist/index.cjs +66 -23
  38. package/dist/index.cjs.map +1 -1
  39. package/dist/index.d.cts +2 -2
  40. package/dist/index.d.ts +2 -2
  41. package/dist/index.mjs +66 -23
  42. package/dist/index.mjs.map +1 -1
  43. package/dist/mocks.cjs.map +1 -1
  44. package/dist/mocks.d.cts +1 -1
  45. package/dist/mocks.d.ts +1 -1
  46. package/dist/mocks.mjs.map +1 -1
  47. package/dist/notifications.cjs.map +1 -1
  48. package/dist/notifications.d.cts +1 -1
  49. package/dist/notifications.d.ts +1 -1
  50. package/dist/notifications.mjs.map +1 -1
  51. package/dist/react.cjs.map +1 -1
  52. package/dist/react.d.cts +1 -1
  53. package/dist/react.d.ts +1 -1
  54. package/dist/react.mjs.map +1 -1
  55. package/dist/support.cjs.map +1 -1
  56. package/dist/support.d.cts +1 -1
  57. package/dist/support.d.ts +1 -1
  58. package/dist/support.mjs.map +1 -1
  59. package/dist/telemetry.cjs +5 -1
  60. package/dist/telemetry.cjs.map +1 -1
  61. package/dist/telemetry.d.cts +1 -1
  62. package/dist/telemetry.d.ts +1 -1
  63. package/dist/telemetry.mjs +5 -1
  64. package/dist/telemetry.mjs.map +1 -1
  65. package/dist/{types-BXvGHppn.d.cts → types-DDiVzgCT.d.cts} +19 -2
  66. package/dist/{types-CQVak2a3.d.ts → types-HWDOUmlC.d.ts} +19 -2
  67. package/dist/usage.cjs +2 -2
  68. package/dist/usage.cjs.map +1 -1
  69. package/dist/usage.d.cts +1 -1
  70. package/dist/usage.d.ts +1 -1
  71. package/dist/usage.mjs +2 -2
  72. package/dist/usage.mjs.map +1 -1
  73. package/dist/webhooks.cjs.map +1 -1
  74. package/dist/webhooks.d.cts +1 -1
  75. package/dist/webhooks.d.ts +1 -1
  76. package/dist/webhooks.mjs.map +1 -1
  77. package/package.json +156 -156
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/firestore-compat.ts","../src/react.ts"],"names":["React","result","allowed"],"mappings":"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","file":"react.cjs","sourcesContent":["/**\r\n * @neetru/sdk/firestore-compat — camada de COMPATIBILIDADE (transicional).\r\n *\r\n * ⚠️ **STATUS: compat / transitional.** Este módulo espelha a superfície\r\n * modular do Firebase Firestore (`doc`, `collection`, `query`, `where`,\r\n * `getDocs`, `setDoc`, `onSnapshot`, `writeBatch`, `runTransaction`,\r\n * `serverTimestamp`, `Timestamp`, `FieldValue`, …) para que produtos que\r\n * migram do Firebase **não precisem reescrever as chamadas à mão**.\r\n *\r\n * Ele NÃO é a API nativa do SDK e NÃO compete com `client.db` (NeetruDb).\r\n * É um auxílio de migração: troque os imports de `firebase/firestore` por\r\n * `@neetru/sdk/firestore-compat`, valide, e depois migre incrementalmente\r\n * para a superfície nativa `client.db.collection(...)` quando fizer sentido.\r\n *\r\n * Esta implementação foi desenhada a partir dos shims reais que os produtos\r\n * `neetru-gestovendas` (`src/neetru/firestore.ts`) e `neetru-pdvagiliza`\r\n * (`src/lib/neetru/firestore-compat.ts`) escreveram à mão — espelha\r\n * exatamente a superfície que eles precisam para poder **deletar os shims**.\r\n *\r\n * ### Backing\r\n * Tudo flui por `client.db` (`NeetruDb`). As funções recebem ou um `NeetruDb`\r\n * (o `client.db`) ou o `NeetruClient` inteiro como primeiro argumento — ambos\r\n * são aceitos por `getFirestore(...)`/`collection(...)`/`doc(...)`.\r\n *\r\n * ### Diferenças deliberadas vs Firebase\r\n * - `serverTimestamp()` e `increment()`/`arrayUnion()`/`arrayRemove()` retornam\r\n * sentinels do SDK (`@neetru/sdk` `serverTimestamp`/`increment`) — resolvidos\r\n * SERVER-SIDE pelo Core (não pelo relógio spoofável do cliente).\r\n * - `Timestamp` é uma classe leve (sem proto de Firebase) com `toDate()`,\r\n * `toMillis()`, `seconds`, `nanoseconds` e `Timestamp.now()/fromDate()/fromMillis()`.\r\n * - `onSnapshot` usa o realtime nativo do `client.db` (`onSnapshot`/`doc().onSnapshot`)\r\n * quando o transporte oferece; caso contrário entrega o snapshot inicial e\r\n * reage às mudanças locais (offline-first do SDK).\r\n *\r\n * @module\r\n */\r\n\r\nimport type {\r\n NeetruDb,\r\n DbCollectionRef,\r\n DbQuery,\r\n DbWhereFilter,\r\n DbListResult,\r\n DbGetResult,\r\n} from './db/client-db';\r\nimport {\r\n serverTimestamp as sdkServerTimestamp,\r\n increment as sdkIncrement,\r\n type FieldSentinel,\r\n} from './db/field-value';\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// Resolução do handle de banco\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Aceita tanto o `NeetruDb` (`client.db`) quanto o `NeetruClient` inteiro.\r\n * Produtos legados chamam `getFirestore(client)` ou `getFirestore(client.db)`;\r\n * ambos resolvem para o `NeetruDb` subjacente.\r\n */\r\nexport type FirestoreLike = NeetruDb | { db: NeetruDb };\r\n\r\n/** Marker brand reconhecível em runtime — `getFirestore()` devolve isto. */\r\nexport interface Firestore {\r\n readonly __neetruFirestore: true;\r\n readonly db: NeetruDb;\r\n}\r\n\r\nfunction isClientWrapper(v: FirestoreLike | Firestore): v is { db: NeetruDb } {\r\n return (\r\n typeof v === 'object' &&\r\n v !== null &&\r\n 'db' in v &&\r\n typeof (v as { db?: unknown }).db === 'object' &&\r\n (v as { db?: { collection?: unknown } }).db?.collection !== undefined\r\n );\r\n}\r\n\r\nfunction resolveDb(handle: FirestoreLike | Firestore): NeetruDb {\r\n if ((handle as Firestore).__neetruFirestore) return (handle as Firestore).db;\r\n if (isClientWrapper(handle)) return handle.db;\r\n // É o próprio NeetruDb (tem `.collection`).\r\n return handle as NeetruDb;\r\n}\r\n\r\n/**\r\n * Equivalente compat de `getFirestore(app)`. Aceita o `NeetruClient` ou o\r\n * `client.db` (`NeetruDb`) e devolve um handle `Firestore` opaco.\r\n *\r\n * @example\r\n * ```ts\r\n * import { getFirestore } from '@neetru/sdk/firestore-compat';\r\n * const db = getFirestore(client); // ou getFirestore(client.db)\r\n * ```\r\n */\r\nexport function getFirestore(handle: FirestoreLike): Firestore {\r\n return { __neetruFirestore: true, db: resolveDb(handle) };\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// Refs — Collection & Document\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/** Operadores `where` suportados (subset do Firestore + ops do SDK). */\r\nexport type WhereFilterOp =\r\n | '=='\r\n | '!='\r\n | '<'\r\n | '<='\r\n | '>'\r\n | '>='\r\n | 'in'\r\n | 'not-in'\r\n | 'array-contains'\r\n | 'array-contains-any';\r\n\r\nexport interface CollectionReference<T = Record<string, unknown>> {\r\n readonly type: 'collection';\r\n readonly __kind: 'collection';\r\n readonly id: string;\r\n readonly path: string;\r\n readonly db: NeetruDb;\r\n /** Handle nativo do SDK — atalho para a superfície `client.db`. */\r\n readonly ref: DbCollectionRef<T>;\r\n}\r\n\r\nexport interface DocumentReference<T = Record<string, unknown>> {\r\n readonly type: 'document';\r\n readonly __kind: 'document';\r\n readonly id: string;\r\n readonly path: string;\r\n readonly collection: string;\r\n readonly db: NeetruDb;\r\n /** Marcador de tipo (phantom) — preserva `T` para inferência do caller. */\r\n readonly __doc?: T;\r\n}\r\n\r\n/** Aceita tanto `Firestore` quanto `NeetruDb`/`NeetruClient` direto. */\r\ntype DbArg = Firestore | FirestoreLike;\r\n\r\n/**\r\n * `collection(db, name)` — referência a uma coleção.\r\n *\r\n * Aceita `db` como `Firestore` (de `getFirestore`), `NeetruClient` ou `client.db`.\r\n */\r\nexport function collection<T = Record<string, unknown>>(\r\n db: DbArg,\r\n name: string,\r\n): CollectionReference<T> {\r\n const resolved = resolveDb(db);\r\n return {\r\n type: 'collection',\r\n __kind: 'collection',\r\n id: name,\r\n path: name,\r\n db: resolved,\r\n ref: resolved.collection<T>(name),\r\n };\r\n}\r\n\r\n/**\r\n * `doc(...)` — referência a um documento. Suporta as 3 assinaturas legadas:\r\n * doc(db, 'collection', 'id') → coleção + id\r\n * doc(collectionRef, 'id') → id dentro de uma CollectionReference\r\n * doc(db, 'collection/id') → path com barra (id auto-gerado se id ausente)\r\n *\r\n * Quando o `id` é omitido, gera um id v4 (espelha `doc(collectionRef)` do Firebase\r\n * que cria uma ref com id automático antes do `setDoc`).\r\n */\r\nexport function doc<T = Record<string, unknown>>(\r\n dbOrCollection: DbArg | CollectionReference<T>,\r\n ...path: string[]\r\n): DocumentReference<T> {\r\n // Forma doc(collectionRef, id?)\r\n if (\r\n typeof dbOrCollection === 'object' &&\r\n dbOrCollection !== null &&\r\n (dbOrCollection as CollectionReference<T>).__kind === 'collection'\r\n ) {\r\n const col = dbOrCollection as CollectionReference<T>;\r\n const id = path[0] ?? generateId();\r\n return makeDocRef<T>(col.db, col.id, id);\r\n }\r\n\r\n const resolved = resolveDb(dbOrCollection as DbArg);\r\n\r\n if (path.length >= 2) {\r\n return makeDocRef<T>(resolved, path[0], path.slice(1).join('/'));\r\n }\r\n if (path[0]?.includes('/')) {\r\n const parts = path[0].split('/');\r\n return makeDocRef<T>(resolved, parts[0], parts.slice(1).join('/') || generateId());\r\n }\r\n // doc(db, 'collection') — id auto-gerado\r\n return makeDocRef<T>(resolved, path[0] ?? '', generateId());\r\n}\r\n\r\nfunction makeDocRef<T>(db: NeetruDb, collectionName: string, id: string): DocumentReference<T> {\r\n return {\r\n type: 'document',\r\n __kind: 'document',\r\n id,\r\n collection: collectionName,\r\n path: `${collectionName}/${id}`,\r\n db,\r\n };\r\n}\r\n\r\n/**\r\n * Gera um id estilo Firestore (20 chars alfanuméricos) com aleatoriedade\r\n * CRIPTOGRÁFICA.\r\n *\r\n * Antes usava `Math.random()` — previsível e colisível (PRNG não-criptográfico,\r\n * estado recuperável). IDs de documento previsíveis permitem enumeração/forja.\r\n * Agora usa `globalThis.crypto.getRandomValues` (WebCrypto), disponível tanto em\r\n * Node ≥20 quanto em browsers — sem importar `node:crypto` (que quebraria o\r\n * bundle browser). Rejeita bytes ≥ 248 (4×62) para eliminar o viés de módulo\r\n * sobre o alfabeto de 62 caracteres.\r\n */\r\nfunction generateId(): string {\r\n const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; // 62\r\n const cryptoObj = (globalThis as { crypto?: Crypto }).crypto;\r\n if (!cryptoObj?.getRandomValues) {\r\n throw new Error(\r\n '[Neetru SDK / firestore-compat] WebCrypto indisponível: generateId() exige ' +\r\n 'globalThis.crypto.getRandomValues (Node ≥20 ou ambiente browser).',\r\n );\r\n }\r\n let out = '';\r\n while (out.length < 20) {\r\n const buf = new Uint8Array(20 - out.length);\r\n cryptoObj.getRandomValues(buf);\r\n for (const byte of buf) {\r\n if (byte < 248) {\r\n out += CHARS[byte % 62];\r\n if (out.length === 20) break;\r\n }\r\n }\r\n }\r\n return out;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// QUERY — acumula constraints e gera DbQuery quando consumido\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\nexport type QueryConstraintType = 'where' | 'orderBy' | 'limit';\r\n\r\nexport interface QueryConstraint {\r\n readonly __constraint: QueryConstraintType;\r\n}\r\n\r\ninterface WhereConstraint extends QueryConstraint {\r\n readonly __constraint: 'where';\r\n readonly field: string;\r\n readonly op: WhereFilterOp;\r\n readonly value: unknown;\r\n}\r\n\r\ninterface OrderByConstraint extends QueryConstraint {\r\n readonly __constraint: 'orderBy';\r\n readonly field: string;\r\n readonly direction: 'asc' | 'desc';\r\n}\r\n\r\ninterface LimitConstraint extends QueryConstraint {\r\n readonly __constraint: 'limit';\r\n readonly value: number;\r\n}\r\n\r\nexport interface Query<T = Record<string, unknown>> {\r\n readonly type: 'query';\r\n readonly __kind: 'query';\r\n readonly path: string;\r\n readonly collection: string;\r\n readonly db: NeetruDb;\r\n readonly ref: DbCollectionRef<T>;\r\n readonly constraints: QueryConstraint[];\r\n}\r\n\r\n/**\r\n * `query(collectionRef, ...constraints)` — combina `where`/`orderBy`/`limit`.\r\n * Aceita também uma `Query` como fonte (encadeamento de constraints).\r\n */\r\nexport function query<T = Record<string, unknown>>(\r\n source: CollectionReference<T> | Query<T>,\r\n ...constraints: QueryConstraint[]\r\n): Query<T> {\r\n const base: Query<T> =\r\n source.__kind === 'query'\r\n ? source\r\n : {\r\n type: 'query',\r\n __kind: 'query',\r\n path: source.path,\r\n collection: source.id,\r\n db: source.db,\r\n ref: source.ref,\r\n constraints: [],\r\n };\r\n return { ...base, constraints: [...base.constraints, ...constraints] };\r\n}\r\n\r\nexport function where(field: string, op: WhereFilterOp, value: unknown): WhereConstraint {\r\n return { __constraint: 'where', field, op, value };\r\n}\r\n\r\nexport function orderBy(field: string, direction: 'asc' | 'desc' = 'asc'): OrderByConstraint {\r\n return { __constraint: 'orderBy', field, direction };\r\n}\r\n\r\nexport function limit(value: number): LimitConstraint {\r\n return { __constraint: 'limit', value };\r\n}\r\n\r\n/**\r\n * Converte os constraints de uma `Query` compat para o `DbQuery` nativo do SDK.\r\n *\r\n * Exportado para que os hooks React (`@neetru/sdk/react`) possam reusar a mesma\r\n * tradução — fonte única de verdade da conversão de constraints.\r\n */\r\nexport function toDbQuery(constraints: QueryConstraint[]): DbQuery {\r\n const whereFilters: DbWhereFilter[] = [];\r\n let orderByClause: DbQuery['orderBy'];\r\n let limitValue: number | undefined;\r\n\r\n for (const c of constraints) {\r\n if (c.__constraint === 'where') {\r\n const w = c as WhereConstraint;\r\n whereFilters.push({ field: w.field, op: normalizeOp(w.op), value: w.value });\r\n } else if (c.__constraint === 'orderBy') {\r\n const o = c as OrderByConstraint;\r\n orderByClause = { field: o.field, direction: o.direction };\r\n } else if (c.__constraint === 'limit') {\r\n limitValue = (c as LimitConstraint).value;\r\n }\r\n }\r\n\r\n const out: DbQuery = {};\r\n if (whereFilters.length > 0) out.where = whereFilters;\r\n if (orderByClause) out.orderBy = orderByClause;\r\n if (limitValue !== undefined) out.limit = limitValue;\r\n return out;\r\n}\r\n\r\n/**\r\n * O `DbWhereFilter` do SDK não declara `array-contains-any`/`not-in` no union.\r\n * Passamos o op como-está; o Core valida server-side e retorna erro explícito\r\n * se não suportado.\r\n *\r\n * Bug corrigido: remapeava 'array-contains-any' → 'array-contains' silenciosamente,\r\n * o que tem semântica completamente diferente (checa literal do array, não interseção)\r\n * e nunca retornava resultados para queries reais.\r\n */\r\nfunction normalizeOp(op: WhereFilterOp): DbWhereFilter['op'] {\r\n // Todas as ops passam direto; o Core valida server-side.\r\n return op as DbWhereFilter['op'];\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// SNAPSHOTS — emulam a API antiga do Firebase\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/** Remove o campo `id` dos dados (o Firestore expõe id via `.id`, não em `data()`). */\r\nfunction stripId<T>(raw: Record<string, unknown>): T {\r\n if (raw && typeof raw === 'object' && 'id' in raw) {\r\n const { id: _omit, ...rest } = raw;\r\n return rest as T;\r\n }\r\n return raw as T;\r\n}\r\n\r\nexport class DocumentSnapshot<T = Record<string, unknown>> {\r\n constructor(\r\n public readonly id: string,\r\n private readonly _data: T | null,\r\n public readonly ref?: DocumentReference<T>,\r\n ) {}\r\n\r\n exists(): boolean {\r\n return this._data != null;\r\n }\r\n\r\n data(): T | undefined {\r\n return this._data ?? undefined;\r\n }\r\n\r\n /** Compat: `snap.get('field')` lê um campo top-level. */\r\n get(field: string): unknown {\r\n return this._data ? (this._data as Record<string, unknown>)[field] : undefined;\r\n }\r\n}\r\n\r\nexport interface QueryDocumentSnapshot<T = Record<string, unknown>> {\r\n readonly id: string;\r\n data(): T;\r\n exists(): boolean;\r\n get(field: string): unknown;\r\n readonly ref: DocumentReference<T>;\r\n}\r\n\r\nexport class QuerySnapshot<T = Record<string, unknown>> {\r\n public readonly docs: Array<QueryDocumentSnapshot<T>>;\r\n public readonly empty: boolean;\r\n public readonly size: number;\r\n\r\n constructor(\r\n rows: Array<{ id: string; data: Record<string, unknown> }>,\r\n db?: NeetruDb,\r\n collectionName?: string,\r\n ) {\r\n this.docs = rows.map(({ id, data }) => {\r\n const stripped = stripId<T>(data);\r\n const ref: DocumentReference<T> | undefined =\r\n db && collectionName ? makeDocRef<T>(db, collectionName, id) : undefined;\r\n return {\r\n id,\r\n data: () => stripped,\r\n exists: () => true,\r\n get: (field: string) => (stripped as Record<string, unknown>)?.[field],\r\n // ref sempre presente quando db+collection conhecidos (caso comum).\r\n ref: ref as DocumentReference<T>,\r\n };\r\n });\r\n this.empty = this.docs.length === 0;\r\n this.size = this.docs.length;\r\n }\r\n\r\n forEach(cb: (doc: QueryDocumentSnapshot<T>) => void): void {\r\n this.docs.forEach(cb);\r\n }\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// READS\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/** Extrai os dados crus do primeiro doc de um `DbGetResult`. */\r\nfunction firstDocData(result: DbGetResult<Record<string, unknown>> | null): {\r\n data: Record<string, unknown> | null;\r\n id: string | null;\r\n} {\r\n const first = result?.docs[0];\r\n return { data: first ? (first.data as Record<string, unknown>) : null, id: first?.id ?? null };\r\n}\r\n\r\nexport async function getDoc<T = Record<string, unknown>>(\r\n ref: DocumentReference<T>,\r\n): Promise<DocumentSnapshot<T>> {\r\n const result = (await ref.db.collection(ref.collection).get(ref.id)) as DbGetResult<\r\n Record<string, unknown>\r\n > | null;\r\n const { data } = firstDocData(result);\r\n return new DocumentSnapshot<T>(\r\n ref.id,\r\n data ? (stripId<T>({ id: ref.id, ...data })) : null,\r\n ref,\r\n );\r\n}\r\n\r\n/** Mapeia um `DbListResult` para linhas `{ id, data }` (id garantido). */\r\nfunction listResultToRows(\r\n result: DbListResult<Record<string, unknown>>,\r\n): Array<{ id: string; data: Record<string, unknown> }> {\r\n return result.docs.map((d) => ({ id: d.id, data: { ...(d.data as Record<string, unknown>) } }));\r\n}\r\n\r\nexport async function getDocs<T = Record<string, unknown>>(\r\n source: CollectionReference<T> | Query<T>,\r\n): Promise<QuerySnapshot<T>> {\r\n const dbQuery = source.__kind === 'query' ? toDbQuery(source.constraints) : undefined;\r\n const collectionName = source.__kind === 'query' ? source.collection : source.id;\r\n const result = (await source.db\r\n .collection(collectionName)\r\n .list(dbQuery)) as DbListResult<Record<string, unknown>>;\r\n return new QuerySnapshot<T>(listResultToRows(result), source.db, collectionName);\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// WRITES\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\nexport interface SetOptions {\r\n merge?: boolean;\r\n mergeFields?: string[];\r\n}\r\n\r\nexport async function setDoc<T = Record<string, unknown>>(\r\n ref: DocumentReference<T>,\r\n data: Partial<T> | Record<string, unknown>,\r\n options: SetOptions = {},\r\n): Promise<void> {\r\n const col = ref.db.collection(ref.collection);\r\n const payload = data as Record<string, unknown>;\r\n if (options.merge || (options.mergeFields && options.mergeFields.length > 0)) {\r\n // Bug corrigido: `update()` retorna 404 no Core quando o doc não existe.\r\n // Verificamos existência antes: se existir → update (merge); se não → set (criar).\r\n // Isso espelha a semântica do Firebase setDoc({merge:true}) (upsert real).\r\n const existing = await col.get(ref.id);\r\n const docExists = Array.isArray((existing as { docs?: unknown[] } | null)?.docs)\r\n ? ((existing as { docs: unknown[] }).docs.length > 0)\r\n : existing != null;\r\n if (docExists) {\r\n await col.update(ref.id, payload);\r\n } else {\r\n await col.set(ref.id, payload);\r\n }\r\n } else {\r\n await col.set(ref.id, payload);\r\n }\r\n}\r\n\r\nexport async function addDoc<T = Record<string, unknown>>(\r\n source: CollectionReference<T>,\r\n data: Partial<T> | Record<string, unknown>,\r\n): Promise<DocumentReference<T>> {\r\n const result = await source.db.collection(source.id).add(data as Record<string, unknown>);\r\n return makeDocRef<T>(source.db, source.id, result.id);\r\n}\r\n\r\nexport async function updateDoc<T = Record<string, unknown>>(\r\n ref: DocumentReference<T>,\r\n data: Partial<T> | Record<string, unknown>,\r\n): Promise<void> {\r\n await ref.db.collection(ref.collection).update(ref.id, data as Record<string, unknown>);\r\n}\r\n\r\nexport async function deleteDoc(ref: DocumentReference): Promise<void> {\r\n await ref.db.collection(ref.collection).remove(ref.id);\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// WRITE BATCH\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\ninterface PendingBatchOp {\r\n collection: string;\r\n op:\r\n | { kind: 'set'; id: string; data: Record<string, unknown> }\r\n | { kind: 'update'; id: string; data: Record<string, unknown> }\r\n | { kind: 'remove'; id: string };\r\n}\r\n\r\nexport class WriteBatch {\r\n private ops: PendingBatchOp[] = [];\r\n\r\n constructor(private readonly db: NeetruDb) {}\r\n\r\n set<T>(\r\n ref: DocumentReference<T>,\r\n data: Partial<T> | Record<string, unknown>,\r\n _options?: SetOptions,\r\n ): this {\r\n this.ops.push({\r\n collection: ref.collection,\r\n op: { kind: 'set', id: ref.id, data: data as Record<string, unknown> },\r\n });\r\n return this;\r\n }\r\n\r\n update<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>): this {\r\n this.ops.push({\r\n collection: ref.collection,\r\n op: { kind: 'update', id: ref.id, data: data as Record<string, unknown> },\r\n });\r\n return this;\r\n }\r\n\r\n delete(ref: DocumentReference): this {\r\n this.ops.push({ collection: ref.collection, op: { kind: 'remove', id: ref.id } });\r\n return this;\r\n }\r\n\r\n async commit(): Promise<void> {\r\n // Agrupa por coleção — o `DbCollectionRef.batch` opera numa coleção por vez.\r\n const byCol = new Map<string, PendingBatchOp['op'][]>();\r\n for (const { collection: name, op } of this.ops) {\r\n const list = byCol.get(name) ?? [];\r\n list.push(op);\r\n byCol.set(name, list);\r\n }\r\n for (const [name, ops] of byCol.entries()) {\r\n // O union nativo `DbBatchOp` casa 1:1 com nossas variantes (set/update/remove).\r\n await this.db.collection(name).batch(ops as never);\r\n }\r\n this.ops = [];\r\n }\r\n}\r\n\r\nexport function writeBatch(db: DbArg): WriteBatch {\r\n return new WriteBatch(resolveDb(db));\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// runTransaction — emulação otimista (read → write) sobre client.db\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Handle de transação compat. O SDK não expõe transações multi-doc atômicas\r\n * com lock server-side, então emulamos a forma do Firebase: `tx.get` lê do\r\n * `client.db`, e `tx.set/update/delete` enfileiram escritas que são aplicadas\r\n * no fim do callback.\r\n *\r\n * ⚠️ **LIMITAÇÃO CONHECIDA — sem isolamento server-side (lost-update silencioso):**\r\n *\r\n * Diferente do Firestore nativo (que usa serializable snapshot isolation com\r\n * contention detection), este shim executa reads e writes em rounds separados\r\n * sem garantia de atomicidade:\r\n *\r\n * 1. `tx.get(ref)` faz um read imediato via `client.db`.\r\n * 2. As escritas (`tx.set/update/delete`) são **enfileiradas** — não bloqueiam\r\n * outros writers.\r\n * 3. No fim do callback, `batch.commit()` aplica as escritas. Se outro processo\r\n * tiver modificado o mesmo documento entre o read e o commit, a escrita\r\n * será um **lost-update silencioso** (sem erro, sem retry automático).\r\n *\r\n * **Quando isso importa:** counters, saldos, estoques — qualquer dado\r\n * que precise de leitura-modificação-escrita atômica.\r\n *\r\n * **Alternativas seguras:**\r\n * - Use **Server Actions no Core** (`src/lib/actions/`) que rodam dentro\r\n * de transações Firestore Admin SDK reais (com locks server-side).\r\n * - Use `increment()` sentinel para contadores numéricos — server-side atomic.\r\n * - Use `arrayUnion()`/`arrayRemove()` para sets (também server-side atomic).\r\n *\r\n * Esta emulação é aceitável para migrações transitórias e para operações\r\n * onde a probabilidade de concorrência é baixa (ex: dados de um único usuário\r\n * sem write concorrente). **Não use para dados financeiros ou de inventário.**\r\n */\r\nexport interface Transaction {\r\n get<T>(ref: DocumentReference<T>): Promise<DocumentSnapshot<T>>;\r\n set<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>, options?: SetOptions): Transaction;\r\n update<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>): Transaction;\r\n delete(ref: DocumentReference): Transaction;\r\n}\r\n\r\n/** Flag para emitir o aviso de limitação uma só vez por processo (não spammar). */\r\nlet _runTransactionWarnEmitted = false;\r\n\r\nexport async function runTransaction<R>(\r\n db: DbArg,\r\n updateFunction: (transaction: Transaction) => Promise<R>,\r\n): Promise<R> {\r\n // Aviso em desenvolvimento/staging: sem isolamento server-side.\r\n if (!_runTransactionWarnEmitted) {\r\n _runTransactionWarnEmitted = true;\r\n console.warn(\r\n '[Neetru SDK / firestore-compat] runTransaction(): esta emulação NÃO oferece' +\r\n ' isolamento server-side. Reads e writes são executados em rounds separados;' +\r\n ' um write concorrente entre o get() e o commit() resultará em lost-update' +\r\n ' silencioso. Para atomicidade real, use Server Actions no Core ou sentinels' +\r\n ' increment()/arrayUnion(). Veja a doc em src/firestore-compat.ts § runTransaction.',\r\n );\r\n }\r\n\r\n const resolved = resolveDb(db);\r\n const batch = new WriteBatch(resolved);\r\n\r\n const tx: Transaction = {\r\n async get<T>(ref: DocumentReference<T>): Promise<DocumentSnapshot<T>> {\r\n return getDoc(ref);\r\n },\r\n set(ref, data, options) {\r\n batch.set(ref, data, options);\r\n return tx;\r\n },\r\n update(ref, data) {\r\n batch.update(ref, data);\r\n return tx;\r\n },\r\n delete(ref) {\r\n batch.delete(ref);\r\n return tx;\r\n },\r\n };\r\n\r\n const result = await updateFunction(tx);\r\n await batch.commit();\r\n return result;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// onSnapshot — realtime via client.db (com fallback inicial)\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\nexport type Unsubscribe = () => void;\r\n\r\ntype DocOnNext<T> = (snap: DocumentSnapshot<T>) => void;\r\ntype QueryOnNext<T> = (snap: QuerySnapshot<T>) => void;\r\ntype OnError = (err: Error) => void;\r\n\r\nexport function onSnapshot<T>(\r\n ref: DocumentReference<T>,\r\n onNext: DocOnNext<T>,\r\n onError?: OnError,\r\n): Unsubscribe;\r\nexport function onSnapshot<T>(\r\n source: Query<T> | CollectionReference<T>,\r\n onNext: QueryOnNext<T>,\r\n onError?: OnError,\r\n): Unsubscribe;\r\nexport function onSnapshot<T>(\r\n source: DocumentReference<T> | Query<T> | CollectionReference<T>,\r\n onNext: DocOnNext<T> | QueryOnNext<T>,\r\n onError?: OnError,\r\n): Unsubscribe {\r\n // Documento único\r\n if (source.__kind === 'document') {\r\n const ref = source as DocumentReference<T>;\r\n const docRef = ref.db.collection(ref.collection).doc(ref.id);\r\n try {\r\n return docRef.onSnapshot((snap) => {\r\n const data = snap?.docs[0]?.data as Record<string, unknown> | undefined;\r\n (onNext as DocOnNext<T>)(\r\n new DocumentSnapshot<T>(\r\n ref.id,\r\n data ? stripId<T>({ id: ref.id, ...data }) : null,\r\n ref,\r\n ),\r\n );\r\n });\r\n } catch (err) {\r\n onError?.(err instanceof Error ? err : new Error(String(err)));\r\n return () => {};\r\n }\r\n }\r\n\r\n // Coleção / Query\r\n const collectionName = source.__kind === 'query' ? source.collection : (source as CollectionReference<T>).id;\r\n const dbQuery = source.__kind === 'query' ? toDbQuery(source.constraints) : undefined;\r\n const col = source.db.collection(collectionName);\r\n try {\r\n return col.onSnapshot(dbQuery, (snap: DbListResult<Record<string, unknown>>) => {\r\n (onNext as QueryOnNext<T>)(\r\n new QuerySnapshot<T>(listResultToRows(snap), source.db, collectionName),\r\n );\r\n });\r\n } catch (err) {\r\n onError?.(err instanceof Error ? err : new Error(String(err)));\r\n return () => {};\r\n }\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// Timestamp — classe leve compat\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Reimplementação compat de `Timestamp` do Firestore. Sem proto do Firebase.\r\n * Cobre `seconds`, `nanoseconds`, `toDate()`, `toMillis()`, `isEqual()`,\r\n * `valueOf()`, `toJSON()` + estáticos `now()`, `fromDate()`, `fromMillis()`.\r\n */\r\nexport class Timestamp {\r\n constructor(\r\n public readonly seconds: number,\r\n public readonly nanoseconds: number,\r\n ) {}\r\n\r\n static now(): Timestamp {\r\n return Timestamp.fromMillis(Date.now());\r\n }\r\n\r\n static fromDate(date: Date): Timestamp {\r\n return Timestamp.fromMillis(date.getTime());\r\n }\r\n\r\n static fromMillis(millis: number): Timestamp {\r\n const seconds = Math.floor(millis / 1000);\r\n const nanoseconds = (millis - seconds * 1000) * 1e6;\r\n return new Timestamp(seconds, nanoseconds);\r\n }\r\n\r\n toDate(): Date {\r\n return new Date(this.toMillis());\r\n }\r\n\r\n toMillis(): number {\r\n return this.seconds * 1000 + Math.floor(this.nanoseconds / 1e6);\r\n }\r\n\r\n isEqual(other: Timestamp): boolean {\r\n return this.seconds === other.seconds && this.nanoseconds === other.nanoseconds;\r\n }\r\n\r\n valueOf(): string {\r\n // Estável para ordenação por string (espelha Firebase).\r\n return `${this.seconds.toString().padStart(12, '0')}.${this.nanoseconds\r\n .toString()\r\n .padStart(9, '0')}`;\r\n }\r\n\r\n toJSON(): { seconds: number; nanoseconds: number } {\r\n return { seconds: this.seconds, nanoseconds: this.nanoseconds };\r\n }\r\n\r\n toString(): string {\r\n return `Timestamp(seconds=${this.seconds}, nanoseconds=${this.nanoseconds})`;\r\n }\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// FieldValue + sentinels\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Sentinel de `arrayUnion`/`arrayRemove`. O SDK ainda não tem sentinel de array\r\n * server-side, então emitimos um marker namespaceado que o Core reconhece\r\n * (mesma família de `__neetru__`). Se o backing não suportar, o produto deve\r\n * preferir read-modify-write via Server Action. Documentado como compat.\r\n */\r\nexport interface ArrayUnionSentinel {\r\n readonly __neetru__: 'arrayUnion';\r\n readonly elements: unknown[];\r\n}\r\nexport interface ArrayRemoveSentinel {\r\n readonly __neetru__: 'arrayRemove';\r\n readonly elements: unknown[];\r\n}\r\n\r\n/**\r\n * Sentinel de campo a deletar (compat `deleteField()`).\r\n */\r\nexport interface DeleteFieldSentinel {\r\n readonly __neetru__: 'deleteField';\r\n}\r\n\r\n/**\r\n * `serverTimestamp()` — delega ao sentinel do SDK (resolvido SERVER-SIDE).\r\n * NÃO retorna mais ISO/Date do cliente (que era spoofável).\r\n */\r\nexport function serverTimestamp(): FieldSentinel {\r\n return sdkServerTimestamp();\r\n}\r\n\r\n/**\r\n * `increment(n)` — incremento atômico server-side (delega ao sentinel do SDK).\r\n */\r\nexport function increment(n: number): FieldSentinel {\r\n return sdkIncrement(n);\r\n}\r\n\r\n/** `arrayUnion(...elements)` — sentinel compat (resolvido pelo Core). */\r\nexport function arrayUnion(...elements: unknown[]): ArrayUnionSentinel {\r\n return { __neetru__: 'arrayUnion', elements };\r\n}\r\n\r\n/** `arrayRemove(...elements)` — sentinel compat (resolvido pelo Core). */\r\nexport function arrayRemove(...elements: unknown[]): ArrayRemoveSentinel {\r\n return { __neetru__: 'arrayRemove', elements };\r\n}\r\n\r\n/** `deleteField()` — sentinel compat para remover um campo. */\r\nexport function deleteField(): DeleteFieldSentinel {\r\n return { __neetru__: 'deleteField' };\r\n}\r\n\r\n/**\r\n * Namespace estático `FieldValue` — espelha `firebase/firestore`'s `FieldValue`.\r\n * Os métodos delegam às funções modulares acima.\r\n *\r\n * @example\r\n * ```ts\r\n * import { FieldValue } from '@neetru/sdk/firestore-compat';\r\n * await updateDoc(ref, {\r\n * tags: FieldValue.arrayUnion('novo'),\r\n * counter: FieldValue.increment(1),\r\n * updatedAt: FieldValue.serverTimestamp(),\r\n * });\r\n * ```\r\n */\r\nexport const FieldValue = {\r\n serverTimestamp,\r\n increment,\r\n arrayUnion,\r\n arrayRemove,\r\n delete: deleteField,\r\n} as const;\r\n","/**\r\n * SDK React helpers (v1.1) — subpath import `@neetru/sdk/react`.\r\n *\r\n * Helpers leves pra React 18+/19. Não puxa `react` como dep direta — caller\r\n * fornece via peer (alinhado com `@stripe/react-stripe-js` / `firebase`).\r\n *\r\n * Exports:\r\n * - `<CheckoutLink>` — wrapper de `<a>` que chama `client.checkout.start()` no click.\r\n * - `<EntitlementGate>` — wrapper que gateia children por entitlement check\r\n * (suporte a `mode='readonly'` pro decisão CEO §5).\r\n * - `useEntitlementContext()` — hook pra ler estado de readonly do contexto.\r\n *\r\n * **Bundle**: este file SÓ é carregado por quem importa `@neetru/sdk/react`.\r\n * Tree-shake garante que SDK consumers Node-only (CLI, edge handlers) não\r\n * puxam React mesmo via transitive.\r\n */\r\nimport * as React from 'react';\r\nimport type { NeetruClient, NeetruUser, AuthNamespace } from './types';\r\nimport type { CheckoutStartInput, CheckoutStartResult } from './checkout';\r\nimport type {\r\n CollectionReference,\r\n Query,\r\n DocumentReference,\r\n} from './firestore-compat';\r\nimport { toDbQuery } from './firestore-compat';\r\nimport type { DbListResult, DbGetResult } from './db/client-db';\r\n\r\n// ─── <CheckoutLink> ─────────────────────────────────────────────────────────\r\n\r\nexport interface CheckoutLinkProps\r\n extends Omit<\r\n React.AnchorHTMLAttributes<HTMLAnchorElement>,\r\n 'href' | 'onClick' | 'onError'\r\n > {\r\n /** Cliente SDK Neetru. Passado explicitamente pra evitar context provider. */\r\n client: NeetruClient;\r\n /** Slug do produto (ex: `neetru-pulse`). */\r\n productId: string;\r\n /** Plan id (ex: `pro_monthly`). */\r\n planId: string;\r\n /** Pra onde o produto SaaS quer voltar pós-checkout. */\r\n callbackUrl: string;\r\n /** Override pra checkout em nome de uma org. Default: PF do uid logado. */\r\n tenantType?: 'pf' | 'pj';\r\n tenantId?: string;\r\n /** Children — texto/JSX do CTA. */\r\n children: React.ReactNode;\r\n /** Callback quando intent foi criada (antes de redirect). */\r\n onIntentCreated?: (result: CheckoutStartResult) => void;\r\n /** Callback de erro. */\r\n onError?: (err: Error) => void;\r\n /** Quando true, NÃO redireciona automaticamente — caller controla. */\r\n noAutoRedirect?: boolean;\r\n /** Override de href (default: `#`). */\r\n href?: string;\r\n}\r\n\r\n/**\r\n * Wrapper de `<a>` que dispara `client.checkout.start()` no click.\r\n *\r\n * Uso típico:\r\n * ```tsx\r\n * <CheckoutLink\r\n * client={client}\r\n * productId=\"meu-saas\"\r\n * planId=\"pro_monthly\"\r\n * callbackUrl=\"https://meu-saas.com/billing/success\"\r\n * >\r\n * Assinar Pro\r\n * </CheckoutLink>\r\n * ```\r\n *\r\n * `href` é stub (`#`) — preventDefault no click. Mantido pra a11y / preview\r\n * de URL no hover (pode ser sobrescrito via prop spread).\r\n */\r\nexport function CheckoutLink({\r\n client,\r\n productId,\r\n planId,\r\n callbackUrl,\r\n tenantType,\r\n tenantId,\r\n children,\r\n onIntentCreated,\r\n onError,\r\n noAutoRedirect,\r\n ...rest\r\n}: CheckoutLinkProps): React.ReactElement {\r\n const [submitting, setSubmitting] = React.useState(false);\r\n\r\n // Lazy access — `client.checkout` foi adicionado em SDK 1.1, fall back gracioso\r\n // se caller passar um client antigo (mesmo que types resolvam, runtime check).\r\n const checkout = (client as { checkout?: { start: (input: CheckoutStartInput) => Promise<CheckoutStartResult> } }).checkout;\r\n\r\n const handleClick = React.useCallback(\r\n async (event: React.MouseEvent<HTMLAnchorElement>) => {\r\n event.preventDefault();\r\n if (submitting) return;\r\n if (!checkout || typeof checkout.start !== 'function') {\r\n onError?.(new Error('SDK client missing `checkout` namespace. Upgrade @neetru/sdk to 1.1+.'));\r\n return;\r\n }\r\n setSubmitting(true);\r\n try {\r\n const result = await checkout.start({\r\n productId,\r\n planId,\r\n callbackUrl,\r\n tenantType,\r\n tenantId,\r\n autoRedirect: !noAutoRedirect,\r\n });\r\n onIntentCreated?.(result);\r\n } catch (err) {\r\n onError?.(err instanceof Error ? err : new Error(String(err)));\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n },\r\n [submitting, checkout, productId, planId, callbackUrl, tenantType, tenantId, noAutoRedirect, onIntentCreated, onError],\r\n );\r\n\r\n return React.createElement(\r\n 'a',\r\n {\r\n ...rest,\r\n href: rest.href ?? '#',\r\n onClick: handleClick,\r\n 'aria-busy': submitting || undefined,\r\n 'data-neetru-checkout-link': 'true',\r\n },\r\n children,\r\n );\r\n}\r\n\r\n// ─── <EntitlementGate> + useEntitlementContext ────────────────────────────\r\n\r\n/** Modo de gate quando entitlement não é permitido. */\r\nexport type EntitlementGateMode = 'block' | 'readonly';\r\n\r\ninterface EntitlementContextValue {\r\n /** True quando feature está em modo read-only (limit exceeded). */\r\n readonly: boolean;\r\n /** Reason code da última check. */\r\n reason?: string;\r\n /** Limite atual (free tier). */\r\n limit?: number;\r\n /** Uso atual. */\r\n currentUsage?: number;\r\n}\r\n\r\nconst EntitlementContext = React.createContext<EntitlementContextValue>({\r\n readonly: false,\r\n});\r\n\r\n/** Hook pra ler estado de readonly. Componentes filhos consomem isso pra\r\n * desabilitar inputs/botões de escrita. */\r\nexport function useEntitlementContext(): EntitlementContextValue {\r\n return React.useContext(EntitlementContext);\r\n}\r\n\r\nexport interface EntitlementGateProps {\r\n /** Cliente SDK Neetru. */\r\n client: NeetruClient;\r\n /** Feature key a checar (ex: `export.csv`). */\r\n feature: string;\r\n /** Slug do produto. Default: lê do client.config se ausente. */\r\n productSlug?: string;\r\n /** Modo:\r\n * - `block` (default): renderiza fallback quando não permitido.\r\n * - `readonly`: sempre renderiza children mas injeta `readonly: true` no contexto. */\r\n mode?: EntitlementGateMode;\r\n /** Fallback UI quando `mode='block'` e check retorna `allowed=false`. */\r\n fallback?: React.ReactNode;\r\n /** Loading UI enquanto check resolve (Suspense-like). */\r\n loading?: React.ReactNode;\r\n children: React.ReactNode;\r\n}\r\n\r\ninterface EntitlementCheckResult {\r\n allowed: boolean;\r\n reason?: string;\r\n limit?: number;\r\n currentUsage?: number;\r\n behavior?: 'readonly' | null;\r\n}\r\n\r\n/**\r\n * Wrapper que gateia children por entitlement check.\r\n *\r\n * Quando `mode='readonly'` + check retorna `behavior='readonly'`:\r\n * - Children renderizam normalmente.\r\n * - Context injeta `{readonly: true}`.\r\n * - Componentes filhos chamam `useEntitlementContext()` pra desabilitar\r\n * escritas (botões, forms, inputs).\r\n *\r\n * Quando `mode='block'` + check retorna `allowed=false`:\r\n * - `fallback` é renderizado (ex: paywall, upsell modal).\r\n *\r\n * Decisão CEO §5 (overage): plataforma usa `readonly` sempre — produto SaaS\r\n * deve preferir `mode='readonly'` pra preservar engajamento (não hard-block).\r\n */\r\nexport function EntitlementGate({\r\n client,\r\n feature,\r\n productSlug,\r\n mode = 'block',\r\n fallback,\r\n loading,\r\n children,\r\n}: EntitlementGateProps): React.ReactElement {\r\n const [state, setState] = React.useState<{ status: 'loading' | 'ready'; result?: EntitlementCheckResult }>({\r\n status: 'loading',\r\n });\r\n\r\n // Resolve productSlug from prop or client.config\r\n const resolvedSlug =\r\n productSlug ?? (client.config as { productId?: string }).productId ?? '';\r\n\r\n // tenantId fallback: client.config.tenantId (default no createNeetruClient).\r\n // usage.check valida ambos productId + tenantId — sem isso, lança\r\n // validation_failed e o Gate fica trancado em allowed:false.\r\n const resolvedTenantId = (client.config as { tenantId?: string }).tenantId;\r\n\r\n React.useEffect(() => {\r\n let cancelled = false;\r\n const run = async () => {\r\n try {\r\n // Try usage.check first (returns full {allowed, reason, behavior, ...})\r\n // Falls back to entitlements.check (just boolean) if usage.check unavailable.\r\n let result: EntitlementCheckResult;\r\n const usage = (client as {\r\n usage?: {\r\n check: (\r\n resource: string,\r\n opts?: { productId?: string; tenantId?: string },\r\n ) => Promise<EntitlementCheckResult>;\r\n };\r\n }).usage;\r\n if (usage && typeof usage.check === 'function' && resolvedTenantId) {\r\n const res = await usage.check(feature, {\r\n productId: resolvedSlug,\r\n tenantId: resolvedTenantId,\r\n });\r\n result = {\r\n allowed: res.allowed === true,\r\n reason: res.reason,\r\n limit: res.limit,\r\n currentUsage: res.currentUsage,\r\n behavior: res.behavior,\r\n };\r\n } else {\r\n // Sem tenantId, cai pra entitlements.check (não exige tenant) em vez\r\n // de chamar usage.check e tomar validation_failed silencioso.\r\n const allowed = await client.entitlements.check(resolvedSlug, feature);\r\n result = { allowed };\r\n }\r\n if (!cancelled) setState({ status: 'ready', result });\r\n } catch (err) {\r\n // Fail open: erros de rede/timeout não bloqueiam o usuário com plano válido.\r\n // Bug corrigido: antes setava allowed:false (fail-closed) contradizendo o comentário.\r\n if (!cancelled) {\r\n setState({ status: 'ready', result: { allowed: true, reason: 'check_error_fallback' } });\r\n }\r\n if (typeof console !== 'undefined') console.warn('[EntitlementGate] check failed — fail-open', err);\r\n }\r\n };\r\n run();\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [client, feature, resolvedSlug, resolvedTenantId]);\r\n\r\n if (state.status === 'loading') {\r\n return React.createElement(React.Fragment, null, loading ?? null);\r\n }\r\n\r\n const result = state.result;\r\n const allowed = result?.allowed === true;\r\n const isReadonly = !allowed && (mode === 'readonly' || result?.behavior === 'readonly');\r\n\r\n if (!allowed && mode === 'block' && !isReadonly) {\r\n return React.createElement(React.Fragment, null, fallback ?? null);\r\n }\r\n\r\n return React.createElement(\r\n EntitlementContext.Provider,\r\n {\r\n value: {\r\n readonly: isReadonly,\r\n reason: result?.reason,\r\n limit: result?.limit,\r\n currentUsage: result?.currentUsage,\r\n },\r\n },\r\n children,\r\n );\r\n}\r\n\r\n// ════════════════════════════════════════════════════════════════════════════\r\n// SDK-2 — Hooks de dados de 1ª classe (compat com hooks caseiros por-produto)\r\n//\r\n// ⚠️ STATUS: 1ª classe, mas desenhados para CASAR com a superfície que os\r\n// produtos (gestovendas / pdvagiliza) escreveram à mão em cima do\r\n// firestore-compat. Substituem os hooks `useCollection`/`useDoc`/`useUser`\r\n// que cada produto reescrevia (~200-400 LOC por produto).\r\n//\r\n// Estes hooks aceitam **refs do `@neetru/sdk/firestore-compat`**\r\n// (`CollectionReference` / `Query` / `DocumentReference`) e devolvem o shape\r\n// `{ data, isLoading, error, isStale, lastUpdated }` que os produtos já\r\n// consomem. Internamente usam o realtime nativo do `client.db`\r\n// (`onSnapshot`) quando disponível, com fallback de polling visibility-aware.\r\n//\r\n// Diferença vs `@neetru/sdk/db/react` (`useDocument`/`useCollection` de lá):\r\n// - Lá: API offline-first, ref = `DbCollectionRef` nativo, retorno\r\n// `{ docs, loading, fromCache, stale }`.\r\n// - Aqui: API firestore-compat, ref = ref do firestore-compat, retorno\r\n// `{ data, isLoading, error, isStale, lastUpdated }` (id já embutido em\r\n// cada item; data nunca duplica o id internamente).\r\n// ════════════════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * Resultado de `useCollection` (subpath `@neetru/sdk/react`, API firestore-compat).\r\n *\r\n * Nome distinto de `UseCollectionResult` do subpath `@neetru/sdk/db/react`:\r\n * - `src/db/react.ts` → `{ docs, loading, fromCache, stale, hasPendingWrites }`\r\n * - `src/react.ts` → `{ data, isLoading, error, isStale, lastUpdated }` (este)\r\n *\r\n * Consumers que importam de ambos subpaths não terão clash de tipo.\r\n * Alias de retrocompat `UseCollectionResult` exportado abaixo.\r\n */\r\nexport interface FirestoreCompatCollectionResult<T> {\r\n /** Documentos (cada um com `id` embutido) ou `null` enquanto carrega/sem ref. */\r\n data: Array<T & { id: string }> | null;\r\n /** `true` enquanto o primeiro snapshot não chegou. */\r\n isLoading: boolean;\r\n /** Erro do último refresh (dados exibidos podem estar defasados). */\r\n error: Error | null;\r\n /** `true` quando um refresh falhou ou o snapshot veio do cache/offline. */\r\n isStale: boolean;\r\n /** epoch ms do último snapshot bem-sucedido, ou `null`. */\r\n lastUpdated: number | null;\r\n}\r\n\r\n/**\r\n * Alias de retrocompat — exportado para não quebrar produtos que importam\r\n * `UseCollectionResult` do subpath `@neetru/sdk/react`. Prefira\r\n * `FirestoreCompatCollectionResult` em código novo para evitar o clash de nome\r\n * com `UseCollectionResult` de `@neetru/sdk/db/react`.\r\n *\r\n * @deprecated Use `FirestoreCompatCollectionResult` em novo código.\r\n */\r\nexport type UseCollectionResult<T> = FirestoreCompatCollectionResult<T>;\r\n\r\n/** Resultado de `useDoc`. */\r\nexport interface UseDocResult<T> {\r\n data: (T & { id: string }) | null;\r\n isLoading: boolean;\r\n error: Error | null;\r\n isStale: boolean;\r\n lastUpdated: number | null;\r\n}\r\n\r\n/** Opções comuns dos hooks de dados. */\r\nexport interface UseDataOptions {\r\n /**\r\n * Intervalo de polling de fallback em ms (quando o transporte não oferece\r\n * realtime nativo). Default 5000. O polling pausa quando a aba está oculta.\r\n */\r\n intervalMs?: number;\r\n /**\r\n * Força polling mesmo quando o `onSnapshot` nativo está disponível. Útil para\r\n * transportes REST onde `onSnapshot` só entrega o snapshot inicial.\r\n * Default: `false` (usa realtime quando o transporte oferece).\r\n */\r\n poll?: boolean;\r\n}\r\n\r\nconst DEFAULT_INTERVAL_MS = 5000;\r\n\r\n/** `true` quando a aba está oculta (não dispara polling em background). */\r\nfunction isDocumentHidden(): boolean {\r\n return typeof document !== 'undefined' && document.hidden === true;\r\n}\r\n\r\n/**\r\n * Serializa uma fonte de coleção/query firestore-compat numa chave estável.\r\n * Garante que mudanças de VALOR (não de identidade) re-subscrevam, mas objetos\r\n * iguais não causem loop de efeito.\r\n */\r\nfunction serializeSource(\r\n source: CollectionReference<unknown> | Query<unknown> | null | undefined,\r\n): string | null {\r\n if (!source) return null;\r\n if (source.__kind === 'collection') {\r\n return `collection:${source.id}`;\r\n }\r\n const dbQuery = toDbQuery(source.constraints);\r\n return `query:${source.collection}:${JSON.stringify(dbQuery)}`;\r\n}\r\n\r\n/** Normaliza linhas de um snapshot do client.db em `{...data, id}` (id embutido). */\r\nfunction rowsFromList<T>(snap: DbListResult<Record<string, unknown>>): Array<T & { id: string }> {\r\n return snap.docs.map((d) => {\r\n const data = d.data as Record<string, unknown>;\r\n // Garante que o id externo prevaleça (sem duplicar dentro do objeto data).\r\n const { id: _omit, ...rest } = data;\r\n return { ...(rest as T), id: d.id };\r\n });\r\n}\r\n\r\nfunction rowFromGet<T>(\r\n snap: DbGetResult<Record<string, unknown>> | null,\r\n id: string,\r\n): (T & { id: string }) | null {\r\n const first = snap?.docs[0];\r\n if (!first) return null;\r\n const data = first.data as Record<string, unknown>;\r\n const { id: _omit, ...rest } = data;\r\n return { ...(rest as T), id };\r\n}\r\n\r\n/**\r\n * Hook de tempo real para uma coleção (ou subconjunto filtrado via `query`).\r\n *\r\n * Aceita uma `CollectionReference` ou `Query` do `@neetru/sdk/firestore-compat`.\r\n * Subscreve ao `onSnapshot` nativo do `client.db`; quando o transporte é REST\r\n * (sem realtime nativo), faz polling visibility-aware no `intervalMs`.\r\n *\r\n * ```tsx\r\n * import { collection, query, where } from '@neetru/sdk/firestore-compat';\r\n * import { useCollection } from '@neetru/sdk/react';\r\n *\r\n * const ref = useMemo(\r\n * () => query(collection(client.db, 'orders'), where('status', '==', 'open')),\r\n * [],\r\n * );\r\n * const { data, isLoading, error, isStale } = useCollection<Order>(ref);\r\n * ```\r\n *\r\n * Seguro em React 18/19 StrictMode.\r\n */\r\nexport function useCollection<T = Record<string, unknown>>(\r\n source: CollectionReference<T> | Query<T> | null | undefined,\r\n options?: UseDataOptions,\r\n): UseCollectionResult<T> {\r\n const intervalMs = options?.intervalMs ?? DEFAULT_INTERVAL_MS;\r\n const poll = options?.poll ?? false;\r\n const sourceKey = serializeSource(\r\n source as CollectionReference<unknown> | Query<unknown> | null | undefined,\r\n );\r\n\r\n const [state, setState] = React.useState<UseCollectionResult<T>>({\r\n data: null,\r\n isLoading: sourceKey !== null,\r\n error: null,\r\n isStale: false,\r\n lastUpdated: null,\r\n });\r\n\r\n const mountedRef = React.useRef(true);\r\n // Mantém a fonte mais recente sem re-disparar o efeito por identidade.\r\n const sourceRef = React.useRef(source);\r\n sourceRef.current = source;\r\n\r\n React.useEffect(() => {\r\n mountedRef.current = true;\r\n const current = sourceRef.current;\r\n\r\n if (!current || sourceKey === null) {\r\n setState({ data: null, isLoading: false, error: null, isStale: false, lastUpdated: null });\r\n return () => {\r\n mountedRef.current = false;\r\n };\r\n }\r\n\r\n setState((prev) => ({ ...prev, isLoading: prev.data === null }));\r\n\r\n const collectionName = current.__kind === 'query' ? current.collection : current.id;\r\n const dbQuery = current.__kind === 'query' ? toDbQuery(current.constraints) : undefined;\r\n const col = current.db.collection(collectionName);\r\n\r\n const applySnap = (snap: DbListResult<Record<string, unknown>>) => {\r\n if (!mountedRef.current) return;\r\n setState({\r\n data: rowsFromList<T>(snap),\r\n isLoading: false,\r\n error: null,\r\n isStale: snap.stale === true,\r\n lastUpdated: Date.now(),\r\n });\r\n };\r\n\r\n const applyError = (e: unknown) => {\r\n if (!mountedRef.current) return;\r\n setState((prev) => ({\r\n ...prev,\r\n // Mantém o último data bom — não limpa em erro de refresh.\r\n isLoading: false,\r\n error: e instanceof Error ? e : new Error(String(e)),\r\n isStale: true,\r\n }));\r\n };\r\n\r\n // Polling explícito (REST) ou realtime nativo.\r\n if (poll) {\r\n let cancelled = false;\r\n const fetchOnce = async () => {\r\n if (cancelled || isDocumentHidden()) return;\r\n try {\r\n const snap = (await col.list(dbQuery)) as DbListResult<Record<string, unknown>>;\r\n if (!cancelled) applySnap(snap);\r\n } catch (e) {\r\n if (!cancelled) applyError(e);\r\n }\r\n };\r\n void fetchOnce();\r\n const timer = setInterval(fetchOnce, intervalMs);\r\n return () => {\r\n cancelled = true;\r\n clearInterval(timer);\r\n mountedRef.current = false;\r\n };\r\n }\r\n\r\n let unsub: (() => void) | undefined;\r\n try {\r\n unsub = col.onSnapshot(dbQuery, applySnap);\r\n } catch (e) {\r\n applyError(e);\r\n }\r\n return () => {\r\n mountedRef.current = false;\r\n unsub?.();\r\n };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [sourceKey, intervalMs, poll]);\r\n\r\n return state;\r\n}\r\n\r\n/**\r\n * Hook de tempo real para um documento.\r\n *\r\n * Aceita uma `DocumentReference` do `@neetru/sdk/firestore-compat`.\r\n *\r\n * ```tsx\r\n * import { doc } from '@neetru/sdk/firestore-compat';\r\n * import { useDoc } from '@neetru/sdk/react';\r\n *\r\n * const ref = useMemo(() => doc(client.db, 'profiles', uid), [uid]);\r\n * const { data, isLoading } = useDoc<Profile>(ref);\r\n * ```\r\n *\r\n * Seguro em React 18/19 StrictMode.\r\n */\r\nexport function useDoc<T = Record<string, unknown>>(\r\n ref: DocumentReference<T> | null | undefined,\r\n options?: UseDataOptions,\r\n): UseDocResult<T> {\r\n const intervalMs = options?.intervalMs ?? DEFAULT_INTERVAL_MS;\r\n const poll = options?.poll ?? false;\r\n const refKey = ref && ref.id ? `${ref.collection}/${ref.id}` : null;\r\n\r\n const [state, setState] = React.useState<UseDocResult<T>>({\r\n data: null,\r\n isLoading: refKey !== null,\r\n error: null,\r\n isStale: false,\r\n lastUpdated: null,\r\n });\r\n\r\n const mountedRef = React.useRef(true);\r\n const refRef = React.useRef(ref);\r\n refRef.current = ref;\r\n\r\n React.useEffect(() => {\r\n mountedRef.current = true;\r\n const current = refRef.current;\r\n\r\n if (!current || refKey === null) {\r\n setState({ data: null, isLoading: false, error: null, isStale: false, lastUpdated: null });\r\n return () => {\r\n mountedRef.current = false;\r\n };\r\n }\r\n\r\n setState((prev) => ({ ...prev, isLoading: prev.data === null }));\r\n\r\n const docRef = current.db.collection(current.collection).doc(current.id);\r\n const id = current.id;\r\n\r\n const applySnap = (snap: DbGetResult<Record<string, unknown>> | null) => {\r\n if (!mountedRef.current) return;\r\n setState({\r\n data: rowFromGet<T>(snap, id),\r\n isLoading: false,\r\n error: null,\r\n isStale: snap?.stale === true,\r\n lastUpdated: Date.now(),\r\n });\r\n };\r\n\r\n const applyError = (e: unknown) => {\r\n if (!mountedRef.current) return;\r\n setState((prev) => ({\r\n ...prev,\r\n isLoading: false,\r\n error: e instanceof Error ? e : new Error(String(e)),\r\n isStale: true,\r\n }));\r\n };\r\n\r\n if (poll) {\r\n let cancelled = false;\r\n const fetchOnce = async () => {\r\n if (cancelled || isDocumentHidden()) return;\r\n try {\r\n const snap = (await docRef.get()) as DbGetResult<Record<string, unknown>> | null;\r\n if (!cancelled) applySnap(snap);\r\n } catch (e) {\r\n if (!cancelled) applyError(e);\r\n }\r\n };\r\n void fetchOnce();\r\n const timer = setInterval(fetchOnce, intervalMs);\r\n return () => {\r\n cancelled = true;\r\n clearInterval(timer);\r\n mountedRef.current = false;\r\n };\r\n }\r\n\r\n let unsub: (() => void) | undefined;\r\n try {\r\n unsub = docRef.onSnapshot(applySnap);\r\n } catch (e) {\r\n applyError(e);\r\n }\r\n return () => {\r\n mountedRef.current = false;\r\n unsub?.();\r\n };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [refKey, intervalMs, poll]);\r\n\r\n return state;\r\n}\r\n\r\n// ─── useUser ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Fonte de auth aceita por `useUser`: o `NeetruClient` inteiro (resolve\r\n * `client.auth`) ou o `AuthNamespace` direto.\r\n */\r\nexport type UseUserInput = NeetruClient | { auth: AuthNamespace } | AuthNamespace;\r\n\r\n/** Resultado de `useUser`. */\r\nexport interface UseUserResult {\r\n /** Usuário autenticado ou `null`. */\r\n user: NeetruUser | null;\r\n /** `true` enquanto o estado de auth inicial não foi resolvido. */\r\n isLoading: boolean;\r\n /** Erro na resolução de auth (raro — listener nunca deveria lançar). */\r\n error: Error | null;\r\n}\r\n\r\nfunction resolveAuth(input: UseUserInput): AuthNamespace {\r\n const maybe = input as { auth?: AuthNamespace };\r\n if (maybe.auth && typeof maybe.auth.onAuthStateChanged === 'function') {\r\n return maybe.auth;\r\n }\r\n return input as AuthNamespace;\r\n}\r\n\r\n/**\r\n * Hook de estado de autenticação.\r\n *\r\n * Subscreve a `client.auth.onAuthStateChanged` e devolve `{ user, isLoading,\r\n * error }`. Inclui um **timeout de seed** (default 8s): se o estado de auth não\r\n * resolver nesse prazo, `isLoading` cai para `false` com `user: null` — evita\r\n * spinners infinitos quando o provedor de auth nunca dispara o callback.\r\n *\r\n * ```tsx\r\n * import { useUser } from '@neetru/sdk/react';\r\n * const { user, isLoading } = useUser(client);\r\n * if (isLoading) return <Spinner />;\r\n * if (!user) return <SignInButton />;\r\n * return <Avatar user={user} />;\r\n * ```\r\n *\r\n * Aceita o `NeetruClient`, `{ auth }` ou o `AuthNamespace` direto.\r\n * Seguro em React 18/19 StrictMode.\r\n */\r\nexport function useUser(\r\n input: UseUserInput,\r\n options?: { timeoutMs?: number },\r\n): UseUserResult {\r\n const timeoutMs = options?.timeoutMs ?? 8000;\r\n const auth = resolveAuth(input);\r\n\r\n const [state, setState] = React.useState<UseUserResult>(() => {\r\n // Seed síncrono do estado atual (se o namespace já tem user em cache).\r\n let seeded: NeetruUser | null = null;\r\n try {\r\n seeded = auth.getUser();\r\n } catch {\r\n seeded = null;\r\n }\r\n return { user: seeded, isLoading: seeded === null, error: null };\r\n });\r\n\r\n const mountedRef = React.useRef(true);\r\n\r\n React.useEffect(() => {\r\n mountedRef.current = true;\r\n let settled = false;\r\n\r\n // Timeout de seed: se onAuthStateChanged nunca disparar, destrava o loading.\r\n const timer = setTimeout(() => {\r\n if (!mountedRef.current || settled) return;\r\n setState((prev) => (prev.isLoading ? { ...prev, isLoading: false } : prev));\r\n }, timeoutMs);\r\n\r\n let unsub: (() => void) | undefined;\r\n try {\r\n unsub = auth.onAuthStateChanged((user) => {\r\n if (!mountedRef.current) return;\r\n settled = true;\r\n setState({ user: user ?? null, isLoading: false, error: null });\r\n });\r\n } catch (e) {\r\n if (mountedRef.current) {\r\n setState({\r\n user: null,\r\n isLoading: false,\r\n error: e instanceof Error ? e : new Error(String(e)),\r\n });\r\n }\r\n }\r\n\r\n return () => {\r\n mountedRef.current = false;\r\n clearTimeout(timer);\r\n unsub?.();\r\n };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [auth, timeoutMs]);\r\n\r\n return state;\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/firestore-compat.ts","../src/react.ts"],"names":["React","result","allowed"],"mappings":"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","file":"react.cjs","sourcesContent":["/**\r\n * @neetru/sdk/firestore-compat — camada de COMPATIBILIDADE (transicional).\r\n *\r\n * ⚠️ **STATUS: compat / transitional.** Este módulo espelha a superfície\r\n * modular do Firebase Firestore (`doc`, `collection`, `query`, `where`,\r\n * `getDocs`, `setDoc`, `onSnapshot`, `writeBatch`, `runTransaction`,\r\n * `serverTimestamp`, `Timestamp`, `FieldValue`, …) para que produtos que\r\n * migram do Firebase **não precisem reescrever as chamadas à mão**.\r\n *\r\n * Ele NÃO é a API nativa do SDK e NÃO compete com `client.db` (NeetruDb).\r\n * É um auxílio de migração: troque os imports de `firebase/firestore` por\r\n * `@neetru/sdk/firestore-compat`, valide, e depois migre incrementalmente\r\n * para a superfície nativa `client.db.collection(...)` quando fizer sentido.\r\n *\r\n * Esta implementação foi desenhada a partir dos shims reais que os produtos\r\n * `neetru-gestovendas` (`src/neetru/firestore.ts`) e `neetru-pdvagiliza`\r\n * (`src/lib/neetru/firestore-compat.ts`) escreveram à mão — espelha\r\n * exatamente a superfície que eles precisam para poder **deletar os shims**.\r\n *\r\n * ### Backing\r\n * Tudo flui por `client.db` (`NeetruDb`). As funções recebem ou um `NeetruDb`\r\n * (o `client.db`) ou o `NeetruClient` inteiro como primeiro argumento — ambos\r\n * são aceitos por `getFirestore(...)`/`collection(...)`/`doc(...)`.\r\n *\r\n * ### Diferenças deliberadas vs Firebase\r\n * - `serverTimestamp()` e `increment()`/`arrayUnion()`/`arrayRemove()` retornam\r\n * sentinels do SDK (`@neetru/sdk` `serverTimestamp`/`increment`) — resolvidos\r\n * SERVER-SIDE pelo Core (não pelo relógio spoofável do cliente).\r\n * - `Timestamp` é uma classe leve (sem proto de Firebase) com `toDate()`,\r\n * `toMillis()`, `seconds`, `nanoseconds` e `Timestamp.now()/fromDate()/fromMillis()`.\r\n * - `onSnapshot` usa o realtime nativo do `client.db` (`onSnapshot`/`doc().onSnapshot`)\r\n * quando o transporte oferece; caso contrário entrega o snapshot inicial e\r\n * reage às mudanças locais (offline-first do SDK).\r\n *\r\n * @module\r\n */\r\n\r\nimport type {\r\n NeetruDb,\r\n DbCollectionRef,\r\n DbQuery,\r\n DbWhereFilter,\r\n DbListResult,\r\n DbGetResult,\r\n} from './db/client-db';\r\nimport {\r\n serverTimestamp as sdkServerTimestamp,\r\n increment as sdkIncrement,\r\n type FieldSentinel,\r\n} from './db/field-value';\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// Resolução do handle de banco\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Aceita tanto o `NeetruDb` (`client.db`) quanto o `NeetruClient` inteiro.\r\n * Produtos legados chamam `getFirestore(client)` ou `getFirestore(client.db)`;\r\n * ambos resolvem para o `NeetruDb` subjacente.\r\n */\r\nexport type FirestoreLike = NeetruDb | { db: NeetruDb };\r\n\r\n/** Marker brand reconhecível em runtime — `getFirestore()` devolve isto. */\r\nexport interface Firestore {\r\n readonly __neetruFirestore: true;\r\n readonly db: NeetruDb;\r\n}\r\n\r\nfunction isClientWrapper(v: FirestoreLike | Firestore): v is { db: NeetruDb } {\r\n return (\r\n typeof v === 'object' &&\r\n v !== null &&\r\n 'db' in v &&\r\n typeof (v as { db?: unknown }).db === 'object' &&\r\n (v as { db?: { collection?: unknown } }).db?.collection !== undefined\r\n );\r\n}\r\n\r\nfunction resolveDb(handle: FirestoreLike | Firestore): NeetruDb {\r\n if ((handle as Firestore).__neetruFirestore) return (handle as Firestore).db;\r\n if (isClientWrapper(handle)) return handle.db;\r\n // É o próprio NeetruDb (tem `.collection`).\r\n return handle as NeetruDb;\r\n}\r\n\r\n/**\r\n * Equivalente compat de `getFirestore(app)`. Aceita o `NeetruClient` ou o\r\n * `client.db` (`NeetruDb`) e devolve um handle `Firestore` opaco.\r\n *\r\n * @example\r\n * ```ts\r\n * import { getFirestore } from '@neetru/sdk/firestore-compat';\r\n * const db = getFirestore(client); // ou getFirestore(client.db)\r\n * ```\r\n */\r\nexport function getFirestore(handle: FirestoreLike): Firestore {\r\n return { __neetruFirestore: true, db: resolveDb(handle) };\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// Refs — Collection & Document\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/** Operadores `where` suportados (subset do Firestore + ops do SDK). */\r\nexport type WhereFilterOp =\r\n | '=='\r\n | '!='\r\n | '<'\r\n | '<='\r\n | '>'\r\n | '>='\r\n | 'in'\r\n | 'not-in'\r\n | 'array-contains'\r\n | 'array-contains-any';\r\n\r\nexport interface CollectionReference<T = Record<string, unknown>> {\r\n readonly type: 'collection';\r\n readonly __kind: 'collection';\r\n readonly id: string;\r\n readonly path: string;\r\n readonly db: NeetruDb;\r\n /** Handle nativo do SDK — atalho para a superfície `client.db`. */\r\n readonly ref: DbCollectionRef<T>;\r\n}\r\n\r\nexport interface DocumentReference<T = Record<string, unknown>> {\r\n readonly type: 'document';\r\n readonly __kind: 'document';\r\n readonly id: string;\r\n readonly path: string;\r\n readonly collection: string;\r\n readonly db: NeetruDb;\r\n /** Marcador de tipo (phantom) — preserva `T` para inferência do caller. */\r\n readonly __doc?: T;\r\n}\r\n\r\n/** Aceita tanto `Firestore` quanto `NeetruDb`/`NeetruClient` direto. */\r\ntype DbArg = Firestore | FirestoreLike;\r\n\r\n/**\r\n * `collection(db, name)` — referência a uma coleção.\r\n *\r\n * Aceita `db` como `Firestore` (de `getFirestore`), `NeetruClient` ou `client.db`.\r\n */\r\nexport function collection<T = Record<string, unknown>>(\r\n db: DbArg,\r\n name: string,\r\n): CollectionReference<T> {\r\n const resolved = resolveDb(db);\r\n return {\r\n type: 'collection',\r\n __kind: 'collection',\r\n id: name,\r\n path: name,\r\n db: resolved,\r\n ref: resolved.collection<T>(name),\r\n };\r\n}\r\n\r\n/**\r\n * `doc(...)` — referência a um documento. Suporta as 3 assinaturas legadas:\r\n * doc(db, 'collection', 'id') → coleção + id\r\n * doc(collectionRef, 'id') → id dentro de uma CollectionReference\r\n * doc(db, 'collection/id') → path com barra (id auto-gerado se id ausente)\r\n *\r\n * Quando o `id` é omitido, gera um id v4 (espelha `doc(collectionRef)` do Firebase\r\n * que cria uma ref com id automático antes do `setDoc`).\r\n */\r\nexport function doc<T = Record<string, unknown>>(\r\n dbOrCollection: DbArg | CollectionReference<T>,\r\n ...path: string[]\r\n): DocumentReference<T> {\r\n // Forma doc(collectionRef, id?)\r\n if (\r\n typeof dbOrCollection === 'object' &&\r\n dbOrCollection !== null &&\r\n (dbOrCollection as CollectionReference<T>).__kind === 'collection'\r\n ) {\r\n const col = dbOrCollection as CollectionReference<T>;\r\n const id = path[0] ?? generateId();\r\n return makeDocRef<T>(col.db, col.id, id);\r\n }\r\n\r\n const resolved = resolveDb(dbOrCollection as DbArg);\r\n\r\n if (path.length >= 2) {\r\n return makeDocRef<T>(resolved, path[0], path.slice(1).join('/'));\r\n }\r\n if (path[0]?.includes('/')) {\r\n const parts = path[0].split('/');\r\n return makeDocRef<T>(resolved, parts[0], parts.slice(1).join('/') || generateId());\r\n }\r\n // doc(db, 'collection') — id auto-gerado\r\n return makeDocRef<T>(resolved, path[0] ?? '', generateId());\r\n}\r\n\r\nfunction makeDocRef<T>(db: NeetruDb, collectionName: string, id: string): DocumentReference<T> {\r\n return {\r\n type: 'document',\r\n __kind: 'document',\r\n id,\r\n collection: collectionName,\r\n path: `${collectionName}/${id}`,\r\n db,\r\n };\r\n}\r\n\r\n/**\r\n * Gera um id estilo Firestore (20 chars alfanuméricos) com aleatoriedade\r\n * CRIPTOGRÁFICA.\r\n *\r\n * Antes usava `Math.random()` — previsível e colisível (PRNG não-criptográfico,\r\n * estado recuperável). IDs de documento previsíveis permitem enumeração/forja.\r\n * Agora usa `globalThis.crypto.getRandomValues` (WebCrypto), disponível tanto em\r\n * Node ≥20 quanto em browsers — sem importar `node:crypto` (que quebraria o\r\n * bundle browser). Rejeita bytes ≥ 248 (4×62) para eliminar o viés de módulo\r\n * sobre o alfabeto de 62 caracteres.\r\n */\r\nfunction generateId(): string {\r\n const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; // 62\r\n const cryptoObj = (globalThis as { crypto?: Crypto }).crypto;\r\n if (!cryptoObj?.getRandomValues) {\r\n throw new Error(\r\n '[Neetru SDK / firestore-compat] WebCrypto indisponível: generateId() exige ' +\r\n 'globalThis.crypto.getRandomValues (Node ≥20 ou ambiente browser).',\r\n );\r\n }\r\n let out = '';\r\n while (out.length < 20) {\r\n const buf = new Uint8Array(20 - out.length);\r\n cryptoObj.getRandomValues(buf);\r\n for (const byte of buf) {\r\n if (byte < 248) {\r\n out += CHARS[byte % 62];\r\n if (out.length === 20) break;\r\n }\r\n }\r\n }\r\n return out;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// QUERY — acumula constraints e gera DbQuery quando consumido\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\nexport type QueryConstraintType = 'where' | 'orderBy' | 'limit';\r\n\r\nexport interface QueryConstraint {\r\n readonly __constraint: QueryConstraintType;\r\n}\r\n\r\ninterface WhereConstraint extends QueryConstraint {\r\n readonly __constraint: 'where';\r\n readonly field: string;\r\n readonly op: WhereFilterOp;\r\n readonly value: unknown;\r\n}\r\n\r\ninterface OrderByConstraint extends QueryConstraint {\r\n readonly __constraint: 'orderBy';\r\n readonly field: string;\r\n readonly direction: 'asc' | 'desc';\r\n}\r\n\r\ninterface LimitConstraint extends QueryConstraint {\r\n readonly __constraint: 'limit';\r\n readonly value: number;\r\n}\r\n\r\nexport interface Query<T = Record<string, unknown>> {\r\n readonly type: 'query';\r\n readonly __kind: 'query';\r\n readonly path: string;\r\n readonly collection: string;\r\n readonly db: NeetruDb;\r\n readonly ref: DbCollectionRef<T>;\r\n readonly constraints: QueryConstraint[];\r\n}\r\n\r\n/**\r\n * `query(collectionRef, ...constraints)` — combina `where`/`orderBy`/`limit`.\r\n * Aceita também uma `Query` como fonte (encadeamento de constraints).\r\n */\r\nexport function query<T = Record<string, unknown>>(\r\n source: CollectionReference<T> | Query<T>,\r\n ...constraints: QueryConstraint[]\r\n): Query<T> {\r\n const base: Query<T> =\r\n source.__kind === 'query'\r\n ? source\r\n : {\r\n type: 'query',\r\n __kind: 'query',\r\n path: source.path,\r\n collection: source.id,\r\n db: source.db,\r\n ref: source.ref,\r\n constraints: [],\r\n };\r\n return { ...base, constraints: [...base.constraints, ...constraints] };\r\n}\r\n\r\nexport function where(field: string, op: WhereFilterOp, value: unknown): WhereConstraint {\r\n return { __constraint: 'where', field, op, value };\r\n}\r\n\r\nexport function orderBy(field: string, direction: 'asc' | 'desc' = 'asc'): OrderByConstraint {\r\n return { __constraint: 'orderBy', field, direction };\r\n}\r\n\r\nexport function limit(value: number): LimitConstraint {\r\n return { __constraint: 'limit', value };\r\n}\r\n\r\n/**\r\n * Converte os constraints de uma `Query` compat para o `DbQuery` nativo do SDK.\r\n *\r\n * Exportado para que os hooks React (`@neetru/sdk/react`) possam reusar a mesma\r\n * tradução — fonte única de verdade da conversão de constraints.\r\n */\r\nexport function toDbQuery(constraints: QueryConstraint[]): DbQuery {\r\n const whereFilters: DbWhereFilter[] = [];\r\n let orderByClause: DbQuery['orderBy'];\r\n let limitValue: number | undefined;\r\n\r\n for (const c of constraints) {\r\n if (c.__constraint === 'where') {\r\n const w = c as WhereConstraint;\r\n whereFilters.push({ field: w.field, op: normalizeOp(w.op), value: w.value });\r\n } else if (c.__constraint === 'orderBy') {\r\n const o = c as OrderByConstraint;\r\n orderByClause = { field: o.field, direction: o.direction };\r\n } else if (c.__constraint === 'limit') {\r\n limitValue = (c as LimitConstraint).value;\r\n }\r\n }\r\n\r\n const out: DbQuery = {};\r\n if (whereFilters.length > 0) out.where = whereFilters;\r\n if (orderByClause) out.orderBy = orderByClause;\r\n if (limitValue !== undefined) out.limit = limitValue;\r\n return out;\r\n}\r\n\r\n/**\r\n * O `DbWhereFilter` do SDK não declara `array-contains-any`/`not-in` no union.\r\n * Passamos o op como-está; o Core valida server-side e retorna erro explícito\r\n * se não suportado.\r\n *\r\n * Bug corrigido: remapeava 'array-contains-any' → 'array-contains' silenciosamente,\r\n * o que tem semântica completamente diferente (checa literal do array, não interseção)\r\n * e nunca retornava resultados para queries reais.\r\n */\r\nfunction normalizeOp(op: WhereFilterOp): DbWhereFilter['op'] {\r\n // Todas as ops passam direto; o Core valida server-side.\r\n return op as DbWhereFilter['op'];\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// SNAPSHOTS — emulam a API antiga do Firebase\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/** Remove o campo `id` dos dados (o Firestore expõe id via `.id`, não em `data()`). */\r\nfunction stripId<T>(raw: Record<string, unknown>): T {\r\n if (raw && typeof raw === 'object' && 'id' in raw) {\r\n const { id: _omit, ...rest } = raw;\r\n return rest as T;\r\n }\r\n return raw as T;\r\n}\r\n\r\nexport class DocumentSnapshot<T = Record<string, unknown>> {\r\n constructor(\r\n public readonly id: string,\r\n private readonly _data: T | null,\r\n public readonly ref?: DocumentReference<T>,\r\n ) {}\r\n\r\n exists(): boolean {\r\n return this._data != null;\r\n }\r\n\r\n data(): T | undefined {\r\n return this._data ?? undefined;\r\n }\r\n\r\n /** Compat: `snap.get('field')` lê um campo top-level. */\r\n get(field: string): unknown {\r\n return this._data ? (this._data as Record<string, unknown>)[field] : undefined;\r\n }\r\n}\r\n\r\nexport interface QueryDocumentSnapshot<T = Record<string, unknown>> {\r\n readonly id: string;\r\n data(): T;\r\n exists(): boolean;\r\n get(field: string): unknown;\r\n readonly ref: DocumentReference<T>;\r\n}\r\n\r\nexport class QuerySnapshot<T = Record<string, unknown>> {\r\n public readonly docs: Array<QueryDocumentSnapshot<T>>;\r\n public readonly empty: boolean;\r\n public readonly size: number;\r\n\r\n constructor(\r\n rows: Array<{ id: string; data: Record<string, unknown> }>,\r\n db?: NeetruDb,\r\n collectionName?: string,\r\n ) {\r\n this.docs = rows.map(({ id, data }) => {\r\n const stripped = stripId<T>(data);\r\n const ref: DocumentReference<T> | undefined =\r\n db && collectionName ? makeDocRef<T>(db, collectionName, id) : undefined;\r\n return {\r\n id,\r\n data: () => stripped,\r\n exists: () => true,\r\n get: (field: string) => (stripped as Record<string, unknown>)?.[field],\r\n // ref sempre presente quando db+collection conhecidos (caso comum).\r\n ref: ref as DocumentReference<T>,\r\n };\r\n });\r\n this.empty = this.docs.length === 0;\r\n this.size = this.docs.length;\r\n }\r\n\r\n forEach(cb: (doc: QueryDocumentSnapshot<T>) => void): void {\r\n this.docs.forEach(cb);\r\n }\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// READS\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/** Extrai os dados crus do primeiro doc de um `DbGetResult`. */\r\nfunction firstDocData(result: DbGetResult<Record<string, unknown>> | null): {\r\n data: Record<string, unknown> | null;\r\n id: string | null;\r\n} {\r\n const first = result?.docs[0];\r\n return { data: first ? (first.data as Record<string, unknown>) : null, id: first?.id ?? null };\r\n}\r\n\r\nexport async function getDoc<T = Record<string, unknown>>(\r\n ref: DocumentReference<T>,\r\n): Promise<DocumentSnapshot<T>> {\r\n const result = (await ref.db.collection(ref.collection).get(ref.id)) as DbGetResult<\r\n Record<string, unknown>\r\n > | null;\r\n const { data } = firstDocData(result);\r\n return new DocumentSnapshot<T>(\r\n ref.id,\r\n data ? (stripId<T>({ id: ref.id, ...data })) : null,\r\n ref,\r\n );\r\n}\r\n\r\n/** Mapeia um `DbListResult` para linhas `{ id, data }` (id garantido). */\r\nfunction listResultToRows(\r\n result: DbListResult<Record<string, unknown>>,\r\n): Array<{ id: string; data: Record<string, unknown> }> {\r\n return result.docs.map((d) => ({ id: d.id, data: { ...(d.data as Record<string, unknown>) } }));\r\n}\r\n\r\nexport async function getDocs<T = Record<string, unknown>>(\r\n source: CollectionReference<T> | Query<T>,\r\n): Promise<QuerySnapshot<T>> {\r\n const dbQuery = source.__kind === 'query' ? toDbQuery(source.constraints) : undefined;\r\n const collectionName = source.__kind === 'query' ? source.collection : source.id;\r\n const result = (await source.db\r\n .collection(collectionName)\r\n .list(dbQuery)) as DbListResult<Record<string, unknown>>;\r\n return new QuerySnapshot<T>(listResultToRows(result), source.db, collectionName);\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// WRITES\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\nexport interface SetOptions {\r\n merge?: boolean;\r\n mergeFields?: string[];\r\n}\r\n\r\nexport async function setDoc<T = Record<string, unknown>>(\r\n ref: DocumentReference<T>,\r\n data: Partial<T> | Record<string, unknown>,\r\n options: SetOptions = {},\r\n): Promise<void> {\r\n const col = ref.db.collection(ref.collection);\r\n const payload = data as Record<string, unknown>;\r\n if (options.merge || (options.mergeFields && options.mergeFields.length > 0)) {\r\n // bug_0273e4dd: ANTES o check de existência usava o cache LOCAL (col.get é\r\n // offline-first). Doc que existia só no SERVIDOR dava docExists=false → caía\r\n // em col.set() (replace) e APAGAVA todos os campos ausentes do payload →\r\n // perda de dados silenciosa. Agora a decisão é DO SERVIDOR via merge-upsert:\r\n // update({upsert:true}) cria-se-ausente OU mescla-se-presente, sem nunca\r\n // apagar campos não enviados — exatamente o setDoc({merge:true}) do Firebase.\r\n // Contrato Core acordado (deploy0632): PATCH com upsert=true não 404a em\r\n // ausente e faz ref.set(data,{merge:true}).\r\n await col.update(ref.id, payload, { upsert: true });\r\n } else {\r\n await col.set(ref.id, payload);\r\n }\r\n}\r\n\r\nexport async function addDoc<T = Record<string, unknown>>(\r\n source: CollectionReference<T>,\r\n data: Partial<T> | Record<string, unknown>,\r\n): Promise<DocumentReference<T>> {\r\n const result = await source.db.collection(source.id).add(data as Record<string, unknown>);\r\n return makeDocRef<T>(source.db, source.id, result.id);\r\n}\r\n\r\nexport async function updateDoc<T = Record<string, unknown>>(\r\n ref: DocumentReference<T>,\r\n data: Partial<T> | Record<string, unknown>,\r\n): Promise<void> {\r\n await ref.db.collection(ref.collection).update(ref.id, data as Record<string, unknown>);\r\n}\r\n\r\nexport async function deleteDoc(ref: DocumentReference): Promise<void> {\r\n await ref.db.collection(ref.collection).remove(ref.id);\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// WRITE BATCH\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\ninterface PendingBatchOp {\r\n collection: string;\r\n op:\r\n | { kind: 'set'; id: string; data: Record<string, unknown> }\r\n | { kind: 'update'; id: string; data: Record<string, unknown>; upsert?: boolean }\r\n | { kind: 'remove'; id: string };\r\n}\r\n\r\nexport class WriteBatch {\r\n private ops: PendingBatchOp[] = [];\r\n\r\n constructor(private readonly db: NeetruDb) {}\r\n\r\n set<T>(\r\n ref: DocumentReference<T>,\r\n data: Partial<T> | Record<string, unknown>,\r\n options?: SetOptions,\r\n ): this {\r\n // bug_0273e4dd: SetOptions.merge era DESCARTADO → batch.set(ref,data,{merge:true})\r\n // virava replace e APAGAVA campos ausentes (perda de dados). Agora merge vira\r\n // update com upsert (merge-server-side, cria-se-ausente), igual ao setDoc.\r\n const merge = !!(options?.merge || (options?.mergeFields && options.mergeFields.length > 0));\r\n this.ops.push({\r\n collection: ref.collection,\r\n op: merge\r\n ? { kind: 'update', id: ref.id, data: data as Record<string, unknown>, upsert: true }\r\n : { kind: 'set', id: ref.id, data: data as Record<string, unknown> },\r\n });\r\n return this;\r\n }\r\n\r\n update<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>): this {\r\n this.ops.push({\r\n collection: ref.collection,\r\n op: { kind: 'update', id: ref.id, data: data as Record<string, unknown> },\r\n });\r\n return this;\r\n }\r\n\r\n delete(ref: DocumentReference): this {\r\n this.ops.push({ collection: ref.collection, op: { kind: 'remove', id: ref.id } });\r\n return this;\r\n }\r\n\r\n async commit(): Promise<void> {\r\n // Agrupa por coleção — o `DbCollectionRef.batch` opera numa coleção por vez.\r\n const byCol = new Map<string, PendingBatchOp['op'][]>();\r\n for (const { collection: name, op } of this.ops) {\r\n const list = byCol.get(name) ?? [];\r\n list.push(op);\r\n byCol.set(name, list);\r\n }\r\n for (const [name, ops] of byCol.entries()) {\r\n // O union nativo `DbBatchOp` casa 1:1 com nossas variantes (set/update/remove).\r\n await this.db.collection(name).batch(ops as never);\r\n }\r\n this.ops = [];\r\n }\r\n}\r\n\r\nexport function writeBatch(db: DbArg): WriteBatch {\r\n return new WriteBatch(resolveDb(db));\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// runTransaction — emulação otimista (read → write) sobre client.db\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Handle de transação compat. O SDK não expõe transações multi-doc atômicas\r\n * com lock server-side, então emulamos a forma do Firebase: `tx.get` lê do\r\n * `client.db`, e `tx.set/update/delete` enfileiram escritas que são aplicadas\r\n * no fim do callback.\r\n *\r\n * ⚠️ **LIMITAÇÃO CONHECIDA — sem isolamento server-side (lost-update silencioso):**\r\n *\r\n * Diferente do Firestore nativo (que usa serializable snapshot isolation com\r\n * contention detection), este shim executa reads e writes em rounds separados\r\n * sem garantia de atomicidade:\r\n *\r\n * 1. `tx.get(ref)` faz um read imediato via `client.db`.\r\n * 2. As escritas (`tx.set/update/delete`) são **enfileiradas** — não bloqueiam\r\n * outros writers.\r\n * 3. No fim do callback, `batch.commit()` aplica as escritas. Se outro processo\r\n * tiver modificado o mesmo documento entre o read e o commit, a escrita\r\n * será um **lost-update silencioso** (sem erro, sem retry automático).\r\n *\r\n * **Quando isso importa:** counters, saldos, estoques — qualquer dado\r\n * que precise de leitura-modificação-escrita atômica.\r\n *\r\n * **Alternativas seguras:**\r\n * - Use **Server Actions no Core** (`src/lib/actions/`) que rodam dentro\r\n * de transações Firestore Admin SDK reais (com locks server-side).\r\n * - Use `increment()` sentinel para contadores numéricos — server-side atomic.\r\n * - Use `arrayUnion()`/`arrayRemove()` para sets (também server-side atomic).\r\n *\r\n * Esta emulação é aceitável para migrações transitórias e para operações\r\n * onde a probabilidade de concorrência é baixa (ex: dados de um único usuário\r\n * sem write concorrente). **Não use para dados financeiros ou de inventário.**\r\n */\r\nexport interface Transaction {\r\n get<T>(ref: DocumentReference<T>): Promise<DocumentSnapshot<T>>;\r\n set<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>, options?: SetOptions): Transaction;\r\n update<T>(ref: DocumentReference<T>, data: Partial<T> | Record<string, unknown>): Transaction;\r\n delete(ref: DocumentReference): Transaction;\r\n}\r\n\r\n/** Flag para emitir o aviso de limitação uma só vez por processo (não spammar). */\r\nlet _runTransactionWarnEmitted = false;\r\n\r\nexport async function runTransaction<R>(\r\n db: DbArg,\r\n updateFunction: (transaction: Transaction) => Promise<R>,\r\n): Promise<R> {\r\n // Aviso em desenvolvimento/staging: sem isolamento server-side.\r\n if (!_runTransactionWarnEmitted) {\r\n _runTransactionWarnEmitted = true;\r\n console.warn(\r\n '[Neetru SDK / firestore-compat] runTransaction(): esta emulação NÃO oferece' +\r\n ' isolamento server-side. Reads e writes são executados em rounds separados;' +\r\n ' um write concorrente entre o get() e o commit() resultará em lost-update' +\r\n ' silencioso. Para atomicidade real, use Server Actions no Core ou sentinels' +\r\n ' increment()/arrayUnion(). Veja a doc em src/firestore-compat.ts § runTransaction.',\r\n );\r\n }\r\n\r\n const resolved = resolveDb(db);\r\n const batch = new WriteBatch(resolved);\r\n\r\n const tx: Transaction = {\r\n async get<T>(ref: DocumentReference<T>): Promise<DocumentSnapshot<T>> {\r\n return getDoc(ref);\r\n },\r\n set(ref, data, options) {\r\n batch.set(ref, data, options);\r\n return tx;\r\n },\r\n update(ref, data) {\r\n batch.update(ref, data);\r\n return tx;\r\n },\r\n delete(ref) {\r\n batch.delete(ref);\r\n return tx;\r\n },\r\n };\r\n\r\n const result = await updateFunction(tx);\r\n await batch.commit();\r\n return result;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// onSnapshot — realtime via client.db (com fallback inicial)\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\nexport type Unsubscribe = () => void;\r\n\r\ntype DocOnNext<T> = (snap: DocumentSnapshot<T>) => void;\r\ntype QueryOnNext<T> = (snap: QuerySnapshot<T>) => void;\r\ntype OnError = (err: Error) => void;\r\n\r\nexport function onSnapshot<T>(\r\n ref: DocumentReference<T>,\r\n onNext: DocOnNext<T>,\r\n onError?: OnError,\r\n): Unsubscribe;\r\nexport function onSnapshot<T>(\r\n source: Query<T> | CollectionReference<T>,\r\n onNext: QueryOnNext<T>,\r\n onError?: OnError,\r\n): Unsubscribe;\r\nexport function onSnapshot<T>(\r\n source: DocumentReference<T> | Query<T> | CollectionReference<T>,\r\n onNext: DocOnNext<T> | QueryOnNext<T>,\r\n onError?: OnError,\r\n): Unsubscribe {\r\n // Documento único\r\n if (source.__kind === 'document') {\r\n const ref = source as DocumentReference<T>;\r\n const docRef = ref.db.collection(ref.collection).doc(ref.id);\r\n try {\r\n return docRef.onSnapshot((snap) => {\r\n const data = snap?.docs[0]?.data as Record<string, unknown> | undefined;\r\n (onNext as DocOnNext<T>)(\r\n new DocumentSnapshot<T>(\r\n ref.id,\r\n data ? stripId<T>({ id: ref.id, ...data }) : null,\r\n ref,\r\n ),\r\n );\r\n });\r\n } catch (err) {\r\n onError?.(err instanceof Error ? err : new Error(String(err)));\r\n return () => {};\r\n }\r\n }\r\n\r\n // Coleção / Query\r\n const collectionName = source.__kind === 'query' ? source.collection : (source as CollectionReference<T>).id;\r\n const dbQuery = source.__kind === 'query' ? toDbQuery(source.constraints) : undefined;\r\n const col = source.db.collection(collectionName);\r\n try {\r\n return col.onSnapshot(dbQuery, (snap: DbListResult<Record<string, unknown>>) => {\r\n (onNext as QueryOnNext<T>)(\r\n new QuerySnapshot<T>(listResultToRows(snap), source.db, collectionName),\r\n );\r\n });\r\n } catch (err) {\r\n onError?.(err instanceof Error ? err : new Error(String(err)));\r\n return () => {};\r\n }\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// Timestamp — classe leve compat\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Reimplementação compat de `Timestamp` do Firestore. Sem proto do Firebase.\r\n * Cobre `seconds`, `nanoseconds`, `toDate()`, `toMillis()`, `isEqual()`,\r\n * `valueOf()`, `toJSON()` + estáticos `now()`, `fromDate()`, `fromMillis()`.\r\n */\r\nexport class Timestamp {\r\n constructor(\r\n public readonly seconds: number,\r\n public readonly nanoseconds: number,\r\n ) {}\r\n\r\n static now(): Timestamp {\r\n return Timestamp.fromMillis(Date.now());\r\n }\r\n\r\n static fromDate(date: Date): Timestamp {\r\n return Timestamp.fromMillis(date.getTime());\r\n }\r\n\r\n static fromMillis(millis: number): Timestamp {\r\n const seconds = Math.floor(millis / 1000);\r\n const nanoseconds = (millis - seconds * 1000) * 1e6;\r\n return new Timestamp(seconds, nanoseconds);\r\n }\r\n\r\n toDate(): Date {\r\n return new Date(this.toMillis());\r\n }\r\n\r\n toMillis(): number {\r\n return this.seconds * 1000 + Math.floor(this.nanoseconds / 1e6);\r\n }\r\n\r\n isEqual(other: Timestamp): boolean {\r\n return this.seconds === other.seconds && this.nanoseconds === other.nanoseconds;\r\n }\r\n\r\n valueOf(): string {\r\n // Estável para ordenação por string (espelha Firebase).\r\n return `${this.seconds.toString().padStart(12, '0')}.${this.nanoseconds\r\n .toString()\r\n .padStart(9, '0')}`;\r\n }\r\n\r\n toJSON(): { seconds: number; nanoseconds: number } {\r\n return { seconds: this.seconds, nanoseconds: this.nanoseconds };\r\n }\r\n\r\n toString(): string {\r\n return `Timestamp(seconds=${this.seconds}, nanoseconds=${this.nanoseconds})`;\r\n }\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// FieldValue + sentinels\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Sentinel de `arrayUnion`/`arrayRemove`. O SDK ainda não tem sentinel de array\r\n * server-side, então emitimos um marker namespaceado que o Core reconhece\r\n * (mesma família de `__neetru__`). Se o backing não suportar, o produto deve\r\n * preferir read-modify-write via Server Action. Documentado como compat.\r\n */\r\nexport interface ArrayUnionSentinel {\r\n readonly __neetru__: 'arrayUnion';\r\n readonly elements: unknown[];\r\n}\r\nexport interface ArrayRemoveSentinel {\r\n readonly __neetru__: 'arrayRemove';\r\n readonly elements: unknown[];\r\n}\r\n\r\n/**\r\n * Sentinel de campo a deletar (compat `deleteField()`).\r\n */\r\nexport interface DeleteFieldSentinel {\r\n readonly __neetru__: 'deleteField';\r\n}\r\n\r\n/**\r\n * `serverTimestamp()` — delega ao sentinel do SDK (resolvido SERVER-SIDE).\r\n * NÃO retorna mais ISO/Date do cliente (que era spoofável).\r\n */\r\nexport function serverTimestamp(): FieldSentinel {\r\n return sdkServerTimestamp();\r\n}\r\n\r\n/**\r\n * `increment(n)` — incremento atômico server-side (delega ao sentinel do SDK).\r\n */\r\nexport function increment(n: number): FieldSentinel {\r\n return sdkIncrement(n);\r\n}\r\n\r\n/** `arrayUnion(...elements)` — sentinel compat (resolvido pelo Core). */\r\nexport function arrayUnion(...elements: unknown[]): ArrayUnionSentinel {\r\n return { __neetru__: 'arrayUnion', elements };\r\n}\r\n\r\n/** `arrayRemove(...elements)` — sentinel compat (resolvido pelo Core). */\r\nexport function arrayRemove(...elements: unknown[]): ArrayRemoveSentinel {\r\n return { __neetru__: 'arrayRemove', elements };\r\n}\r\n\r\n/** `deleteField()` — sentinel compat para remover um campo. */\r\nexport function deleteField(): DeleteFieldSentinel {\r\n return { __neetru__: 'deleteField' };\r\n}\r\n\r\n/**\r\n * Namespace estático `FieldValue` — espelha `firebase/firestore`'s `FieldValue`.\r\n * Os métodos delegam às funções modulares acima.\r\n *\r\n * @example\r\n * ```ts\r\n * import { FieldValue } from '@neetru/sdk/firestore-compat';\r\n * await updateDoc(ref, {\r\n * tags: FieldValue.arrayUnion('novo'),\r\n * counter: FieldValue.increment(1),\r\n * updatedAt: FieldValue.serverTimestamp(),\r\n * });\r\n * ```\r\n */\r\nexport const FieldValue = {\r\n serverTimestamp,\r\n increment,\r\n arrayUnion,\r\n arrayRemove,\r\n delete: deleteField,\r\n} as const;\r\n","/**\r\n * SDK React helpers (v1.1) — subpath import `@neetru/sdk/react`.\r\n *\r\n * Helpers leves pra React 18+/19. Não puxa `react` como dep direta — caller\r\n * fornece via peer (alinhado com `@stripe/react-stripe-js` / `firebase`).\r\n *\r\n * Exports:\r\n * - `<CheckoutLink>` — wrapper de `<a>` que chama `client.checkout.start()` no click.\r\n * - `<EntitlementGate>` — wrapper que gateia children por entitlement check\r\n * (suporte a `mode='readonly'` pro decisão CEO §5).\r\n * - `useEntitlementContext()` — hook pra ler estado de readonly do contexto.\r\n *\r\n * **Bundle**: este file SÓ é carregado por quem importa `@neetru/sdk/react`.\r\n * Tree-shake garante que SDK consumers Node-only (CLI, edge handlers) não\r\n * puxam React mesmo via transitive.\r\n */\r\nimport * as React from 'react';\r\nimport type { NeetruClient, NeetruUser, AuthNamespace } from './types';\r\nimport type { CheckoutStartInput, CheckoutStartResult } from './checkout';\r\nimport type {\r\n CollectionReference,\r\n Query,\r\n DocumentReference,\r\n} from './firestore-compat';\r\nimport { toDbQuery } from './firestore-compat';\r\nimport type { DbListResult, DbGetResult } from './db/client-db';\r\n\r\n// ─── <CheckoutLink> ─────────────────────────────────────────────────────────\r\n\r\nexport interface CheckoutLinkProps\r\n extends Omit<\r\n React.AnchorHTMLAttributes<HTMLAnchorElement>,\r\n 'href' | 'onClick' | 'onError'\r\n > {\r\n /** Cliente SDK Neetru. Passado explicitamente pra evitar context provider. */\r\n client: NeetruClient;\r\n /** Slug do produto (ex: `neetru-pulse`). */\r\n productId: string;\r\n /** Plan id (ex: `pro_monthly`). */\r\n planId: string;\r\n /** Pra onde o produto SaaS quer voltar pós-checkout. */\r\n callbackUrl: string;\r\n /** Override pra checkout em nome de uma org. Default: PF do uid logado. */\r\n tenantType?: 'pf' | 'pj';\r\n tenantId?: string;\r\n /** Children — texto/JSX do CTA. */\r\n children: React.ReactNode;\r\n /** Callback quando intent foi criada (antes de redirect). */\r\n onIntentCreated?: (result: CheckoutStartResult) => void;\r\n /** Callback de erro. */\r\n onError?: (err: Error) => void;\r\n /** Quando true, NÃO redireciona automaticamente — caller controla. */\r\n noAutoRedirect?: boolean;\r\n /** Override de href (default: `#`). */\r\n href?: string;\r\n}\r\n\r\n/**\r\n * Wrapper de `<a>` que dispara `client.checkout.start()` no click.\r\n *\r\n * Uso típico:\r\n * ```tsx\r\n * <CheckoutLink\r\n * client={client}\r\n * productId=\"meu-saas\"\r\n * planId=\"pro_monthly\"\r\n * callbackUrl=\"https://meu-saas.com/billing/success\"\r\n * >\r\n * Assinar Pro\r\n * </CheckoutLink>\r\n * ```\r\n *\r\n * `href` é stub (`#`) — preventDefault no click. Mantido pra a11y / preview\r\n * de URL no hover (pode ser sobrescrito via prop spread).\r\n */\r\nexport function CheckoutLink({\r\n client,\r\n productId,\r\n planId,\r\n callbackUrl,\r\n tenantType,\r\n tenantId,\r\n children,\r\n onIntentCreated,\r\n onError,\r\n noAutoRedirect,\r\n ...rest\r\n}: CheckoutLinkProps): React.ReactElement {\r\n const [submitting, setSubmitting] = React.useState(false);\r\n\r\n // Lazy access — `client.checkout` foi adicionado em SDK 1.1, fall back gracioso\r\n // se caller passar um client antigo (mesmo que types resolvam, runtime check).\r\n const checkout = (client as { checkout?: { start: (input: CheckoutStartInput) => Promise<CheckoutStartResult> } }).checkout;\r\n\r\n const handleClick = React.useCallback(\r\n async (event: React.MouseEvent<HTMLAnchorElement>) => {\r\n event.preventDefault();\r\n if (submitting) return;\r\n if (!checkout || typeof checkout.start !== 'function') {\r\n onError?.(new Error('SDK client missing `checkout` namespace. Upgrade @neetru/sdk to 1.1+.'));\r\n return;\r\n }\r\n setSubmitting(true);\r\n try {\r\n const result = await checkout.start({\r\n productId,\r\n planId,\r\n callbackUrl,\r\n tenantType,\r\n tenantId,\r\n autoRedirect: !noAutoRedirect,\r\n });\r\n onIntentCreated?.(result);\r\n } catch (err) {\r\n onError?.(err instanceof Error ? err : new Error(String(err)));\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n },\r\n [submitting, checkout, productId, planId, callbackUrl, tenantType, tenantId, noAutoRedirect, onIntentCreated, onError],\r\n );\r\n\r\n return React.createElement(\r\n 'a',\r\n {\r\n ...rest,\r\n href: rest.href ?? '#',\r\n onClick: handleClick,\r\n 'aria-busy': submitting || undefined,\r\n 'data-neetru-checkout-link': 'true',\r\n },\r\n children,\r\n );\r\n}\r\n\r\n// ─── <EntitlementGate> + useEntitlementContext ────────────────────────────\r\n\r\n/** Modo de gate quando entitlement não é permitido. */\r\nexport type EntitlementGateMode = 'block' | 'readonly';\r\n\r\ninterface EntitlementContextValue {\r\n /** True quando feature está em modo read-only (limit exceeded). */\r\n readonly: boolean;\r\n /** Reason code da última check. */\r\n reason?: string;\r\n /** Limite atual (free tier). */\r\n limit?: number;\r\n /** Uso atual. */\r\n currentUsage?: number;\r\n}\r\n\r\nconst EntitlementContext = React.createContext<EntitlementContextValue>({\r\n readonly: false,\r\n});\r\n\r\n/** Hook pra ler estado de readonly. Componentes filhos consomem isso pra\r\n * desabilitar inputs/botões de escrita. */\r\nexport function useEntitlementContext(): EntitlementContextValue {\r\n return React.useContext(EntitlementContext);\r\n}\r\n\r\nexport interface EntitlementGateProps {\r\n /** Cliente SDK Neetru. */\r\n client: NeetruClient;\r\n /** Feature key a checar (ex: `export.csv`). */\r\n feature: string;\r\n /** Slug do produto. Default: lê do client.config se ausente. */\r\n productSlug?: string;\r\n /** Modo:\r\n * - `block` (default): renderiza fallback quando não permitido.\r\n * - `readonly`: sempre renderiza children mas injeta `readonly: true` no contexto. */\r\n mode?: EntitlementGateMode;\r\n /** Fallback UI quando `mode='block'` e check retorna `allowed=false`. */\r\n fallback?: React.ReactNode;\r\n /** Loading UI enquanto check resolve (Suspense-like). */\r\n loading?: React.ReactNode;\r\n children: React.ReactNode;\r\n}\r\n\r\ninterface EntitlementCheckResult {\r\n allowed: boolean;\r\n reason?: string;\r\n limit?: number;\r\n currentUsage?: number;\r\n behavior?: 'readonly' | null;\r\n}\r\n\r\n/**\r\n * Wrapper que gateia children por entitlement check.\r\n *\r\n * Quando `mode='readonly'` + check retorna `behavior='readonly'`:\r\n * - Children renderizam normalmente.\r\n * - Context injeta `{readonly: true}`.\r\n * - Componentes filhos chamam `useEntitlementContext()` pra desabilitar\r\n * escritas (botões, forms, inputs).\r\n *\r\n * Quando `mode='block'` + check retorna `allowed=false`:\r\n * - `fallback` é renderizado (ex: paywall, upsell modal).\r\n *\r\n * Decisão CEO §5 (overage): plataforma usa `readonly` sempre — produto SaaS\r\n * deve preferir `mode='readonly'` pra preservar engajamento (não hard-block).\r\n */\r\nexport function EntitlementGate({\r\n client,\r\n feature,\r\n productSlug,\r\n mode = 'block',\r\n fallback,\r\n loading,\r\n children,\r\n}: EntitlementGateProps): React.ReactElement {\r\n const [state, setState] = React.useState<{ status: 'loading' | 'ready'; result?: EntitlementCheckResult }>({\r\n status: 'loading',\r\n });\r\n\r\n // Resolve productSlug from prop or client.config\r\n const resolvedSlug =\r\n productSlug ?? (client.config as { productId?: string }).productId ?? '';\r\n\r\n // tenantId fallback: client.config.tenantId (default no createNeetruClient).\r\n // usage.check valida ambos productId + tenantId — sem isso, lança\r\n // validation_failed e o Gate fica trancado em allowed:false.\r\n const resolvedTenantId = (client.config as { tenantId?: string }).tenantId;\r\n\r\n React.useEffect(() => {\r\n let cancelled = false;\r\n const run = async () => {\r\n try {\r\n // Try usage.check first (returns full {allowed, reason, behavior, ...})\r\n // Falls back to entitlements.check (just boolean) if usage.check unavailable.\r\n let result: EntitlementCheckResult;\r\n const usage = (client as {\r\n usage?: {\r\n check: (\r\n resource: string,\r\n opts?: { productId?: string; tenantId?: string },\r\n ) => Promise<EntitlementCheckResult>;\r\n };\r\n }).usage;\r\n if (usage && typeof usage.check === 'function' && resolvedTenantId) {\r\n const res = await usage.check(feature, {\r\n productId: resolvedSlug,\r\n tenantId: resolvedTenantId,\r\n });\r\n result = {\r\n allowed: res.allowed === true,\r\n reason: res.reason,\r\n limit: res.limit,\r\n currentUsage: res.currentUsage,\r\n behavior: res.behavior,\r\n };\r\n } else {\r\n // Sem tenantId, cai pra entitlements.check (não exige tenant) em vez\r\n // de chamar usage.check e tomar validation_failed silencioso.\r\n const allowed = await client.entitlements.check(resolvedSlug, feature);\r\n result = { allowed };\r\n }\r\n if (!cancelled) setState({ status: 'ready', result });\r\n } catch (err) {\r\n // Fail open: erros de rede/timeout não bloqueiam o usuário com plano válido.\r\n // Bug corrigido: antes setava allowed:false (fail-closed) contradizendo o comentário.\r\n if (!cancelled) {\r\n setState({ status: 'ready', result: { allowed: true, reason: 'check_error_fallback' } });\r\n }\r\n if (typeof console !== 'undefined') console.warn('[EntitlementGate] check failed — fail-open', err);\r\n }\r\n };\r\n run();\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [client, feature, resolvedSlug, resolvedTenantId]);\r\n\r\n if (state.status === 'loading') {\r\n return React.createElement(React.Fragment, null, loading ?? null);\r\n }\r\n\r\n const result = state.result;\r\n const allowed = result?.allowed === true;\r\n const isReadonly = !allowed && (mode === 'readonly' || result?.behavior === 'readonly');\r\n\r\n if (!allowed && mode === 'block' && !isReadonly) {\r\n return React.createElement(React.Fragment, null, fallback ?? null);\r\n }\r\n\r\n return React.createElement(\r\n EntitlementContext.Provider,\r\n {\r\n value: {\r\n readonly: isReadonly,\r\n reason: result?.reason,\r\n limit: result?.limit,\r\n currentUsage: result?.currentUsage,\r\n },\r\n },\r\n children,\r\n );\r\n}\r\n\r\n// ════════════════════════════════════════════════════════════════════════════\r\n// SDK-2 — Hooks de dados de 1ª classe (compat com hooks caseiros por-produto)\r\n//\r\n// ⚠️ STATUS: 1ª classe, mas desenhados para CASAR com a superfície que os\r\n// produtos (gestovendas / pdvagiliza) escreveram à mão em cima do\r\n// firestore-compat. Substituem os hooks `useCollection`/`useDoc`/`useUser`\r\n// que cada produto reescrevia (~200-400 LOC por produto).\r\n//\r\n// Estes hooks aceitam **refs do `@neetru/sdk/firestore-compat`**\r\n// (`CollectionReference` / `Query` / `DocumentReference`) e devolvem o shape\r\n// `{ data, isLoading, error, isStale, lastUpdated }` que os produtos já\r\n// consomem. Internamente usam o realtime nativo do `client.db`\r\n// (`onSnapshot`) quando disponível, com fallback de polling visibility-aware.\r\n//\r\n// Diferença vs `@neetru/sdk/db/react` (`useDocument`/`useCollection` de lá):\r\n// - Lá: API offline-first, ref = `DbCollectionRef` nativo, retorno\r\n// `{ docs, loading, fromCache, stale }`.\r\n// - Aqui: API firestore-compat, ref = ref do firestore-compat, retorno\r\n// `{ data, isLoading, error, isStale, lastUpdated }` (id já embutido em\r\n// cada item; data nunca duplica o id internamente).\r\n// ════════════════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * Resultado de `useCollection` (subpath `@neetru/sdk/react`, API firestore-compat).\r\n *\r\n * Nome distinto de `UseCollectionResult` do subpath `@neetru/sdk/db/react`:\r\n * - `src/db/react.ts` → `{ docs, loading, fromCache, stale, hasPendingWrites }`\r\n * - `src/react.ts` → `{ data, isLoading, error, isStale, lastUpdated }` (este)\r\n *\r\n * Consumers que importam de ambos subpaths não terão clash de tipo.\r\n * Alias de retrocompat `UseCollectionResult` exportado abaixo.\r\n */\r\nexport interface FirestoreCompatCollectionResult<T> {\r\n /** Documentos (cada um com `id` embutido) ou `null` enquanto carrega/sem ref. */\r\n data: Array<T & { id: string }> | null;\r\n /** `true` enquanto o primeiro snapshot não chegou. */\r\n isLoading: boolean;\r\n /** Erro do último refresh (dados exibidos podem estar defasados). */\r\n error: Error | null;\r\n /** `true` quando um refresh falhou ou o snapshot veio do cache/offline. */\r\n isStale: boolean;\r\n /** epoch ms do último snapshot bem-sucedido, ou `null`. */\r\n lastUpdated: number | null;\r\n}\r\n\r\n/**\r\n * Alias de retrocompat — exportado para não quebrar produtos que importam\r\n * `UseCollectionResult` do subpath `@neetru/sdk/react`. Prefira\r\n * `FirestoreCompatCollectionResult` em código novo para evitar o clash de nome\r\n * com `UseCollectionResult` de `@neetru/sdk/db/react`.\r\n *\r\n * @deprecated Use `FirestoreCompatCollectionResult` em novo código.\r\n */\r\nexport type UseCollectionResult<T> = FirestoreCompatCollectionResult<T>;\r\n\r\n/** Resultado de `useDoc`. */\r\nexport interface UseDocResult<T> {\r\n data: (T & { id: string }) | null;\r\n isLoading: boolean;\r\n error: Error | null;\r\n isStale: boolean;\r\n lastUpdated: number | null;\r\n}\r\n\r\n/** Opções comuns dos hooks de dados. */\r\nexport interface UseDataOptions {\r\n /**\r\n * Intervalo de polling de fallback em ms (quando o transporte não oferece\r\n * realtime nativo). Default 5000. O polling pausa quando a aba está oculta.\r\n */\r\n intervalMs?: number;\r\n /**\r\n * Força polling mesmo quando o `onSnapshot` nativo está disponível. Útil para\r\n * transportes REST onde `onSnapshot` só entrega o snapshot inicial.\r\n * Default: `false` (usa realtime quando o transporte oferece).\r\n */\r\n poll?: boolean;\r\n}\r\n\r\nconst DEFAULT_INTERVAL_MS = 5000;\r\n\r\n/** `true` quando a aba está oculta (não dispara polling em background). */\r\nfunction isDocumentHidden(): boolean {\r\n return typeof document !== 'undefined' && document.hidden === true;\r\n}\r\n\r\n/**\r\n * Serializa uma fonte de coleção/query firestore-compat numa chave estável.\r\n * Garante que mudanças de VALOR (não de identidade) re-subscrevam, mas objetos\r\n * iguais não causem loop de efeito.\r\n */\r\nfunction serializeSource(\r\n source: CollectionReference<unknown> | Query<unknown> | null | undefined,\r\n): string | null {\r\n if (!source) return null;\r\n if (source.__kind === 'collection') {\r\n return `collection:${source.id}`;\r\n }\r\n const dbQuery = toDbQuery(source.constraints);\r\n return `query:${source.collection}:${JSON.stringify(dbQuery)}`;\r\n}\r\n\r\n/** Normaliza linhas de um snapshot do client.db em `{...data, id}` (id embutido). */\r\nfunction rowsFromList<T>(snap: DbListResult<Record<string, unknown>>): Array<T & { id: string }> {\r\n return snap.docs.map((d) => {\r\n const data = d.data as Record<string, unknown>;\r\n // Garante que o id externo prevaleça (sem duplicar dentro do objeto data).\r\n const { id: _omit, ...rest } = data;\r\n return { ...(rest as T), id: d.id };\r\n });\r\n}\r\n\r\nfunction rowFromGet<T>(\r\n snap: DbGetResult<Record<string, unknown>> | null,\r\n id: string,\r\n): (T & { id: string }) | null {\r\n const first = snap?.docs[0];\r\n if (!first) return null;\r\n const data = first.data as Record<string, unknown>;\r\n const { id: _omit, ...rest } = data;\r\n return { ...(rest as T), id };\r\n}\r\n\r\n/**\r\n * Hook de tempo real para uma coleção (ou subconjunto filtrado via `query`).\r\n *\r\n * Aceita uma `CollectionReference` ou `Query` do `@neetru/sdk/firestore-compat`.\r\n * Subscreve ao `onSnapshot` nativo do `client.db`; quando o transporte é REST\r\n * (sem realtime nativo), faz polling visibility-aware no `intervalMs`.\r\n *\r\n * ```tsx\r\n * import { collection, query, where } from '@neetru/sdk/firestore-compat';\r\n * import { useCollection } from '@neetru/sdk/react';\r\n *\r\n * const ref = useMemo(\r\n * () => query(collection(client.db, 'orders'), where('status', '==', 'open')),\r\n * [],\r\n * );\r\n * const { data, isLoading, error, isStale } = useCollection<Order>(ref);\r\n * ```\r\n *\r\n * Seguro em React 18/19 StrictMode.\r\n */\r\nexport function useCollection<T = Record<string, unknown>>(\r\n source: CollectionReference<T> | Query<T> | null | undefined,\r\n options?: UseDataOptions,\r\n): UseCollectionResult<T> {\r\n const intervalMs = options?.intervalMs ?? DEFAULT_INTERVAL_MS;\r\n const poll = options?.poll ?? false;\r\n const sourceKey = serializeSource(\r\n source as CollectionReference<unknown> | Query<unknown> | null | undefined,\r\n );\r\n\r\n const [state, setState] = React.useState<UseCollectionResult<T>>({\r\n data: null,\r\n isLoading: sourceKey !== null,\r\n error: null,\r\n isStale: false,\r\n lastUpdated: null,\r\n });\r\n\r\n const mountedRef = React.useRef(true);\r\n // Mantém a fonte mais recente sem re-disparar o efeito por identidade.\r\n const sourceRef = React.useRef(source);\r\n sourceRef.current = source;\r\n\r\n React.useEffect(() => {\r\n mountedRef.current = true;\r\n const current = sourceRef.current;\r\n\r\n if (!current || sourceKey === null) {\r\n setState({ data: null, isLoading: false, error: null, isStale: false, lastUpdated: null });\r\n return () => {\r\n mountedRef.current = false;\r\n };\r\n }\r\n\r\n setState((prev) => ({ ...prev, isLoading: prev.data === null }));\r\n\r\n const collectionName = current.__kind === 'query' ? current.collection : current.id;\r\n const dbQuery = current.__kind === 'query' ? toDbQuery(current.constraints) : undefined;\r\n const col = current.db.collection(collectionName);\r\n\r\n const applySnap = (snap: DbListResult<Record<string, unknown>>) => {\r\n if (!mountedRef.current) return;\r\n setState({\r\n data: rowsFromList<T>(snap),\r\n isLoading: false,\r\n error: null,\r\n isStale: snap.stale === true,\r\n lastUpdated: Date.now(),\r\n });\r\n };\r\n\r\n const applyError = (e: unknown) => {\r\n if (!mountedRef.current) return;\r\n setState((prev) => ({\r\n ...prev,\r\n // Mantém o último data bom — não limpa em erro de refresh.\r\n isLoading: false,\r\n error: e instanceof Error ? e : new Error(String(e)),\r\n isStale: true,\r\n }));\r\n };\r\n\r\n // Polling explícito (REST) ou realtime nativo.\r\n if (poll) {\r\n let cancelled = false;\r\n const fetchOnce = async () => {\r\n if (cancelled || isDocumentHidden()) return;\r\n try {\r\n const snap = (await col.list(dbQuery)) as DbListResult<Record<string, unknown>>;\r\n if (!cancelled) applySnap(snap);\r\n } catch (e) {\r\n if (!cancelled) applyError(e);\r\n }\r\n };\r\n void fetchOnce();\r\n const timer = setInterval(fetchOnce, intervalMs);\r\n return () => {\r\n cancelled = true;\r\n clearInterval(timer);\r\n mountedRef.current = false;\r\n };\r\n }\r\n\r\n let unsub: (() => void) | undefined;\r\n try {\r\n unsub = col.onSnapshot(dbQuery, applySnap);\r\n } catch (e) {\r\n applyError(e);\r\n }\r\n return () => {\r\n mountedRef.current = false;\r\n unsub?.();\r\n };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [sourceKey, intervalMs, poll]);\r\n\r\n return state;\r\n}\r\n\r\n/**\r\n * Hook de tempo real para um documento.\r\n *\r\n * Aceita uma `DocumentReference` do `@neetru/sdk/firestore-compat`.\r\n *\r\n * ```tsx\r\n * import { doc } from '@neetru/sdk/firestore-compat';\r\n * import { useDoc } from '@neetru/sdk/react';\r\n *\r\n * const ref = useMemo(() => doc(client.db, 'profiles', uid), [uid]);\r\n * const { data, isLoading } = useDoc<Profile>(ref);\r\n * ```\r\n *\r\n * Seguro em React 18/19 StrictMode.\r\n */\r\nexport function useDoc<T = Record<string, unknown>>(\r\n ref: DocumentReference<T> | null | undefined,\r\n options?: UseDataOptions,\r\n): UseDocResult<T> {\r\n const intervalMs = options?.intervalMs ?? DEFAULT_INTERVAL_MS;\r\n const poll = options?.poll ?? false;\r\n const refKey = ref && ref.id ? `${ref.collection}/${ref.id}` : null;\r\n\r\n const [state, setState] = React.useState<UseDocResult<T>>({\r\n data: null,\r\n isLoading: refKey !== null,\r\n error: null,\r\n isStale: false,\r\n lastUpdated: null,\r\n });\r\n\r\n const mountedRef = React.useRef(true);\r\n const refRef = React.useRef(ref);\r\n refRef.current = ref;\r\n\r\n React.useEffect(() => {\r\n mountedRef.current = true;\r\n const current = refRef.current;\r\n\r\n if (!current || refKey === null) {\r\n setState({ data: null, isLoading: false, error: null, isStale: false, lastUpdated: null });\r\n return () => {\r\n mountedRef.current = false;\r\n };\r\n }\r\n\r\n setState((prev) => ({ ...prev, isLoading: prev.data === null }));\r\n\r\n const docRef = current.db.collection(current.collection).doc(current.id);\r\n const id = current.id;\r\n\r\n const applySnap = (snap: DbGetResult<Record<string, unknown>> | null) => {\r\n if (!mountedRef.current) return;\r\n setState({\r\n data: rowFromGet<T>(snap, id),\r\n isLoading: false,\r\n error: null,\r\n isStale: snap?.stale === true,\r\n lastUpdated: Date.now(),\r\n });\r\n };\r\n\r\n const applyError = (e: unknown) => {\r\n if (!mountedRef.current) return;\r\n setState((prev) => ({\r\n ...prev,\r\n isLoading: false,\r\n error: e instanceof Error ? e : new Error(String(e)),\r\n isStale: true,\r\n }));\r\n };\r\n\r\n if (poll) {\r\n let cancelled = false;\r\n const fetchOnce = async () => {\r\n if (cancelled || isDocumentHidden()) return;\r\n try {\r\n const snap = (await docRef.get()) as DbGetResult<Record<string, unknown>> | null;\r\n if (!cancelled) applySnap(snap);\r\n } catch (e) {\r\n if (!cancelled) applyError(e);\r\n }\r\n };\r\n void fetchOnce();\r\n const timer = setInterval(fetchOnce, intervalMs);\r\n return () => {\r\n cancelled = true;\r\n clearInterval(timer);\r\n mountedRef.current = false;\r\n };\r\n }\r\n\r\n let unsub: (() => void) | undefined;\r\n try {\r\n unsub = docRef.onSnapshot(applySnap);\r\n } catch (e) {\r\n applyError(e);\r\n }\r\n return () => {\r\n mountedRef.current = false;\r\n unsub?.();\r\n };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [refKey, intervalMs, poll]);\r\n\r\n return state;\r\n}\r\n\r\n// ─── useUser ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Fonte de auth aceita por `useUser`: o `NeetruClient` inteiro (resolve\r\n * `client.auth`) ou o `AuthNamespace` direto.\r\n */\r\nexport type UseUserInput = NeetruClient | { auth: AuthNamespace } | AuthNamespace;\r\n\r\n/** Resultado de `useUser`. */\r\nexport interface UseUserResult {\r\n /** Usuário autenticado ou `null`. */\r\n user: NeetruUser | null;\r\n /** `true` enquanto o estado de auth inicial não foi resolvido. */\r\n isLoading: boolean;\r\n /** Erro na resolução de auth (raro — listener nunca deveria lançar). */\r\n error: Error | null;\r\n}\r\n\r\nfunction resolveAuth(input: UseUserInput): AuthNamespace {\r\n const maybe = input as { auth?: AuthNamespace };\r\n if (maybe.auth && typeof maybe.auth.onAuthStateChanged === 'function') {\r\n return maybe.auth;\r\n }\r\n return input as AuthNamespace;\r\n}\r\n\r\n/**\r\n * Hook de estado de autenticação.\r\n *\r\n * Subscreve a `client.auth.onAuthStateChanged` e devolve `{ user, isLoading,\r\n * error }`. Inclui um **timeout de seed** (default 8s): se o estado de auth não\r\n * resolver nesse prazo, `isLoading` cai para `false` com `user: null` — evita\r\n * spinners infinitos quando o provedor de auth nunca dispara o callback.\r\n *\r\n * ```tsx\r\n * import { useUser } from '@neetru/sdk/react';\r\n * const { user, isLoading } = useUser(client);\r\n * if (isLoading) return <Spinner />;\r\n * if (!user) return <SignInButton />;\r\n * return <Avatar user={user} />;\r\n * ```\r\n *\r\n * Aceita o `NeetruClient`, `{ auth }` ou o `AuthNamespace` direto.\r\n * Seguro em React 18/19 StrictMode.\r\n */\r\nexport function useUser(\r\n input: UseUserInput,\r\n options?: { timeoutMs?: number },\r\n): UseUserResult {\r\n const timeoutMs = options?.timeoutMs ?? 8000;\r\n const auth = resolveAuth(input);\r\n\r\n const [state, setState] = React.useState<UseUserResult>(() => {\r\n // Seed síncrono do estado atual (se o namespace já tem user em cache).\r\n let seeded: NeetruUser | null = null;\r\n try {\r\n seeded = auth.getUser();\r\n } catch {\r\n seeded = null;\r\n }\r\n return { user: seeded, isLoading: seeded === null, error: null };\r\n });\r\n\r\n const mountedRef = React.useRef(true);\r\n\r\n React.useEffect(() => {\r\n mountedRef.current = true;\r\n let settled = false;\r\n\r\n // Timeout de seed: se onAuthStateChanged nunca disparar, destrava o loading.\r\n const timer = setTimeout(() => {\r\n if (!mountedRef.current || settled) return;\r\n setState((prev) => (prev.isLoading ? { ...prev, isLoading: false } : prev));\r\n }, timeoutMs);\r\n\r\n let unsub: (() => void) | undefined;\r\n try {\r\n unsub = auth.onAuthStateChanged((user) => {\r\n if (!mountedRef.current) return;\r\n settled = true;\r\n setState({ user: user ?? null, isLoading: false, error: null });\r\n });\r\n } catch (e) {\r\n if (mountedRef.current) {\r\n setState({\r\n user: null,\r\n isLoading: false,\r\n error: e instanceof Error ? e : new Error(String(e)),\r\n });\r\n }\r\n }\r\n\r\n return () => {\r\n mountedRef.current = false;\r\n clearTimeout(timer);\r\n unsub?.();\r\n };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [auth, timeoutMs]);\r\n\r\n return state;\r\n}\r\n"]}
package/dist/react.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { B as NeetruClient, h as CheckoutStartResult, A as AuthNamespace, U as NeetruUser } from './types-BXvGHppn.cjs';
2
+ import { B as NeetruClient, h as CheckoutStartResult, A as AuthNamespace, U as NeetruUser } from './types-DDiVzgCT.cjs';
3
3
  import { CollectionReference, Query, DocumentReference } from './firestore-compat.cjs';
4
4
  import 'drizzle-orm/node-postgres';
5
5
  import './errors.cjs';
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { B as NeetruClient, h as CheckoutStartResult, A as AuthNamespace, U as NeetruUser } from './types-CQVak2a3.js';
2
+ import { B as NeetruClient, h as CheckoutStartResult, A as AuthNamespace, U as NeetruUser } from './types-HWDOUmlC.js';
3
3
  import { CollectionReference, Query, DocumentReference } from './firestore-compat.js';
4
4
  import 'drizzle-orm/node-postgres';
5
5
  import './errors.js';