@neetru/sdk 1.1.0 → 1.2.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 +33 -3
- package/README.md +135 -159
- package/dist/auth.cjs +486 -40
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.mjs +486 -40
- package/dist/auth.mjs.map +1 -1
- package/dist/catalog.cjs +64 -21
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +2 -2
- package/dist/catalog.d.ts +2 -2
- package/dist/catalog.mjs +64 -21
- package/dist/catalog.mjs.map +1 -1
- package/dist/checkout.cjs +61 -15
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/checkout.mjs +61 -15
- package/dist/checkout.mjs.map +1 -1
- package/dist/db.cjs +67 -22
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.mjs +67 -22
- package/dist/db.mjs.map +1 -1
- package/dist/entitlements.cjs +102 -21
- package/dist/entitlements.cjs.map +1 -1
- package/dist/entitlements.d.cts +11 -5
- package/dist/entitlements.d.ts +11 -5
- package/dist/entitlements.mjs +102 -21
- package/dist/entitlements.mjs.map +1 -1
- package/dist/index.cjs +491 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +488 -42
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.cjs +3 -2
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.cts +4 -2
- package/dist/mocks.d.ts +4 -2
- package/dist/mocks.mjs +3 -2
- package/dist/mocks.mjs.map +1 -1
- package/dist/notifications.cjs +296 -0
- package/dist/notifications.cjs.map +1 -0
- package/dist/notifications.d.cts +1 -0
- package/dist/notifications.d.ts +1 -0
- package/dist/notifications.mjs +293 -0
- package/dist/notifications.mjs.map +1 -0
- package/dist/react.cjs +7 -3
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.mjs +7 -3
- package/dist/react.mjs.map +1 -1
- package/dist/support.cjs +61 -15
- package/dist/support.cjs.map +1 -1
- package/dist/support.d.cts +1 -1
- package/dist/support.d.ts +1 -1
- package/dist/support.mjs +61 -15
- package/dist/support.mjs.map +1 -1
- package/dist/telemetry.cjs +131 -16
- package/dist/telemetry.cjs.map +1 -1
- package/dist/telemetry.d.cts +17 -1
- package/dist/telemetry.d.ts +17 -1
- package/dist/telemetry.mjs +131 -16
- package/dist/telemetry.mjs.map +1 -1
- package/dist/{types-BA53dd8S.d.cts → types-CQAfwqUS.d.cts} +172 -8
- package/dist/{types-BA53dd8S.d.ts → types-CQAfwqUS.d.ts} +172 -8
- package/dist/usage.cjs +61 -15
- package/dist/usage.cjs.map +1 -1
- package/dist/usage.d.cts +1 -1
- package/dist/usage.d.ts +1 -1
- package/dist/usage.mjs +61 -15
- package/dist/usage.mjs.map +1 -1
- package/dist/webhooks.cjs +316 -0
- package/dist/webhooks.cjs.map +1 -0
- package/dist/webhooks.d.cts +1 -0
- package/dist/webhooks.d.ts +1 -0
- package/dist/webhooks.mjs +312 -0
- package/dist/webhooks.mjs.map +1 -0
- package/package.json +22 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/notifications.ts"],"names":["err","message"],"mappings":"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","file":"notifications.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 * 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 * 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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { L as ListNotificationsOptions, o as MockNotifications, s as NotificationsNamespace, t as ProductNotification, u as ProductNotificationSeverity, S as SendNotificationInput, X as createNotificationsNamespace } from './types-CQAfwqUS.cjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { L as ListNotificationsOptions, o as MockNotifications, s as NotificationsNamespace, t as ProductNotification, u as ProductNotificationSeverity, S as SendNotificationInput, X as createNotificationsNamespace } from './types-CQAfwqUS.js';
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var NeetruError = class _NeetruError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
status;
|
|
5
|
+
requestId;
|
|
6
|
+
constructor(code, message, status, requestId) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "NeetruError";
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.requestId = requestId;
|
|
12
|
+
Object.setPrototypeOf(this, _NeetruError.prototype);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// src/http.ts
|
|
17
|
+
var DEFAULT_RETRIES = 2;
|
|
18
|
+
var RETRYABLE_CODES = /* @__PURE__ */ new Set([
|
|
19
|
+
"rate_limited",
|
|
20
|
+
"server_error",
|
|
21
|
+
"network_error"
|
|
22
|
+
]);
|
|
23
|
+
function backoffMs(attempt) {
|
|
24
|
+
const base = 200 * Math.pow(4, attempt);
|
|
25
|
+
const jitter = base * 0.2 * (Math.random() * 2 - 1);
|
|
26
|
+
return Math.max(50, Math.round(base + jitter));
|
|
27
|
+
}
|
|
28
|
+
function parseRetryAfter(value) {
|
|
29
|
+
if (!value) return null;
|
|
30
|
+
const secs = Number(value);
|
|
31
|
+
if (Number.isFinite(secs) && secs >= 0) return Math.round(secs * 1e3);
|
|
32
|
+
const dateMs = Date.parse(value);
|
|
33
|
+
if (Number.isFinite(dateMs)) {
|
|
34
|
+
const delta = dateMs - Date.now();
|
|
35
|
+
if (delta > 0) return delta;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
function sleep(ms) {
|
|
40
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
41
|
+
}
|
|
42
|
+
function statusToCode(status) {
|
|
43
|
+
if (status === 401) return "unauthorized";
|
|
44
|
+
if (status === 403) return "forbidden";
|
|
45
|
+
if (status === 404) return "not_found";
|
|
46
|
+
if (status === 422 || status === 400) return "validation_failed";
|
|
47
|
+
if (status === 429) return "rate_limited";
|
|
48
|
+
if (status >= 500) return "server_error";
|
|
49
|
+
return "unknown";
|
|
50
|
+
}
|
|
51
|
+
function buildUrl(baseUrl, path, query) {
|
|
52
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
53
|
+
const p = path.startsWith("/") ? path : `/${path}`;
|
|
54
|
+
const url = new URL(`${base}${p}`);
|
|
55
|
+
if (query) {
|
|
56
|
+
for (const [k, v] of Object.entries(query)) {
|
|
57
|
+
if (v === void 0) continue;
|
|
58
|
+
url.searchParams.set(k, String(v));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return url.toString();
|
|
62
|
+
}
|
|
63
|
+
async function safeJson(res) {
|
|
64
|
+
const text = await res.text();
|
|
65
|
+
if (!text) return void 0;
|
|
66
|
+
try {
|
|
67
|
+
return JSON.parse(text);
|
|
68
|
+
} catch {
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function httpRequest(config, opts) {
|
|
73
|
+
const method = opts.method ?? "GET";
|
|
74
|
+
const url = buildUrl(config.baseUrl, opts.path, opts.query);
|
|
75
|
+
const maxRetries = opts.retries ?? DEFAULT_RETRIES;
|
|
76
|
+
const headers = {
|
|
77
|
+
accept: "application/json",
|
|
78
|
+
...opts.headers
|
|
79
|
+
};
|
|
80
|
+
if (opts.requireAuth) {
|
|
81
|
+
if (!config.apiKey) {
|
|
82
|
+
throw new NeetruError(
|
|
83
|
+
"missing_api_key",
|
|
84
|
+
"This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var."
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
headers.authorization = `Bearer ${config.apiKey}`;
|
|
88
|
+
}
|
|
89
|
+
const bodyString = opts.body !== void 0 && method !== "GET" && method !== "DELETE" ? JSON.stringify(opts.body) : void 0;
|
|
90
|
+
if (bodyString !== void 0) {
|
|
91
|
+
headers["content-type"] = "application/json";
|
|
92
|
+
}
|
|
93
|
+
let lastError = null;
|
|
94
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
95
|
+
const init = { method, headers };
|
|
96
|
+
if (bodyString !== void 0) init.body = bodyString;
|
|
97
|
+
init.signal = AbortSignal.timeout(3e4);
|
|
98
|
+
let res;
|
|
99
|
+
try {
|
|
100
|
+
res = await config.fetch(url, init);
|
|
101
|
+
} catch (err2) {
|
|
102
|
+
const message2 = err2 instanceof DOMException && err2.name === "TimeoutError" ? "Network error: timeout after 30s" : `Network error: ${err2 instanceof Error ? err2.message : "fetch failed"}`;
|
|
103
|
+
lastError = new NeetruError("network_error", message2);
|
|
104
|
+
if (attempt < maxRetries) {
|
|
105
|
+
await sleep(backoffMs(attempt));
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
throw lastError;
|
|
109
|
+
}
|
|
110
|
+
const requestId = res.headers.get("x-request-id") ?? res.headers.get("x-correlation-id") ?? void 0;
|
|
111
|
+
if (res.ok) {
|
|
112
|
+
const parsed = await safeJson(res);
|
|
113
|
+
return parsed;
|
|
114
|
+
}
|
|
115
|
+
const body = await safeJson(res);
|
|
116
|
+
let code = statusToCode(res.status);
|
|
117
|
+
let message = `HTTP ${res.status}`;
|
|
118
|
+
if (body && typeof body === "object" && "error" in body) {
|
|
119
|
+
const errField = body.error;
|
|
120
|
+
if (typeof errField === "string") {
|
|
121
|
+
message = errField;
|
|
122
|
+
} else if (errField && typeof errField === "object") {
|
|
123
|
+
if (typeof errField.code === "string") code = errField.code;
|
|
124
|
+
if (typeof errField.message === "string") message = errField.message;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const err = new NeetruError(code, message, res.status, requestId);
|
|
128
|
+
lastError = err;
|
|
129
|
+
const isRetryable = RETRYABLE_CODES.has(code);
|
|
130
|
+
if (isRetryable && attempt < maxRetries) {
|
|
131
|
+
const retryAfter = parseRetryAfter(res.headers.get("retry-after"));
|
|
132
|
+
const delay = retryAfter ?? backoffMs(attempt);
|
|
133
|
+
await sleep(delay);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
throw err;
|
|
137
|
+
}
|
|
138
|
+
throw lastError ?? new NeetruError("unknown", "unexpected httpRequest exit");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/notifications.ts
|
|
142
|
+
var VALID_SEVERITIES = [
|
|
143
|
+
"info",
|
|
144
|
+
"success",
|
|
145
|
+
"warning",
|
|
146
|
+
"error"
|
|
147
|
+
];
|
|
148
|
+
function toNotification(raw) {
|
|
149
|
+
if (!raw || typeof raw !== "object") {
|
|
150
|
+
throw new NeetruError("invalid_response", "Notification response is not an object");
|
|
151
|
+
}
|
|
152
|
+
const r = raw;
|
|
153
|
+
if (typeof r.id !== "string") {
|
|
154
|
+
throw new NeetruError("invalid_response", "Notification missing id");
|
|
155
|
+
}
|
|
156
|
+
const sev = VALID_SEVERITIES.includes(r.severity) ? r.severity : "info";
|
|
157
|
+
return {
|
|
158
|
+
id: r.id,
|
|
159
|
+
userId: typeof r.userId === "string" ? r.userId : "",
|
|
160
|
+
kind: typeof r.kind === "string" ? r.kind : "unknown",
|
|
161
|
+
severity: sev,
|
|
162
|
+
title: typeof r.title === "string" ? r.title : "",
|
|
163
|
+
body: typeof r.body === "string" ? r.body : void 0,
|
|
164
|
+
link: typeof r.link === "string" ? r.link : void 0,
|
|
165
|
+
metadata: r.metadata && typeof r.metadata === "object" ? r.metadata : void 0,
|
|
166
|
+
createdAt: typeof r.createdAt === "string" ? r.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
167
|
+
readAt: typeof r.readAt === "string" ? r.readAt : void 0,
|
|
168
|
+
dismissedAt: typeof r.dismissedAt === "string" ? r.dismissedAt : void 0
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function validateInput(input) {
|
|
172
|
+
if (!input.userId) throw new NeetruError("validation_failed", "userId obrigat\xF3rio");
|
|
173
|
+
if (!input.kind) throw new NeetruError("validation_failed", "kind obrigat\xF3rio");
|
|
174
|
+
if (!input.title) throw new NeetruError("validation_failed", "title obrigat\xF3rio");
|
|
175
|
+
if (input.severity && !VALID_SEVERITIES.includes(input.severity)) {
|
|
176
|
+
throw new NeetruError(
|
|
177
|
+
"validation_failed",
|
|
178
|
+
`severity inv\xE1lida: ${input.severity} (use ${VALID_SEVERITIES.join("|")})`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
if (input.title.length > 200) {
|
|
182
|
+
throw new NeetruError("validation_failed", "title m\xE1x 200 chars");
|
|
183
|
+
}
|
|
184
|
+
if (input.body && input.body.length > 2e3) {
|
|
185
|
+
throw new NeetruError("validation_failed", "body m\xE1x 2000 chars");
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function createNotificationsNamespace(config) {
|
|
189
|
+
return {
|
|
190
|
+
async send(input) {
|
|
191
|
+
validateInput(input);
|
|
192
|
+
const raw = await httpRequest(config, {
|
|
193
|
+
method: "POST",
|
|
194
|
+
path: "/api/sdk/v1/notifications",
|
|
195
|
+
body: input,
|
|
196
|
+
requireAuth: true
|
|
197
|
+
});
|
|
198
|
+
return toNotification(raw);
|
|
199
|
+
},
|
|
200
|
+
async list(userId, options) {
|
|
201
|
+
if (!userId) throw new NeetruError("validation_failed", "userId obrigat\xF3rio");
|
|
202
|
+
const params = new URLSearchParams();
|
|
203
|
+
if (options?.includeDismissed) params.set("includeDismissed", "true");
|
|
204
|
+
if (options?.onlyUnread) params.set("onlyUnread", "true");
|
|
205
|
+
if (options?.limit) {
|
|
206
|
+
params.set("limit", Math.min(Math.max(1, options.limit), 200).toString());
|
|
207
|
+
}
|
|
208
|
+
const qs = params.toString();
|
|
209
|
+
const raw = await httpRequest(config, {
|
|
210
|
+
method: "GET",
|
|
211
|
+
path: `/api/sdk/v1/notifications/user/${encodeURIComponent(userId)}${qs ? `?${qs}` : ""}`,
|
|
212
|
+
requireAuth: true
|
|
213
|
+
});
|
|
214
|
+
const list = Array.isArray(raw?.notifications) ? raw.notifications : [];
|
|
215
|
+
return list.map(toNotification);
|
|
216
|
+
},
|
|
217
|
+
async markRead(id) {
|
|
218
|
+
if (!id) throw new NeetruError("validation_failed", "id obrigat\xF3rio");
|
|
219
|
+
await httpRequest(config, {
|
|
220
|
+
method: "POST",
|
|
221
|
+
path: `/api/sdk/v1/notifications/${encodeURIComponent(id)}/read`,
|
|
222
|
+
requireAuth: true
|
|
223
|
+
});
|
|
224
|
+
return { ok: true };
|
|
225
|
+
},
|
|
226
|
+
async dismiss(id) {
|
|
227
|
+
if (!id) throw new NeetruError("validation_failed", "id obrigat\xF3rio");
|
|
228
|
+
await httpRequest(config, {
|
|
229
|
+
method: "POST",
|
|
230
|
+
path: `/api/sdk/v1/notifications/${encodeURIComponent(id)}/dismiss`,
|
|
231
|
+
requireAuth: true
|
|
232
|
+
});
|
|
233
|
+
return { ok: true };
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
var MockNotifications = class {
|
|
238
|
+
notifications = /* @__PURE__ */ new Map();
|
|
239
|
+
nextId = 1;
|
|
240
|
+
async send(input) {
|
|
241
|
+
validateInput(input);
|
|
242
|
+
if (input.fingerprint) {
|
|
243
|
+
const dayAgo = Date.now() - 864e5;
|
|
244
|
+
for (const existing of this.notifications.values()) {
|
|
245
|
+
const meta = existing.metadata ?? {};
|
|
246
|
+
if (meta.fingerprint === input.fingerprint && existing.userId === input.userId && new Date(existing.createdAt).getTime() > dayAgo) {
|
|
247
|
+
return existing;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const id = `mock_notif_${this.nextId++}`;
|
|
252
|
+
const notif = {
|
|
253
|
+
id,
|
|
254
|
+
userId: input.userId,
|
|
255
|
+
kind: input.kind,
|
|
256
|
+
severity: input.severity ?? "info",
|
|
257
|
+
title: input.title,
|
|
258
|
+
body: input.body,
|
|
259
|
+
link: input.link,
|
|
260
|
+
metadata: input.fingerprint ? { ...input.metadata ?? {}, fingerprint: input.fingerprint } : input.metadata,
|
|
261
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
262
|
+
};
|
|
263
|
+
this.notifications.set(id, notif);
|
|
264
|
+
return notif;
|
|
265
|
+
}
|
|
266
|
+
async list(userId, options) {
|
|
267
|
+
if (!userId) throw new NeetruError("validation_failed", "userId obrigat\xF3rio");
|
|
268
|
+
const limit = Math.min(Math.max(1, options?.limit ?? 50), 200);
|
|
269
|
+
return [...this.notifications.values()].filter((n) => n.userId === userId).filter((n) => options?.includeDismissed || !n.dismissedAt).filter((n) => !options?.onlyUnread || !n.readAt).sort((a, b) => b.createdAt.localeCompare(a.createdAt)).slice(0, limit);
|
|
270
|
+
}
|
|
271
|
+
async markRead(id) {
|
|
272
|
+
const n = this.notifications.get(id);
|
|
273
|
+
if (!n) throw new NeetruError("not_found", `Notification ${id} n\xE3o encontrada`);
|
|
274
|
+
if (!n.readAt) {
|
|
275
|
+
n.readAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
276
|
+
this.notifications.set(id, n);
|
|
277
|
+
}
|
|
278
|
+
return { ok: true };
|
|
279
|
+
}
|
|
280
|
+
async dismiss(id) {
|
|
281
|
+
const n = this.notifications.get(id);
|
|
282
|
+
if (!n) throw new NeetruError("not_found", `Notification ${id} n\xE3o encontrada`);
|
|
283
|
+
if (!n.dismissedAt) {
|
|
284
|
+
n.dismissedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
285
|
+
this.notifications.set(id, n);
|
|
286
|
+
}
|
|
287
|
+
return { ok: true };
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
export { MockNotifications, createNotificationsNamespace };
|
|
292
|
+
//# sourceMappingURL=notifications.mjs.map
|
|
293
|
+
//# sourceMappingURL=notifications.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/notifications.ts"],"names":["err","message"],"mappings":"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","file":"notifications.mjs","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 * 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 * 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"]}
|
package/dist/react.cjs
CHANGED
|
@@ -96,14 +96,18 @@ function EntitlementGate({
|
|
|
96
96
|
status: "loading"
|
|
97
97
|
});
|
|
98
98
|
const resolvedSlug = productSlug ?? client.config.productId ?? "";
|
|
99
|
+
const resolvedTenantId = client.config.tenantId;
|
|
99
100
|
React__namespace.useEffect(() => {
|
|
100
101
|
let cancelled = false;
|
|
101
102
|
const run = async () => {
|
|
102
103
|
try {
|
|
103
104
|
let result2;
|
|
104
105
|
const usage = client.usage;
|
|
105
|
-
if (usage && typeof usage.check === "function") {
|
|
106
|
-
const res = await usage.check(feature, {
|
|
106
|
+
if (usage && typeof usage.check === "function" && resolvedTenantId) {
|
|
107
|
+
const res = await usage.check(feature, {
|
|
108
|
+
productId: resolvedSlug,
|
|
109
|
+
tenantId: resolvedTenantId
|
|
110
|
+
});
|
|
107
111
|
result2 = {
|
|
108
112
|
allowed: res.allowed === true,
|
|
109
113
|
reason: res.reason,
|
|
@@ -127,7 +131,7 @@ function EntitlementGate({
|
|
|
127
131
|
return () => {
|
|
128
132
|
cancelled = true;
|
|
129
133
|
};
|
|
130
|
-
}, [client, feature, resolvedSlug]);
|
|
134
|
+
}, [client, feature, resolvedSlug, resolvedTenantId]);
|
|
131
135
|
if (state.status === "loading") {
|
|
132
136
|
return React__namespace.createElement(React__namespace.Fragment, null, loading ?? null);
|
|
133
137
|
}
|
package/dist/react.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react.ts"],"names":["React","result","allowed"],"mappings":"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","file":"react.cjs","sourcesContent":["/**\n * SDK React helpers (v1.1) — subpath import `@neetru/sdk/react`.\n *\n * Helpers leves pra React 18+/19. Não puxa `react` como dep direta — caller\n * fornece via peer (alinhado com `@stripe/react-stripe-js` / `firebase`).\n *\n * Exports:\n * - `<CheckoutLink>` — wrapper de `<a>` que chama `client.checkout.start()` no click.\n * - `<EntitlementGate>` — wrapper que gateia children por entitlement check\n * (suporte a `mode='readonly'` pro decisão CEO §5).\n * - `useEntitlementContext()` — hook pra ler estado de readonly do contexto.\n *\n * **Bundle**: este file SÓ é carregado por quem importa `@neetru/sdk/react`.\n * Tree-shake garante que SDK consumers Node-only (CLI, edge handlers) não\n * puxam React mesmo via transitive.\n */\nimport * as React from 'react';\nimport type { NeetruClient } from './types';\nimport type { CheckoutStartInput, CheckoutStartResult } from './checkout';\n\n// ─── <CheckoutLink> ─────────────────────────────────────────────────────────\n\nexport interface CheckoutLinkProps\n extends Omit<\n React.AnchorHTMLAttributes<HTMLAnchorElement>,\n 'href' | 'onClick' | 'onError'\n > {\n /** Cliente SDK Neetru. Passado explicitamente pra evitar context provider. */\n client: NeetruClient;\n /** Slug do produto (ex: `neetru-pulse`). */\n productId: string;\n /** Plan id (ex: `pro_monthly`). */\n planId: string;\n /** Pra onde o produto SaaS quer voltar pós-checkout. */\n callbackUrl: string;\n /** Override pra checkout em nome de uma org. Default: PF do uid logado. */\n tenantType?: 'pf' | 'pj';\n tenantId?: string;\n /** Children — texto/JSX do CTA. */\n children: React.ReactNode;\n /** Callback quando intent foi criada (antes de redirect). */\n onIntentCreated?: (result: CheckoutStartResult) => void;\n /** Callback de erro. */\n onError?: (err: Error) => void;\n /** Quando true, NÃO redireciona automaticamente — caller controla. */\n noAutoRedirect?: boolean;\n /** Override de href (default: `#`). */\n href?: string;\n}\n\n/**\n * Wrapper de `<a>` que dispara `client.checkout.start()` no click.\n *\n * Uso típico:\n * ```tsx\n * <CheckoutLink\n * client={client}\n * productId=\"meu-saas\"\n * planId=\"pro_monthly\"\n * callbackUrl=\"https://meu-saas.com/billing/success\"\n * >\n * Assinar Pro\n * </CheckoutLink>\n * ```\n *\n * `href` é stub (`#`) — preventDefault no click. Mantido pra a11y / preview\n * de URL no hover (pode ser sobrescrito via prop spread).\n */\nexport function CheckoutLink({\n client,\n productId,\n planId,\n callbackUrl,\n tenantType,\n tenantId,\n children,\n onIntentCreated,\n onError,\n noAutoRedirect,\n ...rest\n}: CheckoutLinkProps): React.ReactElement {\n const [submitting, setSubmitting] = React.useState(false);\n\n // Lazy access — `client.checkout` foi adicionado em SDK 1.1, fall back gracioso\n // se caller passar um client antigo (mesmo que types resolvam, runtime check).\n const checkout = (client as { checkout?: { start: (input: CheckoutStartInput) => Promise<CheckoutStartResult> } }).checkout;\n\n const handleClick = React.useCallback(\n async (event: React.MouseEvent<HTMLAnchorElement>) => {\n event.preventDefault();\n if (submitting) return;\n if (!checkout || typeof checkout.start !== 'function') {\n onError?.(new Error('SDK client missing `checkout` namespace. Upgrade @neetru/sdk to 1.1+.'));\n return;\n }\n setSubmitting(true);\n try {\n const result = await checkout.start({\n productId,\n planId,\n callbackUrl,\n tenantType,\n tenantId,\n autoRedirect: !noAutoRedirect,\n });\n onIntentCreated?.(result);\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setSubmitting(false);\n }\n },\n [submitting, checkout, productId, planId, callbackUrl, tenantType, tenantId, noAutoRedirect, onIntentCreated, onError],\n );\n\n return React.createElement(\n 'a',\n {\n ...rest,\n href: rest.href ?? '#',\n onClick: handleClick,\n 'aria-busy': submitting || undefined,\n 'data-neetru-checkout-link': 'true',\n },\n children,\n );\n}\n\n// ─── <EntitlementGate> + useEntitlementContext ────────────────────────────\n\n/** Modo de gate quando entitlement não é permitido. */\nexport type EntitlementGateMode = 'block' | 'readonly';\n\ninterface EntitlementContextValue {\n /** True quando feature está em modo read-only (limit exceeded). */\n readonly: boolean;\n /** Reason code da última check. */\n reason?: string;\n /** Limite atual (free tier). */\n limit?: number;\n /** Uso atual. */\n currentUsage?: number;\n}\n\nconst EntitlementContext = React.createContext<EntitlementContextValue>({\n readonly: false,\n});\n\n/** Hook pra ler estado de readonly. Componentes filhos consomem isso pra\n * desabilitar inputs/botões de escrita. */\nexport function useEntitlementContext(): EntitlementContextValue {\n return React.useContext(EntitlementContext);\n}\n\nexport interface EntitlementGateProps {\n /** Cliente SDK Neetru. */\n client: NeetruClient;\n /** Feature key a checar (ex: `export.csv`). */\n feature: string;\n /** Slug do produto. Default: lê do client.config se ausente. */\n productSlug?: string;\n /** Modo:\n * - `block` (default): renderiza fallback quando não permitido.\n * - `readonly`: sempre renderiza children mas injeta `readonly: true` no contexto. */\n mode?: EntitlementGateMode;\n /** Fallback UI quando `mode='block'` e check retorna `allowed=false`. */\n fallback?: React.ReactNode;\n /** Loading UI enquanto check resolve (Suspense-like). */\n loading?: React.ReactNode;\n children: React.ReactNode;\n}\n\ninterface EntitlementCheckResult {\n allowed: boolean;\n reason?: string;\n limit?: number;\n currentUsage?: number;\n behavior?: 'readonly' | null;\n}\n\n/**\n * Wrapper que gateia children por entitlement check.\n *\n * Quando `mode='readonly'` + check retorna `behavior='readonly'`:\n * - Children renderizam normalmente.\n * - Context injeta `{readonly: true}`.\n * - Componentes filhos chamam `useEntitlementContext()` pra desabilitar\n * escritas (botões, forms, inputs).\n *\n * Quando `mode='block'` + check retorna `allowed=false`:\n * - `fallback` é renderizado (ex: paywall, upsell modal).\n *\n * Decisão CEO §5 (overage): plataforma usa `readonly` sempre — produto SaaS\n * deve preferir `mode='readonly'` pra preservar engajamento (não hard-block).\n */\nexport function EntitlementGate({\n client,\n feature,\n productSlug,\n mode = 'block',\n fallback,\n loading,\n children,\n}: EntitlementGateProps): React.ReactElement {\n const [state, setState] = React.useState<{ status: 'loading' | 'ready'; result?: EntitlementCheckResult }>({\n status: 'loading',\n });\n\n // Resolve productSlug from prop or client.config\n const resolvedSlug =\n productSlug ?? (client.config as { productId?: string }).productId ?? '';\n\n React.useEffect(() => {\n let cancelled = false;\n const run = async () => {\n try {\n // Try usage.check first (returns full {allowed, reason, behavior, ...})\n // Falls back to entitlements.check (just boolean) if usage.check unavailable.\n let result: EntitlementCheckResult;\n const usage = (client as { usage?: { check: (resource: string, opts?: { productId?: string }) => Promise<EntitlementCheckResult> } }).usage;\n if (usage && typeof usage.check === 'function') {\n const res = await usage.check(feature, { productId: resolvedSlug });\n result = {\n allowed: res.allowed === true,\n reason: res.reason,\n limit: res.limit,\n currentUsage: res.currentUsage,\n behavior: res.behavior,\n };\n } else {\n const allowed = await client.entitlements.check(resolvedSlug, feature);\n result = { allowed };\n }\n if (!cancelled) setState({ status: 'ready', result });\n } catch (err) {\n // Fail open in dev/prod — caller pode decidir via onError pattern futuro.\n if (!cancelled) {\n setState({ status: 'ready', result: { allowed: false, reason: 'check_failed' } });\n }\n if (typeof console !== 'undefined') console.warn('[EntitlementGate] check failed', err);\n }\n };\n run();\n return () => {\n cancelled = true;\n };\n }, [client, feature, resolvedSlug]);\n\n if (state.status === 'loading') {\n return React.createElement(React.Fragment, null, loading ?? null);\n }\n\n const result = state.result;\n const allowed = result?.allowed === true;\n const isReadonly = !allowed && (mode === 'readonly' || result?.behavior === 'readonly');\n\n if (!allowed && mode === 'block' && !isReadonly) {\n return React.createElement(React.Fragment, null, fallback ?? null);\n }\n\n return React.createElement(\n EntitlementContext.Provider,\n {\n value: {\n readonly: isReadonly,\n reason: result?.reason,\n limit: result?.limit,\n currentUsage: result?.currentUsage,\n },\n },\n children,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/react.ts"],"names":["React","result","allowed"],"mappings":"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","file":"react.cjs","sourcesContent":["/**\n * SDK React helpers (v1.1) — subpath import `@neetru/sdk/react`.\n *\n * Helpers leves pra React 18+/19. Não puxa `react` como dep direta — caller\n * fornece via peer (alinhado com `@stripe/react-stripe-js` / `firebase`).\n *\n * Exports:\n * - `<CheckoutLink>` — wrapper de `<a>` que chama `client.checkout.start()` no click.\n * - `<EntitlementGate>` — wrapper que gateia children por entitlement check\n * (suporte a `mode='readonly'` pro decisão CEO §5).\n * - `useEntitlementContext()` — hook pra ler estado de readonly do contexto.\n *\n * **Bundle**: este file SÓ é carregado por quem importa `@neetru/sdk/react`.\n * Tree-shake garante que SDK consumers Node-only (CLI, edge handlers) não\n * puxam React mesmo via transitive.\n */\nimport * as React from 'react';\nimport type { NeetruClient } from './types';\nimport type { CheckoutStartInput, CheckoutStartResult } from './checkout';\n\n// ─── <CheckoutLink> ─────────────────────────────────────────────────────────\n\nexport interface CheckoutLinkProps\n extends Omit<\n React.AnchorHTMLAttributes<HTMLAnchorElement>,\n 'href' | 'onClick' | 'onError'\n > {\n /** Cliente SDK Neetru. Passado explicitamente pra evitar context provider. */\n client: NeetruClient;\n /** Slug do produto (ex: `neetru-pulse`). */\n productId: string;\n /** Plan id (ex: `pro_monthly`). */\n planId: string;\n /** Pra onde o produto SaaS quer voltar pós-checkout. */\n callbackUrl: string;\n /** Override pra checkout em nome de uma org. Default: PF do uid logado. */\n tenantType?: 'pf' | 'pj';\n tenantId?: string;\n /** Children — texto/JSX do CTA. */\n children: React.ReactNode;\n /** Callback quando intent foi criada (antes de redirect). */\n onIntentCreated?: (result: CheckoutStartResult) => void;\n /** Callback de erro. */\n onError?: (err: Error) => void;\n /** Quando true, NÃO redireciona automaticamente — caller controla. */\n noAutoRedirect?: boolean;\n /** Override de href (default: `#`). */\n href?: string;\n}\n\n/**\n * Wrapper de `<a>` que dispara `client.checkout.start()` no click.\n *\n * Uso típico:\n * ```tsx\n * <CheckoutLink\n * client={client}\n * productId=\"meu-saas\"\n * planId=\"pro_monthly\"\n * callbackUrl=\"https://meu-saas.com/billing/success\"\n * >\n * Assinar Pro\n * </CheckoutLink>\n * ```\n *\n * `href` é stub (`#`) — preventDefault no click. Mantido pra a11y / preview\n * de URL no hover (pode ser sobrescrito via prop spread).\n */\nexport function CheckoutLink({\n client,\n productId,\n planId,\n callbackUrl,\n tenantType,\n tenantId,\n children,\n onIntentCreated,\n onError,\n noAutoRedirect,\n ...rest\n}: CheckoutLinkProps): React.ReactElement {\n const [submitting, setSubmitting] = React.useState(false);\n\n // Lazy access — `client.checkout` foi adicionado em SDK 1.1, fall back gracioso\n // se caller passar um client antigo (mesmo que types resolvam, runtime check).\n const checkout = (client as { checkout?: { start: (input: CheckoutStartInput) => Promise<CheckoutStartResult> } }).checkout;\n\n const handleClick = React.useCallback(\n async (event: React.MouseEvent<HTMLAnchorElement>) => {\n event.preventDefault();\n if (submitting) return;\n if (!checkout || typeof checkout.start !== 'function') {\n onError?.(new Error('SDK client missing `checkout` namespace. Upgrade @neetru/sdk to 1.1+.'));\n return;\n }\n setSubmitting(true);\n try {\n const result = await checkout.start({\n productId,\n planId,\n callbackUrl,\n tenantType,\n tenantId,\n autoRedirect: !noAutoRedirect,\n });\n onIntentCreated?.(result);\n } catch (err) {\n onError?.(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setSubmitting(false);\n }\n },\n [submitting, checkout, productId, planId, callbackUrl, tenantType, tenantId, noAutoRedirect, onIntentCreated, onError],\n );\n\n return React.createElement(\n 'a',\n {\n ...rest,\n href: rest.href ?? '#',\n onClick: handleClick,\n 'aria-busy': submitting || undefined,\n 'data-neetru-checkout-link': 'true',\n },\n children,\n );\n}\n\n// ─── <EntitlementGate> + useEntitlementContext ────────────────────────────\n\n/** Modo de gate quando entitlement não é permitido. */\nexport type EntitlementGateMode = 'block' | 'readonly';\n\ninterface EntitlementContextValue {\n /** True quando feature está em modo read-only (limit exceeded). */\n readonly: boolean;\n /** Reason code da última check. */\n reason?: string;\n /** Limite atual (free tier). */\n limit?: number;\n /** Uso atual. */\n currentUsage?: number;\n}\n\nconst EntitlementContext = React.createContext<EntitlementContextValue>({\n readonly: false,\n});\n\n/** Hook pra ler estado de readonly. Componentes filhos consomem isso pra\n * desabilitar inputs/botões de escrita. */\nexport function useEntitlementContext(): EntitlementContextValue {\n return React.useContext(EntitlementContext);\n}\n\nexport interface EntitlementGateProps {\n /** Cliente SDK Neetru. */\n client: NeetruClient;\n /** Feature key a checar (ex: `export.csv`). */\n feature: string;\n /** Slug do produto. Default: lê do client.config se ausente. */\n productSlug?: string;\n /** Modo:\n * - `block` (default): renderiza fallback quando não permitido.\n * - `readonly`: sempre renderiza children mas injeta `readonly: true` no contexto. */\n mode?: EntitlementGateMode;\n /** Fallback UI quando `mode='block'` e check retorna `allowed=false`. */\n fallback?: React.ReactNode;\n /** Loading UI enquanto check resolve (Suspense-like). */\n loading?: React.ReactNode;\n children: React.ReactNode;\n}\n\ninterface EntitlementCheckResult {\n allowed: boolean;\n reason?: string;\n limit?: number;\n currentUsage?: number;\n behavior?: 'readonly' | null;\n}\n\n/**\n * Wrapper que gateia children por entitlement check.\n *\n * Quando `mode='readonly'` + check retorna `behavior='readonly'`:\n * - Children renderizam normalmente.\n * - Context injeta `{readonly: true}`.\n * - Componentes filhos chamam `useEntitlementContext()` pra desabilitar\n * escritas (botões, forms, inputs).\n *\n * Quando `mode='block'` + check retorna `allowed=false`:\n * - `fallback` é renderizado (ex: paywall, upsell modal).\n *\n * Decisão CEO §5 (overage): plataforma usa `readonly` sempre — produto SaaS\n * deve preferir `mode='readonly'` pra preservar engajamento (não hard-block).\n */\nexport function EntitlementGate({\n client,\n feature,\n productSlug,\n mode = 'block',\n fallback,\n loading,\n children,\n}: EntitlementGateProps): React.ReactElement {\n const [state, setState] = React.useState<{ status: 'loading' | 'ready'; result?: EntitlementCheckResult }>({\n status: 'loading',\n });\n\n // Resolve productSlug from prop or client.config\n const resolvedSlug =\n productSlug ?? (client.config as { productId?: string }).productId ?? '';\n\n // tenantId fallback: client.config.tenantId (default no createNeetruClient).\n // usage.check valida ambos productId + tenantId — sem isso, lança\n // validation_failed e o Gate fica trancado em allowed:false.\n const resolvedTenantId = (client.config as { tenantId?: string }).tenantId;\n\n React.useEffect(() => {\n let cancelled = false;\n const run = async () => {\n try {\n // Try usage.check first (returns full {allowed, reason, behavior, ...})\n // Falls back to entitlements.check (just boolean) if usage.check unavailable.\n let result: EntitlementCheckResult;\n const usage = (client as {\n usage?: {\n check: (\n resource: string,\n opts?: { productId?: string; tenantId?: string },\n ) => Promise<EntitlementCheckResult>;\n };\n }).usage;\n if (usage && typeof usage.check === 'function' && resolvedTenantId) {\n const res = await usage.check(feature, {\n productId: resolvedSlug,\n tenantId: resolvedTenantId,\n });\n result = {\n allowed: res.allowed === true,\n reason: res.reason,\n limit: res.limit,\n currentUsage: res.currentUsage,\n behavior: res.behavior,\n };\n } else {\n // Sem tenantId, cai pra entitlements.check (não exige tenant) em vez\n // de chamar usage.check e tomar validation_failed silencioso.\n const allowed = await client.entitlements.check(resolvedSlug, feature);\n result = { allowed };\n }\n if (!cancelled) setState({ status: 'ready', result });\n } catch (err) {\n // Fail open in dev/prod — caller pode decidir via onError pattern futuro.\n if (!cancelled) {\n setState({ status: 'ready', result: { allowed: false, reason: 'check_failed' } });\n }\n if (typeof console !== 'undefined') console.warn('[EntitlementGate] check failed', err);\n }\n };\n run();\n return () => {\n cancelled = true;\n };\n }, [client, feature, resolvedSlug, resolvedTenantId]);\n\n if (state.status === 'loading') {\n return React.createElement(React.Fragment, null, loading ?? null);\n }\n\n const result = state.result;\n const allowed = result?.allowed === true;\n const isReadonly = !allowed && (mode === 'readonly' || result?.behavior === 'readonly');\n\n if (!allowed && mode === 'block' && !isReadonly) {\n return React.createElement(React.Fragment, null, fallback ?? null);\n }\n\n return React.createElement(\n EntitlementContext.Provider,\n {\n value: {\n readonly: isReadonly,\n reason: result?.reason,\n limit: result?.limit,\n currentUsage: result?.currentUsage,\n },\n },\n children,\n );\n}\n"]}
|
package/dist/react.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { a as NeetruClient, h as CheckoutStartResult } from './types-
|
|
2
|
+
import { a as NeetruClient, h as CheckoutStartResult } from './types-CQAfwqUS.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* SDK React helpers (v1.1) — subpath import `@neetru/sdk/react`.
|
package/dist/react.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { a as NeetruClient, h as CheckoutStartResult } from './types-
|
|
2
|
+
import { a as NeetruClient, h as CheckoutStartResult } from './types-CQAfwqUS.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* SDK React helpers (v1.1) — subpath import `@neetru/sdk/react`.
|
package/dist/react.mjs
CHANGED
|
@@ -74,14 +74,18 @@ function EntitlementGate({
|
|
|
74
74
|
status: "loading"
|
|
75
75
|
});
|
|
76
76
|
const resolvedSlug = productSlug ?? client.config.productId ?? "";
|
|
77
|
+
const resolvedTenantId = client.config.tenantId;
|
|
77
78
|
React.useEffect(() => {
|
|
78
79
|
let cancelled = false;
|
|
79
80
|
const run = async () => {
|
|
80
81
|
try {
|
|
81
82
|
let result2;
|
|
82
83
|
const usage = client.usage;
|
|
83
|
-
if (usage && typeof usage.check === "function") {
|
|
84
|
-
const res = await usage.check(feature, {
|
|
84
|
+
if (usage && typeof usage.check === "function" && resolvedTenantId) {
|
|
85
|
+
const res = await usage.check(feature, {
|
|
86
|
+
productId: resolvedSlug,
|
|
87
|
+
tenantId: resolvedTenantId
|
|
88
|
+
});
|
|
85
89
|
result2 = {
|
|
86
90
|
allowed: res.allowed === true,
|
|
87
91
|
reason: res.reason,
|
|
@@ -105,7 +109,7 @@ function EntitlementGate({
|
|
|
105
109
|
return () => {
|
|
106
110
|
cancelled = true;
|
|
107
111
|
};
|
|
108
|
-
}, [client, feature, resolvedSlug]);
|
|
112
|
+
}, [client, feature, resolvedSlug, resolvedTenantId]);
|
|
109
113
|
if (state.status === "loading") {
|
|
110
114
|
return React.createElement(React.Fragment, null, loading ?? null);
|
|
111
115
|
}
|