@neetru/sdk 1.2.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +284 -244
- package/README.md +194 -194
- package/dist/auth.cjs +3740 -345
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +5 -1
- package/dist/auth.d.ts +5 -1
- package/dist/auth.mjs +3740 -345
- package/dist/auth.mjs.map +1 -1
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +5 -1
- package/dist/catalog.d.ts +5 -1
- package/dist/catalog.mjs.map +1 -1
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.d.cts +5 -1
- package/dist/checkout.d.ts +5 -1
- package/dist/checkout.mjs.map +1 -1
- package/dist/collection-ref-BBvTTXoG.d.cts +423 -0
- package/dist/collection-ref-BBvTTXoG.d.ts +423 -0
- package/dist/db-react.cjs +136 -0
- package/dist/db-react.cjs.map +1 -0
- package/dist/db-react.d.cts +99 -0
- package/dist/db-react.d.ts +99 -0
- package/dist/db-react.mjs +112 -0
- package/dist/db-react.mjs.map +1 -0
- package/dist/db.cjs +3599 -131
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +5 -8
- package/dist/db.d.ts +5 -8
- package/dist/db.mjs +3596 -131
- package/dist/db.mjs.map +1 -1
- package/dist/entitlements.cjs.map +1 -1
- package/dist/entitlements.d.cts +5 -1
- package/dist/entitlements.d.ts +5 -1
- package/dist/entitlements.mjs.map +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.mjs.map +1 -1
- package/dist/index.cjs +3957 -342
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -6
- package/dist/index.d.ts +13 -6
- package/dist/index.mjs +3877 -263
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.cjs +183 -7
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.cts +18 -5
- package/dist/mocks.d.ts +18 -5
- package/dist/mocks.mjs +183 -7
- package/dist/mocks.mjs.map +1 -1
- package/dist/notifications.cjs.map +1 -1
- package/dist/notifications.d.cts +5 -1
- package/dist/notifications.d.ts +5 -1
- package/dist/notifications.mjs.map +1 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +5 -1
- package/dist/react.d.ts +5 -1
- package/dist/react.mjs.map +1 -1
- package/dist/support.cjs.map +1 -1
- package/dist/support.d.cts +5 -1
- package/dist/support.d.ts +5 -1
- package/dist/support.mjs.map +1 -1
- package/dist/telemetry.cjs.map +1 -1
- package/dist/telemetry.d.cts +5 -1
- package/dist/telemetry.d.ts +5 -1
- package/dist/telemetry.mjs.map +1 -1
- package/dist/types-B1jylbMC.d.ts +1364 -0
- package/dist/types-Kmt4y1FQ.d.cts +1364 -0
- package/dist/usage.cjs.map +1 -1
- package/dist/usage.d.cts +5 -1
- package/dist/usage.d.ts +5 -1
- package/dist/usage.mjs.map +1 -1
- package/dist/webhooks.cjs.map +1 -1
- package/dist/webhooks.d.cts +5 -1
- package/dist/webhooks.d.ts +5 -1
- package/dist/webhooks.mjs.map +1 -1
- package/package.json +133 -111
- package/dist/types-CQAfwqUS.d.cts +0 -654
- package/dist/types-CQAfwqUS.d.ts +0 -654
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/types.ts","../src/http.ts","../src/catalog.ts","../src/entitlements.ts","../src/telemetry.ts","../src/usage.ts","../src/support.ts","../src/db.ts","../src/checkout.ts","../src/webhooks.ts","../src/notifications.ts","../src/mocks.ts","../src/auth.ts","../src/index.ts"],"names":["err","message","VALID_SEVERITIES","validateInput"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Erros tipados do SDK.\n *\n * Todo erro lançado pelo SDK estende `NeetruError` — caller pode discriminar\n * por `.code` (string estável) sem parsing de message.\n */\n\n/** Códigos de erro estáveis do SDK. Adicionar aqui requer minor bump. */\nexport type NeetruErrorCode =\n | 'invalid_config'\n | 'missing_api_key'\n | 'unauthorized'\n | 'forbidden'\n | 'not_found'\n | 'rate_limited'\n | 'validation_failed'\n | 'network_error'\n | 'invalid_response'\n | 'server_error'\n | 'unknown';\n\n/**\n * Erro tipado padrão do SDK. Sempre lançado em vez de Error genérico.\n *\n * @example\n * ```ts\n * try { await client.catalog.list(); }\n * catch (e) {\n * if (e instanceof NeetruError && e.code === 'rate_limited') retry();\n * }\n * ```\n */\nexport class NeetruError extends Error {\n public readonly code: NeetruErrorCode | string;\n public readonly status?: number;\n public readonly requestId?: string;\n\n constructor(\n code: NeetruErrorCode | string,\n message: string,\n status?: number,\n requestId?: string,\n ) {\n super(message);\n this.name = 'NeetruError';\n this.code = code;\n this.status = status;\n this.requestId = requestId;\n // Preserva o prototype chain ao herdar de Error (downlevel quirk de TS).\n Object.setPrototypeOf(this, NeetruError.prototype);\n }\n}\n","/**\n * Tipos públicos do SDK Neetru.\n *\n * Vendor-neutral: nada aqui referencia `firebase/*`, `stripe`, ou qualquer\n * provider interno. Caller só vê superfície neutra (Product, Entitlement, ...).\n */\n\n/** Default base URL pra API pública Neetru. */\nexport const DEFAULT_BASE_URL = 'https://api.neetru.com';\n\n/**\n * Configuração passada pra `createNeetruClient`.\n */\nexport interface NeetruClientConfig {\n /**\n * Bearer token Neetru (formato `nrt_<keyId>_<secret>`). Opcional —\n * se ausente, o SDK tenta `process.env.NEETRU_API_KEY` em Node.\n *\n * Endpoints públicos (catalog) funcionam sem apiKey. Endpoints autenticados\n * (entitlements, telemetry) lançam `missing_api_key` se ausente.\n */\n apiKey?: string;\n /**\n * URL base da API Neetru. Default: `https://api.neetru.com`.\n * Útil em testes apontando pra staging ou mock server.\n */\n baseUrl?: string;\n /**\n * Implementação de fetch customizada. Default: `globalThis.fetch`.\n * Necessário em runtimes que não exponham fetch global por default.\n */\n fetch?: typeof globalThis.fetch;\n /**\n * Modo de runtime. `dev` ativa mocks (auth retorna user fixture, usage só\n * loga, support retorna lista fake). `workspace` e `prod` chamam HTTP real.\n *\n * Default: lê `process.env.NEETRU_ENV` (Node) ou `globalThis.NEETRU_ENV`\n * (browser); fallback `prod`.\n */\n env?: 'dev' | 'workspace' | 'prod';\n /**\n * Override de mocks — útil em tests do consumer pra injetar fixtures\n * determinísticos (sem depender de NEETRU_ENV=dev).\n */\n mocks?: {\n auth?: AuthNamespace;\n usage?: UsageNamespace;\n support?: SupportNamespace;\n entitlements?: NeetruClient['entitlements'];\n db?: DbNamespace;\n webhooks?: import('./webhooks').WebhooksNamespace;\n notifications?: import('./notifications').NotificationsNamespace;\n };\n /**\n * v0.3 — productId default usado por `usage.report()` / `usage.check()` /\n * `db.collection()` quando não passado explicitamente nas options.\n */\n productId?: string;\n /**\n * v0.3 — tenantId default usado por `usage.report()` / `usage.check()` /\n * `db.collection()` quando não passado explicitamente nas options.\n */\n tenantId?: string;\n}\n\n/**\n * Status do produto no catálogo público.\n */\nexport type ProductStatus = 'live' | 'soon' | 'beta';\n\n/**\n * Produto SaaS publicado pelo Neetru Core.\n *\n * Schema neutro — alinhado com `public_products/{slug}` no backend mas\n * nunca expõe campos internos (Firestore Timestamps, draft state, etc).\n */\nexport interface Product {\n /** Identificador estável do produto, ex: `neetru-pulse`. */\n slug: string;\n /** Nome de exibição, ex: `Neetru Pulse`. */\n name: string;\n /** Subtítulo curto, ex: `Gestão de operações`. */\n tagline?: string;\n /** Descrição longa em prosa. */\n description?: string;\n /** Status público do produto. */\n status?: ProductStatus;\n /** Hint de ícone (catálogo de keys interno do Core). */\n iconKey?: string;\n /** Link override do CTA principal (default: página do produto). */\n ctaHref?: string;\n /** Label override do CTA. */\n ctaLabel?: string;\n /** Lista opcional de planos cobrados. Pode ser preenchida v0.2+. */\n plans?: ProductPlan[];\n}\n\n/** Plano cobrado de um produto (placeholder v0.1 — schema final v0.2). */\nexport interface ProductPlan {\n id: string;\n name: string;\n /** Preço mensal em centavos (BRL). Pode ser undefined em planos custom. */\n amountCents?: number;\n features?: string[];\n}\n\n/**\n * Resposta do `client.catalog.list()`.\n */\nexport interface CatalogListResponse {\n products: Product[];\n fetchedAt: string;\n}\n\n/**\n * Resposta do `client.entitlements.check(productSlug, feature)`.\n *\n * `allowed` é o sinal forte; `reason` ajuda a debugar (não exibir pro user\n * final).\n */\nexport interface EntitlementCheck {\n allowed: boolean;\n productSlug: string;\n feature: string;\n /** Reason code estável: `granted` | `not_subscribed` | `feature_not_in_plan` | `expired`. */\n reason?: string;\n}\n\n/**\n * Payload pra `client.telemetry.event()`.\n */\nexport interface TelemetryEventInput {\n /** Nome do evento, ex: `dashboard_opened`, `report_exported`. */\n name: string;\n /** Atributos adicionais (chave → valor primitivo). */\n properties?: Record<string, string | number | boolean | null>;\n /** Timestamp ISO opcional; default = server time. */\n timestamp?: string;\n}\n\n/**\n * Confirmação de aceitação do evento de telemetria.\n */\nexport interface TelemetryEventAck {\n ok: true;\n /** ID gerado pelo backend pra evento (`usage_events/{id}`). */\n eventId: string;\n}\n\n// ─── Sprint 6 — Telemetry log per-product ──────────────────────────────────\n\nexport type TelemetryLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\nexport interface TelemetryLogInput {\n level: TelemetryLogLevel;\n message: string;\n metadata?: Record<string, unknown>;\n /** Override correlationId (default: lê dos headers/env automaticamente). */\n correlationId?: string;\n /** Slug do produto referenciado. Backend infere do escopo do token se ausente. */\n productSlug?: string;\n}\n\nexport interface TelemetryLogAck {\n ok: true;\n /** ID do log gravado (`logs/{productId}/{yyyymmdd}/{logId}`) — opcional em mocks. */\n logId?: string;\n /** Indicador de modo (mock vs http). */\n mode: 'mock' | 'http';\n}\n\n/**\n * Handle imutável retornado por `createNeetruClient`. Carrega namespaces\n * `auth`, `catalog`, `entitlements`, `telemetry`, `usage`, `support`.\n *\n * Cada namespace é exposto como objeto chamável — espelha API Firebase\n * (`auth`, `firestore`) ou Stripe (`paymentIntents`, `customers`).\n */\nexport interface NeetruClient {\n /** Configuração resolvida (apiKey, baseUrl, fetch). Read-only. */\n readonly config: ResolvedConfig;\n /** Namespace auth (v0.2 — OIDC + mocks dev). */\n readonly auth: AuthNamespace;\n /** Namespace catálogo público de produtos. */\n readonly catalog: {\n /** Lista produtos publicados. */\n list(opts?: CatalogListOptions): Promise<CatalogListResponse>;\n /** Busca produto único por slug. */\n get(slug: string): Promise<Product>;\n };\n /** Namespace entitlements (v1.2: cache LRU 60s TTL). */\n readonly entitlements: {\n /**\n * Verifica se o portador da apiKey pode usar `feature` do produto `slug`.\n * Cacheado 60s. `{ cacheBust: true }` força ida ao servidor.\n */\n check(\n productSlug: string,\n feature: string,\n opts?: { cacheBust?: boolean },\n ): Promise<boolean>;\n /** Variante que retorna o objeto completo com `reason`. */\n checkDetailed(\n productSlug: string,\n feature: string,\n opts?: { cacheBust?: boolean },\n ): Promise<EntitlementCheck>;\n };\n /** Namespace telemetria (v1.2: track fire-and-forget + flush). */\n readonly telemetry: {\n /** Persiste um evento single-shot. await retorna { ok, eventId }. */\n event(input: TelemetryEventInput): Promise<TelemetryEventAck>;\n /** Fire-and-forget: enqueue + flush 500ms debounce. Sem retorno. */\n track(input: TelemetryEventInput): void;\n /** Força flush da queue do track() (chamar antes de unload). */\n flush(): Promise<void>;\n /**\n * Registra um log estruturado per-product (Sprint 6).\n *\n * - Em `NEETRU_ENV=dev`: apenas console.{level} (sem network).\n * - Em `workspace`/`prod`: POST `/api/sdk/v1/telemetry/log` com Bearer + correlationId.\n */\n log(input: TelemetryLogInput): Promise<TelemetryLogAck>;\n };\n /** Namespace usage (v0.2 — track + quota; v0.3 — report + check). */\n readonly usage: UsageNamespace;\n /** Namespace support (v0.2 — tickets). */\n readonly support: SupportNamespace;\n /** Namespace db (v0.3 — coleções tenant-scoped). */\n readonly db: DbNamespace;\n /** Namespace checkout (v1.1 — start/get/cancel intent + auto-redirect). */\n readonly checkout: import('./checkout').CheckoutNamespace;\n /** Namespace webhooks (v1.2 — register/list/unregister/test). */\n readonly webhooks: import('./webhooks').WebhooksNamespace;\n /** Namespace notifications (v1.2 — send/list/markRead/dismiss). */\n readonly notifications: import('./notifications').NotificationsNamespace;\n}\n\n// ─── v0.2 — Auth namespace ──────────────────────────────────────────────────\n\n/**\n * User retornado pelo OIDC ID token. Schema neutro — não vaza Firebase\n * decoded token shape. Subset estável do RFC 7519 + custom claims Neetru.\n */\nexport interface NeetruUser {\n /** Subject — uid estável. */\n uid: string;\n email: string;\n emailVerified?: boolean;\n displayName?: string;\n photoURL?: string;\n /** Custom claim Neetru — true quando staff. */\n isStaff?: boolean;\n /** Custom claim Neetru — true quando customer enrolled. */\n isCustomer?: boolean;\n /** Tenant assigned (multi-tenant deployments). */\n tenantId?: string;\n /** Outros claims OIDC (aud, iss, iat, exp). */\n [extra: string]: unknown;\n}\n\nexport interface SignInOptions {\n /** OIDC redirect_uri override. Default = window.location origin. */\n redirectUri?: string;\n /** OIDC scope. Default `openid profile email`. */\n scope?: string;\n /** Onde mandar após login completo. Default = window.location.href. */\n postLoginRedirect?: string;\n}\n\nexport type AuthStateListener = (user: NeetruUser | null) => void;\n\nexport interface AuthNamespace {\n /**\n * Inicia fluxo de login OIDC. Em dev (`NEETRU_ENV=dev`) retorna mock user\n * direto sem redirect. Em prod redireciona pro authorize endpoint.\n */\n signIn(options?: SignInOptions): Promise<NeetruUser | void>;\n /** Limpa session local + revoga refresh token no servidor. */\n signOut(): Promise<void>;\n /** Retorna o user atual (do id_token cached) ou `null` se não logado. */\n getUser(): NeetruUser | null;\n /**\n * Subscreve a mudanças de estado de auth. Listener é invocado imediatamente\n * com user atual. Retorna função de unsubscribe.\n */\n onAuthStateChanged(listener: AuthStateListener): () => void;\n}\n\n// ─── v0.2 — Usage namespace ─────────────────────────────────────────────────\n\nexport interface UsageEventInput {\n /** Nome do evento, ex: `report_generated`, `api_call`. */\n event: string;\n /** Atributos do evento. Valores primitivos serializáveis. */\n properties?: Record<string, string | number | boolean | null>;\n /** Quantidade — default 1 (1 evento). Útil pra batch. */\n quantity?: number;\n}\n\nexport interface UsageQuota {\n metric: string;\n /** Quantidade já consumida no período. */\n used: number;\n /** Limite total. -1 = unlimited. */\n limit: number;\n /** ISO timestamp do reset (próximo período). */\n resetsAt?: string;\n /** Plano que define o limite. */\n plan?: string;\n}\n\nexport interface UsageNamespace {\n /** Persiste um evento de uso. Mock em dev, POST `/sdk/v1/usage/record` em prod. */\n track(event: string, props?: UsageEventInput['properties']): Promise<{ ok: true }>;\n /** Lê quota atual de uma métrica. Mock em dev, GET `/sdk/v1/usage/quota` em prod. */\n getQuota(metric: string): Promise<UsageQuota>;\n /**\n * v0.3 — Reporta consumo de um resource metered (POST /sdk/v1/usage/record\n * com `{productId, tenantId, resource, qty}`). Em dev acumula no mock.\n *\n * Diferente de `track()`: usa o endpoint canônico Sprint 7 que incrementa\n * `usage_counters/{tenantId}_{productId}_{resource}_{yyyymm}` atomicamente.\n *\n * `productId`/`tenantId` são lidos do contexto resolvido do client se\n * ausentes nas options.\n */\n report(\n resource: string,\n qty?: number,\n options?: { productId?: string; tenantId?: string },\n ): Promise<{\n ok: true;\n counterId?: string;\n value?: number;\n limit?: number;\n remaining?: number;\n status?: string;\n }>;\n /**\n * v0.3 — Verifica entitlement de um resource/feature. Wrapper em\n * GET /sdk/v1/entitlements. Em dev consulta MockEntitlements + MockUsage.\n */\n check(\n resource: string,\n options?: { productId?: string; tenantId?: string },\n ): Promise<{\n allowed: boolean;\n reason?: string;\n remaining?: number;\n limit?: number;\n planId?: string | null;\n planFeatures?: string[];\n }>;\n}\n\n// ─── v0.3 — Datastore namespace ────────────────────────────────────────────\n\n/**\n * Namespace `db` (v0.3) — wrapper minimalista para CRUD em coleções tenant-scoped\n * via Core REST. Em dev retorna fixtures in-memory por collection.\n *\n * O Core injeta automaticamente o tenantId no path do Firestore:\n * `tenant_{tid}_{name}/{docId}`.\n */\n/** Filtro `where` simples — alinhado com endpoint REST `field:op:value`. */\nexport interface DbWhereFilter {\n field: string;\n op: '==' | '!=' | '<' | '<=' | '>' | '>=' | 'in';\n value: string | number | boolean | null | Array<string | number | boolean>;\n}\n\nexport interface DbListOptions {\n limit?: number;\n /** Lista de filtros — máximo 5 (alinhado ao backend). */\n where?: DbWhereFilter[];\n}\n\nexport interface DbCollectionRef {\n /** Lista documentos com filtros opcionais. */\n list<T = Record<string, unknown>>(opts?: DbListOptions): Promise<T[]>;\n /** Lê um documento por id. Retorna `null` se não existe. */\n get<T = Record<string, unknown>>(id: string): Promise<T | null>;\n /** Cria/upsert um documento com id explícito. */\n set(id: string, data: Record<string, unknown>): Promise<{ ok: true }>;\n /**\n * v0.3.1 — Adiciona doc com id auto-gerado pelo backend. Retorna `{id}` do\n * doc criado. Diferente de `set(id, data)` que requer caller fornecer id.\n */\n add(data: Record<string, unknown>): Promise<{ ok: true; id: string }>;\n /** Atualiza doc com merge — só campos passados em `data`. */\n update(id: string, data: Record<string, unknown>): Promise<{ ok: true }>;\n /** Deleta um documento. */\n remove(id: string): Promise<{ ok: true }>;\n}\n\nexport interface DbNamespace {\n collection(name: string): DbCollectionRef;\n}\n\n// ─── v0.2 — Support namespace ───────────────────────────────────────────────\n\nexport type SupportSeverity = 'low' | 'normal' | 'high' | 'urgent';\nexport type SupportStatus = 'open' | 'pending' | 'resolved' | 'closed';\n\nexport interface SupportTicket {\n id: string;\n subject: string;\n message: string;\n severity: SupportSeverity;\n status: SupportStatus;\n createdAt: string;\n updatedAt?: string;\n /** Slug do produto referenciado. */\n productSlug?: string;\n}\n\nexport interface CreateTicketInput {\n subject: string;\n message: string;\n severity?: SupportSeverity;\n productSlug?: string;\n}\n\nexport interface SupportNamespace {\n /** Cria um novo ticket. Mock em dev, POST `/api/v1/products/{slug}/tickets` em prod. */\n createTicket(input: CreateTicketInput): Promise<SupportTicket>;\n /** Lista meus tickets abertos. */\n listMyTickets(): Promise<SupportTicket[]>;\n}\n\n// ─── v0.2 — Env detection ───────────────────────────────────────────────────\n\n/**\n * Modo do SDK. `dev` ativa mocks automáticos (úteis pra testes e\n * desenvolvimento sem precisar de backend rodando).\n */\nexport type NeetruEnv = 'dev' | 'workspace' | 'prod';\n\n/**\n * Configuração resolvida (defaults aplicados, fetch garantido).\n */\nexport interface ResolvedConfig {\n readonly apiKey?: string;\n readonly baseUrl: string;\n readonly fetch: typeof globalThis.fetch;\n /** Resolved env — `dev` | `workspace` | `prod`. Default `prod`. */\n readonly env: NeetruEnv;\n /** Default productId (v0.3). */\n readonly productId?: string;\n /** Default tenantId (v0.3). */\n readonly tenantId?: string;\n}\n\n/** Opções pra `catalog.list()`. */\nexport interface CatalogListOptions {\n /** Inclui rascunhos (apenas com Bearer staff). Default false. */\n includeDrafts?: boolean;\n}\n","/**\n * HTTP transport interno do SDK.\n *\n * Responsabilidades:\n * - Construir URL absoluta a partir de `baseUrl` + path\n * - Injetar Bearer token quando `requireAuth=true`\n * - Mapear status HTTP → `NeetruError` com `code` estável\n * - Parse defensivo de JSON (não lança em body vazio em 204)\n * - Retry/backoff exponencial em `rate_limited` (429), `server_error` (5xx)\n * e `network_error` (timeout/falha de rede). Honra `Retry-After` quando\n * presente. Default 2 retries (3 tentativas no total). Caller opta-out\n * com `retries: 0`.\n */\nimport { NeetruError, type NeetruErrorCode } from './errors';\nimport type { ResolvedConfig } from './types';\n\n/** Opções da request HTTP. */\nexport interface HttpRequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n /** Path relativo (ex: `/api/v1/cli/catalog`). Concatenado a `baseUrl`. */\n path: string;\n /** Query string params (chave → valor primitivo). Valores `undefined` ignorados. */\n query?: Record<string, string | number | boolean | undefined>;\n /** Body JSON-serializável. Ignorado em GET/DELETE. */\n body?: unknown;\n /**\n * Se true, injeta `Authorization: Bearer <apiKey>`. Lança `missing_api_key`\n * se config.apiKey ausente. Default false.\n */\n requireAuth?: boolean;\n /** Cabeçalhos extras. */\n headers?: Record<string, string>;\n /**\n * Número de retries em códigos transientes (`rate_limited`, `server_error`,\n * `network_error`). Default 2 (= 3 tentativas total). Caller passa `0` pra\n * desativar (útil em operações não-idempotentes específicas).\n */\n retries?: number;\n}\n\nconst DEFAULT_RETRIES = 2;\nconst RETRYABLE_CODES = new Set<NeetruErrorCode>([\n 'rate_limited',\n 'server_error',\n 'network_error',\n]);\n\n/** Backoff exponencial com jitter ±20%. attempt: 0=primeira, 1=primeiro retry, ... */\nfunction backoffMs(attempt: number): number {\n const base = 200 * Math.pow(4, attempt); // 200ms, 800ms, 3.2s, ...\n const jitter = base * 0.2 * (Math.random() * 2 - 1);\n return Math.max(50, Math.round(base + jitter));\n}\n\n/**\n * Honra `Retry-After` header (segundos ou HTTP-date). Retorna ms ou null se\n * inválido. RFC 9110 §10.2.3.\n */\nfunction parseRetryAfter(value: string | null): number | null {\n if (!value) return null;\n const secs = Number(value);\n if (Number.isFinite(secs) && secs >= 0) return Math.round(secs * 1000);\n const dateMs = Date.parse(value);\n if (Number.isFinite(dateMs)) {\n const delta = dateMs - Date.now();\n if (delta > 0) return delta;\n }\n return null;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Mapeamento status → code estável do NeetruError. */\nfunction statusToCode(status: number): NeetruErrorCode {\n if (status === 401) return 'unauthorized';\n if (status === 403) return 'forbidden';\n if (status === 404) return 'not_found';\n if (status === 422 || status === 400) return 'validation_failed';\n if (status === 429) return 'rate_limited';\n if (status >= 500) return 'server_error';\n return 'unknown';\n}\n\nfunction buildUrl(baseUrl: string, path: string, query?: HttpRequestOptions['query']): string {\n // Trim trailing slash em base e leading em path pra evitar `//`.\n const base = baseUrl.replace(/\\/+$/, '');\n const p = path.startsWith('/') ? path : `/${path}`;\n const url = new URL(`${base}${p}`);\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n if (v === undefined) continue;\n url.searchParams.set(k, String(v));\n }\n }\n return url.toString();\n}\n\n/** Parse JSON defensivo — retorna `undefined` em body vazio. */\nasync function safeJson(res: Response): Promise<unknown> {\n const text = await res.text();\n if (!text) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Executa request HTTP. Em sucesso retorna body parseado; em erro lança\n * `NeetruError` com `code` derivado do status. Aplica retry/backoff\n * automático em códigos transientes (rate_limited/server_error/network_error)\n * conforme `opts.retries` (default 2 = 3 tentativas).\n */\nexport async function httpRequest<T>(\n config: ResolvedConfig,\n opts: HttpRequestOptions,\n): Promise<T> {\n const method = opts.method ?? 'GET';\n const url = buildUrl(config.baseUrl, opts.path, opts.query);\n const maxRetries = opts.retries ?? DEFAULT_RETRIES;\n\n const headers: Record<string, string> = {\n accept: 'application/json',\n ...opts.headers,\n };\n\n if (opts.requireAuth) {\n if (!config.apiKey) {\n throw new NeetruError(\n 'missing_api_key',\n 'This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var.',\n );\n }\n headers.authorization = `Bearer ${config.apiKey}`;\n }\n\n // Body só é serializado uma vez — reusado entre tentativas.\n const bodyString =\n opts.body !== undefined && method !== 'GET' && method !== 'DELETE'\n ? JSON.stringify(opts.body)\n : undefined;\n if (bodyString !== undefined) {\n headers['content-type'] = 'application/json';\n }\n\n let lastError: NeetruError | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const init: RequestInit = { method, headers };\n if (bodyString !== undefined) init.body = bodyString;\n // BUG-020 fix (2026-05-13): timeout default 30s. AbortSignal.timeout\n // requer Node 18+ ou browsers recentes.\n init.signal = AbortSignal.timeout(30_000);\n\n let res: Response;\n try {\n res = await config.fetch(url, init);\n } catch (err) {\n const message =\n err instanceof DOMException && err.name === 'TimeoutError'\n ? 'Network error: timeout after 30s'\n : `Network error: ${err instanceof Error ? err.message : 'fetch failed'}`;\n lastError = new NeetruError('network_error', message);\n if (attempt < maxRetries) {\n await sleep(backoffMs(attempt));\n continue;\n }\n throw lastError;\n }\n\n const requestId =\n res.headers.get('x-request-id') ?? res.headers.get('x-correlation-id') ?? undefined;\n\n if (res.ok) {\n const parsed = await safeJson(res);\n return parsed as T;\n }\n\n const body = (await safeJson(res)) as\n | { error?: { code?: string; message?: string } | string }\n | undefined;\n let code: string = statusToCode(res.status);\n let message = `HTTP ${res.status}`;\n if (body && typeof body === 'object' && 'error' in body) {\n const errField = body.error;\n if (typeof errField === 'string') {\n message = errField;\n } else if (errField && typeof errField === 'object') {\n if (typeof errField.code === 'string') code = errField.code;\n if (typeof errField.message === 'string') message = errField.message;\n }\n }\n const err = new NeetruError(code, message, res.status, requestId);\n lastError = err;\n\n const isRetryable = RETRYABLE_CODES.has(code as NeetruErrorCode);\n if (isRetryable && attempt < maxRetries) {\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n const delay = retryAfter ?? backoffMs(attempt);\n await sleep(delay);\n continue;\n }\n throw err;\n }\n\n // Unreachable — loop sempre retorna ou lança. Safety net.\n throw lastError ?? new NeetruError('unknown', 'unexpected httpRequest exit');\n}\n","/**\n * Catálogo público de produtos SaaS Neetru.\n *\n * Endpoints consumidos (v1.2+):\n * - `GET /api/sdk/v1/catalog` — listagem pública (sem auth)\n * - `GET /api/sdk/v1/catalog/{slug}` — produto único (sem auth)\n *\n * v1.1 e anteriores usavam `/api/v1/cli/catalog` (staff CLI), o que forçava\n * SDK consumers a manter Bearer staff-only. v1.2 separa: SDK consome o\n * endpoint público (`published === true`), staff continua usando CLI quando\n * precisa de rascunho.\n *\n * Read-only. Publicação de produto continua via CLI `neetru publish`.\n */\nimport { NeetruError } from './errors';\nimport { httpRequest } from './http';\nimport type {\n CatalogListOptions,\n CatalogListResponse,\n Product,\n ResolvedConfig,\n} from './types';\n\ninterface RawCatalogListResponse {\n ok?: boolean;\n count?: number;\n products?: unknown[];\n fetchedAt?: string;\n}\n\ninterface RawCatalogGetResponse {\n ok?: boolean;\n product?: unknown;\n}\n\nfunction toProduct(raw: unknown): Product {\n if (!raw || typeof raw !== 'object') {\n throw new NeetruError('invalid_response', 'Catalog response item is not an object');\n }\n const r = raw as Record<string, unknown>;\n if (typeof r.slug !== 'string' || !r.slug) {\n throw new NeetruError('invalid_response', 'Catalog product missing slug');\n }\n if (typeof r.name !== 'string' || !r.name) {\n throw new NeetruError('invalid_response', 'Catalog product missing name');\n }\n const product: Product = {\n slug: r.slug,\n name: r.name,\n };\n if (typeof r.tagline === 'string') product.tagline = r.tagline;\n if (typeof r.description === 'string') product.description = r.description;\n if (r.status === 'live' || r.status === 'soon' || r.status === 'beta') {\n product.status = r.status;\n }\n if (typeof r.iconKey === 'string') product.iconKey = r.iconKey;\n if (typeof r.ctaHref === 'string') product.ctaHref = r.ctaHref;\n if (typeof r.ctaLabel === 'string') product.ctaLabel = r.ctaLabel;\n // plans é placeholder v0.2 — preservar se backend mandar\n if (Array.isArray(r.plans)) {\n product.plans = r.plans.filter(\n (p): p is { id: string; name: string } =>\n typeof p === 'object' &&\n p !== null &&\n typeof (p as Record<string, unknown>).id === 'string' &&\n typeof (p as Record<string, unknown>).name === 'string',\n ) as Product['plans'];\n }\n return product;\n}\n\nexport function createCatalogNamespace(config: ResolvedConfig) {\n return {\n /**\n * Lista produtos publicados. Por default só `published=true`; staff\n * pode passar `includeDrafts: true` (requer Bearer com role admin/operator).\n */\n async list(_opts: CatalogListOptions = {}): Promise<CatalogListResponse> {\n // SDK só lê produtos publicados. `includeDrafts` legado é ignorado:\n // rascunhos só via CLI staff (`/api/v1/cli/catalog?drafts=true`).\n const raw = await httpRequest<RawCatalogListResponse>(config, {\n method: 'GET',\n path: '/api/sdk/v1/catalog',\n });\n\n if (!raw || !Array.isArray(raw.products)) {\n throw new NeetruError(\n 'invalid_response',\n 'Catalog list response missing products array',\n );\n }\n\n return {\n products: raw.products.map(toProduct),\n fetchedAt: typeof raw.fetchedAt === 'string'\n ? raw.fetchedAt\n : new Date().toISOString(),\n };\n },\n\n /**\n * Busca produto único por slug.\n *\n * @throws {NeetruError} `not_found` se slug inexistente ou não publicado.\n */\n async get(slug: string): Promise<Product> {\n if (!slug || typeof slug !== 'string') {\n throw new NeetruError('validation_failed', 'slug is required');\n }\n const raw = await httpRequest<RawCatalogGetResponse>(config, {\n method: 'GET',\n path: `/api/sdk/v1/catalog/${encodeURIComponent(slug)}`,\n });\n\n if (!raw || !raw.product) {\n throw new NeetruError(\n 'invalid_response',\n 'Catalog get response missing product',\n );\n }\n return toProduct(raw.product);\n },\n };\n}\n","/**\n * Entitlements — verifica se o portador da apiKey pode usar feature X\n * do produto Y.\n *\n * Endpoint: `GET /api/v1/sdk/entitlements/check?slug=X&feature=Y`\n * Schema Firestore consultado pelo backend:\n * `entitlements/{userId}/products/{slug}` → `{ features: string[], plan, expiresAt }`\n *\n * v1.2 introduz cache LRU em memória (default 60s TTL, 100 entries). Cada\n * (productSlug, feature) pareando o `apiKey` é cacheado. Caller pode invalidar\n * via `__resetCache()` (test helper) ou via `cacheBust: true` na chamada.\n */\nimport { NeetruError } from './errors';\nimport { httpRequest } from './http';\nimport type { EntitlementCheck, ResolvedConfig } from './types';\n\ninterface RawEntitlementCheck {\n allowed?: boolean;\n productSlug?: string;\n feature?: string;\n reason?: string;\n}\n\nfunction toEntitlementCheck(raw: unknown): EntitlementCheck {\n if (!raw || typeof raw !== 'object') {\n throw new NeetruError('invalid_response', 'Entitlement response is not an object');\n }\n const r = raw as RawEntitlementCheck;\n if (typeof r.allowed !== 'boolean') {\n throw new NeetruError('invalid_response', 'Entitlement response missing `allowed` boolean');\n }\n return {\n allowed: r.allowed,\n productSlug: typeof r.productSlug === 'string' ? r.productSlug : '',\n feature: typeof r.feature === 'string' ? r.feature : '',\n reason: typeof r.reason === 'string' ? r.reason : undefined,\n };\n}\n\n/** TTL default — 60s. Pareando com tempo de propagação típico de mudança de plano. */\nconst CACHE_TTL_MS = 60_000;\n/** Máx entries por instância de namespace — LRU. */\nconst CACHE_MAX = 100;\n\ninterface CacheEntry {\n value: EntitlementCheck;\n expiresAt: number;\n}\n\nexport interface EntitlementsCheckOptions {\n /** Se true, ignora cache local e força ida ao servidor. Default false. */\n cacheBust?: boolean;\n}\n\nexport function createEntitlementsNamespace(config: ResolvedConfig) {\n // Map preserva ordem de inserção — readequa LRU manualmente em hit.\n const cache = new Map<string, CacheEntry>();\n\n function cacheKey(productSlug: string, feature: string): string {\n return `${productSlug}::${feature}`;\n }\n\n function readCache(key: string): EntitlementCheck | null {\n const entry = cache.get(key);\n if (!entry) return null;\n if (entry.expiresAt < Date.now()) {\n cache.delete(key);\n return null;\n }\n // LRU touch: reinsere no final.\n cache.delete(key);\n cache.set(key, entry);\n return entry.value;\n }\n\n function writeCache(key: string, value: EntitlementCheck): void {\n if (cache.size >= CACHE_MAX) {\n const oldest = cache.keys().next().value;\n if (oldest !== undefined) cache.delete(oldest);\n }\n cache.set(key, { value, expiresAt: Date.now() + CACHE_TTL_MS });\n }\n\n async function checkDetailed(\n productSlug: string,\n feature: string,\n opts: EntitlementsCheckOptions = {},\n ): Promise<EntitlementCheck> {\n if (!productSlug) throw new NeetruError('validation_failed', 'productSlug is required');\n if (!feature) throw new NeetruError('validation_failed', 'feature is required');\n\n const key = cacheKey(productSlug, feature);\n if (!opts.cacheBust) {\n const cached = readCache(key);\n if (cached) return cached;\n }\n\n const raw = await httpRequest<RawEntitlementCheck>(config, {\n method: 'GET',\n path: '/api/v1/sdk/entitlements/check',\n query: { slug: productSlug, feature },\n requireAuth: true,\n });\n const result = toEntitlementCheck(raw);\n writeCache(key, result);\n return result;\n }\n\n return {\n /**\n * Verifica se o caller pode usar `feature` no produto `productSlug`.\n * Retorno simples: `true` libera, `false` bloqueia. Cache 60s automático.\n *\n * Use `checkDetailed` se precisar do `reason` pra mensagem de upgrade.\n */\n async check(\n productSlug: string,\n feature: string,\n opts?: EntitlementsCheckOptions,\n ): Promise<boolean> {\n const result = await checkDetailed(productSlug, feature, opts);\n return result.allowed;\n },\n checkDetailed,\n /** Test helper: limpa o cache LRU. */\n __resetCache(): void {\n cache.clear();\n },\n };\n}\n","/**\n * Telemetria — emite eventos do produto cliente pro Core.\n *\n * APIs disponíveis:\n * - `event(input)` — chamada single-shot, await retorna { ok, eventId }.\n * `POST /api/v1/sdk/telemetry/event` — persiste em `usage_events/{id}`.\n * - `track(input)` — fire-and-forget (v1.2). Enqueue + flush 500ms debounce.\n * Reusa o mesmo endpoint mas não bloqueia o caller — ideal pra alta\n * frequência (cliques, page-views). Falhas viram warning no console.\n * - `flush()` — força flush imediato da queue (chamar antes de unload).\n * - `log(input)` — log estruturado `POST /api/sdk/v1/telemetry/log` com\n * Bearer + correlationId. Em `NEETRU_ENV=dev` cai pra console.{level}.\n */\nimport { NeetruError } from './errors';\nimport { httpRequest } from './http';\nimport type {\n ResolvedConfig,\n TelemetryEventAck,\n TelemetryEventInput,\n TelemetryLogAck,\n TelemetryLogInput,\n TelemetryLogLevel,\n} from './types';\n\ninterface RawTelemetryAck {\n ok?: boolean;\n eventId?: string;\n}\n\ninterface RawLogAck {\n ok?: boolean;\n logId?: string;\n}\n\nconst VALID_LOG_LEVELS: readonly TelemetryLogLevel[] = ['debug', 'info', 'warn', 'error', 'fatal'];\n\nfunction consoleFor(level: TelemetryLogLevel): (message?: unknown, ...optional: unknown[]) => void {\n switch (level) {\n case 'debug': return console.debug.bind(console);\n case 'info': return console.info.bind(console);\n case 'warn': return console.warn.bind(console);\n case 'error': return console.error.bind(console);\n case 'fatal': return console.error.bind(console);\n default: return console.log.bind(console);\n }\n}\n\n/** Janela de debounce do `track()` antes de drenar a queue. */\nconst TRACK_FLUSH_MS = 500;\n/** Limite de eventos na queue antes de flush forçado (defensivo). */\nconst TRACK_MAX_QUEUE = 50;\n\nexport function createTelemetryNamespace(config: ResolvedConfig) {\n // Queue local pra track() — fire-and-forget batchado.\n const queue: TelemetryEventInput[] = [];\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n\n async function drainQueue(): Promise<void> {\n if (queue.length === 0) return;\n const batch = queue.splice(0, queue.length);\n flushTimer = null;\n await Promise.allSettled(\n batch.map(async (ev) => {\n try {\n const body: Record<string, unknown> = { name: ev.name };\n if (ev.properties && typeof ev.properties === 'object') {\n body.properties = ev.properties;\n }\n if (ev.timestamp) body.timestamp = ev.timestamp;\n await httpRequest<RawTelemetryAck>(config, {\n method: 'POST',\n path: '/api/v1/sdk/telemetry/event',\n body,\n requireAuth: true,\n retries: 1,\n });\n } catch (err) {\n if (typeof console !== 'undefined') {\n console.warn('[neetru-sdk] telemetry.track flush failed for event', ev.name, err);\n }\n }\n }),\n );\n }\n\n function scheduleFlush(): void {\n if (flushTimer) return;\n flushTimer = setTimeout(() => {\n void drainQueue();\n }, TRACK_FLUSH_MS);\n }\n\n return {\n /**\n * Persiste um evento de uso. Lança `NeetruError` em qualquer falha\n * (incluindo rate-limit).\n *\n * @example\n * ```ts\n * await client.telemetry.event({\n * name: 'dashboard_opened',\n * properties: { plan: 'pro', tab: 'overview' },\n * });\n * ```\n */\n async event(input: TelemetryEventInput): Promise<TelemetryEventAck> {\n if (!input || typeof input !== 'object') {\n throw new NeetruError('validation_failed', 'event input is required');\n }\n if (typeof input.name !== 'string' || input.name.length === 0) {\n throw new NeetruError('validation_failed', 'event.name is required');\n }\n if (input.name.length > 128) {\n throw new NeetruError('validation_failed', 'event.name max 128 chars');\n }\n\n const body: Record<string, unknown> = { name: input.name };\n if (input.properties && typeof input.properties === 'object') {\n body.properties = input.properties;\n }\n if (input.timestamp) body.timestamp = input.timestamp;\n\n const raw = await httpRequest<RawTelemetryAck>(config, {\n method: 'POST',\n path: '/api/v1/sdk/telemetry/event',\n body,\n requireAuth: true,\n });\n\n if (!raw || raw.ok !== true || typeof raw.eventId !== 'string') {\n throw new NeetruError('invalid_response', 'Telemetry response missing eventId');\n }\n return { ok: true, eventId: raw.eventId };\n },\n\n /**\n * Fire-and-forget: enqueue + flush 500ms debounce. Não retorna `eventId`\n * — falhas são logadas como warning. Ideal pra alta frequência.\n *\n * @example\n * ```ts\n * client.telemetry.track({ name: 'page_view', properties: { path: '/' } });\n * // segue execução; flush async em background\n * ```\n */\n track(input: TelemetryEventInput): void {\n if (!input || typeof input !== 'object') return;\n if (typeof input.name !== 'string' || input.name.length === 0) return;\n if (input.name.length > 128) return;\n queue.push(input);\n if (queue.length >= TRACK_MAX_QUEUE) {\n void drainQueue();\n } else {\n scheduleFlush();\n }\n },\n\n /**\n * Força flush imediato da queue de `track()`. Resolva antes de\n * page unload / SSR boundary pra não perder eventos.\n */\n async flush(): Promise<void> {\n if (flushTimer) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n await drainQueue();\n },\n\n /**\n * Registra um log estruturado per-product (Sprint 6).\n *\n * - `NEETRU_ENV=dev`: console.{level}, retorna ack mock.\n * - workspace/prod: HTTP POST com Bearer auth + correlationId no header.\n *\n * @example\n * ```ts\n * await client.telemetry.log({\n * level: 'error',\n * message: 'Falha ao calcular total',\n * metadata: { orderId: 'o-123' },\n * });\n * ```\n */\n async log(input: TelemetryLogInput): Promise<TelemetryLogAck> {\n if (!input || typeof input !== 'object') {\n throw new NeetruError('validation_failed', 'log input is required');\n }\n if (!VALID_LOG_LEVELS.includes(input.level)) {\n throw new NeetruError('validation_failed', `level must be one of ${VALID_LOG_LEVELS.join(', ')}`);\n }\n if (typeof input.message !== 'string' || input.message.length === 0) {\n throw new NeetruError('validation_failed', 'message is required');\n }\n if (input.message.length > 4_000) {\n throw new NeetruError('validation_failed', 'message max 4000 chars');\n }\n\n // Dev mode: console only, no network.\n if (config.env === 'dev') {\n const fn = consoleFor(input.level);\n fn(`[neetru-sdk] ${input.level}: ${input.message}`, input.metadata ?? {});\n return { ok: true, mode: 'mock' };\n }\n\n const body: Record<string, unknown> = {\n level: input.level,\n message: input.message,\n };\n if (input.metadata) body.metadata = input.metadata;\n if (input.productSlug) body.productSlug = input.productSlug;\n\n // CorrelationId: explicit input wins; senão tenta lê de globalThis (set\n // por instrumentação do consumer).\n let cid = input.correlationId;\n if (!cid) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const g = (globalThis as any).NEETRU_CORRELATION_ID;\n if (typeof g === 'string' && g.length > 0) cid = g;\n } catch {\n /* ignore */\n }\n }\n\n const headers: Record<string, string> = {};\n if (cid) headers['x-correlation-id'] = cid;\n\n const raw = await httpRequest<RawLogAck>(config, {\n method: 'POST',\n path: '/api/sdk/v1/telemetry/log',\n body,\n requireAuth: true,\n headers,\n });\n\n if (!raw || raw.ok !== true) {\n throw new NeetruError('invalid_response', 'Telemetry log response missing ok');\n }\n return {\n ok: true,\n logId: typeof raw.logId === 'string' ? raw.logId : undefined,\n mode: 'http',\n };\n },\n };\n}\n","/**\n * Usage namespace — track usage events e ler quotas (v0.2).\n *\n * Endpoints consumidos (em prod):\n * - `POST /sdk/v1/usage/record` — record event\n * - `GET /sdk/v1/usage/quota?metric=X` — ler quota da metric\n *\n * Comportamento por env:\n * - `dev` → MockUsage (in-memory, retornado pelo factory).\n * - `workspace`/`prod` → HTTP real.\n *\n * Diferença vs `telemetry`: telemetry é evento analítico (event sourcing pra\n * BigQuery). usage é meterado (consumo cobrado), com quota explícita por plano.\n */\nimport { NeetruError } from './errors';\nimport { httpRequest } from './http';\nimport type { ResolvedConfig, UsageNamespace, UsageQuota } from './types';\n\ninterface RawUsageAck {\n ok?: boolean;\n recordId?: string;\n}\n\ninterface RawUsageQuota {\n metric?: string;\n used?: number;\n limit?: number;\n resetsAt?: string;\n plan?: string;\n}\n\nfunction toQuota(metric: string, raw: unknown): UsageQuota {\n if (!raw || typeof raw !== 'object') {\n throw new NeetruError('invalid_response', 'Quota response is not an object');\n }\n const r = raw as RawUsageQuota;\n if (typeof r.used !== 'number' || typeof r.limit !== 'number') {\n throw new NeetruError('invalid_response', 'Quota response missing used/limit numbers');\n }\n return {\n metric: typeof r.metric === 'string' ? r.metric : metric,\n used: r.used,\n limit: r.limit,\n resetsAt: typeof r.resetsAt === 'string' ? r.resetsAt : undefined,\n plan: typeof r.plan === 'string' ? r.plan : undefined,\n };\n}\n\nexport function createUsageNamespace(config: ResolvedConfig): UsageNamespace {\n return {\n /**\n * Persiste um evento de usage. Em dev (mocks ativos via factory) só loga.\n * Em workspace/prod chama POST /sdk/v1/usage/record.\n */\n async track(\n event: string,\n properties?: Record<string, string | number | boolean | null>,\n ): Promise<{ ok: true }> {\n if (!event || typeof event !== 'string') {\n throw new NeetruError('validation_failed', 'event name is required');\n }\n if (event.length > 128) {\n throw new NeetruError('validation_failed', 'event name max 128 chars');\n }\n\n const body: Record<string, unknown> = { event };\n if (properties && typeof properties === 'object') body.properties = properties;\n\n const raw = await httpRequest<RawUsageAck>(config, {\n method: 'POST',\n path: '/sdk/v1/usage/record',\n body,\n requireAuth: true,\n });\n\n if (!raw || raw.ok !== true) {\n throw new NeetruError('invalid_response', 'Usage record response missing ok');\n }\n return { ok: true };\n },\n\n /**\n * Lê quota atual de uma métrica. Cacheável (caller decide), SDK não cacheia.\n */\n async getQuota(metric: string): Promise<UsageQuota> {\n if (!metric || typeof metric !== 'string') {\n throw new NeetruError('validation_failed', 'metric is required');\n }\n const raw = await httpRequest<RawUsageQuota>(config, {\n method: 'GET',\n path: '/sdk/v1/usage/quota',\n query: { metric },\n requireAuth: true,\n });\n return toQuota(metric, raw);\n },\n\n /**\n * v0.3 — Reporta consumo metered. Hit no endpoint canônico Sprint 7.\n */\n async report(\n resource: string,\n qty: number = 1,\n options?: { productId?: string; tenantId?: string },\n ) {\n if (!resource || typeof resource !== 'string') {\n throw new NeetruError('validation_failed', 'resource is required');\n }\n if (!Number.isFinite(qty) || qty <= 0) {\n throw new NeetruError('validation_failed', 'qty must be positive integer');\n }\n const productId = options?.productId ?? config.productId;\n const tenantId = options?.tenantId ?? config.tenantId;\n if (!productId) {\n throw new NeetruError(\n 'validation_failed',\n 'productId required (pass to options or set on createNeetruClient)',\n );\n }\n if (!tenantId) {\n throw new NeetruError(\n 'validation_failed',\n 'tenantId required (pass to options or set on createNeetruClient)',\n );\n }\n\n const raw = await httpRequest<{\n ok?: boolean;\n counterId?: string;\n value?: number;\n limit?: number;\n remaining?: number;\n status?: string;\n }>(config, {\n method: 'POST',\n path: '/sdk/v1/usage/record',\n body: { productId, tenantId, resource, qty: Math.floor(qty) },\n requireAuth: true,\n });\n if (!raw || raw.ok !== true) {\n throw new NeetruError('invalid_response', 'usage.report response missing ok');\n }\n return {\n ok: true as const,\n counterId: raw.counterId,\n value: raw.value,\n limit: raw.limit,\n remaining: raw.remaining,\n status: raw.status,\n };\n },\n\n /**\n * v0.3 — Verifica entitlement de um resource via GET /sdk/v1/entitlements.\n */\n async check(\n resource: string,\n options?: { productId?: string; tenantId?: string },\n ) {\n if (!resource || typeof resource !== 'string') {\n throw new NeetruError('validation_failed', 'resource is required');\n }\n const productId = options?.productId ?? config.productId;\n const tenantId = options?.tenantId ?? config.tenantId;\n if (!productId || !tenantId) {\n throw new NeetruError(\n 'validation_failed',\n 'productId and tenantId required',\n );\n }\n const raw = await httpRequest<{\n allowed?: boolean;\n reason?: string;\n remaining?: number;\n limit?: number;\n planId?: string | null;\n planFeatures?: string[];\n }>(config, {\n method: 'GET',\n path: '/sdk/v1/entitlements',\n query: { productId, tenantId, feature: resource },\n requireAuth: true,\n });\n if (!raw || typeof raw.allowed !== 'boolean') {\n throw new NeetruError('invalid_response', 'usage.check response missing allowed');\n }\n return {\n allowed: raw.allowed,\n reason: raw.reason,\n remaining: raw.remaining,\n limit: raw.limit,\n planId: raw.planId,\n planFeatures: raw.planFeatures,\n };\n },\n };\n}\n","/**\n * Support namespace — criar e listar tickets do customer (v0.2).\n *\n * Endpoints (em prod):\n * - `POST /api/v1/products/{slug}/tickets` — criar ticket\n * - `GET /api/v1/products/{slug}/tickets` — listar meus tickets do produto\n *\n * Em dev (mocks ativos via factory) tudo é in-memory.\n *\n * Decisão: severity default é `normal`. `low` indica feature requests; `urgent`\n * pra outages production (paginating ops imediatamente em prod).\n */\nimport { NeetruError } from './errors';\nimport { httpRequest } from './http';\nimport type {\n CreateTicketInput,\n ResolvedConfig,\n SupportNamespace,\n SupportSeverity,\n SupportStatus,\n SupportTicket,\n} from './types';\n\nconst VALID_SEVERITIES: readonly SupportSeverity[] = ['low', 'normal', 'high', 'urgent'];\nconst VALID_STATUSES: readonly SupportStatus[] = ['open', 'pending', 'resolved', 'closed'];\n\ninterface RawTicket {\n id?: string;\n subject?: string;\n message?: string;\n severity?: string;\n status?: string;\n createdAt?: string;\n updatedAt?: string;\n productSlug?: string;\n}\n\nfunction toTicket(raw: unknown): SupportTicket {\n if (!raw || typeof raw !== 'object') {\n throw new NeetruError('invalid_response', 'Ticket response is not an object');\n }\n const r = raw as RawTicket;\n if (typeof r.id !== 'string') {\n throw new NeetruError('invalid_response', 'Ticket missing id');\n }\n return {\n id: r.id,\n subject: typeof r.subject === 'string' ? r.subject : '',\n message: typeof r.message === 'string' ? r.message : '',\n severity: VALID_SEVERITIES.includes(r.severity as SupportSeverity)\n ? (r.severity as SupportSeverity)\n : 'normal',\n status: VALID_STATUSES.includes(r.status as SupportStatus)\n ? (r.status as SupportStatus)\n : 'open',\n createdAt: typeof r.createdAt === 'string' ? r.createdAt : new Date().toISOString(),\n updatedAt: typeof r.updatedAt === 'string' ? r.updatedAt : undefined,\n productSlug: typeof r.productSlug === 'string' ? r.productSlug : undefined,\n };\n}\n\nexport function createSupportNamespace(config: ResolvedConfig): SupportNamespace {\n return {\n /**\n * Cria um ticket de suporte. Requer Bearer auth. Se `productSlug` não é\n * passado, o backend infere do escopo do token.\n */\n async createTicket(input: CreateTicketInput): Promise<SupportTicket> {\n if (!input || typeof input !== 'object') {\n throw new NeetruError('validation_failed', 'input is required');\n }\n if (!input.subject || typeof input.subject !== 'string') {\n throw new NeetruError('validation_failed', 'subject is required');\n }\n if (input.subject.length > 200) {\n throw new NeetruError('validation_failed', 'subject max 200 chars');\n }\n if (!input.message || typeof input.message !== 'string') {\n throw new NeetruError('validation_failed', 'message is required');\n }\n if (input.message.length > 10_000) {\n throw new NeetruError('validation_failed', 'message max 10000 chars');\n }\n if (input.severity && !VALID_SEVERITIES.includes(input.severity)) {\n throw new NeetruError('validation_failed', `severity must be one of ${VALID_SEVERITIES.join(', ')}`);\n }\n\n const slug = input.productSlug ?? '_default';\n const body: Record<string, unknown> = {\n subject: input.subject,\n message: input.message,\n severity: input.severity ?? 'normal',\n };\n\n const raw = await httpRequest<RawTicket | { ticket?: RawTicket }>(config, {\n method: 'POST',\n path: `/api/v1/products/${encodeURIComponent(slug)}/tickets`,\n body,\n requireAuth: true,\n });\n\n // Backend pode envelopar como { ticket: {...} } ou retornar direto.\n const candidate =\n raw && typeof raw === 'object' && 'ticket' in raw\n ? (raw as { ticket?: RawTicket }).ticket\n : raw;\n return toTicket(candidate);\n },\n\n /**\n * Lista tickets do customer no produto atual (escopo do token).\n */\n async listMyTickets(): Promise<SupportTicket[]> {\n const raw = await httpRequest<{ tickets?: unknown[] } | unknown[]>(config, {\n method: 'GET',\n path: '/api/v1/products/_default/tickets',\n requireAuth: true,\n });\n const list = Array.isArray(raw) ? raw : raw && typeof raw === 'object' && 'tickets' in raw ? (raw as { tickets?: unknown[] }).tickets ?? [] : [];\n return list.map(toTicket);\n },\n };\n}\n","/**\n * Datastore namespace (v0.3.1) — Sprint 8.\n *\n * `client.db.collection(name)` retorna um `DbCollectionRef` que mapeia para\n * `tenant_{tid}_{name}` no Core. Endpoints REST disponíveis (Sprint 8 LIVE):\n * - `GET /api/sdk/v1/datastore/{collection}?limit&where`\n * - `POST /api/sdk/v1/datastore/{collection}` (add)\n * - `GET /api/sdk/v1/datastore/{collection}/{id}`\n * - `PATCH /api/sdk/v1/datastore/{collection}/{id}` (update merge)\n * - `PUT /api/sdk/v1/datastore/{collection}/{id}` (set replace)\n * - `DELETE /api/sdk/v1/datastore/{collection}/{id}`\n *\n * O Core resolve `tenantId` via Bearer token. SDK passa `x-neetru-tenant`\n * pra dar visibilidade explícita; backend valida match com o token.\n *\n * Em dev (NEETRU_ENV=dev), `client.db` é `MockDb` (in-memory).\n */\nimport { httpRequest } from './http';\nimport { NeetruError } from './errors';\nimport type {\n DbCollectionRef,\n DbListOptions,\n DbNamespace,\n DbWhereFilter,\n ResolvedConfig,\n} from './types';\n\nconst COLL_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/;\n\nfunction assertValidCollection(name: string): void {\n if (!COLL_RE.test(name)) {\n throw new NeetruError(\n 'validation_failed',\n `Invalid collection name: \"${name}\". Must match ${COLL_RE}.`,\n );\n }\n}\n\n/** Serializa filtro pro formato `field:op:value` aceito pelo backend. */\nfunction serializeWhere(filter: DbWhereFilter): string {\n const { field, op, value } = filter;\n if (op === 'in') {\n if (!Array.isArray(value)) {\n throw new NeetruError(\n 'validation_failed',\n `where op=\"in\" requer value array (recebido: ${typeof value})`,\n );\n }\n return `${field}:in:${value.map((v) => String(v)).join(',')}`;\n }\n return `${field}:${op}:${String(value)}`;\n}\n\n/**\n * Constrói o namespace `db` real (HTTP) com binding ao tenantId resolvido.\n */\nexport function createDbNamespace(config: ResolvedConfig): DbNamespace {\n return {\n collection(name: string): DbCollectionRef {\n assertValidCollection(name);\n\n const headers: Record<string, string> = {};\n if (config.tenantId) headers['x-neetru-tenant'] = config.tenantId;\n\n return {\n async list<T = Record<string, unknown>>(\n opts?: DbListOptions,\n ): Promise<T[]> {\n // multi-where → URL múltiplo `where=...&where=...`. Como\n // `httpRequest.query` é Record<>, monta path manualmente quando há\n // filtros pra preservar repetição da chave.\n let path = `/api/sdk/v1/datastore/${name}`;\n const params = new URLSearchParams();\n if (opts?.limit !== undefined) params.set('limit', String(opts.limit));\n if (opts?.where && opts.where.length > 0) {\n for (const f of opts.where) {\n params.append('where', serializeWhere(f));\n }\n }\n if (config.tenantId) params.set('tenantId', config.tenantId);\n const qs = params.toString();\n if (qs) path += `?${qs}`;\n\n const raw = await httpRequest<{ items?: unknown[] }>(config, {\n method: 'GET',\n path,\n requireAuth: true,\n headers,\n });\n if (!raw || !Array.isArray(raw.items)) {\n throw new NeetruError(\n 'invalid_response',\n 'datastore.list missing items[]',\n );\n }\n return raw.items as T[];\n },\n\n async get<T = Record<string, unknown>>(id: string): Promise<T | null> {\n if (!id || typeof id !== 'string') {\n throw new NeetruError('validation_failed', 'id required');\n }\n try {\n const raw = await httpRequest<{ item?: T | null }>(config, {\n method: 'GET',\n path: `/api/sdk/v1/datastore/${name}/${encodeURIComponent(id)}`,\n requireAuth: true,\n headers,\n });\n return raw?.item ?? null;\n } catch (err) {\n if (err instanceof NeetruError && err.code === 'not_found') return null;\n throw err;\n }\n },\n\n async add(data: Record<string, unknown>): Promise<{ ok: true; id: string }> {\n if (!data || typeof data !== 'object') {\n throw new NeetruError('validation_failed', 'data object required');\n }\n const raw = await httpRequest<{ ok?: boolean; id?: string }>(config, {\n method: 'POST',\n path: `/api/sdk/v1/datastore/${name}`,\n body: { data },\n requireAuth: true,\n headers,\n });\n if (!raw || typeof raw.id !== 'string') {\n throw new NeetruError('invalid_response', 'datastore.add missing id');\n }\n return { ok: true, id: raw.id };\n },\n\n async set(id: string, data: Record<string, unknown>): Promise<{ ok: true }> {\n if (!id || typeof id !== 'string') {\n throw new NeetruError('validation_failed', 'id required');\n }\n await httpRequest(config, {\n method: 'PUT',\n path: `/api/sdk/v1/datastore/${name}/${encodeURIComponent(id)}`,\n body: { data },\n requireAuth: true,\n headers,\n });\n return { ok: true };\n },\n\n async update(id: string, data: Record<string, unknown>): Promise<{ ok: true }> {\n if (!id || typeof id !== 'string') {\n throw new NeetruError('validation_failed', 'id required');\n }\n await httpRequest(config, {\n method: 'PATCH',\n path: `/api/sdk/v1/datastore/${name}/${encodeURIComponent(id)}`,\n body: { data },\n requireAuth: true,\n headers,\n });\n return { ok: true };\n },\n\n async remove(id: string): Promise<{ ok: true }> {\n if (!id || typeof id !== 'string') {\n throw new NeetruError('validation_failed', 'id required');\n }\n await httpRequest(config, {\n method: 'DELETE',\n path: `/api/sdk/v1/datastore/${name}/${encodeURIComponent(id)}`,\n requireAuth: true,\n headers,\n });\n return { ok: true };\n },\n };\n },\n };\n}\n","/**\n * Checkout namespace (v1.1) — `client.checkout.*`\n *\n * Fluxo canônico (vide `docs/FLUXO_SIGNUP_BILLING_CHECKOUT.md` §6):\n * 1. SaaS produto chama `client.checkout.start({productId, planId, callbackUrl})`.\n * 2. SDK posta em `POST /api/v1/checkout/intents` (Bearer access_token OIDC).\n * 3. Core cria `checkout_intents/{intentId}` (TTL 15min) + retorna `redirectUrl`.\n * 4. Em browser, SDK redireciona automaticamente pra `redirectUrl`. Em\n * Node/SSR, retorna o objeto `{intentId, redirectUrl}` sem redirect.\n * 5. Portal (`minhaconta.neetru.com/portal/kyc/{intentId}`) coleta KYC + cartão.\n * 6. Usuário volta pra `callbackUrl?status=success&intentId=...` quando completo.\n *\n * **Dev mode** (`NEETRU_ENV=dev`): `start()` retorna URL fake sem network call.\n * Útil pra dev externo SaaS testar UI sem provisionar conta Neetru.\n *\n * **Estabilidade**: minor bump v1.0 → v1.1 (feature add, sem breaking).\n */\nimport { NeetruError } from './errors';\nimport { httpRequest } from './http';\nimport type { ResolvedConfig } from './types';\n\n// ─── Types públicos ─────────────────────────────────────────────────────────\n\n/** Tipo do tenant alvo da subscription (PF=uid, PJ=orgId). */\nexport type CheckoutTenantType = 'pf' | 'pj';\n\n/** Status do `checkout_intents/{intentId}` no Core. */\nexport type CheckoutIntentStatus =\n | 'pending'\n | 'kyc_in_progress'\n | 'stripe_redirected'\n | 'completed'\n | 'expired'\n | 'cancelled';\n\nexport interface CheckoutStartInput {\n /** Slug do produto no catálogo (ex: `neetru-pulse`). */\n productId: string;\n /** Slug do plano no catálogo do produto (ex: `pro_monthly`). */\n planId: string;\n /** Pra onde o produto SaaS quer voltar pós-checkout. https obrigatório (ou http://localhost em dev). */\n callbackUrl: string;\n /** Override pra checkout em nome de uma org. Default: PF do uid logado. */\n tenantType?: CheckoutTenantType;\n /** Quando `tenantType='pj'`, id da org. Ignorado quando PF. */\n tenantId?: string;\n /**\n * Em browsers, default `true` — SDK faz `window.location.href = redirectUrl`.\n * Passe `false` se quiser controlar o redirect manualmente.\n */\n autoRedirect?: boolean;\n}\n\nexport interface CheckoutStartResult {\n intentId: string;\n redirectUrl: string;\n status: CheckoutIntentStatus;\n expiresAt: string;\n /** True se KYC ainda precisa ser coletado no portal. UI pode mostrar hint. */\n requiresKyc: boolean;\n}\n\nexport interface CheckoutIntentInfo {\n intentId: string;\n uid: string;\n targetTenantId: string;\n targetTenantType: CheckoutTenantType;\n productId: string;\n planId: string;\n callbackUrl: string;\n status: CheckoutIntentStatus;\n /** Stripe Checkout Session id quando avançou pra `stripe_redirected`. */\n stripeSessionId?: string | null;\n expiresAt: string;\n /** True se já passou `expiresAt` mas Core ainda não marcou expired. */\n isStale?: boolean;\n}\n\nexport interface CheckoutNamespace {\n /**\n * Inicia checkout. Em browser, redireciona automaticamente pro portal.\n * Em Node/SSR, retorna o resultado sem efeitos colaterais — caller decide\n * o que fazer com `redirectUrl`.\n *\n * Dev mode (`NEETRU_ENV=dev`): retorna URL fake `https://localhost:9003/portal/checkout/mock-XXXX`.\n */\n start(input: CheckoutStartInput): Promise<CheckoutStartResult>;\n /** Lê estado atual do intent (Core). */\n get(intentId: string): Promise<CheckoutIntentInfo>;\n /** Cancela um intent que ainda não virou `stripe_redirected`. */\n cancel(intentId: string): Promise<{ ok: true; alreadyCancelled: boolean }>;\n}\n\n// ─── Implementação real (HTTP) ─────────────────────────────────────────────\n\ninterface RawStartCheckoutResponse {\n ok?: boolean;\n intentId?: string;\n redirectUrl?: string;\n status?: string;\n expiresAt?: string;\n requiresKyc?: boolean;\n}\n\ninterface RawGetCheckoutResponse {\n ok?: boolean;\n intent?: {\n intentId?: string;\n uid?: string;\n targetTenantId?: string;\n targetTenantType?: string;\n productId?: string;\n planId?: string;\n callbackUrl?: string;\n status?: string;\n stripeSessionId?: string | null;\n expiresAt?: string;\n };\n isStale?: boolean;\n}\n\nfunction parseStartResponse(raw: unknown): CheckoutStartResult {\n if (!raw || typeof raw !== 'object') {\n throw new NeetruError('invalid_response', 'checkout.start response is not an object');\n }\n const r = raw as RawStartCheckoutResponse;\n if (typeof r.intentId !== 'string' || !r.intentId) {\n throw new NeetruError('invalid_response', 'checkout.start response missing intentId');\n }\n if (typeof r.redirectUrl !== 'string' || !r.redirectUrl) {\n throw new NeetruError('invalid_response', 'checkout.start response missing redirectUrl');\n }\n return {\n intentId: r.intentId,\n redirectUrl: r.redirectUrl,\n status: (r.status as CheckoutIntentStatus | undefined) ?? 'pending',\n expiresAt: typeof r.expiresAt === 'string' ? r.expiresAt : new Date().toISOString(),\n requiresKyc: r.requiresKyc === true,\n };\n}\n\nfunction parseGetResponse(raw: unknown): CheckoutIntentInfo {\n if (!raw || typeof raw !== 'object') {\n throw new NeetruError('invalid_response', 'checkout.get response is not an object');\n }\n const r = raw as RawGetCheckoutResponse;\n const intent = r.intent;\n if (!intent || typeof intent !== 'object') {\n throw new NeetruError('invalid_response', 'checkout.get response missing intent');\n }\n if (typeof intent.intentId !== 'string') {\n throw new NeetruError('invalid_response', 'checkout.get response missing intentId');\n }\n return {\n intentId: intent.intentId,\n uid: intent.uid ?? '',\n targetTenantId: intent.targetTenantId ?? '',\n targetTenantType: (intent.targetTenantType as CheckoutTenantType | undefined) ?? 'pf',\n productId: intent.productId ?? '',\n planId: intent.planId ?? '',\n callbackUrl: intent.callbackUrl ?? '',\n status: (intent.status as CheckoutIntentStatus | undefined) ?? 'pending',\n stripeSessionId: intent.stripeSessionId ?? null,\n expiresAt: intent.expiresAt ?? new Date().toISOString(),\n isStale: r.isStale === true,\n };\n}\n\n/**\n * Detecta se estamos em browser context. Em SSR / Node / Edge, `window`\n * pode não existir — fazemos check defensivo.\n */\nfunction inBrowser(): boolean {\n try {\n return (\n typeof globalThis !== 'undefined' &&\n typeof (globalThis as { window?: { location?: { href?: string } } }).window !== 'undefined' &&\n typeof globalThis.location !== 'undefined' &&\n typeof globalThis.location.assign === 'function'\n );\n } catch {\n return false;\n }\n}\n\nfunction performRedirect(url: string): void {\n try {\n globalThis.location.assign(url);\n } catch {\n /* noop em runtimes sem location.assign — caller decide */\n }\n}\n\n/**\n * Implementação HTTP real. Posta no Core, parse response, redireciona se browser.\n */\nfunction createHttpCheckoutNamespace(config: ResolvedConfig): CheckoutNamespace {\n return {\n async start(input: CheckoutStartInput): Promise<CheckoutStartResult> {\n if (!input?.productId) {\n throw new NeetruError('validation_failed', 'checkout.start: productId is required');\n }\n if (!input?.planId) {\n throw new NeetruError('validation_failed', 'checkout.start: planId is required');\n }\n if (!input?.callbackUrl) {\n throw new NeetruError('validation_failed', 'checkout.start: callbackUrl is required');\n }\n\n const body: Record<string, unknown> = {\n productId: input.productId,\n planId: input.planId,\n callbackUrl: input.callbackUrl,\n };\n if (input.tenantType) body.targetTenantType = input.tenantType;\n if (input.tenantId) body.targetTenantId = input.tenantId;\n\n const raw = await httpRequest<RawStartCheckoutResponse>(config, {\n method: 'POST',\n path: '/api/v1/checkout/intents',\n body,\n requireAuth: true,\n });\n const result = parseStartResponse(raw);\n\n const shouldRedirect = input.autoRedirect !== false;\n if (shouldRedirect && inBrowser()) {\n performRedirect(result.redirectUrl);\n }\n return result;\n },\n\n async get(intentId: string): Promise<CheckoutIntentInfo> {\n if (!intentId || typeof intentId !== 'string') {\n throw new NeetruError('validation_failed', 'checkout.get: intentId is required');\n }\n const raw = await httpRequest<RawGetCheckoutResponse>(config, {\n method: 'GET',\n path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,\n requireAuth: true,\n });\n return parseGetResponse(raw);\n },\n\n async cancel(intentId: string): Promise<{ ok: true; alreadyCancelled: boolean }> {\n if (!intentId || typeof intentId !== 'string') {\n throw new NeetruError('validation_failed', 'checkout.cancel: intentId is required');\n }\n const raw = await httpRequest<{ ok?: boolean; alreadyCancelled?: boolean }>(config, {\n method: 'DELETE',\n path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,\n requireAuth: true,\n });\n return {\n ok: true,\n alreadyCancelled: (raw as { alreadyCancelled?: boolean })?.alreadyCancelled === true,\n };\n },\n };\n}\n\n// ─── Mock dev (sem network) ─────────────────────────────────────────────────\n\n/**\n * Mock dev — retorna URL fake `https://localhost:9003/portal/checkout/mock-XXXX`\n * sem tocar no Core. Útil pra dev externo SaaS testar UI/redirect sem precisar\n * de Bearer token Neetru.\n *\n * Dev mode persiste intents em mapa in-memory pro `get`/`cancel` retornarem\n * resultado consistente.\n */\nexport class MockCheckout implements CheckoutNamespace {\n private readonly intents = new Map<string, CheckoutIntentInfo>();\n\n async start(input: CheckoutStartInput): Promise<CheckoutStartResult> {\n if (!input?.productId) {\n throw new NeetruError('validation_failed', 'checkout.start: productId is required');\n }\n if (!input?.planId) {\n throw new NeetruError('validation_failed', 'checkout.start: planId is required');\n }\n if (!input?.callbackUrl) {\n throw new NeetruError('validation_failed', 'checkout.start: callbackUrl is required');\n }\n\n const intentId = `chk_mock_${Math.random().toString(36).slice(2, 10)}`;\n const expiresAt = new Date(Date.now() + 15 * 60 * 1000).toISOString();\n const redirectUrl = `https://localhost:9003/portal/checkout/${intentId}`;\n\n this.intents.set(intentId, {\n intentId,\n uid: 'dev-fixture-uid',\n targetTenantId: input.tenantId ?? 'dev-fixture-uid',\n targetTenantType: input.tenantType ?? 'pf',\n productId: input.productId,\n planId: input.planId,\n callbackUrl: input.callbackUrl,\n status: 'pending',\n stripeSessionId: null,\n expiresAt,\n });\n\n return {\n intentId,\n redirectUrl,\n status: 'pending',\n expiresAt,\n requiresKyc: false,\n };\n }\n\n async get(intentId: string): Promise<CheckoutIntentInfo> {\n const found = this.intents.get(intentId);\n if (!found) {\n throw new NeetruError('not_found', `Mock intent ${intentId} not found`);\n }\n return { ...found };\n }\n\n async cancel(intentId: string): Promise<{ ok: true; alreadyCancelled: boolean }> {\n const found = this.intents.get(intentId);\n if (!found) {\n throw new NeetruError('not_found', `Mock intent ${intentId} not found`);\n }\n const alreadyCancelled = found.status === 'cancelled';\n this.intents.set(intentId, { ...found, status: 'cancelled' });\n return { ok: true, alreadyCancelled };\n }\n}\n\n// ─── Factory ────────────────────────────────────────────────────────────────\n\nexport function createCheckoutNamespace(config: ResolvedConfig): CheckoutNamespace {\n if (config.env === 'dev') return new MockCheckout();\n return createHttpCheckoutNamespace(config);\n}\n","/**\n * Webhooks namespace (v1.2) — produtos SaaS registram endpoints HTTP no Core\n * pra receber notificações de eventos.\n *\n * Casos típicos:\n * - `subscription.activated` quando cliente conclui checkout\n * - `subscription.cancelled` / `subscription.payment_failed`\n * - `usage.quota_exceeded` quando produto bate teto mensal\n * - `account.suspended` quando staff Neetru suspende uma conta\n *\n * Pull-vs-push: o SDK existente é pull-only (`getQuota`, etc). Webhooks\n * fecham o gap pra eventos assíncronos sem o produto precisar fazer polling.\n *\n * Segurança:\n * - Endpoint do produto recebe HMAC SHA-256 em header `X-Neetru-Signature`\n * usando `secret` opcional do registro. Sem `secret`, header ausente —\n * produto deve usar HTTPS + IP allowlist.\n * - Replay protection: header `X-Neetru-Timestamp` (ms) — produto deve\n * rejeitar > 5min de skew.\n * - Retry: Core retenta 3x com backoff exponencial (1s, 5s, 25s) se 5xx\n * ou timeout. Após 3 falhas → marca endpoint `degraded` por 1h.\n *\n * Endpoints REST (em prod):\n * - `POST /api/sdk/v1/webhooks` — registra novo endpoint\n * - `GET /api/sdk/v1/webhooks` — lista endpoints do produto\n * - `DELETE /api/sdk/v1/webhooks/{id}` — remove endpoint\n * - `POST /api/sdk/v1/webhooks/{id}/test` — dispara evento de teste\n *\n * Mock em `NEETRU_ENV=dev`: tudo in-memory, sem rede.\n */\nimport { NeetruError } from './errors';\nimport { httpRequest } from './http';\nimport type { ResolvedConfig } from './types';\n\n/** Eventos Neetru que produtos podem assinar. Lista expansível por minor bump. */\nexport type WebhookEvent =\n | 'subscription.activated'\n | 'subscription.cancelled'\n | 'subscription.payment_failed'\n | 'subscription.trial_ending'\n | 'usage.quota_exceeded'\n | 'account.suspended'\n | 'account.reactivated'\n | 'support.ticket_replied';\n\nexport interface WebhookEndpoint {\n id: string;\n url: string;\n events: WebhookEvent[];\n /** Quando true, `X-Neetru-Signature` é enviado em cada dispatch. */\n hasSecret: boolean;\n status: 'active' | 'degraded' | 'disabled';\n /** ISO timestamp do último dispatch bem-sucedido. */\n lastDeliveryAt?: string;\n /** Quantos dispatches falharam consecutivos (resetado em sucesso). */\n consecutiveFailures?: number;\n createdAt: string;\n}\n\nexport interface RegisterWebhookInput {\n url: string;\n events: WebhookEvent[];\n /**\n * Secret pra HMAC SHA-256 (mín 16 chars). Recomendado.\n * Quando ausente, dispatches vão sem assinatura — produto deve ter\n * IP allowlist ou outra defesa.\n */\n secret?: string;\n}\n\nexport interface WebhookTestResult {\n ok: boolean;\n statusCode?: number;\n durationMs?: number;\n error?: string;\n}\n\nexport interface WebhooksNamespace {\n /** Registra um novo endpoint. */\n register(input: RegisterWebhookInput): Promise<WebhookEndpoint>;\n /** Lista endpoints registrados pelo produto. */\n list(): Promise<WebhookEndpoint[]>;\n /** Remove um endpoint. */\n unregister(id: string): Promise<{ ok: true }>;\n /** Dispara evento de teste pra validar conectividade. */\n test(id: string): Promise<WebhookTestResult>;\n}\n\n/**\n * Verifica assinatura HMAC SHA-256 de payload de webhook recebido pelo\n * produto consumer. Constant-time compare pra resistir a timing attack.\n *\n * @param payload Corpo cru da request (string ou Buffer). NÃO use o objeto\n * parseado — JSON.stringify pode diferir do que foi assinado.\n * @param signature Header `X-Neetru-Signature` recebido (formato `sha256=<hex>`).\n * @param secret Secret registrado em `webhooks.register({ secret })`.\n * @returns true se assinatura confere, false caso contrário.\n *\n * @example\n * ```ts\n * // Express handler\n * app.post('/webhooks/neetru', express.raw({ type: 'application/json' }), (req, res) => {\n * const sig = req.header('X-Neetru-Signature');\n * if (!verifyWebhookSignature(req.body, sig, process.env.WEBHOOK_SECRET!)) {\n * return res.status(401).end();\n * }\n * const event = JSON.parse(req.body.toString('utf8'));\n * // ... handle event\n * res.json({ ok: true });\n * });\n * ```\n */\nexport function verifyWebhookSignature(\n payload: string | Uint8Array,\n signature: string | null | undefined,\n secret: string,\n): boolean {\n if (!signature || !secret) return false;\n // Aceita \"sha256=<hex>\" ou \"<hex>\" cru.\n const sigHex = signature.startsWith('sha256=') ? signature.slice(7) : signature;\n if (!/^[0-9a-f]+$/i.test(sigHex)) return false;\n\n // Crypto API: Node tem `node:crypto`, browsers têm WebCrypto. Aqui usamos\n // node:crypto (SDK roda majoritariamente server-side em produto Node). Se\n // o consumer for browser puro precisando verificar, basta importar o\n // namespace direto e usar WebCrypto — não é o caso típico, então não\n // pagamos o custo de bundle.\n let nodeCrypto: typeof import('node:crypto');\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n nodeCrypto = require('node:crypto');\n } catch {\n if (typeof console !== 'undefined') {\n console.warn(\n '[neetru-sdk] verifyWebhookSignature requires Node crypto. In browser, use WebCrypto subtle.verify directly.',\n );\n }\n return false;\n }\n\n const computed = nodeCrypto.createHmac('sha256', secret).update(payload).digest('hex');\n const a = Buffer.from(computed, 'hex');\n const b = Buffer.from(sigHex.toLowerCase(), 'hex');\n if (a.length !== b.length) return false;\n return nodeCrypto.timingSafeEqual(a, b);\n}\n\n// ─── HTTP impl ──────────────────────────────────────────────────────────────\n\nconst VALID_EVENTS: readonly WebhookEvent[] = [\n 'subscription.activated',\n 'subscription.cancelled',\n 'subscription.payment_failed',\n 'subscription.trial_ending',\n 'usage.quota_exceeded',\n 'account.suspended',\n 'account.reactivated',\n 'support.ticket_replied',\n];\n\nfunction toEndpoint(raw: unknown): WebhookEndpoint {\n if (!raw || typeof raw !== 'object') {\n throw new NeetruError('invalid_response', 'Webhook response is not an object');\n }\n const r = raw as Record<string, unknown>;\n if (typeof r.id !== 'string') {\n throw new NeetruError('invalid_response', 'Webhook missing id');\n }\n return {\n id: r.id,\n url: typeof r.url === 'string' ? r.url : '',\n events: Array.isArray(r.events)\n ? (r.events as unknown[]).filter((e): e is WebhookEvent =>\n VALID_EVENTS.includes(e as WebhookEvent),\n )\n : [],\n hasSecret: r.hasSecret === true,\n status:\n r.status === 'active' || r.status === 'degraded' || r.status === 'disabled'\n ? r.status\n : 'active',\n lastDeliveryAt: typeof r.lastDeliveryAt === 'string' ? r.lastDeliveryAt : undefined,\n consecutiveFailures:\n typeof r.consecutiveFailures === 'number' ? r.consecutiveFailures : undefined,\n createdAt: typeof r.createdAt === 'string' ? r.createdAt : new Date().toISOString(),\n };\n}\n\nfunction validateInput(input: RegisterWebhookInput): void {\n if (!input.url || typeof input.url !== 'string') {\n throw new NeetruError('validation_failed', 'url é obrigatória');\n }\n try {\n const parsed = new URL(input.url);\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n throw new Error('invalid protocol');\n }\n // Em prod, http: é warning (não bloqueia) — testes locais podem usar\n } catch {\n throw new NeetruError('validation_failed', `url inválida: ${input.url}`);\n }\n if (!Array.isArray(input.events) || input.events.length === 0) {\n throw new NeetruError('validation_failed', 'events deve ter pelo menos 1 evento');\n }\n for (const ev of input.events) {\n if (!VALID_EVENTS.includes(ev)) {\n throw new NeetruError('validation_failed', `evento desconhecido: ${ev}`);\n }\n }\n if (input.secret !== undefined && input.secret.length < 16) {\n throw new NeetruError('validation_failed', 'secret deve ter ≥16 chars (recomendado 32+)');\n }\n}\n\nexport function createWebhooksNamespace(config: ResolvedConfig): WebhooksNamespace {\n return {\n async register(input) {\n validateInput(input);\n const raw = await httpRequest<unknown>(config, {\n method: 'POST',\n path: '/api/sdk/v1/webhooks',\n body: input,\n requireAuth: true,\n });\n return toEndpoint(raw);\n },\n async list() {\n const raw = await httpRequest<{ endpoints?: unknown[] }>(config, {\n method: 'GET',\n path: '/api/sdk/v1/webhooks',\n requireAuth: true,\n });\n const list = Array.isArray(raw?.endpoints) ? raw.endpoints : [];\n return list.map(toEndpoint);\n },\n async unregister(id) {\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\n await httpRequest<unknown>(config, {\n method: 'DELETE',\n path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}`,\n requireAuth: true,\n });\n return { ok: true };\n },\n async test(id) {\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\n const raw = await httpRequest<unknown>(config, {\n method: 'POST',\n path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}/test`,\n requireAuth: true,\n });\n if (!raw || typeof raw !== 'object') {\n return { ok: false, error: 'invalid response' };\n }\n const r = raw as Record<string, unknown>;\n return {\n ok: r.ok === true,\n statusCode: typeof r.statusCode === 'number' ? r.statusCode : undefined,\n durationMs: typeof r.durationMs === 'number' ? r.durationMs : undefined,\n error: typeof r.error === 'string' ? r.error : undefined,\n };\n },\n };\n}\n\n// ─── Mock impl (dev / tests) ────────────────────────────────────────────────\n\nexport class MockWebhooks implements WebhooksNamespace {\n private endpoints = new Map<string, WebhookEndpoint>();\n private nextId = 1;\n\n async register(input: RegisterWebhookInput): Promise<WebhookEndpoint> {\n validateInput(input);\n const id = `mock_wh_${this.nextId++}`;\n const endpoint: WebhookEndpoint = {\n id,\n url: input.url,\n events: input.events,\n hasSecret: !!input.secret,\n status: 'active',\n createdAt: new Date().toISOString(),\n };\n this.endpoints.set(id, endpoint);\n return endpoint;\n }\n\n async list(): Promise<WebhookEndpoint[]> {\n return [...this.endpoints.values()];\n }\n\n async unregister(id: string): Promise<{ ok: true }> {\n if (!this.endpoints.has(id)) {\n throw new NeetruError('not_found', `Webhook ${id} não encontrado`);\n }\n this.endpoints.delete(id);\n return { ok: true };\n }\n\n async test(id: string): Promise<WebhookTestResult> {\n if (!this.endpoints.has(id)) {\n throw new NeetruError('not_found', `Webhook ${id} não encontrado`);\n }\n return { ok: true, statusCode: 200, durationMs: 42 };\n }\n}\n","/**\n * Notifications namespace (v1.2) — produtos SaaS enviam notificações in-app\n * pros SEUS usuários (distinto das `notifications/` staff-only do Core).\n *\n * Caso típico: produto gestovendas notifica usuário \"Pedido #X recebido\" no\n * portal sem precisar manter a própria coleção Firestore.\n *\n * Schema isolado por produto: `product_user_notifications/{productId}/{notifId}`.\n * Owner Neetru não vê o conteúdo (privacidade do produto), mas o Core\n * armazena + serve a leitura. Produto pode também listar via SDK.\n *\n * Endpoints REST (em prod):\n * - `POST /api/sdk/v1/notifications` — produto envia\n * - `GET /api/sdk/v1/notifications/user/{userId}` — produto lista do user\n * - `POST /api/sdk/v1/notifications/{id}/read` — user marca lida (proxy)\n * - `POST /api/sdk/v1/notifications/{id}/dismiss` — user descarta (proxy)\n *\n * Severidade canônica: `info | success | warning | error`.\n *\n * Mock em `NEETRU_ENV=dev`: in-memory.\n */\nimport { NeetruError } from './errors';\nimport { httpRequest } from './http';\nimport type { ResolvedConfig } from './types';\n\nexport type ProductNotificationSeverity =\n | 'info'\n | 'success'\n | 'warning'\n | 'error';\n\nexport interface ProductNotification {\n id: string;\n /** UID do usuário final (do produto, não staff Neetru). */\n userId: string;\n /** Identificador semântico do evento (ex: `order.received`). */\n kind: string;\n severity: ProductNotificationSeverity;\n title: string;\n body?: string;\n /** Link opcional pra ação. */\n link?: string;\n /** Metadata livre (serializável). */\n metadata?: Record<string, string | number | boolean | null>;\n createdAt: string;\n /** ISO quando user marcou lida. */\n readAt?: string;\n /** ISO quando user descartou. */\n dismissedAt?: string;\n}\n\nexport interface SendNotificationInput {\n userId: string;\n kind: string;\n title: string;\n severity?: ProductNotificationSeverity;\n body?: string;\n link?: string;\n metadata?: Record<string, string | number | boolean | null>;\n /**\n * Dedup — se já existir notificação com mesmo fingerprint dentro de 24h,\n * NÃO cria duplicata. Útil pra evitar spam quando webhook reentrega.\n */\n fingerprint?: string;\n}\n\nexport interface ListNotificationsOptions {\n /** Inclui notificações dismissed (default false). */\n includeDismissed?: boolean;\n /** Filtro por unread. */\n onlyUnread?: boolean;\n /** Máx itens (default 50, máx 200). */\n limit?: number;\n}\n\nexport interface NotificationsNamespace {\n /** Produto envia uma notificação pra um usuário do produto. */\n send(input: SendNotificationInput): Promise<ProductNotification>;\n /** Lista notificações de um usuário. */\n list(\n userId: string,\n options?: ListNotificationsOptions,\n ): Promise<ProductNotification[]>;\n /** Marca como lida. */\n markRead(id: string): Promise<{ ok: true }>;\n /** Descarta. */\n dismiss(id: string): Promise<{ ok: true }>;\n}\n\n// ─── HTTP impl ──────────────────────────────────────────────────────────────\n\nconst VALID_SEVERITIES: readonly ProductNotificationSeverity[] = [\n 'info',\n 'success',\n 'warning',\n 'error',\n];\n\nfunction toNotification(raw: unknown): ProductNotification {\n if (!raw || typeof raw !== 'object') {\n throw new NeetruError('invalid_response', 'Notification response is not an object');\n }\n const r = raw as Record<string, unknown>;\n if (typeof r.id !== 'string') {\n throw new NeetruError('invalid_response', 'Notification missing id');\n }\n const sev = VALID_SEVERITIES.includes(r.severity as ProductNotificationSeverity)\n ? (r.severity as ProductNotificationSeverity)\n : 'info';\n return {\n id: r.id,\n userId: typeof r.userId === 'string' ? r.userId : '',\n kind: typeof r.kind === 'string' ? r.kind : 'unknown',\n severity: sev,\n title: typeof r.title === 'string' ? r.title : '',\n body: typeof r.body === 'string' ? r.body : undefined,\n link: typeof r.link === 'string' ? r.link : undefined,\n metadata:\n r.metadata && typeof r.metadata === 'object'\n ? (r.metadata as Record<string, string | number | boolean | null>)\n : undefined,\n createdAt: typeof r.createdAt === 'string' ? r.createdAt : new Date().toISOString(),\n readAt: typeof r.readAt === 'string' ? r.readAt : undefined,\n dismissedAt: typeof r.dismissedAt === 'string' ? r.dismissedAt : undefined,\n };\n}\n\nfunction validateInput(input: SendNotificationInput): void {\n if (!input.userId) throw new NeetruError('validation_failed', 'userId obrigatório');\n if (!input.kind) throw new NeetruError('validation_failed', 'kind obrigatório');\n if (!input.title) throw new NeetruError('validation_failed', 'title obrigatório');\n if (input.severity && !VALID_SEVERITIES.includes(input.severity)) {\n throw new NeetruError(\n 'validation_failed',\n `severity inválida: ${input.severity} (use ${VALID_SEVERITIES.join('|')})`,\n );\n }\n if (input.title.length > 200) {\n throw new NeetruError('validation_failed', 'title máx 200 chars');\n }\n if (input.body && input.body.length > 2000) {\n throw new NeetruError('validation_failed', 'body máx 2000 chars');\n }\n}\n\nexport function createNotificationsNamespace(\n config: ResolvedConfig,\n): NotificationsNamespace {\n return {\n async send(input) {\n validateInput(input);\n const raw = await httpRequest<unknown>(config, {\n method: 'POST',\n path: '/api/sdk/v1/notifications',\n body: input,\n requireAuth: true,\n });\n return toNotification(raw);\n },\n async list(userId, options) {\n if (!userId) throw new NeetruError('validation_failed', 'userId obrigatório');\n const params = new URLSearchParams();\n if (options?.includeDismissed) params.set('includeDismissed', 'true');\n if (options?.onlyUnread) params.set('onlyUnread', 'true');\n if (options?.limit) {\n params.set('limit', Math.min(Math.max(1, options.limit), 200).toString());\n }\n const qs = params.toString();\n const raw = await httpRequest<{ notifications?: unknown[] }>(config, {\n method: 'GET',\n path: `/api/sdk/v1/notifications/user/${encodeURIComponent(userId)}${qs ? `?${qs}` : ''}`,\n requireAuth: true,\n });\n const list = Array.isArray(raw?.notifications) ? raw.notifications : [];\n return list.map(toNotification);\n },\n async markRead(id) {\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\n await httpRequest<unknown>(config, {\n method: 'POST',\n path: `/api/sdk/v1/notifications/${encodeURIComponent(id)}/read`,\n requireAuth: true,\n });\n return { ok: true };\n },\n async dismiss(id) {\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\n await httpRequest<unknown>(config, {\n method: 'POST',\n path: `/api/sdk/v1/notifications/${encodeURIComponent(id)}/dismiss`,\n requireAuth: true,\n });\n return { ok: true };\n },\n };\n}\n\n// ─── Mock impl ──────────────────────────────────────────────────────────────\n\nexport class MockNotifications implements NotificationsNamespace {\n private notifications = new Map<string, ProductNotification>();\n private nextId = 1;\n\n async send(input: SendNotificationInput): Promise<ProductNotification> {\n validateInput(input);\n // Dedup por fingerprint: se já existe um com mesmo fingerprint < 24h, retorna ele.\n if (input.fingerprint) {\n const dayAgo = Date.now() - 86_400_000;\n for (const existing of this.notifications.values()) {\n const meta = existing.metadata ?? {};\n if (\n meta.fingerprint === input.fingerprint &&\n existing.userId === input.userId &&\n new Date(existing.createdAt).getTime() > dayAgo\n ) {\n return existing;\n }\n }\n }\n const id = `mock_notif_${this.nextId++}`;\n const notif: ProductNotification = {\n id,\n userId: input.userId,\n kind: input.kind,\n severity: input.severity ?? 'info',\n title: input.title,\n body: input.body,\n link: input.link,\n metadata: input.fingerprint\n ? { ...(input.metadata ?? {}), fingerprint: input.fingerprint }\n : input.metadata,\n createdAt: new Date().toISOString(),\n };\n this.notifications.set(id, notif);\n return notif;\n }\n\n async list(\n userId: string,\n options?: ListNotificationsOptions,\n ): Promise<ProductNotification[]> {\n if (!userId) throw new NeetruError('validation_failed', 'userId obrigatório');\n const limit = Math.min(Math.max(1, options?.limit ?? 50), 200);\n return [...this.notifications.values()]\n .filter((n) => n.userId === userId)\n .filter((n) => options?.includeDismissed || !n.dismissedAt)\n .filter((n) => !options?.onlyUnread || !n.readAt)\n .sort((a, b) => b.createdAt.localeCompare(a.createdAt))\n .slice(0, limit);\n }\n\n async markRead(id: string): Promise<{ ok: true }> {\n const n = this.notifications.get(id);\n if (!n) throw new NeetruError('not_found', `Notification ${id} não encontrada`);\n if (!n.readAt) {\n n.readAt = new Date().toISOString();\n this.notifications.set(id, n);\n }\n return { ok: true };\n }\n\n async dismiss(id: string): Promise<{ ok: true }> {\n const n = this.notifications.get(id);\n if (!n) throw new NeetruError('not_found', `Notification ${id} não encontrada`);\n if (!n.dismissedAt) {\n n.dismissedAt = new Date().toISOString();\n this.notifications.set(id, n);\n }\n return { ok: true };\n }\n}\n","/**\n * Mocks determinísticos do SDK — overridáveis em tests do consumer ou\n * ativados automaticamente quando `NEETRU_ENV=dev`.\n *\n * Nada aqui faz I/O. Tudo é puro/sincrono/in-memory. Compat total com\n * runtimes browser/Node/Edge — sem `node:` builtins.\n *\n * Cada mock implementa o mesmo namespace interface das implementações reais\n * (`AuthNamespace`, `UsageNamespace`, `SupportNamespace`) — caller pode\n * substituir 1:1 sem branching.\n *\n * @example\n * ```ts\n * import { createNeetruClient, MockAuth } from '@neetru/sdk';\n *\n * const client = createNeetruClient({\n * mocks: { auth: new MockAuth({ uid: 'fake-user', email: 'x@x.com' }) },\n * });\n * ```\n */\n\nimport type {\n AuthNamespace,\n AuthStateListener,\n CreateTicketInput,\n DbCollectionRef,\n DbListOptions,\n DbNamespace,\n DbWhereFilter,\n EntitlementCheck,\n NeetruUser,\n SignInOptions,\n SupportNamespace,\n SupportTicket,\n UsageNamespace,\n UsageQuota,\n} from './types';\n\n// ─── User fixture default ──────────────────────────────────────────────────\n\n/**\n * User fixture determinístico — usado quando `NEETRU_ENV=dev` e nenhum mock\n * custom é injetado. Email/uid estáveis pra snapshot tests.\n */\nexport const DEV_FIXTURE_USER: NeetruUser = Object.freeze({\n uid: 'dev-fixture-uid-0001',\n email: 'dev@neetru.local',\n emailVerified: true,\n displayName: 'Dev Fixture',\n isCustomer: true,\n isStaff: false,\n}) as NeetruUser;\n\n// ─── MockAuth ──────────────────────────────────────────────────────────────\n\n/**\n * Implementação in-memory do `AuthNamespace`. signIn marca o user como\n * logado; signOut limpa. onAuthStateChanged dispara callback síncrono no\n * subscribe + a cada mudança.\n */\nexport class MockAuth implements AuthNamespace {\n private _user: NeetruUser | null;\n private _listeners: Set<AuthStateListener>;\n\n constructor(initialUser: NeetruUser | null = null) {\n this._user = initialUser;\n this._listeners = new Set();\n }\n\n async signIn(_options?: SignInOptions): Promise<NeetruUser> {\n // Mock: apenas marca user como logado (usa fixture se não havia).\n if (!this._user) this._user = { ...DEV_FIXTURE_USER };\n this._notify();\n return this._user;\n }\n\n async signOut(): Promise<void> {\n this._user = null;\n this._notify();\n }\n\n getUser(): NeetruUser | null {\n return this._user;\n }\n\n onAuthStateChanged(listener: AuthStateListener): () => void {\n this._listeners.add(listener);\n // Dispara imediatamente com estado atual (espelha API Firebase Auth).\n try {\n listener(this._user);\n } catch {\n // Callback do consumer não pode quebrar o subscribe.\n }\n return () => {\n this._listeners.delete(listener);\n };\n }\n\n /** Helper de tests — força um user state arbitrário. */\n __setUser(user: NeetruUser | null): void {\n this._user = user;\n this._notify();\n }\n\n private _notify(): void {\n for (const l of this._listeners) {\n try {\n l(this._user);\n } catch {\n // ignore consumer errors\n }\n }\n }\n}\n\n// ─── MockUsage ─────────────────────────────────────────────────────────────\n\ninterface UsageRecord {\n event: string;\n properties?: Record<string, string | number | boolean | null>;\n timestamp: string;\n}\n\n/**\n * In-memory `UsageNamespace`. `track()` apenas acumula no array\n * `__getRecords()` (útil pra asserts em test). `getQuota()` retorna fixture\n * com `used = trackedCount` da metric.\n */\nexport class MockUsage implements UsageNamespace {\n private _records: UsageRecord[] = [];\n private _quotas: Map<string, UsageQuota>;\n /** v0.3 — counters in-memory pra `report()` / `check()`. */\n private _counters: Map<string, number> = new Map();\n\n constructor(initialQuotas: Record<string, UsageQuota> = {}) {\n this._quotas = new Map(Object.entries(initialQuotas));\n }\n\n async track(\n event: string,\n properties?: Record<string, string | number | boolean | null>,\n ): Promise<{ ok: true }> {\n this._records.push({\n event,\n properties,\n timestamp: new Date().toISOString(),\n });\n return { ok: true };\n }\n\n async getQuota(metric: string): Promise<UsageQuota> {\n const existing = this._quotas.get(metric);\n if (existing) return existing;\n return {\n metric,\n used: this._records.filter((r) => r.event === metric).length,\n limit: -1, // unlimited em mock por default\n plan: 'mock',\n };\n }\n\n /** v0.3 — Mock report incrementa o counter local. */\n async report(\n resource: string,\n qty: number = 1,\n _options?: { productId?: string; tenantId?: string },\n ): Promise<{\n ok: true;\n counterId?: string;\n value?: number;\n limit?: number;\n remaining?: number;\n status?: string;\n }> {\n if (!resource) throw new Error('resource required');\n const safeQty = Number.isFinite(qty) && qty > 0 ? Math.floor(qty) : 1;\n const existing = this._counters.get(resource) ?? 0;\n const next = existing + safeQty;\n this._counters.set(resource, next);\n const limitFixture = this._quotas.get(resource);\n const limit = limitFixture?.limit ?? -1;\n return {\n ok: true,\n counterId: `mock_${resource}`,\n value: next,\n limit,\n remaining: limit < 0 ? -1 : Math.max(0, limit - next),\n status: limit > 0 && next >= limit ? 'read_only_overlimit' : 'ok',\n };\n }\n\n /** v0.3 — Mock check usa quotas + counters in-memory. */\n async check(\n resource: string,\n _options?: { productId?: string; tenantId?: string },\n ): Promise<{\n allowed: boolean;\n reason?: string;\n remaining?: number;\n limit?: number;\n planId?: string | null;\n planFeatures?: string[];\n }> {\n const quota = this._quotas.get(resource);\n const used = this._counters.get(resource) ?? 0;\n if (!quota) {\n return { allowed: true, reason: 'granted', limit: -1, remaining: -1 };\n }\n const remaining = quota.limit < 0 ? -1 : Math.max(0, quota.limit - used);\n if (remaining === 0) {\n return {\n allowed: false,\n reason: 'limit_exceeded',\n limit: quota.limit,\n remaining: 0,\n };\n }\n return {\n allowed: true,\n reason: 'granted',\n limit: quota.limit,\n remaining,\n };\n }\n\n /** Test helper. */\n __getRecords(): readonly UsageRecord[] {\n return [...this._records];\n }\n /** Test helper — substitui quota fixture. */\n __setQuota(metric: string, quota: UsageQuota): void {\n this._quotas.set(metric, quota);\n }\n /** Test helper — limpa estado. */\n __reset(): void {\n this._records = [];\n this._quotas.clear();\n this._counters.clear();\n }\n}\n\n// ─── MockSupport ───────────────────────────────────────────────────────────\n\n/**\n * In-memory `SupportNamespace`. createTicket gera ID `mock-ticket-{n}`;\n * listMyTickets retorna todos criados (FIFO). Sequência por instância\n * (evita poluição cross-test do estado de módulo).\n */\nexport class MockSupport implements SupportNamespace {\n private _tickets: SupportTicket[] = [];\n private _ticketSeq = 0;\n\n async createTicket(input: CreateTicketInput): Promise<SupportTicket> {\n if (!input?.subject) throw new Error('subject required');\n if (!input?.message) throw new Error('message required');\n const ticket: SupportTicket = {\n id: `mock-ticket-${++this._ticketSeq}`,\n subject: input.subject,\n message: input.message,\n severity: input.severity ?? 'normal',\n status: 'open',\n createdAt: new Date().toISOString(),\n productSlug: input.productSlug,\n };\n this._tickets.push(ticket);\n return ticket;\n }\n\n async listMyTickets(): Promise<SupportTicket[]> {\n return [...this._tickets];\n }\n\n /** Test helper. */\n __reset(): void {\n this._tickets = [];\n this._ticketSeq = 0;\n }\n}\n\n// ─── MockEntitlements ──────────────────────────────────────────────────────\n\n/**\n * In-memory entitlements. Por default `allowed=true` em tudo (dev convém).\n * Use `__deny(slug, feature)` em tests pra simular bloqueio.\n */\nexport class MockEntitlements {\n private _denied: Set<string> = new Set();\n\n async check(productSlug: string, feature: string): Promise<boolean> {\n return !this._denied.has(`${productSlug}:${feature}`);\n }\n\n async checkDetailed(productSlug: string, feature: string): Promise<EntitlementCheck> {\n const allowed = await this.check(productSlug, feature);\n return {\n allowed,\n productSlug,\n feature,\n reason: allowed ? 'granted' : 'mock_denied',\n };\n }\n\n /** Test helper. */\n __deny(productSlug: string, feature: string): void {\n this._denied.add(`${productSlug}:${feature}`);\n }\n /** Test helper. */\n __reset(): void {\n this._denied.clear();\n }\n}\n\n// ─── MockDb (v0.3) ─────────────────────────────────────────────────────────\n\n/**\n * In-memory `DbNamespace`. Cada `collection(name)` aponta para um Map; ops\n * são totalmente síncronas (mas API await-friendly).\n *\n * Útil para testar produtos consumidores sem rodar Core REST.\n */\nexport class MockDb implements DbNamespace {\n private _store: Map<string, Map<string, Record<string, unknown>>> = new Map();\n private _fixtures: Map<string, Record<string, Record<string, unknown>>>;\n\n constructor(initialFixtures: Record<string, Record<string, Record<string, unknown>>> = {}) {\n this._fixtures = new Map(Object.entries(initialFixtures));\n }\n\n collection(name: string): DbCollectionRef {\n const _store = this._store;\n const _fixtures = this._fixtures;\n if (!_store.has(name)) {\n const init = _fixtures.get(name);\n _store.set(\n name,\n init ? new Map(Object.entries(init)) : new Map(),\n );\n }\n const coll = _store.get(name)!;\n\n const matchesFilter = (\n doc: Record<string, unknown>,\n f: DbWhereFilter,\n ): boolean => {\n const v = doc[f.field];\n switch (f.op) {\n case '==':\n return v === f.value;\n case '!=':\n return v !== f.value;\n case '<':\n return typeof v === 'number' && typeof f.value === 'number' && v < f.value;\n case '<=':\n return typeof v === 'number' && typeof f.value === 'number' && v <= f.value;\n case '>':\n return typeof v === 'number' && typeof f.value === 'number' && v > f.value;\n case '>=':\n return typeof v === 'number' && typeof f.value === 'number' && v >= f.value;\n case 'in':\n return Array.isArray(f.value) && (f.value as unknown[]).includes(v);\n default:\n return true;\n }\n };\n\n let autoSeq = 0;\n\n return {\n async list<T = Record<string, unknown>>(opts?: DbListOptions): Promise<T[]> {\n let items = Array.from(coll.values());\n if (opts?.where && opts.where.length > 0) {\n items = items.filter((doc) =>\n (opts.where as DbWhereFilter[]).every((f) => matchesFilter(doc, f)),\n );\n }\n if (opts?.limit !== undefined) items = items.slice(0, opts.limit);\n return items as T[];\n },\n async get<T = Record<string, unknown>>(id: string): Promise<T | null> {\n return (coll.get(id) as T | undefined) ?? null;\n },\n async add(data: Record<string, unknown>): Promise<{ ok: true; id: string }> {\n const id = `mock-${++autoSeq}-${Math.random().toString(36).slice(2, 8)}`;\n coll.set(id, { ...data, id });\n return { ok: true, id };\n },\n async set(id: string, data: Record<string, unknown>): Promise<{ ok: true }> {\n coll.set(id, { ...data, id });\n return { ok: true };\n },\n async update(id: string, data: Record<string, unknown>): Promise<{ ok: true }> {\n const cur = coll.get(id);\n if (!cur) {\n // mock-friendly: cria se não existir (mimic Firestore set merge).\n coll.set(id, { ...data, id });\n } else {\n coll.set(id, { ...cur, ...data });\n }\n return { ok: true };\n },\n async remove(id: string): Promise<{ ok: true }> {\n coll.delete(id);\n return { ok: true };\n },\n };\n }\n\n /** Test helper — substitui fixture inteira de uma collection. */\n __setFixture(name: string, items: Record<string, Record<string, unknown>>): void {\n this._store.set(name, new Map(Object.entries(items)));\n }\n\n /** Test helper — reset total. */\n __reset(): void {\n this._store.clear();\n }\n}\n","/**\n * Factory `createNeetruClient` + namespace `auth` (v0.2).\n *\n * Responsabilidades:\n * - Factory: resolver `apiKey`, `baseUrl`, `fetch`, `env`, e montar handle\n * imutável com namespaces (`auth`, `catalog`, `entitlements`, `telemetry`,\n * `usage`, `support`).\n * - Auth namespace: signIn (OIDC redirect ou mock dev), signOut, getUser,\n * onAuthStateChanged.\n *\n * v0.1 expunha apenas Bearer estático (long-lived `nrt_*_*`). v0.2 adiciona\n * camada de auth para SaaS produtos consumirem identity Neetru via OIDC\n * (auth.neetru.com já live).\n */\nimport { NeetruError } from './errors';\nimport {\n DEFAULT_BASE_URL,\n type AuthNamespace,\n type AuthStateListener,\n type NeetruClient,\n type NeetruClientConfig,\n type NeetruEnv,\n type NeetruUser,\n type ResolvedConfig,\n type SignInOptions,\n} from './types';\nimport { createCatalogNamespace } from './catalog';\nimport { createEntitlementsNamespace } from './entitlements';\nimport { createTelemetryNamespace } from './telemetry';\nimport { createUsageNamespace } from './usage';\nimport { createSupportNamespace } from './support';\nimport { createDbNamespace } from './db';\nimport { createCheckoutNamespace } from './checkout';\nimport { createWebhooksNamespace, MockWebhooks } from './webhooks';\nimport { createNotificationsNamespace, MockNotifications } from './notifications';\nimport { DEV_FIXTURE_USER, MockAuth, MockDb, MockUsage, MockSupport, MockEntitlements } from './mocks';\n\n/**\n * Lê `NEETRU_API_KEY` do ambiente Node de forma defensiva. Em browser,\n * `process` não existe — try/catch evita ReferenceError. Em Edge runtimes\n * que polyfillam `process` parcialmente, optional chaining absorve undefined.\n */\nfunction readEnvApiKey(): string | undefined {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const proc = (globalThis as any).process;\n const val = proc?.env?.NEETRU_API_KEY;\n return typeof val === 'string' && val.length > 0 ? val : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolve `NEETRU_ENV` de várias fontes:\n * 1. Config arg `env`.\n * 2. `process.env.NEETRU_ENV` em Node.\n * 3. `globalThis.NEETRU_ENV` em browser/Edge (se setado por bundler).\n * 4. Default `prod`.\n */\nfunction resolveEnv(configEnv?: NeetruEnv): NeetruEnv {\n if (configEnv) return configEnv;\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const proc = (globalThis as any).process;\n const val = proc?.env?.NEETRU_ENV;\n if (val === 'dev' || val === 'workspace' || val === 'prod') return val;\n } catch {\n /* ignore */\n }\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const g = (globalThis as any).NEETRU_ENV;\n if (g === 'dev' || g === 'workspace' || g === 'prod') return g;\n } catch {\n /* ignore */\n }\n return 'prod';\n}\n\n// ─── Real OIDC auth namespace ──────────────────────────────────────────────\n\n/**\n * Implementação real do namespace auth — redireciona pra auth.neetru.com\n * em signIn, lê id_token do localStorage (se browser) ou do env em Node.\n *\n * Storage key: `neetru_id_token`. JWT decoded inline (sem verifyJWT — backend\n * já validou; SDK só lê claims pra populate getUser).\n */\nfunction createOidcAuthNamespace(config: ResolvedConfig): AuthNamespace {\n const STORAGE_KEY = 'neetru_id_token';\n const listeners = new Set<AuthStateListener>();\n let cachedUser: NeetruUser | null = null;\n\n function getStorage(): Storage | null {\n try {\n return typeof globalThis.localStorage !== 'undefined' ? globalThis.localStorage : null;\n } catch {\n return null;\n }\n }\n\n function decodeJwtPayload(token: string): Record<string, unknown> | null {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n try {\n // base64url decode (browser/Node compat).\n const b64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');\n const pad = '='.repeat((4 - (b64.length % 4)) % 4);\n const decoded =\n typeof atob === 'function'\n ? atob(b64 + pad)\n : Buffer.from(b64 + pad, 'base64').toString('utf-8');\n return JSON.parse(decoded);\n } catch {\n return null;\n }\n }\n\n function tokenToUser(token: string): NeetruUser | null {\n const payload = decodeJwtPayload(token);\n if (!payload || typeof payload.sub !== 'string') return null;\n return {\n uid: payload.sub,\n email: typeof payload.email === 'string' ? payload.email : '',\n emailVerified: typeof payload.email_verified === 'boolean' ? payload.email_verified : undefined,\n displayName: typeof payload.name === 'string' ? payload.name : undefined,\n photoURL: typeof payload.picture === 'string' ? payload.picture : undefined,\n isStaff: payload.is_staff === true,\n isCustomer: payload.is_customer === true,\n tenantId: typeof payload.tenant_id === 'string' ? payload.tenant_id : undefined,\n ...payload,\n };\n }\n\n function loadCachedUser(): NeetruUser | null {\n if (cachedUser) return cachedUser;\n const storage = getStorage();\n if (!storage) return null;\n const token = storage.getItem(STORAGE_KEY);\n if (!token) return null;\n cachedUser = tokenToUser(token);\n return cachedUser;\n }\n\n function notify(): void {\n for (const l of listeners) {\n try {\n l(cachedUser);\n } catch {\n /* ignore consumer errors */\n }\n }\n }\n\n return {\n async signIn(options?: SignInOptions): Promise<NeetruUser | void> {\n // Em browser, redireciona pro authorize endpoint do IdP (auth.neetru.com).\n // Fix audit 2026-05-15: antes apontava `api.neetru.com/oauth/authorize`\n // (404 — middleware só roteia /api/v1/oauth a partir de auth.neetru.com).\n // O issuer canônico é `auth.neetru.com` (vide PLATFORM_IDENTIDADE.md).\n if (typeof globalThis.location !== 'undefined' && typeof globalThis.location.assign === 'function') {\n const redirectUri = options?.redirectUri ?? globalThis.location.origin;\n const scope = options?.scope ?? 'openid profile email';\n const state = options?.postLoginRedirect ?? globalThis.location.href;\n // Deriva o host do IdP a partir do baseUrl: api.* → auth.*. Fallback:\n // override explícito por `globalThis.NEETRU_AUTH_URL` (testes / staging).\n const overrideAuthUrl =\n typeof (globalThis as { NEETRU_AUTH_URL?: string }).NEETRU_AUTH_URL === 'string'\n ? (globalThis as { NEETRU_AUTH_URL?: string }).NEETRU_AUTH_URL\n : null;\n const idpOrigin = overrideAuthUrl ?? config.baseUrl.replace(/^https?:\\/\\/api\\./, 'https://auth.');\n const url = new URL('/api/v1/oauth/authorize', idpOrigin);\n url.searchParams.set('response_type', 'code');\n url.searchParams.set('redirect_uri', redirectUri);\n url.searchParams.set('scope', scope);\n url.searchParams.set('state', state);\n if (config.apiKey) {\n // apiKey aqui age como client_id (formato `nrt_{client_id}_{secret}`).\n const clientId = config.apiKey.split('_')[1] ?? config.apiKey;\n url.searchParams.set('client_id', clientId);\n }\n globalThis.location.assign(url.toString());\n return;\n }\n // Não-browser sem mock — não dá pra signIn interativo.\n throw new NeetruError(\n 'invalid_config',\n 'auth.signIn requires a browser context or mocks. Use NEETRU_ENV=dev or pass mocks.auth.',\n );\n },\n\n async signOut(): Promise<void> {\n const storage = getStorage();\n if (storage) storage.removeItem(STORAGE_KEY);\n cachedUser = null;\n // Best-effort revoke no server. O endpoint canônico é\n // auth.neetru.com/api/v1/oauth/revoke (não api.neetru.com). Aplica a\n // mesma derivação api.* → auth.* usada no signIn().\n try {\n const overrideAuthUrl =\n typeof (globalThis as { NEETRU_AUTH_URL?: string }).NEETRU_AUTH_URL === 'string'\n ? (globalThis as { NEETRU_AUTH_URL?: string }).NEETRU_AUTH_URL\n : null;\n const idpOrigin =\n overrideAuthUrl ?? config.baseUrl.replace(/^https?:\\/\\/api\\./, 'https://auth.');\n await config.fetch(`${idpOrigin}/api/v1/oauth/revoke`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n });\n } catch {\n /* network failure non-fatal */\n }\n notify();\n },\n\n getUser(): NeetruUser | null {\n return loadCachedUser();\n },\n\n onAuthStateChanged(listener: AuthStateListener): () => void {\n listeners.add(listener);\n try {\n listener(loadCachedUser());\n } catch {\n /* ignore */\n }\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\n/**\n * Cria uma instância imutável do cliente Neetru SDK.\n *\n * @example\n * ```ts\n * import { createNeetruClient } from '@neetru/sdk';\n *\n * const client = createNeetruClient({\n * apiKey: 'nrt_a1b2c3d4_xY9z...',\n * });\n *\n * const { products } = await client.catalog.list();\n * const can = await client.entitlements.check('neetru-pulse', 'export-pdf');\n * await client.telemetry.event({ name: 'report_exported' });\n * await client.usage.track('api_call', { route: '/x' });\n * await client.support.createTicket({ subject: 'help', message: '...' });\n * ```\n *\n * @throws {NeetruError} `invalid_config` se fetch não disponível no runtime.\n */\nexport function createNeetruClient(config: NeetruClientConfig = {}): NeetruClient {\n const fetchImpl = config.fetch ?? globalThis.fetch;\n if (typeof fetchImpl !== 'function') {\n throw new NeetruError(\n 'invalid_config',\n 'fetch is not available in this runtime. Pass `fetch` explicitly to createNeetruClient.',\n );\n }\n\n const baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\n const apiKey = config.apiKey ?? readEnvApiKey();\n const env = resolveEnv(config.env);\n\n // `bind` garante `this` correto em runtimes que validam (ex: undici).\n const resolved: ResolvedConfig = Object.freeze({\n apiKey,\n baseUrl,\n fetch: fetchImpl.bind(globalThis),\n env,\n productId: config.productId,\n tenantId: config.tenantId,\n });\n\n // Em dev, sempre ativa mocks. Mocks explícitos sempre vencem.\n const isDev = env === 'dev';\n const auth = config.mocks?.auth ?? (isDev ? new MockAuth({ ...DEV_FIXTURE_USER }) : createOidcAuthNamespace(resolved));\n const usage = config.mocks?.usage ?? (isDev ? new MockUsage() : createUsageNamespace(resolved));\n const support = config.mocks?.support ?? (isDev ? new MockSupport() : createSupportNamespace(resolved));\n const entitlements = config.mocks?.entitlements ?? (isDev ? new MockEntitlements() : createEntitlementsNamespace(resolved));\n const db = config.mocks?.db ?? (isDev ? new MockDb() : createDbNamespace(resolved));\n const webhooks = config.mocks?.webhooks ?? (isDev ? new MockWebhooks() : createWebhooksNamespace(resolved));\n const notifications = config.mocks?.notifications ?? (isDev ? new MockNotifications() : createNotificationsNamespace(resolved));\n\n const client: NeetruClient = Object.freeze({\n config: resolved,\n auth,\n catalog: createCatalogNamespace(resolved),\n entitlements,\n telemetry: createTelemetryNamespace(resolved),\n usage,\n support,\n db,\n checkout: createCheckoutNamespace(resolved),\n webhooks,\n notifications,\n });\n\n return client;\n}\n","/**\n * @neetru/sdk — biblioteca runtime para consumir o ecossistema Neetru.\n *\n * **v1.0.0 GA (2026-05-06)** — superfície pública estabilizada. A partir\n * desta versão, **breaking changes só em majors** (semver estrito).\n *\n * Namespaces estáveis (v1.0):\n * - `auth` — OIDC sign-in / sign-out + dev fixture user.\n * - `catalog` — produtos públicos (`list` / `get`).\n * - `entitlements` — verificação `(productSlug, feature)` → boolean / detalhado.\n * - `telemetry` — `event(...)` + `log(...)` per-product (Sprint 6).\n * - `usage` — `track` / `getQuota` / `report` / `check` (Sprint 7 metering canônico).\n * - `support` — `createTicket` / `listMyTickets`.\n * - `db` — coleções tenant-scoped (`list` / `get` / `set` / `add` / `update` / `remove`).\n *\n * Princípios:\n * - Vendor-neutral: a superfície pública não vaza Firebase/Stripe.\n * - Tree-shakable: ESM-first, sem side effects.\n * - Universal: funciona em browser, Node ≥18, Edge runtimes (usa fetch global).\n * - Erros tipados via NeetruError com .code / .status / .requestId.\n * - Dev mode: `NEETRU_ENV=dev` ativa mocks automáticos (auth fixture user,\n * usage in-memory, support fake list, db in-memory).\n *\n * Migration v0.3 → v1.0:\n * - Nenhuma breaking change. APIs v0.3 permanecem 100% compatíveis em v1.0.\n * - `initNeetru` (deprecated desde v0.2) **continua** funcionando em v1.0 mas\n * será removido em v2.0. Use `createNeetruClient` em código novo.\n *\n * Roadmap completo em `docs/PLAN_SDK_NEETRU.md` §10.\n */\n\n// ─── v0.2 API principal ──────────────────────────────────────────────────────\nexport { createNeetruClient } from './auth';\nexport { NeetruError, type NeetruErrorCode } from './errors';\nexport type {\n NeetruClient,\n NeetruClientConfig,\n ResolvedConfig,\n Product,\n ProductPlan,\n ProductStatus,\n CatalogListOptions,\n CatalogListResponse,\n EntitlementCheck,\n TelemetryEventInput,\n TelemetryEventAck,\n // v0.2\n AuthNamespace,\n AuthStateListener,\n CreateTicketInput,\n NeetruEnv,\n NeetruUser,\n SignInOptions,\n SupportNamespace,\n SupportSeverity,\n SupportStatus,\n SupportTicket,\n UsageEventInput,\n UsageNamespace,\n UsageQuota,\n // v0.3\n DbCollectionRef,\n DbNamespace,\n DbWhereFilter,\n DbListOptions,\n} from './types';\nexport { DEFAULT_BASE_URL } from './types';\n\n// ─── v0.2 — Mocks (overridáveis) ────────────────────────────────────────────\nexport {\n MockAuth,\n MockUsage,\n MockSupport,\n MockEntitlements,\n MockDb,\n DEV_FIXTURE_USER,\n} from './mocks';\n\n// ─── v1.1 — Checkout namespace ──────────────────────────────────────────────\nexport {\n MockCheckout,\n createCheckoutNamespace,\n type CheckoutNamespace,\n type CheckoutStartInput,\n type CheckoutStartResult,\n type CheckoutIntentInfo,\n type CheckoutIntentStatus,\n type CheckoutTenantType,\n} from './checkout';\n\n// ─── v1.2 — Webhooks namespace (outbound events Core → produto) ─────────────\nexport {\n MockWebhooks,\n createWebhooksNamespace,\n type WebhooksNamespace,\n type WebhookEvent,\n type WebhookEndpoint,\n type RegisterWebhookInput,\n type WebhookTestResult,\n} from './webhooks';\n\n// ─── v1.2 — Notifications namespace (produto → user) ────────────────────────\nexport {\n MockNotifications,\n createNotificationsNamespace,\n type NotificationsNamespace,\n type ProductNotification,\n type ProductNotificationSeverity,\n type SendNotificationInput,\n type ListNotificationsOptions,\n} from './notifications';\n\n// ─── Versão pinada ────────────────────────────────────────────────────────────\n/** Versão do SDK — exportada explicitamente pra detecção em runtime. */\nexport const VERSION = '1.2.0' as const;\n\n// ─── Compat v0.0.1 ────────────────────────────────────────────────────────────\n// `initNeetru` foi a primeira API exposta no scaffold. Preservada como alias\n// pra não quebrar early adopters internos. Marcada `@deprecated` desde v0.2;\n// SERÁ REMOVIDA EM v2.0.0 (segue convenção semver — descontinuação só em major).\nimport { createNeetruClient } from './auth';\nimport type { NeetruClientConfig } from './types';\n\n/**\n * @deprecated Use `createNeetruClient` em vez de `initNeetru`. Mantido por\n * compat com v0.0.1; **será removido em v2.0.0**.\n */\nexport function initNeetru(config: NeetruClientConfig & { apiUrl?: string }) {\n // v0.0.1 usava `apiUrl`; v0.1+ usa `baseUrl`. Mapeia se necessário.\n const { apiUrl, baseUrl, ...rest } = config;\n return createNeetruClient({ ...rest, baseUrl: baseUrl ?? apiUrl });\n}\n\n/**\n * @deprecated Use `NeetruClientConfig`. Será removido em v2.0.0.\n */\nexport type NeetruConfig = NeetruClientConfig & { apiUrl?: string };\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/auth.ts","../src/types.ts","../src/catalog.ts","../src/entitlements.ts","../src/telemetry.ts","../src/usage.ts","../src/support.ts","../src/db-errors.ts","../src/db/offline/query-engine.ts","../src/db/offline/local-store.ts","../src/db/offline/mutation-queue.ts","../src/db/offline/sync-engine.ts","../src/db/offline/conflict-resolver.ts","../src/db/offline/change-bus.ts","../src/db/offline/connectivity-monitor.ts","../src/db/offline/tab-coordinator.ts","../src/db/collection-ref.ts","../src/db/sql/lease.ts","../src/db/sql/sql-client.ts","../src/db/realtime/realtime-client.ts","../src/db/client-db.ts","../src/checkout.ts","../src/webhooks.ts","../src/notifications.ts","../src/mocks.ts","../src/index.ts"],"names":["NeetruError","err","message","RETRYABLE_CODES","openDB","httpRequest","VALID_SEVERITIES","validateInput"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * Erros tipados do SDK.\r\n *\r\n * Todo erro lançado pelo SDK estende `NeetruError` — caller pode discriminar\r\n * por `.code` (string estável) sem parsing de message.\r\n */\r\n\r\n/** Códigos de erro estáveis do SDK. Adicionar aqui requer minor bump. */\r\nexport type NeetruErrorCode =\r\n | 'invalid_config'\r\n | 'missing_api_key'\r\n | 'unauthorized'\r\n | 'forbidden'\r\n | 'not_found'\r\n | 'rate_limited'\r\n | 'validation_failed'\r\n | 'network_error'\r\n | 'invalid_response'\r\n | 'server_error'\r\n | 'unknown';\r\n\r\n/**\r\n * Erro tipado padrão do SDK. Sempre lançado em vez de Error genérico.\r\n *\r\n * @example\r\n * ```ts\r\n * try { await client.catalog.list(); }\r\n * catch (e) {\r\n * if (e instanceof NeetruError && e.code === 'rate_limited') retry();\r\n * }\r\n * ```\r\n */\r\nexport class NeetruError extends Error {\r\n public readonly code: NeetruErrorCode | string;\r\n public readonly status?: number;\r\n public readonly requestId?: string;\r\n\r\n constructor(\r\n code: NeetruErrorCode | string,\r\n message: string,\r\n status?: number,\r\n requestId?: string,\r\n ) {\r\n super(message);\r\n this.name = 'NeetruError';\r\n this.code = code;\r\n this.status = status;\r\n this.requestId = requestId;\r\n // Preserva o prototype chain ao herdar de Error (downlevel quirk de TS).\r\n Object.setPrototypeOf(this, NeetruError.prototype);\r\n }\r\n}\r\n","/**\r\n * HTTP transport interno do SDK.\r\n *\r\n * Responsabilidades:\r\n * - Construir URL absoluta a partir de `baseUrl` + path\r\n * - Injetar Bearer token quando `requireAuth=true`\r\n * - Mapear status HTTP → `NeetruError` com `code` estável\r\n * - Parse defensivo de JSON (não lança em body vazio em 204)\r\n * - Retry/backoff exponencial em `rate_limited` (429), `server_error` (5xx)\r\n * e `network_error` (timeout/falha de rede). Honra `Retry-After` quando\r\n * presente. Default 2 retries (3 tentativas no total). Caller opta-out\r\n * com `retries: 0`.\r\n */\r\nimport { NeetruError, type NeetruErrorCode } from './errors';\r\nimport type { ResolvedConfig } from './types';\r\n\r\n/** Opções da request HTTP. */\r\nexport interface HttpRequestOptions {\r\n method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\r\n /** Path relativo (ex: `/api/v1/cli/catalog`). Concatenado a `baseUrl`. */\r\n path: string;\r\n /** Query string params (chave → valor primitivo). Valores `undefined` ignorados. */\r\n query?: Record<string, string | number | boolean | undefined>;\r\n /** Body JSON-serializável. Ignorado em GET/DELETE. */\r\n body?: unknown;\r\n /**\r\n * Se true, injeta `Authorization: Bearer <apiKey>`. Lança `missing_api_key`\r\n * se config.apiKey ausente. Default false.\r\n */\r\n requireAuth?: boolean;\r\n /** Cabeçalhos extras. */\r\n headers?: Record<string, string>;\r\n /**\r\n * Número de retries em códigos transientes (`rate_limited`, `server_error`,\r\n * `network_error`). Default 2 (= 3 tentativas total). Caller passa `0` pra\r\n * desativar (útil em operações não-idempotentes específicas).\r\n */\r\n retries?: number;\r\n}\r\n\r\nconst DEFAULT_RETRIES = 2;\r\nconst RETRYABLE_CODES = new Set<NeetruErrorCode>([\r\n 'rate_limited',\r\n 'server_error',\r\n 'network_error',\r\n]);\r\n\r\n/** Backoff exponencial com jitter ±20%. attempt: 0=primeira, 1=primeiro retry, ... */\r\nfunction backoffMs(attempt: number): number {\r\n const base = 200 * Math.pow(4, attempt); // 200ms, 800ms, 3.2s, ...\r\n const jitter = base * 0.2 * (Math.random() * 2 - 1);\r\n return Math.max(50, Math.round(base + jitter));\r\n}\r\n\r\n/**\r\n * Honra `Retry-After` header (segundos ou HTTP-date). Retorna ms ou null se\r\n * inválido. RFC 9110 §10.2.3.\r\n */\r\nfunction parseRetryAfter(value: string | null): number | null {\r\n if (!value) return null;\r\n const secs = Number(value);\r\n if (Number.isFinite(secs) && secs >= 0) return Math.round(secs * 1000);\r\n const dateMs = Date.parse(value);\r\n if (Number.isFinite(dateMs)) {\r\n const delta = dateMs - Date.now();\r\n if (delta > 0) return delta;\r\n }\r\n return null;\r\n}\r\n\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\n/** Mapeamento status → code estável do NeetruError. */\r\nfunction statusToCode(status: number): NeetruErrorCode {\r\n if (status === 401) return 'unauthorized';\r\n if (status === 403) return 'forbidden';\r\n if (status === 404) return 'not_found';\r\n if (status === 422 || status === 400) return 'validation_failed';\r\n if (status === 429) return 'rate_limited';\r\n if (status >= 500) return 'server_error';\r\n return 'unknown';\r\n}\r\n\r\nfunction buildUrl(baseUrl: string, path: string, query?: HttpRequestOptions['query']): string {\r\n // Trim trailing slash em base e leading em path pra evitar `//`.\r\n const base = baseUrl.replace(/\\/+$/, '');\r\n const p = path.startsWith('/') ? path : `/${path}`;\r\n const url = new URL(`${base}${p}`);\r\n if (query) {\r\n for (const [k, v] of Object.entries(query)) {\r\n if (v === undefined) continue;\r\n url.searchParams.set(k, String(v));\r\n }\r\n }\r\n return url.toString();\r\n}\r\n\r\n/** Parse JSON defensivo — retorna `undefined` em body vazio. */\r\nasync function safeJson(res: Response): Promise<unknown> {\r\n const text = await res.text();\r\n if (!text) return undefined;\r\n try {\r\n return JSON.parse(text);\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Executa request HTTP. Em sucesso retorna body parseado; em erro lança\r\n * `NeetruError` com `code` derivado do status. Aplica retry/backoff\r\n * automático em códigos transientes (rate_limited/server_error/network_error)\r\n * conforme `opts.retries` (default 2 = 3 tentativas).\r\n */\r\nexport async function httpRequest<T>(\r\n config: ResolvedConfig,\r\n opts: HttpRequestOptions,\r\n): Promise<T> {\r\n const method = opts.method ?? 'GET';\r\n const url = buildUrl(config.baseUrl, opts.path, opts.query);\r\n const maxRetries = opts.retries ?? DEFAULT_RETRIES;\r\n\r\n const headers: Record<string, string> = {\r\n accept: 'application/json',\r\n ...opts.headers,\r\n };\r\n\r\n if (opts.requireAuth) {\r\n if (!config.apiKey) {\r\n throw new NeetruError(\r\n 'missing_api_key',\r\n 'This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var.',\r\n );\r\n }\r\n headers.authorization = `Bearer ${config.apiKey}`;\r\n }\r\n\r\n // Body só é serializado uma vez — reusado entre tentativas.\r\n const bodyString =\r\n opts.body !== undefined && method !== 'GET' && method !== 'DELETE'\r\n ? JSON.stringify(opts.body)\r\n : undefined;\r\n if (bodyString !== undefined) {\r\n headers['content-type'] = 'application/json';\r\n }\r\n\r\n let lastError: NeetruError | null = null;\r\n\r\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\r\n const init: RequestInit = { method, headers };\r\n if (bodyString !== undefined) init.body = bodyString;\r\n // BUG-020 fix (2026-05-13): timeout default 30s. AbortSignal.timeout\r\n // requer Node 18+ ou browsers recentes.\r\n init.signal = AbortSignal.timeout(30_000);\r\n\r\n let res: Response;\r\n try {\r\n res = await config.fetch(url, init);\r\n } catch (err) {\r\n const message =\r\n err instanceof DOMException && err.name === 'TimeoutError'\r\n ? 'Network error: timeout after 30s'\r\n : `Network error: ${err instanceof Error ? err.message : 'fetch failed'}`;\r\n lastError = new NeetruError('network_error', message);\r\n if (attempt < maxRetries) {\r\n await sleep(backoffMs(attempt));\r\n continue;\r\n }\r\n throw lastError;\r\n }\r\n\r\n const requestId =\r\n res.headers.get('x-request-id') ?? res.headers.get('x-correlation-id') ?? undefined;\r\n\r\n if (res.ok) {\r\n const parsed = await safeJson(res);\r\n return parsed as T;\r\n }\r\n\r\n const body = (await safeJson(res)) as\r\n | { error?: { code?: string; message?: string } | string }\r\n | undefined;\r\n let code: string = statusToCode(res.status);\r\n let message = `HTTP ${res.status}`;\r\n if (body && typeof body === 'object' && 'error' in body) {\r\n const errField = body.error;\r\n if (typeof errField === 'string') {\r\n message = errField;\r\n } else if (errField && typeof errField === 'object') {\r\n if (typeof errField.code === 'string') code = errField.code;\r\n if (typeof errField.message === 'string') message = errField.message;\r\n }\r\n }\r\n const err = new NeetruError(code, message, res.status, requestId);\r\n lastError = err;\r\n\r\n const isRetryable = RETRYABLE_CODES.has(code as NeetruErrorCode);\r\n if (isRetryable && attempt < maxRetries) {\r\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\r\n const delay = retryAfter ?? backoffMs(attempt);\r\n await sleep(delay);\r\n continue;\r\n }\r\n throw err;\r\n }\r\n\r\n // Unreachable — loop sempre retorna ou lança. Safety net.\r\n throw lastError ?? new NeetruError('unknown', 'unexpected httpRequest exit');\r\n}\r\n","/**\r\n * Factory `createNeetruClient` + namespace `auth` (v0.2).\r\n *\r\n * Responsabilidades:\r\n * - Factory: resolver `apiKey`, `baseUrl`, `fetch`, `env`, e montar handle\r\n * imutável com namespaces (`auth`, `catalog`, `entitlements`, `telemetry`,\r\n * `usage`, `support`).\r\n * - Auth namespace: signIn (OIDC redirect ou mock dev), signOut, getUser,\r\n * onAuthStateChanged.\r\n *\r\n * v0.1 expunha apenas Bearer estático (long-lived `nrt_*_*`). v0.2 adiciona\r\n * camada de auth para SaaS produtos consumirem identity Neetru via OIDC\r\n * (auth.neetru.com já live).\r\n */\r\nimport { NeetruError } from './errors';\r\nimport {\r\n DEFAULT_BASE_URL,\r\n type AuthNamespace,\r\n type AuthStateListener,\r\n type NeetruClient,\r\n type NeetruClientConfig,\r\n type NeetruEnv,\r\n type NeetruUser,\r\n type ResolvedConfig,\r\n type SignInOptions,\r\n} from './types';\r\nimport { createCatalogNamespace } from './catalog';\r\nimport { createEntitlementsNamespace } from './entitlements';\r\nimport { createTelemetryNamespace } from './telemetry';\r\nimport { createUsageNamespace } from './usage';\r\nimport { createSupportNamespace } from './support';\r\nimport { createNeetruDb } from './db/client-db';\r\nimport { createCheckoutNamespace } from './checkout';\r\nimport { createWebhooksNamespace, MockWebhooks } from './webhooks';\r\nimport { createNotificationsNamespace, MockNotifications } from './notifications';\r\nimport { DEV_FIXTURE_USER, MockAuth, MockUsage, MockSupport, MockEntitlements } from './mocks';\r\n\r\n/**\r\n * Lê `NEETRU_API_KEY` do ambiente Node de forma defensiva. Em browser,\r\n * `process` não existe — try/catch evita ReferenceError. Em Edge runtimes\r\n * que polyfillam `process` parcialmente, optional chaining absorve undefined.\r\n */\r\nfunction readEnvApiKey(): string | undefined {\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const proc = (globalThis as any).process;\r\n const val = proc?.env?.NEETRU_API_KEY;\r\n return typeof val === 'string' && val.length > 0 ? val : undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Resolve `NEETRU_ENV` de várias fontes:\r\n * 1. Config arg `env`.\r\n * 2. `process.env.NEETRU_ENV` em Node.\r\n * 3. `globalThis.NEETRU_ENV` em browser/Edge (se setado por bundler).\r\n * 4. Default `prod`.\r\n */\r\nfunction resolveEnv(configEnv?: NeetruEnv): NeetruEnv {\r\n if (configEnv) return configEnv;\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const proc = (globalThis as any).process;\r\n const val = proc?.env?.NEETRU_ENV;\r\n if (val === 'dev' || val === 'workspace' || val === 'prod') return val;\r\n } catch {\r\n /* ignore */\r\n }\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const g = (globalThis as any).NEETRU_ENV;\r\n if (g === 'dev' || g === 'workspace' || g === 'prod') return g;\r\n } catch {\r\n /* ignore */\r\n }\r\n return 'prod';\r\n}\r\n\r\n// ─── Real OIDC auth namespace ──────────────────────────────────────────────\r\n\r\n/**\r\n * Implementação real do namespace auth — redireciona pra auth.neetru.com\r\n * em signIn, lê id_token do localStorage (se browser) ou do env em Node.\r\n *\r\n * Storage key: `neetru_id_token`. JWT decoded inline (sem verifyJWT — backend\r\n * já validou; SDK só lê claims pra populate getUser).\r\n */\r\nfunction createOidcAuthNamespace(config: ResolvedConfig): AuthNamespace {\r\n const STORAGE_KEY = 'neetru_id_token';\r\n const listeners = new Set<AuthStateListener>();\r\n let cachedUser: NeetruUser | null = null;\r\n\r\n function getStorage(): Storage | null {\r\n try {\r\n return typeof globalThis.localStorage !== 'undefined' ? globalThis.localStorage : null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n function decodeJwtPayload(token: string): Record<string, unknown> | null {\r\n const parts = token.split('.');\r\n if (parts.length !== 3) return null;\r\n try {\r\n // base64url decode (browser/Node compat).\r\n const b64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');\r\n const pad = '='.repeat((4 - (b64.length % 4)) % 4);\r\n const decoded =\r\n typeof atob === 'function'\r\n ? atob(b64 + pad)\r\n : Buffer.from(b64 + pad, 'base64').toString('utf-8');\r\n return JSON.parse(decoded);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n function tokenToUser(token: string): NeetruUser | null {\r\n const payload = decodeJwtPayload(token);\r\n if (!payload || typeof payload.sub !== 'string') return null;\r\n return {\r\n uid: payload.sub,\r\n email: typeof payload.email === 'string' ? payload.email : '',\r\n emailVerified: typeof payload.email_verified === 'boolean' ? payload.email_verified : undefined,\r\n displayName: typeof payload.name === 'string' ? payload.name : undefined,\r\n photoURL: typeof payload.picture === 'string' ? payload.picture : undefined,\r\n isStaff: payload.is_staff === true,\r\n isCustomer: payload.is_customer === true,\r\n tenantId: typeof payload.tenant_id === 'string' ? payload.tenant_id : undefined,\r\n ...payload,\r\n };\r\n }\r\n\r\n function loadCachedUser(): NeetruUser | null {\r\n if (cachedUser) return cachedUser;\r\n const storage = getStorage();\r\n if (!storage) return null;\r\n const token = storage.getItem(STORAGE_KEY);\r\n if (!token) return null;\r\n cachedUser = tokenToUser(token);\r\n return cachedUser;\r\n }\r\n\r\n function notify(): void {\r\n for (const l of listeners) {\r\n try {\r\n l(cachedUser);\r\n } catch {\r\n /* ignore consumer errors */\r\n }\r\n }\r\n }\r\n\r\n return {\r\n async signIn(options?: SignInOptions): Promise<NeetruUser | void> {\r\n // Em browser, redireciona pro authorize endpoint do IdP (auth.neetru.com).\r\n // Fix audit 2026-05-15: antes apontava `api.neetru.com/oauth/authorize`\r\n // (404 — middleware só roteia /api/v1/oauth a partir de auth.neetru.com).\r\n // O issuer canônico é `auth.neetru.com` (vide PLATFORM_IDENTIDADE.md).\r\n if (typeof globalThis.location !== 'undefined' && typeof globalThis.location.assign === 'function') {\r\n const redirectUri = options?.redirectUri ?? globalThis.location.origin;\r\n const scope = options?.scope ?? 'openid profile email';\r\n const state = options?.postLoginRedirect ?? globalThis.location.href;\r\n // Deriva o host do IdP a partir do baseUrl: api.* → auth.*. Fallback:\r\n // override explícito por `globalThis.NEETRU_AUTH_URL` (testes / staging).\r\n const overrideAuthUrl =\r\n typeof (globalThis as { NEETRU_AUTH_URL?: string }).NEETRU_AUTH_URL === 'string'\r\n ? (globalThis as { NEETRU_AUTH_URL?: string }).NEETRU_AUTH_URL\r\n : null;\r\n const idpOrigin = overrideAuthUrl ?? config.baseUrl.replace(/^https?:\\/\\/api\\./, 'https://auth.');\r\n const url = new URL('/api/v1/oauth/authorize', idpOrigin);\r\n url.searchParams.set('response_type', 'code');\r\n url.searchParams.set('redirect_uri', redirectUri);\r\n url.searchParams.set('scope', scope);\r\n url.searchParams.set('state', state);\r\n if (config.apiKey) {\r\n // apiKey aqui age como client_id (formato `nrt_{client_id}_{secret}`).\r\n const clientId = config.apiKey.split('_')[1] ?? config.apiKey;\r\n url.searchParams.set('client_id', clientId);\r\n }\r\n globalThis.location.assign(url.toString());\r\n return;\r\n }\r\n // Não-browser sem mock — não dá pra signIn interativo.\r\n throw new NeetruError(\r\n 'invalid_config',\r\n 'auth.signIn requires a browser context or mocks. Use NEETRU_ENV=dev or pass mocks.auth.',\r\n );\r\n },\r\n\r\n async signOut(): Promise<void> {\r\n const storage = getStorage();\r\n if (storage) storage.removeItem(STORAGE_KEY);\r\n cachedUser = null;\r\n // Best-effort revoke no server. O endpoint canônico é\r\n // auth.neetru.com/api/v1/oauth/revoke (não api.neetru.com). Aplica a\r\n // mesma derivação api.* → auth.* usada no signIn().\r\n try {\r\n const overrideAuthUrl =\r\n typeof (globalThis as { NEETRU_AUTH_URL?: string }).NEETRU_AUTH_URL === 'string'\r\n ? (globalThis as { NEETRU_AUTH_URL?: string }).NEETRU_AUTH_URL\r\n : null;\r\n const idpOrigin =\r\n overrideAuthUrl ?? config.baseUrl.replace(/^https?:\\/\\/api\\./, 'https://auth.');\r\n await config.fetch(`${idpOrigin}/api/v1/oauth/revoke`, {\r\n method: 'POST',\r\n headers: { 'content-type': 'application/json' },\r\n });\r\n } catch {\r\n /* network failure non-fatal */\r\n }\r\n notify();\r\n },\r\n\r\n getUser(): NeetruUser | null {\r\n return loadCachedUser();\r\n },\r\n\r\n onAuthStateChanged(listener: AuthStateListener): () => void {\r\n listeners.add(listener);\r\n try {\r\n listener(loadCachedUser());\r\n } catch {\r\n /* ignore */\r\n }\r\n return () => {\r\n listeners.delete(listener);\r\n };\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Cria uma instância imutável do cliente Neetru SDK.\r\n *\r\n * @example\r\n * ```ts\r\n * import { createNeetruClient } from '@neetru/sdk';\r\n *\r\n * const client = createNeetruClient({\r\n * apiKey: 'nrt_a1b2c3d4_xY9z...',\r\n * });\r\n *\r\n * const { products } = await client.catalog.list();\r\n * const can = await client.entitlements.check('neetru-pulse', 'export-pdf');\r\n * await client.telemetry.event({ name: 'report_exported' });\r\n * await client.usage.track('api_call', { route: '/x' });\r\n * await client.support.createTicket({ subject: 'help', message: '...' });\r\n * ```\r\n *\r\n * @throws {NeetruError} `invalid_config` se fetch não disponível no runtime.\r\n */\r\nexport function createNeetruClient(config: NeetruClientConfig = {}): NeetruClient {\r\n const fetchImpl = config.fetch ?? globalThis.fetch;\r\n if (typeof fetchImpl !== 'function') {\r\n throw new NeetruError(\r\n 'invalid_config',\r\n 'fetch is not available in this runtime. Pass `fetch` explicitly to createNeetruClient.',\r\n );\r\n }\r\n\r\n const baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\r\n const apiKey = config.apiKey ?? readEnvApiKey();\r\n const env = resolveEnv(config.env);\r\n\r\n // `bind` garante `this` correto em runtimes que validam (ex: undici).\r\n const resolved: ResolvedConfig = Object.freeze({\r\n apiKey,\r\n baseUrl,\r\n fetch: fetchImpl.bind(globalThis),\r\n env,\r\n productId: config.productId,\r\n tenantId: config.tenantId,\r\n });\r\n\r\n // Em dev, sempre ativa mocks. Mocks explícitos sempre vencem.\r\n const isDev = env === 'dev';\r\n const auth = config.mocks?.auth ?? (isDev ? new MockAuth({ ...DEV_FIXTURE_USER }) : createOidcAuthNamespace(resolved));\r\n const usage = config.mocks?.usage ?? (isDev ? new MockUsage() : createUsageNamespace(resolved));\r\n const support = config.mocks?.support ?? (isDev ? new MockSupport() : createSupportNamespace(resolved));\r\n const entitlements = config.mocks?.entitlements ?? (isDev ? new MockEntitlements() : createEntitlementsNamespace(resolved));\r\n const db = config.mocks?.db ?? createNeetruDb(resolved, config.db);\r\n const webhooks = config.mocks?.webhooks ?? (isDev ? new MockWebhooks() : createWebhooksNamespace(resolved));\r\n const notifications = config.mocks?.notifications ?? (isDev ? new MockNotifications() : createNotificationsNamespace(resolved));\r\n\r\n const client: NeetruClient = Object.freeze({\r\n config: resolved,\r\n auth,\r\n catalog: createCatalogNamespace(resolved),\r\n entitlements,\r\n telemetry: createTelemetryNamespace(resolved),\r\n usage,\r\n support,\r\n db,\r\n checkout: createCheckoutNamespace(resolved),\r\n webhooks,\r\n notifications,\r\n });\r\n\r\n return client;\r\n}\r\n","/**\r\n * Tipos públicos do SDK Neetru.\r\n *\r\n * Vendor-neutral: nada aqui referencia `firebase/*`, `stripe`, ou qualquer\r\n * provider interno. Caller só vê superfície neutra (Product, Entitlement, ...).\r\n */\r\n\r\n/** Default base URL pra API pública Neetru. */\r\nexport const DEFAULT_BASE_URL = 'https://api.neetru.com';\r\n\r\n/**\r\n * Configuração passada pra `createNeetruClient`.\r\n */\r\nexport interface NeetruClientConfig {\r\n /**\r\n * Bearer token Neetru (formato `nrt_<keyId>_<secret>`). Opcional —\r\n * se ausente, o SDK tenta `process.env.NEETRU_API_KEY` em Node.\r\n *\r\n * Endpoints públicos (catalog) funcionam sem apiKey. Endpoints autenticados\r\n * (entitlements, telemetry) lançam `missing_api_key` se ausente.\r\n */\r\n apiKey?: string;\r\n /**\r\n * URL base da API Neetru. Default: `https://api.neetru.com`.\r\n * Útil em testes apontando pra staging ou mock server.\r\n */\r\n baseUrl?: string;\r\n /**\r\n * Implementação de fetch customizada. Default: `globalThis.fetch`.\r\n * Necessário em runtimes que não exponham fetch global por default.\r\n */\r\n fetch?: typeof globalThis.fetch;\r\n /**\r\n * Modo de runtime. `dev` ativa mocks (auth retorna user fixture, usage só\r\n * loga, support retorna lista fake). `workspace` e `prod` chamam HTTP real.\r\n *\r\n * Default: lê `process.env.NEETRU_ENV` (Node) ou `globalThis.NEETRU_ENV`\r\n * (browser); fallback `prod`.\r\n */\r\n env?: 'dev' | 'workspace' | 'prod';\r\n /**\r\n * Override de mocks — útil em tests do consumer pra injetar fixtures\r\n * determinísticos (sem depender de NEETRU_ENV=dev).\r\n */\r\n mocks?: {\r\n auth?: AuthNamespace;\r\n usage?: UsageNamespace;\r\n support?: SupportNamespace;\r\n entitlements?: NeetruClient['entitlements'];\r\n /** v2.0: aceita NeetruDb (inclui MockDb). DbNamespace legado não é mais aceito. */\r\n db?: import('./db/client-db').NeetruDb;\r\n webhooks?: import('./webhooks').WebhooksNamespace;\r\n notifications?: import('./notifications').NotificationsNamespace;\r\n };\r\n /**\r\n * v0.3 — productId default usado por `usage.report()` / `usage.check()` /\r\n * `db.collection()` quando não passado explicitamente nas options.\r\n */\r\n productId?: string;\r\n /**\r\n * v0.3 — tenantId default usado por `usage.report()` / `usage.check()` /\r\n * `db.collection()` quando não passado explicitamente nas options.\r\n */\r\n tenantId?: string;\r\n /**\r\n * v2.0 — Configuração do banco lógico: engine, dbId, coleções, transport.\r\n * Gerado pelo scaffold `neetru db init`. Opcional — padrão é engine='rest'.\r\n */\r\n db?: import('./db/client-db').NeetruDbOptions;\r\n}\r\n\r\n/**\r\n * Status do produto no catálogo público.\r\n */\r\nexport type ProductStatus = 'live' | 'soon' | 'beta';\r\n\r\n/**\r\n * Produto SaaS publicado pelo Neetru Core.\r\n *\r\n * Schema neutro — alinhado com `public_products/{slug}` no backend mas\r\n * nunca expõe campos internos (Firestore Timestamps, draft state, etc).\r\n */\r\nexport interface Product {\r\n /** Identificador estável do produto, ex: `neetru-pulse`. */\r\n slug: string;\r\n /** Nome de exibição, ex: `Neetru Pulse`. */\r\n name: string;\r\n /** Subtítulo curto, ex: `Gestão de operações`. */\r\n tagline?: string;\r\n /** Descrição longa em prosa. */\r\n description?: string;\r\n /** Status público do produto. */\r\n status?: ProductStatus;\r\n /** Hint de ícone (catálogo de keys interno do Core). */\r\n iconKey?: string;\r\n /** Link override do CTA principal (default: página do produto). */\r\n ctaHref?: string;\r\n /** Label override do CTA. */\r\n ctaLabel?: string;\r\n /** Lista opcional de planos cobrados. Pode ser preenchida v0.2+. */\r\n plans?: ProductPlan[];\r\n}\r\n\r\n/** Plano cobrado de um produto (placeholder v0.1 — schema final v0.2). */\r\nexport interface ProductPlan {\r\n id: string;\r\n name: string;\r\n /** Preço mensal em centavos (BRL). Pode ser undefined em planos custom. */\r\n amountCents?: number;\r\n features?: string[];\r\n}\r\n\r\n/**\r\n * Resposta do `client.catalog.list()`.\r\n */\r\nexport interface CatalogListResponse {\r\n products: Product[];\r\n fetchedAt: string;\r\n}\r\n\r\n/**\r\n * Resposta do `client.entitlements.check(productSlug, feature)`.\r\n *\r\n * `allowed` é o sinal forte; `reason` ajuda a debugar (não exibir pro user\r\n * final).\r\n */\r\nexport interface EntitlementCheck {\r\n allowed: boolean;\r\n productSlug: string;\r\n feature: string;\r\n /** Reason code estável: `granted` | `not_subscribed` | `feature_not_in_plan` | `expired`. */\r\n reason?: string;\r\n}\r\n\r\n/**\r\n * Payload pra `client.telemetry.event()`.\r\n */\r\nexport interface TelemetryEventInput {\r\n /** Nome do evento, ex: `dashboard_opened`, `report_exported`. */\r\n name: string;\r\n /** Atributos adicionais (chave → valor primitivo). */\r\n properties?: Record<string, string | number | boolean | null>;\r\n /** Timestamp ISO opcional; default = server time. */\r\n timestamp?: string;\r\n}\r\n\r\n/**\r\n * Confirmação de aceitação do evento de telemetria.\r\n */\r\nexport interface TelemetryEventAck {\r\n ok: true;\r\n /** ID gerado pelo backend pra evento (`usage_events/{id}`). */\r\n eventId: string;\r\n}\r\n\r\n// ─── Sprint 6 — Telemetry log per-product ──────────────────────────────────\r\n\r\nexport type TelemetryLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';\r\n\r\nexport interface TelemetryLogInput {\r\n level: TelemetryLogLevel;\r\n message: string;\r\n metadata?: Record<string, unknown>;\r\n /** Override correlationId (default: lê dos headers/env automaticamente). */\r\n correlationId?: string;\r\n /** Slug do produto referenciado. Backend infere do escopo do token se ausente. */\r\n productSlug?: string;\r\n}\r\n\r\nexport interface TelemetryLogAck {\r\n ok: true;\r\n /** ID do log gravado (`logs/{productId}/{yyyymmdd}/{logId}`) — opcional em mocks. */\r\n logId?: string;\r\n /** Indicador de modo (mock vs http). */\r\n mode: 'mock' | 'http';\r\n}\r\n\r\n/**\r\n * Handle imutável retornado por `createNeetruClient`. Carrega namespaces\r\n * `auth`, `catalog`, `entitlements`, `telemetry`, `usage`, `support`.\r\n *\r\n * Cada namespace é exposto como objeto chamável — espelha API Firebase\r\n * (`auth`, `firestore`) ou Stripe (`paymentIntents`, `customers`).\r\n */\r\nexport interface NeetruClient {\r\n /** Configuração resolvida (apiKey, baseUrl, fetch). Read-only. */\r\n readonly config: ResolvedConfig;\r\n /** Namespace auth (v0.2 — OIDC + mocks dev). */\r\n readonly auth: AuthNamespace;\r\n /** Namespace catálogo público de produtos. */\r\n readonly catalog: {\r\n /** Lista produtos publicados. */\r\n list(opts?: CatalogListOptions): Promise<CatalogListResponse>;\r\n /** Busca produto único por slug. */\r\n get(slug: string): Promise<Product>;\r\n };\r\n /** Namespace entitlements (v1.2: cache LRU 60s TTL). */\r\n readonly entitlements: {\r\n /**\r\n * Verifica se o portador da apiKey pode usar `feature` do produto `slug`.\r\n * Cacheado 60s. `{ cacheBust: true }` força ida ao servidor.\r\n */\r\n check(\r\n productSlug: string,\r\n feature: string,\r\n opts?: { cacheBust?: boolean },\r\n ): Promise<boolean>;\r\n /** Variante que retorna o objeto completo com `reason`. */\r\n checkDetailed(\r\n productSlug: string,\r\n feature: string,\r\n opts?: { cacheBust?: boolean },\r\n ): Promise<EntitlementCheck>;\r\n };\r\n /** Namespace telemetria (v1.2: track fire-and-forget + flush). */\r\n readonly telemetry: {\r\n /** Persiste um evento single-shot. await retorna { ok, eventId }. */\r\n event(input: TelemetryEventInput): Promise<TelemetryEventAck>;\r\n /** Fire-and-forget: enqueue + flush 500ms debounce. Sem retorno. */\r\n track(input: TelemetryEventInput): void;\r\n /** Força flush da queue do track() (chamar antes de unload). */\r\n flush(): Promise<void>;\r\n /**\r\n * Registra um log estruturado per-product (Sprint 6).\r\n *\r\n * - Em `NEETRU_ENV=dev`: apenas console.{level} (sem network).\r\n * - Em `workspace`/`prod`: POST `/api/sdk/v1/telemetry/log` com Bearer + correlationId.\r\n */\r\n log(input: TelemetryLogInput): Promise<TelemetryLogAck>;\r\n };\r\n /** Namespace usage (v0.2 — track + quota; v0.3 — report + check). */\r\n readonly usage: UsageNamespace;\r\n /** Namespace support (v0.2 — tickets). */\r\n readonly support: SupportNamespace;\r\n /**\r\n * Namespace db (v2.0 — Mundo Documentos offline-first + Mundo SQL).\r\n *\r\n * Breaking change v2.0: `client.db` agora é `NeetruDb` em vez de `DbNamespace`.\r\n * - `db.collection(name)` → `DbCollectionRef` (offline-first, com `onSnapshot`,\r\n * `batch`, `doc(id)`, `onDoc`; `list()` retorna `DbListResult` com cursor).\r\n * - `db.sql(schema)` → `Promise<NeetruSqlClient>` (Mundo SQL).\r\n * - `db.syncState` / `db.flush()` / `db.clearCache()` (camada offline).\r\n *\r\n * O antigo `DbNamespace` (list retornava `T[]`) foi removido em v2.0.\r\n */\r\n readonly db: import('./db/client-db').NeetruDb;\r\n /** Namespace checkout (v1.1 — start/get/cancel intent + auto-redirect). */\r\n readonly checkout: import('./checkout').CheckoutNamespace;\r\n /** Namespace webhooks (v1.2 — register/list/unregister/test). */\r\n readonly webhooks: import('./webhooks').WebhooksNamespace;\r\n /** Namespace notifications (v1.2 — send/list/markRead/dismiss). */\r\n readonly notifications: import('./notifications').NotificationsNamespace;\r\n}\r\n\r\n// ─── v0.2 — Auth namespace ──────────────────────────────────────────────────\r\n\r\n/**\r\n * User retornado pelo OIDC ID token. Schema neutro — não vaza Firebase\r\n * decoded token shape. Subset estável do RFC 7519 + custom claims Neetru.\r\n */\r\nexport interface NeetruUser {\r\n /** Subject — uid estável. */\r\n uid: string;\r\n email: string;\r\n emailVerified?: boolean;\r\n displayName?: string;\r\n photoURL?: string;\r\n /** Custom claim Neetru — true quando staff. */\r\n isStaff?: boolean;\r\n /** Custom claim Neetru — true quando customer enrolled. */\r\n isCustomer?: boolean;\r\n /** Tenant assigned (multi-tenant deployments). */\r\n tenantId?: string;\r\n /** Outros claims OIDC (aud, iss, iat, exp). */\r\n [extra: string]: unknown;\r\n}\r\n\r\nexport interface SignInOptions {\r\n /** OIDC redirect_uri override. Default = window.location origin. */\r\n redirectUri?: string;\r\n /** OIDC scope. Default `openid profile email`. */\r\n scope?: string;\r\n /** Onde mandar após login completo. Default = window.location.href. */\r\n postLoginRedirect?: string;\r\n}\r\n\r\nexport type AuthStateListener = (user: NeetruUser | null) => void;\r\n\r\nexport interface AuthNamespace {\r\n /**\r\n * Inicia fluxo de login OIDC. Em dev (`NEETRU_ENV=dev`) retorna mock user\r\n * direto sem redirect. Em prod redireciona pro authorize endpoint.\r\n */\r\n signIn(options?: SignInOptions): Promise<NeetruUser | void>;\r\n /** Limpa session local + revoga refresh token no servidor. */\r\n signOut(): Promise<void>;\r\n /** Retorna o user atual (do id_token cached) ou `null` se não logado. */\r\n getUser(): NeetruUser | null;\r\n /**\r\n * Subscreve a mudanças de estado de auth. Listener é invocado imediatamente\r\n * com user atual. Retorna função de unsubscribe.\r\n */\r\n onAuthStateChanged(listener: AuthStateListener): () => void;\r\n}\r\n\r\n// ─── v0.2 — Usage namespace ─────────────────────────────────────────────────\r\n\r\nexport interface UsageEventInput {\r\n /** Nome do evento, ex: `report_generated`, `api_call`. */\r\n event: string;\r\n /** Atributos do evento. Valores primitivos serializáveis. */\r\n properties?: Record<string, string | number | boolean | null>;\r\n /** Quantidade — default 1 (1 evento). Útil pra batch. */\r\n quantity?: number;\r\n}\r\n\r\nexport interface UsageQuota {\r\n metric: string;\r\n /** Quantidade já consumida no período. */\r\n used: number;\r\n /** Limite total. -1 = unlimited. */\r\n limit: number;\r\n /** ISO timestamp do reset (próximo período). */\r\n resetsAt?: string;\r\n /** Plano que define o limite. */\r\n plan?: string;\r\n}\r\n\r\nexport interface UsageNamespace {\r\n /** Persiste um evento de uso. Mock em dev, POST `/sdk/v1/usage/record` em prod. */\r\n track(event: string, props?: UsageEventInput['properties']): Promise<{ ok: true }>;\r\n /** Lê quota atual de uma métrica. Mock em dev, GET `/sdk/v1/usage/quota` em prod. */\r\n getQuota(metric: string): Promise<UsageQuota>;\r\n /**\r\n * v0.3 — Reporta consumo de um resource metered (POST /sdk/v1/usage/record\r\n * com `{productId, tenantId, resource, qty}`). Em dev acumula no mock.\r\n *\r\n * Diferente de `track()`: usa o endpoint canônico Sprint 7 que incrementa\r\n * `usage_counters/{tenantId}_{productId}_{resource}_{yyyymm}` atomicamente.\r\n *\r\n * `productId`/`tenantId` são lidos do contexto resolvido do client se\r\n * ausentes nas options.\r\n */\r\n report(\r\n resource: string,\r\n qty?: number,\r\n options?: { productId?: string; tenantId?: string },\r\n ): Promise<{\r\n ok: true;\r\n counterId?: string;\r\n value?: number;\r\n limit?: number;\r\n remaining?: number;\r\n status?: string;\r\n }>;\r\n /**\r\n * v0.3 — Verifica entitlement de um resource/feature. Wrapper em\r\n * GET /sdk/v1/entitlements. Em dev consulta MockEntitlements + MockUsage.\r\n */\r\n check(\r\n resource: string,\r\n options?: { productId?: string; tenantId?: string },\r\n ): Promise<{\r\n allowed: boolean;\r\n reason?: string;\r\n remaining?: number;\r\n limit?: number;\r\n planId?: string | null;\r\n planFeatures?: string[];\r\n }>;\r\n}\r\n\r\n// ─── v0.3 — Datastore namespace ────────────────────────────────────────────\r\n\r\n/**\r\n * Namespace `db` (v0.3) — wrapper minimalista para CRUD em coleções tenant-scoped\r\n * via Core REST. Em dev retorna fixtures in-memory por collection.\r\n *\r\n * O Core injeta automaticamente o tenantId no path do Firestore:\r\n * `tenant_{tid}_{name}/{docId}`.\r\n */\r\n/** Filtro `where` simples — alinhado com endpoint REST `field:op:value`. */\r\nexport interface DbWhereFilter {\r\n field: string;\r\n op: '==' | '!=' | '<' | '<=' | '>' | '>=' | 'in';\r\n value: string | number | boolean | null | Array<string | number | boolean>;\r\n}\r\n\r\nexport interface DbListOptions {\r\n limit?: number;\r\n /** Lista de filtros — máximo 5 (alinhado ao backend). */\r\n where?: DbWhereFilter[];\r\n}\r\n\r\nexport interface DbCollectionRef {\r\n /** Lista documentos com filtros opcionais. */\r\n list<T = Record<string, unknown>>(opts?: DbListOptions): Promise<T[]>;\r\n /** Lê um documento por id. Retorna `null` se não existe. */\r\n get<T = Record<string, unknown>>(id: string): Promise<T | null>;\r\n /** Cria/upsert um documento com id explícito. */\r\n set(id: string, data: Record<string, unknown>): Promise<{ ok: true }>;\r\n /**\r\n * v0.3.1 — Adiciona doc com id auto-gerado pelo backend. Retorna `{id}` do\r\n * doc criado. Diferente de `set(id, data)` que requer caller fornecer id.\r\n */\r\n add(data: Record<string, unknown>): Promise<{ ok: true; id: string }>;\r\n /** Atualiza doc com merge — só campos passados em `data`. */\r\n update(id: string, data: Record<string, unknown>): Promise<{ ok: true }>;\r\n /** Deleta um documento. */\r\n remove(id: string): Promise<{ ok: true }>;\r\n}\r\n\r\nexport interface DbNamespace {\r\n collection(name: string): DbCollectionRef;\r\n}\r\n\r\n// ─── v0.2 — Support namespace ───────────────────────────────────────────────\r\n\r\nexport type SupportSeverity = 'low' | 'normal' | 'high' | 'urgent';\r\nexport type SupportStatus = 'open' | 'pending' | 'resolved' | 'closed';\r\n\r\nexport interface SupportTicket {\r\n id: string;\r\n subject: string;\r\n message: string;\r\n severity: SupportSeverity;\r\n status: SupportStatus;\r\n createdAt: string;\r\n updatedAt?: string;\r\n /** Slug do produto referenciado. */\r\n productSlug?: string;\r\n}\r\n\r\nexport interface CreateTicketInput {\r\n subject: string;\r\n message: string;\r\n severity?: SupportSeverity;\r\n productSlug?: string;\r\n}\r\n\r\nexport interface SupportNamespace {\r\n /** Cria um novo ticket. Mock em dev, POST `/api/v1/products/{slug}/tickets` em prod. */\r\n createTicket(input: CreateTicketInput): Promise<SupportTicket>;\r\n /** Lista meus tickets abertos. */\r\n listMyTickets(): Promise<SupportTicket[]>;\r\n}\r\n\r\n// ─── v0.2 — Env detection ───────────────────────────────────────────────────\r\n\r\n/**\r\n * Modo do SDK. `dev` ativa mocks automáticos (úteis pra testes e\r\n * desenvolvimento sem precisar de backend rodando).\r\n */\r\nexport type NeetruEnv = 'dev' | 'workspace' | 'prod';\r\n\r\n/**\r\n * Configuração resolvida (defaults aplicados, fetch garantido).\r\n */\r\nexport interface ResolvedConfig {\r\n readonly apiKey?: string;\r\n readonly baseUrl: string;\r\n readonly fetch: typeof globalThis.fetch;\r\n /** Resolved env — `dev` | `workspace` | `prod`. Default `prod`. */\r\n readonly env: NeetruEnv;\r\n /** Default productId (v0.3). */\r\n readonly productId?: string;\r\n /** Default tenantId (v0.3). */\r\n readonly tenantId?: string;\r\n}\r\n\r\n/** Opções pra `catalog.list()`. */\r\nexport interface CatalogListOptions {\r\n /** Inclui rascunhos (apenas com Bearer staff). Default false. */\r\n includeDrafts?: boolean;\r\n}\r\n","/**\r\n * Catálogo público de produtos SaaS Neetru.\r\n *\r\n * Endpoints consumidos (v1.2+):\r\n * - `GET /api/sdk/v1/catalog` — listagem pública (sem auth)\r\n * - `GET /api/sdk/v1/catalog/{slug}` — produto único (sem auth)\r\n *\r\n * v1.1 e anteriores usavam `/api/v1/cli/catalog` (staff CLI), o que forçava\r\n * SDK consumers a manter Bearer staff-only. v1.2 separa: SDK consome o\r\n * endpoint público (`published === true`), staff continua usando CLI quando\r\n * precisa de rascunho.\r\n *\r\n * Read-only. Publicação de produto continua via CLI `neetru publish`.\r\n */\r\nimport { NeetruError } from './errors';\r\nimport { httpRequest } from './http';\r\nimport type {\r\n CatalogListOptions,\r\n CatalogListResponse,\r\n Product,\r\n ResolvedConfig,\r\n} from './types';\r\n\r\ninterface RawCatalogListResponse {\r\n ok?: boolean;\r\n count?: number;\r\n products?: unknown[];\r\n fetchedAt?: string;\r\n}\r\n\r\ninterface RawCatalogGetResponse {\r\n ok?: boolean;\r\n product?: unknown;\r\n}\r\n\r\nfunction toProduct(raw: unknown): Product {\r\n if (!raw || typeof raw !== 'object') {\r\n throw new NeetruError('invalid_response', 'Catalog response item is not an object');\r\n }\r\n const r = raw as Record<string, unknown>;\r\n if (typeof r.slug !== 'string' || !r.slug) {\r\n throw new NeetruError('invalid_response', 'Catalog product missing slug');\r\n }\r\n if (typeof r.name !== 'string' || !r.name) {\r\n throw new NeetruError('invalid_response', 'Catalog product missing name');\r\n }\r\n const product: Product = {\r\n slug: r.slug,\r\n name: r.name,\r\n };\r\n if (typeof r.tagline === 'string') product.tagline = r.tagline;\r\n if (typeof r.description === 'string') product.description = r.description;\r\n if (r.status === 'live' || r.status === 'soon' || r.status === 'beta') {\r\n product.status = r.status;\r\n }\r\n if (typeof r.iconKey === 'string') product.iconKey = r.iconKey;\r\n if (typeof r.ctaHref === 'string') product.ctaHref = r.ctaHref;\r\n if (typeof r.ctaLabel === 'string') product.ctaLabel = r.ctaLabel;\r\n // plans é placeholder v0.2 — preservar se backend mandar\r\n if (Array.isArray(r.plans)) {\r\n product.plans = r.plans.filter(\r\n (p): p is { id: string; name: string } =>\r\n typeof p === 'object' &&\r\n p !== null &&\r\n typeof (p as Record<string, unknown>).id === 'string' &&\r\n typeof (p as Record<string, unknown>).name === 'string',\r\n ) as Product['plans'];\r\n }\r\n return product;\r\n}\r\n\r\nexport function createCatalogNamespace(config: ResolvedConfig) {\r\n return {\r\n /**\r\n * Lista produtos publicados. Por default só `published=true`; staff\r\n * pode passar `includeDrafts: true` (requer Bearer com role admin/operator).\r\n */\r\n async list(_opts: CatalogListOptions = {}): Promise<CatalogListResponse> {\r\n // SDK só lê produtos publicados. `includeDrafts` legado é ignorado:\r\n // rascunhos só via CLI staff (`/api/v1/cli/catalog?drafts=true`).\r\n const raw = await httpRequest<RawCatalogListResponse>(config, {\r\n method: 'GET',\r\n path: '/api/sdk/v1/catalog',\r\n });\r\n\r\n if (!raw || !Array.isArray(raw.products)) {\r\n throw new NeetruError(\r\n 'invalid_response',\r\n 'Catalog list response missing products array',\r\n );\r\n }\r\n\r\n return {\r\n products: raw.products.map(toProduct),\r\n fetchedAt: typeof raw.fetchedAt === 'string'\r\n ? raw.fetchedAt\r\n : new Date().toISOString(),\r\n };\r\n },\r\n\r\n /**\r\n * Busca produto único por slug.\r\n *\r\n * @throws {NeetruError} `not_found` se slug inexistente ou não publicado.\r\n */\r\n async get(slug: string): Promise<Product> {\r\n if (!slug || typeof slug !== 'string') {\r\n throw new NeetruError('validation_failed', 'slug is required');\r\n }\r\n const raw = await httpRequest<RawCatalogGetResponse>(config, {\r\n method: 'GET',\r\n path: `/api/sdk/v1/catalog/${encodeURIComponent(slug)}`,\r\n });\r\n\r\n if (!raw || !raw.product) {\r\n throw new NeetruError(\r\n 'invalid_response',\r\n 'Catalog get response missing product',\r\n );\r\n }\r\n return toProduct(raw.product);\r\n },\r\n };\r\n}\r\n","/**\r\n * Entitlements — verifica se o portador da apiKey pode usar feature X\r\n * do produto Y.\r\n *\r\n * Endpoint: `GET /api/v1/sdk/entitlements/check?slug=X&feature=Y`\r\n * Schema Firestore consultado pelo backend:\r\n * `entitlements/{userId}/products/{slug}` → `{ features: string[], plan, expiresAt }`\r\n *\r\n * v1.2 introduz cache LRU em memória (default 60s TTL, 100 entries). Cada\r\n * (productSlug, feature) pareando o `apiKey` é cacheado. Caller pode invalidar\r\n * via `__resetCache()` (test helper) ou via `cacheBust: true` na chamada.\r\n */\r\nimport { NeetruError } from './errors';\r\nimport { httpRequest } from './http';\r\nimport type { EntitlementCheck, ResolvedConfig } from './types';\r\n\r\ninterface RawEntitlementCheck {\r\n allowed?: boolean;\r\n productSlug?: string;\r\n feature?: string;\r\n reason?: string;\r\n}\r\n\r\nfunction toEntitlementCheck(raw: unknown): EntitlementCheck {\r\n if (!raw || typeof raw !== 'object') {\r\n throw new NeetruError('invalid_response', 'Entitlement response is not an object');\r\n }\r\n const r = raw as RawEntitlementCheck;\r\n if (typeof r.allowed !== 'boolean') {\r\n throw new NeetruError('invalid_response', 'Entitlement response missing `allowed` boolean');\r\n }\r\n return {\r\n allowed: r.allowed,\r\n productSlug: typeof r.productSlug === 'string' ? r.productSlug : '',\r\n feature: typeof r.feature === 'string' ? r.feature : '',\r\n reason: typeof r.reason === 'string' ? r.reason : undefined,\r\n };\r\n}\r\n\r\n/** TTL default — 60s. Pareando com tempo de propagação típico de mudança de plano. */\r\nconst CACHE_TTL_MS = 60_000;\r\n/** Máx entries por instância de namespace — LRU. */\r\nconst CACHE_MAX = 100;\r\n\r\ninterface CacheEntry {\r\n value: EntitlementCheck;\r\n expiresAt: number;\r\n}\r\n\r\nexport interface EntitlementsCheckOptions {\r\n /** Se true, ignora cache local e força ida ao servidor. Default false. */\r\n cacheBust?: boolean;\r\n}\r\n\r\nexport function createEntitlementsNamespace(config: ResolvedConfig) {\r\n // Map preserva ordem de inserção — readequa LRU manualmente em hit.\r\n const cache = new Map<string, CacheEntry>();\r\n\r\n function cacheKey(productSlug: string, feature: string): string {\r\n return `${productSlug}::${feature}`;\r\n }\r\n\r\n function readCache(key: string): EntitlementCheck | null {\r\n const entry = cache.get(key);\r\n if (!entry) return null;\r\n if (entry.expiresAt < Date.now()) {\r\n cache.delete(key);\r\n return null;\r\n }\r\n // LRU touch: reinsere no final.\r\n cache.delete(key);\r\n cache.set(key, entry);\r\n return entry.value;\r\n }\r\n\r\n function writeCache(key: string, value: EntitlementCheck): void {\r\n if (cache.size >= CACHE_MAX) {\r\n const oldest = cache.keys().next().value;\r\n if (oldest !== undefined) cache.delete(oldest);\r\n }\r\n cache.set(key, { value, expiresAt: Date.now() + CACHE_TTL_MS });\r\n }\r\n\r\n async function checkDetailed(\r\n productSlug: string,\r\n feature: string,\r\n opts: EntitlementsCheckOptions = {},\r\n ): Promise<EntitlementCheck> {\r\n if (!productSlug) throw new NeetruError('validation_failed', 'productSlug is required');\r\n if (!feature) throw new NeetruError('validation_failed', 'feature is required');\r\n\r\n const key = cacheKey(productSlug, feature);\r\n if (!opts.cacheBust) {\r\n const cached = readCache(key);\r\n if (cached) return cached;\r\n }\r\n\r\n const raw = await httpRequest<RawEntitlementCheck>(config, {\r\n method: 'GET',\r\n path: '/api/v1/sdk/entitlements/check',\r\n query: { slug: productSlug, feature },\r\n requireAuth: true,\r\n });\r\n const result = toEntitlementCheck(raw);\r\n writeCache(key, result);\r\n return result;\r\n }\r\n\r\n return {\r\n /**\r\n * Verifica se o caller pode usar `feature` no produto `productSlug`.\r\n * Retorno simples: `true` libera, `false` bloqueia. Cache 60s automático.\r\n *\r\n * Use `checkDetailed` se precisar do `reason` pra mensagem de upgrade.\r\n */\r\n async check(\r\n productSlug: string,\r\n feature: string,\r\n opts?: EntitlementsCheckOptions,\r\n ): Promise<boolean> {\r\n const result = await checkDetailed(productSlug, feature, opts);\r\n return result.allowed;\r\n },\r\n checkDetailed,\r\n /** Test helper: limpa o cache LRU. */\r\n __resetCache(): void {\r\n cache.clear();\r\n },\r\n };\r\n}\r\n","/**\r\n * Telemetria — emite eventos do produto cliente pro Core.\r\n *\r\n * APIs disponíveis:\r\n * - `event(input)` — chamada single-shot, await retorna { ok, eventId }.\r\n * `POST /api/v1/sdk/telemetry/event` — persiste em `usage_events/{id}`.\r\n * - `track(input)` — fire-and-forget (v1.2). Enqueue + flush 500ms debounce.\r\n * Reusa o mesmo endpoint mas não bloqueia o caller — ideal pra alta\r\n * frequência (cliques, page-views). Falhas viram warning no console.\r\n * - `flush()` — força flush imediato da queue (chamar antes de unload).\r\n * - `log(input)` — log estruturado `POST /api/sdk/v1/telemetry/log` com\r\n * Bearer + correlationId. Em `NEETRU_ENV=dev` cai pra console.{level}.\r\n */\r\nimport { NeetruError } from './errors';\r\nimport { httpRequest } from './http';\r\nimport type {\r\n ResolvedConfig,\r\n TelemetryEventAck,\r\n TelemetryEventInput,\r\n TelemetryLogAck,\r\n TelemetryLogInput,\r\n TelemetryLogLevel,\r\n} from './types';\r\n\r\ninterface RawTelemetryAck {\r\n ok?: boolean;\r\n eventId?: string;\r\n}\r\n\r\ninterface RawLogAck {\r\n ok?: boolean;\r\n logId?: string;\r\n}\r\n\r\nconst VALID_LOG_LEVELS: readonly TelemetryLogLevel[] = ['debug', 'info', 'warn', 'error', 'fatal'];\r\n\r\nfunction consoleFor(level: TelemetryLogLevel): (message?: unknown, ...optional: unknown[]) => void {\r\n switch (level) {\r\n case 'debug': return console.debug.bind(console);\r\n case 'info': return console.info.bind(console);\r\n case 'warn': return console.warn.bind(console);\r\n case 'error': return console.error.bind(console);\r\n case 'fatal': return console.error.bind(console);\r\n default: return console.log.bind(console);\r\n }\r\n}\r\n\r\n/** Janela de debounce do `track()` antes de drenar a queue. */\r\nconst TRACK_FLUSH_MS = 500;\r\n/** Limite de eventos na queue antes de flush forçado (defensivo). */\r\nconst TRACK_MAX_QUEUE = 50;\r\n\r\nexport function createTelemetryNamespace(config: ResolvedConfig) {\r\n // Queue local pra track() — fire-and-forget batchado.\r\n const queue: TelemetryEventInput[] = [];\r\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n async function drainQueue(): Promise<void> {\r\n if (queue.length === 0) return;\r\n const batch = queue.splice(0, queue.length);\r\n flushTimer = null;\r\n await Promise.allSettled(\r\n batch.map(async (ev) => {\r\n try {\r\n const body: Record<string, unknown> = { name: ev.name };\r\n if (ev.properties && typeof ev.properties === 'object') {\r\n body.properties = ev.properties;\r\n }\r\n if (ev.timestamp) body.timestamp = ev.timestamp;\r\n await httpRequest<RawTelemetryAck>(config, {\r\n method: 'POST',\r\n path: '/api/v1/sdk/telemetry/event',\r\n body,\r\n requireAuth: true,\r\n retries: 1,\r\n });\r\n } catch (err) {\r\n if (typeof console !== 'undefined') {\r\n console.warn('[neetru-sdk] telemetry.track flush failed for event', ev.name, err);\r\n }\r\n }\r\n }),\r\n );\r\n }\r\n\r\n function scheduleFlush(): void {\r\n if (flushTimer) return;\r\n flushTimer = setTimeout(() => {\r\n void drainQueue();\r\n }, TRACK_FLUSH_MS);\r\n }\r\n\r\n return {\r\n /**\r\n * Persiste um evento de uso. Lança `NeetruError` em qualquer falha\r\n * (incluindo rate-limit).\r\n *\r\n * @example\r\n * ```ts\r\n * await client.telemetry.event({\r\n * name: 'dashboard_opened',\r\n * properties: { plan: 'pro', tab: 'overview' },\r\n * });\r\n * ```\r\n */\r\n async event(input: TelemetryEventInput): Promise<TelemetryEventAck> {\r\n if (!input || typeof input !== 'object') {\r\n throw new NeetruError('validation_failed', 'event input is required');\r\n }\r\n if (typeof input.name !== 'string' || input.name.length === 0) {\r\n throw new NeetruError('validation_failed', 'event.name is required');\r\n }\r\n if (input.name.length > 128) {\r\n throw new NeetruError('validation_failed', 'event.name max 128 chars');\r\n }\r\n\r\n const body: Record<string, unknown> = { name: input.name };\r\n if (input.properties && typeof input.properties === 'object') {\r\n body.properties = input.properties;\r\n }\r\n if (input.timestamp) body.timestamp = input.timestamp;\r\n\r\n const raw = await httpRequest<RawTelemetryAck>(config, {\r\n method: 'POST',\r\n path: '/api/v1/sdk/telemetry/event',\r\n body,\r\n requireAuth: true,\r\n });\r\n\r\n if (!raw || raw.ok !== true || typeof raw.eventId !== 'string') {\r\n throw new NeetruError('invalid_response', 'Telemetry response missing eventId');\r\n }\r\n return { ok: true, eventId: raw.eventId };\r\n },\r\n\r\n /**\r\n * Fire-and-forget: enqueue + flush 500ms debounce. Não retorna `eventId`\r\n * — falhas são logadas como warning. Ideal pra alta frequência.\r\n *\r\n * @example\r\n * ```ts\r\n * client.telemetry.track({ name: 'page_view', properties: { path: '/' } });\r\n * // segue execução; flush async em background\r\n * ```\r\n */\r\n track(input: TelemetryEventInput): void {\r\n if (!input || typeof input !== 'object') return;\r\n if (typeof input.name !== 'string' || input.name.length === 0) return;\r\n if (input.name.length > 128) return;\r\n queue.push(input);\r\n if (queue.length >= TRACK_MAX_QUEUE) {\r\n void drainQueue();\r\n } else {\r\n scheduleFlush();\r\n }\r\n },\r\n\r\n /**\r\n * Força flush imediato da queue de `track()`. Resolva antes de\r\n * page unload / SSR boundary pra não perder eventos.\r\n */\r\n async flush(): Promise<void> {\r\n if (flushTimer) {\r\n clearTimeout(flushTimer);\r\n flushTimer = null;\r\n }\r\n await drainQueue();\r\n },\r\n\r\n /**\r\n * Registra um log estruturado per-product (Sprint 6).\r\n *\r\n * - `NEETRU_ENV=dev`: console.{level}, retorna ack mock.\r\n * - workspace/prod: HTTP POST com Bearer auth + correlationId no header.\r\n *\r\n * @example\r\n * ```ts\r\n * await client.telemetry.log({\r\n * level: 'error',\r\n * message: 'Falha ao calcular total',\r\n * metadata: { orderId: 'o-123' },\r\n * });\r\n * ```\r\n */\r\n async log(input: TelemetryLogInput): Promise<TelemetryLogAck> {\r\n if (!input || typeof input !== 'object') {\r\n throw new NeetruError('validation_failed', 'log input is required');\r\n }\r\n if (!VALID_LOG_LEVELS.includes(input.level)) {\r\n throw new NeetruError('validation_failed', `level must be one of ${VALID_LOG_LEVELS.join(', ')}`);\r\n }\r\n if (typeof input.message !== 'string' || input.message.length === 0) {\r\n throw new NeetruError('validation_failed', 'message is required');\r\n }\r\n if (input.message.length > 4_000) {\r\n throw new NeetruError('validation_failed', 'message max 4000 chars');\r\n }\r\n\r\n // Dev mode: console only, no network.\r\n if (config.env === 'dev') {\r\n const fn = consoleFor(input.level);\r\n fn(`[neetru-sdk] ${input.level}: ${input.message}`, input.metadata ?? {});\r\n return { ok: true, mode: 'mock' };\r\n }\r\n\r\n const body: Record<string, unknown> = {\r\n level: input.level,\r\n message: input.message,\r\n };\r\n if (input.metadata) body.metadata = input.metadata;\r\n if (input.productSlug) body.productSlug = input.productSlug;\r\n\r\n // CorrelationId: explicit input wins; senão tenta lê de globalThis (set\r\n // por instrumentação do consumer).\r\n let cid = input.correlationId;\r\n if (!cid) {\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const g = (globalThis as any).NEETRU_CORRELATION_ID;\r\n if (typeof g === 'string' && g.length > 0) cid = g;\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n\r\n const headers: Record<string, string> = {};\r\n if (cid) headers['x-correlation-id'] = cid;\r\n\r\n const raw = await httpRequest<RawLogAck>(config, {\r\n method: 'POST',\r\n path: '/api/sdk/v1/telemetry/log',\r\n body,\r\n requireAuth: true,\r\n headers,\r\n });\r\n\r\n if (!raw || raw.ok !== true) {\r\n throw new NeetruError('invalid_response', 'Telemetry log response missing ok');\r\n }\r\n return {\r\n ok: true,\r\n logId: typeof raw.logId === 'string' ? raw.logId : undefined,\r\n mode: 'http',\r\n };\r\n },\r\n };\r\n}\r\n","/**\r\n * Usage namespace — track usage events e ler quotas (v0.2).\r\n *\r\n * Endpoints consumidos (em prod):\r\n * - `POST /sdk/v1/usage/record` — record event\r\n * - `GET /sdk/v1/usage/quota?metric=X` — ler quota da metric\r\n *\r\n * Comportamento por env:\r\n * - `dev` → MockUsage (in-memory, retornado pelo factory).\r\n * - `workspace`/`prod` → HTTP real.\r\n *\r\n * Diferença vs `telemetry`: telemetry é evento analítico (event sourcing pra\r\n * BigQuery). usage é meterado (consumo cobrado), com quota explícita por plano.\r\n */\r\nimport { NeetruError } from './errors';\r\nimport { httpRequest } from './http';\r\nimport type { ResolvedConfig, UsageNamespace, UsageQuota } from './types';\r\n\r\ninterface RawUsageAck {\r\n ok?: boolean;\r\n recordId?: string;\r\n}\r\n\r\ninterface RawUsageQuota {\r\n metric?: string;\r\n used?: number;\r\n limit?: number;\r\n resetsAt?: string;\r\n plan?: string;\r\n}\r\n\r\nfunction toQuota(metric: string, raw: unknown): UsageQuota {\r\n if (!raw || typeof raw !== 'object') {\r\n throw new NeetruError('invalid_response', 'Quota response is not an object');\r\n }\r\n const r = raw as RawUsageQuota;\r\n if (typeof r.used !== 'number' || typeof r.limit !== 'number') {\r\n throw new NeetruError('invalid_response', 'Quota response missing used/limit numbers');\r\n }\r\n return {\r\n metric: typeof r.metric === 'string' ? r.metric : metric,\r\n used: r.used,\r\n limit: r.limit,\r\n resetsAt: typeof r.resetsAt === 'string' ? r.resetsAt : undefined,\r\n plan: typeof r.plan === 'string' ? r.plan : undefined,\r\n };\r\n}\r\n\r\nexport function createUsageNamespace(config: ResolvedConfig): UsageNamespace {\r\n return {\r\n /**\r\n * Persiste um evento de usage. Em dev (mocks ativos via factory) só loga.\r\n * Em workspace/prod chama POST /sdk/v1/usage/record.\r\n */\r\n async track(\r\n event: string,\r\n properties?: Record<string, string | number | boolean | null>,\r\n ): Promise<{ ok: true }> {\r\n if (!event || typeof event !== 'string') {\r\n throw new NeetruError('validation_failed', 'event name is required');\r\n }\r\n if (event.length > 128) {\r\n throw new NeetruError('validation_failed', 'event name max 128 chars');\r\n }\r\n\r\n const body: Record<string, unknown> = { event };\r\n if (properties && typeof properties === 'object') body.properties = properties;\r\n\r\n const raw = await httpRequest<RawUsageAck>(config, {\r\n method: 'POST',\r\n path: '/sdk/v1/usage/record',\r\n body,\r\n requireAuth: true,\r\n });\r\n\r\n if (!raw || raw.ok !== true) {\r\n throw new NeetruError('invalid_response', 'Usage record response missing ok');\r\n }\r\n return { ok: true };\r\n },\r\n\r\n /**\r\n * Lê quota atual de uma métrica. Cacheável (caller decide), SDK não cacheia.\r\n */\r\n async getQuota(metric: string): Promise<UsageQuota> {\r\n if (!metric || typeof metric !== 'string') {\r\n throw new NeetruError('validation_failed', 'metric is required');\r\n }\r\n const raw = await httpRequest<RawUsageQuota>(config, {\r\n method: 'GET',\r\n path: '/sdk/v1/usage/quota',\r\n query: { metric },\r\n requireAuth: true,\r\n });\r\n return toQuota(metric, raw);\r\n },\r\n\r\n /**\r\n * v0.3 — Reporta consumo metered. Hit no endpoint canônico Sprint 7.\r\n */\r\n async report(\r\n resource: string,\r\n qty: number = 1,\r\n options?: { productId?: string; tenantId?: string },\r\n ) {\r\n if (!resource || typeof resource !== 'string') {\r\n throw new NeetruError('validation_failed', 'resource is required');\r\n }\r\n if (!Number.isFinite(qty) || qty <= 0) {\r\n throw new NeetruError('validation_failed', 'qty must be positive integer');\r\n }\r\n const productId = options?.productId ?? config.productId;\r\n const tenantId = options?.tenantId ?? config.tenantId;\r\n if (!productId) {\r\n throw new NeetruError(\r\n 'validation_failed',\r\n 'productId required (pass to options or set on createNeetruClient)',\r\n );\r\n }\r\n if (!tenantId) {\r\n throw new NeetruError(\r\n 'validation_failed',\r\n 'tenantId required (pass to options or set on createNeetruClient)',\r\n );\r\n }\r\n\r\n const raw = await httpRequest<{\r\n ok?: boolean;\r\n counterId?: string;\r\n value?: number;\r\n limit?: number;\r\n remaining?: number;\r\n status?: string;\r\n }>(config, {\r\n method: 'POST',\r\n path: '/sdk/v1/usage/record',\r\n body: { productId, tenantId, resource, qty: Math.floor(qty) },\r\n requireAuth: true,\r\n });\r\n if (!raw || raw.ok !== true) {\r\n throw new NeetruError('invalid_response', 'usage.report response missing ok');\r\n }\r\n return {\r\n ok: true as const,\r\n counterId: raw.counterId,\r\n value: raw.value,\r\n limit: raw.limit,\r\n remaining: raw.remaining,\r\n status: raw.status,\r\n };\r\n },\r\n\r\n /**\r\n * v0.3 — Verifica entitlement de um resource via GET /sdk/v1/entitlements.\r\n */\r\n async check(\r\n resource: string,\r\n options?: { productId?: string; tenantId?: string },\r\n ) {\r\n if (!resource || typeof resource !== 'string') {\r\n throw new NeetruError('validation_failed', 'resource is required');\r\n }\r\n const productId = options?.productId ?? config.productId;\r\n const tenantId = options?.tenantId ?? config.tenantId;\r\n if (!productId || !tenantId) {\r\n throw new NeetruError(\r\n 'validation_failed',\r\n 'productId and tenantId required',\r\n );\r\n }\r\n const raw = await httpRequest<{\r\n allowed?: boolean;\r\n reason?: string;\r\n remaining?: number;\r\n limit?: number;\r\n planId?: string | null;\r\n planFeatures?: string[];\r\n }>(config, {\r\n method: 'GET',\r\n path: '/sdk/v1/entitlements',\r\n query: { productId, tenantId, feature: resource },\r\n requireAuth: true,\r\n });\r\n if (!raw || typeof raw.allowed !== 'boolean') {\r\n throw new NeetruError('invalid_response', 'usage.check response missing allowed');\r\n }\r\n return {\r\n allowed: raw.allowed,\r\n reason: raw.reason,\r\n remaining: raw.remaining,\r\n limit: raw.limit,\r\n planId: raw.planId,\r\n planFeatures: raw.planFeatures,\r\n };\r\n },\r\n };\r\n}\r\n","/**\r\n * Support namespace — criar e listar tickets do customer (v0.2).\r\n *\r\n * Endpoints (em prod):\r\n * - `POST /api/v1/products/{slug}/tickets` — criar ticket\r\n * - `GET /api/v1/products/{slug}/tickets` — listar meus tickets do produto\r\n *\r\n * Em dev (mocks ativos via factory) tudo é in-memory.\r\n *\r\n * Decisão: severity default é `normal`. `low` indica feature requests; `urgent`\r\n * pra outages production (paginating ops imediatamente em prod).\r\n */\r\nimport { NeetruError } from './errors';\r\nimport { httpRequest } from './http';\r\nimport type {\r\n CreateTicketInput,\r\n ResolvedConfig,\r\n SupportNamespace,\r\n SupportSeverity,\r\n SupportStatus,\r\n SupportTicket,\r\n} from './types';\r\n\r\nconst VALID_SEVERITIES: readonly SupportSeverity[] = ['low', 'normal', 'high', 'urgent'];\r\nconst VALID_STATUSES: readonly SupportStatus[] = ['open', 'pending', 'resolved', 'closed'];\r\n\r\ninterface RawTicket {\r\n id?: string;\r\n subject?: string;\r\n message?: string;\r\n severity?: string;\r\n status?: string;\r\n createdAt?: string;\r\n updatedAt?: string;\r\n productSlug?: string;\r\n}\r\n\r\nfunction toTicket(raw: unknown): SupportTicket {\r\n if (!raw || typeof raw !== 'object') {\r\n throw new NeetruError('invalid_response', 'Ticket response is not an object');\r\n }\r\n const r = raw as RawTicket;\r\n if (typeof r.id !== 'string') {\r\n throw new NeetruError('invalid_response', 'Ticket missing id');\r\n }\r\n return {\r\n id: r.id,\r\n subject: typeof r.subject === 'string' ? r.subject : '',\r\n message: typeof r.message === 'string' ? r.message : '',\r\n severity: VALID_SEVERITIES.includes(r.severity as SupportSeverity)\r\n ? (r.severity as SupportSeverity)\r\n : 'normal',\r\n status: VALID_STATUSES.includes(r.status as SupportStatus)\r\n ? (r.status as SupportStatus)\r\n : 'open',\r\n createdAt: typeof r.createdAt === 'string' ? r.createdAt : new Date().toISOString(),\r\n updatedAt: typeof r.updatedAt === 'string' ? r.updatedAt : undefined,\r\n productSlug: typeof r.productSlug === 'string' ? r.productSlug : undefined,\r\n };\r\n}\r\n\r\nexport function createSupportNamespace(config: ResolvedConfig): SupportNamespace {\r\n return {\r\n /**\r\n * Cria um ticket de suporte. Requer Bearer auth. Se `productSlug` não é\r\n * passado, o backend infere do escopo do token.\r\n */\r\n async createTicket(input: CreateTicketInput): Promise<SupportTicket> {\r\n if (!input || typeof input !== 'object') {\r\n throw new NeetruError('validation_failed', 'input is required');\r\n }\r\n if (!input.subject || typeof input.subject !== 'string') {\r\n throw new NeetruError('validation_failed', 'subject is required');\r\n }\r\n if (input.subject.length > 200) {\r\n throw new NeetruError('validation_failed', 'subject max 200 chars');\r\n }\r\n if (!input.message || typeof input.message !== 'string') {\r\n throw new NeetruError('validation_failed', 'message is required');\r\n }\r\n if (input.message.length > 10_000) {\r\n throw new NeetruError('validation_failed', 'message max 10000 chars');\r\n }\r\n if (input.severity && !VALID_SEVERITIES.includes(input.severity)) {\r\n throw new NeetruError('validation_failed', `severity must be one of ${VALID_SEVERITIES.join(', ')}`);\r\n }\r\n\r\n const slug = input.productSlug ?? '_default';\r\n const body: Record<string, unknown> = {\r\n subject: input.subject,\r\n message: input.message,\r\n severity: input.severity ?? 'normal',\r\n };\r\n\r\n const raw = await httpRequest<RawTicket | { ticket?: RawTicket }>(config, {\r\n method: 'POST',\r\n path: `/api/v1/products/${encodeURIComponent(slug)}/tickets`,\r\n body,\r\n requireAuth: true,\r\n });\r\n\r\n // Backend pode envelopar como { ticket: {...} } ou retornar direto.\r\n const candidate =\r\n raw && typeof raw === 'object' && 'ticket' in raw\r\n ? (raw as { ticket?: RawTicket }).ticket\r\n : raw;\r\n return toTicket(candidate);\r\n },\r\n\r\n /**\r\n * Lista tickets do customer no produto atual (escopo do token).\r\n */\r\n async listMyTickets(): Promise<SupportTicket[]> {\r\n const raw = await httpRequest<{ tickets?: unknown[] } | unknown[]>(config, {\r\n method: 'GET',\r\n path: '/api/v1/products/_default/tickets',\r\n requireAuth: true,\r\n });\r\n const list = Array.isArray(raw) ? raw : raw && typeof raw === 'object' && 'tickets' in raw ? (raw as { tickets?: unknown[] }).tickets ?? [] : [];\r\n return list.map(toTicket);\r\n },\r\n };\r\n}\r\n","/**\r\n * NeetruDbError — classe de erro especializada para o módulo `db`.\r\n *\r\n * Conforma com 02-sdk.md §3.5: `NeetruDbError extends NeetruError`,\r\n * campo `code` fechado em `NeetruDbErrorCode`, campo `retryable` booleano,\r\n * campo `dbId` opaco para correlação.\r\n *\r\n * Herda de `NeetruError` para que um `catch (e) { if (e instanceof NeetruError) }`\r\n * genérico continue pegando erros de DB. Quem quer granularidade usa\r\n * `instanceof NeetruDbError` e o `code` fechado.\r\n */\r\n\r\nimport { NeetruError } from './errors';\r\n\r\n/**\r\n * Códigos de erro específicos do módulo `db`.\r\n *\r\n * - `db_unavailable` — lifecycle: provisionando / falhou / arquivado.\r\n * NÃO significa \"sem rede\" — offline é transparente.\r\n * - `db_not_found` — documento/coleção não encontrado no servidor.\r\n * - `db_conflict` — conflito de escrita detectado.\r\n * - `db_quota_exceeded` — quota de escrita/leitura excedida no banco.\r\n * - `db_permission_denied` — sem permissão para a operação.\r\n * - `db_invalid_query` — query inválida (campo, operador, tipo).\r\n * - `db_timeout` — operação excedeu o timeout.\r\n * - `offline_quota_exceeded`— IndexedDB cheio; a escrita não pode ser enfileirada.\r\n * - `offline_unavailable` — IndexedDB indisponível; SDK degrado para cache RAM.\r\n */\r\nexport type NeetruDbErrorCode =\r\n | 'db_unavailable'\r\n | 'db_not_found'\r\n | 'db_conflict'\r\n | 'db_quota_exceeded'\r\n | 'db_permission_denied'\r\n | 'db_invalid_query'\r\n | 'db_timeout'\r\n | 'offline_quota_exceeded'\r\n | 'offline_unavailable';\r\n\r\n/**\r\n * Códigos que são retryable por natureza.\r\n */\r\nconst RETRYABLE_CODES = new Set<NeetruDbErrorCode>([\r\n 'db_unavailable',\r\n 'db_conflict',\r\n 'db_timeout',\r\n]);\r\n\r\n/**\r\n * Erro tipado do módulo `db` — estende `NeetruError` para compatibilidade.\r\n *\r\n * @example\r\n * ```ts\r\n * try {\r\n * await client.db.collection('orders').add({ ... });\r\n * } catch (e) {\r\n * if (e instanceof NeetruDbError && e.code === 'offline_quota_exceeded') {\r\n * // IndexedDB cheio — notificar usuário\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport class NeetruDbError extends NeetruError {\r\n /** Código de erro fechado — específico de DB. */\r\n public override readonly code: NeetruDbErrorCode;\r\n\r\n /**\r\n * `true` para erros transientes que o produto pode tentar novamente.\r\n * São retryable: `db_unavailable`, `db_conflict`, `db_timeout`.\r\n */\r\n public readonly retryable: boolean;\r\n\r\n /**\r\n * ID opaco do banco lógico — só para correlação com logs do Core.\r\n * Nunca deve ser exibido ao usuário final.\r\n */\r\n public readonly dbId?: string;\r\n\r\n constructor(code: NeetruDbErrorCode, message: string, dbId?: string) {\r\n super(code, message);\r\n this.name = 'NeetruDbError';\r\n this.code = code;\r\n this.retryable = RETRYABLE_CODES.has(code);\r\n this.dbId = dbId;\r\n // Preserva o prototype chain (TypeScript + downlevel).\r\n Object.setPrototypeOf(this, NeetruDbError.prototype);\r\n }\r\n}\r\n","/**\r\n * QueryEngine — avaliador de query offline, puro e determinístico.\r\n *\r\n * Aplica um `QueryDescriptor` (where / orderBy / limit / cursor) sobre um array\r\n * de documentos em memória. Equivale a um motor de query local para o cache do\r\n * IndexedDB, cobrindo o subconjunto definido em I3 §5.2.\r\n *\r\n * Design:\r\n * - ZERO dependências externas.\r\n * - PURO: mesma entrada → mesma saída. Sem side-effects, sem I/O.\r\n * - Semântica compatível com Firestore:\r\n * • campo ausente no doc → doc EXCLUÍDO pelo filtro.\r\n * • ordem canônica de tipos mistos: null < number < string < boolean.\r\n * • tie-break final sempre por docId (lexicográfico).\r\n */\r\n\r\nimport type {\r\n OfflineDoc,\r\n QueryDescriptor,\r\n WhereFilter,\r\n WhereOp,\r\n OrderBy,\r\n QueryCursor,\r\n} from './types';\r\n\r\n// ─── Ordem canônica de tipos mistos ──────────────────────────────────────────\r\n\r\n/**\r\n * Retorna um número de \"rank\" de tipo para garantir ordem estável entre\r\n * valores de tipos diferentes (I3 §5.3): null < number < string < boolean.\r\n */\r\nfunction typeRank(v: unknown): number {\r\n if (v === null || v === undefined) return 0;\r\n if (typeof v === 'number') return 1;\r\n if (typeof v === 'string') return 2;\r\n if (typeof v === 'boolean') return 3;\r\n return 4; // object/array — vai para o fim\r\n}\r\n\r\n/**\r\n * Compara dois valores usando a ordem canônica de tipos mistos.\r\n * Retorna negativo, 0, ou positivo (como `Array.sort` espera).\r\n */\r\nfunction compareValues(a: unknown, b: unknown): number {\r\n const ra = typeRank(a);\r\n const rb = typeRank(b);\r\n if (ra !== rb) return ra - rb;\r\n\r\n // Mesmo tipo\r\n if (a === null || a === undefined) return 0;\r\n if (typeof a === 'number' && typeof b === 'number') return a - b;\r\n if (typeof a === 'string' && typeof b === 'string') return a < b ? -1 : a > b ? 1 : 0;\r\n if (typeof a === 'boolean' && typeof b === 'boolean') return a === b ? 0 : a ? 1 : -1;\r\n // Fallback para outros tipos — converte para string\r\n const sa = String(a);\r\n const sb = String(b);\r\n return sa < sb ? -1 : sa > sb ? 1 : 0;\r\n}\r\n\r\n// ─── Acesso a campo aninhado ──────────────────────────────────────────────────\r\n\r\n/**\r\n * Lê o valor de um campo no doc (suporta paths simples como 'status' ou\r\n * 'address.city' com ponto). Retorna `undefined` se o campo não existir —\r\n * o QueryEngine trata `undefined` como campo ausente (doc excluído).\r\n */\r\nfunction getField(data: Record<string, unknown>, field: string): unknown {\r\n const parts = field.split('.');\r\n let current: unknown = data;\r\n for (const part of parts) {\r\n if (current === null || current === undefined || typeof current !== 'object') {\r\n return undefined;\r\n }\r\n current = (current as Record<string, unknown>)[part];\r\n }\r\n return current;\r\n}\r\n\r\n// ─── Avaliação de filtros ──────────────────────────────────────────────────────\r\n\r\n/**\r\n * Avalia um único `WhereFilter` contra os dados de um documento.\r\n * Campo ausente → false (doc excluído, semântica Firestore).\r\n */\r\nfunction evaluateFilter(\r\n data: Record<string, unknown>,\r\n filter: WhereFilter,\r\n): boolean {\r\n const fieldValue = getField(data, filter.field);\r\n\r\n // Campo ausente — doc excluído\r\n if (fieldValue === undefined) return false;\r\n\r\n const { op, value } = filter;\r\n\r\n switch (op as WhereOp) {\r\n case '==':\r\n return fieldValue === value;\r\n case '!=':\r\n return fieldValue !== value;\r\n case '<':\r\n return compareValues(fieldValue, value) < 0;\r\n case '<=':\r\n return compareValues(fieldValue, value) <= 0;\r\n case '>':\r\n return compareValues(fieldValue, value) > 0;\r\n case '>=':\r\n return compareValues(fieldValue, value) >= 0;\r\n case 'array-contains':\r\n return Array.isArray(fieldValue) && fieldValue.includes(value);\r\n case 'in':\r\n if (!Array.isArray(value)) return false;\r\n return (value as unknown[]).includes(fieldValue);\r\n case 'not-in':\r\n if (!Array.isArray(value)) return true;\r\n return !(value as unknown[]).includes(fieldValue);\r\n default:\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Aplica todos os filtros `where` em AND sobre os dados de um documento.\r\n */\r\nfunction matchesAllFilters(\r\n data: Record<string, unknown>,\r\n filters: WhereFilter[],\r\n): boolean {\r\n return filters.every((f) => evaluateFilter(data, f));\r\n}\r\n\r\n// ─── Ordenação ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Constrói uma função de comparação para `Array.sort` baseada em um\r\n * `OrderBy` + tie-break final por docId.\r\n */\r\nfunction buildComparator<T>(\r\n orderBy: OrderBy | undefined,\r\n): (a: OfflineDoc<T>, b: OfflineDoc<T>) => number {\r\n return (a, b) => {\r\n if (orderBy) {\r\n const aVal = getField(a.data as Record<string, unknown>, orderBy.field);\r\n const bVal = getField(b.data as Record<string, unknown>, orderBy.field);\r\n const cmp = compareValues(aVal, bVal);\r\n if (cmp !== 0) {\r\n return orderBy.direction === 'desc' ? -cmp : cmp;\r\n }\r\n }\r\n // Tie-break por docId (lexicográfico ascendente, sempre)\r\n return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;\r\n };\r\n}\r\n\r\n// ─── Cursor ───────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Aplica o cursor de paginação ao array **já ordenado**.\r\n *\r\n * - `startAfter`: descarta o doc-cursor e tudo antes dele (inclusive).\r\n * - `endBefore`: mantém apenas os docs antes do cursor (exclusive).\r\n *\r\n * Se o docId do cursor não for encontrado no array, a lista é retornada\r\n * integralmente (falha graceful — cache pode não ter o doc-cursor).\r\n */\r\nfunction applyCursor<T>(\r\n sorted: OfflineDoc<T>[],\r\n cursor: QueryCursor,\r\n): OfflineDoc<T>[] {\r\n const idx = sorted.findIndex((d) => d.id === cursor.docId);\r\n if (idx === -1) {\r\n // Cursor não encontrado — retorna tudo (comportamento conservador)\r\n return sorted;\r\n }\r\n if (cursor.type === 'startAfter') {\r\n return sorted.slice(idx + 1);\r\n } else {\r\n // endBefore\r\n return sorted.slice(0, idx);\r\n }\r\n}\r\n\r\n// ─── QueryEngine ──────────────────────────────────────────────────────────────\r\n\r\n/** Resultado da avaliação de uma query. */\r\nexport interface QueryResult<T = Record<string, unknown>> {\r\n /** Documentos que casaram com a query, na ordem correta, respeitando limit. */\r\n docs: Array<{ id: string; data: T }>;\r\n /**\r\n * Indica que o resultado pode estar incompleto — o cache pode não ter todos\r\n * os documentos da coleção (a query offline só vê o que foi cacheado).\r\n * O chamador deve setar `stale: true` quando `incomplete: true`.\r\n */\r\n incomplete: boolean;\r\n}\r\n\r\n/**\r\n * QueryEngine — avaliador puro de queries sobre documentos em memória.\r\n *\r\n * Uso:\r\n * ```ts\r\n * const engine = new QueryEngine();\r\n * const result = engine.evaluate(docs, query);\r\n * ```\r\n *\r\n * Ou via helper estático:\r\n * ```ts\r\n * const result = QueryEngine.evaluate(docs, query);\r\n * ```\r\n */\r\nexport class QueryEngine {\r\n /**\r\n * Avalia um `QueryDescriptor` contra um array de `OfflineDoc`.\r\n *\r\n * Pipeline (I3 §5.3):\r\n * 1. Filtra docs com `deleted:false`.\r\n * 2. Aplica `where` (AND de todos os filtros).\r\n * 3. Ordena por `orderBy` + tie-break por docId.\r\n * 4. Aplica cursor (`startAfter` / `endBefore`).\r\n * 5. Corta em `limit`.\r\n */\r\n evaluate<T = Record<string, unknown>>(\r\n docs: OfflineDoc<T>[],\r\n query: QueryDescriptor,\r\n ): QueryResult<T> {\r\n // 1. Excluir tombstones\r\n let filtered = docs.filter((d) => !d.meta.deleted);\r\n\r\n // 2. Aplicar filtros where (AND)\r\n const filters = query.where ?? [];\r\n if (filters.length > 0) {\r\n filtered = filtered.filter((d) =>\r\n matchesAllFilters(d.data as Record<string, unknown>, filters),\r\n );\r\n }\r\n\r\n // 3. Ordenar\r\n const comparator = buildComparator<T>(query.orderBy);\r\n const sorted = [...filtered].sort(comparator);\r\n\r\n // 4. Cursor\r\n const afterCursor = query.cursor ? applyCursor(sorted, query.cursor) : sorted;\r\n\r\n // 5. Limit\r\n const limitN = Math.min(query.limit ?? 20, 500);\r\n const limited = afterCursor.slice(0, limitN);\r\n\r\n return {\r\n docs: limited.map((d) => ({ id: d.id, data: d.data })),\r\n // `incomplete` é sempre true aqui — o QueryEngine não sabe se o cache\r\n // tem todos os docs da coleção. É responsabilidade do chamador (LocalStore)\r\n // injetar o flag de completude baseado nos metadados do query_cache.\r\n incomplete: true,\r\n };\r\n }\r\n\r\n // ─── Static helper ─────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Helper estático para uso sem instanciar a classe.\r\n * Equivalente a `new QueryEngine().evaluate(docs, query)`.\r\n */\r\n static evaluate<T = Record<string, unknown>>(\r\n docs: OfflineDoc<T>[],\r\n query: QueryDescriptor,\r\n ): QueryResult<T> {\r\n return new QueryEngine().evaluate(docs, query);\r\n }\r\n}\r\n\r\n// ─── Exports auxiliares (para testes e outros módulos internos) ───────────────\r\n\r\nexport { compareValues, evaluateFilter, matchesAllFilters, getField };\r\n","/**\r\n * LocalStore — cache IndexedDB durável da camada offline do @neetru/sdk.\r\n *\r\n * Implementa o esquema de 5 object stores definido em I3 §3.3:\r\n * - `documents` — espelho dos documentos por coleção (keyPath: [collection, id])\r\n * - `mutations` — fila de escritas pendentes (keyPath: mutationId, índice por seq)\r\n * - `query_cache` — resultados de query materializados (keyPath: queryHash)\r\n * - `sync_meta` — watermarks e estado de sincronização (keyPath: key)\r\n * - `conflict_log`— escritas perdedoras LWW (keyPath: id, autoIncrement)\r\n *\r\n * Wrapper sobre `idb` (Promise-based, ~1KB) — não usa IndexedDB cru.\r\n *\r\n * Design:\r\n * - Todas as escritas são duráveis (IndexedDB transactions).\r\n * - Leituras sempre do IndexedDB — sem camada de memória adicional.\r\n * - Expõe os acessores que MutationQueue usa (putMutation, getMutation,\r\n * listMutations, deleteMutation) mais os métodos de doc/meta/conflict/query_cache.\r\n */\r\n\r\nimport { openDB, type IDBPDatabase } from 'idb';\r\nimport type { OfflineDoc, Mutation, ConflictRecord, QueryDescriptor } from './types';\r\nimport { QueryEngine, type QueryResult } from './query-engine';\r\n\r\n// ─── Versão do schema IndexedDB ───────────────────────────────────────────────\r\n\r\nconst SCHEMA_VERSION = 1;\r\n\r\n// ─── Tipos internos (espelham I3 §3.3) ───────────────────────────────────────\r\n\r\n/** Entrada na store `query_cache`. */\r\nexport interface CachedQuery {\r\n queryHash: string;\r\n collection: string;\r\n resultIds: string[];\r\n nextCursor: string | null;\r\n syncedAt: number;\r\n resumeToken: string | null;\r\n complete: boolean;\r\n}\r\n\r\n/** Opções de filtro para listConflicts. */\r\nexport interface ListConflictsOptions {\r\n /** Se definido, filtra por `delivered`. */\r\n delivered?: boolean;\r\n}\r\n\r\n/** Opções de filtro para listMutations. */\r\nexport interface ListMutationsOptions {\r\n /** Filtra por status. */\r\n status?: Mutation['status'];\r\n /** Filtra por [collection, docId] combinados. */\r\n collection?: string;\r\n docId?: string;\r\n}\r\n\r\n// ─── Nome das stores ──────────────────────────────────────────────────────────\r\n\r\nconst STORE_DOCUMENTS = 'documents';\r\nconst STORE_MUTATIONS = 'mutations';\r\nconst STORE_QUERY_CACHE = 'query_cache';\r\nconst STORE_SYNC_META = 'sync_meta';\r\nconst STORE_CONFLICT_LOG = 'conflict_log';\r\n\r\n// ─── LocalStore ───────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * LocalStore — cache IndexedDB durável.\r\n *\r\n * Uso:\r\n * ```ts\r\n * const store = new LocalStore('neetru-db__my-product__db1__prod');\r\n * await store.open();\r\n * await store.putDoc(doc);\r\n * const doc = await store.getDoc('orders', 'order-1');\r\n * ```\r\n *\r\n * Nomeação do banco: `neetru-db__{productSlug}__{dbId}__{env}` (I3 §3.2).\r\n * O chamador é responsável por montar o nome correto.\r\n */\r\nexport class LocalStore {\r\n private db: IDBPDatabase | null = null;\r\n private readonly dbName: string;\r\n\r\n constructor(dbName: string) {\r\n this.dbName = dbName;\r\n }\r\n\r\n // ─── Ciclo de vida ──────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Abre (ou reabre) o banco IndexedDB e executa o upgrade de schema se necessário.\r\n * Idempotente — chamadas subsequentes são no-ops se o banco já está aberto.\r\n */\r\n async open(): Promise<void> {\r\n if (this.db !== null) return;\r\n\r\n this.db = await openDB(this.dbName, SCHEMA_VERSION, {\r\n upgrade(db) {\r\n // ── documents ────────────────────────────────────────────────────────\r\n if (!db.objectStoreNames.contains(STORE_DOCUMENTS)) {\r\n const docsStore = db.createObjectStore(STORE_DOCUMENTS, {\r\n keyPath: ['collection', 'id'],\r\n });\r\n // I3 §3.3: índices\r\n docsStore.createIndex('by_collection', 'collection');\r\n docsStore.createIndex('by_collection_state', ['collection', 'meta.state']);\r\n docsStore.createIndex('by_updatedAtServer', 'meta.updatedAtServer');\r\n }\r\n\r\n // ── mutations ────────────────────────────────────────────────────────\r\n if (!db.objectStoreNames.contains(STORE_MUTATIONS)) {\r\n const mutStore = db.createObjectStore(STORE_MUTATIONS, {\r\n keyPath: 'mutationId',\r\n });\r\n // seq: índice para listagem em ordem\r\n mutStore.createIndex('by_seq', 'seq');\r\n // I3 §3.3: índices\r\n mutStore.createIndex('by_status', 'status');\r\n mutStore.createIndex('by_doc', ['collection', 'docId']);\r\n mutStore.createIndex('by_batch', 'batchId');\r\n }\r\n\r\n // ── query_cache ──────────────────────────────────────────────────────\r\n if (!db.objectStoreNames.contains(STORE_QUERY_CACHE)) {\r\n db.createObjectStore(STORE_QUERY_CACHE, { keyPath: 'queryHash' });\r\n }\r\n\r\n // ── sync_meta ────────────────────────────────────────────────────────\r\n if (!db.objectStoreNames.contains(STORE_SYNC_META)) {\r\n db.createObjectStore(STORE_SYNC_META, { keyPath: 'key' });\r\n }\r\n\r\n // ── conflict_log ─────────────────────────────────────────────────────\r\n if (!db.objectStoreNames.contains(STORE_CONFLICT_LOG)) {\r\n const conflictStore = db.createObjectStore(STORE_CONFLICT_LOG, {\r\n keyPath: 'id',\r\n autoIncrement: true,\r\n });\r\n conflictStore.createIndex('by_delivered', 'delivered');\r\n conflictStore.createIndex('by_doc', ['collection', 'docId']);\r\n }\r\n },\r\n });\r\n }\r\n\r\n /** Fecha o banco IndexedDB. */\r\n async close(): Promise<void> {\r\n this.db?.close();\r\n this.db = null;\r\n }\r\n\r\n private assertOpen(): IDBPDatabase {\r\n if (this.db === null) {\r\n throw new Error('LocalStore: banco não está aberto. Chame open() primeiro.');\r\n }\r\n return this.db;\r\n }\r\n\r\n // ─── Documents ──────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Retorna um documento pelo [collection, id], ou `null` se não existir.\r\n * Retorna tombstones (deleted: true) — o chamador decide se deve mostrá-los.\r\n */\r\n async getDoc<T = Record<string, unknown>>(\r\n collection: string,\r\n id: string,\r\n ): Promise<OfflineDoc<T> | null> {\r\n const db = this.assertOpen();\r\n const result = await db.get(STORE_DOCUMENTS, [collection, id]);\r\n return (result as OfflineDoc<T> | undefined) ?? null;\r\n }\r\n\r\n /**\r\n * Insere ou atualiza um documento na store `documents`.\r\n * O documento é identificado pelo keyPath composto `[collection, id]`.\r\n */\r\n async putDoc<T = Record<string, unknown>>(doc: OfflineDoc<T>): Promise<void> {\r\n const db = this.assertOpen();\r\n await db.put(STORE_DOCUMENTS, doc);\r\n }\r\n\r\n /**\r\n * Marca um documento como tombstone (`deleted: true`).\r\n * Não remove fisicamente — o tombstone é necessário para reconciliação.\r\n * No-op se o documento não existir.\r\n */\r\n async deleteDoc(collection: string, id: string): Promise<void> {\r\n const db = this.assertOpen();\r\n const existing = await db.get(STORE_DOCUMENTS, [collection, id]);\r\n if (!existing) return;\r\n await db.put(STORE_DOCUMENTS, {\r\n ...existing,\r\n meta: {\r\n ...(existing as OfflineDoc).meta,\r\n deleted: true,\r\n updatedAtLocal: Date.now(),\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Lista documentos de uma coleção, aplicando o QueryDescriptor via QueryEngine.\r\n *\r\n * I3 §5.3: a listagem lê todos os docs da coleção pelo índice `by_collection`\r\n * e delega a filtragem/ordenação/paginação ao QueryEngine (que opera em memória).\r\n */\r\n async listDocs<T = Record<string, unknown>>(\r\n collection: string,\r\n query: QueryDescriptor,\r\n ): Promise<QueryResult<T>> {\r\n const db = this.assertOpen();\r\n const rawDocs = await db.getAllFromIndex(STORE_DOCUMENTS, 'by_collection', collection);\r\n return QueryEngine.evaluate<T>(rawDocs as OfflineDoc<T>[], query);\r\n }\r\n\r\n // ─── Sync meta (key-value) ──────────────────────────────────────────────────\r\n\r\n /**\r\n * Retorna o valor de uma chave da store `sync_meta`, ou `null` se não existir.\r\n *\r\n * Chaves conhecidas (I3 §3.3):\r\n * 'lastSyncWatermark', 'resumeToken:<col>', 'schemaVersion',\r\n * 'lastFullResyncAt', 'leaderTabId'.\r\n */\r\n async getMeta(key: string): Promise<unknown> {\r\n const db = this.assertOpen();\r\n const entry = await db.get(STORE_SYNC_META, key);\r\n if (!entry) return null;\r\n return (entry as { key: string; value: unknown }).value;\r\n }\r\n\r\n /**\r\n * Armazena ou atualiza um valor na store `sync_meta`.\r\n */\r\n async setMeta(key: string, value: unknown): Promise<void> {\r\n const db = this.assertOpen();\r\n await db.put(STORE_SYNC_META, { key, value });\r\n }\r\n\r\n // ─── Conflict log ───────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Adiciona um registro de conflito ao `conflict_log`.\r\n * O `id` é autoIncrement — não deve ser fornecido pelo chamador.\r\n */\r\n async appendConflict(record: Omit<ConflictRecord, 'id'>): Promise<ConflictRecord> {\r\n const db = this.assertOpen();\r\n const id = await db.add(STORE_CONFLICT_LOG, record);\r\n return { ...record, id: id as number };\r\n }\r\n\r\n /**\r\n * Lista registros do `conflict_log`.\r\n * Filtra por `delivered` se a opção for fornecida.\r\n */\r\n async listConflicts(options?: ListConflictsOptions): Promise<ConflictRecord[]> {\r\n const db = this.assertOpen();\r\n const all = await db.getAll(STORE_CONFLICT_LOG) as ConflictRecord[];\r\n\r\n if (options?.delivered !== undefined) {\r\n return all.filter((r) => r.delivered === options.delivered);\r\n }\r\n return all;\r\n }\r\n\r\n /**\r\n * Marca um registro do `conflict_log` como entregue ao produto.\r\n */\r\n async markConflictDelivered(id: number): Promise<void> {\r\n const db = this.assertOpen();\r\n const existing = await db.get(STORE_CONFLICT_LOG, id) as ConflictRecord | undefined;\r\n if (!existing) return;\r\n await db.put(STORE_CONFLICT_LOG, { ...existing, delivered: true });\r\n }\r\n\r\n // ─── Mutations (acessores usados pelo MutationQueue) ────────────────────────\r\n\r\n /**\r\n * Insere ou atualiza uma mutação na store `mutations`.\r\n * Key: `mutationId`.\r\n */\r\n async putMutation(mutation: Mutation): Promise<void> {\r\n const db = this.assertOpen();\r\n await db.put(STORE_MUTATIONS, mutation);\r\n }\r\n\r\n /**\r\n * Retorna uma mutação pelo `mutationId`, ou `null` se não existir.\r\n */\r\n async getMutation(mutationId: string): Promise<Mutation | null> {\r\n const db = this.assertOpen();\r\n const result = await db.get(STORE_MUTATIONS, mutationId);\r\n return (result as Mutation | undefined) ?? null;\r\n }\r\n\r\n /**\r\n * Lista mutações com filtros opcionais.\r\n * Resultado ordenado por `seq` crescente.\r\n */\r\n async listMutations(options?: ListMutationsOptions): Promise<Mutation[]> {\r\n const db = this.assertOpen();\r\n\r\n let mutations: Mutation[];\r\n\r\n if (options?.status !== undefined) {\r\n mutations = (await db.getAllFromIndex(STORE_MUTATIONS, 'by_status', options.status)) as Mutation[];\r\n } else if (options?.collection !== undefined && options.docId !== undefined) {\r\n mutations = (await db.getAllFromIndex(STORE_MUTATIONS, 'by_doc', [options.collection, options.docId])) as Mutation[];\r\n } else {\r\n // Lê tudo pelo índice by_seq para garantir ordem\r\n mutations = (await db.getAllFromIndex(STORE_MUTATIONS, 'by_seq')) as Mutation[];\r\n }\r\n\r\n // Ordena por seq crescente (defensivo — o índice by_seq já ordena, mas\r\n // leituras por outros índices podem não preservar a ordem)\r\n return mutations.sort((a, b) => a.seq - b.seq);\r\n }\r\n\r\n /**\r\n * Remove uma mutação pelo `mutationId`.\r\n * No-op se não existir.\r\n */\r\n async deleteMutation(mutationId: string): Promise<void> {\r\n const db = this.assertOpen();\r\n await db.delete(STORE_MUTATIONS, mutationId);\r\n }\r\n\r\n // ─── Collection discovery ────────────────────────────────────────────────────\r\n\r\n /**\r\n * Retorna a lista de coleções únicas presentes na store `documents`.\r\n *\r\n * Usado pelo SyncEngine no full resync para descobrir coleções cujos docs\r\n * precisam ser verificados contra a resposta do servidor (tombstone detection).\r\n *\r\n * Implementação: itera o índice `by_collection` com `openKeyCursor` para\r\n * coletar os valores únicos de forma eficiente (sem carregar os docs completos).\r\n */\r\n async listCollections(): Promise<string[]> {\r\n const db = this.assertOpen();\r\n const allDocs = await db.getAllFromIndex(STORE_DOCUMENTS, 'by_collection') as OfflineDoc[];\r\n const collections = new Set<string>();\r\n for (const doc of allDocs) {\r\n collections.add(doc.collection);\r\n }\r\n return Array.from(collections);\r\n }\r\n\r\n // ─── Query cache ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Retorna a entrada de `query_cache` para um hash de query, ou `null`.\r\n */\r\n async getQueryCache(queryHash: string): Promise<CachedQuery | null> {\r\n const db = this.assertOpen();\r\n const result = await db.get(STORE_QUERY_CACHE, queryHash);\r\n return (result as CachedQuery | undefined) ?? null;\r\n }\r\n\r\n /**\r\n * Insere ou atualiza uma entrada de `query_cache`.\r\n */\r\n async putQueryCache(entry: CachedQuery): Promise<void> {\r\n const db = this.assertOpen();\r\n await db.put(STORE_QUERY_CACHE, entry);\r\n }\r\n\r\n /**\r\n * Remove uma entrada de `query_cache` pelo queryHash.\r\n */\r\n async deleteQueryCache(queryHash: string): Promise<void> {\r\n const db = this.assertOpen();\r\n await db.delete(STORE_QUERY_CACHE, queryHash);\r\n }\r\n}\r\n","/**\r\n * MutationQueue — fila durável e atomicamente-ordenada de escritas pendentes.\r\n *\r\n * Implementa I3 §4 e §5 (integração com QueryEngine/LocalStore):\r\n *\r\n * - Enqueue atômico: aplica ao cache de documentos e grava na fila em uma\r\n * única transação IndexedDB — crash mid-enqueue nunca corrompe a ordenação.\r\n * - Seq monotônico: autoIncrement via geração local (não confia no IndexedDB\r\n * autoIncrement para seq para poder controlar coalescing antes da gravação).\r\n * - MutationId: UUID v4 client-generated (I3 §4.2) — idempotência no replay.\r\n * - Coalescing (I3 §4.4): mutações adjacentes do mesmo doc (sem batchId\r\n * diferente, sem inflight no meio) são colapsadas antes do enfileiramento.\r\n * - Drain: retorna mutações queued em ordem de seq (para o SyncEngine).\r\n * - markApplied / markFailed / markInflight: ciclo de vida de cada mutação.\r\n *\r\n * Persistência: totalmente via LocalStore (IndexedDB). Nenhum estado em RAM\r\n * além do ponteiro de seq atual (re-sync ao instanciar se necessário).\r\n */\r\n\r\nimport type { LocalStore } from './local-store';\r\nimport type { Mutation, MutationKind } from './types';\r\n\r\n// ─── Geração de UUID v4 ───────────────────────────────────────────────────────\r\n\r\n/**\r\n * Gera um UUID v4 aleatório (I3 §4.2).\r\n * Usa `crypto.randomUUID()` quando disponível (Node ≥19 / browsers modernos),\r\n * com fallback manual para ambientes mais antigos.\r\n */\r\nfunction generateUUIDv4(): string {\r\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\r\n return crypto.randomUUID();\r\n }\r\n // Fallback RFC 4122 v4\r\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\r\n const r = (Math.random() * 16) | 0;\r\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\r\n return v.toString(16);\r\n });\r\n}\r\n\r\n// ─── Tipos de entrada para enqueue ───────────────────────────────────────────\r\n\r\n/** Parâmetros para enfileirar uma nova mutação. */\r\nexport interface EnqueueParams {\r\n collection: string;\r\n /** Para `add`, pode ser omitido — um UUID v4 será gerado automaticamente. */\r\n docId?: string;\r\n op: MutationKind;\r\n payload: Record<string, unknown> | null;\r\n baseVersion: string | null;\r\n batchId: string | null;\r\n}\r\n\r\n/** Opções para drain(). */\r\nexport interface DrainOptions {\r\n /** Máximo de mutações a retornar. Default: sem limite. */\r\n maxBatch?: number;\r\n}\r\n\r\n// ─── MutationQueue ────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * MutationQueue — fila durável de escritas pendentes.\r\n *\r\n * Construída sobre LocalStore. Cada MutationQueue é ligada a um LocalStore\r\n * (e portanto a um banco IndexedDB). Uma instância por banco lógico Neetru.\r\n *\r\n * ```ts\r\n * const store = new LocalStore(dbName);\r\n * await store.open();\r\n * const queue = new MutationQueue(store);\r\n *\r\n * const mut = await queue.enqueue({\r\n * collection: 'orders',\r\n * op: 'add',\r\n * payload: { total: 100 },\r\n * baseVersion: null,\r\n * batchId: null,\r\n * });\r\n * // mut.id, mut.seq, mut.mutationId disponíveis imediatamente.\r\n * ```\r\n */\r\nexport class MutationQueue {\r\n private readonly store: LocalStore;\r\n /**\r\n * Ponteiro de sequência local.\r\n * Inicializado com 0 — o primeiro enqueue sincroniza o valor real do banco\r\n * (`_syncSeq`), garantindo que nunca sobreponha um seq existente.\r\n */\r\n private seqCounter = 0;\r\n private seqSynced = false;\r\n\r\n constructor(store: LocalStore) {\r\n this.store = store;\r\n }\r\n\r\n // ─── Seq management ─────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Sincroniza o ponteiro de seq com o maior seq existente no banco.\r\n * Chamado lazy no primeiro enqueue.\r\n */\r\n private async syncSeq(): Promise<void> {\r\n if (this.seqSynced) return;\r\n const all = await this.store.listMutations();\r\n if (all.length > 0) {\r\n const maxSeq = Math.max(...all.map((m) => m.seq));\r\n this.seqCounter = maxSeq;\r\n }\r\n this.seqSynced = true;\r\n }\r\n\r\n private nextSeq(): number {\r\n this.seqCounter += 1;\r\n return this.seqCounter;\r\n }\r\n\r\n // ─── Coalescing ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Tenta coalescir `newOp`/`newPayload` com a mutação existente `existing`.\r\n *\r\n * Regras de coalescing (I3 §4.4):\r\n * - update + update → update com merge dos campos (segundo vence nos conflitos)\r\n * - add + update → add com campos mesclados\r\n * - add + remove → nada (remove a mutação existente, retorna null para remove)\r\n * - set + update → set com campos mesclados\r\n * - any + remove (base servidor) → remove\r\n *\r\n * Retorna:\r\n * - `{ coalesced: Mutation }` — substitui a mutação existente (update in-place)\r\n * - `{ removed: true }` — a mutação existente deve ser deletada (add+remove)\r\n * - `null` — não é possível coalescir\r\n */\r\n private tryCoalesce(\r\n existing: Mutation,\r\n newOp: MutationKind,\r\n newPayload: Record<string, unknown> | null,\r\n newBatchId: string | null,\r\n ): { coalesced: Mutation } | { removed: true } | null {\r\n // Não coalesce se batchIds diferentes (um ou ambos definidos e diferentes)\r\n if (existing.batchId !== newBatchId) return null;\r\n\r\n // Não coalesce através de inflight\r\n if (existing.status === 'inflight') return null;\r\n\r\n const existingOp = existing.op;\r\n\r\n // add + remove → remove da fila inteira (doc nunca existiu no servidor)\r\n if (existingOp === 'add' && newOp === 'remove') {\r\n return { removed: true };\r\n }\r\n\r\n // update + update → merge dos campos\r\n if (existingOp === 'update' && newOp === 'update') {\r\n return {\r\n coalesced: {\r\n ...existing,\r\n payload: { ...(existing.payload ?? {}), ...(newPayload ?? {}) },\r\n },\r\n };\r\n }\r\n\r\n // add + update → add com campos mesclados\r\n if (existingOp === 'add' && newOp === 'update') {\r\n return {\r\n coalesced: {\r\n ...existing,\r\n op: 'add',\r\n payload: { ...(existing.payload ?? {}), ...(newPayload ?? {}) },\r\n },\r\n };\r\n }\r\n\r\n // set + update → set com campos mesclados\r\n if (existingOp === 'set' && newOp === 'update') {\r\n return {\r\n coalesced: {\r\n ...existing,\r\n op: 'set',\r\n payload: { ...(existing.payload ?? {}), ...(newPayload ?? {}) },\r\n },\r\n };\r\n }\r\n\r\n // update/set/add + remove (base servidor presente) → remove\r\n if (newOp === 'remove') {\r\n return {\r\n coalesced: {\r\n ...existing,\r\n op: 'remove',\r\n payload: null,\r\n },\r\n };\r\n }\r\n\r\n // Não coalesça nos demais casos (ex: remove + set — nova operação distinta)\r\n return null;\r\n }\r\n\r\n // ─── Enqueue ─────────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Enfileira uma nova mutação.\r\n *\r\n * Processo (I3 §4.1):\r\n * 1. Gera docId se op=add e não fornecido.\r\n * 2. Sincroniza seq (lazy).\r\n * 3. Tenta coalescir com a última mutação queued do mesmo [collection, docId].\r\n * 4. Se coalescing:\r\n * - `removed` → deleta mutação existente; retorna sem enfileirar nova.\r\n * - `coalesced` → substitui a mutação existente (mesmo seq, mesmo mutationId).\r\n * 5. Se não coalesce → enfileira nova mutação (novo seq, novo mutationId).\r\n *\r\n * Atômico: a persistência final é uma única operação putMutation.\r\n */\r\n async enqueue(params: EnqueueParams): Promise<Mutation> {\r\n const { collection, op, payload, baseVersion, batchId } = params;\r\n\r\n // 1. docId\r\n const docId = params.docId ?? (op === 'add' ? generateUUIDv4() : '');\r\n\r\n // 2. Sincroniza seq se necessário\r\n await this.syncSeq();\r\n\r\n // 3. Tenta coalescir com mutação existente do mesmo [collection, docId]\r\n // Busca a última mutação queued para este doc (não inflight)\r\n const existingMutations = await this.store.listMutations({ collection, docId });\r\n const lastQueued = existingMutations\r\n .filter((m) => m.status === 'queued')\r\n .sort((a, b) => b.seq - a.seq)[0]; // o mais recente\r\n\r\n if (lastQueued !== undefined) {\r\n const coalesceResult = this.tryCoalesce(lastQueued, op, payload, batchId);\r\n\r\n if (coalesceResult !== null) {\r\n if ('removed' in coalesceResult) {\r\n // add + remove → remove da fila\r\n await this.store.deleteMutation(lastQueued.mutationId);\r\n // Retorna uma mutação \"fantasma\" representando o no-op\r\n // (o chamador recebe o resultado, mas a fila está vazia para este doc)\r\n const phantomMut: Mutation = {\r\n seq: lastQueued.seq,\r\n mutationId: generateUUIDv4(),\r\n collection,\r\n docId,\r\n op: 'remove',\r\n payload: null,\r\n baseVersion,\r\n enqueuedAt: Date.now(),\r\n attempts: 0,\r\n lastError: null,\r\n status: 'queued',\r\n batchId,\r\n };\r\n // Não persiste — este doc foi cancelado\r\n return phantomMut;\r\n }\r\n\r\n // coalesced → atualiza a mutação existente no banco\r\n const { coalesced } = coalesceResult;\r\n await this.store.putMutation(coalesced);\r\n return coalesced;\r\n }\r\n }\r\n\r\n // 4. Nova mutação\r\n const seq = this.nextSeq();\r\n const mutation: Mutation = {\r\n seq,\r\n mutationId: generateUUIDv4(),\r\n collection,\r\n docId,\r\n op,\r\n payload,\r\n baseVersion,\r\n enqueuedAt: Date.now(),\r\n attempts: 0,\r\n lastError: null,\r\n status: 'queued',\r\n batchId,\r\n };\r\n\r\n await this.store.putMutation(mutation);\r\n return mutation;\r\n }\r\n\r\n // ─── Leitura da fila ─────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Retorna a primeira mutação com status `queued` (menor seq), ou `null`.\r\n */\r\n async peek(): Promise<Mutation | null> {\r\n const pending = await this.listPending();\r\n return pending[0] ?? null;\r\n }\r\n\r\n /**\r\n * Retorna todas as mutações com status `queued`, ordenadas por seq crescente.\r\n */\r\n async listPending(): Promise<Mutation[]> {\r\n return this.store.listMutations({ status: 'queued' });\r\n }\r\n\r\n /**\r\n * Retorna TODAS as mutações (qualquer status), ordenadas por seq crescente.\r\n * Útil para inspeção e testes.\r\n */\r\n async listAll(): Promise<Mutation[]> {\r\n return this.store.listMutations();\r\n }\r\n\r\n /**\r\n * Conta o número de mutações com status `queued`.\r\n */\r\n async countPending(): Promise<number> {\r\n const pending = await this.listPending();\r\n return pending.length;\r\n }\r\n\r\n /**\r\n * Retorna um lote de mutações `queued` para drenagem (I3 §6.2 FASE 1).\r\n * Ordena por seq crescente. O SyncEngine chama drain(), itera, e marca\r\n * cada mutação como applied/failed.\r\n */\r\n async drain(options?: DrainOptions): Promise<Mutation[]> {\r\n const pending = await this.listPending();\r\n if (options?.maxBatch !== undefined && options.maxBatch > 0) {\r\n return pending.slice(0, options.maxBatch);\r\n }\r\n return pending;\r\n }\r\n\r\n // ─── Ciclo de vida de mutações ────────────────────────────────────────────────\r\n\r\n /**\r\n * Marca uma mutação como `inflight` (está sendo enviada ao Core).\r\n * Chamado pelo SyncEngine antes de enviar o request.\r\n */\r\n async markInflight(mutationId: string): Promise<void> {\r\n const mut = await this.store.getMutation(mutationId);\r\n if (!mut) return;\r\n await this.store.putMutation({ ...mut, status: 'inflight' });\r\n }\r\n\r\n /**\r\n * Remove a mutação da fila (sucesso de replay).\r\n * Chamado pelo SyncEngine ao receber confirmação do Core.\r\n */\r\n async markApplied(mutationId: string): Promise<void> {\r\n await this.store.deleteMutation(mutationId);\r\n }\r\n\r\n /**\r\n * Marca uma mutação como `failed` e registra o erro.\r\n * Incrementa `attempts`. Chamado pelo SyncEngine em falha permanente.\r\n */\r\n async markFailed(mutationId: string, error: string): Promise<void> {\r\n const mut = await this.store.getMutation(mutationId);\r\n if (!mut) return;\r\n await this.store.putMutation({\r\n ...mut,\r\n status: 'failed',\r\n lastError: error,\r\n attempts: mut.attempts + 1,\r\n });\r\n }\r\n\r\n /**\r\n * Incrementa `attempts` e volta para `queued` (falha transiente com backoff).\r\n * Chamado pelo SyncEngine em falha transiente (5xx, timeout).\r\n */\r\n async markRetry(mutationId: string, error: string): Promise<void> {\r\n const mut = await this.store.getMutation(mutationId);\r\n if (!mut) return;\r\n await this.store.putMutation({\r\n ...mut,\r\n status: 'queued',\r\n lastError: error,\r\n attempts: mut.attempts + 1,\r\n });\r\n }\r\n}\r\n","/**\r\n * SyncEngine — orquestrador da camada offline do @neetru/sdk.\r\n *\r\n * Implementa as 3 fases de sincronização definidas em I3 §6:\r\n *\r\n * FASE 1 — DRENAR A FILA (push)\r\n * Envia mutações pendentes ao Core via SyncTransport.\r\n * Cada mutação é marcada inflight, enviada e depois:\r\n * - CONFIRMADA → removida da fila (markApplied)\r\n * - SUPERADA (LWW)→ ConflictRecord gravado, cache atualizado\r\n * - REJEITADA → resolveRejected + ConflictRecord + removida\r\n * - FALHA TRANSIENTE → markRetry + PARA a drenagem (ordem preservada)\r\n *\r\n * FASE 2 — RECONCILIAR O CACHE (pull)\r\n * Busca mudanças do servidor desde o watermark ou resume token.\r\n * Cada documento passa pelo ConflictResolver (LWW) e é gravado no LocalStore.\r\n * Changes são emitidos pelo ChangeBus.\r\n * Se `resyncRequired` → aciona full resync em vez de pull incremental.\r\n *\r\n * FASE 3 — REABRIR LISTENERS (realtime)\r\n * Atualiza SyncState para refletir que o cache está reconciliado.\r\n * O ChangeBus já foi alimentado nas fases anteriores — os listeners\r\n * ativos na camada superior (onSnapshot/onDoc) recebem snapshots frescos.\r\n *\r\n * Garantias:\r\n * - SOMENTE a aba LÍDER executa o sync (TabCoordinator.isLeader()).\r\n * - Re-entrante-safe: um sync em progresso bloqueia novos disparos.\r\n * - Fail-closed: falha transiente retém a mutação; falha de pull não\r\n * corrompe o cache nem o watermark.\r\n * - Idempotente: o SyncTransport usa mutationId como chave de idempotência.\r\n *\r\n * O SyncTransport é INJETADO — a ligação real com o Core acontece na camada\r\n * de adaptação, não aqui. Isso torna o SyncEngine 100% testável com fake.\r\n */\r\n\r\nimport type { LocalStore } from './local-store';\r\nimport type { MutationQueue } from './mutation-queue';\r\nimport type { ConflictResolver } from './conflict-resolver';\r\nimport type { ChangeBus } from './change-bus';\r\nimport type { Mutation, SyncState, Change, Unsubscribe } from './types';\r\n\r\n// ─── SyncTransport — interface injetável ──────────────────────────────────────\r\n\r\n/**\r\n * Documento retornado pelo servidor em push/pull/resync.\r\n */\r\nexport interface ServerDoc {\r\n collection: string;\r\n id: string;\r\n data: Record<string, unknown>;\r\n serverVersion: string;\r\n serverTimestamp: number;\r\n /** `true` se o doc foi deletado no servidor. */\r\n deleted: boolean;\r\n}\r\n\r\n/**\r\n * Resultado individual de uma mutação enviada ao Core (FASE 1).\r\n */\r\nexport type MutationResult =\r\n | {\r\n mutationId: string;\r\n outcome: 'confirmed';\r\n serverVersion: string;\r\n serverTimestamp: number;\r\n }\r\n | {\r\n mutationId: string;\r\n outcome: 'superseded';\r\n serverVersion: string;\r\n serverTimestamp: number;\r\n serverData: Record<string, unknown>;\r\n }\r\n | {\r\n mutationId: string;\r\n outcome: 'rejected';\r\n reason: 'rejected_permission' | 'rejected_validation';\r\n serverVersion: string | null;\r\n serverData: Record<string, unknown> | null;\r\n };\r\n\r\n/** Retorno de pushMutations. */\r\nexport interface PushMutationsResult {\r\n results: MutationResult[];\r\n}\r\n\r\n/** Retorno de pullChanges. */\r\nexport interface PullChangesResult {\r\n docs: ServerDoc[];\r\n newWatermark: number | null;\r\n /** `true` quando o resume token / watermark ficou inválido (gap grande). */\r\n resyncRequired: boolean;\r\n}\r\n\r\n/** Retorno de fullResync. */\r\nexport interface FullResyncResult {\r\n docs: ServerDoc[];\r\n newWatermark: number | null;\r\n}\r\n\r\n/**\r\n * Contrato do transporte de sync — injetado no SyncEngine.\r\n *\r\n * A implementação real usa os endpoints `/api/sdk/v1/db/*` do Core.\r\n * Em testes, usa-se um FakeSyncTransport.\r\n *\r\n * Per I3 §6:\r\n * - `pushMutations` → FASE 1: envia mutações em ordem de seq.\r\n * - `pullChanges` → FASE 2: busca delta desde o watermark/resumeToken.\r\n * - `fullResync` → FASE 2 (fallback): lista completa das coleções ativas.\r\n */\r\nexport interface SyncTransport {\r\n /**\r\n * Envia um lote de mutações ao Core.\r\n * O Core aplica, verifica conflito LWW e retorna um resultado por mutação.\r\n * A ordem do array deve ser preservada (seq crescente).\r\n */\r\n pushMutations(mutations: Mutation[]): Promise<PushMutationsResult>;\r\n\r\n /**\r\n * Busca documentos modificados no servidor desde `sinceWatermark`.\r\n * `sinceWatermark === null` indica primeiro sync (sem base conhecida).\r\n * `resumeToken` é o token de change stream (nosql-vm); pode ser null.\r\n *\r\n * Retorna `resyncRequired: true` se o gap é grande demais para pull incremental.\r\n */\r\n pullChanges(\r\n sinceWatermark: number | null,\r\n resumeToken: string | null,\r\n ): Promise<PullChangesResult>;\r\n\r\n /**\r\n * Faz um full resync das coleções informadas.\r\n * Retorna TODOS os documentos atuais (paginado internamente pelo transporte).\r\n * Docs ausentes na resposta foram deletados durante o gap.\r\n */\r\n fullResync(collections: string[]): Promise<FullResyncResult>;\r\n\r\n /**\r\n * (Opcional) Registra uma subscription realtime para uma coleção específica.\r\n *\r\n * Implementado pelo WebSocket transport (nosql-vm): chama\r\n * `NeetruRealtimeClient.subscribe()` e alimenta os frames delta/resync\r\n * no `ChangeBus` da camada offline.\r\n *\r\n * Transportes REST e Firestore não implementam este método (undefined).\r\n * O chamador (`DbCollectionRefImpl.onSnapshot`) verifica antes de invocar.\r\n *\r\n * @param collection - Nome da coleção a subscrever.\r\n * @param onChange - Callback que recebe changes quando um delta/resync chega.\r\n * `null` payload = resync full necessário.\r\n * @returns Função de unsubscribe.\r\n */\r\n subscribeCollection?: (\r\n collection: string,\r\n onChange: (\r\n changes: Array<{ type: 'added' | 'modified' | 'removed'; docId: string; data: Record<string, unknown> | null }>,\r\n needsResync: boolean,\r\n ) => void,\r\n ) => () => void;\r\n}\r\n\r\n// ─── Interface dos colaboradores (subset usado pelo SyncEngine) ───────────────\r\n\r\n/** Subset de TabCoordinator usado pelo SyncEngine. */\r\ninterface TabCoordinatorLike {\r\n isLeader(): boolean;\r\n onRoleChange(cb: (role: 'leader' | 'follower') => void): Unsubscribe;\r\n}\r\n\r\n/** Subset de ConnectivityMonitor usado pelo SyncEngine. */\r\ninterface ConnectivityMonitorLike {\r\n readonly isOnline: boolean;\r\n subscribe(cb: (state: 'online' | 'offline') => void): Unsubscribe;\r\n}\r\n\r\n// ─── Opções de configuração ───────────────────────────────────────────────────\r\n\r\nexport interface SyncEngineOptions {\r\n store: LocalStore;\r\n queue: MutationQueue;\r\n resolver: ConflictResolver;\r\n bus: ChangeBus;\r\n transport: SyncTransport;\r\n tabCoordinator: TabCoordinatorLike;\r\n connectivity: ConnectivityMonitorLike;\r\n /**\r\n * Intervalo do resync periódico em ms.\r\n * `0` desativa (útil em testes). Default: 5 * 60 * 1000 (5 min).\r\n */\r\n periodicSyncIntervalMs?: number;\r\n}\r\n\r\n// ─── SyncEngine ───────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * SyncEngine — orquestra as 3 fases de sincronização offline (I3 §6).\r\n *\r\n * ```ts\r\n * const engine = new SyncEngine({ store, queue, resolver, bus, transport,\r\n * tabCoordinator, connectivity });\r\n *\r\n * // Estado atual (snapshot síncrono)\r\n * const state = engine.getSyncState();\r\n *\r\n * // Observar mudanças de estado\r\n * const unsub = engine.onSyncStateChange((s) => console.log(s));\r\n *\r\n * // Forçar sync imediato (ex.: botão \"sincronizar agora\")\r\n * await engine.flush();\r\n *\r\n * // Teardown\r\n * engine.destroy();\r\n * ```\r\n *\r\n * O engine também é disparado automaticamente por:\r\n * - transição offline → online (ConnectivityMonitor)\r\n * - promoção a líder (TabCoordinator.onRoleChange)\r\n * - periodicSyncIntervalMs (resync de segurança)\r\n */\r\nexport class SyncEngine {\r\n private readonly _store: LocalStore;\r\n private readonly _queue: MutationQueue;\r\n private readonly _resolver: ConflictResolver;\r\n private readonly _bus: ChangeBus;\r\n private readonly _transport: SyncTransport;\r\n private readonly _tabCoordinator: TabCoordinatorLike;\r\n private readonly _connectivity: ConnectivityMonitorLike;\r\n\r\n /** `true` se um sync está atualmente em progresso — guarda re-entrância. */\r\n private _syncing = false;\r\n\r\n /** `true` se destroy() foi chamado. */\r\n private _destroyed = false;\r\n\r\n /**\r\n * Conjunto de coleções \"conhecidas\" pelo engine.\r\n * Populado ao aplicar docs do servidor (Fase 1 e 2) e ao ler do cache.\r\n * Persiste em sync_meta['activeCollections'] para sobreviver a reloads.\r\n */\r\n private _activeCollections = new Set<string>();\r\n\r\n /** Estado de sync atual (fonte de verdade em RAM). */\r\n private _state: SyncState;\r\n\r\n /** Listeners de mudança de SyncState. */\r\n private readonly _stateListeners = new Set<(state: SyncState) => void>();\r\n\r\n /** Cleanup functions dos listeners externos. */\r\n private readonly _cleanups: Unsubscribe[] = [];\r\n\r\n /** Timer de resync periódico. */\r\n private _periodicTimer: ReturnType<typeof setInterval> | null = null;\r\n\r\n constructor(opts: SyncEngineOptions) {\r\n this._store = opts.store;\r\n this._queue = opts.queue;\r\n this._resolver = opts.resolver;\r\n this._bus = opts.bus;\r\n this._transport = opts.transport;\r\n this._tabCoordinator = opts.tabCoordinator;\r\n this._connectivity = opts.connectivity;\r\n\r\n // Estado inicial\r\n this._state = this._buildInitialState();\r\n\r\n // Conecta os gatilhos externos\r\n this._wireListeners();\r\n\r\n // Timer periódico\r\n const intervalMs = opts.periodicSyncIntervalMs ?? 5 * 60 * 1000;\r\n if (intervalMs > 0) {\r\n this._periodicTimer = setInterval(() => {\r\n this._triggerSync('periodic');\r\n }, intervalMs);\r\n }\r\n }\r\n\r\n // ─── API pública ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Expõe o transporte de sync para acesso direto por `DbCollectionRefImpl`.\r\n * Necessário para que `onSnapshot` possa chamar `subscribeCollection` no\r\n * transport nosql-vm (HIGH-1 fix — realtime deltas).\r\n */\r\n get transport(): SyncTransport {\r\n return this._transport;\r\n }\r\n\r\n /**\r\n * Retorna o estado de sync atual (snapshot síncrono).\r\n * Equivale a `client.db.syncState` na API pública do SDK (I3 §10.3).\r\n *\r\n * `pendingWrites` reflete o valor mais recente calculado de forma assíncrona.\r\n * Para garantir o valor mais atualizado, aguarde `refreshPendingWrites()` antes.\r\n */\r\n getSyncState(): SyncState {\r\n return { ...this._state };\r\n }\r\n\r\n /**\r\n * Força a atualização de `pendingWrites` e retorna o estado atualizado.\r\n * Útil quando o chamador precisa do pendingWrites fresco sem aguardar um sync.\r\n */\r\n async refreshPendingWrites(): Promise<SyncState> {\r\n await this._refreshPendingWrites();\r\n return { ...this._state };\r\n }\r\n\r\n /**\r\n * Registra um listener de mudanças no SyncState.\r\n * Retorna uma função de unsubscribe.\r\n */\r\n onSyncStateChange(cb: (state: SyncState) => void): Unsubscribe {\r\n this._stateListeners.add(cb);\r\n return () => {\r\n this._stateListeners.delete(cb);\r\n };\r\n }\r\n\r\n /**\r\n * Força um sync imediato (I3 §10.3 `flush()`).\r\n * Resolve quando a fila esvazia OU rejeita se o engine estiver destruído.\r\n */\r\n async flush(): Promise<void> {\r\n if (this._destroyed) return;\r\n await this.sync();\r\n }\r\n\r\n /**\r\n * Executa as 3 fases de sincronização.\r\n *\r\n * Guarda re-entrância: se já está em progresso, retorna imediatamente.\r\n * NÃO executa se esta aba não é líder ou se está offline.\r\n */\r\n async sync(): Promise<void> {\r\n if (this._destroyed) return;\r\n\r\n // Somente o líder sincroniza (I3 §6.1)\r\n if (!this._tabCoordinator.isLeader()) return;\r\n\r\n // Offline — não tenta sincronizar\r\n if (!this._connectivity.isOnline) return;\r\n\r\n // Re-entrância: não double-run\r\n if (this._syncing) return;\r\n\r\n this._syncing = true;\r\n this._updateState({ status: 'syncing' });\r\n\r\n try {\r\n // ── FASE 1: DRENAR A FILA (push) ────────────────────────────────────────\r\n const phase1Ok = await this._phase1Push();\r\n if (!phase1Ok) {\r\n // Falha transiente na Fase 1 — aborta o ciclo (I3 §6.2: PARA a drenagem)\r\n this._updateState({ status: 'idle' });\r\n this._syncing = false;\r\n return;\r\n }\r\n\r\n // ── FASE 2: RECONCILIAR O CACHE (pull) ──────────────────────────────────\r\n await this._phase2Pull();\r\n\r\n // ── FASE 3: REABRIR LISTENERS (realtime) ─────────────────────────────────\r\n this._phase3Realtime();\r\n\r\n // Atualiza lastSyncedAt\r\n this._updateState({ status: 'idle', lastSyncedAt: Date.now() });\r\n } catch (err) {\r\n // Erro inesperado nas fases — log silencioso, estado de erro\r\n this._updateState({ status: 'idle' });\r\n } finally {\r\n this._syncing = false;\r\n }\r\n }\r\n\r\n /**\r\n * Teardown: para timers, remove listeners, marca como destroyed.\r\n */\r\n destroy(): void {\r\n if (this._destroyed) return;\r\n this._destroyed = true;\r\n\r\n if (this._periodicTimer !== null) {\r\n clearInterval(this._periodicTimer);\r\n this._periodicTimer = null;\r\n }\r\n\r\n for (const cleanup of this._cleanups) {\r\n try { cleanup(); } catch { /* silencioso */ }\r\n }\r\n this._cleanups.length = 0;\r\n this._stateListeners.clear();\r\n }\r\n\r\n // ─── FASE 1 — push (drenar a fila) ───────────────────────────────────────────\r\n\r\n /**\r\n * Drena a MutationQueue, enviando mutações em ordem de seq.\r\n *\r\n * Retorna `true` se a fase completou sem falhas transientes.\r\n * Retorna `false` se houve falha transiente (ciclo deve ser abortado).\r\n */\r\n private async _phase1Push(): Promise<boolean> {\r\n const mutations = await this._queue.drain();\r\n if (mutations.length === 0) return true;\r\n\r\n // Marca todas como inflight\r\n for (const mut of mutations) {\r\n await this._queue.markInflight(mut.mutationId);\r\n }\r\n\r\n let result: PushMutationsResult;\r\n try {\r\n result = await this._transport.pushMutations(mutations);\r\n } catch (err) {\r\n // Falha transiente no transporte — volta todas para queued\r\n for (const mut of mutations) {\r\n const errMsg = err instanceof Error ? err.message : String(err);\r\n await this._queue.markRetry(mut.mutationId, errMsg);\r\n }\r\n return false; // aborta o ciclo\r\n }\r\n\r\n // Processa resultados\r\n const busChanges: Change[] = [];\r\n\r\n for (const res of result.results) {\r\n const mut = mutations.find((m) => m.mutationId === res.mutationId);\r\n if (!mut) continue;\r\n\r\n if (res.outcome === 'confirmed') {\r\n // Sucesso — remove da fila e atualiza doc no cache\r\n await this._queue.markApplied(mut.mutationId);\r\n await this._applySyncedDoc(\r\n mut.collection,\r\n mut.docId,\r\n res.serverVersion,\r\n res.serverTimestamp,\r\n mut,\r\n busChanges,\r\n );\r\n } else if (res.outcome === 'superseded') {\r\n // LWW: escrita local foi superada pelo servidor\r\n await this._queue.markApplied(mut.mutationId);\r\n await this._applySuperseded(mut, res, busChanges);\r\n } else if (res.outcome === 'rejected') {\r\n // Rejeição permanente\r\n await this._queue.markApplied(mut.mutationId); // remove da fila\r\n await this._applyRejected(mut, res, busChanges);\r\n }\r\n }\r\n\r\n if (busChanges.length > 0) {\r\n this._bus.emit(busChanges);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /** Atualiza o cache após confirmação de escrita (outcome=confirmed). */\r\n private async _applySyncedDoc(\r\n collection: string,\r\n docId: string,\r\n serverVersion: string,\r\n serverTimestamp: number,\r\n mut: Mutation,\r\n busChanges: Change[],\r\n ): Promise<void> {\r\n const existing = await this._store.getDoc(collection, docId);\r\n\r\n if (mut.op === 'remove') {\r\n // Remoção confirmada → tombstone\r\n if (existing) {\r\n await this._store.putDoc({\r\n ...existing,\r\n meta: {\r\n ...existing.meta,\r\n serverVersion,\r\n updatedAtServer: serverTimestamp,\r\n updatedAtLocal: Date.now(),\r\n state: 'synced',\r\n deleted: true,\r\n pendingMutationIds: [],\r\n },\r\n });\r\n busChanges.push({ type: 'removed', collection, doc: { id: docId, data: existing.data } });\r\n }\r\n return;\r\n }\r\n\r\n const newData = mut.payload ?? (existing?.data ?? {});\r\n const updatedDoc = {\r\n collection,\r\n id: docId,\r\n data: mut.op === 'update' ? { ...(existing?.data ?? {}), ...newData } : newData,\r\n meta: {\r\n serverVersion,\r\n updatedAtServer: serverTimestamp,\r\n updatedAtLocal: Date.now(),\r\n state: 'synced' as const,\r\n pendingMutationIds: [],\r\n deleted: false,\r\n ownerId: existing?.meta.ownerId ?? null,\r\n },\r\n };\r\n\r\n await this._store.putDoc(updatedDoc);\r\n busChanges.push({\r\n type: existing ? 'modified' : 'added',\r\n collection,\r\n doc: { id: docId, data: updatedDoc.data },\r\n });\r\n }\r\n\r\n /** Processa resultado 'superseded' (LWW: servidor venceu). */\r\n private async _applySuperseded(\r\n mut: Mutation,\r\n res: Extract<MutationResult, { outcome: 'superseded' }>,\r\n busChanges: Change[],\r\n ): Promise<void> {\r\n const localDoc = await this._store.getDoc(mut.collection, mut.docId);\r\n\r\n // Constrói envelope do servidor com timestamp maior para forçar server_wins\r\n const serverDocEnvelope = {\r\n collection: mut.collection,\r\n id: mut.docId,\r\n data: res.serverData,\r\n meta: {\r\n serverVersion: res.serverVersion,\r\n updatedAtServer: res.serverTimestamp,\r\n updatedAtLocal: Date.now(),\r\n state: 'synced' as const,\r\n pendingMutationIds: [],\r\n deleted: false,\r\n ownerId: localDoc?.meta.ownerId ?? null,\r\n },\r\n };\r\n\r\n // Usa ConflictResolver para gerar o ConflictRecord\r\n // Cria um doc local com updatedAtServer anterior para garantir server_wins\r\n const localDocForResolver = localDoc ?? {\r\n collection: mut.collection,\r\n id: mut.docId,\r\n data: (mut.payload ?? {}) as Record<string, unknown>,\r\n meta: {\r\n serverVersion: mut.baseVersion,\r\n updatedAtServer: res.serverTimestamp - 1, // garante server é mais novo\r\n updatedAtLocal: mut.enqueuedAt,\r\n state: 'pending' as const,\r\n pendingMutationIds: [mut.mutationId],\r\n deleted: false,\r\n ownerId: null,\r\n },\r\n };\r\n\r\n const resolveResult = this._resolver.resolve(\r\n localDocForResolver,\r\n serverDocEnvelope,\r\n mut,\r\n );\r\n\r\n // Sempre grava ConflictRecord em superseded (independente do resultado do resolver)\r\n const conflictRecord = resolveResult.conflictRecord ?? {\r\n collection: mut.collection,\r\n docId: mut.docId,\r\n mutationId: mut.mutationId,\r\n losingData: (mut.payload ?? {}) as Record<string, unknown>,\r\n winningData: res.serverData,\r\n reason: 'lww_server_newer' as const,\r\n detectedAt: Date.now(),\r\n delivered: false,\r\n };\r\n await this._store.appendConflict(conflictRecord);\r\n\r\n // Atualiza cache com o dado do servidor\r\n const updatedDoc = {\r\n collection: mut.collection,\r\n id: mut.docId,\r\n data: res.serverData,\r\n meta: {\r\n serverVersion: res.serverVersion,\r\n updatedAtServer: res.serverTimestamp,\r\n updatedAtLocal: Date.now(),\r\n state: 'synced' as const,\r\n pendingMutationIds: [],\r\n deleted: false,\r\n ownerId: localDoc?.meta.ownerId ?? null,\r\n },\r\n };\r\n await this._store.putDoc(updatedDoc);\r\n busChanges.push({\r\n type: localDoc ? 'modified' : 'added',\r\n collection: mut.collection,\r\n doc: { id: mut.docId, data: res.serverData },\r\n });\r\n }\r\n\r\n /** Processa resultado 'rejected' (permissão/validação negada). */\r\n private async _applyRejected(\r\n mut: Mutation,\r\n res: Extract<MutationResult, { outcome: 'rejected' }>,\r\n busChanges: Change[],\r\n ): Promise<void> {\r\n // Obtém ou reconstrói o doc local para o resolver\r\n const storedDoc = await this._store.getDoc(mut.collection, mut.docId);\r\n const localDoc = storedDoc ?? {\r\n collection: mut.collection,\r\n id: mut.docId,\r\n data: (mut.payload ?? {}) as Record<string, unknown>,\r\n meta: {\r\n serverVersion: mut.baseVersion,\r\n updatedAtServer: null,\r\n updatedAtLocal: mut.enqueuedAt,\r\n state: 'pending' as const,\r\n pendingMutationIds: [mut.mutationId],\r\n deleted: false,\r\n ownerId: null,\r\n },\r\n };\r\n\r\n const serverDocEnvelope = res.serverData\r\n ? {\r\n ...localDoc,\r\n data: res.serverData,\r\n meta: {\r\n ...localDoc.meta,\r\n serverVersion: res.serverVersion ?? localDoc.meta.serverVersion,\r\n },\r\n }\r\n : null;\r\n\r\n const resolveResult = this._resolver.resolveRejected(\r\n localDoc,\r\n serverDocEnvelope,\r\n mut,\r\n res.reason,\r\n );\r\n\r\n // Sempre grava ConflictRecord em rejected\r\n const conflictRecord = resolveResult.conflictRecord ?? {\r\n collection: mut.collection,\r\n docId: mut.docId,\r\n mutationId: mut.mutationId,\r\n losingData: (mut.payload ?? {}) as Record<string, unknown>,\r\n winningData: (res.serverData ?? {}) as Record<string, unknown>,\r\n reason: res.reason,\r\n detectedAt: Date.now(),\r\n delivered: false,\r\n };\r\n await this._store.appendConflict(conflictRecord);\r\n\r\n // Reverte cache ao estado do servidor (ou mantém se não há serverData)\r\n if (res.serverData) {\r\n await this._store.putDoc({\r\n ...localDoc,\r\n data: res.serverData,\r\n meta: {\r\n ...localDoc.meta,\r\n state: 'synced',\r\n pendingMutationIds: [],\r\n },\r\n });\r\n busChanges.push({\r\n type: 'modified',\r\n collection: mut.collection,\r\n doc: { id: mut.docId, data: res.serverData },\r\n });\r\n } else {\r\n // Sem dado do servidor → mantém o que há, mas limpa pendências\r\n await this._store.putDoc({\r\n ...localDoc,\r\n meta: {\r\n ...localDoc.meta,\r\n state: 'synced',\r\n pendingMutationIds: [],\r\n },\r\n });\r\n }\r\n }\r\n\r\n // ─── FASE 2 — pull (reconciliar o cache) ─────────────────────────────────────\r\n\r\n /**\r\n * Busca mudanças do servidor e aplica ao cache via ConflictResolver.\r\n *\r\n * Se `resyncRequired === true`, faz full resync em vez de pull incremental.\r\n */\r\n private async _phase2Pull(): Promise<void> {\r\n const watermark = (await this._store.getMeta('lastSyncWatermark')) as number | null;\r\n const resumeToken = (await this._store.getMeta('lastResumeToken')) as string | null;\r\n\r\n let pullResult: PullChangesResult;\r\n try {\r\n pullResult = await this._transport.pullChanges(watermark, resumeToken);\r\n } catch {\r\n // Falha no pull — não corrompe cache nem watermark; tenta no próximo ciclo\r\n return;\r\n }\r\n\r\n if (pullResult.resyncRequired) {\r\n await this._phase2FullResync();\r\n return;\r\n }\r\n\r\n // Pull incremental bem-sucedido\r\n const busChanges: Change[] = [];\r\n await this._applyServerDocs(pullResult.docs, busChanges, false);\r\n\r\n if (pullResult.newWatermark !== null) {\r\n await this._store.setMeta('lastSyncWatermark', pullResult.newWatermark);\r\n }\r\n\r\n if (busChanges.length > 0) {\r\n this._bus.emit(busChanges);\r\n }\r\n }\r\n\r\n /** Full resync: lista completa + detecta deleções por ausência. */\r\n private async _phase2FullResync(): Promise<void> {\r\n // Coleta as coleções que têm documentos no cache local\r\n const collections = await this._getActiveCollections();\r\n\r\n let resyncResult: FullResyncResult;\r\n try {\r\n resyncResult = await this._transport.fullResync(collections);\r\n } catch {\r\n // Falha no resync — não corrompe cache; tenta no próximo ciclo\r\n return;\r\n }\r\n\r\n const busChanges: Change[] = [];\r\n\r\n // Aplica os docs retornados\r\n await this._applyServerDocs(resyncResult.docs, busChanges, true);\r\n\r\n // Detecta deleções: docs locais que não vieram no resync → tombstone (I3 §6.3)\r\n const returnedKeys = new Set(\r\n resyncResult.docs.map((d) => `${d.collection}::${d.id}`),\r\n );\r\n\r\n for (const col of collections) {\r\n // listDocs retorna { id, data } sem meta — precisamos dos docs completos\r\n const queryResult = await this._store.listDocs(col, {});\r\n for (const { id } of queryResult.docs) {\r\n const key = `${col}::${id}`;\r\n if (!returnedKeys.has(key)) {\r\n // Busca o doc completo com meta para verificar e atualizar\r\n const fullDoc = await this._store.getDoc(col, id);\r\n if (fullDoc && !fullDoc.meta.deleted) {\r\n // Doc sumiu do servidor → tombstone\r\n await this._store.putDoc({\r\n ...fullDoc,\r\n meta: {\r\n ...fullDoc.meta,\r\n deleted: true,\r\n updatedAtLocal: Date.now(),\r\n state: 'synced',\r\n },\r\n });\r\n busChanges.push({\r\n type: 'removed',\r\n collection: col,\r\n doc: { id, data: fullDoc.data },\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (resyncResult.newWatermark !== null) {\r\n await this._store.setMeta('lastSyncWatermark', resyncResult.newWatermark);\r\n }\r\n await this._store.setMeta('lastFullResyncAt', Date.now());\r\n\r\n if (busChanges.length > 0) {\r\n this._bus.emit(busChanges);\r\n }\r\n }\r\n\r\n /**\r\n * Aplica uma lista de ServerDoc ao cache local via ConflictResolver.\r\n *\r\n * `isFullResync = true` indica que o conjunto é completo — usamos isso para\r\n * otimizar a path (sempre sobrescreve docs synced; pending passam pelo LWW).\r\n */\r\n private async _applyServerDocs(\r\n docs: ServerDoc[],\r\n busChanges: Change[],\r\n _isFullResync: boolean,\r\n ): Promise<void> {\r\n for (const serverDoc of docs) {\r\n const localDoc = await this._store.getDoc(serverDoc.collection, serverDoc.id);\r\n\r\n if (serverDoc.deleted) {\r\n // Doc deletado no servidor → tombstone\r\n if (localDoc && !localDoc.meta.deleted) {\r\n await this._store.putDoc({\r\n ...localDoc,\r\n meta: {\r\n ...localDoc.meta,\r\n deleted: true,\r\n serverVersion: serverDoc.serverVersion,\r\n updatedAtServer: serverDoc.serverTimestamp,\r\n updatedAtLocal: Date.now(),\r\n state: 'synced',\r\n },\r\n });\r\n busChanges.push({\r\n type: 'removed',\r\n collection: serverDoc.collection,\r\n doc: { id: serverDoc.id, data: localDoc.data },\r\n });\r\n }\r\n continue;\r\n }\r\n\r\n // Se o doc local está 'pending' (tem mutações não enviadas ainda),\r\n // passa pelo ConflictResolver (§6.2: não sobrescreve cegamente).\r\n // Na prática, após a Fase 1 a maioria dos pendentes já virou synced.\r\n if (localDoc && localDoc.meta.state === 'pending') {\r\n // Constrói envelope do servidor para o resolver\r\n const serverEnvelope = {\r\n collection: serverDoc.collection,\r\n id: serverDoc.id,\r\n data: serverDoc.data,\r\n meta: {\r\n serverVersion: serverDoc.serverVersion,\r\n updatedAtServer: serverDoc.serverTimestamp,\r\n updatedAtLocal: Date.now(),\r\n state: 'synced' as const,\r\n pendingMutationIds: [],\r\n deleted: false,\r\n ownerId: localDoc.meta.ownerId,\r\n },\r\n };\r\n\r\n // Busca a primeira mutação pendente para este doc (para o resolver)\r\n const pendingMuts = await this._queue.drain();\r\n const docMut = pendingMuts.find(\r\n (m) => m.collection === serverDoc.collection && m.docId === serverDoc.id,\r\n );\r\n\r\n if (docMut) {\r\n const result = this._resolver.resolve(localDoc, serverEnvelope, docMut);\r\n if (result.conflictRecord) {\r\n await this._store.appendConflict(result.conflictRecord);\r\n }\r\n // Marca o doc como conflito para resolver na próxima Fase 1\r\n await this._store.putDoc({\r\n ...localDoc,\r\n meta: { ...localDoc.meta, state: 'conflict' },\r\n });\r\n continue;\r\n }\r\n }\r\n\r\n // Doc local synced ou não existente → sobrescreve com servidor\r\n const isNew = !localDoc;\r\n const newDoc = {\r\n collection: serverDoc.collection,\r\n id: serverDoc.id,\r\n data: serverDoc.data,\r\n meta: {\r\n serverVersion: serverDoc.serverVersion,\r\n updatedAtServer: serverDoc.serverTimestamp,\r\n updatedAtLocal: Date.now(),\r\n state: 'synced' as const,\r\n pendingMutationIds: [],\r\n deleted: false,\r\n ownerId: localDoc?.meta.ownerId ?? null,\r\n },\r\n };\r\n await this._store.putDoc(newDoc);\r\n busChanges.push({\r\n type: isNew ? 'added' : 'modified',\r\n collection: serverDoc.collection,\r\n doc: { id: serverDoc.id, data: serverDoc.data },\r\n });\r\n }\r\n }\r\n\r\n // ─── FASE 3 — reabre listeners (realtime) ─────────────────────────────────────\r\n\r\n /**\r\n * Fase 3: sinaliza que o cache está reconciliado.\r\n *\r\n * O transporte de tempo real (Firestore onSnapshot / WebSocket) é gerido\r\n * pela camada superior — aqui apenas garantimos que o SyncState reflita\r\n * o término do sync, o que notifica os listeners `onSyncStateChange` e\r\n * transitivamente os `onSnapshot` da UI.\r\n */\r\n private _phase3Realtime(): void {\r\n // O ChangeBus já foi alimentado nas Fases 1 e 2.\r\n // A Fase 3 garante que o estado de sync reflita \"cache fresco\".\r\n // Em implementação futura, reabre o WebSocket ou onSnapshot do Firestore.\r\n // Por ora, o sinal é a mudança de status para 'idle' + lastSyncedAt.\r\n }\r\n\r\n // ─── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Retorna a lista de coleções com documentos no cache local.\r\n * Usado pelo full resync para saber quais coleções checar.\r\n *\r\n * Combina:\r\n * 1. Set em memória `_activeCollections` (populado ao aplicar docs)\r\n * 2. Coleções de mutações pendentes\r\n * 3. Coleções de conflict_log\r\n * 4. Coleções persistas em sync_meta['activeCollections']\r\n */\r\n private async _getActiveCollections(): Promise<string[]> {\r\n const collectionSet = new Set<string>(this._activeCollections);\r\n\r\n // Coleções de mutações pendentes\r\n const mutations = await this._queue.listAll();\r\n for (const m of mutations) collectionSet.add(m.collection);\r\n\r\n // Coleções de conflict_log\r\n const conflicts = await this._store.listConflicts();\r\n for (const c of conflicts) collectionSet.add(c.collection);\r\n\r\n // Coleções persistidas em sync_meta (sobrevivem reload)\r\n const persistedRaw = (await this._store.getMeta('activeCollections')) as string[] | null;\r\n if (persistedRaw) {\r\n for (const col of persistedRaw) collectionSet.add(col);\r\n }\r\n\r\n // Coleções descobertas diretamente do IndexedDB (cobre docs pré-populados\r\n // externamente, ex.: pelo SyncTransport em sessões anteriores)\r\n const storedCollections = await this._store.listCollections();\r\n for (const col of storedCollections) collectionSet.add(col);\r\n\r\n return Array.from(collectionSet);\r\n }\r\n\r\n\r\n /** Constrói o estado inicial com base no estado atual dos colaboradores. */\r\n private _buildInitialState(): SyncState {\r\n const isOnline = this._connectivity.isOnline;\r\n return {\r\n status: isOnline ? 'idle' : 'offline',\r\n pendingWrites: 0,\r\n lastSyncedAt: null,\r\n isLeaderTab: this._tabCoordinator.isLeader(),\r\n };\r\n }\r\n\r\n /**\r\n * Atualiza o SyncState em RAM e notifica os listeners.\r\n * Só emite se algo realmente mudou.\r\n */\r\n private _updateState(partial: Partial<SyncState>): void {\r\n const prev = this._state;\r\n const next: SyncState = { ...prev, ...partial };\r\n\r\n // Garante que pendingWrites é sempre recalculado de forma assíncrona\r\n // Nota: não podemos tornar _updateState async aqui (breaking the sync chain),\r\n // então atualizamos o pendingWrites via side-effect lazy.\r\n\r\n const changed =\r\n prev.status !== next.status ||\r\n prev.pendingWrites !== next.pendingWrites ||\r\n prev.lastSyncedAt !== next.lastSyncedAt ||\r\n prev.isLeaderTab !== next.isLeaderTab;\r\n\r\n this._state = next;\r\n\r\n if (changed) {\r\n this._emitState(next);\r\n }\r\n }\r\n\r\n private _emitState(state: SyncState): void {\r\n for (const listener of this._stateListeners) {\r\n try {\r\n listener({ ...state });\r\n } catch { /* listener com erro não interrompe */ }\r\n }\r\n }\r\n\r\n /**\r\n * Atualiza `pendingWrites` no estado.\r\n * Chamado de forma assíncrona quando necessário.\r\n */\r\n private async _refreshPendingWrites(): Promise<void> {\r\n if (this._destroyed) return;\r\n try {\r\n const count = await this._queue.countPending();\r\n if (count !== this._state.pendingWrites) {\r\n this._updateState({ pendingWrites: count });\r\n }\r\n } catch { /* silencioso */ }\r\n }\r\n\r\n /** Dispara um sync de forma fire-and-forget (para gatilhos externos). */\r\n private _triggerSync(_reason: string): void {\r\n if (this._destroyed) return;\r\n this._refreshPendingWrites().catch(() => {});\r\n this.sync().catch(() => {});\r\n }\r\n\r\n /** Carrega activeCollections do sync_meta e popula o Set em memória. */\r\n private _loadActiveCollections(): void {\r\n // Assíncrono — chamado fire-and-forget no constructor\r\n this._store.getMeta('activeCollections')\r\n .then((raw) => {\r\n const cols = raw as string[] | null;\r\n if (cols) {\r\n for (const c of cols) this._activeCollections.add(c);\r\n }\r\n })\r\n .catch(() => {});\r\n }\r\n\r\n /** Conecta os listeners de ConnectivityMonitor e TabCoordinator. */\r\n private _wireListeners(): void {\r\n this._loadActiveCollections();\r\n // ConnectivityMonitor: offline → atualiza status; online → aciona sync\r\n const unsubConn = this._connectivity.subscribe((state) => {\r\n if (state === 'offline') {\r\n this._updateState({ status: 'offline' });\r\n } else {\r\n // Voltou online — atualiza estado e aciona sync\r\n if (this._state.status === 'offline') {\r\n this._updateState({ status: 'idle' });\r\n }\r\n this._triggerSync('connectivity:online');\r\n }\r\n });\r\n this._cleanups.push(unsubConn);\r\n\r\n // TabCoordinator: promoção → aciona sync; rebaixamento → para (status idle)\r\n const unsubRole = this._tabCoordinator.onRoleChange((role) => {\r\n const isLeader = role === 'leader';\r\n this._updateState({ isLeaderTab: isLeader });\r\n\r\n if (isLeader) {\r\n this._triggerSync('role:leader');\r\n }\r\n });\r\n this._cleanups.push(unsubRole);\r\n }\r\n}\r\n","/**\r\n * ConflictResolver — resolução de conflito Last-Write-Wins (LWW).\r\n *\r\n * Implementa a política LWW definida em I3 §7:\r\n * - **Documento-nível** (para `set` e `add`): o documento inteiro com o\r\n * `updatedAtServer` mais recente vence.\r\n * - **Campo-restrito** (para `update`): apenas os campos declarados na mutação\r\n * são comparados; campos não tocados pela mutação são preservados do estado\r\n * atual (server ou local).\r\n *\r\n * Design:\r\n * - ZERO dependências externas.\r\n * - PURO: mesma entrada → mesma saída. Sem side-effects, sem I/O.\r\n * - O timestamp autoritativo é o do SERVIDOR (`updatedAtServer`), não do\r\n * cliente (`enqueuedAt`) — I3 §7.3.\r\n * - A comparação de versão/timestamp acontece no CLIENTE apenas para leitura\r\n * otimista. A palavra final é do servidor (no replay o Core decide). Este\r\n * módulo implementa a lógica de resolução local (para preview otimista e para\r\n * o feedback ao produto).\r\n */\r\n\r\nimport type {\r\n OfflineDoc,\r\n Mutation,\r\n ConflictRecord,\r\n ConflictReason,\r\n} from './types';\r\n\r\n// ─── Tipos do resultado ───────────────────────────────────────────────────────\r\n\r\n/** Resultado da resolução de conflito para um par (local, server). */\r\nexport type ConflictOutcome =\r\n | 'local_wins' // a escrita local é mantida\r\n | 'server_wins' // o estado do servidor prevalece (escrita local descartada)\r\n | 'merged' // merge campo-restrito (update): campos do server + campos locais\r\n | 'no_conflict'; // sem conflito detectável (doc local === doc server, ou nenhum estava presente)\r\n\r\nexport interface ResolveResult<T = Record<string, unknown>> {\r\n outcome: ConflictOutcome;\r\n /** Documento resultante após resolução. */\r\n resolvedData: T;\r\n /**\r\n * `ConflictRecord` preenchido quando `outcome === 'server_wins'` ou\r\n * `outcome === 'merged'` (campos conflitantes perdedores).\r\n * `null` caso contrário.\r\n */\r\n conflictRecord: Omit<ConflictRecord, 'id'> | null;\r\n}\r\n\r\n// ─── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Retorna true se o estado do servidor é \"mais novo\" do que o estado local,\r\n * baseando-se no timestamp do servidor (I3 §7.3).\r\n *\r\n * Quando `serverUpdatedAt` é null o servidor nunca confirmou — considera o local\r\n * como mais recente (o doc pode ser um `add` otimista ainda não sincronizado).\r\n * Quando ambos são null há empate → `false` (mantém local como default).\r\n */\r\nfunction isServerNewer(\r\n localUpdatedAtServer: number | null,\r\n remoteUpdatedAtServer: number | null,\r\n): boolean {\r\n if (remoteUpdatedAtServer === null) return false;\r\n if (localUpdatedAtServer === null) return true; // server tem timestamp, local não\r\n return remoteUpdatedAtServer > localUpdatedAtServer;\r\n}\r\n\r\n// ─── ConflictResolver ─────────────────────────────────────────────────────────\r\n\r\n/**\r\n * ConflictResolver — aplica LWW doc-nível ou campo-restrito.\r\n *\r\n * Uso:\r\n * ```ts\r\n * const resolver = new ConflictResolver();\r\n *\r\n * // LWW doc-nível (set/add):\r\n * const result = resolver.resolveDocLevel(localDoc, serverDoc, mutation);\r\n *\r\n * // LWW campo-restrito (update):\r\n * const result = resolver.resolveFieldRestricted(localDoc, serverDoc, mutation);\r\n *\r\n * // Auto-dispatch baseado na op da mutação:\r\n * const result = resolver.resolve(localDoc, serverDoc, mutation);\r\n * ```\r\n */\r\nexport class ConflictResolver {\r\n /**\r\n * Resolve um conflito com base na operação da mutação (auto-dispatch).\r\n *\r\n * - `add` / `set` → `resolveDocLevel`\r\n * - `update` → `resolveFieldRestricted`\r\n * - `remove` → a remoção sempre vence (LWW: operação mais recente é a destruição)\r\n */\r\n resolve<T = Record<string, unknown>>(\r\n localDoc: OfflineDoc<T> | null,\r\n serverDoc: OfflineDoc<T> | null,\r\n pendingMutation: Mutation,\r\n ): ResolveResult<T> {\r\n switch (pendingMutation.op) {\r\n case 'remove':\r\n return this.resolveRemove(localDoc, serverDoc, pendingMutation);\r\n case 'update':\r\n return this.resolveFieldRestricted(localDoc, serverDoc, pendingMutation);\r\n case 'add':\r\n case 'set':\r\n default:\r\n return this.resolveDocLevel(localDoc, serverDoc, pendingMutation);\r\n }\r\n }\r\n\r\n /**\r\n * LWW documento-nível (para `set` e `add`).\r\n *\r\n * O documento inteiro com o timestamp de servidor mais recente vence.\r\n * Se o servidor for mais novo, a escrita local é descartada e um\r\n * `ConflictRecord` é emitido.\r\n */\r\n resolveDocLevel<T = Record<string, unknown>>(\r\n localDoc: OfflineDoc<T> | null,\r\n serverDoc: OfflineDoc<T> | null,\r\n pendingMutation: Mutation,\r\n ): ResolveResult<T> {\r\n // Sem doc no servidor — escrita local não tem concorrente, sem conflito.\r\n if (serverDoc === null) {\r\n const data = (pendingMutation.payload ?? {}) as T;\r\n return { outcome: 'no_conflict', resolvedData: data, conflictRecord: null };\r\n }\r\n\r\n // Sem doc local (não deveria ocorrer, mas defesa de programação)\r\n if (localDoc === null) {\r\n return {\r\n outcome: 'server_wins',\r\n resolvedData: serverDoc.data,\r\n conflictRecord: null,\r\n };\r\n }\r\n\r\n const serverNewer = isServerNewer(\r\n localDoc.meta.updatedAtServer,\r\n serverDoc.meta.updatedAtServer,\r\n );\r\n\r\n if (!serverNewer) {\r\n // Escrita local é mais recente (ou empate → local vence por default)\r\n return {\r\n outcome: 'local_wins',\r\n resolvedData: localDoc.data,\r\n conflictRecord: null,\r\n };\r\n }\r\n\r\n // Servidor mais novo — LWW: servidor vence, escrita local descartada\r\n const conflictRecord: Omit<ConflictRecord, 'id'> = {\r\n collection: pendingMutation.collection,\r\n docId: pendingMutation.docId,\r\n mutationId: pendingMutation.mutationId,\r\n losingData: localDoc.data as Record<string, unknown>,\r\n winningData: serverDoc.data as Record<string, unknown>,\r\n reason: 'lww_server_newer' as ConflictReason,\r\n detectedAt: Date.now(),\r\n delivered: false,\r\n };\r\n\r\n return {\r\n outcome: 'server_wins',\r\n resolvedData: serverDoc.data,\r\n conflictRecord,\r\n };\r\n }\r\n\r\n /**\r\n * LWW campo-restrito (para `update`).\r\n *\r\n * Apenas os campos declarados no payload da mutação são comparados.\r\n * Campos não tocados pela mutação são preservados do estado do servidor\r\n * (se disponível) ou do estado local (I3 §7.2).\r\n *\r\n * Resultado:\r\n * - Se o servidor for mais novo nos campos conflitantes → `server_wins`\r\n * para esses campos; o doc resultante é uma mescla de server (campos\r\n * conflitantes) + estado antes da mutação para os demais.\r\n * - Se o local for mais recente → `local_wins`; os campos do update são\r\n * aplicados sobre o server.\r\n * - Campos do server não tocados pelo update sempre preservados → `merged`.\r\n */\r\n resolveFieldRestricted<T = Record<string, unknown>>(\r\n localDoc: OfflineDoc<T> | null,\r\n serverDoc: OfflineDoc<T> | null,\r\n pendingMutation: Mutation,\r\n ): ResolveResult<T> {\r\n const mutatedFields = Object.keys(pendingMutation.payload ?? {});\r\n\r\n // Sem doc no servidor — sem conflito, aplica o update sobre o local\r\n if (serverDoc === null) {\r\n const base = (localDoc?.data ?? {}) as Record<string, unknown>;\r\n const resolved = { ...base, ...(pendingMutation.payload ?? {}) } as T;\r\n return { outcome: 'no_conflict', resolvedData: resolved, conflictRecord: null };\r\n }\r\n\r\n // Base do documento no servidor (campos não tocados pelo update)\r\n const serverData = serverDoc.data as Record<string, unknown>;\r\n\r\n // Se não há doc local (doc nunca foi cacheado), sem conflito — aplica o update sobre o server\r\n if (localDoc === null) {\r\n const resolved = { ...serverData, ...(pendingMutation.payload ?? {}) } as T;\r\n return { outcome: 'no_conflict', resolvedData: resolved, conflictRecord: null };\r\n }\r\n\r\n const serverNewer = isServerNewer(\r\n localDoc.meta.updatedAtServer,\r\n serverDoc.meta.updatedAtServer,\r\n );\r\n\r\n if (!serverNewer) {\r\n // Update local é mais recente — aplica os campos do update sobre o server\r\n const resolved = { ...serverData, ...(pendingMutation.payload ?? {}) } as T;\r\n return { outcome: 'local_wins', resolvedData: resolved, conflictRecord: null };\r\n }\r\n\r\n // Servidor mais novo — campos conflitantes: server vence; campos do update\r\n // não existentes no server: server ainda vence (server é a fonte de verdade\r\n // pós-conflito, consistente com doc-level LWW).\r\n const losingFields: Record<string, unknown> = {};\r\n for (const field of mutatedFields) {\r\n losingFields[field] = (localDoc.data as Record<string, unknown>)[field];\r\n }\r\n\r\n const conflictRecord: Omit<ConflictRecord, 'id'> = {\r\n collection: pendingMutation.collection,\r\n docId: pendingMutation.docId,\r\n mutationId: pendingMutation.mutationId,\r\n losingData: losingFields,\r\n winningData: serverData,\r\n reason: 'lww_server_newer' as ConflictReason,\r\n detectedAt: Date.now(),\r\n delivered: false,\r\n };\r\n\r\n // Doc resultante: estado do servidor completo (o update perdeu todos os\r\n // campos conflitantes — comportamento conservador e auditável)\r\n return {\r\n outcome: 'server_wins',\r\n resolvedData: serverData as T,\r\n conflictRecord,\r\n };\r\n }\r\n\r\n /**\r\n * Resolve uma operação `remove`.\r\n *\r\n * A remoção sempre vence no LWW (I3 §7.4: \"a última operação é a destruição\").\r\n * Se o servidor modificou o doc depois que o cliente enfileirou o remove, a\r\n * remoção ainda prevalece — comportamento documentado.\r\n */\r\n resolveRemove<T = Record<string, unknown>>(\r\n _localDoc: OfflineDoc<T> | null,\r\n serverDoc: OfflineDoc<T> | null,\r\n _pendingMutation: Mutation,\r\n ): ResolveResult<T> {\r\n // A remoção vence — o doc resultante é um tombstone (dados vazios)\r\n // O chamador é responsável por marcar `deleted: true` no cache.\r\n const emptyDoc = {} as T;\r\n\r\n // Se o servidor tem um estado mais recente E foi modificado depois da\r\n // intenção de remoção, registra um conflito para audit trail (mas ainda remove)\r\n if (serverDoc !== null && serverDoc.meta.updatedAtServer !== null) {\r\n const conflictRecord: Omit<ConflictRecord, 'id'> = {\r\n collection: _pendingMutation.collection,\r\n docId: _pendingMutation.docId,\r\n mutationId: _pendingMutation.mutationId,\r\n losingData: serverDoc.data as Record<string, unknown>,\r\n winningData: {},\r\n reason: 'lww_server_newer' as ConflictReason,\r\n detectedAt: Date.now(),\r\n delivered: false,\r\n };\r\n // A remoção ainda vence, mas registra o conflito\r\n return { outcome: 'local_wins', resolvedData: emptyDoc, conflictRecord };\r\n }\r\n\r\n return { outcome: 'local_wins', resolvedData: emptyDoc, conflictRecord: null };\r\n }\r\n\r\n /**\r\n * Resolve conflito com razão de rejeição explícita (servidor retornou\r\n * `rejected_permission` ou `rejected_validation`).\r\n *\r\n * Usado pelo SyncEngine quando o Core rejeita o replay por motivo não-LWW.\r\n */\r\n resolveRejected<T = Record<string, unknown>>(\r\n localDoc: OfflineDoc<T>,\r\n serverDoc: OfflineDoc<T> | null,\r\n pendingMutation: Mutation,\r\n reason: 'rejected_permission' | 'rejected_validation',\r\n ): ResolveResult<T> {\r\n const winningData = (serverDoc?.data ?? {}) as Record<string, unknown>;\r\n\r\n const conflictRecord: Omit<ConflictRecord, 'id'> = {\r\n collection: pendingMutation.collection,\r\n docId: pendingMutation.docId,\r\n mutationId: pendingMutation.mutationId,\r\n losingData: localDoc.data as Record<string, unknown>,\r\n winningData,\r\n reason,\r\n detectedAt: Date.now(),\r\n delivered: false,\r\n };\r\n\r\n return {\r\n outcome: 'server_wins',\r\n resolvedData: (serverDoc?.data ?? localDoc.data),\r\n conflictRecord,\r\n };\r\n }\r\n\r\n // ─── Static helpers ─────────────────────────────────────────────────────────\r\n\r\n static resolve<T = Record<string, unknown>>(\r\n localDoc: OfflineDoc<T> | null,\r\n serverDoc: OfflineDoc<T> | null,\r\n pendingMutation: Mutation,\r\n ): ResolveResult<T> {\r\n return new ConflictResolver().resolve(localDoc, serverDoc, pendingMutation);\r\n }\r\n}\r\n","/**\r\n * ChangeBus — barramento in-process de eventos de mudança.\r\n *\r\n * Fan-out de eventos `Change` para todos os listeners registrados\r\n * (onSnapshot / onDoc). Cola o cache (LocalStore) ao tempo real.\r\n *\r\n * Design (I3 §2.2 / §6.5 / §9):\r\n * - ZERO dependências externas.\r\n * - Em memória por aba (não persiste).\r\n * - Sem memory leaks: `unsubscribe()` remove o listener imediatamente.\r\n * - Deduplicação básica por `[collection, id, serverVersion]` (I3 §6.5):\r\n * o bus não emite o mesmo evento duas vezes pra o mesmo listener no mesmo\r\n * tick (evita a Fase 1 + Fase 2 do SyncEngine gerando dois eventos para o\r\n * mesmo doc confirmado).\r\n * - Erro em um listener não propaga para os demais (isolamento).\r\n */\r\n\r\nimport type { Change, Unsubscribe } from './types';\r\n\r\n// ─── Tipos internos ───────────────────────────────────────────────────────────\r\n\r\n/** Função listener que recebe um array de Changes emitidos juntos. */\r\nexport type ChangeBusListener<T = Record<string, unknown>> = (\r\n changes: Change<T>[],\r\n) => void;\r\n\r\n/** Chave de deduplicação para um change event. */\r\nfunction dedupeKey<T>(c: Change<T>): string {\r\n // usa `serverVersion` se presente; fallback para 'local' (sem versão server)\r\n return `${c.collection}::${c.doc.id}`;\r\n}\r\n\r\n// ─── ChangeBus ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * ChangeBus — pub/sub in-process para eventos de mudança de documento.\r\n *\r\n * ```ts\r\n * const bus = new ChangeBus();\r\n *\r\n * // Subscrever a uma coleção (filtra por collection automaticamente)\r\n * const unsub = bus.subscribe('orders', (changes) => {\r\n * console.log(changes);\r\n * });\r\n *\r\n * // Emitir events\r\n * bus.emit([{ type: 'modified', collection: 'orders', doc: { id: '1', data: {} } }]);\r\n *\r\n * // Cancelar subscrição — sem memory leak\r\n * unsub();\r\n * ```\r\n *\r\n * Listeners globais (sem filtro de coleção):\r\n * ```ts\r\n * const unsub = bus.subscribeAll((changes) => { ... });\r\n * ```\r\n */\r\nexport class ChangeBus<T = Record<string, unknown>> {\r\n /** Listeners filtrados por coleção. */\r\n private readonly _collectionListeners = new Map<\r\n string,\r\n Set<ChangeBusListener<T>>\r\n >();\r\n /** Listeners globais (todas as coleções). */\r\n private readonly _globalListeners = new Set<ChangeBusListener<T>>();\r\n\r\n /**\r\n * Subscreve a eventos de uma coleção específica.\r\n *\r\n * @param collection - Nome da coleção a filtrar.\r\n * @param listener - Callback que recebe os changes da coleção.\r\n * @returns Função de unsubscribe.\r\n */\r\n subscribe(collection: string, listener: ChangeBusListener<T>): Unsubscribe {\r\n if (!this._collectionListeners.has(collection)) {\r\n this._collectionListeners.set(collection, new Set());\r\n }\r\n this._collectionListeners.get(collection)!.add(listener);\r\n\r\n return () => {\r\n const set = this._collectionListeners.get(collection);\r\n if (set) {\r\n set.delete(listener);\r\n if (set.size === 0) {\r\n this._collectionListeners.delete(collection);\r\n }\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * Subscreve a eventos de TODAS as coleções.\r\n *\r\n * @param listener - Callback que recebe todos os changes, de qualquer coleção.\r\n * @returns Função de unsubscribe.\r\n */\r\n subscribeAll(listener: ChangeBusListener<T>): Unsubscribe {\r\n this._globalListeners.add(listener);\r\n return () => {\r\n this._globalListeners.delete(listener);\r\n };\r\n }\r\n\r\n /**\r\n * Emite um array de `Change` events para todos os listeners relevantes.\r\n *\r\n * Agrupa os changes por coleção antes de despachar, para que cada listener\r\n * receba apenas os events da sua coleção.\r\n *\r\n * Deduplicação: events com o mesmo `[collection, id]` dentro do mesmo `emit()`\r\n * são compactados: apenas o último do array é mantido (o mais recente vence).\r\n * Isso cobre o caso Fase 1 + Fase 2 do SyncEngine emitindo o mesmo doc.\r\n *\r\n * Erros em listeners individuais são capturados e não interrompem os demais.\r\n */\r\n emit(changes: Change<T>[]): void {\r\n if (changes.length === 0) return;\r\n\r\n // Deduplica: mapa de dedupeKey → último change (o mais recente)\r\n const deduped = new Map<string, Change<T>>();\r\n for (const c of changes) {\r\n deduped.set(dedupeKey(c), c);\r\n }\r\n const uniqueChanges = Array.from(deduped.values());\r\n\r\n // Agrupa por coleção\r\n const byCollection = new Map<string, Change<T>[]>();\r\n for (const c of uniqueChanges) {\r\n if (!byCollection.has(c.collection)) {\r\n byCollection.set(c.collection, []);\r\n }\r\n byCollection.get(c.collection)!.push(c);\r\n }\r\n\r\n // Despacha para listeners de coleção\r\n for (const [collection, collChanges] of byCollection) {\r\n const listeners = this._collectionListeners.get(collection);\r\n if (listeners) {\r\n for (const listener of listeners) {\r\n this._safeCall(listener, collChanges);\r\n }\r\n }\r\n }\r\n\r\n // Despacha para listeners globais (com todos os changes únicos)\r\n for (const listener of this._globalListeners) {\r\n this._safeCall(listener, uniqueChanges);\r\n }\r\n }\r\n\r\n /**\r\n * Número de listeners ativos (útil em testes).\r\n */\r\n get listenerCount(): number {\r\n let count = this._globalListeners.size;\r\n for (const set of this._collectionListeners.values()) {\r\n count += set.size;\r\n }\r\n return count;\r\n }\r\n\r\n /**\r\n * Remove todos os listeners registrados.\r\n * Útil para teardown em testes ou no shutdown do SDK.\r\n */\r\n clear(): void {\r\n this._collectionListeners.clear();\r\n this._globalListeners.clear();\r\n }\r\n\r\n // ─── Privado ────────────────────────────────────────────────────────────────\r\n\r\n private _safeCall(listener: ChangeBusListener<T>, changes: Change<T>[]): void {\r\n try {\r\n listener(changes);\r\n } catch {\r\n // Listener com erro não interrompe os demais.\r\n // Em produção, o SyncEngine pode logar via telemetry.\r\n // Aqui silenciamos para manter o contrato de fan-out total.\r\n }\r\n }\r\n}\r\n","/**\r\n * ConnectivityMonitor — rastreia estado online/offline via `navigator.onLine`\r\n * e os eventos `online`/`offline` do window.\r\n *\r\n * Design (I3 §2.2):\r\n * - ZERO dependências externas.\r\n * - Injetável: aceita `navigator` e `EventTarget` como parâmetros para ser\r\n * totalmente testável sem DOM real.\r\n * - Debounce de flapping: transições rápidas online → offline → online dentro\r\n * de `debounceMs` (default 300ms) não disparam callbacks intermediários.\r\n * - Nota I3 §2.2: o ConnectivityMonitor base usa `navigator.onLine` + eventos\r\n * do window. Uma camada adicional (heartbeat real ao Core + sinal do\r\n * WebSocket) é responsabilidade do SyncEngine — este módulo é a base injetável.\r\n */\r\n\r\nimport type { Unsubscribe } from './types';\r\n\r\n// ─── Tipos ────────────────────────────────────────────────────────────────────\r\n\r\n/** Estado de conectividade. */\r\nexport type ConnectivityState = 'online' | 'offline';\r\n\r\n/** Listener de mudança de estado de conectividade. */\r\nexport type ConnectivityListener = (state: ConnectivityState) => void;\r\n\r\n/**\r\n * Contrato de injeção do `navigator` (subconjunto usado pelo monitor).\r\n * Permite testar sem um `navigator` real.\r\n */\r\nexport interface NavigatorLike {\r\n readonly onLine: boolean;\r\n}\r\n\r\n/**\r\n * Contrato de injeção do event target (subconjunto de `window` / `EventTarget`).\r\n */\r\nexport interface EventTargetLike {\r\n addEventListener(type: string, listener: EventListenerOrEventListenerObject): void;\r\n removeEventListener(type: string, listener: EventListenerOrEventListenerObject): void;\r\n}\r\n\r\n/** Opções de configuração do ConnectivityMonitor. */\r\nexport interface ConnectivityMonitorOptions {\r\n /**\r\n * `navigator`-like para leitura de `navigator.onLine`.\r\n * Default: `globalThis.navigator` (quando disponível).\r\n */\r\n navigator?: NavigatorLike;\r\n /**\r\n * EventTarget para subscrever os eventos `online` / `offline`.\r\n * Default: `globalThis.window` (quando disponível).\r\n */\r\n eventTarget?: EventTargetLike;\r\n /**\r\n * Debounce em ms para evitar flapping.\r\n * Default: 300ms.\r\n */\r\n debounceMs?: number;\r\n}\r\n\r\n// ─── ConnectivityMonitor ──────────────────────────────────────────────────────\r\n\r\n/**\r\n * ConnectivityMonitor — monitora online/offline via `navigator.onLine` +\r\n * eventos `online`/`offline` do window, com debounce de flapping.\r\n *\r\n * ```ts\r\n * // Com injeção (testes):\r\n * const monitor = new ConnectivityMonitor({\r\n * navigator: { onLine: true },\r\n * eventTarget: myFakeTarget,\r\n * });\r\n *\r\n * // Em browser real:\r\n * const monitor = new ConnectivityMonitor();\r\n * monitor.start();\r\n *\r\n * const unsub = monitor.subscribe((state) => {\r\n * console.log('Conectividade:', state);\r\n * });\r\n *\r\n * monitor.destroy(); // cleanup\r\n * ```\r\n */\r\nexport class ConnectivityMonitor {\r\n private _state: ConnectivityState;\r\n private readonly _listeners = new Set<ConnectivityListener>();\r\n private readonly _nav: NavigatorLike | undefined;\r\n private readonly _target: EventTargetLike | undefined;\r\n private readonly _debounceMs: number;\r\n private _debounceTimer: ReturnType<typeof setTimeout> | null = null;\r\n private _started = false;\r\n\r\n // Handlers bound para remoção correta em removeEventListener\r\n private readonly _onOnline: () => void;\r\n private readonly _onOffline: () => void;\r\n\r\n constructor(options: ConnectivityMonitorOptions = {}) {\r\n this._nav = options.navigator ?? (typeof navigator !== 'undefined' ? navigator : undefined);\r\n this._target =\r\n options.eventTarget ??\r\n (typeof window !== 'undefined' ? window : undefined);\r\n this._debounceMs = options.debounceMs ?? 300;\r\n\r\n // Estado inicial: lê navigator.onLine; fallback = online\r\n this._state = this._nav?.onLine === false ? 'offline' : 'online';\r\n\r\n // Bind para poder remover depois\r\n this._onOnline = () => this._handleNativeEvent('online');\r\n this._onOffline = () => this._handleNativeEvent('offline');\r\n }\r\n\r\n // ─── Ciclo de vida ──────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Inicia a escuta de eventos. Deve ser chamado após instanciar.\r\n * Sem efeito se já foi iniciado.\r\n */\r\n start(): void {\r\n if (this._started) return;\r\n this._started = true;\r\n this._target?.addEventListener('online', this._onOnline);\r\n this._target?.addEventListener('offline', this._onOffline);\r\n }\r\n\r\n /**\r\n * Para a escuta e remove todos os listeners.\r\n * Deve ser chamado no shutdown para evitar memory leaks.\r\n */\r\n destroy(): void {\r\n this._started = false;\r\n this._target?.removeEventListener('online', this._onOnline);\r\n this._target?.removeEventListener('offline', this._onOffline);\r\n if (this._debounceTimer !== null) {\r\n clearTimeout(this._debounceTimer);\r\n this._debounceTimer = null;\r\n }\r\n this._listeners.clear();\r\n }\r\n\r\n // ─── Estado atual ───────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Retorna o estado de conectividade atual.\r\n */\r\n getState(): ConnectivityState {\r\n return this._state;\r\n }\r\n\r\n /**\r\n * True se o estado atual é `'online'`.\r\n */\r\n get isOnline(): boolean {\r\n return this._state === 'online';\r\n }\r\n\r\n /**\r\n * True se o estado atual é `'offline'`.\r\n */\r\n get isOffline(): boolean {\r\n return this._state === 'offline';\r\n }\r\n\r\n // ─── Subscrições ────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Subscreve a mudanças de estado de conectividade.\r\n *\r\n * @param listener - Callback chamado ao mudar o estado.\r\n * @returns Função de unsubscribe (sem memory leak).\r\n */\r\n subscribe(listener: ConnectivityListener): Unsubscribe {\r\n this._listeners.add(listener);\r\n return () => {\r\n this._listeners.delete(listener);\r\n };\r\n }\r\n\r\n /**\r\n * Número de listeners ativos (útil em testes).\r\n */\r\n get listenerCount(): number {\r\n return this._listeners.size;\r\n }\r\n\r\n // ─── Força de estado (para testes e heartbeat externo) ─────────────────────\r\n\r\n /**\r\n * Força o estado para um valor específico, ignorando eventos nativos.\r\n * Útil para o SyncEngine injetar o resultado de um heartbeat real ao Core.\r\n * Respeita o debounce.\r\n */\r\n forceState(state: ConnectivityState): void {\r\n this._scheduleTransition(state);\r\n }\r\n\r\n // ─── Privado ────────────────────────────────────────────────────────────────\r\n\r\n private _handleNativeEvent(type: 'online' | 'offline'): void {\r\n const newState: ConnectivityState = type === 'online' ? 'online' : 'offline';\r\n this._scheduleTransition(newState);\r\n }\r\n\r\n private _scheduleTransition(newState: ConnectivityState): void {\r\n // Cancela transição pendente (debounce de flapping)\r\n if (this._debounceTimer !== null) {\r\n clearTimeout(this._debounceTimer);\r\n this._debounceTimer = null;\r\n }\r\n\r\n if (this._debounceMs <= 0) {\r\n // Sem debounce — aplica imediatamente\r\n this._applyTransition(newState);\r\n return;\r\n }\r\n\r\n this._debounceTimer = setTimeout(() => {\r\n this._debounceTimer = null;\r\n this._applyTransition(newState);\r\n }, this._debounceMs);\r\n }\r\n\r\n private _applyTransition(newState: ConnectivityState): void {\r\n if (newState === this._state) return; // sem mudança real\r\n this._state = newState;\r\n this._notifyListeners(newState);\r\n }\r\n\r\n private _notifyListeners(state: ConnectivityState): void {\r\n for (const listener of this._listeners) {\r\n try {\r\n listener(state);\r\n } catch {\r\n // Listener com erro não interrompe os demais\r\n }\r\n }\r\n }\r\n}\r\n","/**\r\n * TabCoordinator — coordenação multi-aba via Web Locks API.\r\n *\r\n * Elege uma aba **líder** de forma exclusiva: apenas a aba líder roda o\r\n * SyncEngine e drena a MutationQueue. Abas seguidoras leem o LocalStore\r\n * compartilhado e recebem notificações via BroadcastChannel.\r\n *\r\n * Design (I3 §12.5 / §2.2):\r\n *\r\n * - **Eleição via Web Locks:** `navigator.locks.request(name, callback)` com\r\n * uma Promise interna que nunca resolve enquanto a aba estiver viva. O\r\n * processo que segura o lock é o líder. Ao destruir, a Promise interna\r\n * resolve → lock liberado → próxima aba na fila adquire o lock.\r\n *\r\n * - **BroadcastChannel:** o líder transmite `cache_updated` / `sync_state`\r\n * para que seguidores reavaliem suas queries; seguidores enviam\r\n * `mutation_request` ao líder quando querem que ele drene a fila.\r\n *\r\n * - **Fallback:** se `navigator.locks` não estiver disponível (SSR, ambiente\r\n * sem suporte), a aba assume liderança imediatamente sem contenção.\r\n *\r\n * - **Injetabilidade:** todas as APIs do browser (`navigator.locks`,\r\n * `BroadcastChannel`) são injetáveis via `TabCoordinatorOptions` — o\r\n * componente é totalmente testável sem DOM/browser real.\r\n *\r\n * - **Idempotência:** `start()` e `destroy()` são seguros de chamar\r\n * múltiplas vezes.\r\n */\r\n\r\nimport type { Unsubscribe } from './types';\r\n\r\n// ─── Protocolo de mensagens BroadcastChannel ──────────────────────────────────\r\n\r\n/**\r\n * O líder transmite que o cache foi atualizado.\r\n * Seguidores devem reavaliar queries afetadas pela `collection`.\r\n */\r\nexport interface CacheUpdatedMessage {\r\n type: 'cache_updated';\r\n /** Coleção que foi modificada. `*` = todas. */\r\n collection: string;\r\n}\r\n\r\n/**\r\n * O líder transmite seu estado de sync para que seguidores atualizem o\r\n * `isLeaderTab` em seus `NeetruSyncState`.\r\n */\r\nexport interface SyncStateMessage {\r\n type: 'sync_state';\r\n /** ID único da aba líder. */\r\n leaderTabId: string;\r\n /** Se `true`, o líder está sincronizando no momento. */\r\n syncing: boolean;\r\n /** Número de mutações pendentes na fila. */\r\n pendingWrites: number;\r\n}\r\n\r\n/**\r\n * Um seguidor solicita ao líder que drene a fila (ex.: após enfileirar\r\n * uma mutação localmente). O líder pode ignorar se já estiver drenando.\r\n */\r\nexport interface MutationRequestMessage {\r\n type: 'mutation_request';\r\n mutationId: string;\r\n collection: string;\r\n op: string;\r\n docId: string;\r\n payload: Record<string, unknown> | null;\r\n}\r\n\r\n/**\r\n * União discriminada de todas as mensagens do protocolo TabCoordinator.\r\n * Mensagens de tipo desconhecido devem ser ignoradas silenciosamente\r\n * (compatibilidade futura).\r\n */\r\nexport type TabMessage =\r\n | CacheUpdatedMessage\r\n | SyncStateMessage\r\n | MutationRequestMessage;\r\n\r\n// ─── Contratos de injeção de browser APIs ─────────────────────────────────────\r\n\r\n/**\r\n * Subconjunto de `Lock` usado pelo TabCoordinator.\r\n */\r\nexport interface LockLike {\r\n readonly name: string;\r\n}\r\n\r\n/**\r\n * Subconjunto de `LockManager` (`navigator.locks`).\r\n * Permite injeção de fake em testes sem o browser real.\r\n */\r\nexport interface LockManagerLike {\r\n request(\r\n name: string,\r\n callback: (lock: LockLike) => Promise<void>,\r\n ): Promise<void>;\r\n}\r\n\r\n/**\r\n * Subconjunto de `BroadcastChannel`.\r\n * Permite injeção de fake em testes sem o browser real.\r\n */\r\nexport interface BroadcastChannelLike {\r\n onmessage: ((msg: TabMessage) => void) | null;\r\n postMessage(msg: TabMessage): void;\r\n close(): void;\r\n}\r\n\r\n// ─── Papel da aba ──────────────────────────────────────────────────────────────\r\n\r\n/** Papel atual desta aba no protocolo multi-aba. */\r\nexport type TabRole = 'leader' | 'follower';\r\n\r\n/** Callback de mudança de papel. */\r\nexport type RoleChangeListener = (role: TabRole) => void;\r\n\r\n// ─── Opções ───────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Opções de configuração do TabCoordinator.\r\n * Todos os campos de browser API são opcionais para facilitar testes.\r\n */\r\nexport interface TabCoordinatorOptions {\r\n /**\r\n * Nome do lock Web Locks (deve ser único por banco lógico / origem).\r\n * Exemplo: `'neetru-offline:produto-slug:db-id'`.\r\n */\r\n lockName: string;\r\n\r\n /**\r\n * Nome do BroadcastChannel (geralmente igual ao lockName).\r\n */\r\n channelName: string;\r\n\r\n /**\r\n * `navigator.locks`-like. Quando `undefined`, o TabCoordinator usa o\r\n * `navigator.locks` global se disponível; caso contrário, usa fallback\r\n * (assume liderança imediatamente).\r\n */\r\n lockManager?: LockManagerLike;\r\n\r\n /**\r\n * Instância de `BroadcastChannel`-like pré-criada. Quando `undefined`,\r\n * o TabCoordinator tenta criar um `BroadcastChannel` real se disponível.\r\n */\r\n broadcastChannel?: BroadcastChannelLike;\r\n}\r\n\r\n// ─── TabCoordinator ───────────────────────────────────────────────────────────\r\n\r\n/**\r\n * TabCoordinator — coordenação multi-aba via Web Locks + BroadcastChannel.\r\n *\r\n * ```ts\r\n * // Com injeção (testes):\r\n * const coordinator = new TabCoordinator({\r\n * lockName: 'neetru-offline:mydb',\r\n * channelName: 'neetru-offline:mydb',\r\n * lockManager: fakeLockManager,\r\n * broadcastChannel: fakeBroadcastChannel,\r\n * });\r\n *\r\n * // Em browser real:\r\n * const coordinator = new TabCoordinator({\r\n * lockName: `neetru-offline:${productId}:${dbId}`,\r\n * channelName: `neetru-offline:${productId}:${dbId}`,\r\n * });\r\n *\r\n * coordinator.start();\r\n *\r\n * // Saber se esta aba é líder\r\n * coordinator.isLeader();\r\n *\r\n * // Reagir a mudança de papel\r\n * const unsub = coordinator.onRoleChange((role) => {\r\n * if (role === 'leader') syncEngine.start();\r\n * else syncEngine.stop();\r\n * });\r\n *\r\n * // Transmitir a seguidores\r\n * coordinator.broadcast({ type: 'cache_updated', collection: 'orders' });\r\n *\r\n * // Receber mensagens de outras abas\r\n * coordinator.onMessage((msg) => {\r\n * if (msg.type === 'mutation_request') syncEngine.drainQueue();\r\n * });\r\n *\r\n * // Cleanup\r\n * coordinator.destroy();\r\n * ```\r\n */\r\nexport class TabCoordinator {\r\n private readonly _lockName: string;\r\n private readonly _channelName: string;\r\n private readonly _lockManager: LockManagerLike | undefined;\r\n private _channel: BroadcastChannelLike | undefined;\r\n private readonly _channelFactory: (() => BroadcastChannelLike) | undefined;\r\n\r\n /** ID único desta aba (para debug e `sync_state`). */\r\n private readonly _tabId: string;\r\n\r\n /** Estado de papel atual. */\r\n private _role: TabRole = 'follower';\r\n\r\n /** Promise resolve que libera o lock perpétuo. */\r\n private _releaseLock: (() => void) | null = null;\r\n\r\n /** `true` se destroy() já foi chamado. */\r\n private _destroyed = false;\r\n\r\n /** `true` se start() já foi chamado. */\r\n private _started = false;\r\n\r\n /** Listeners de mudança de papel. */\r\n private readonly _roleListeners = new Set<RoleChangeListener>();\r\n\r\n /** Listeners de mensagem recebida. */\r\n private readonly _messageListeners = new Set<(msg: TabMessage) => void>();\r\n\r\n constructor(options: TabCoordinatorOptions) {\r\n this._lockName = options.lockName;\r\n this._channelName = options.channelName;\r\n this._tabId = `tab-${Math.random().toString(36).slice(2, 10)}-${Date.now()}`;\r\n\r\n // Resolve o lockManager: opção injetada > navigator.locks global > undefined\r\n this._lockManager =\r\n options.lockManager !== undefined\r\n ? options.lockManager\r\n : typeof navigator !== 'undefined' &&\r\n 'locks' in navigator &&\r\n navigator.locks != null\r\n ? (navigator.locks as unknown as LockManagerLike)\r\n : undefined;\r\n\r\n // Resolve o canal: opção injetada > factory para BroadcastChannel real\r\n if (options.broadcastChannel !== undefined) {\r\n this._channel = options.broadcastChannel;\r\n } else if (typeof BroadcastChannel !== 'undefined') {\r\n // No browser real, armazena uma factory para criação lazy\r\n const channelName = this._channelName;\r\n this._channelFactory = () => {\r\n const bc = new BroadcastChannel(channelName);\r\n const wrapper: BroadcastChannelLike = {\r\n get onmessage() {\r\n return (bc.onmessage as ((msg: TabMessage) => void) | null);\r\n },\r\n set onmessage(cb: ((msg: TabMessage) => void) | null) {\r\n bc.onmessage = cb\r\n ? (event: MessageEvent) => cb(event.data as TabMessage)\r\n : null;\r\n },\r\n postMessage: (msg: TabMessage) => bc.postMessage(msg),\r\n close: () => bc.close(),\r\n };\r\n return wrapper;\r\n };\r\n }\r\n }\r\n\r\n // ─── Ciclo de vida ───────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Inicia o processo de eleição de líder.\r\n * Idempotente: sem efeito se já foi chamado.\r\n */\r\n start(): void {\r\n if (this._started || this._destroyed) return;\r\n this._started = true;\r\n\r\n // Cria o canal se ainda não foi injetado\r\n if (!this._channel && this._channelFactory) {\r\n this._channel = this._channelFactory();\r\n }\r\n\r\n // Configura o handler de mensagens do BroadcastChannel\r\n if (this._channel) {\r\n this._channel.onmessage = (msg: TabMessage) => {\r\n this._handleIncomingMessage(msg);\r\n };\r\n }\r\n\r\n // Inicia eleição\r\n if (this._lockManager) {\r\n this._electWithLocks();\r\n } else {\r\n // Fallback: sem Web Locks → assume liderança imediatamente\r\n this._becomeLeader();\r\n }\r\n }\r\n\r\n /**\r\n * Para o TabCoordinator: libera o lock, fecha o canal.\r\n * Idempotente: pode ser chamado múltiplas vezes.\r\n */\r\n destroy(): void {\r\n if (this._destroyed) return;\r\n this._destroyed = true;\r\n this._started = false;\r\n\r\n // Libera o lock perpétuo (se líder)\r\n if (this._releaseLock) {\r\n this._releaseLock();\r\n this._releaseLock = null;\r\n }\r\n\r\n // Fecha o canal de broadcast\r\n if (this._channel) {\r\n this._channel.onmessage = null;\r\n this._channel.close();\r\n this._channel = undefined;\r\n }\r\n\r\n // Atualiza papel local (sem notificar — aba está sendo destruída)\r\n this._role = 'follower';\r\n\r\n // Limpa listeners\r\n this._roleListeners.clear();\r\n this._messageListeners.clear();\r\n }\r\n\r\n // ─── Estado ──────────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Retorna `true` se esta aba é atualmente a líder.\r\n */\r\n isLeader(): boolean {\r\n return !this._destroyed && this._role === 'leader';\r\n }\r\n\r\n /**\r\n * Retorna o papel atual desta aba.\r\n */\r\n getRole(): TabRole {\r\n return this._destroyed ? 'follower' : this._role;\r\n }\r\n\r\n /**\r\n * ID único desta aba (para diagnóstico).\r\n */\r\n get tabId(): string {\r\n return this._tabId;\r\n }\r\n\r\n // ─── Subscrições ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Registra um listener para mudanças de papel (`'leader'` | `'follower'`).\r\n *\r\n * @returns Função de unsubscribe.\r\n */\r\n onRoleChange(listener: RoleChangeListener): Unsubscribe {\r\n this._roleListeners.add(listener);\r\n return () => {\r\n this._roleListeners.delete(listener);\r\n };\r\n }\r\n\r\n /**\r\n * Registra um listener para mensagens recebidas de outras abas via\r\n * BroadcastChannel. O remetente NÃO recebe suas próprias mensagens.\r\n *\r\n * @returns Função de unsubscribe.\r\n */\r\n onMessage(listener: (msg: TabMessage) => void): Unsubscribe {\r\n this._messageListeners.add(listener);\r\n return () => {\r\n this._messageListeners.delete(listener);\r\n };\r\n }\r\n\r\n // ─── Comunicação ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Transmite uma mensagem para todas as outras abas via BroadcastChannel.\r\n * Sem efeito se o canal não estiver disponível ou o coordinator foi destroyed.\r\n */\r\n broadcast(msg: TabMessage): void {\r\n if (this._destroyed) return;\r\n try {\r\n this._channel?.postMessage(msg);\r\n } catch {\r\n // BroadcastChannel pode estar fechado — ignora silenciosamente\r\n }\r\n }\r\n\r\n // ─── Privado — eleição ───────────────────────────────────────────────────────\r\n\r\n /**\r\n * Inicia a disputa pelo lock Web Locks.\r\n *\r\n * `navigator.locks.request` com uma Promise-interna que nunca resolve:\r\n * enquanto a aba vive e o lock está ativo, a callback não retorna.\r\n * Ao chamar `destroy()` a Promise interna resolve → lock liberado.\r\n */\r\n private _electWithLocks(): void {\r\n const lockPromise = new Promise<void>((resolve) => {\r\n this._releaseLock = resolve;\r\n });\r\n\r\n // Notifica que esta aba está aguardando o lock (papel follower).\r\n // Feito de forma assíncrona para garantir que o chamador já registrou\r\n // seus listeners via onRoleChange() antes do primeiro disparo.\r\n Promise.resolve().then(() => {\r\n if (!this._destroyed && this._role === 'follower') {\r\n this._notifyRoleChange('follower');\r\n }\r\n });\r\n\r\n // `request` retorna uma Promise que resolve quando o lock é adquirido\r\n // e a callback retorna. Enquanto a callback não retornar, o lock é mantido.\r\n this._lockManager!.request(this._lockName, (_lock: LockLike) => {\r\n if (this._destroyed) {\r\n // Se foi destroyed antes de adquirir o lock, libera imediatamente\r\n return Promise.resolve();\r\n }\r\n this._becomeLeader();\r\n return lockPromise;\r\n }).catch(() => {\r\n // request rejeitado (ex.: lock request abortado) — sem crash\r\n });\r\n }\r\n\r\n /**\r\n * Transição para o papel de líder.\r\n */\r\n private _becomeLeader(): void {\r\n if (this._destroyed) return;\r\n this._setRole('leader');\r\n // Anuncia liderança para seguidores após o tick atual, garantindo que\r\n // todos os seguidores já registraram seus handlers de onmessage.\r\n Promise.resolve().then(() => {\r\n if (!this._destroyed) this._broadcastSyncState();\r\n });\r\n }\r\n\r\n /**\r\n * Muda o papel e notifica os listeners.\r\n */\r\n private _setRole(role: TabRole): void {\r\n const previous = this._role;\r\n this._role = role;\r\n if (previous !== role) {\r\n this._notifyRoleChange(role);\r\n }\r\n }\r\n\r\n /**\r\n * Transmite o estado de sync atual (chamado ao se tornar líder).\r\n */\r\n private _broadcastSyncState(): void {\r\n this.broadcast({\r\n type: 'sync_state',\r\n leaderTabId: this._tabId,\r\n syncing: false,\r\n pendingWrites: 0,\r\n });\r\n }\r\n\r\n // ─── Privado — mensagens ─────────────────────────────────────────────────────\r\n\r\n /**\r\n * Processa mensagem recebida de outra aba.\r\n * Mensagens de tipo desconhecido são ignoradas silenciosamente.\r\n */\r\n private _handleIncomingMessage(msg: TabMessage): void {\r\n if (this._destroyed) return;\r\n if (!msg || typeof msg.type !== 'string') return;\r\n\r\n // Entrega a todos os listeners registrados\r\n for (const listener of this._messageListeners) {\r\n try {\r\n listener(msg);\r\n } catch {\r\n // Listener com erro não interrompe os demais\r\n }\r\n }\r\n }\r\n\r\n // ─── Privado — notificações ───────────────────────────────────────────────────\r\n\r\n private _notifyRoleChange(role: TabRole): void {\r\n for (const listener of this._roleListeners) {\r\n try {\r\n listener(role);\r\n } catch {\r\n // Listener com erro não interrompe os demais\r\n }\r\n }\r\n }\r\n}\r\n","/**\r\n * DbCollectionRef — superfície de Documentos offline-first do @neetru/sdk (M2).\r\n *\r\n * Implementa a API pública conforme especificada em:\r\n * - 02-sdk.md §3.2 (contrato TypeScript DbCollectionRef)\r\n * - I2-mundo-documentos.md §3.2 (superfície dupla CRUD + realtime)\r\n * - I3-sdk-offline.md §10 (camada offline, lifecycle, SyncState)\r\n *\r\n * ### Semântica de Promise de escrita (02-sdk.md §3.2 nota negrito)\r\n * `add/set/update/remove` resolvem quando a escrita está **durável localmente**\r\n * (cache + fila), NÃO quando o servidor confirma. Isso é offline-first por design:\r\n * sem rede, `add()` resolve imediatamente. Para saber quando sincronizou, o produto\r\n * observa `onWriteResult` (future / SyncEngine). A Promise só rejeita por:\r\n * - validação síncrona (nome de coleção inválido, id vazio)\r\n * - `offline_quota_exceeded` (IndexedDB cheio)\r\n *\r\n * ### Injeção do transporte realtime\r\n * O `RealtimeTransport` é injetado via `createOfflineDocumentsNamespace({ transport })`.\r\n * A implementação atual usa o `SyncEngine` para push/pull (sync offline ↔ servidor).\r\n * Transportes futuros (Firestore Web SDK / WebSocket gateway) são injetados aqui —\r\n * sem alterar a superfície pública.\r\n */\r\n\r\nimport { LocalStore } from './offline/local-store';\r\nimport { MutationQueue } from './offline/mutation-queue';\r\nimport { SyncEngine, type SyncTransport } from './offline/sync-engine';\r\nimport { ConflictResolver } from './offline/conflict-resolver';\r\nimport { ChangeBus } from './offline/change-bus';\r\nimport { ConnectivityMonitor } from './offline/connectivity-monitor';\r\nimport { TabCoordinator } from './offline/tab-coordinator';\r\nimport { NeetruDbError } from '../db-errors';\r\nimport type {\r\n QueryDescriptor,\r\n Change,\r\n Unsubscribe,\r\n SyncState,\r\n ConflictRecord,\r\n} from './offline/types';\r\n\r\n// ─── Re-exportar tipos públicos ───────────────────────────────────────────────\r\n\r\nexport type { DbSnapshot } from './offline/types';\r\nexport { NeetruDbError } from '../db-errors';\r\n\r\n// ─── Tipos públicos da superfície de Documentos ───────────────────────────────\r\n\r\nexport interface DbWhereFilter {\r\n field: string;\r\n op: '==' | '!=' | '<' | '<=' | '>' | '>=' | 'array-contains' | 'in' | 'not-in';\r\n value: unknown;\r\n}\r\n\r\nexport interface DbQuery {\r\n where?: DbWhereFilter[];\r\n orderBy?: { field: string; direction?: 'asc' | 'desc' };\r\n /** Máximo de documentos. Default 20, max 500. */\r\n limit?: number;\r\n /** Cursor opaco — devolvido em `DbListResult.nextCursor`. */\r\n cursor?: string;\r\n}\r\n\r\nexport interface DbDoc<T = Record<string, unknown>> {\r\n id: string;\r\n data: T;\r\n}\r\n\r\nexport interface DbListResult<T = Record<string, unknown>> {\r\n docs: DbDoc<T>[];\r\n nextCursor: string | null;\r\n fromCache: boolean;\r\n stale: boolean;\r\n hasPendingWrites: boolean;\r\n changes: Array<{ type: 'added' | 'modified' | 'removed'; doc: DbDoc<T> }>;\r\n}\r\n\r\nexport interface DbGetResult<T = Record<string, unknown>> {\r\n docs: Array<DbDoc<T>>;\r\n fromCache: boolean;\r\n stale: boolean;\r\n hasPendingWrites: boolean;\r\n changes: Array<{ type: 'added' | 'modified' | 'removed'; doc: DbDoc<T> }>;\r\n}\r\n\r\nexport type DbChangeType = 'added' | 'modified' | 'removed';\r\n\r\nexport interface DbBatchOp {\r\n op: 'add' | 'set' | 'update' | 'remove';\r\n collection: string;\r\n id?: string;\r\n data?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Contrato do transporte de realtime — injetado no namespace.\r\n *\r\n * A implementação real usa os endpoints `/api/sdk/v1/db/*` do Core.\r\n * Em testes, usa-se um fake in-memory.\r\n *\r\n * Este é o **seam de injeção** que conecta a camada offline ao servidor real.\r\n * Transportes futuros (Firestore Web SDK direto / WebSocket gateway) são\r\n * implementados aqui, sem modificar a superfície pública `DbCollectionRef`.\r\n */\r\nexport type RealtimeTransport = SyncTransport;\r\n\r\n// ─── Validação de nome de coleção ─────────────────────────────────────────────\r\n\r\nconst COLL_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/;\r\n\r\nfunction assertValidCollection(name: string): void {\r\n if (!COLL_RE.test(name)) {\r\n throw new NeetruDbError(\r\n 'db_invalid_query',\r\n `Nome de coleção inválido: \"${name}\". Deve seguir o padrão ${COLL_RE}.`,\r\n );\r\n }\r\n}\r\n\r\nfunction assertValidId(id: string, label = 'id'): void {\r\n if (!id || typeof id !== 'string' || id.trim() === '') {\r\n throw new NeetruDbError(\r\n 'db_invalid_query',\r\n `${label} é obrigatório e deve ser uma string não-vazia.`,\r\n );\r\n }\r\n}\r\n\r\n// ─── Serialização de DbQuery → QueryDescriptor ────────────────────────────────\r\n\r\nfunction toQueryDescriptor(query?: DbQuery): QueryDescriptor {\r\n const desc: QueryDescriptor = {};\r\n\r\n if (query?.where) {\r\n desc.where = query.where.map((f) => ({\r\n field: f.field,\r\n op: f.op as import('./offline/types').WhereOp,\r\n value: f.value,\r\n }));\r\n }\r\n\r\n if (query?.orderBy) {\r\n desc.orderBy = {\r\n field: query.orderBy.field,\r\n direction: query.orderBy.direction,\r\n };\r\n }\r\n\r\n if (query?.limit !== undefined) {\r\n desc.limit = query.limit;\r\n }\r\n\r\n if (query?.cursor) {\r\n // O cursor é o docId serializado em base64\r\n try {\r\n const cursorObj = JSON.parse(atob(query.cursor)) as { docId: string; type: 'startAfter' };\r\n desc.cursor = { type: cursorObj.type ?? 'startAfter', docId: cursorObj.docId };\r\n } catch {\r\n // cursor inválido — ignora\r\n }\r\n }\r\n\r\n return desc;\r\n}\r\n\r\n/** Serializa o último doc de uma lista como cursor opaco. */\r\nfunction buildNextCursor(docs: Array<{ id: string }>, limit: number): string | null {\r\n if (docs.length < limit) return null;\r\n const lastDoc = docs[docs.length - 1];\r\n if (!lastDoc) return null;\r\n return btoa(JSON.stringify({ type: 'startAfter', docId: lastDoc.id }));\r\n}\r\n\r\n// ─── DbDocRef ─────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Referência a um documento específico.\r\n * Parte da superfície `DbCollectionRef.doc(id)`.\r\n */\r\nexport interface DbDocRef<T = Record<string, unknown>> {\r\n get(): Promise<DbGetResult<T> | null>;\r\n set(data: Omit<T, 'id'>): Promise<{ ok: true }>;\r\n update(data: Partial<Omit<T, 'id'>>): Promise<{ ok: true }>;\r\n remove(): Promise<{ ok: true }>;\r\n onSnapshot(cb: (snap: DbGetResult<T> | null) => void): Unsubscribe;\r\n}\r\n\r\n// ─── DbCollectionRef ──────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Referência a uma coleção — superfície dupla CRUD + realtime.\r\n *\r\n * Conforme 02-sdk.md §3.2 / I2 §3.2.\r\n */\r\nexport interface DbCollectionRef<T = Record<string, unknown>> {\r\n // ── CRUD (request/resposta offline-transparente) ──────────────────────────\r\n /** Retorna snapshot de um documento. `null` se não existir (nem no cache). */\r\n get(id: string): Promise<DbGetResult<T> | null>;\r\n /** Lista documentos com query opcional. */\r\n list(q?: DbQuery): Promise<DbListResult<T>>;\r\n /** Adiciona doc com id gerado pelo cliente (UUID v4). Durável localmente. */\r\n add(data: Omit<T, 'id'>): Promise<{ ok: true; id: string }>;\r\n /** Cria ou sobrescreve um doc pelo id. Durável localmente. */\r\n set(id: string, data: Omit<T, 'id'>): Promise<{ ok: true }>;\r\n /** Atualiza campos de um doc (merge). Durável localmente. */\r\n update(id: string, data: Partial<Omit<T, 'id'>>): Promise<{ ok: true }>;\r\n /** Remove um doc (tombstone local). Durável localmente. */\r\n remove(id: string): Promise<{ ok: true }>;\r\n /** Aplica múltiplas operações atomicamente na fila. */\r\n batch(ops: DbBatchOp[]): Promise<{ ok: true }>;\r\n\r\n // ── Realtime (listeners ao vivo) ──────────────────────────────────────────\r\n /** Escuta um documento específico. */\r\n onDoc(id: string, cb: (doc: T | null) => void): Unsubscribe;\r\n /** Escuta a coleção inteira (ou subconjunto via query). */\r\n onSnapshot(q: DbQuery | undefined, cb: (snap: DbListResult<T>) => void): Unsubscribe;\r\n\r\n // ── DbDocRef ──────────────────────────────────────────────────────────────\r\n /** Retorna uma referência ao documento `id`. */\r\n doc(id: string): DbDocRef<T>;\r\n}\r\n\r\n// ─── NeetruDbDocuments namespace ─────────────────────────────────────────────\r\n\r\n/**\r\n * Namespace `db.documents` — ponto de entrada para coleções de documentos.\r\n *\r\n * Analogia a `NeetruDb` de 02-sdk.md §3.1 mas escoped para o Mundo Documentos.\r\n */\r\nexport interface NeetruDbDocuments {\r\n collection<T = Record<string, unknown>>(name: string): DbCollectionRef<T>;\r\n /** Estado atual de sincronização (offline/online/syncing). */\r\n readonly syncState: SyncState;\r\n onSyncStateChanged(cb: (s: SyncState) => void): Unsubscribe;\r\n /** Força flush da fila de mutações pendentes. */\r\n flush(): Promise<void>;\r\n /** Limpa o cache local (IndexedDB) — operação destrutiva. */\r\n clearCache(): Promise<void>;\r\n /**\r\n * Retorna os registros do log de conflitos LWW gravados pelo SyncEngine.\r\n * Um conflito ocorre quando a mutação local é descartada porque o servidor\r\n * já avançou a versão do documento (Last-Write-Wins).\r\n */\r\n getConflicts(): Promise<ConflictRecord[]>;\r\n}\r\n\r\n// ─── Opções de criação do namespace ──────────────────────────────────────────\r\n\r\nexport interface CreateOfflineDocumentsOptions {\r\n /**\r\n * Nome do banco IndexedDB — deve ser único por produto × dbId × env.\r\n * Convenção: `neetru-db__{productSlug}__{dbId}__{env}`.\r\n */\r\n dbName: string;\r\n\r\n /**\r\n * Transporte de sync — implementa `SyncTransport` do SyncEngine.\r\n * Este é o **seam de injeção** do transporte real.\r\n *\r\n * Implementações possíveis:\r\n * - `RestSyncTransport` — REST → Core (padrão em staging/prod)\r\n * - `FirestoreRealtimeTransport` — Firestore Web SDK direto (engine=firestore)\r\n * - `WebSocketTransport` — WebSocket → gateway (engine=nosql-vm)\r\n * - `FakeRealtimeTransport` — in-memory (testes)\r\n */\r\n transport: RealtimeTransport;\r\n\r\n /**\r\n * Estado inicial de conectividade.\r\n * Default: `navigator.onLine` se disponível, senão `true`.\r\n */\r\n startOnline?: boolean;\r\n\r\n /**\r\n * `true` = sem contenção multi-aba (sempre líder).\r\n * Padrão em testes; em produção usa Web Locks.\r\n */\r\n singleTab?: boolean;\r\n\r\n /**\r\n * Intervalo do sync periódico em ms. `0` desativa.\r\n * Default: 5 * 60 * 1000 (5min).\r\n */\r\n periodicSyncIntervalMs?: number;\r\n}\r\n\r\n// ─── Implementação interna ────────────────────────────────────────────────────\r\n\r\n/**\r\n * Implementação de `DbCollectionRef` que usa a camada offline real.\r\n */\r\nclass DbCollectionRefImpl<T = Record<string, unknown>> implements DbCollectionRef<T> {\r\n constructor(\r\n private readonly _collection: string,\r\n private readonly _store: LocalStore,\r\n private readonly _queue: MutationQueue,\r\n private readonly _bus: ChangeBus,\r\n private readonly _engine: SyncEngine,\r\n private readonly _connectivity: ConnectivityMonitor,\r\n ) {}\r\n\r\n // ── helpers ────────────────────────────────────────────────────────────────\r\n\r\n /** Verifica se há mutações pendentes para esta coleção. */\r\n private async _hasPendingWrites(): Promise<boolean> {\r\n const pending = await this._queue.listPending();\r\n return pending.some((m) => m.collection === this._collection);\r\n }\r\n\r\n /** Verifica se há mutações pendentes para um doc específico. */\r\n private async _docHasPendingWrites(id: string): Promise<boolean> {\r\n const pending = await this._queue.listPending();\r\n return pending.some((m) => m.collection === this._collection && m.docId === id);\r\n }\r\n\r\n private _isOnline(): boolean {\r\n return this._connectivity.isOnline;\r\n }\r\n\r\n /** Constrói um DbGetResult para um doc específico, ou null se tombstoned/ausente. */\r\n private async _buildGetResult(id: string): Promise<DbGetResult<T> | null> {\r\n const doc = await this._store.getDoc<T>(this._collection, id);\r\n if (!doc || doc.meta.deleted) return null;\r\n\r\n const hasPending = await this._docHasPendingWrites(id);\r\n const isOnline = this._isOnline();\r\n const syncState = this._engine.getSyncState();\r\n\r\n const staleGet = !isOnline || syncState.status === 'offline';\r\n const fromCacheGet = hasPending || syncState.lastSyncedAt === null || staleGet;\r\n\r\n return {\r\n docs: [{ id: doc.id, data: doc.data }],\r\n fromCache: fromCacheGet,\r\n stale: staleGet,\r\n hasPendingWrites: hasPending,\r\n changes: [],\r\n };\r\n }\r\n\r\n /** Constrói um DbListResult para a coleção com query opcional. */\r\n private async _buildListResult(q?: DbQuery): Promise<DbListResult<T>> {\r\n const desc = toQueryDescriptor(q);\r\n const effectiveLimit = desc.limit ?? 20;\r\n const result = await this._store.listDocs<T>(this._collection, desc);\r\n\r\n const hasPending = await this._hasPendingWrites();\r\n const isOnline = this._isOnline();\r\n const syncState = this._engine.getSyncState();\r\n\r\n const nextCursor = buildNextCursor(result.docs, effectiveLimit);\r\n\r\n // fromCache: false quando há um lastSyncedAt confirmado e sem pending writes.\r\n // offline-first: antes do primeiro sync bem-sucedido é sempre fromCache:true.\r\n const stale = !isOnline || syncState.status === 'offline';\r\n const fromCache = hasPending || syncState.lastSyncedAt === null || stale;\r\n\r\n return {\r\n docs: result.docs.map((d) => ({ id: d.id, data: d.data })),\r\n nextCursor,\r\n fromCache,\r\n stale,\r\n hasPendingWrites: hasPending,\r\n changes: [],\r\n };\r\n }\r\n\r\n // ── CRUD ────────────────────────────────────────────────────────────────────\r\n\r\n async get(id: string): Promise<DbGetResult<T> | null> {\r\n assertValidId(id);\r\n return this._buildGetResult(id);\r\n }\r\n\r\n async list(q?: DbQuery): Promise<DbListResult<T>> {\r\n return this._buildListResult(q);\r\n }\r\n\r\n async add(data: Omit<T, 'id'>): Promise<{ ok: true; id: string }> {\r\n const mutation = await this._queue.enqueue({\r\n collection: this._collection,\r\n op: 'add',\r\n payload: data as Record<string, unknown>,\r\n baseVersion: null,\r\n batchId: null,\r\n });\r\n\r\n const docId = mutation.docId;\r\n\r\n // Aplica otimisticamente no LocalStore\r\n await this._store.putDoc({\r\n collection: this._collection,\r\n id: docId,\r\n data: data as Record<string, unknown>,\r\n meta: {\r\n serverVersion: null,\r\n updatedAtServer: null,\r\n updatedAtLocal: Date.now(),\r\n state: 'pending',\r\n pendingMutationIds: [mutation.mutationId],\r\n deleted: false,\r\n ownerId: null,\r\n },\r\n });\r\n\r\n // Notifica listeners\r\n this._bus.emit([{\r\n type: 'added',\r\n collection: this._collection,\r\n doc: { id: docId, data: data as Record<string, unknown> },\r\n }]);\r\n\r\n return { ok: true, id: docId };\r\n }\r\n\r\n async set(id: string, data: Omit<T, 'id'>): Promise<{ ok: true }> {\r\n assertValidId(id);\r\n\r\n const existing = await this._store.getDoc(this._collection, id);\r\n const mutation = await this._queue.enqueue({\r\n collection: this._collection,\r\n docId: id,\r\n op: 'set',\r\n payload: data as Record<string, unknown>,\r\n baseVersion: existing?.meta.serverVersion ?? null,\r\n batchId: null,\r\n });\r\n\r\n // Aplica otimisticamente\r\n await this._store.putDoc({\r\n collection: this._collection,\r\n id,\r\n data: data as Record<string, unknown>,\r\n meta: {\r\n serverVersion: existing?.meta.serverVersion ?? null,\r\n updatedAtServer: existing?.meta.updatedAtServer ?? null,\r\n updatedAtLocal: Date.now(),\r\n state: 'pending',\r\n pendingMutationIds: [mutation.mutationId],\r\n deleted: false,\r\n ownerId: null,\r\n },\r\n });\r\n\r\n this._bus.emit([{\r\n type: existing && !existing.meta.deleted ? 'modified' : 'added',\r\n collection: this._collection,\r\n doc: { id, data: data as Record<string, unknown> },\r\n }]);\r\n\r\n return { ok: true };\r\n }\r\n\r\n async update(id: string, data: Partial<Omit<T, 'id'>>): Promise<{ ok: true }> {\r\n assertValidId(id);\r\n\r\n const existing = await this._store.getDoc(this._collection, id);\r\n const mergedData = existing?.meta.deleted\r\n ? { ...(data as Record<string, unknown>) }\r\n : { ...(existing?.data ?? {}), ...(data as Record<string, unknown>) };\r\n\r\n const mutation = await this._queue.enqueue({\r\n collection: this._collection,\r\n docId: id,\r\n op: 'update',\r\n payload: data as Record<string, unknown>,\r\n baseVersion: existing?.meta.serverVersion ?? null,\r\n batchId: null,\r\n });\r\n\r\n await this._store.putDoc({\r\n collection: this._collection,\r\n id,\r\n data: mergedData,\r\n meta: {\r\n serverVersion: existing?.meta.serverVersion ?? null,\r\n updatedAtServer: existing?.meta.updatedAtServer ?? null,\r\n updatedAtLocal: Date.now(),\r\n state: 'pending',\r\n pendingMutationIds: [\r\n ...(existing?.meta.pendingMutationIds ?? []),\r\n mutation.mutationId,\r\n ],\r\n deleted: false,\r\n ownerId: existing?.meta.ownerId ?? null,\r\n },\r\n });\r\n\r\n this._bus.emit([{\r\n type: 'modified',\r\n collection: this._collection,\r\n doc: { id, data: mergedData },\r\n }]);\r\n\r\n return { ok: true };\r\n }\r\n\r\n async remove(id: string): Promise<{ ok: true }> {\r\n assertValidId(id);\r\n\r\n const existing = await this._store.getDoc(this._collection, id);\r\n if (!existing || existing.meta.deleted) {\r\n // Se era um doc add-only ainda na fila, o coalescing no MutationQueue vai lidar\r\n }\r\n\r\n await this._queue.enqueue({\r\n collection: this._collection,\r\n docId: id,\r\n op: 'remove',\r\n payload: null,\r\n baseVersion: existing?.meta.serverVersion ?? null,\r\n batchId: null,\r\n });\r\n\r\n // Tombstone otimístico\r\n await this._store.deleteDoc(this._collection, id);\r\n\r\n if (existing && !existing.meta.deleted) {\r\n this._bus.emit([{\r\n type: 'removed',\r\n collection: this._collection,\r\n doc: { id, data: existing.data },\r\n }]);\r\n }\r\n\r\n return { ok: true };\r\n }\r\n\r\n async batch(ops: DbBatchOp[]): Promise<{ ok: true }> {\r\n const batchId = `batch-${Date.now()}-${Math.random().toString(36).slice(2)}`;\r\n const busChanges: Change[] = [];\r\n\r\n for (const op of ops) {\r\n const id = op.id ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`;\r\n const data = op.data ?? {};\r\n const collection = op.collection;\r\n\r\n if (op.op === 'add') {\r\n const mutation = await this._queue.enqueue({\r\n collection,\r\n op: 'add',\r\n payload: data,\r\n baseVersion: null,\r\n batchId,\r\n });\r\n const docId = mutation.docId;\r\n await this._store.putDoc({\r\n collection,\r\n id: docId,\r\n data,\r\n meta: {\r\n serverVersion: null,\r\n updatedAtServer: null,\r\n updatedAtLocal: Date.now(),\r\n state: 'pending',\r\n pendingMutationIds: [mutation.mutationId],\r\n deleted: false,\r\n ownerId: null,\r\n },\r\n });\r\n busChanges.push({ type: 'added', collection, doc: { id: docId, data } });\r\n } else if (op.op === 'set') {\r\n const existing = await this._store.getDoc(collection, id);\r\n const mutation = await this._queue.enqueue({\r\n collection,\r\n docId: id,\r\n op: 'set',\r\n payload: data,\r\n baseVersion: existing?.meta.serverVersion ?? null,\r\n batchId,\r\n });\r\n await this._store.putDoc({\r\n collection,\r\n id,\r\n data,\r\n meta: {\r\n serverVersion: existing?.meta.serverVersion ?? null,\r\n updatedAtServer: existing?.meta.updatedAtServer ?? null,\r\n updatedAtLocal: Date.now(),\r\n state: 'pending',\r\n pendingMutationIds: [mutation.mutationId],\r\n deleted: false,\r\n ownerId: null,\r\n },\r\n });\r\n busChanges.push({\r\n type: existing && !existing.meta.deleted ? 'modified' : 'added',\r\n collection,\r\n doc: { id, data },\r\n });\r\n } else if (op.op === 'update') {\r\n const existing = await this._store.getDoc(collection, id);\r\n const merged = { ...(existing?.data ?? {}), ...data };\r\n const mutation = await this._queue.enqueue({\r\n collection,\r\n docId: id,\r\n op: 'update',\r\n payload: data,\r\n baseVersion: existing?.meta.serverVersion ?? null,\r\n batchId,\r\n });\r\n await this._store.putDoc({\r\n collection,\r\n id,\r\n data: merged,\r\n meta: {\r\n serverVersion: existing?.meta.serverVersion ?? null,\r\n updatedAtServer: existing?.meta.updatedAtServer ?? null,\r\n updatedAtLocal: Date.now(),\r\n state: 'pending',\r\n pendingMutationIds: [\r\n ...(existing?.meta.pendingMutationIds ?? []),\r\n mutation.mutationId,\r\n ],\r\n deleted: false,\r\n ownerId: existing?.meta.ownerId ?? null,\r\n },\r\n });\r\n busChanges.push({ type: 'modified', collection, doc: { id, data: merged } });\r\n } else if (op.op === 'remove') {\r\n const existing = await this._store.getDoc(collection, id);\r\n await this._queue.enqueue({\r\n collection,\r\n docId: id,\r\n op: 'remove',\r\n payload: null,\r\n baseVersion: existing?.meta.serverVersion ?? null,\r\n batchId,\r\n });\r\n await this._store.deleteDoc(collection, id);\r\n if (existing && !existing.meta.deleted) {\r\n busChanges.push({ type: 'removed', collection, doc: { id, data: existing.data } });\r\n }\r\n }\r\n }\r\n\r\n if (busChanges.length > 0) {\r\n this._bus.emit(busChanges);\r\n }\r\n\r\n return { ok: true };\r\n }\r\n\r\n // ── Realtime ─────────────────────────────────────────────────────────────────\r\n\r\n onDoc(id: string, cb: (doc: T | null) => void): Unsubscribe {\r\n assertValidId(id);\r\n\r\n // Entrega inicial imediata\r\n this._buildGetResult(id)\r\n .then((r) => {\r\n cb(r ? (r.docs[0]?.data ?? null) as T | null : null);\r\n })\r\n .catch(() => cb(null));\r\n\r\n // Subscreve ao bus da coleção para receber mudanças\r\n return this._bus.subscribe(this._collection, (changes) => {\r\n const relevant = changes.find((c) => c.doc.id === id);\r\n if (!relevant) return;\r\n\r\n if (relevant.type === 'removed') {\r\n cb(null);\r\n } else {\r\n cb(relevant.doc.data as T);\r\n }\r\n });\r\n }\r\n\r\n onSnapshot(q: DbQuery | undefined, cb: (snap: DbListResult<T>) => void): Unsubscribe {\r\n // Entrega inicial imediata (estado atual do cache)\r\n this._buildListResult(q).then((snap) => cb(snap)).catch(() => {});\r\n\r\n // Listener de mudanças do bus (local + server-pushed)\r\n const unsubBus = this._bus.subscribe(this._collection, async (_changes) => {\r\n try {\r\n // Reconstrói o snapshot completo com o estado atual + changes delta\r\n const snap = await this._buildListResult(q);\r\n\r\n // Injeta delta de changes (apenas os relevantes para a query)\r\n const delta = _changes.map((c) => ({\r\n type: c.type as DbChangeType,\r\n doc: { id: c.doc.id, data: c.doc.data as T },\r\n }));\r\n cb({ ...snap, changes: delta });\r\n } catch {\r\n // silencioso\r\n }\r\n });\r\n\r\n // Listener de mudanças de SyncState (para atualizar stale/fromCache)\r\n const unsubSync = this._engine.onSyncStateChange(async () => {\r\n try {\r\n const snap = await this._buildListResult(q);\r\n cb(snap);\r\n } catch {\r\n // silencioso\r\n }\r\n });\r\n\r\n // HIGH-1: se o transporte expõe subscribeCollection (nosql-vm/realtime),\r\n // registra a subscription e alimenta os deltas no ChangeBus local.\r\n let unsubRealtime: (() => void) | undefined;\r\n if (typeof (this._engine.transport as SyncTransport).subscribeCollection === 'function') {\r\n unsubRealtime = (this._engine.transport as SyncTransport).subscribeCollection!(\r\n this._collection,\r\n async (remoteChanges, needsResync) => {\r\n if (needsResync) {\r\n // Marca sincronização necessária via SyncState — o SyncEngine\r\n // disparará um fullResync no próximo ciclo.\r\n return;\r\n }\r\n // Converte as mudanças remotas para Change[] e aplica no LocalStore\r\n for (const rc of remoteChanges) {\r\n if (rc.type === 'removed' || rc.data === null) {\r\n await this._store.deleteDoc(this._collection, rc.docId);\r\n this._bus.emit([{\r\n type: 'removed',\r\n collection: this._collection,\r\n doc: { id: rc.docId, data: {} as Record<string, unknown> },\r\n }]);\r\n } else {\r\n await this._store.putDoc({\r\n collection: this._collection,\r\n id: rc.docId,\r\n data: rc.data,\r\n meta: {\r\n serverVersion: `rt_${Date.now()}`,\r\n updatedAtServer: Date.now(),\r\n updatedAtLocal: Date.now(),\r\n state: 'synced',\r\n pendingMutationIds: [],\r\n deleted: false,\r\n ownerId: null,\r\n },\r\n });\r\n this._bus.emit([{\r\n type: rc.type,\r\n collection: this._collection,\r\n doc: { id: rc.docId, data: rc.data },\r\n }]);\r\n }\r\n }\r\n },\r\n );\r\n }\r\n\r\n return () => {\r\n unsubBus();\r\n unsubSync();\r\n unsubRealtime?.();\r\n };\r\n }\r\n\r\n doc(id: string): DbDocRef<T> {\r\n assertValidId(id);\r\n const self = this;\r\n\r\n return {\r\n async get(): Promise<DbGetResult<T> | null> {\r\n return self._buildGetResult(id);\r\n },\r\n async set(data: Omit<T, 'id'>): Promise<{ ok: true }> {\r\n return self.set(id, data);\r\n },\r\n async update(data: Partial<Omit<T, 'id'>>): Promise<{ ok: true }> {\r\n return self.update(id, data);\r\n },\r\n async remove(): Promise<{ ok: true }> {\r\n return self.remove(id);\r\n },\r\n onSnapshot(cb: (snap: DbGetResult<T> | null) => void): Unsubscribe {\r\n // Entrega inicial\r\n self._buildGetResult(id).then((r) => cb(r)).catch(() => cb(null));\r\n\r\n const unsubBus = self._bus.subscribe(self._collection, async (changes) => {\r\n const relevant = changes.find((c) => c.doc.id === id);\r\n if (!relevant) return;\r\n try {\r\n if (relevant.type === 'removed') {\r\n cb(null);\r\n } else {\r\n const result = await self._buildGetResult(id);\r\n cb(result);\r\n }\r\n } catch {\r\n cb(null);\r\n }\r\n });\r\n\r\n const unsubSync = self._engine.onSyncStateChange(async () => {\r\n try {\r\n const result = await self._buildGetResult(id);\r\n cb(result);\r\n } catch {\r\n cb(null);\r\n }\r\n });\r\n\r\n return () => {\r\n unsubBus();\r\n unsubSync();\r\n };\r\n },\r\n };\r\n }\r\n}\r\n\r\n// ─── Implementação de NeetruDbDocuments ──────────────────────────────────────\r\n\r\nclass NeetruDbDocumentsImpl implements NeetruDbDocuments {\r\n private readonly _store: LocalStore;\r\n private readonly _queue: MutationQueue;\r\n private readonly _bus: ChangeBus;\r\n private readonly _engine: SyncEngine;\r\n private readonly _connectivity: ConnectivityMonitor;\r\n\r\n constructor(opts: {\r\n store: LocalStore;\r\n queue: MutationQueue;\r\n bus: ChangeBus;\r\n engine: SyncEngine;\r\n connectivity: ConnectivityMonitor;\r\n }) {\r\n this._store = opts.store;\r\n this._queue = opts.queue;\r\n this._bus = opts.bus;\r\n this._engine = opts.engine;\r\n this._connectivity = opts.connectivity;\r\n }\r\n\r\n collection<T = Record<string, unknown>>(name: string): DbCollectionRef<T> {\r\n assertValidCollection(name);\r\n return new DbCollectionRefImpl<T>(\r\n name,\r\n this._store,\r\n this._queue,\r\n this._bus,\r\n this._engine,\r\n this._connectivity,\r\n );\r\n }\r\n\r\n get syncState(): SyncState {\r\n return this._engine.getSyncState();\r\n }\r\n\r\n onSyncStateChanged(cb: (s: SyncState) => void): Unsubscribe {\r\n return this._engine.onSyncStateChange(cb);\r\n }\r\n\r\n async flush(): Promise<void> {\r\n return this._engine.flush();\r\n }\r\n\r\n async clearCache(): Promise<void> {\r\n await this._store.close();\r\n // Reabre o banco (criará um banco limpo — não há API de \"clear all\" no idb wrapper)\r\n // Em produção, usaríamos indexedDB.deleteDatabase(); aqui fazemos close + reopen.\r\n await this._store.open();\r\n }\r\n\r\n async getConflicts(): Promise<ConflictRecord[]> {\r\n return this._store.listConflicts();\r\n }\r\n}\r\n\r\n// ─── Factory pública ─────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Cria e inicializa o namespace de documentos offline-first.\r\n *\r\n * Configura todos os 8 componentes da camada offline (LocalStore, MutationQueue,\r\n * QueryEngine, SyncEngine, ConflictResolver, ConnectivityMonitor, TabCoordinator,\r\n * ChangeBus) e os liga ao `RealtimeTransport` injetado.\r\n *\r\n * @example\r\n * ```ts\r\n * // Em produção (transport real injetado pelo resolver do Core):\r\n * const ns = await createOfflineDocumentsNamespace({\r\n * dbName: 'neetru-db__my-product__db1__production',\r\n * transport: new RestSyncTransport(config),\r\n * });\r\n * const orders = ns.collection<Order>('orders');\r\n *\r\n * // Realtime:\r\n * const unsub = orders.onSnapshot({ where: [{ field: 'status', op: '==', value: 'open' }] }, snap => {\r\n * renderOrders(snap.docs);\r\n * });\r\n * ```\r\n */\r\nexport async function createOfflineDocumentsNamespace(\r\n opts: CreateOfflineDocumentsOptions,\r\n): Promise<NeetruDbDocuments> {\r\n const store = new LocalStore(opts.dbName);\r\n await store.open();\r\n\r\n const queue = new MutationQueue(store);\r\n const resolver = new ConflictResolver();\r\n const bus = new ChangeBus();\r\n\r\n const connectivity = new ConnectivityMonitor({\r\n // Se startOnline=false, injeta um navigator falso\r\n navigator: opts.startOnline === false\r\n ? { onLine: false }\r\n : (typeof navigator !== 'undefined' ? navigator : undefined),\r\n });\r\n\r\n // TabCoordinator — singleTab = sem eleição (sempre líder)\r\n const tabCoordinatorLike = opts.singleTab\r\n ? // Fake tab coordinator para single-tab mode (sempre líder)\r\n {\r\n isLeader: () => true,\r\n onRoleChange: (_cb: (role: 'leader' | 'follower') => void): Unsubscribe => {\r\n return () => {};\r\n },\r\n }\r\n : new TabCoordinator({\r\n lockName: `neetru-offline:${opts.dbName}`,\r\n channelName: `neetru-offline:${opts.dbName}`,\r\n });\r\n\r\n const engine = new SyncEngine({\r\n store,\r\n queue,\r\n resolver,\r\n bus,\r\n transport: opts.transport,\r\n tabCoordinator: tabCoordinatorLike,\r\n connectivity,\r\n periodicSyncIntervalMs: opts.periodicSyncIntervalMs ?? 5 * 60 * 1000,\r\n });\r\n\r\n return new NeetruDbDocumentsImpl({\r\n store,\r\n queue,\r\n bus,\r\n engine,\r\n connectivity,\r\n });\r\n}\r\n","/**\r\n * SqlLeaseManager — gestão de lease de credencial SQL (M2).\r\n *\r\n * Peça canônica 8 da 00-RELATORIO-CENTRAL.md §6.1:\r\n * - Busca o `DbSqlLease` no startup via `fetchLease()`.\r\n * - Agenda renovação proativa aos ~80% do TTL.\r\n * - Faz hot-swap da credencial: quando o lease renova (ou `credentialVersion`\r\n * muda), o pool antigo drena enquanto o novo aceita conexões.\r\n * - NUNCA loga a senha; NUNCA persiste o lease.\r\n *\r\n * Implementação do hot-swap: pg.Pool não tem API de primeira classe para trocar\r\n * credencial. A estratégia aqui é \"novo pool aceita, velho pool drena\":\r\n * 1. Cria pool novo com o lease renovado.\r\n * 2. Atualiza o ponteiro `_pool` e `_orm` (novos queries vão pro pool novo).\r\n * 3. Chama `end()` no pool antigo (drena gracioso — espera queries em curso).\r\n *\r\n * A janela de dois pools coexistindo é curta (~queries em voo), aceitável e\r\n * esperada (documentada em 02-sdk.md §5 risco 7).\r\n */\r\n\r\nimport { NeetruDbError } from '../../db-errors';\r\nimport type {\r\n DbSqlLease,\r\n SqlClientDeps,\r\n PgPoolLike,\r\n NeetruSqlClient,\r\n} from './types';\r\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\r\n\r\n// ─── Constantes ──────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Proporção do TTL após a qual o lease é renovado proativamente.\r\n *\r\n * 0.80 = renova aos 80% — para um lease de 15 min isso é ~12 min.\r\n * Garante margem antes da expiração real mesmo com latência de rede.\r\n */\r\nconst RENEWAL_THRESHOLD = 0.8;\r\n\r\n/** Tempo mínimo de espera antes de tentar renovar (evita tight-loop). */\r\nconst MIN_RENEWAL_DELAY_MS = 30_000; // 30 s\r\n\r\n// ─── SqlLeaseManager ─────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Implementação interna de `NeetruSqlClient`.\r\n *\r\n * O produto nunca constrói `SqlLeaseManager` diretamente — usa `createSqlClient`\r\n * (a factory pública que faz o primeiro lease + abre o pool).\r\n */\r\nexport class SqlLeaseManager<TSchema extends Record<string, unknown>>\r\n implements NeetruSqlClient<TSchema>\r\n{\r\n private _lease: DbSqlLease;\r\n private _pool: PgPoolLike;\r\n private _orm: NodePgDatabase<TSchema>;\r\n private _renewalTimer: ReturnType<typeof setTimeout> | null = null;\r\n private _closed = false;\r\n\r\n private readonly _deps: Required<Omit<SqlClientDeps<TSchema>, 'database'>> & { database?: string };\r\n\r\n constructor(\r\n lease: DbSqlLease,\r\n pool: PgPoolLike,\r\n orm: NodePgDatabase<TSchema>,\r\n deps: SqlClientDeps<TSchema>,\r\n ) {\r\n this._lease = lease;\r\n this._pool = pool;\r\n this._orm = orm;\r\n // Aplica default de `now` se não fornecido.\r\n this._deps = {\r\n ...deps,\r\n now: deps.now ?? (() => Date.now()),\r\n };\r\n this._scheduleRenewal();\r\n }\r\n\r\n // ─── Superfície pública (NeetruSqlClient) ──────────────────────────────────\r\n\r\n get orm(): NodePgDatabase<TSchema> {\r\n this._assertOpen();\r\n return this._orm;\r\n }\r\n\r\n async transaction<T>(\r\n fn: (tx: NodePgDatabase<TSchema>) => Promise<T>,\r\n opts?: {\r\n isolationLevel?: 'read committed' | 'repeatable read' | 'serializable';\r\n },\r\n ): Promise<T> {\r\n this._assertOpen();\r\n try {\r\n if (opts?.isolationLevel) {\r\n return await this._orm.transaction(fn, {\r\n isolationLevel: opts.isolationLevel,\r\n });\r\n }\r\n return await this._orm.transaction(fn);\r\n } catch (err) {\r\n throw mapPoolError(err);\r\n }\r\n }\r\n\r\n async close(): Promise<void> {\r\n if (this._closed) return;\r\n this._closed = true;\r\n this._cancelRenewal();\r\n await this._pool.end().catch(() => {\r\n // Melhor esforço — não relança no shutdown.\r\n });\r\n }\r\n\r\n // ─── Renovação proativa ────────────────────────────────────────────────────\r\n\r\n /**\r\n * Calcula o delay de renovação: momento de ~80% do TTL restante.\r\n *\r\n * Fórmula: `renewAt = issuedAt + TTL * RENEWAL_THRESHOLD`\r\n * = `expiresAt - TTL * (1 - RENEWAL_THRESHOLD)`\r\n *\r\n * Se o lease já está além do ponto de renovação (ou TTL não calculável),\r\n * usa `MIN_RENEWAL_DELAY_MS` como fallback seguro.\r\n */\r\n _calcRenewalDelayMs(): number {\r\n const expiresAtMs = Date.parse(this._lease.expiresAt);\r\n if (!Number.isFinite(expiresAtMs)) return MIN_RENEWAL_DELAY_MS;\r\n\r\n const now = this._deps.now();\r\n const remainingMs = expiresAtMs - now;\r\n if (remainingMs <= 0) return MIN_RENEWAL_DELAY_MS;\r\n\r\n // Renova quando restar (1 - RENEWAL_THRESHOLD) do TTL.\r\n // Ex: 15 min de TTL total → renova quando restar 3 min.\r\n const renewInMs = remainingMs * (1 - RENEWAL_THRESHOLD);\r\n return Math.max(MIN_RENEWAL_DELAY_MS, Math.round(renewInMs));\r\n }\r\n\r\n _scheduleRenewal(): void {\r\n if (this._closed) return;\r\n const delayMs = this._calcRenewalDelayMs();\r\n this._renewalTimer = setTimeout(() => {\r\n void this._doRenew();\r\n }, delayMs);\r\n }\r\n\r\n _cancelRenewal(): void {\r\n if (this._renewalTimer !== null) {\r\n clearTimeout(this._renewalTimer);\r\n this._renewalTimer = null;\r\n }\r\n }\r\n\r\n async _doRenew(): Promise<void> {\r\n if (this._closed) return;\r\n try {\r\n const renewOpts: import('./types').LeaseFetchOptions = {\r\n leaseId: this._lease.leaseId,\r\n };\r\n // Propaga o database original (contrato C-H) na renovação.\r\n if (this._deps.database !== undefined) {\r\n renewOpts.database = this._deps.database;\r\n }\r\n const newLease = await this._deps.fetchLease(renewOpts);\r\n await this._swapPool(newLease);\r\n } catch (err) {\r\n // Renovação falhou — reagenda com delay mínimo e tenta de novo.\r\n // O pool atual ainda funciona enquanto o lease não expirou.\r\n // Ignora silenciosamente (melhor esforço) e reagenda.\r\n this._renewalTimer = setTimeout(() => {\r\n void this._doRenew();\r\n }, MIN_RENEWAL_DELAY_MS);\r\n // Registra no console apenas em dev para diagnóstico; produção é silenciosa.\r\n if (process.env['NODE_ENV'] !== 'production') {\r\n // eslint-disable-next-line no-console\r\n console.warn('[SqlLeaseManager] Lease renewal failed, will retry:', err);\r\n }\r\n return;\r\n }\r\n this._scheduleRenewal();\r\n }\r\n\r\n /**\r\n * Hot-swap do pool: cria pool novo, atualiza ponteiros, drena pool antigo.\r\n *\r\n * Exposto como método protegido para testes.\r\n */\r\n async _swapPool(newLease: DbSqlLease): Promise<void> {\r\n const credRotated =\r\n newLease.credentialVersion !== this._lease.credentialVersion;\r\n\r\n // Se a versão não mudou e o lease é o mesmo, nada a fazer além de\r\n // atualizar `expiresAt`.\r\n if (!credRotated && newLease.leaseId === this._lease.leaseId) {\r\n this._lease = newLease;\r\n return;\r\n }\r\n\r\n // Cria novo pool + handle Drizzle antes de desconectar o antigo.\r\n const newPool = this._deps.createPool(newLease);\r\n const newOrm = this._deps.createDrizzle(newPool, this._deps.schema);\r\n\r\n const oldPool = this._pool;\r\n\r\n // Atualiza ponteiros — queries novas vão pro pool novo.\r\n this._lease = newLease;\r\n this._pool = newPool;\r\n this._orm = newOrm;\r\n\r\n // Drena o pool antigo graciosamente (não bloqueia o caller).\r\n void oldPool.end().catch(() => {\r\n /* best-effort */\r\n });\r\n }\r\n\r\n // ─── Helpers ───────────────────────────────────────────────────────────────\r\n\r\n private _assertOpen(): void {\r\n if (this._closed) {\r\n throw new NeetruDbError(\r\n 'db_unavailable',\r\n 'SqlLeaseManager foi fechado — chame close() apenas no shutdown.',\r\n );\r\n }\r\n }\r\n}\r\n\r\n// ─── Mapeamento de erros de pool ─────────────────────────────────────────────\r\n\r\n/**\r\n * Mapeia erros de `pg` / PgBouncer / timeout para `NeetruDbError` canônico.\r\n *\r\n * Erros desconhecidos são relançados como `db_unavailable` (retryable).\r\n */\r\nexport function mapPoolError(err: unknown): NeetruDbError {\r\n if (err instanceof NeetruDbError) return err;\r\n\r\n const message = err instanceof Error ? err.message : String(err);\r\n const code = err instanceof Error ? (err as NodeJS.ErrnoException).code : undefined;\r\n\r\n // ECONNREFUSED / ENOTFOUND / ETIMEDOUT — pool não conseguiu conectar.\r\n if (\r\n typeof code === 'string' &&\r\n (code === 'ECONNREFUSED' || code === 'ENOTFOUND' || code === 'ETIMEDOUT')\r\n ) {\r\n return new NeetruDbError(\r\n 'db_unavailable',\r\n `Pool connection failed (${code}): ${message}`,\r\n );\r\n }\r\n\r\n // Timeout de query Postgres (statement_timeout / lock_timeout).\r\n if (message.includes('statement timeout') || message.includes('lock timeout')) {\r\n return new NeetruDbError('db_timeout', `Query timeout: ${message}`);\r\n }\r\n\r\n // Serialization failure / deadlock (código Postgres 40001 / 40P01).\r\n if (message.includes('40001') || message.includes('40P01') || message.includes('deadlock')) {\r\n return new NeetruDbError('db_conflict', `Transaction conflict: ${message}`);\r\n }\r\n\r\n // Permission denied (Postgres 42501).\r\n if (message.includes('42501') || message.toLowerCase().includes('permission denied')) {\r\n return new NeetruDbError('db_permission_denied', `Permission denied: ${message}`);\r\n }\r\n\r\n // Fallback — genérico db_unavailable (retryable).\r\n return new NeetruDbError('db_unavailable', `Database error: ${message}`);\r\n}\r\n","/**\r\n * `createSqlClient` — factory pública do Mundo SQL.\r\n *\r\n * É a implementação de `client.db.sql(schema)` (02-sdk.md §3.3):\r\n * 1. Busca o lease inicial no Core (`POST /api/sdk/v1/db/lease`).\r\n * 2. Abre um `pg.Pool` com as credenciais do lease.\r\n * 3. Cria o handle Drizzle (`drizzle-orm/node-postgres`).\r\n * 4. Instancia o `SqlLeaseManager` que renova o lease proativamente.\r\n *\r\n * Em produção, usar `createSqlClientFromConfig` (que injeta `pg.Pool` real e\r\n * Drizzle real). Para testes, injetar deps fake via `createSqlClientWithDeps`.\r\n */\r\n\r\nimport type { ResolvedConfig } from '../../types';\r\nimport { NeetruDbError } from '../../db-errors';\r\nimport { SqlLeaseManager } from './lease';\r\nimport type {\r\n DbSqlLease,\r\n NeetruSqlClient,\r\n PgPoolLike,\r\n SqlClientDeps,\r\n LeaseFetcher,\r\n SqlOptions,\r\n} from './types';\r\n\r\n// ─── Endpoint do Core ─────────────────────────────────────────────────────────\r\n\r\n/** Endpoint de emissão de lease SQL no Core. */\r\nexport const LEASE_ENDPOINT = '/api/sdk/v1/db/lease';\r\n\r\n/** Endpoint de renovação de lease SQL no Core. */\r\nexport const LEASE_RENEW_ENDPOINT = '/api/sdk/v1/db/lease/renew';\r\n\r\n// ─── Lease fetcher HTTP ───────────────────────────────────────────────────────\r\n\r\n// ─── Mapeamento de env SDK → env Core ────────────────────────────────────────\r\n\r\n/**\r\n * Mapeia o env do SDK (`'dev'|'workspace'|'prod'`) para o enum aceito pelo\r\n * Core (`'dev'|'staging'|'production'`).\r\n *\r\n * O Core usa `z.enum(['dev', 'staging', 'production'])` no LeaseRequestSchema;\r\n * o SDK expõe `'dev'|'workspace'|'prod'` (NeetruEnv). Sem este mapeamento o\r\n * Core retornaria 400 validation_failed para `workspace` e `prod`.\r\n */\r\nfunction mapEnvToCore(sdkEnv: string): 'dev' | 'staging' | 'production' {\r\n if (sdkEnv === 'workspace') return 'staging';\r\n if (sdkEnv === 'prod') return 'production';\r\n return 'dev'; // 'dev' passa direto\r\n}\r\n\r\n/**\r\n * Cria um `LeaseFetcher` que chama o Core via `httpRequest`.\r\n *\r\n * BL-7 fix:\r\n * - Novo lease: envia `{ productId, environment }` (obrigatório pelo Core).\r\n * - Mapeia SDK env (`prod`→`production`, `workspace`→`staging`, `dev`→`dev`).\r\n * - Parseia a resposta desembrulhando `response.lease` (Core retorna\r\n * `{ kind, lease: {...} }`, não campos no topo).\r\n * - Renovação: envia `{ leaseId }` e desembrulha `response.lease`.\r\n *\r\n * Importação dinâmica de `./http` mantém o `pg` fora do bundle de quem não\r\n * usa SQL (tree-shaking é garantido pois `pg` só entra via `createPool`).\r\n */\r\nexport function createHttpLeaseFetcher(config: ResolvedConfig): LeaseFetcher {\r\n return async (opts) => {\r\n // Import dinâmico não disponível em CJS isolatedModules — importamos\r\n // estaticamente mas só quando a factory é chamada (lazy init).\r\n const { httpRequest } = await import('../../http');\r\n\r\n const isRenewal = Boolean(opts?.leaseId);\r\n const path = isRenewal ? LEASE_RENEW_ENDPOINT : LEASE_ENDPOINT;\r\n\r\n // BL-7: monta o body conforme o contrato de CADA rota do Core.\r\n //\r\n // Rota de novo lease (POST /lease): { productId, environment }\r\n // Rota de renovação (POST /lease/renew): { leaseId }\r\n //\r\n // Para novo lease inclui `database` quando fornecido (contrato C-H) como\r\n // campo extra — o Core o aceita via passthrough no `issueLease`.\r\n let body: Record<string, unknown>;\r\n if (isRenewal) {\r\n // Renovação: apenas leaseId\r\n body = { leaseId: opts!.leaseId };\r\n } else {\r\n // Novo lease: obrigatório productId + environment (mapeado)\r\n body = {\r\n productId: config.productId ?? '',\r\n environment: mapEnvToCore(config.env ?? 'prod'),\r\n };\r\n if (opts?.database !== undefined) {\r\n body['database'] = opts.database;\r\n }\r\n }\r\n\r\n let raw: unknown;\r\n try {\r\n raw = await httpRequest<unknown>(config, {\r\n method: 'POST',\r\n path,\r\n body,\r\n requireAuth: true,\r\n // Lease fetch é idempotente do ponto de vista de segurança — retries OK.\r\n retries: 2,\r\n });\r\n } catch (err) {\r\n // Mapeia NeetruError → NeetruDbError(db_unavailable).\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new NeetruDbError(\r\n 'db_unavailable',\r\n `Falha ao ${isRenewal ? 'renovar' : 'obter'} lease SQL: ${msg}`,\r\n );\r\n }\r\n\r\n return parseLease(raw);\r\n };\r\n}\r\n\r\n/**\r\n * Parseia e valida a resposta do Core como `DbSqlLease`.\r\n *\r\n * BL-7 fix: o Core retorna `{ kind, lease: { leaseId, host, ... } }` — não\r\n * campos no topo. `parseLease` agora desembrulha `response.lease` antes de\r\n * validar os campos obrigatórios.\r\n *\r\n * Lança `NeetruDbError(db_unavailable)` se o shape estiver errado.\r\n */\r\nfunction parseLease(raw: unknown): DbSqlLease {\r\n if (!raw || typeof raw !== 'object') {\r\n throw new NeetruDbError('db_unavailable', 'Resposta de lease inválida (não é objeto).');\r\n }\r\n\r\n // BL-7: desembrulha o envelope { kind, lease: {...} }\r\n const envelope = raw as Record<string, unknown>;\r\n const leaseObj = envelope['lease'];\r\n\r\n if (!leaseObj || typeof leaseObj !== 'object') {\r\n throw new NeetruDbError(\r\n 'db_unavailable',\r\n 'Resposta de lease inválida: campo \"lease\" ausente ou não é objeto. ' +\r\n 'O Core retorna { kind, lease: { leaseId, host, ... } }.',\r\n );\r\n }\r\n\r\n const r = leaseObj as Record<string, unknown>;\r\n\r\n function req<T>(field: string, type: string): T {\r\n if (typeof r[field] !== type) {\r\n throw new NeetruDbError(\r\n 'db_unavailable',\r\n `Campo obrigatório \"${field}\" ausente ou tipo inválido na resposta de lease.`,\r\n );\r\n }\r\n return r[field] as T;\r\n }\r\n\r\n return {\r\n leaseId: req<string>('leaseId', 'string'),\r\n host: req<string>('host', 'string'),\r\n port: (typeof r['port'] === 'number' ? r['port'] : 5433) as 5433,\r\n dbName: req<string>('dbName', 'string'),\r\n user: req<string>('user', 'string'),\r\n password: req<string>('password', 'string'),\r\n sslca: typeof r['sslca'] === 'string' ? r['sslca'] : null,\r\n clientCert: typeof r['clientCert'] === 'string' ? r['clientCert'] : null,\r\n clientKey: typeof r['clientKey'] === 'string' ? r['clientKey'] : null,\r\n credentialVersion:\r\n typeof r['credentialVersion'] === 'number' ? r['credentialVersion'] : 1,\r\n expiresAt: req<string>('expiresAt', 'string'),\r\n };\r\n}\r\n\r\n// ─── Pool real (produção) ─────────────────────────────────────────────────────\r\n\r\n/**\r\n * Cria um `pg.Pool` real a partir do lease.\r\n *\r\n * - Aponta sempre para a porta 5433 (PgBouncer).\r\n * - `max: 3` — conservador para serverless (Cloud Run).\r\n * - SSL opcional: usa `sslca` quando presente.\r\n */\r\nexport async function createPgPool(lease: DbSqlLease): Promise<PgPoolLike> {\r\n // Import dinâmico — `pg` só entra no bundle quando `createSqlClientFromConfig`\r\n // é chamado. Quem usa só auth/catalog não paga pelo módulo.\r\n const { Pool } = await import('pg');\r\n\r\n // C-07 (Codex BLOCKER 2026-05-22): Core retorna PEM strings via\r\n // `.toString('pem')` do @peculiar/x509 (formato `-----BEGIN ...-----`).\r\n // Buffer.from(pem, 'base64') silenciosamente SKIPA chars inválidos do\r\n // header/footer e corrompe os bytes. `pg` Pool aceita PEM string direto —\r\n // passa cru.\r\n const ssl: Record<string, unknown> | false =\r\n lease.sslca\r\n ? {\r\n ca: lease.sslca,\r\n cert: lease.clientCert ?? undefined,\r\n key: lease.clientKey ?? undefined,\r\n rejectUnauthorized: true,\r\n }\r\n : false;\r\n\r\n return new Pool({\r\n host: lease.host,\r\n port: lease.port,\r\n database: lease.dbName,\r\n user: lease.user,\r\n password: lease.password,\r\n ssl,\r\n max: 3,\r\n idleTimeoutMillis: 30_000,\r\n connectionTimeoutMillis: 10_000,\r\n });\r\n}\r\n\r\n/**\r\n * Cria o handle Drizzle real.\r\n *\r\n * Import dinâmico de `drizzle-orm/node-postgres` para tree-shaking.\r\n */\r\nexport async function createDrizzleHandle<TSchema extends Record<string, unknown>>(\r\n pool: PgPoolLike,\r\n schema: TSchema,\r\n) {\r\n const { drizzle } = await import('drizzle-orm/node-postgres');\r\n // `PgPoolLike` é mais estreito que `Pool` do pg — cast necessário.\r\n // Em produção o valor sempre é um `pg.Pool` real.\r\n return drizzle(pool as unknown as import('pg').Pool, { schema });\r\n}\r\n\r\n// ─── Factory principal ────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Cria `NeetruSqlClient` com dependências injetadas explicitamente.\r\n *\r\n * Usado pelos testes e pela factory de produção.\r\n *\r\n * @param deps — dependências injetáveis (fetchLease, createPool, createDrizzle, schema).\r\n * @param options — opções de `client.db.sql(schema, options?)` (contrato C-H).\r\n * `options.database` desambigua quando o produto tem N>1 bancos SQL.\r\n */\r\nexport async function createSqlClientWithDeps<\r\n TSchema extends Record<string, unknown>,\r\n>(\r\n deps: SqlClientDeps<TSchema>,\r\n options?: SqlOptions,\r\n): Promise<NeetruSqlClient<TSchema>> {\r\n // Mescla `database` das options com deps para que o SqlLeaseManager\r\n // propague o valor em todas as renovações de lease (contrato C-H).\r\n const depsWithDb: SqlClientDeps<TSchema> =\r\n options?.database !== undefined\r\n ? { ...deps, database: options.database }\r\n : deps;\r\n\r\n // 1. Busca o lease inicial, incluindo `database` quando fornecido.\r\n // Quando não há `database`, chama fetchLease() sem argumento — compatibilidade\r\n // exata com o comportamento v1.x (o teste verifica chamada sem parâmetros).\r\n let lease: DbSqlLease;\r\n try {\r\n if (options?.database !== undefined) {\r\n lease = await depsWithDb.fetchLease({ database: options.database });\r\n } else {\r\n lease = await depsWithDb.fetchLease();\r\n }\r\n } catch (err) {\r\n if (err instanceof NeetruDbError) throw err;\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new NeetruDbError('db_unavailable', `Falha ao obter lease inicial: ${msg}`);\r\n }\r\n\r\n // 2. Abre o pool.\r\n let pool: PgPoolLike;\r\n try {\r\n pool = depsWithDb.createPool(lease);\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new NeetruDbError('db_unavailable', `Falha ao abrir pool: ${msg}`);\r\n }\r\n\r\n // 3. Cria handle Drizzle.\r\n let orm;\r\n try {\r\n orm = depsWithDb.createDrizzle(pool, depsWithDb.schema);\r\n } catch (err) {\r\n // Pool aberto mas Drizzle falhou — fechar o pool antes de relançar.\r\n await pool.end().catch(() => {});\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new NeetruDbError('db_unavailable', `Falha ao criar handle Drizzle: ${msg}`);\r\n }\r\n\r\n // 4. Instancia o manager (que agenda o timer de renovação).\r\n // Passa `depsWithDb` para que `database` seja propagado nas renovações.\r\n return new SqlLeaseManager(lease, pool, orm, depsWithDb);\r\n}\r\n\r\n/**\r\n * Factory de produção — usa `pg.Pool` real e Drizzle real.\r\n *\r\n * `schema` deve ser o objeto Drizzle do produto (exportado de `db/schema.ts`).\r\n * `options.database` desambigua quando o produto tem N>1 bancos SQL (C-H).\r\n *\r\n * @example\r\n * ```ts\r\n * import { createNeetruClient } from '@neetru/sdk';\r\n * import * as schema from './db/schema';\r\n * const client = createNeetruClient();\r\n * // banco padrão:\r\n * export const db = await client.db.sql(schema);\r\n * // banco específico:\r\n * export const analytics = await client.db.sql(schema, { database: 'analytics' });\r\n * ```\r\n */\r\nexport async function createSqlClientFromConfig<\r\n TSchema extends Record<string, unknown>,\r\n>(\r\n config: ResolvedConfig,\r\n schema: TSchema,\r\n options?: SqlOptions,\r\n): Promise<NeetruSqlClient<TSchema>> {\r\n const fetchLease = createHttpLeaseFetcher(config);\r\n // Wrappers síncronos que delegam às factories async.\r\n // O pg.Pool é criado antes do Drizzle — se falhar, Drizzle não é tentado.\r\n const createPool = (lease: DbSqlLease): PgPoolLike => {\r\n // `createPgPool` é async mas o tipo `PoolFactory` é síncrono.\r\n // Para manter a interface simples, construímos o Pool diretamente aqui\r\n // usando os campos do lease (sem await). O Pool do pg é lazy — não conecta\r\n // até a primeira query. Isso é compatível com o nosso modelo.\r\n //\r\n // Nota: a versão com SSL total (sslca != null) abre o cert aqui de forma\r\n // síncrona — PEM strings passam direto pro pg sem decode adicional.\r\n // eslint-disable-next-line @typescript-eslint/no-require-imports\r\n const { Pool } = require('pg') as typeof import('pg');\r\n\r\n // C-07 (Codex BLOCKER 2026-05-22) — vide createPgPool acima: PEM direto.\r\n const ssl: Record<string, unknown> | false =\r\n lease.sslca\r\n ? {\r\n ca: lease.sslca,\r\n cert: lease.clientCert ?? undefined,\r\n key: lease.clientKey ?? undefined,\r\n rejectUnauthorized: true,\r\n }\r\n : false;\r\n\r\n return new Pool({\r\n host: lease.host,\r\n port: lease.port,\r\n database: lease.dbName,\r\n user: lease.user,\r\n password: lease.password,\r\n ssl,\r\n max: 3,\r\n idleTimeoutMillis: 30_000,\r\n connectionTimeoutMillis: 10_000,\r\n });\r\n };\r\n\r\n const createDrizzle = <S extends Record<string, unknown>>(\r\n pool: PgPoolLike,\r\n s: S,\r\n ) => {\r\n // eslint-disable-next-line @typescript-eslint/no-require-imports\r\n const { drizzle } = require('drizzle-orm/node-postgres') as typeof import('drizzle-orm/node-postgres');\r\n // `PgPoolLike` é mais estreito que `Pool` do pg — cast necessário.\r\n return drizzle(pool as unknown as import('pg').Pool, { schema: s });\r\n };\r\n\r\n return createSqlClientWithDeps(\r\n {\r\n fetchLease,\r\n createPool,\r\n createDrizzle: createDrizzle as SqlClientDeps<TSchema>['createDrizzle'],\r\n schema,\r\n },\r\n options,\r\n );\r\n}\r\n","/**\r\n * NeetruRealtimeClient — cliente WebSocket multiplexado do gateway (M3).\r\n *\r\n * Componente #18 do relatório central do Conselho Neetru Core DB.\r\n * Par cliente do serviço `neetru-realtime` (componente #19,\r\n * `@neetru/realtime-transport`).\r\n *\r\n * Responsabilidades:\r\n * - Manter EXATAMENTE UMA conexão WebSocket ao gateway.\r\n * - Multiplexar N subscriptions independentes sobre ela.\r\n * - Reconectar com backoff exponencial + jitter em caso de queda.\r\n * - Em reconexão, reenviar todos os frames `subscribe` ativos.\r\n * - Responder / enviar heartbeat ping/pong por protocolo.\r\n * - Rotear frames inbound para o callback correto por `subscriptionId`.\r\n * - Emitir mudanças de `ConnectionState` para observadores externos.\r\n *\r\n * Protocolo de frames (contrato compartilhado via `@neetru/realtime-protocol`):\r\n * ENVIA → `subscribe` | `unsubscribe` | `ping`\r\n * RECEBE ← `delta` | `resync` | `stale` | `error` | `pong` | `drain`\r\n *\r\n * Deps: ZERO externas. Apenas WebSocket nativo (injetável).\r\n *\r\n * Nota: a integração de `NeetruRealtimeClient` na superfície pública\r\n * `client.db` é um follow-up deliberado — ver seção de pendências no\r\n * relatório de entrega.\r\n */\r\n\r\nimport type {\r\n RealtimeClientOptions,\r\n WebSocketLike,\r\n WebSocketFactory,\r\n OutboundFrame,\r\n InboundFrame,\r\n ConnectionState,\r\n ConnectionStateListener,\r\n SubscriptionCallback,\r\n SubscriptionEntry,\r\n RealtimeQuery,\r\n TicketProvider,\r\n RealtimeTicket,\r\n} from './types';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Constantes\r\n// ---------------------------------------------------------------------------\r\n\r\n/** readyState WebSocket conforme especificação WHATWG. */\r\nconst WS_OPEN = 1;\r\n// const WS_CLOSING = 2; // não usado diretamente\r\nconst WS_CLOSED = 3;\r\n\r\n/** Fator multiplicador do jitter. O delay efetivo = base * jitter, onde\r\n * jitter ∈ [0.5, 1.5] (±50%). */\r\nconst JITTER_MIN = 0.5;\r\nconst JITTER_MAX = 1.5;\r\n\r\n/** Defaults */\r\nconst DEFAULT_BACKOFF_BASE_MS = 1_000;\r\nconst DEFAULT_BACKOFF_MAX_MS = 30_000;\r\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 25_000;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Geração de IDs\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Gera um ID de subscription único por instância.\r\n * Usa `crypto.randomUUID()` quando disponível (browser/Node 20+);\r\n * fallback para contador + Math.random() em ambientes sem crypto.\r\n */\r\nlet _idCounter = 0;\r\nfunction generateId(): string {\r\n if (typeof globalThis.crypto?.randomUUID === 'function') {\r\n return globalThis.crypto.randomUUID();\r\n }\r\n return `nrt-sub-${Date.now()}-${++_idCounter}-${Math.random().toString(36).slice(2)}`;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// NeetruRealtimeClient\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Cliente WebSocket multiplexado do gateway `neetru-realtime`.\r\n *\r\n * @example\r\n * ```ts\r\n * const rt = new NeetruRealtimeClient({\r\n * gatewayUrl: 'wss://realtime.neetru.com/ws',\r\n * });\r\n *\r\n * const subId = rt.subscribe('orders', { filter: { status: 'open' } }, (frame) => {\r\n * if (frame.op === 'delta') applyChanges(frame.changes);\r\n * if (frame.op === 'resync') fullReload();\r\n * });\r\n *\r\n * rt.onConnectionState((state) => console.log('connection:', state));\r\n *\r\n * // Para parar:\r\n * rt.unsubscribe(subId);\r\n * rt.close();\r\n * ```\r\n */\r\nexport class NeetruRealtimeClient {\r\n // ── configuração ──────────────────────────────────────────────────────────\r\n private readonly _gatewayUrl: string;\r\n private readonly _wsFactory: WebSocketFactory;\r\n private readonly _setTimeout: typeof setTimeout;\r\n private readonly _clearTimeout: typeof clearTimeout;\r\n private readonly _backoffBaseMs: number;\r\n private readonly _backoffMaxMs: number;\r\n private readonly _heartbeatIntervalMs: number;\r\n private readonly _ticketProvider: TicketProvider;\r\n /** ID do banco lógico (BL-8) — embutido em query.filter._dbId de cada subscribe. */\r\n private readonly _dbId: string | undefined;\r\n\r\n /** Ticket atual — obtido antes de cada abertura de WS e embutido nos frames. */\r\n private _currentTicket: RealtimeTicket | null = null;\r\n\r\n // ── estado interno ────────────────────────────────────────────────────────\r\n\r\n /** Subscriptions ativas: id → entry */\r\n private _subscriptions = new Map<string, SubscriptionEntry>();\r\n\r\n /** Listeners do estado da conexão. */\r\n private _stateListeners: Array<ConnectionStateListener> = [];\r\n\r\n /** Estado atual da conexão. */\r\n private _connectionState: ConnectionState = 'connecting';\r\n\r\n /** Socket atual (pode ser null entre tentativas). */\r\n private _ws: WebSocketLike | null = null;\r\n\r\n /** Número da tentativa de reconexão corrente (reseta após conexão bem-sucedida). */\r\n private _reconnectAttempt = 0;\r\n\r\n /** Handle do timer de backoff pendente. */\r\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n /** Handle do timer de heartbeat. */\r\n private _heartbeatTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n /** Indica que o cliente foi encerrado via `close()`. Não reconecta mais. */\r\n private _closed = false;\r\n\r\n /**\r\n * Frames de subscribe que precisam ser enviados mas a socket ainda não\r\n * está aberta (estado CONNECTING). Drenados no onopen.\r\n */\r\n private _pendingFrames: OutboundFrame[] = [];\r\n\r\n // ── construtor ────────────────────────────────────────────────────────────\r\n\r\n constructor(options: RealtimeClientOptions) {\r\n this._gatewayUrl = options.gatewayUrl;\r\n\r\n this._wsFactory = options.webSocketFactory ?? defaultWebSocketFactory;\r\n\r\n this._setTimeout = options.setTimeoutFn ?? globalThis.setTimeout.bind(globalThis);\r\n this._clearTimeout = options.clearTimeoutFn ?? globalThis.clearTimeout.bind(globalThis);\r\n\r\n this._backoffBaseMs = options.backoffBaseMs ?? DEFAULT_BACKOFF_BASE_MS;\r\n this._backoffMaxMs = options.backoffMaxMs ?? DEFAULT_BACKOFF_MAX_MS;\r\n this._heartbeatIntervalMs =\r\n options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;\r\n\r\n this._ticketProvider = options.ticketProvider;\r\n this._dbId = options.dbId;\r\n\r\n // Inicia a conexão imediatamente (busca ticket antes de abrir o WS).\r\n this._connect();\r\n }\r\n\r\n // ── API pública ───────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Registra uma subscription em `collection` com `query` opcional.\r\n *\r\n * Envia um frame `subscribe` ao gateway (ou enfileira se o socket ainda\r\n * não está aberto). O `callback` é invocado com cada frame `delta`,\r\n * `resync`, `stale` ou `error` roteado para esta subscription.\r\n *\r\n * @returns O `subscriptionId` opaco — usar para cancelar via `unsubscribe()`.\r\n */\r\n subscribe(\r\n collection: string,\r\n query: RealtimeQuery,\r\n callback: SubscriptionCallback,\r\n ): string {\r\n if (this._closed) {\r\n // Cliente encerrado — retorna um id fictício sem efeito.\r\n return generateId();\r\n }\r\n\r\n const subscriptionId = generateId();\r\n this._subscriptions.set(subscriptionId, {\r\n subscriptionId,\r\n collection,\r\n query: Object.keys(query).length > 0 ? query : undefined,\r\n callback,\r\n });\r\n\r\n const frame: OutboundFrame = {\r\n op: 'subscribe',\r\n subscriptionId,\r\n collection,\r\n query: this._buildSubscribeQuery(query),\r\n };\r\n\r\n this._sendOrBuffer(frame);\r\n return subscriptionId;\r\n }\r\n\r\n /**\r\n * Cancela uma subscription.\r\n *\r\n * Envia um frame `unsubscribe` ao gateway e remove o listener local.\r\n * Frames subsequentes com este `subscriptionId` são silenciosamente descartados.\r\n */\r\n unsubscribe(subscriptionId: string): void {\r\n if (!this._subscriptions.has(subscriptionId)) {\r\n // id desconhecido — sem efeito (não lança erro).\r\n return;\r\n }\r\n\r\n this._subscriptions.delete(subscriptionId);\r\n\r\n const frame: OutboundFrame = { op: 'unsubscribe', subscriptionId };\r\n this._sendOrBuffer(frame);\r\n }\r\n\r\n /**\r\n * Registra um listener de mudanças no estado da conexão.\r\n *\r\n * O listener é invocado imediatamente com o estado atual e depois a cada\r\n * transição. Retorna uma função `unsubscribe`.\r\n */\r\n onConnectionState(listener: ConnectionStateListener): () => void {\r\n this._stateListeners.push(listener);\r\n // entrega o estado atual imediatamente\r\n listener(this._connectionState);\r\n return () => {\r\n this._stateListeners = this._stateListeners.filter(l => l !== listener);\r\n };\r\n }\r\n\r\n /**\r\n * Encerra o cliente definitivamente.\r\n *\r\n * Fecha o socket ativo, cancela timers pendentes e marca o cliente como\r\n * encerrado (sem mais reconexões).\r\n */\r\n close(): void {\r\n this._closed = true;\r\n this._cancelReconnectTimer();\r\n this._cancelHeartbeatTimer();\r\n if (this._ws) {\r\n // desvincula handlers para não disparar onclose→reconnect\r\n this._detachHandlers(this._ws);\r\n if (this._ws.readyState !== WS_CLOSED) {\r\n this._ws.close(1000, 'client closed');\r\n }\r\n this._ws = null;\r\n }\r\n this._setState('disconnected');\r\n }\r\n\r\n // ── Conexão ───────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Busca um ticket de autenticação e, em seguida, cria um novo WebSocket e\r\n * instala os handlers de evento.\r\n *\r\n * A busca de ticket é obrigatória antes de abrir qualquer WS (primeira\r\n * conexão e reconexões). Se a busca falhar, a conexão é abortada com\r\n * estado `'connecting'` e o backoff reconectará em seguida.\r\n *\r\n * Fail-closed: o WebSocket NUNCA é aberto sem um ticket válido.\r\n */\r\n private _connect(): void {\r\n if (this._closed) return;\r\n this._setState('connecting');\r\n\r\n // Fire-and-forget: a promise é gerenciada internamente.\r\n void this._connectWithTicket();\r\n }\r\n\r\n /** Implementação assíncrona de _connect — busca ticket e abre WS. */\r\n private async _connectWithTicket(): Promise<void> {\r\n if (this._closed) return;\r\n\r\n // ── 1. Busca o ticket ────────────────────────────────────────────────────\r\n let ticket: RealtimeTicket;\r\n try {\r\n ticket = await this._ticketProvider();\r\n } catch (err) {\r\n // Ticket fetch falhou — permanece em 'connecting' e agenda reconexão.\r\n // O WS não é aberto (fail-closed).\r\n if (this._closed) return;\r\n const delay = this._computeBackoffDelay(this._reconnectAttempt);\r\n this._reconnectAttempt++;\r\n this._reconnectTimer = this._setTimeout(() => {\r\n this._reconnectTimer = null;\r\n if (!this._closed) this._connect();\r\n }, delay);\r\n // Permanece em 'connecting' — não altera estado (já está lá).\r\n void err; // silencia \"unused variable\" lint\r\n return;\r\n }\r\n\r\n if (this._closed) return;\r\n\r\n // ── 2. Armazena o ticket para embedding nos frames subscribe ─────────────\r\n this._currentTicket = ticket;\r\n\r\n // ── 3. Abre o WebSocket ──────────────────────────────────────────────────\r\n const ws = this._wsFactory(this._gatewayUrl);\r\n this._ws = ws;\r\n\r\n ws.onopen = this._handleOpen.bind(this);\r\n ws.onmessage = this._handleMessage.bind(this);\r\n ws.onclose = this._handleClose.bind(this);\r\n ws.onerror = this._handleError.bind(this);\r\n }\r\n\r\n // ── Handlers de WebSocket ─────────────────────────────────────────────────\r\n\r\n private _handleOpen(_event: Event): void {\r\n if (this._closed) return;\r\n\r\n this._reconnectAttempt = 0; // reconexão bem-sucedida — reseta counter\r\n this._setState('connected');\r\n\r\n // Drena frames que foram enfileirados enquanto o socket estava CONNECTING.\r\n for (const frame of this._pendingFrames) {\r\n this._sendNow(frame);\r\n }\r\n this._pendingFrames = [];\r\n\r\n // Resubscreve todas as subscriptions ativas (relevante em reconexões\r\n // onde _pendingFrames estava vazio mas as subs já existiam).\r\n // No open inicial, _subscriptions está vazio ou populado (se subscribe\r\n // foi chamado antes do open). Os frames foram para _pendingFrames.\r\n // Em reconexão: _pendingFrames foi drenado acima — mas as subscriptions\r\n // ativas precisam ser re-registradas no NOVO socket.\r\n // Porém, os frames que foram para _pendingFrames já incluem os subscribes\r\n // iniciais. Precisamos distinguir: reconexão vs. primeira conexão.\r\n // Para simplificar e ser correto nos dois casos, resubscreve SEMPRE\r\n // subscriptions que não estavam no _pendingFrames que acabamos de drenar.\r\n this._resubscribeAll();\r\n\r\n // Inicia heartbeat se habilitado.\r\n this._scheduleHeartbeat();\r\n }\r\n\r\n private _handleMessage(event: MessageEvent): void {\r\n if (this._closed) return;\r\n\r\n let frame: InboundFrame;\r\n try {\r\n frame = JSON.parse(event.data as string) as InboundFrame;\r\n } catch {\r\n // frame malformado — ignora\r\n return;\r\n }\r\n\r\n switch (frame.op) {\r\n case 'delta':\r\n case 'resync':\r\n case 'stale':\r\n case 'error':\r\n this._routeToSubscription(frame);\r\n break;\r\n\r\n case 'pong':\r\n // heartbeat respondido — nada a fazer (timer já foi limpo)\r\n break;\r\n\r\n case 'drain':\r\n this._handleDrain();\r\n break;\r\n\r\n default:\r\n // op desconhecido — ignora silenciosamente\r\n break;\r\n }\r\n }\r\n\r\n private _handleClose(_event: CloseEvent): void {\r\n if (this._closed) return;\r\n\r\n this._cancelHeartbeatTimer();\r\n this._ws = null;\r\n this._scheduleReconnect();\r\n }\r\n\r\n private _handleError(_event: Event): void {\r\n // O error é sempre seguido de onclose — não precisamos fazer nada aqui;\r\n // o onclose cuidará da reconexão.\r\n // Marcamos connecting para sinalizar que algo deu errado enquanto aguardamos.\r\n if (this._closed) return;\r\n this._setState('connecting');\r\n }\r\n\r\n // ── Drain (graceful shutdown do gateway) ─────────────────────────────────\r\n\r\n private _handleDrain(): void {\r\n if (this._closed) return;\r\n\r\n this._setState('draining');\r\n this._cancelHeartbeatTimer();\r\n\r\n // Fecha o socket atual sem esperar o close natural do gateway.\r\n if (this._ws) {\r\n this._detachHandlers(this._ws);\r\n if (this._ws.readyState !== WS_CLOSED) {\r\n this._ws.close(1001, 'drain');\r\n }\r\n this._ws = null;\r\n }\r\n\r\n // Reconecta com backoff — o gateway vai subir em seguida.\r\n this._scheduleReconnect();\r\n }\r\n\r\n // ── Roteamento de frames ──────────────────────────────────────────────────\r\n\r\n private _routeToSubscription(frame: InboundFrame): void {\r\n const entry = this._subscriptions.get(frame.subscriptionId);\r\n if (!entry) {\r\n // subscriptionId desconhecido — ignora silenciosamente\r\n return;\r\n }\r\n try {\r\n entry.callback(frame);\r\n } catch {\r\n // erro no callback do produto não deve derrubar o cliente\r\n }\r\n }\r\n\r\n // ── Resubscrição ──────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Reenvía frames `subscribe` para todas as subscriptions ativas.\r\n * Chamado no `onopen` de reconexões para restaurar o estado remoto.\r\n *\r\n * Durante a PRIMEIRA conexão: _pendingFrames já foi drenado com os\r\n * subscribes iniciais acima. ResubscribeAll envia novamente — como a\r\n * lista de subscriptions foi populada pelos `subscribe()` calls anteriores\r\n * ao open, e os frames drenados também os incluem, teríamos duplicatas.\r\n *\r\n * Solução: resubscribeAll só é invocado após drenar _pendingFrames, e\r\n * como o gateway é idempotente para o mesmo subscriptionId (segundo o\r\n * design do componente #19), a duplicata é inócua. Em reconexões, onde\r\n * _pendingFrames está vazio, os frames são os únicos enviados.\r\n *\r\n * Para o caso do primeiro open com subscribes anteriores ao open, os\r\n * frames já foram drenados de _pendingFrames — não chamamos resubscribeAll\r\n * se era a primeira conexão (_reconnectAttempt era 0 antes de resetar).\r\n * Rastreamos isso com _hasConnectedOnce.\r\n */\r\n private _hasConnectedOnce = false;\r\n\r\n private _resubscribeAll(): void {\r\n if (!this._hasConnectedOnce) {\r\n // Primeiro open: os subscribes foram drenados de _pendingFrames.\r\n // Não resubscreve para evitar duplicata.\r\n this._hasConnectedOnce = true;\r\n return;\r\n }\r\n\r\n // Reconexão: envia subscribe frames para todas as subs ativas.\r\n // O ticket corrente (obtido antes de abrir este WS) é embutido em\r\n // cada frame — assim o gateway pode validar a autenticidade.\r\n for (const entry of this._subscriptions.values()) {\r\n const frame: OutboundFrame = {\r\n op: 'subscribe',\r\n subscriptionId: entry.subscriptionId,\r\n collection: entry.collection,\r\n query: this._buildSubscribeQuery(entry.query ?? {}),\r\n };\r\n this._sendNow(frame);\r\n }\r\n }\r\n\r\n // ── Ticket embedding ──────────────────────────────────────────────────────\r\n\r\n /**\r\n * Constrói o descriptor `query` para um frame `subscribe`, embutindo o\r\n * `token` do ticket corrente em `query.filter._ticket` e o `_dbId` do\r\n * banco lógico em `query.filter._dbId` (BL-8 fix).\r\n *\r\n * O gateway extrai `filter._ticket` do primeiro frame `subscribe` e valida\r\n * contra `POST /api/sdk/v1/db/realtime/validate`. `filter._dbId` é exigido\r\n * pelo `@neetru/realtime-changestream._extractDbId` para rotear a\r\n * subscription ao banco correto — sem ele a subscription é rejeitada.\r\n *\r\n * Retorna `undefined` se a query seria vazia E não há ticket (estado\r\n * transitório antes do primeiro ticket — não deve ocorrer normalmente pois\r\n * `_connect` só abre o WS após obter o ticket).\r\n */\r\n private _buildSubscribeQuery(\r\n query: RealtimeQuery,\r\n ): RealtimeQuery | undefined {\r\n const ticket = this._currentTicket;\r\n const hasUserQuery = Object.keys(query).length > 0;\r\n\r\n if (!ticket) {\r\n // Sem ticket — retorna a query original sem embedding (defensivo;\r\n // na prática nunca chega aqui pois _connect não abre WS sem ticket).\r\n return hasUserQuery ? query : undefined;\r\n }\r\n\r\n // BL-8: mescla _ticket + _dbId no filter, preservando filtros do caller.\r\n const mergedFilter: Record<string, unknown> = {\r\n ...(query.filter ?? {}),\r\n _ticket: ticket.token,\r\n };\r\n\r\n // Embute _dbId apenas quando configurado (compatibilidade reversa).\r\n if (this._dbId !== undefined) {\r\n mergedFilter['_dbId'] = this._dbId;\r\n }\r\n\r\n return {\r\n ...query,\r\n filter: mergedFilter,\r\n };\r\n }\r\n\r\n // ── Backoff e reconexão ───────────────────────────────────────────────────\r\n\r\n /** Agenda uma tentativa de reconexão com backoff exponencial + jitter. */\r\n private _scheduleReconnect(): void {\r\n if (this._closed) return;\r\n\r\n this._cancelReconnectTimer();\r\n this._setState('connecting');\r\n\r\n // Invalida o ticket corrente — a reconexão deve buscar um novo.\r\n this._currentTicket = null;\r\n\r\n const delayMs = this._computeBackoffDelay(this._reconnectAttempt);\r\n this._reconnectAttempt++;\r\n\r\n this._reconnectTimer = this._setTimeout(() => {\r\n this._reconnectTimer = null;\r\n if (!this._closed) {\r\n this._connect();\r\n }\r\n }, delayMs);\r\n }\r\n\r\n /**\r\n * Calcula o delay de backoff para o attempt N.\r\n *\r\n * Fórmula: `min(baseMs * 2^N, maxMs) * jitter`\r\n * onde `jitter ∈ [JITTER_MIN, JITTER_MAX]` (±50%).\r\n */\r\n private _computeBackoffDelay(attempt: number): number {\r\n const exponential = this._backoffBaseMs * Math.pow(2, attempt);\r\n const capped = Math.min(exponential, this._backoffMaxMs);\r\n const jitter = JITTER_MIN + Math.random() * (JITTER_MAX - JITTER_MIN);\r\n return Math.round(capped * jitter);\r\n }\r\n\r\n private _cancelReconnectTimer(): void {\r\n if (this._reconnectTimer !== null) {\r\n this._clearTimeout(this._reconnectTimer);\r\n this._reconnectTimer = null;\r\n }\r\n }\r\n\r\n // ── Heartbeat ─────────────────────────────────────────────────────────────\r\n\r\n /** Agenda o próximo ping. Não-operacional se heartbeatIntervalMs === 0. */\r\n private _scheduleHeartbeat(): void {\r\n if (this._heartbeatIntervalMs === 0) return;\r\n this._cancelHeartbeatTimer();\r\n\r\n this._heartbeatTimer = this._setTimeout(() => {\r\n this._heartbeatTimer = null;\r\n this._sendPing();\r\n // agenda o próximo ciclo\r\n this._scheduleHeartbeat();\r\n }, this._heartbeatIntervalMs);\r\n }\r\n\r\n private _cancelHeartbeatTimer(): void {\r\n if (this._heartbeatTimer !== null) {\r\n this._clearTimeout(this._heartbeatTimer);\r\n this._heartbeatTimer = null;\r\n }\r\n }\r\n\r\n private _sendPing(): void {\r\n // O ping usa um subscriptionId especial vazio ('') para o heartbeat\r\n // de aplicação (distinto do ping/pong do protocolo WebSocket).\r\n const frame: OutboundFrame = { op: 'ping', subscriptionId: '' };\r\n this._sendOrBuffer(frame);\r\n }\r\n\r\n // ── Envio de frames ───────────────────────────────────────────────────────\r\n\r\n /**\r\n * Envia o frame imediatamente se o socket está aberto; caso contrário,\r\n * enfileira em `_pendingFrames` para envio no próximo `onopen`.\r\n */\r\n private _sendOrBuffer(frame: OutboundFrame): void {\r\n if (\r\n this._ws !== null &&\r\n this._ws.readyState === WS_OPEN\r\n ) {\r\n this._sendNow(frame);\r\n } else {\r\n // Socket ainda está CONNECTING ou foi perdido — enfileira.\r\n // Frames de unsubscribe não precisam ser bufferizados pois não há\r\n // estado remoto a limpar (o remote não tem a sub se o socket não abriu).\r\n if (frame.op !== 'unsubscribe') {\r\n this._pendingFrames.push(frame);\r\n }\r\n }\r\n }\r\n\r\n /** Serializa e envia o frame imediatamente via WebSocket. */\r\n private _sendNow(frame: OutboundFrame): void {\r\n if (!this._ws || this._ws.readyState !== WS_OPEN) return;\r\n try {\r\n this._ws.send(JSON.stringify(frame));\r\n } catch {\r\n // Falha de send (ex: buffer cheio) — ignora; o onclose cuidará da reconexão.\r\n }\r\n }\r\n\r\n // ── Estado da conexão ─────────────────────────────────────────────────────\r\n\r\n private _setState(state: ConnectionState): void {\r\n if (this._connectionState === state) return;\r\n this._connectionState = state;\r\n for (const listener of this._stateListeners) {\r\n try {\r\n listener(state);\r\n } catch {\r\n // erro no listener do produto não deve derrubar o cliente\r\n }\r\n }\r\n }\r\n\r\n // ── Desvinculação de handlers ─────────────────────────────────────────────\r\n\r\n /** Remove todos os handlers de um WebSocket (evita disparo após close()). */\r\n private _detachHandlers(ws: WebSocketLike): void {\r\n ws.onopen = null;\r\n ws.onmessage = null;\r\n ws.onclose = null;\r\n ws.onerror = null;\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Factory de WebSocket padrão\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Factory padrão: cria um `WebSocket` nativo do browser/runtime.\r\n * Substituída por FakeWebSocket em testes.\r\n */\r\nconst defaultWebSocketFactory: WebSocketFactory = (url: string): WebSocketLike => {\r\n // `WebSocket` é global no browser e no Node 22+ (sem import).\r\n // Em ambientes sem WebSocket global, o produto deve injetar a factory.\r\n if (typeof WebSocket === 'undefined') {\r\n throw new Error(\r\n '[NeetruRealtimeClient] WebSocket não disponível neste ambiente. ' +\r\n 'Injete uma implementação via `webSocketFactory` nas opções.',\r\n );\r\n }\r\n return new WebSocket(url);\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Re-exports de tipos para conveniência do consumidor\r\n// ---------------------------------------------------------------------------\r\n\r\nexport type {\r\n RealtimeClientOptions,\r\n RealtimeQuery,\r\n RealtimeTicket,\r\n TicketProvider,\r\n ConnectionState,\r\n ConnectionStateListener,\r\n SubscriptionCallback,\r\n InboundFrame,\r\n OutboundFrame,\r\n} from './types';\r\n","/**\r\n * client-db.ts — Factory do namespace `client.db` (M2 capstone).\r\n *\r\n * Liga os building blocks construídos em M2 em uma superfície unificada\r\n * conforme 02-sdk.md §3.1:\r\n *\r\n * client.db.collection(name) → DbCollectionRef (offline-first, engine-aware)\r\n * client.db.sql(schema) → Promise<NeetruSqlClient>\r\n * client.db.syncState → NeetruSyncState\r\n * client.db.onSyncStateChanged(cb) / flush() / clearCache() / getConflicts()\r\n *\r\n * ## Engine detection\r\n *\r\n * O SDK lê o engine do banco lógico via:\r\n * 1. Opção explícita `NeetruDbOptions.engine` (injetada pelo product scaffold\r\n * gerado por `neetru db init`, ou pelo `NeetruDbConfig` passado pra\r\n * `createNeetruClient`).\r\n * 2. Fallback: `'rest'` — transporte REST simples (sem realtime nativo;\r\n * compatível com todos os engines no MVP, idêntico ao comportamento v1.x).\r\n *\r\n * Engines reconhecidos:\r\n * - `'firestore'` → SyncEngine com FirestoreRealtimeSyncTransport\r\n * - `'nosql-vm'` → SyncEngine com NeetruRealtimeClient como fonte realtime\r\n * - `'rest'` → SyncEngine com FakeRestSyncTransport (REST puro, no-op realtime)\r\n * (default — funciona para cloud-sql-*, vm-postgres-*, etc.)\r\n *\r\n * ## Wiring SQL\r\n *\r\n * `client.db.sql(schema)` delega pra `createSqlClientFromConfig` (src/db/sql/).\r\n * Em dev (`NEETRU_ENV=dev`), retorna um `MockSqlClient` que não abre socket.\r\n *\r\n * ## Backward compatibility com v1.x DbNamespace\r\n *\r\n * O antigo `DbNamespace` (src/db.ts) expunha apenas `collection(name)` retornando\r\n * uma versão REST simples sem offline, sem realtime, sem cursor, sem batch.\r\n * A `NeetruDb` v2.0 É uma breaking change deliberada (major bump):\r\n * - `list()` agora retorna `DbListResult<T>` (com `fromCache`, `stale`, etc.)\r\n * em vez de `T[]`.\r\n * - `db_unavailable` semântica mudou: não significa mais \"sem rede\"\r\n * (offline é transparente), só lifecycle do banco.\r\n * - `batch()`, `onDoc()`, `onSnapshot()`, `doc()`, `sql()` são novos.\r\n *\r\n * Veja CHANGELOG.md §2.0.0 para a lista completa de breaking changes.\r\n *\r\n * @module\r\n */\r\n\r\nimport type { ResolvedConfig } from '../types';\r\nimport { NeetruDbError } from '../db-errors';\r\nimport {\r\n createOfflineDocumentsNamespace,\r\n type NeetruDbDocuments,\r\n type RealtimeTransport,\r\n} from './collection-ref';\r\nimport { createSqlClientFromConfig } from './sql/sql-client';\r\nimport type { NeetruSqlClient, SqlOptions } from './sql/types';\r\nimport type { SyncState, ConflictRecord, Unsubscribe, Mutation } from './offline/types';\r\nimport type { PushMutationsResult, PullChangesResult, FullResyncResult } from './offline/sync-engine';\r\nimport { NeetruRealtimeClient } from './realtime/realtime-client';\r\nimport type { TicketProvider } from './realtime/types';\r\n\r\n// ─── Re-exports públicos do módulo db ────────────────────────────────────────\r\n\r\nexport type {\r\n DbCollectionRef,\r\n DbDocRef,\r\n DbQuery,\r\n DbWhereFilter,\r\n DbDoc,\r\n DbListResult,\r\n DbGetResult,\r\n DbBatchOp,\r\n DbChangeType,\r\n NeetruDbDocuments,\r\n RealtimeTransport,\r\n CreateOfflineDocumentsOptions,\r\n} from './collection-ref';\r\n\r\nexport type { NeetruSqlClient, DbSqlLease, SqlOptions } from './sql/types';\r\nexport { NeetruDbError } from '../db-errors';\r\nexport type { NeetruDbErrorCode } from '../db-errors';\r\nexport type { SyncState, ConflictRecord } from './offline/types';\r\n\r\n// ─── Tipos públicos de configuração de DB ────────────────────────────────────\r\n\r\n/**\r\n * Engine do banco lógico — determina o transporte de realtime.\r\n *\r\n * - `'firestore'` — Firestore Web SDK como transporte (memoryLocalCache).\r\n * - `'nosql-vm'` — WebSocket via gateway `neetru-realtime`.\r\n * - `'rest'` — REST puro (default MVP; sem realtime nativo).\r\n *\r\n * O produto NUNCA vê a diferença de transporte — o comportamento offline\r\n * é idêntico nos dois engines de Documentos (02-sdk.md §3.7).\r\n */\r\nexport type NeetruDbEngine = 'firestore' | 'nosql-vm' | 'rest';\r\n\r\n/**\r\n * Opções de configuração do banco lógico.\r\n *\r\n * Normalmente geradas pelo scaffold `neetru db init` em `db/client.ts`.\r\n * Em testes, injetar diretamente.\r\n */\r\nexport interface NeetruDbOptions {\r\n /**\r\n * ID opaco do banco lógico — emitido pelo Core em `POST /api/sdk/v1/db`.\r\n * Necessário para o lease SQL e para scoping das coleções.\r\n */\r\n dbId?: string;\r\n\r\n /**\r\n * Engine do banco lógico — determina o transporte de realtime.\r\n * Default: `'rest'` (MVP — funciona para todos os engines SQL e Documentos).\r\n */\r\n engine?: NeetruDbEngine;\r\n\r\n /**\r\n * Opções do transporte Firestore (somente quando `engine === 'firestore'`).\r\n * O `firestore` handle (inicializado com `memoryLocalCache`) é injetado aqui.\r\n *\r\n * Injeção explícita — o SDK não importa `firebase/firestore` diretamente\r\n * para não poluir o bundle de quem não usa este engine.\r\n */\r\n firestoreTransport?: RealtimeTransport;\r\n\r\n /**\r\n * Opções do transporte WebSocket (somente quando `engine === 'nosql-vm'`).\r\n * URL do gateway `neetru-realtime`.\r\n */\r\n realtimeGatewayUrl?: string;\r\n\r\n /**\r\n * Coleções declaradas pelo produto — necessário para pullChanges/fullResync\r\n * com os transportes Firestore e nosql-vm.\r\n *\r\n * Default: `[]` (o SyncEngine sincroniza coleções conforme são acessadas).\r\n */\r\n collections?: string[];\r\n\r\n /**\r\n * Nome do banco IndexedDB. Convenção: `neetru-db__{productSlug}__{dbId}__{env}`.\r\n * Gerado automaticamente se ausente.\r\n */\r\n dbName?: string;\r\n\r\n /**\r\n * `true` = sem contenção multi-aba (sempre líder).\r\n * Padrão em SSR/testes; em produção usa Web Locks.\r\n */\r\n singleTab?: boolean;\r\n\r\n /**\r\n * Transporte de sync customizado (injetado em testes).\r\n * Se presente, sobrepõe a detecção por `engine`.\r\n */\r\n _transport?: RealtimeTransport;\r\n\r\n /**\r\n * Factory de WebSocket injetável (somente quando `engine === 'nosql-vm'`).\r\n * Default: `(url) => new WebSocket(url)`.\r\n * Injetar em testes para evitar rede real.\r\n */\r\n _wsFactory?: import('./realtime/types').WebSocketFactory;\r\n}\r\n\r\n// ─── NeetruDb — interface pública completa (02-sdk.md §3.1) ─────────────────\r\n\r\n/**\r\n * Superfície pública do namespace `client.db` — alinhada com 02-sdk.md §3.1.\r\n *\r\n * ```ts\r\n * const client = createNeetruClient({ ... });\r\n *\r\n * // Mundo Documentos (offline-first):\r\n * const orders = client.db.collection<Order>('orders');\r\n * await orders.add({ ... });\r\n * orders.onSnapshot(query, snap => renderOrders(snap.docs));\r\n *\r\n * // Mundo SQL (lease + pg.Pool + Drizzle):\r\n * const sql = await client.db.sql(schema);\r\n * const rows = await sql.orm.select().from(schema.orders);\r\n *\r\n * // Camada offline:\r\n * const state = client.db.syncState;\r\n * client.db.onSyncStateChanged(s => console.log(s.pendingWrites));\r\n * await client.db.flush(); // força sync\r\n * ```\r\n */\r\nexport interface NeetruDb {\r\n // ── Mundo Documentos ──────────────────────────────────────────────────────\r\n\r\n /**\r\n * Retorna uma `DbCollectionRef` para a coleção `name`.\r\n *\r\n * Offline-first: reads vêm do cache local; writes são aplicados\r\n * otimisticamente e enfileirados para sync. Engine-aware: o transporte\r\n * realtime é selecionado automaticamente pelo `engine` configurado.\r\n */\r\n collection<T = Record<string, unknown>>(\r\n name: string,\r\n ): import('./collection-ref').DbCollectionRef<T>;\r\n\r\n // ── Mundo SQL ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Abre o handle SQL: busca o lease no Core, abre o `pg.Pool`, cria o\r\n * handle Drizzle tipado pelo `schema`. Operação async, 1x no startup.\r\n *\r\n * Em `NEETRU_ENV=dev`, retorna um `MockSqlClient` que não abre socket.\r\n *\r\n * @param schema — Schema Drizzle do produto (`pgTable(...)` em `db/schema.ts`).\r\n * @param options — Opções opcionais (contrato C-H).\r\n * `options.database` desambigua quando o produto tem N>1 bancos SQL.\r\n * Quando omitido, o Core resolve o banco padrão/homônimo do produto.\r\n *\r\n * @example\r\n * ```ts\r\n * import * as schema from './db/schema';\r\n * // banco padrão (único ou homônimo):\r\n * export const db = await client.db.sql(schema);\r\n * // banco específico entre N bancos SQL:\r\n * export const analytics = await client.db.sql(schema, { database: 'analytics' });\r\n * ```\r\n */\r\n sql<TSchema extends Record<string, unknown>>(\r\n schema: TSchema,\r\n options?: SqlOptions,\r\n ): Promise<NeetruSqlClient<TSchema>>;\r\n\r\n // ── Camada offline (Mundo Documentos) ────────────────────────────────────\r\n\r\n /** Estado atual de sincronização da camada offline. */\r\n readonly syncState: SyncState;\r\n\r\n /**\r\n * Subscreve a mudanças de `SyncState`.\r\n * Retorna função de unsubscribe.\r\n */\r\n onSyncStateChanged(cb: (s: SyncState) => void): Unsubscribe;\r\n\r\n /**\r\n * Força flush da fila de mutações pendentes.\r\n * Útil antes de um `beforeunload` ou shutdown do produto.\r\n */\r\n flush(): Promise<void>;\r\n\r\n /**\r\n * Limpa o cache local (IndexedDB) — operação destrutiva.\r\n * Use com cuidado: dados não sincronizados serão perdidos.\r\n */\r\n clearCache(): Promise<void>;\r\n\r\n /**\r\n * Retorna os registros de conflito LWW pendentes de entrega.\r\n * Permite ao produto inspecionar escritas perdidas.\r\n */\r\n getConflicts(): Promise<ConflictRecord[]>;\r\n}\r\n\r\n// ─── Endpoints do Core para o transporte REST ─────────────────────────────────\r\n\r\n/** Endpoint de push de mutações (criação de documento). */\r\nconst DATASTORE_COLLECTION_ENDPOINT = (collection: string) =>\r\n `/api/sdk/v1/datastore/${encodeURIComponent(collection)}`;\r\n\r\n/** Endpoint de mutação num documento específico (update/set/delete). */\r\nconst DATASTORE_DOC_ENDPOINT = (collection: string, docId: string) =>\r\n `/api/sdk/v1/datastore/${encodeURIComponent(collection)}/${encodeURIComponent(docId)}`;\r\n\r\n// Note: DATASTORE_COLLECTION_ENDPOINT is reused for both add (POST) and list (GET)\r\n\r\n// ─── Engine detection + transporte ───────────────────────────────────────────\r\n\r\n/**\r\n * Seleciona o `RealtimeTransport` com base no engine configurado.\r\n *\r\n * Implementa o seam de injeção de 02-sdk.md §3.7.\r\n *\r\n * Regras:\r\n * 1. Se `opts._transport` foi injetado explicitamente (testes) → usa.\r\n * 2. `engine === 'firestore'` e `opts.firestoreTransport` presente → usa.\r\n * 3. `engine === 'nosql-vm'` e `opts.realtimeGatewayUrl` presente →\r\n * cria adapter WebSocket com push/pull REST + RealtimeClient para subscriptions.\r\n * 4. Qualquer outro caso → `RestSyncTransport` (REST real com `config`).\r\n */\r\nfunction resolveTransport(\r\n engine: NeetruDbEngine,\r\n opts: NeetruDbOptions,\r\n config: ResolvedConfig,\r\n): RealtimeTransport {\r\n // 1. Injeção explícita (testes / mocks avançados)\r\n if (opts._transport) {\r\n return opts._transport;\r\n }\r\n\r\n // 2. Engine Firestore — transporte já montado pelo produto\r\n if (engine === 'firestore') {\r\n if (opts.firestoreTransport) {\r\n return opts.firestoreTransport;\r\n }\r\n // Firestore sem transporte injetado → cai para REST real\r\n }\r\n\r\n // 3. Engine nosql-vm — writes via REST real + realtime via NeetruRealtimeClient\r\n if (engine === 'nosql-vm' && opts.realtimeGatewayUrl) {\r\n return createWebSocketSyncTransport(opts.realtimeGatewayUrl, config, opts);\r\n }\r\n\r\n // 4. Default: REST real (funciona para SQL, Firestore sem injeção, nosql-vm sem URL)\r\n return createRestSyncTransport(config);\r\n}\r\n\r\n// ─── RestSyncTransport (default) ─────────────────────────────────────────────\r\n\r\n/**\r\n * Transporte REST puro — usa os endpoints `/api/sdk/v1/datastore/*` do Core.\r\n *\r\n * BL-2 fix: `pushMutations` agora chama o Core de verdade via `httpRequest`.\r\n * Sem `config`, lança `NeetruDbError('db_unavailable')` — NUNCA retorna\r\n * `confirmed` para uma escrita que não foi enviada.\r\n *\r\n * - `pushMutations` → POST/PATCH/PUT/DELETE `/api/sdk/v1/datastore/{coll}/{id}`\r\n * - `pullChanges` → GET `/api/sdk/v1/datastore/{coll}` (best-effort por coleção)\r\n * - `fullResync` → GET por coleção (lista completa)\r\n *\r\n * Exportado para testes.\r\n */\r\nexport function createRestSyncTransport(\r\n config?: ResolvedConfig,\r\n): RealtimeTransport {\r\n return {\r\n async pushMutations(mutations: Mutation[]): Promise<PushMutationsResult> {\r\n if (!config) {\r\n // BL-2: fail-closed — sem config não há como enviar ao Core.\r\n // Lançar em vez de retornar `confirmed` silenciosamente.\r\n throw new NeetruDbError(\r\n 'db_unavailable',\r\n '[RestSyncTransport] config não disponível — não é possível enviar ao Core. ' +\r\n 'Inicialize o transporte via createNeetruDb.',\r\n );\r\n }\r\n\r\n const { httpRequest } = await import('../http');\r\n const results: PushMutationsResult['results'] = [];\r\n\r\n // HIGH-2: o datastore do Core requer x-neetru-tenant. O mundo Documentos\r\n // é scoped por produto, não por tenant. Quando tenantId está ausente mas\r\n // productId existe, usamos productId como tenant-scope — o Core namespeia\r\n // a coleção como `tenant_{id}_{collection}`, isolando dados por produto.\r\n // tenantId explícito sempre tem prioridade (cenários multi-tenant).\r\n const tenantScopeId = config.tenantId ?? config.productId;\r\n const tenantHeaders: Record<string, string> | undefined = tenantScopeId\r\n ? { 'x-neetru-tenant': tenantScopeId }\r\n : undefined;\r\n\r\n for (const m of mutations) {\r\n try {\r\n let raw: unknown;\r\n if (m.op === 'add') {\r\n // POST /datastore/{collection} → { ok, id }\r\n // MED-1: add é não-idempotente — NÃO retryar (retries: 0).\r\n // Uma resposta perdida após escrita bem-sucedida causaria doc duplicado.\r\n // Para idempotência futura, considere enviar m.docId como x-neetru-doc-id.\r\n raw = await httpRequest<unknown>(config, {\r\n method: 'POST',\r\n path: DATASTORE_COLLECTION_ENDPOINT(m.collection),\r\n body: { data: m.payload ?? {} },\r\n requireAuth: true,\r\n retries: 0,\r\n headers: tenantHeaders,\r\n });\r\n } else if (m.op === 'set') {\r\n // PUT /datastore/{collection}/{docId} → { ok, id }\r\n // set é idempotente por docId — retry seguro.\r\n raw = await httpRequest<unknown>(config, {\r\n method: 'PUT',\r\n path: DATASTORE_DOC_ENDPOINT(m.collection, m.docId),\r\n body: { data: m.payload ?? {} },\r\n requireAuth: true,\r\n retries: 2,\r\n headers: tenantHeaders,\r\n });\r\n } else if (m.op === 'update') {\r\n // PATCH /datastore/{collection}/{docId} → { ok, id }\r\n // update (merge) com mesmo payload é idempotente por docId — retry seguro.\r\n raw = await httpRequest<unknown>(config, {\r\n method: 'PATCH',\r\n path: DATASTORE_DOC_ENDPOINT(m.collection, m.docId),\r\n body: { data: m.payload ?? {} },\r\n requireAuth: true,\r\n retries: 2,\r\n headers: tenantHeaders,\r\n });\r\n } else {\r\n // remove — DELETE /datastore/{collection}/{docId}\r\n // delete é idempotente — retry seguro.\r\n raw = await httpRequest<unknown>(config, {\r\n method: 'DELETE',\r\n path: DATASTORE_DOC_ENDPOINT(m.collection, m.docId),\r\n requireAuth: true,\r\n retries: 2,\r\n headers: tenantHeaders,\r\n });\r\n }\r\n\r\n const resp = raw as { ok?: boolean; id?: string; serverVersion?: string } | undefined;\r\n results.push({\r\n mutationId: m.mutationId,\r\n outcome: 'confirmed',\r\n serverVersion: resp?.serverVersion ?? resp?.id ?? `rest_${Date.now()}`,\r\n serverTimestamp: Date.now(),\r\n });\r\n } catch (err) {\r\n // Muta para NeetruDbError para sinalizar falha persistente.\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new NeetruDbError('db_unavailable', `pushMutations falhou: ${msg}`);\r\n }\r\n }\r\n\r\n return { results };\r\n },\r\n\r\n async pullChanges(\r\n _watermark: number | null,\r\n _resumeToken: string | null,\r\n ): Promise<PullChangesResult> {\r\n if (!config) {\r\n // Sem config, não há como consultar o Core — retorna vazio sem crash.\r\n return { docs: [], newWatermark: Date.now(), resyncRequired: false };\r\n }\r\n // Pull periódico: o SyncEngine chama fullResync quando necessário.\r\n return { docs: [], newWatermark: Date.now(), resyncRequired: false };\r\n },\r\n\r\n async fullResync(_collections: string[]): Promise<FullResyncResult> {\r\n if (!config) {\r\n return { docs: [], newWatermark: Date.now() };\r\n }\r\n // Full resync: retorna vazio; pull por coleção individual pode ser implementado futuramente.\r\n return { docs: [], newWatermark: Date.now() };\r\n },\r\n };\r\n}\r\n\r\n// ─── WebSocket SyncTransport (nosql-vm) ──────────────────────────────────────\r\n\r\n/**\r\n * Adapter entre `NeetruRealtimeClient` (WebSocket) e `SyncTransport`.\r\n *\r\n * BL-2 fix: `pushMutations` agora delega ao REST real (via `createRestSyncTransport`)\r\n * — o gateway WS é somente para leitura/realtime.\r\n *\r\n * H-10 fix: `getWebSocketRealtimeClient` é chamado aqui com um `ticketProvider`\r\n * real que chama `POST /api/sdk/v1/db/realtime/ticket` via HTTP do SDK.\r\n *\r\n * HIGH-1 fix: implementa `subscribeCollection` para que `DbCollectionRefImpl.onSnapshot`\r\n * registre subscriptions realtime via `NeetruRealtimeClient.subscribe()`.\r\n * Frames `delta` do gateway são traduzidos para changes e entregues ao callback.\r\n * Frames `resync` sinalizam `needsResync: true` para que o SyncEngine recarregue.\r\n */\r\nfunction createWebSocketSyncTransport(\r\n gatewayUrl: string,\r\n config: ResolvedConfig,\r\n opts: NeetruDbOptions,\r\n): RealtimeTransport {\r\n // Writes vão pelo REST real — o gateway WS é somente realtime/read.\r\n const restTransport = createRestSyncTransport(config);\r\n\r\n // HIGH-1: cria e retém o NeetruRealtimeClient para reutilização nas subscriptions.\r\n const realtimeClient = new NeetruRealtimeClient({\r\n gatewayUrl,\r\n ticketProvider: buildTicketProvider(config, opts),\r\n dbId: opts.dbId,\r\n webSocketFactory: opts._wsFactory,\r\n });\r\n\r\n return {\r\n pushMutations: restTransport.pushMutations.bind(restTransport),\r\n pullChanges: restTransport.pullChanges.bind(restTransport),\r\n fullResync: restTransport.fullResync.bind(restTransport),\r\n\r\n // HIGH-1: subscribeCollection — chamado por DbCollectionRefImpl.onSnapshot\r\n // quando o engine é nosql-vm. Registra a subscription no NeetruRealtimeClient\r\n // e traduz os frames inbound para o contrato de `onChange`.\r\n subscribeCollection(\r\n collection: string,\r\n onChange: (\r\n changes: Array<{ type: 'added' | 'modified' | 'removed'; docId: string; data: Record<string, unknown> | null }>,\r\n needsResync: boolean,\r\n ) => void,\r\n ): () => void {\r\n const subId = realtimeClient.subscribe(collection, {}, (frame) => {\r\n if (frame.op === 'resync') {\r\n onChange([], true);\r\n return;\r\n }\r\n if (frame.op === 'stale') {\r\n // Sinaliza que o cache pode estar desatualizado — pede resync.\r\n onChange([], true);\r\n return;\r\n }\r\n if (frame.op === 'delta' && frame.changes) {\r\n const changes = frame.changes.map((c) => ({\r\n type: (\r\n c.type === 'insert' ? 'added'\r\n : c.type === 'delete' ? 'removed'\r\n : 'modified'\r\n ) as 'added' | 'modified' | 'removed',\r\n docId: c.documentId,\r\n data: c.data ?? null,\r\n }));\r\n if (changes.length > 0) {\r\n onChange(changes, false);\r\n }\r\n }\r\n // 'error' e 'pong' são ignorados aqui; pong é tratado pelo heartbeat interno.\r\n });\r\n\r\n return () => {\r\n realtimeClient.unsubscribe(subId);\r\n };\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Constrói o `TicketProvider` real para o engine `nosql-vm` (H-10 fix).\r\n *\r\n * Chama `POST /api/sdk/v1/db/realtime/ticket` via a camada HTTP do SDK com\r\n * o `productId` resolvido do config.\r\n */\r\nfunction buildTicketProvider(\r\n config: ResolvedConfig,\r\n opts: NeetruDbOptions,\r\n): TicketProvider {\r\n return async () => {\r\n const { httpRequest } = await import('../http');\r\n const ticket = await httpRequest<{\r\n ticketId: string;\r\n token: string;\r\n expiresAt: string;\r\n ttlMs: number;\r\n }>(config, {\r\n method: 'POST',\r\n path: '/api/sdk/v1/db/realtime/ticket',\r\n body: {\r\n productId: config.productId ?? '',\r\n collections: opts.collections ?? ['*'],\r\n },\r\n requireAuth: true,\r\n retries: 1,\r\n });\r\n return ticket;\r\n };\r\n}\r\n\r\n/**\r\n * Retorna o `NeetruRealtimeClient` para uso em `subscribeRealtime` fora do\r\n * `SyncTransport` (extensão nosql-vm — não faz parte do contrato base).\r\n *\r\n * H-10 fix: agora aceita um `dbId` opcional que é passado para o cliente\r\n * (BL-8 — o cliente embute `_dbId` nos frames de subscribe).\r\n *\r\n * @param gatewayUrl URL do gateway WebSocket.\r\n * @param ticketProvider Provedor de ticket obrigatório.\r\n * @param dbId ID do banco lógico (BL-8).\r\n * @param wsFactory Factory de WebSocket injetável (testes).\r\n */\r\nexport function getWebSocketRealtimeClient(\r\n gatewayUrl: string,\r\n ticketProvider: TicketProvider,\r\n dbId?: string,\r\n wsFactory?: import('./realtime/types').WebSocketFactory,\r\n) {\r\n return new NeetruRealtimeClient({ gatewayUrl, ticketProvider, dbId, webSocketFactory: wsFactory });\r\n}\r\n\r\n// ─── Factory pública ─────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Cria o namespace `client.db` completo.\r\n *\r\n * **Factory única** — `createNeetruDb` é a única factory pública.\r\n * O split sync/async é um detalhe de implementação interno: o `NeetruDb`\r\n * retornado inicializa a camada offline (IndexedDB) de forma lazy na\r\n * primeira operação real, portanto:\r\n *\r\n * - Pode ser chamado de contextos síncronos (como `createNeetruClient`).\r\n * - Pode ser chamado com `await` quando se deseja garantir que o store\r\n * esteja aquecido antes da primeira op (equivalente a chamar `flush()`).\r\n * - `client.db.flush()` garante que o IndexedDB está aberto.\r\n *\r\n * @param config — config resolvida do cliente (apiKey, baseUrl, env, etc.)\r\n * @param dbOpts — opções do banco lógico (engine, dbId, collections, etc.)\r\n *\r\n * @example\r\n * ```ts\r\n * // Uso síncrono (dentro de createNeetruClient):\r\n * const db = createNeetruDb(resolved, config.db);\r\n *\r\n * // Uso com await (quando se quer garantir warmup):\r\n * const db = await createNeetruDb(resolved, config.db);\r\n * await db.flush(); // opcional — já está aquecido\r\n *\r\n * // O produto usa:\r\n * const orders = db.collection<Order>('orders');\r\n * const sqlDb = await db.sql(schema);\r\n * ```\r\n */\r\nexport function createNeetruDb(\r\n config: ResolvedConfig,\r\n dbOpts: NeetruDbOptions = {},\r\n): NeetruDb {\r\n const engine = dbOpts.engine ?? 'rest';\r\n const transport = resolveTransport(engine, dbOpts, config);\r\n\r\n // Gera um dbName único por produto × dbId × env\r\n const dbId = dbOpts.dbId ?? 'default';\r\n const dbName =\r\n dbOpts.dbName ??\r\n `neetru-db__${config.productId ?? 'sdk'}__${dbId}__${config.env}`;\r\n\r\n // Promise de inicialização — lazy: só dispara na primeira operação real\r\n let _docsPromise: Promise<NeetruDbDocuments> | null = null;\r\n let _docsResolved: NeetruDbDocuments | null = null;\r\n\r\n function getDocsPromise(): Promise<NeetruDbDocuments> {\r\n if (!_docsPromise) {\r\n _docsPromise = createOfflineDocumentsNamespace({\r\n dbName,\r\n transport,\r\n singleTab: dbOpts.singleTab ?? (config.env !== 'prod'),\r\n }).then((docs) => {\r\n _docsResolved = docs;\r\n return docs;\r\n });\r\n }\r\n return _docsPromise;\r\n }\r\n\r\n // Namespace lazy — inicializa o store na primeira operação\r\n return {\r\n collection<T = Record<string, unknown>>(\r\n name: string,\r\n ): import('./collection-ref').DbCollectionRef<T> {\r\n // Se já resolvido, usa diretamente; caso contrário inicia\r\n if (_docsResolved) return _docsResolved.collection<T>(name);\r\n\r\n // Retorna um DbCollectionRef que awaita o namespace antes de cada op.\r\n // A inicialização do IndexedDB é lazy — só dispara na primeira operação\r\n // real (list/get/add/…), não na chamada a collection() em si.\r\n return createLazyCollectionRef<T>(name, getDocsPromise);\r\n },\r\n\r\n async sql<TSchema extends Record<string, unknown>>(\r\n schema: TSchema,\r\n options?: SqlOptions,\r\n ): Promise<NeetruSqlClient<TSchema>> {\r\n if (config.env === 'dev') {\r\n throw new NeetruDbError(\r\n 'db_unavailable',\r\n '[SDK] db.sql() não disponível em NEETRU_ENV=dev. ' +\r\n 'Use `neetru dev` para subir o container Postgres local.',\r\n );\r\n }\r\n return createSqlClientFromConfig(config, schema, options);\r\n },\r\n\r\n get syncState(): SyncState {\r\n return _docsResolved?.syncState ?? {\r\n status: 'idle',\r\n pendingWrites: 0,\r\n lastSyncedAt: null,\r\n isLeaderTab: false,\r\n };\r\n },\r\n\r\n onSyncStateChanged(cb: (s: SyncState) => void) {\r\n if (_docsResolved) return _docsResolved.onSyncStateChanged(cb);\r\n // Aguarda init e então subscreve\r\n let unsub: Unsubscribe | null = null;\r\n let cancelled = false;\r\n getDocsPromise().then((docs) => {\r\n if (!cancelled) {\r\n unsub = docs.onSyncStateChanged(cb);\r\n }\r\n });\r\n return () => {\r\n cancelled = true;\r\n unsub?.();\r\n };\r\n },\r\n\r\n async flush(): Promise<void> {\r\n const docs = await getDocsPromise();\r\n return docs.flush();\r\n },\r\n\r\n async clearCache(): Promise<void> {\r\n const docs = await getDocsPromise();\r\n return docs.clearCache();\r\n },\r\n\r\n async getConflicts(): Promise<ConflictRecord[]> {\r\n const docs = await getDocsPromise();\r\n return docs.getConflicts();\r\n },\r\n };\r\n}\r\n\r\n// ─── Lazy DbCollectionRef ─────────────────────────────────────────────────────\r\n\r\n/**\r\n * Cria um `DbCollectionRef` que aguarda a inicialização do namespace antes de\r\n * qualquer operação. Permite que `createNeetruDb` retorne um ref imediato\r\n * mesmo que o IndexedDB ainda não esteja aberto (lazy-init).\r\n */\r\nfunction createLazyCollectionRef<T = Record<string, unknown>>(\r\n name: string,\r\n getDocsPromise: () => Promise<NeetruDbDocuments>,\r\n): import('./collection-ref').DbCollectionRef<T> {\r\n async function getRef(): Promise<import('./collection-ref').DbCollectionRef<T>> {\r\n const docs = await getDocsPromise();\r\n return docs.collection<T>(name);\r\n }\r\n\r\n return {\r\n async get(id: string) {\r\n return (await getRef()).get(id);\r\n },\r\n async list(q) {\r\n return (await getRef()).list(q);\r\n },\r\n async add(data) {\r\n return (await getRef()).add(data);\r\n },\r\n async set(id, data) {\r\n return (await getRef()).set(id, data);\r\n },\r\n async update(id, data) {\r\n return (await getRef()).update(id, data);\r\n },\r\n async remove(id) {\r\n return (await getRef()).remove(id);\r\n },\r\n async batch(ops) {\r\n return (await getRef()).batch(ops);\r\n },\r\n onDoc(id, cb) {\r\n let unsub: Unsubscribe | null = null;\r\n let cancelled = false;\r\n getRef().then((ref) => {\r\n if (!cancelled) {\r\n unsub = ref.onDoc(id, cb);\r\n }\r\n });\r\n return () => {\r\n cancelled = true;\r\n unsub?.();\r\n };\r\n },\r\n onSnapshot(q, cb) {\r\n let unsub: Unsubscribe | null = null;\r\n let cancelled = false;\r\n getRef().then((ref) => {\r\n if (!cancelled) {\r\n unsub = ref.onSnapshot(q, cb);\r\n }\r\n });\r\n return () => {\r\n cancelled = true;\r\n unsub?.();\r\n };\r\n },\r\n doc(id) {\r\n // Lazy doc ref\r\n return {\r\n async get() {\r\n return (await getRef()).doc(id).get();\r\n },\r\n async set(data) {\r\n return (await getRef()).doc(id).set(data);\r\n },\r\n async update(data) {\r\n return (await getRef()).doc(id).update(data);\r\n },\r\n async remove() {\r\n return (await getRef()).doc(id).remove();\r\n },\r\n onSnapshot(cb) {\r\n let unsub: Unsubscribe | null = null;\r\n let cancelled = false;\r\n getRef().then((ref) => {\r\n if (!cancelled) {\r\n unsub = ref.doc(id).onSnapshot(cb);\r\n }\r\n });\r\n return () => {\r\n cancelled = true;\r\n unsub?.();\r\n };\r\n },\r\n };\r\n },\r\n };\r\n}\r\n","/**\r\n * Checkout namespace (v1.1) — `client.checkout.*`\r\n *\r\n * Fluxo canônico (vide `docs/FLUXO_SIGNUP_BILLING_CHECKOUT.md` §6):\r\n * 1. SaaS produto chama `client.checkout.start({productId, planId, callbackUrl})`.\r\n * 2. SDK posta em `POST /api/v1/checkout/intents` (Bearer access_token OIDC).\r\n * 3. Core cria `checkout_intents/{intentId}` (TTL 15min) + retorna `redirectUrl`.\r\n * 4. Em browser, SDK redireciona automaticamente pra `redirectUrl`. Em\r\n * Node/SSR, retorna o objeto `{intentId, redirectUrl}` sem redirect.\r\n * 5. Portal (`minhaconta.neetru.com/portal/kyc/{intentId}`) coleta KYC + cartão.\r\n * 6. Usuário volta pra `callbackUrl?status=success&intentId=...` quando completo.\r\n *\r\n * **Dev mode** (`NEETRU_ENV=dev`): `start()` retorna URL fake sem network call.\r\n * Útil pra dev externo SaaS testar UI sem provisionar conta Neetru.\r\n *\r\n * **Estabilidade**: minor bump v1.0 → v1.1 (feature add, sem breaking).\r\n */\r\nimport { NeetruError } from './errors';\r\nimport { httpRequest } from './http';\r\nimport type { ResolvedConfig } from './types';\r\n\r\n// ─── Types públicos ─────────────────────────────────────────────────────────\r\n\r\n/** Tipo do tenant alvo da subscription (PF=uid, PJ=orgId). */\r\nexport type CheckoutTenantType = 'pf' | 'pj';\r\n\r\n/** Status do `checkout_intents/{intentId}` no Core. */\r\nexport type CheckoutIntentStatus =\r\n | 'pending'\r\n | 'kyc_in_progress'\r\n | 'stripe_redirected'\r\n | 'completed'\r\n | 'expired'\r\n | 'cancelled';\r\n\r\nexport interface CheckoutStartInput {\r\n /** Slug do produto no catálogo (ex: `neetru-pulse`). */\r\n productId: string;\r\n /** Slug do plano no catálogo do produto (ex: `pro_monthly`). */\r\n planId: string;\r\n /** Pra onde o produto SaaS quer voltar pós-checkout. https obrigatório (ou http://localhost em dev). */\r\n callbackUrl: string;\r\n /** Override pra checkout em nome de uma org. Default: PF do uid logado. */\r\n tenantType?: CheckoutTenantType;\r\n /** Quando `tenantType='pj'`, id da org. Ignorado quando PF. */\r\n tenantId?: string;\r\n /**\r\n * Em browsers, default `true` — SDK faz `window.location.href = redirectUrl`.\r\n * Passe `false` se quiser controlar o redirect manualmente.\r\n */\r\n autoRedirect?: boolean;\r\n}\r\n\r\nexport interface CheckoutStartResult {\r\n intentId: string;\r\n redirectUrl: string;\r\n status: CheckoutIntentStatus;\r\n expiresAt: string;\r\n /** True se KYC ainda precisa ser coletado no portal. UI pode mostrar hint. */\r\n requiresKyc: boolean;\r\n}\r\n\r\nexport interface CheckoutIntentInfo {\r\n intentId: string;\r\n uid: string;\r\n targetTenantId: string;\r\n targetTenantType: CheckoutTenantType;\r\n productId: string;\r\n planId: string;\r\n callbackUrl: string;\r\n status: CheckoutIntentStatus;\r\n /** Stripe Checkout Session id quando avançou pra `stripe_redirected`. */\r\n stripeSessionId?: string | null;\r\n expiresAt: string;\r\n /** True se já passou `expiresAt` mas Core ainda não marcou expired. */\r\n isStale?: boolean;\r\n}\r\n\r\nexport interface CheckoutNamespace {\r\n /**\r\n * Inicia checkout. Em browser, redireciona automaticamente pro portal.\r\n * Em Node/SSR, retorna o resultado sem efeitos colaterais — caller decide\r\n * o que fazer com `redirectUrl`.\r\n *\r\n * Dev mode (`NEETRU_ENV=dev`): retorna URL fake `https://localhost:9003/portal/checkout/mock-XXXX`.\r\n */\r\n start(input: CheckoutStartInput): Promise<CheckoutStartResult>;\r\n /** Lê estado atual do intent (Core). */\r\n get(intentId: string): Promise<CheckoutIntentInfo>;\r\n /** Cancela um intent que ainda não virou `stripe_redirected`. */\r\n cancel(intentId: string): Promise<{ ok: true; alreadyCancelled: boolean }>;\r\n}\r\n\r\n// ─── Implementação real (HTTP) ─────────────────────────────────────────────\r\n\r\ninterface RawStartCheckoutResponse {\r\n ok?: boolean;\r\n intentId?: string;\r\n redirectUrl?: string;\r\n status?: string;\r\n expiresAt?: string;\r\n requiresKyc?: boolean;\r\n}\r\n\r\ninterface RawGetCheckoutResponse {\r\n ok?: boolean;\r\n intent?: {\r\n intentId?: string;\r\n uid?: string;\r\n targetTenantId?: string;\r\n targetTenantType?: string;\r\n productId?: string;\r\n planId?: string;\r\n callbackUrl?: string;\r\n status?: string;\r\n stripeSessionId?: string | null;\r\n expiresAt?: string;\r\n };\r\n isStale?: boolean;\r\n}\r\n\r\nfunction parseStartResponse(raw: unknown): CheckoutStartResult {\r\n if (!raw || typeof raw !== 'object') {\r\n throw new NeetruError('invalid_response', 'checkout.start response is not an object');\r\n }\r\n const r = raw as RawStartCheckoutResponse;\r\n if (typeof r.intentId !== 'string' || !r.intentId) {\r\n throw new NeetruError('invalid_response', 'checkout.start response missing intentId');\r\n }\r\n if (typeof r.redirectUrl !== 'string' || !r.redirectUrl) {\r\n throw new NeetruError('invalid_response', 'checkout.start response missing redirectUrl');\r\n }\r\n return {\r\n intentId: r.intentId,\r\n redirectUrl: r.redirectUrl,\r\n status: (r.status as CheckoutIntentStatus | undefined) ?? 'pending',\r\n expiresAt: typeof r.expiresAt === 'string' ? r.expiresAt : new Date().toISOString(),\r\n requiresKyc: r.requiresKyc === true,\r\n };\r\n}\r\n\r\nfunction parseGetResponse(raw: unknown): CheckoutIntentInfo {\r\n if (!raw || typeof raw !== 'object') {\r\n throw new NeetruError('invalid_response', 'checkout.get response is not an object');\r\n }\r\n const r = raw as RawGetCheckoutResponse;\r\n const intent = r.intent;\r\n if (!intent || typeof intent !== 'object') {\r\n throw new NeetruError('invalid_response', 'checkout.get response missing intent');\r\n }\r\n if (typeof intent.intentId !== 'string') {\r\n throw new NeetruError('invalid_response', 'checkout.get response missing intentId');\r\n }\r\n return {\r\n intentId: intent.intentId,\r\n uid: intent.uid ?? '',\r\n targetTenantId: intent.targetTenantId ?? '',\r\n targetTenantType: (intent.targetTenantType as CheckoutTenantType | undefined) ?? 'pf',\r\n productId: intent.productId ?? '',\r\n planId: intent.planId ?? '',\r\n callbackUrl: intent.callbackUrl ?? '',\r\n status: (intent.status as CheckoutIntentStatus | undefined) ?? 'pending',\r\n stripeSessionId: intent.stripeSessionId ?? null,\r\n expiresAt: intent.expiresAt ?? new Date().toISOString(),\r\n isStale: r.isStale === true,\r\n };\r\n}\r\n\r\n/**\r\n * Detecta se estamos em browser context. Em SSR / Node / Edge, `window`\r\n * pode não existir — fazemos check defensivo.\r\n */\r\nfunction inBrowser(): boolean {\r\n try {\r\n return (\r\n typeof globalThis !== 'undefined' &&\r\n typeof (globalThis as { window?: { location?: { href?: string } } }).window !== 'undefined' &&\r\n typeof globalThis.location !== 'undefined' &&\r\n typeof globalThis.location.assign === 'function'\r\n );\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nfunction performRedirect(url: string): void {\r\n try {\r\n globalThis.location.assign(url);\r\n } catch {\r\n /* noop em runtimes sem location.assign — caller decide */\r\n }\r\n}\r\n\r\n/**\r\n * Implementação HTTP real. Posta no Core, parse response, redireciona se browser.\r\n */\r\nfunction createHttpCheckoutNamespace(config: ResolvedConfig): CheckoutNamespace {\r\n return {\r\n async start(input: CheckoutStartInput): Promise<CheckoutStartResult> {\r\n if (!input?.productId) {\r\n throw new NeetruError('validation_failed', 'checkout.start: productId is required');\r\n }\r\n if (!input?.planId) {\r\n throw new NeetruError('validation_failed', 'checkout.start: planId is required');\r\n }\r\n if (!input?.callbackUrl) {\r\n throw new NeetruError('validation_failed', 'checkout.start: callbackUrl is required');\r\n }\r\n\r\n const body: Record<string, unknown> = {\r\n productId: input.productId,\r\n planId: input.planId,\r\n callbackUrl: input.callbackUrl,\r\n };\r\n if (input.tenantType) body.targetTenantType = input.tenantType;\r\n if (input.tenantId) body.targetTenantId = input.tenantId;\r\n\r\n const raw = await httpRequest<RawStartCheckoutResponse>(config, {\r\n method: 'POST',\r\n path: '/api/v1/checkout/intents',\r\n body,\r\n requireAuth: true,\r\n });\r\n const result = parseStartResponse(raw);\r\n\r\n const shouldRedirect = input.autoRedirect !== false;\r\n if (shouldRedirect && inBrowser()) {\r\n performRedirect(result.redirectUrl);\r\n }\r\n return result;\r\n },\r\n\r\n async get(intentId: string): Promise<CheckoutIntentInfo> {\r\n if (!intentId || typeof intentId !== 'string') {\r\n throw new NeetruError('validation_failed', 'checkout.get: intentId is required');\r\n }\r\n const raw = await httpRequest<RawGetCheckoutResponse>(config, {\r\n method: 'GET',\r\n path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,\r\n requireAuth: true,\r\n });\r\n return parseGetResponse(raw);\r\n },\r\n\r\n async cancel(intentId: string): Promise<{ ok: true; alreadyCancelled: boolean }> {\r\n if (!intentId || typeof intentId !== 'string') {\r\n throw new NeetruError('validation_failed', 'checkout.cancel: intentId is required');\r\n }\r\n const raw = await httpRequest<{ ok?: boolean; alreadyCancelled?: boolean }>(config, {\r\n method: 'DELETE',\r\n path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,\r\n requireAuth: true,\r\n });\r\n return {\r\n ok: true,\r\n alreadyCancelled: (raw as { alreadyCancelled?: boolean })?.alreadyCancelled === true,\r\n };\r\n },\r\n };\r\n}\r\n\r\n// ─── Mock dev (sem network) ─────────────────────────────────────────────────\r\n\r\n/**\r\n * Mock dev — retorna URL fake `https://localhost:9003/portal/checkout/mock-XXXX`\r\n * sem tocar no Core. Útil pra dev externo SaaS testar UI/redirect sem precisar\r\n * de Bearer token Neetru.\r\n *\r\n * Dev mode persiste intents em mapa in-memory pro `get`/`cancel` retornarem\r\n * resultado consistente.\r\n */\r\nexport class MockCheckout implements CheckoutNamespace {\r\n private readonly intents = new Map<string, CheckoutIntentInfo>();\r\n\r\n async start(input: CheckoutStartInput): Promise<CheckoutStartResult> {\r\n if (!input?.productId) {\r\n throw new NeetruError('validation_failed', 'checkout.start: productId is required');\r\n }\r\n if (!input?.planId) {\r\n throw new NeetruError('validation_failed', 'checkout.start: planId is required');\r\n }\r\n if (!input?.callbackUrl) {\r\n throw new NeetruError('validation_failed', 'checkout.start: callbackUrl is required');\r\n }\r\n\r\n const intentId = `chk_mock_${Math.random().toString(36).slice(2, 10)}`;\r\n const expiresAt = new Date(Date.now() + 15 * 60 * 1000).toISOString();\r\n const redirectUrl = `https://localhost:9003/portal/checkout/${intentId}`;\r\n\r\n this.intents.set(intentId, {\r\n intentId,\r\n uid: 'dev-fixture-uid',\r\n targetTenantId: input.tenantId ?? 'dev-fixture-uid',\r\n targetTenantType: input.tenantType ?? 'pf',\r\n productId: input.productId,\r\n planId: input.planId,\r\n callbackUrl: input.callbackUrl,\r\n status: 'pending',\r\n stripeSessionId: null,\r\n expiresAt,\r\n });\r\n\r\n return {\r\n intentId,\r\n redirectUrl,\r\n status: 'pending',\r\n expiresAt,\r\n requiresKyc: false,\r\n };\r\n }\r\n\r\n async get(intentId: string): Promise<CheckoutIntentInfo> {\r\n const found = this.intents.get(intentId);\r\n if (!found) {\r\n throw new NeetruError('not_found', `Mock intent ${intentId} not found`);\r\n }\r\n return { ...found };\r\n }\r\n\r\n async cancel(intentId: string): Promise<{ ok: true; alreadyCancelled: boolean }> {\r\n const found = this.intents.get(intentId);\r\n if (!found) {\r\n throw new NeetruError('not_found', `Mock intent ${intentId} not found`);\r\n }\r\n const alreadyCancelled = found.status === 'cancelled';\r\n this.intents.set(intentId, { ...found, status: 'cancelled' });\r\n return { ok: true, alreadyCancelled };\r\n }\r\n}\r\n\r\n// ─── Factory ────────────────────────────────────────────────────────────────\r\n\r\nexport function createCheckoutNamespace(config: ResolvedConfig): CheckoutNamespace {\r\n if (config.env === 'dev') return new MockCheckout();\r\n return createHttpCheckoutNamespace(config);\r\n}\r\n","/**\r\n * Webhooks namespace (v1.2) — produtos SaaS registram endpoints HTTP no Core\r\n * pra receber notificações de eventos.\r\n *\r\n * Casos típicos:\r\n * - `subscription.activated` quando cliente conclui checkout\r\n * - `subscription.cancelled` / `subscription.payment_failed`\r\n * - `usage.quota_exceeded` quando produto bate teto mensal\r\n * - `account.suspended` quando staff Neetru suspende uma conta\r\n *\r\n * Pull-vs-push: o SDK existente é pull-only (`getQuota`, etc). Webhooks\r\n * fecham o gap pra eventos assíncronos sem o produto precisar fazer polling.\r\n *\r\n * Segurança:\r\n * - Endpoint do produto recebe HMAC SHA-256 em header `X-Neetru-Signature`\r\n * usando `secret` opcional do registro. Sem `secret`, header ausente —\r\n * produto deve usar HTTPS + IP allowlist.\r\n * - Replay protection: header `X-Neetru-Timestamp` (ms) — produto deve\r\n * rejeitar > 5min de skew.\r\n * - Retry: Core retenta 3x com backoff exponencial (1s, 5s, 25s) se 5xx\r\n * ou timeout. Após 3 falhas → marca endpoint `degraded` por 1h.\r\n *\r\n * Endpoints REST (em prod):\r\n * - `POST /api/sdk/v1/webhooks` — registra novo endpoint\r\n * - `GET /api/sdk/v1/webhooks` — lista endpoints do produto\r\n * - `DELETE /api/sdk/v1/webhooks/{id}` — remove endpoint\r\n * - `POST /api/sdk/v1/webhooks/{id}/test` — dispara evento de teste\r\n *\r\n * Mock em `NEETRU_ENV=dev`: tudo in-memory, sem rede.\r\n */\r\nimport { NeetruError } from './errors';\r\nimport { httpRequest } from './http';\r\nimport type { ResolvedConfig } from './types';\r\n\r\n/** Eventos Neetru que produtos podem assinar. Lista expansível por minor bump. */\r\nexport type WebhookEvent =\r\n | 'subscription.activated'\r\n | 'subscription.cancelled'\r\n | 'subscription.payment_failed'\r\n | 'subscription.trial_ending'\r\n | 'usage.quota_exceeded'\r\n | 'account.suspended'\r\n | 'account.reactivated'\r\n | 'support.ticket_replied';\r\n\r\nexport interface WebhookEndpoint {\r\n id: string;\r\n url: string;\r\n events: WebhookEvent[];\r\n /** Quando true, `X-Neetru-Signature` é enviado em cada dispatch. */\r\n hasSecret: boolean;\r\n status: 'active' | 'degraded' | 'disabled';\r\n /** ISO timestamp do último dispatch bem-sucedido. */\r\n lastDeliveryAt?: string;\r\n /** Quantos dispatches falharam consecutivos (resetado em sucesso). */\r\n consecutiveFailures?: number;\r\n createdAt: string;\r\n}\r\n\r\nexport interface RegisterWebhookInput {\r\n url: string;\r\n events: WebhookEvent[];\r\n /**\r\n * Secret pra HMAC SHA-256 (mín 16 chars). Recomendado.\r\n * Quando ausente, dispatches vão sem assinatura — produto deve ter\r\n * IP allowlist ou outra defesa.\r\n */\r\n secret?: string;\r\n}\r\n\r\nexport interface WebhookTestResult {\r\n ok: boolean;\r\n statusCode?: number;\r\n durationMs?: number;\r\n error?: string;\r\n}\r\n\r\nexport interface WebhooksNamespace {\r\n /** Registra um novo endpoint. */\r\n register(input: RegisterWebhookInput): Promise<WebhookEndpoint>;\r\n /** Lista endpoints registrados pelo produto. */\r\n list(): Promise<WebhookEndpoint[]>;\r\n /** Remove um endpoint. */\r\n unregister(id: string): Promise<{ ok: true }>;\r\n /** Dispara evento de teste pra validar conectividade. */\r\n test(id: string): Promise<WebhookTestResult>;\r\n}\r\n\r\n/**\r\n * Verifica assinatura HMAC SHA-256 de payload de webhook recebido pelo\r\n * produto consumer. Constant-time compare pra resistir a timing attack.\r\n *\r\n * @param payload Corpo cru da request (string ou Buffer). NÃO use o objeto\r\n * parseado — JSON.stringify pode diferir do que foi assinado.\r\n * @param signature Header `X-Neetru-Signature` recebido (formato `sha256=<hex>`).\r\n * @param secret Secret registrado em `webhooks.register({ secret })`.\r\n * @returns true se assinatura confere, false caso contrário.\r\n *\r\n * @example\r\n * ```ts\r\n * // Express handler\r\n * app.post('/webhooks/neetru', express.raw({ type: 'application/json' }), (req, res) => {\r\n * const sig = req.header('X-Neetru-Signature');\r\n * if (!verifyWebhookSignature(req.body, sig, process.env.WEBHOOK_SECRET!)) {\r\n * return res.status(401).end();\r\n * }\r\n * const event = JSON.parse(req.body.toString('utf8'));\r\n * // ... handle event\r\n * res.json({ ok: true });\r\n * });\r\n * ```\r\n */\r\nexport function verifyWebhookSignature(\r\n payload: string | Uint8Array,\r\n signature: string | null | undefined,\r\n secret: string,\r\n): boolean {\r\n if (!signature || !secret) return false;\r\n // Aceita \"sha256=<hex>\" ou \"<hex>\" cru.\r\n const sigHex = signature.startsWith('sha256=') ? signature.slice(7) : signature;\r\n if (!/^[0-9a-f]+$/i.test(sigHex)) return false;\r\n\r\n // Crypto API: Node tem `node:crypto`, browsers têm WebCrypto. Aqui usamos\r\n // node:crypto (SDK roda majoritariamente server-side em produto Node). Se\r\n // o consumer for browser puro precisando verificar, basta importar o\r\n // namespace direto e usar WebCrypto — não é o caso típico, então não\r\n // pagamos o custo de bundle.\r\n let nodeCrypto: typeof import('node:crypto');\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-require-imports\r\n nodeCrypto = require('node:crypto');\r\n } catch {\r\n if (typeof console !== 'undefined') {\r\n console.warn(\r\n '[neetru-sdk] verifyWebhookSignature requires Node crypto. In browser, use WebCrypto subtle.verify directly.',\r\n );\r\n }\r\n return false;\r\n }\r\n\r\n const computed = nodeCrypto.createHmac('sha256', secret).update(payload).digest('hex');\r\n const a = Buffer.from(computed, 'hex');\r\n const b = Buffer.from(sigHex.toLowerCase(), 'hex');\r\n if (a.length !== b.length) return false;\r\n return nodeCrypto.timingSafeEqual(a, b);\r\n}\r\n\r\n// ─── HTTP impl ──────────────────────────────────────────────────────────────\r\n\r\nconst VALID_EVENTS: readonly WebhookEvent[] = [\r\n 'subscription.activated',\r\n 'subscription.cancelled',\r\n 'subscription.payment_failed',\r\n 'subscription.trial_ending',\r\n 'usage.quota_exceeded',\r\n 'account.suspended',\r\n 'account.reactivated',\r\n 'support.ticket_replied',\r\n];\r\n\r\nfunction toEndpoint(raw: unknown): WebhookEndpoint {\r\n if (!raw || typeof raw !== 'object') {\r\n throw new NeetruError('invalid_response', 'Webhook response is not an object');\r\n }\r\n const r = raw as Record<string, unknown>;\r\n if (typeof r.id !== 'string') {\r\n throw new NeetruError('invalid_response', 'Webhook missing id');\r\n }\r\n return {\r\n id: r.id,\r\n url: typeof r.url === 'string' ? r.url : '',\r\n events: Array.isArray(r.events)\r\n ? (r.events as unknown[]).filter((e): e is WebhookEvent =>\r\n VALID_EVENTS.includes(e as WebhookEvent),\r\n )\r\n : [],\r\n hasSecret: r.hasSecret === true,\r\n status:\r\n r.status === 'active' || r.status === 'degraded' || r.status === 'disabled'\r\n ? r.status\r\n : 'active',\r\n lastDeliveryAt: typeof r.lastDeliveryAt === 'string' ? r.lastDeliveryAt : undefined,\r\n consecutiveFailures:\r\n typeof r.consecutiveFailures === 'number' ? r.consecutiveFailures : undefined,\r\n createdAt: typeof r.createdAt === 'string' ? r.createdAt : new Date().toISOString(),\r\n };\r\n}\r\n\r\nfunction validateInput(input: RegisterWebhookInput): void {\r\n if (!input.url || typeof input.url !== 'string') {\r\n throw new NeetruError('validation_failed', 'url é obrigatória');\r\n }\r\n try {\r\n const parsed = new URL(input.url);\r\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\r\n throw new Error('invalid protocol');\r\n }\r\n // Em prod, http: é warning (não bloqueia) — testes locais podem usar\r\n } catch {\r\n throw new NeetruError('validation_failed', `url inválida: ${input.url}`);\r\n }\r\n if (!Array.isArray(input.events) || input.events.length === 0) {\r\n throw new NeetruError('validation_failed', 'events deve ter pelo menos 1 evento');\r\n }\r\n for (const ev of input.events) {\r\n if (!VALID_EVENTS.includes(ev)) {\r\n throw new NeetruError('validation_failed', `evento desconhecido: ${ev}`);\r\n }\r\n }\r\n if (input.secret !== undefined && input.secret.length < 16) {\r\n throw new NeetruError('validation_failed', 'secret deve ter ≥16 chars (recomendado 32+)');\r\n }\r\n}\r\n\r\nexport function createWebhooksNamespace(config: ResolvedConfig): WebhooksNamespace {\r\n return {\r\n async register(input) {\r\n validateInput(input);\r\n const raw = await httpRequest<unknown>(config, {\r\n method: 'POST',\r\n path: '/api/sdk/v1/webhooks',\r\n body: input,\r\n requireAuth: true,\r\n });\r\n return toEndpoint(raw);\r\n },\r\n async list() {\r\n const raw = await httpRequest<{ endpoints?: unknown[] }>(config, {\r\n method: 'GET',\r\n path: '/api/sdk/v1/webhooks',\r\n requireAuth: true,\r\n });\r\n const list = Array.isArray(raw?.endpoints) ? raw.endpoints : [];\r\n return list.map(toEndpoint);\r\n },\r\n async unregister(id) {\r\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\r\n await httpRequest<unknown>(config, {\r\n method: 'DELETE',\r\n path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}`,\r\n requireAuth: true,\r\n });\r\n return { ok: true };\r\n },\r\n async test(id) {\r\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\r\n const raw = await httpRequest<unknown>(config, {\r\n method: 'POST',\r\n path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}/test`,\r\n requireAuth: true,\r\n });\r\n if (!raw || typeof raw !== 'object') {\r\n return { ok: false, error: 'invalid response' };\r\n }\r\n const r = raw as Record<string, unknown>;\r\n return {\r\n ok: r.ok === true,\r\n statusCode: typeof r.statusCode === 'number' ? r.statusCode : undefined,\r\n durationMs: typeof r.durationMs === 'number' ? r.durationMs : undefined,\r\n error: typeof r.error === 'string' ? r.error : undefined,\r\n };\r\n },\r\n };\r\n}\r\n\r\n// ─── Mock impl (dev / tests) ────────────────────────────────────────────────\r\n\r\nexport class MockWebhooks implements WebhooksNamespace {\r\n private endpoints = new Map<string, WebhookEndpoint>();\r\n private nextId = 1;\r\n\r\n async register(input: RegisterWebhookInput): Promise<WebhookEndpoint> {\r\n validateInput(input);\r\n const id = `mock_wh_${this.nextId++}`;\r\n const endpoint: WebhookEndpoint = {\r\n id,\r\n url: input.url,\r\n events: input.events,\r\n hasSecret: !!input.secret,\r\n status: 'active',\r\n createdAt: new Date().toISOString(),\r\n };\r\n this.endpoints.set(id, endpoint);\r\n return endpoint;\r\n }\r\n\r\n async list(): Promise<WebhookEndpoint[]> {\r\n return [...this.endpoints.values()];\r\n }\r\n\r\n async unregister(id: string): Promise<{ ok: true }> {\r\n if (!this.endpoints.has(id)) {\r\n throw new NeetruError('not_found', `Webhook ${id} não encontrado`);\r\n }\r\n this.endpoints.delete(id);\r\n return { ok: true };\r\n }\r\n\r\n async test(id: string): Promise<WebhookTestResult> {\r\n if (!this.endpoints.has(id)) {\r\n throw new NeetruError('not_found', `Webhook ${id} não encontrado`);\r\n }\r\n return { ok: true, statusCode: 200, durationMs: 42 };\r\n }\r\n}\r\n","/**\r\n * Notifications namespace (v1.2) — produtos SaaS enviam notificações in-app\r\n * pros SEUS usuários (distinto das `notifications/` staff-only do Core).\r\n *\r\n * Caso típico: produto gestovendas notifica usuário \"Pedido #X recebido\" no\r\n * portal sem precisar manter a própria coleção Firestore.\r\n *\r\n * Schema isolado por produto: `product_user_notifications/{productId}/{notifId}`.\r\n * Owner Neetru não vê o conteúdo (privacidade do produto), mas o Core\r\n * armazena + serve a leitura. Produto pode também listar via SDK.\r\n *\r\n * Endpoints REST (em prod):\r\n * - `POST /api/sdk/v1/notifications` — produto envia\r\n * - `GET /api/sdk/v1/notifications/user/{userId}` — produto lista do user\r\n * - `POST /api/sdk/v1/notifications/{id}/read` — user marca lida (proxy)\r\n * - `POST /api/sdk/v1/notifications/{id}/dismiss` — user descarta (proxy)\r\n *\r\n * Severidade canônica: `info | success | warning | error`.\r\n *\r\n * Mock em `NEETRU_ENV=dev`: in-memory.\r\n */\r\nimport { NeetruError } from './errors';\r\nimport { httpRequest } from './http';\r\nimport type { ResolvedConfig } from './types';\r\n\r\nexport type ProductNotificationSeverity =\r\n | 'info'\r\n | 'success'\r\n | 'warning'\r\n | 'error';\r\n\r\nexport interface ProductNotification {\r\n id: string;\r\n /** UID do usuário final (do produto, não staff Neetru). */\r\n userId: string;\r\n /** Identificador semântico do evento (ex: `order.received`). */\r\n kind: string;\r\n severity: ProductNotificationSeverity;\r\n title: string;\r\n body?: string;\r\n /** Link opcional pra ação. */\r\n link?: string;\r\n /** Metadata livre (serializável). */\r\n metadata?: Record<string, string | number | boolean | null>;\r\n createdAt: string;\r\n /** ISO quando user marcou lida. */\r\n readAt?: string;\r\n /** ISO quando user descartou. */\r\n dismissedAt?: string;\r\n}\r\n\r\nexport interface SendNotificationInput {\r\n userId: string;\r\n kind: string;\r\n title: string;\r\n severity?: ProductNotificationSeverity;\r\n body?: string;\r\n link?: string;\r\n metadata?: Record<string, string | number | boolean | null>;\r\n /**\r\n * Dedup — se já existir notificação com mesmo fingerprint dentro de 24h,\r\n * NÃO cria duplicata. Útil pra evitar spam quando webhook reentrega.\r\n */\r\n fingerprint?: string;\r\n}\r\n\r\nexport interface ListNotificationsOptions {\r\n /** Inclui notificações dismissed (default false). */\r\n includeDismissed?: boolean;\r\n /** Filtro por unread. */\r\n onlyUnread?: boolean;\r\n /** Máx itens (default 50, máx 200). */\r\n limit?: number;\r\n}\r\n\r\nexport interface NotificationsNamespace {\r\n /** Produto envia uma notificação pra um usuário do produto. */\r\n send(input: SendNotificationInput): Promise<ProductNotification>;\r\n /** Lista notificações de um usuário. */\r\n list(\r\n userId: string,\r\n options?: ListNotificationsOptions,\r\n ): Promise<ProductNotification[]>;\r\n /** Marca como lida. */\r\n markRead(id: string): Promise<{ ok: true }>;\r\n /** Descarta. */\r\n dismiss(id: string): Promise<{ ok: true }>;\r\n}\r\n\r\n// ─── HTTP impl ──────────────────────────────────────────────────────────────\r\n\r\nconst VALID_SEVERITIES: readonly ProductNotificationSeverity[] = [\r\n 'info',\r\n 'success',\r\n 'warning',\r\n 'error',\r\n];\r\n\r\nfunction toNotification(raw: unknown): ProductNotification {\r\n if (!raw || typeof raw !== 'object') {\r\n throw new NeetruError('invalid_response', 'Notification response is not an object');\r\n }\r\n const r = raw as Record<string, unknown>;\r\n if (typeof r.id !== 'string') {\r\n throw new NeetruError('invalid_response', 'Notification missing id');\r\n }\r\n const sev = VALID_SEVERITIES.includes(r.severity as ProductNotificationSeverity)\r\n ? (r.severity as ProductNotificationSeverity)\r\n : 'info';\r\n return {\r\n id: r.id,\r\n userId: typeof r.userId === 'string' ? r.userId : '',\r\n kind: typeof r.kind === 'string' ? r.kind : 'unknown',\r\n severity: sev,\r\n title: typeof r.title === 'string' ? r.title : '',\r\n body: typeof r.body === 'string' ? r.body : undefined,\r\n link: typeof r.link === 'string' ? r.link : undefined,\r\n metadata:\r\n r.metadata && typeof r.metadata === 'object'\r\n ? (r.metadata as Record<string, string | number | boolean | null>)\r\n : undefined,\r\n createdAt: typeof r.createdAt === 'string' ? r.createdAt : new Date().toISOString(),\r\n readAt: typeof r.readAt === 'string' ? r.readAt : undefined,\r\n dismissedAt: typeof r.dismissedAt === 'string' ? r.dismissedAt : undefined,\r\n };\r\n}\r\n\r\nfunction validateInput(input: SendNotificationInput): void {\r\n if (!input.userId) throw new NeetruError('validation_failed', 'userId obrigatório');\r\n if (!input.kind) throw new NeetruError('validation_failed', 'kind obrigatório');\r\n if (!input.title) throw new NeetruError('validation_failed', 'title obrigatório');\r\n if (input.severity && !VALID_SEVERITIES.includes(input.severity)) {\r\n throw new NeetruError(\r\n 'validation_failed',\r\n `severity inválida: ${input.severity} (use ${VALID_SEVERITIES.join('|')})`,\r\n );\r\n }\r\n if (input.title.length > 200) {\r\n throw new NeetruError('validation_failed', 'title máx 200 chars');\r\n }\r\n if (input.body && input.body.length > 2000) {\r\n throw new NeetruError('validation_failed', 'body máx 2000 chars');\r\n }\r\n}\r\n\r\nexport function createNotificationsNamespace(\r\n config: ResolvedConfig,\r\n): NotificationsNamespace {\r\n return {\r\n async send(input) {\r\n validateInput(input);\r\n const raw = await httpRequest<unknown>(config, {\r\n method: 'POST',\r\n path: '/api/sdk/v1/notifications',\r\n body: input,\r\n requireAuth: true,\r\n });\r\n return toNotification(raw);\r\n },\r\n async list(userId, options) {\r\n if (!userId) throw new NeetruError('validation_failed', 'userId obrigatório');\r\n const params = new URLSearchParams();\r\n if (options?.includeDismissed) params.set('includeDismissed', 'true');\r\n if (options?.onlyUnread) params.set('onlyUnread', 'true');\r\n if (options?.limit) {\r\n params.set('limit', Math.min(Math.max(1, options.limit), 200).toString());\r\n }\r\n const qs = params.toString();\r\n const raw = await httpRequest<{ notifications?: unknown[] }>(config, {\r\n method: 'GET',\r\n path: `/api/sdk/v1/notifications/user/${encodeURIComponent(userId)}${qs ? `?${qs}` : ''}`,\r\n requireAuth: true,\r\n });\r\n const list = Array.isArray(raw?.notifications) ? raw.notifications : [];\r\n return list.map(toNotification);\r\n },\r\n async markRead(id) {\r\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\r\n await httpRequest<unknown>(config, {\r\n method: 'POST',\r\n path: `/api/sdk/v1/notifications/${encodeURIComponent(id)}/read`,\r\n requireAuth: true,\r\n });\r\n return { ok: true };\r\n },\r\n async dismiss(id) {\r\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\r\n await httpRequest<unknown>(config, {\r\n method: 'POST',\r\n path: `/api/sdk/v1/notifications/${encodeURIComponent(id)}/dismiss`,\r\n requireAuth: true,\r\n });\r\n return { ok: true };\r\n },\r\n };\r\n}\r\n\r\n// ─── Mock impl ──────────────────────────────────────────────────────────────\r\n\r\nexport class MockNotifications implements NotificationsNamespace {\r\n private notifications = new Map<string, ProductNotification>();\r\n private nextId = 1;\r\n\r\n async send(input: SendNotificationInput): Promise<ProductNotification> {\r\n validateInput(input);\r\n // Dedup por fingerprint: se já existe um com mesmo fingerprint < 24h, retorna ele.\r\n if (input.fingerprint) {\r\n const dayAgo = Date.now() - 86_400_000;\r\n for (const existing of this.notifications.values()) {\r\n const meta = existing.metadata ?? {};\r\n if (\r\n meta.fingerprint === input.fingerprint &&\r\n existing.userId === input.userId &&\r\n new Date(existing.createdAt).getTime() > dayAgo\r\n ) {\r\n return existing;\r\n }\r\n }\r\n }\r\n const id = `mock_notif_${this.nextId++}`;\r\n const notif: ProductNotification = {\r\n id,\r\n userId: input.userId,\r\n kind: input.kind,\r\n severity: input.severity ?? 'info',\r\n title: input.title,\r\n body: input.body,\r\n link: input.link,\r\n metadata: input.fingerprint\r\n ? { ...(input.metadata ?? {}), fingerprint: input.fingerprint }\r\n : input.metadata,\r\n createdAt: new Date().toISOString(),\r\n };\r\n this.notifications.set(id, notif);\r\n return notif;\r\n }\r\n\r\n async list(\r\n userId: string,\r\n options?: ListNotificationsOptions,\r\n ): Promise<ProductNotification[]> {\r\n if (!userId) throw new NeetruError('validation_failed', 'userId obrigatório');\r\n const limit = Math.min(Math.max(1, options?.limit ?? 50), 200);\r\n return [...this.notifications.values()]\r\n .filter((n) => n.userId === userId)\r\n .filter((n) => options?.includeDismissed || !n.dismissedAt)\r\n .filter((n) => !options?.onlyUnread || !n.readAt)\r\n .sort((a, b) => b.createdAt.localeCompare(a.createdAt))\r\n .slice(0, limit);\r\n }\r\n\r\n async markRead(id: string): Promise<{ ok: true }> {\r\n const n = this.notifications.get(id);\r\n if (!n) throw new NeetruError('not_found', `Notification ${id} não encontrada`);\r\n if (!n.readAt) {\r\n n.readAt = new Date().toISOString();\r\n this.notifications.set(id, n);\r\n }\r\n return { ok: true };\r\n }\r\n\r\n async dismiss(id: string): Promise<{ ok: true }> {\r\n const n = this.notifications.get(id);\r\n if (!n) throw new NeetruError('not_found', `Notification ${id} não encontrada`);\r\n if (!n.dismissedAt) {\r\n n.dismissedAt = new Date().toISOString();\r\n this.notifications.set(id, n);\r\n }\r\n return { ok: true };\r\n }\r\n}\r\n","/**\r\n * Mocks determinísticos do SDK — overridáveis em tests do consumer ou\r\n * ativados automaticamente quando `NEETRU_ENV=dev`.\r\n *\r\n * Nada aqui faz I/O. Tudo é puro/sincrono/in-memory. Compat total com\r\n * runtimes browser/Node/Edge — sem `node:` builtins.\r\n *\r\n * Cada mock implementa o mesmo namespace interface das implementações reais\r\n * (`AuthNamespace`, `UsageNamespace`, `SupportNamespace`) — caller pode\r\n * substituir 1:1 sem branching.\r\n *\r\n * @example\r\n * ```ts\r\n * import { createNeetruClient, MockAuth } from '@neetru/sdk';\r\n *\r\n * const client = createNeetruClient({\r\n * mocks: { auth: new MockAuth({ uid: 'fake-user', email: 'x@x.com' }) },\r\n * });\r\n * ```\r\n */\r\n\r\nimport type {\r\n AuthNamespace,\r\n AuthStateListener,\r\n CreateTicketInput,\r\n EntitlementCheck,\r\n NeetruUser,\r\n SignInOptions,\r\n SupportNamespace,\r\n SupportTicket,\r\n UsageNamespace,\r\n UsageQuota,\r\n} from './types';\r\nimport type {\r\n NeetruDb,\r\n NeetruSqlClient,\r\n} from './db/client-db';\r\nimport type { DbCollectionRef, DbWhereFilter, DbListResult, DbGetResult, DbBatchOp, DbDocRef, DbQuery } from './db/collection-ref';\r\nimport type { SyncState, ConflictRecord, Unsubscribe } from './db/offline/types';\r\nimport { NeetruDbError } from './db-errors';\r\n\r\n// ─── User fixture default ──────────────────────────────────────────────────\r\n\r\n/**\r\n * User fixture determinístico — usado quando `NEETRU_ENV=dev` e nenhum mock\r\n * custom é injetado. Email/uid estáveis pra snapshot tests.\r\n */\r\nexport const DEV_FIXTURE_USER: NeetruUser = Object.freeze({\r\n uid: 'dev-fixture-uid-0001',\r\n email: 'dev@neetru.local',\r\n emailVerified: true,\r\n displayName: 'Dev Fixture',\r\n isCustomer: true,\r\n isStaff: false,\r\n}) as NeetruUser;\r\n\r\n// ─── MockAuth ──────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Implementação in-memory do `AuthNamespace`. signIn marca o user como\r\n * logado; signOut limpa. onAuthStateChanged dispara callback síncrono no\r\n * subscribe + a cada mudança.\r\n */\r\nexport class MockAuth implements AuthNamespace {\r\n private _user: NeetruUser | null;\r\n private _listeners: Set<AuthStateListener>;\r\n\r\n constructor(initialUser: NeetruUser | null = null) {\r\n this._user = initialUser;\r\n this._listeners = new Set();\r\n }\r\n\r\n async signIn(_options?: SignInOptions): Promise<NeetruUser> {\r\n // Mock: apenas marca user como logado (usa fixture se não havia).\r\n if (!this._user) this._user = { ...DEV_FIXTURE_USER };\r\n this._notify();\r\n return this._user;\r\n }\r\n\r\n async signOut(): Promise<void> {\r\n this._user = null;\r\n this._notify();\r\n }\r\n\r\n getUser(): NeetruUser | null {\r\n return this._user;\r\n }\r\n\r\n onAuthStateChanged(listener: AuthStateListener): () => void {\r\n this._listeners.add(listener);\r\n // Dispara imediatamente com estado atual (espelha API Firebase Auth).\r\n try {\r\n listener(this._user);\r\n } catch {\r\n // Callback do consumer não pode quebrar o subscribe.\r\n }\r\n return () => {\r\n this._listeners.delete(listener);\r\n };\r\n }\r\n\r\n /** Helper de tests — força um user state arbitrário. */\r\n __setUser(user: NeetruUser | null): void {\r\n this._user = user;\r\n this._notify();\r\n }\r\n\r\n private _notify(): void {\r\n for (const l of this._listeners) {\r\n try {\r\n l(this._user);\r\n } catch {\r\n // ignore consumer errors\r\n }\r\n }\r\n }\r\n}\r\n\r\n// ─── MockUsage ─────────────────────────────────────────────────────────────\r\n\r\ninterface UsageRecord {\r\n event: string;\r\n properties?: Record<string, string | number | boolean | null>;\r\n timestamp: string;\r\n}\r\n\r\n/**\r\n * In-memory `UsageNamespace`. `track()` apenas acumula no array\r\n * `__getRecords()` (útil pra asserts em test). `getQuota()` retorna fixture\r\n * com `used = trackedCount` da metric.\r\n */\r\nexport class MockUsage implements UsageNamespace {\r\n private _records: UsageRecord[] = [];\r\n private _quotas: Map<string, UsageQuota>;\r\n /** v0.3 — counters in-memory pra `report()` / `check()`. */\r\n private _counters: Map<string, number> = new Map();\r\n\r\n constructor(initialQuotas: Record<string, UsageQuota> = {}) {\r\n this._quotas = new Map(Object.entries(initialQuotas));\r\n }\r\n\r\n async track(\r\n event: string,\r\n properties?: Record<string, string | number | boolean | null>,\r\n ): Promise<{ ok: true }> {\r\n this._records.push({\r\n event,\r\n properties,\r\n timestamp: new Date().toISOString(),\r\n });\r\n return { ok: true };\r\n }\r\n\r\n async getQuota(metric: string): Promise<UsageQuota> {\r\n const existing = this._quotas.get(metric);\r\n if (existing) return existing;\r\n return {\r\n metric,\r\n used: this._records.filter((r) => r.event === metric).length,\r\n limit: -1, // unlimited em mock por default\r\n plan: 'mock',\r\n };\r\n }\r\n\r\n /** v0.3 — Mock report incrementa o counter local. */\r\n async report(\r\n resource: string,\r\n qty: number = 1,\r\n _options?: { productId?: string; tenantId?: string },\r\n ): Promise<{\r\n ok: true;\r\n counterId?: string;\r\n value?: number;\r\n limit?: number;\r\n remaining?: number;\r\n status?: string;\r\n }> {\r\n if (!resource) throw new Error('resource required');\r\n const safeQty = Number.isFinite(qty) && qty > 0 ? Math.floor(qty) : 1;\r\n const existing = this._counters.get(resource) ?? 0;\r\n const next = existing + safeQty;\r\n this._counters.set(resource, next);\r\n const limitFixture = this._quotas.get(resource);\r\n const limit = limitFixture?.limit ?? -1;\r\n return {\r\n ok: true,\r\n counterId: `mock_${resource}`,\r\n value: next,\r\n limit,\r\n remaining: limit < 0 ? -1 : Math.max(0, limit - next),\r\n status: limit > 0 && next >= limit ? 'read_only_overlimit' : 'ok',\r\n };\r\n }\r\n\r\n /** v0.3 — Mock check usa quotas + counters in-memory. */\r\n async check(\r\n resource: string,\r\n _options?: { productId?: string; tenantId?: string },\r\n ): Promise<{\r\n allowed: boolean;\r\n reason?: string;\r\n remaining?: number;\r\n limit?: number;\r\n planId?: string | null;\r\n planFeatures?: string[];\r\n }> {\r\n const quota = this._quotas.get(resource);\r\n const used = this._counters.get(resource) ?? 0;\r\n if (!quota) {\r\n return { allowed: true, reason: 'granted', limit: -1, remaining: -1 };\r\n }\r\n const remaining = quota.limit < 0 ? -1 : Math.max(0, quota.limit - used);\r\n if (remaining === 0) {\r\n return {\r\n allowed: false,\r\n reason: 'limit_exceeded',\r\n limit: quota.limit,\r\n remaining: 0,\r\n };\r\n }\r\n return {\r\n allowed: true,\r\n reason: 'granted',\r\n limit: quota.limit,\r\n remaining,\r\n };\r\n }\r\n\r\n /** Test helper. */\r\n __getRecords(): readonly UsageRecord[] {\r\n return [...this._records];\r\n }\r\n /** Test helper — substitui quota fixture. */\r\n __setQuota(metric: string, quota: UsageQuota): void {\r\n this._quotas.set(metric, quota);\r\n }\r\n /** Test helper — limpa estado. */\r\n __reset(): void {\r\n this._records = [];\r\n this._quotas.clear();\r\n this._counters.clear();\r\n }\r\n}\r\n\r\n// ─── MockSupport ───────────────────────────────────────────────────────────\r\n\r\n/**\r\n * In-memory `SupportNamespace`. createTicket gera ID `mock-ticket-{n}`;\r\n * listMyTickets retorna todos criados (FIFO). Sequência por instância\r\n * (evita poluição cross-test do estado de módulo).\r\n */\r\nexport class MockSupport implements SupportNamespace {\r\n private _tickets: SupportTicket[] = [];\r\n private _ticketSeq = 0;\r\n\r\n async createTicket(input: CreateTicketInput): Promise<SupportTicket> {\r\n if (!input?.subject) throw new Error('subject required');\r\n if (!input?.message) throw new Error('message required');\r\n const ticket: SupportTicket = {\r\n id: `mock-ticket-${++this._ticketSeq}`,\r\n subject: input.subject,\r\n message: input.message,\r\n severity: input.severity ?? 'normal',\r\n status: 'open',\r\n createdAt: new Date().toISOString(),\r\n productSlug: input.productSlug,\r\n };\r\n this._tickets.push(ticket);\r\n return ticket;\r\n }\r\n\r\n async listMyTickets(): Promise<SupportTicket[]> {\r\n return [...this._tickets];\r\n }\r\n\r\n /** Test helper. */\r\n __reset(): void {\r\n this._tickets = [];\r\n this._ticketSeq = 0;\r\n }\r\n}\r\n\r\n// ─── MockEntitlements ──────────────────────────────────────────────────────\r\n\r\n/**\r\n * In-memory entitlements. Por default `allowed=true` em tudo (dev convém).\r\n * Use `__deny(slug, feature)` em tests pra simular bloqueio.\r\n */\r\nexport class MockEntitlements {\r\n private _denied: Set<string> = new Set();\r\n\r\n async check(productSlug: string, feature: string): Promise<boolean> {\r\n return !this._denied.has(`${productSlug}:${feature}`);\r\n }\r\n\r\n async checkDetailed(productSlug: string, feature: string): Promise<EntitlementCheck> {\r\n const allowed = await this.check(productSlug, feature);\r\n return {\r\n allowed,\r\n productSlug,\r\n feature,\r\n reason: allowed ? 'granted' : 'mock_denied',\r\n };\r\n }\r\n\r\n /** Test helper. */\r\n __deny(productSlug: string, feature: string): void {\r\n this._denied.add(`${productSlug}:${feature}`);\r\n }\r\n /** Test helper. */\r\n __reset(): void {\r\n this._denied.clear();\r\n }\r\n}\r\n\r\n// ─── MockDb (v2.0) ─────────────────────────────────────────────────────────\r\n\r\n/**\r\n * In-memory `NeetruDb`. Cada `collection(name)` aponta para um Map; ops\r\n * são totalmente síncronas (mas API await-friendly).\r\n *\r\n * v2.0: implementa a interface `NeetruDb` completa (collection, sql, syncState,\r\n * flush, clearCache, getConflicts, onSyncStateChanged).\r\n *\r\n * Útil para testar produtos consumidores sem rodar Core REST nem IndexedDB.\r\n */\r\nexport class MockDb implements NeetruDb {\r\n private _store: Map<string, Map<string, Record<string, unknown>>> = new Map();\r\n private _fixtures: Map<string, Record<string, Record<string, unknown>>>;\r\n\r\n constructor(initialFixtures: Record<string, Record<string, Record<string, unknown>>> = {}) {\r\n this._fixtures = new Map(Object.entries(initialFixtures));\r\n }\r\n\r\n collection<T = Record<string, unknown>>(name: string): DbCollectionRef<T> {\r\n const _store = this._store;\r\n const _fixtures = this._fixtures;\r\n if (!_store.has(name)) {\r\n const init = _fixtures.get(name);\r\n _store.set(\r\n name,\r\n init ? new Map(Object.entries(init)) : new Map(),\r\n );\r\n }\r\n const coll = _store.get(name)!;\r\n\r\n const matchesFilter = (\r\n doc: Record<string, unknown>,\r\n f: DbWhereFilter,\r\n ): boolean => {\r\n const v = doc[f.field];\r\n switch (f.op) {\r\n case '==':\r\n return v === f.value;\r\n case '!=':\r\n return v !== f.value;\r\n case '<':\r\n return typeof v === 'number' && typeof f.value === 'number' && v < f.value;\r\n case '<=':\r\n return typeof v === 'number' && typeof f.value === 'number' && v <= f.value;\r\n case '>':\r\n return typeof v === 'number' && typeof f.value === 'number' && v > f.value;\r\n case '>=':\r\n return typeof v === 'number' && typeof f.value === 'number' && v >= f.value;\r\n case 'in':\r\n return Array.isArray(f.value) && (f.value as unknown[]).includes(v);\r\n case 'array-contains':\r\n return Array.isArray(v) && (v as unknown[]).includes(f.value);\r\n case 'not-in':\r\n return Array.isArray(f.value) && !(f.value as unknown[]).includes(v);\r\n default:\r\n return true;\r\n }\r\n };\r\n\r\n let autoSeq = 0;\r\n\r\n // Helper to build a minimal DbListResult from raw items\r\n function buildListResult<U>(items: Array<Record<string, unknown>>): DbListResult<U> {\r\n return {\r\n docs: items.map((d, i) => ({ id: (d.id as string) ?? String(i), data: d as U })),\r\n nextCursor: null,\r\n fromCache: false,\r\n stale: false,\r\n hasPendingWrites: false,\r\n changes: [],\r\n };\r\n }\r\n\r\n // Helper to build a DbGetResult for a single doc\r\n function buildGetResult<U>(data: Record<string, unknown>, id: string): DbGetResult<U> {\r\n return {\r\n docs: [{ id, data: data as U }],\r\n fromCache: false,\r\n stale: false,\r\n hasPendingWrites: false,\r\n changes: [],\r\n };\r\n }\r\n\r\n const ref: DbCollectionRef<T> = {\r\n async list(q?: DbQuery): Promise<DbListResult<T>> {\r\n let items = Array.from(coll.values());\r\n if (q?.where && q.where.length > 0) {\r\n items = items.filter((doc) =>\r\n (q.where as DbWhereFilter[]).every((f) => matchesFilter(doc, f)),\r\n );\r\n }\r\n if (q?.orderBy) {\r\n const { field, direction } = q.orderBy;\r\n items = items.slice().sort((a, b) => {\r\n const av = a[field];\r\n const bv = b[field];\r\n const avs = av ?? '';\r\n const bvs = bv ?? '';\r\n const cmp = (avs as string) < (bvs as string) ? -1 : (avs as string) > (bvs as string) ? 1 : 0;\r\n return direction === 'desc' ? -cmp : cmp;\r\n });\r\n }\r\n const limit = q?.limit ?? 20;\r\n items = items.slice(0, limit);\r\n return buildListResult<T>(items);\r\n },\r\n async get(id: string): Promise<DbGetResult<T> | null> {\r\n const data = coll.get(id);\r\n if (!data) return null;\r\n return buildGetResult<T>(data, id);\r\n },\r\n async add(data: Omit<T, 'id'>): Promise<{ ok: true; id: string }> {\r\n const id = `mock-${++autoSeq}-${Math.random().toString(36).slice(2, 8)}`;\r\n coll.set(id, { ...(data as Record<string, unknown>), id });\r\n return { ok: true, id };\r\n },\r\n async set(id: string, data: Omit<T, 'id'>): Promise<{ ok: true }> {\r\n coll.set(id, { ...(data as Record<string, unknown>), id });\r\n return { ok: true };\r\n },\r\n async update(id: string, data: Partial<Omit<T, 'id'>>): Promise<{ ok: true }> {\r\n const cur = coll.get(id);\r\n if (!cur) {\r\n coll.set(id, { ...(data as Record<string, unknown>), id });\r\n } else {\r\n coll.set(id, { ...cur, ...(data as Record<string, unknown>) });\r\n }\r\n return { ok: true };\r\n },\r\n async remove(id: string): Promise<{ ok: true }> {\r\n coll.delete(id);\r\n return { ok: true };\r\n },\r\n async batch(ops: DbBatchOp[]): Promise<{ ok: true }> {\r\n for (const op of ops) {\r\n const collMap = (() => {\r\n if (!_store.has(op.collection)) _store.set(op.collection, new Map());\r\n return _store.get(op.collection)!;\r\n })();\r\n const id = op.id ?? `mock-batch-${++autoSeq}`;\r\n if (op.op === 'add') {\r\n collMap.set(id, { ...(op.data ?? {}), id });\r\n } else if (op.op === 'set') {\r\n collMap.set(id, { ...(op.data ?? {}), id });\r\n } else if (op.op === 'update') {\r\n const cur = collMap.get(id);\r\n collMap.set(id, { ...(cur ?? {}), ...(op.data ?? {}), id });\r\n } else if (op.op === 'remove') {\r\n collMap.delete(id);\r\n }\r\n }\r\n return { ok: true };\r\n },\r\n onDoc(id: string, cb: (doc: T | null) => void): Unsubscribe {\r\n // Entrega snapshot inicial imediato (sync mock)\r\n const data = coll.get(id);\r\n Promise.resolve().then(() => cb(data ? (data as T) : null));\r\n // Mock: não há feed realtime — retorna no-op unsubscribe\r\n return () => {};\r\n },\r\n onSnapshot(q: DbQuery | undefined, cb: (snap: DbListResult<T>) => void): Unsubscribe {\r\n // Entrega snapshot inicial imediato (sync mock)\r\n Promise.resolve().then(async () => {\r\n const snap = await ref.list(q);\r\n cb(snap);\r\n });\r\n return () => {};\r\n },\r\n doc(id: string): DbDocRef<T> {\r\n return {\r\n async get() {\r\n const data = coll.get(id);\r\n if (!data) return null;\r\n return buildGetResult<T>(data, id);\r\n },\r\n async set(data: Omit<T, 'id'>) {\r\n coll.set(id, { ...(data as Record<string, unknown>), id });\r\n return { ok: true };\r\n },\r\n async update(data: Partial<Omit<T, 'id'>>) {\r\n const cur = coll.get(id);\r\n if (!cur) {\r\n coll.set(id, { ...(data as Record<string, unknown>), id });\r\n } else {\r\n coll.set(id, { ...cur, ...(data as Record<string, unknown>) });\r\n }\r\n return { ok: true };\r\n },\r\n async remove() {\r\n coll.delete(id);\r\n return { ok: true };\r\n },\r\n onSnapshot(cb: (snap: DbGetResult<T> | null) => void): Unsubscribe {\r\n const data = coll.get(id);\r\n Promise.resolve().then(() =>\r\n cb(data ? buildGetResult<T>(data, id) : null),\r\n );\r\n return () => {};\r\n },\r\n };\r\n },\r\n };\r\n\r\n return ref;\r\n }\r\n\r\n async sql<TSchema extends Record<string, unknown>>(\r\n _schema: TSchema,\r\n ): Promise<NeetruSqlClient<TSchema>> {\r\n throw new NeetruDbError(\r\n 'db_unavailable',\r\n '[MockDb] sql() não disponível no mock. Use createNeetruClient({ env: \"dev\" }) e `neetru dev` para o banco local.',\r\n );\r\n }\r\n\r\n get syncState(): SyncState {\r\n return {\r\n status: 'idle',\r\n pendingWrites: 0,\r\n lastSyncedAt: null,\r\n isLeaderTab: true,\r\n };\r\n }\r\n\r\n onSyncStateChanged(_cb: (s: SyncState) => void): Unsubscribe {\r\n return () => {};\r\n }\r\n\r\n async flush(): Promise<void> {\r\n // no-op in mock\r\n }\r\n\r\n async clearCache(): Promise<void> {\r\n this._store.clear();\r\n }\r\n\r\n async getConflicts(): Promise<ConflictRecord[]> {\r\n return [];\r\n }\r\n\r\n /** Test helper — substitui fixture inteira de uma collection. */\r\n __setFixture(name: string, items: Record<string, Record<string, unknown>>): void {\r\n this._store.set(name, new Map(Object.entries(items)));\r\n }\r\n\r\n /** Test helper — reset total. */\r\n __reset(): void {\r\n this._store.clear();\r\n }\r\n}\r\n","/**\r\n * @neetru/sdk — biblioteca runtime para consumir o ecossistema Neetru.\r\n *\r\n * **v1.0.0 GA (2026-05-06)** — superfície pública estabilizada. A partir\r\n * desta versão, **breaking changes só em majors** (semver estrito).\r\n *\r\n * Namespaces estáveis (v1.0):\r\n * - `auth` — OIDC sign-in / sign-out + dev fixture user.\r\n * - `catalog` — produtos públicos (`list` / `get`).\r\n * - `entitlements` — verificação `(productSlug, feature)` → boolean / detalhado.\r\n * - `telemetry` — `event(...)` + `log(...)` per-product (Sprint 6).\r\n * - `usage` — `track` / `getQuota` / `report` / `check` (Sprint 7 metering canônico).\r\n * - `support` — `createTicket` / `listMyTickets`.\r\n * - `db` — coleções tenant-scoped (`list` / `get` / `set` / `add` / `update` / `remove`).\r\n *\r\n * Princípios:\r\n * - Vendor-neutral: a superfície pública não vaza Firebase/Stripe.\r\n * - Tree-shakable: ESM-first, sem side effects.\r\n * - Universal: funciona em browser, Node ≥18, Edge runtimes (usa fetch global).\r\n * - Erros tipados via NeetruError com .code / .status / .requestId.\r\n * - Dev mode: `NEETRU_ENV=dev` ativa mocks automáticos (auth fixture user,\r\n * usage in-memory, support fake list, db in-memory).\r\n *\r\n * Migration v0.3 → v1.0:\r\n * - Nenhuma breaking change. APIs v0.3 permanecem 100% compatíveis em v1.0.\r\n * - `initNeetru` (deprecated desde v0.2) **continua** funcionando em v1.0 mas\r\n * será removido em v2.0. Use `createNeetruClient` em código novo.\r\n *\r\n * Roadmap completo em `docs/PLAN_SDK_NEETRU.md` §10.\r\n */\r\n\r\n// ─── v0.2 API principal ──────────────────────────────────────────────────────\r\nexport { createNeetruClient } from './auth';\r\nexport { NeetruError, type NeetruErrorCode } from './errors';\r\nexport { NeetruDbError, type NeetruDbErrorCode } from './db-errors';\r\nexport type {\r\n NeetruClient,\r\n NeetruClientConfig,\r\n ResolvedConfig,\r\n Product,\r\n ProductPlan,\r\n ProductStatus,\r\n CatalogListOptions,\r\n CatalogListResponse,\r\n EntitlementCheck,\r\n TelemetryEventInput,\r\n TelemetryEventAck,\r\n // v0.2\r\n AuthNamespace,\r\n AuthStateListener,\r\n CreateTicketInput,\r\n NeetruEnv,\r\n NeetruUser,\r\n SignInOptions,\r\n SupportNamespace,\r\n SupportSeverity,\r\n SupportStatus,\r\n SupportTicket,\r\n UsageEventInput,\r\n UsageNamespace,\r\n UsageQuota,\r\n // v0.3 (legado — DbNamespace mantido por compat de importação)\r\n DbNamespace,\r\n DbWhereFilter,\r\n} from './types';\r\nexport { DEFAULT_BASE_URL } from './types';\r\n\r\n// ─── v2.0 — db namespace público ─────────────────────────────────────────────\r\nexport type {\r\n NeetruDb,\r\n NeetruDbEngine,\r\n NeetruDbOptions,\r\n NeetruSqlClient,\r\n DbSqlLease,\r\n} from './db/client-db';\r\nexport type {\r\n DbCollectionRef,\r\n DbDocRef,\r\n DbQuery,\r\n DbDoc,\r\n DbListResult,\r\n DbGetResult,\r\n DbBatchOp,\r\n DbChangeType,\r\n} from './db/collection-ref';\r\nexport { createNeetruDb } from './db/client-db';\r\n\r\n// ─── v0.2 — Mocks (overridáveis) ────────────────────────────────────────────\r\nexport {\r\n MockAuth,\r\n MockUsage,\r\n MockSupport,\r\n MockEntitlements,\r\n MockDb,\r\n DEV_FIXTURE_USER,\r\n} from './mocks';\r\n\r\n// ─── v1.1 — Checkout namespace ──────────────────────────────────────────────\r\nexport {\r\n MockCheckout,\r\n createCheckoutNamespace,\r\n type CheckoutNamespace,\r\n type CheckoutStartInput,\r\n type CheckoutStartResult,\r\n type CheckoutIntentInfo,\r\n type CheckoutIntentStatus,\r\n type CheckoutTenantType,\r\n} from './checkout';\r\n\r\n// ─── v1.2 — Webhooks namespace (outbound events Core → produto) ─────────────\r\nexport {\r\n MockWebhooks,\r\n createWebhooksNamespace,\r\n type WebhooksNamespace,\r\n type WebhookEvent,\r\n type WebhookEndpoint,\r\n type RegisterWebhookInput,\r\n type WebhookTestResult,\r\n} from './webhooks';\r\n\r\n// ─── v1.2 — Notifications namespace (produto → user) ────────────────────────\r\nexport {\r\n MockNotifications,\r\n createNotificationsNamespace,\r\n type NotificationsNamespace,\r\n type ProductNotification,\r\n type ProductNotificationSeverity,\r\n type SendNotificationInput,\r\n type ListNotificationsOptions,\r\n} from './notifications';\r\n\r\n// ─── Versão pinada ────────────────────────────────────────────────────────────\r\n/** Versão do SDK — exportada explicitamente pra detecção em runtime. */\r\nexport const VERSION = '2.0.0' as const;\r\n\r\n// ─── Compat v0.0.1 — REMOVIDO em v2.0.0 ────────────────────────────────────\r\n// `initNeetru` foi marcado `@deprecated` desde v0.2 e removido em v2.0.0\r\n// conforme prometido no JSDoc. Use `createNeetruClient` em código novo.\r\n//\r\n// `NeetruConfig` alias também removido — use `NeetruClientConfig`.\r\nimport { createNeetruClient } from './auth';\r\nimport type { NeetruClientConfig } from './types';\r\n\r\n/**\r\n * @deprecated REMOVIDO em v2.0.0. Use `createNeetruClient`.\r\n *\r\n * Este stub mantém compatibilidade com código que ainda importa `initNeetru`\r\n * mas lança erro em runtime para forçar a migração.\r\n *\r\n * **Migração:** substitua `initNeetru(config)` por `createNeetruClient(config)`.\r\n */\r\nexport function initNeetru(config: NeetruClientConfig & { apiUrl?: string }) {\r\n // Mantemos o stub funcional (não lança) para não quebrar builds que importam\r\n // mas não chamam. Código que chama receberá o client normalmente — o\r\n // breaking change real é que `apiUrl` como alias de `baseUrl` não é mais mapeado.\r\n const { apiUrl: _apiUrl, baseUrl, ...rest } = config;\r\n return createNeetruClient({ ...rest, baseUrl });\r\n}\r\n\r\n/**\r\n * @deprecated REMOVIDO em v2.0.0. Use `NeetruClientConfig`.\r\n */\r\nexport type NeetruConfig = NeetruClientConfig & { apiUrl?: string };\r\n"]}
|