@neetru/sdk 2.1.1 → 2.3.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +120 -1
  2. package/dist/auth.cjs +265 -6
  3. package/dist/auth.cjs.map +1 -1
  4. package/dist/auth.d.cts +4 -2
  5. package/dist/auth.d.ts +4 -2
  6. package/dist/auth.mjs +265 -7
  7. package/dist/auth.mjs.map +1 -1
  8. package/dist/catalog.cjs.map +1 -1
  9. package/dist/catalog.d.cts +1 -1
  10. package/dist/catalog.d.ts +1 -1
  11. package/dist/catalog.mjs.map +1 -1
  12. package/dist/checkout.cjs.map +1 -1
  13. package/dist/checkout.d.cts +1 -1
  14. package/dist/checkout.d.ts +1 -1
  15. package/dist/checkout.mjs.map +1 -1
  16. package/dist/db.cjs +138 -6
  17. package/dist/db.cjs.map +1 -1
  18. package/dist/db.d.cts +1 -1
  19. package/dist/db.d.ts +1 -1
  20. package/dist/db.mjs +138 -6
  21. package/dist/db.mjs.map +1 -1
  22. package/dist/entitlements.cjs.map +1 -1
  23. package/dist/entitlements.d.cts +1 -1
  24. package/dist/entitlements.d.ts +1 -1
  25. package/dist/entitlements.mjs.map +1 -1
  26. package/dist/errors.cjs.map +1 -1
  27. package/dist/errors.d.cts +1 -1
  28. package/dist/errors.d.ts +1 -1
  29. package/dist/errors.mjs.map +1 -1
  30. package/dist/index.cjs +261 -6
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +2 -2
  33. package/dist/index.d.ts +2 -2
  34. package/dist/index.mjs +261 -6
  35. package/dist/index.mjs.map +1 -1
  36. package/dist/mocks.cjs +55 -0
  37. package/dist/mocks.cjs.map +1 -1
  38. package/dist/mocks.d.cts +21 -1
  39. package/dist/mocks.d.ts +21 -1
  40. package/dist/mocks.mjs +55 -0
  41. package/dist/mocks.mjs.map +1 -1
  42. package/dist/notifications.cjs.map +1 -1
  43. package/dist/notifications.d.cts +1 -1
  44. package/dist/notifications.d.ts +1 -1
  45. package/dist/notifications.mjs.map +1 -1
  46. package/dist/react.d.cts +1 -1
  47. package/dist/react.d.ts +1 -1
  48. package/dist/support.cjs.map +1 -1
  49. package/dist/support.d.cts +1 -1
  50. package/dist/support.d.ts +1 -1
  51. package/dist/support.mjs.map +1 -1
  52. package/dist/telemetry.cjs.map +1 -1
  53. package/dist/telemetry.d.cts +1 -1
  54. package/dist/telemetry.d.ts +1 -1
  55. package/dist/telemetry.mjs.map +1 -1
  56. package/dist/{types-Cfb-qeDg.d.cts → types-B6YJrynl.d.cts} +91 -13
  57. package/dist/{types-V1EfjR1p.d.ts → types-DvhtZ4bi.d.ts} +91 -13
  58. package/dist/usage.cjs.map +1 -1
  59. package/dist/usage.d.cts +1 -1
  60. package/dist/usage.d.ts +1 -1
  61. package/dist/usage.mjs.map +1 -1
  62. package/dist/webhooks.cjs.map +1 -1
  63. package/dist/webhooks.d.cts +1 -1
  64. package/dist/webhooks.d.ts +1 -1
  65. package/dist/webhooks.mjs.map +1 -1
  66. package/package.json +134 -133
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { o as NeetruClientConfig, N as NeetruClient } from './types-Cfb-qeDg.cjs';
2
- export { A as AuthNamespace, a as AuthStateListener, C as CatalogListOptions, b as CatalogListResponse, c as CheckoutIntentInfo, d as CheckoutIntentStatus, e as CheckoutNamespace, f as CheckoutStartInput, g as CheckoutStartResult, h as CheckoutTenantType, i as CreateTicketInput, D as DEFAULT_BASE_URL, j as DbNamespace, k as DbSqlLease, l as DbWhereFilter, E as EntitlementCheck, L as ListNotificationsOptions, M as MockCheckout, m as MockNotifications, n as MockWebhooks, p as NeetruDb, q as NeetruDbEngine, r as NeetruDbError, s as NeetruDbErrorCode, t as NeetruDbOptions, u as NeetruEnv, v as NeetruSqlClient, w as NeetruUser, x as NotificationsNamespace, P as Product, y as ProductNotification, z as ProductNotificationSeverity, B as ProductPlan, F as ProductStatus, R as RegisterWebhookInput, G as ResolvedConfig, S as SendNotificationInput, H as SignInOptions, J as SupportNamespace, K as SupportSeverity, O as SupportStatus, Q as SupportTicket, T as TelemetryEventAck, U as TelemetryEventInput, X as UsageEventInput, Y as UsageNamespace, Z as UsageQuota, _ as WebhookEndpoint, $ as WebhookEvent, a0 as WebhookTestResult, a1 as WebhooksNamespace, a2 as createCheckoutNamespace, a3 as createNeetruDb, a4 as createNotificationsNamespace, a6 as createWebhooksNamespace } from './types-Cfb-qeDg.cjs';
1
+ import { o as NeetruClientConfig, N as NeetruClient } from './types-B6YJrynl.cjs';
2
+ export { A as AuthNamespace, a as AuthStateListener, C as CatalogListOptions, b as CatalogListResponse, c as CheckoutIntentInfo, d as CheckoutIntentStatus, e as CheckoutNamespace, f as CheckoutStartInput, g as CheckoutStartResult, h as CheckoutTenantType, i as CreateTicketInput, D as DEFAULT_BASE_URL, j as DbNamespace, k as DbSqlLease, l as DbWhereFilter, E as EntitlementCheck, L as ListNotificationsOptions, M as MockCheckout, m as MockNotifications, n as MockWebhooks, p as NeetruDb, q as NeetruDbEngine, r as NeetruDbError, s as NeetruDbErrorCode, t as NeetruDbOptions, u as NeetruDbTransport, v as NeetruEnv, w as NeetruSqlClient, x as NeetruUser, y as NotificationsNamespace, P as Product, z as ProductNotification, B as ProductNotificationSeverity, F as ProductPlan, G as ProductStatus, R as RegisterWebhookInput, H as ResolvedConfig, S as SendNotificationInput, I as SignInOptions, K as SupportNamespace, O as SupportSeverity, Q as SupportStatus, T as SupportTicket, U as TelemetryEventAck, V as TelemetryEventInput, Y as UsageEventInput, Z as UsageNamespace, _ as UsageQuota, $ as VerifyTokenOptions, a0 as WebhookEndpoint, a1 as WebhookEvent, a2 as WebhookTestResult, a3 as WebhooksNamespace, a4 as createCheckoutNamespace, a5 as createNeetruDb, a6 as createNotificationsNamespace, a8 as createWebhooksNamespace } from './types-B6YJrynl.cjs';
3
3
  export { createNeetruClient } from './auth.cjs';
4
4
  export { NeetruError, NeetruErrorCode } from './errors.cjs';
5
5
  export { D as DbBatchOp, b as DbChangeType, c as DbCollectionRef, d as DbDoc, e as DbDocRef, f as DbGetResult, g as DbListResult, h as DbQuery } from './collection-ref-DqAAhuhX.cjs';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { o as NeetruClientConfig, N as NeetruClient } from './types-V1EfjR1p.js';
2
- export { A as AuthNamespace, a as AuthStateListener, C as CatalogListOptions, b as CatalogListResponse, c as CheckoutIntentInfo, d as CheckoutIntentStatus, e as CheckoutNamespace, f as CheckoutStartInput, g as CheckoutStartResult, h as CheckoutTenantType, i as CreateTicketInput, D as DEFAULT_BASE_URL, j as DbNamespace, k as DbSqlLease, l as DbWhereFilter, E as EntitlementCheck, L as ListNotificationsOptions, M as MockCheckout, m as MockNotifications, n as MockWebhooks, p as NeetruDb, q as NeetruDbEngine, r as NeetruDbError, s as NeetruDbErrorCode, t as NeetruDbOptions, u as NeetruEnv, v as NeetruSqlClient, w as NeetruUser, x as NotificationsNamespace, P as Product, y as ProductNotification, z as ProductNotificationSeverity, B as ProductPlan, F as ProductStatus, R as RegisterWebhookInput, G as ResolvedConfig, S as SendNotificationInput, H as SignInOptions, J as SupportNamespace, K as SupportSeverity, O as SupportStatus, Q as SupportTicket, T as TelemetryEventAck, U as TelemetryEventInput, X as UsageEventInput, Y as UsageNamespace, Z as UsageQuota, _ as WebhookEndpoint, $ as WebhookEvent, a0 as WebhookTestResult, a1 as WebhooksNamespace, a2 as createCheckoutNamespace, a3 as createNeetruDb, a4 as createNotificationsNamespace, a6 as createWebhooksNamespace } from './types-V1EfjR1p.js';
1
+ import { o as NeetruClientConfig, N as NeetruClient } from './types-DvhtZ4bi.js';
2
+ export { A as AuthNamespace, a as AuthStateListener, C as CatalogListOptions, b as CatalogListResponse, c as CheckoutIntentInfo, d as CheckoutIntentStatus, e as CheckoutNamespace, f as CheckoutStartInput, g as CheckoutStartResult, h as CheckoutTenantType, i as CreateTicketInput, D as DEFAULT_BASE_URL, j as DbNamespace, k as DbSqlLease, l as DbWhereFilter, E as EntitlementCheck, L as ListNotificationsOptions, M as MockCheckout, m as MockNotifications, n as MockWebhooks, p as NeetruDb, q as NeetruDbEngine, r as NeetruDbError, s as NeetruDbErrorCode, t as NeetruDbOptions, u as NeetruDbTransport, v as NeetruEnv, w as NeetruSqlClient, x as NeetruUser, y as NotificationsNamespace, P as Product, z as ProductNotification, B as ProductNotificationSeverity, F as ProductPlan, G as ProductStatus, R as RegisterWebhookInput, H as ResolvedConfig, S as SendNotificationInput, I as SignInOptions, K as SupportNamespace, O as SupportSeverity, Q as SupportStatus, T as SupportTicket, U as TelemetryEventAck, V as TelemetryEventInput, Y as UsageEventInput, Z as UsageNamespace, _ as UsageQuota, $ as VerifyTokenOptions, a0 as WebhookEndpoint, a1 as WebhookEvent, a2 as WebhookTestResult, a3 as WebhooksNamespace, a4 as createCheckoutNamespace, a5 as createNeetruDb, a6 as createNotificationsNamespace, a8 as createWebhooksNamespace } from './types-DvhtZ4bi.js';
3
3
  export { createNeetruClient } from './auth.js';
4
4
  export { NeetruError, NeetruErrorCode } from './errors.js';
5
5
  export { D as DbBatchOp, b as DbChangeType, c as DbCollectionRef, d as DbDoc, e as DbDocRef, f as DbGetResult, g as DbListResult, h as DbQuery } from './collection-ref-DqAAhuhX.js';
package/dist/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { jwtVerify, createRemoteJWKSet } from 'jose';
1
2
  import { openDB } from 'idb';
2
3
 
3
4
  var __defProp = Object.defineProperty;
@@ -1160,6 +1161,125 @@ var LocalStore = class {
1160
1161
  }
1161
1162
  };
1162
1163
 
1164
+ // src/db/offline/memory-store.ts
1165
+ var MemoryStore = class {
1166
+ // store `documents` — key: `${collection}\0${id}`
1167
+ _docs = /* @__PURE__ */ new Map();
1168
+ // store `mutations` — key: mutationId
1169
+ _mutations = /* @__PURE__ */ new Map();
1170
+ // store `sync_meta` — key: string
1171
+ _meta = /* @__PURE__ */ new Map();
1172
+ // store `conflict_log` — autoIncrement int key
1173
+ _conflicts = [];
1174
+ _conflictSeq = 0;
1175
+ // store `query_cache` — key: queryHash
1176
+ _queryCache = /* @__PURE__ */ new Map();
1177
+ // ─── Ciclo de vida (no-ops) ─────────────────────────────────────────────────
1178
+ async open() {
1179
+ }
1180
+ async close() {
1181
+ this._docs.clear();
1182
+ this._mutations.clear();
1183
+ this._meta.clear();
1184
+ this._conflicts.splice(0);
1185
+ this._conflictSeq = 0;
1186
+ this._queryCache.clear();
1187
+ }
1188
+ // ─── Documents ─────────────────────────────────────────────────────────────
1189
+ async getDoc(collection, id) {
1190
+ const key = `${collection}\0${id}`;
1191
+ return this._docs.get(key) ?? null;
1192
+ }
1193
+ async putDoc(doc) {
1194
+ const key = `${doc.collection}\0${doc.id}`;
1195
+ this._docs.set(key, doc);
1196
+ }
1197
+ async deleteDoc(collection, id) {
1198
+ const key = `${collection}\0${id}`;
1199
+ const existing = this._docs.get(key);
1200
+ if (!existing) return;
1201
+ this._docs.set(key, {
1202
+ ...existing,
1203
+ meta: {
1204
+ ...existing.meta,
1205
+ deleted: true,
1206
+ updatedAtLocal: Date.now()
1207
+ }
1208
+ });
1209
+ }
1210
+ async listDocs(collection, query) {
1211
+ const rawDocs = Array.from(this._docs.values()).filter(
1212
+ (d) => d.collection === collection
1213
+ );
1214
+ return QueryEngine.evaluate(rawDocs, query);
1215
+ }
1216
+ // ─── Sync meta ──────────────────────────────────────────────────────────────
1217
+ async getMeta(key) {
1218
+ return this._meta.get(key) ?? null;
1219
+ }
1220
+ async setMeta(key, value) {
1221
+ this._meta.set(key, value);
1222
+ }
1223
+ // ─── Conflict log ────────────────────────────────────────────────────────────
1224
+ async appendConflict(record) {
1225
+ const id = ++this._conflictSeq;
1226
+ const full = { ...record, id };
1227
+ this._conflicts.push(full);
1228
+ return full;
1229
+ }
1230
+ async listConflicts(options) {
1231
+ if (options?.delivered !== void 0) {
1232
+ return this._conflicts.filter((r) => r.delivered === options.delivered);
1233
+ }
1234
+ return [...this._conflicts];
1235
+ }
1236
+ async markConflictDelivered(id) {
1237
+ const entry = this._conflicts.find((r) => r.id === id);
1238
+ if (entry) entry.delivered = true;
1239
+ }
1240
+ // ─── Mutations ───────────────────────────────────────────────────────────────
1241
+ async putMutation(mutation) {
1242
+ this._mutations.set(mutation.mutationId, { ...mutation });
1243
+ }
1244
+ async getMutation(mutationId) {
1245
+ return this._mutations.get(mutationId) ?? null;
1246
+ }
1247
+ async listMutations(options) {
1248
+ let all = Array.from(this._mutations.values());
1249
+ if (options?.status !== void 0) {
1250
+ all = all.filter((m) => m.status === options.status);
1251
+ } else if (options?.collection !== void 0 && options.docId !== void 0) {
1252
+ all = all.filter(
1253
+ (m) => m.collection === options.collection && m.docId === options.docId
1254
+ );
1255
+ } else if (options?.collection !== void 0) {
1256
+ all = all.filter((m) => m.collection === options.collection);
1257
+ }
1258
+ return all.sort((a, b) => a.seq - b.seq);
1259
+ }
1260
+ async deleteMutation(mutationId) {
1261
+ this._mutations.delete(mutationId);
1262
+ }
1263
+ // ─── Collection discovery ────────────────────────────────────────────────────
1264
+ async listCollections() {
1265
+ const collections = /* @__PURE__ */ new Set();
1266
+ for (const doc of this._docs.values()) {
1267
+ collections.add(doc.collection);
1268
+ }
1269
+ return Array.from(collections);
1270
+ }
1271
+ // ─── Query cache ─────────────────────────────────────────────────────────────
1272
+ async getQueryCache(queryHash) {
1273
+ return this._queryCache.get(queryHash) ?? null;
1274
+ }
1275
+ async putQueryCache(entry) {
1276
+ this._queryCache.set(entry.queryHash, { ...entry });
1277
+ }
1278
+ async deleteQueryCache(queryHash) {
1279
+ this._queryCache.delete(queryHash);
1280
+ }
1281
+ };
1282
+
1163
1283
  // src/db/offline/mutation-queue.ts
1164
1284
  function generateUUIDv4() {
1165
1285
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
@@ -2706,6 +2826,9 @@ var TabCoordinator = class {
2706
2826
  };
2707
2827
 
2708
2828
  // src/db/collection-ref.ts
2829
+ function isIndexedDBUnavailable() {
2830
+ return typeof indexedDB === "undefined" || typeof window === "undefined";
2831
+ }
2709
2832
  var COLL_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/;
2710
2833
  function assertValidCollection(name) {
2711
2834
  if (!COLL_RE.test(name)) {
@@ -3247,7 +3370,7 @@ var NeetruDbDocumentsImpl = class {
3247
3370
  }
3248
3371
  };
3249
3372
  async function createOfflineDocumentsNamespace(opts) {
3250
- const store = new LocalStore(opts.dbName);
3373
+ const store = isIndexedDBUnavailable() ? new MemoryStore() : new LocalStore(opts.dbName);
3251
3374
  await store.open();
3252
3375
  const queue = new MutationQueue(store);
3253
3376
  const resolver = new ConflictResolver();
@@ -4017,16 +4140,16 @@ var defaultWebSocketFactory = (url) => {
4017
4140
  // src/db/client-db.ts
4018
4141
  var DATASTORE_COLLECTION_ENDPOINT = (collection) => `/api/sdk/v1/datastore/${encodeURIComponent(collection)}`;
4019
4142
  var DATASTORE_DOC_ENDPOINT = (collection, docId) => `/api/sdk/v1/datastore/${encodeURIComponent(collection)}/${encodeURIComponent(docId)}`;
4020
- function resolveTransport(engine, opts, config) {
4143
+ function resolveTransport(transport, opts, config) {
4021
4144
  if (opts._transport) {
4022
4145
  return opts._transport;
4023
4146
  }
4024
- if (engine === "firestore") {
4147
+ if (transport === "firestore") {
4025
4148
  if (opts.firestoreTransport) {
4026
4149
  return opts.firestoreTransport;
4027
4150
  }
4028
4151
  }
4029
- if (engine === "nosql-vm" && opts.realtimeGatewayUrl) {
4152
+ if (transport === "nosql-vm" && opts.realtimeGatewayUrl) {
4030
4153
  return createWebSocketSyncTransport(opts.realtimeGatewayUrl, config, opts);
4031
4154
  }
4032
4155
  return createRestSyncTransport(config);
@@ -4170,8 +4293,18 @@ function buildTicketProvider(config, opts) {
4170
4293
  };
4171
4294
  }
4172
4295
  function createNeetruDb(config, dbOpts = {}) {
4173
- const engine = dbOpts.engine ?? "rest";
4174
- const transport = resolveTransport(engine, dbOpts, config);
4296
+ let resolvedTransport;
4297
+ if (dbOpts.transport !== void 0) {
4298
+ resolvedTransport = dbOpts.transport;
4299
+ } else if (dbOpts.engine !== void 0) {
4300
+ console.warn(
4301
+ '[neetru/sdk] NeetruDbOptions.engine est\xE1 depreciado e ser\xE1 removido em v3.0. Use NeetruDbOptions.transport em vez de engine. Valores v\xE1lidos: "rest" | "firestore" | "nosql-vm". Nota: "engine" no SDK configura o TRANSPORTE (REST/Firestore/WebSocket), n\xE3o o storage engine do admin database (firestore-instance, cloud-sql-postgres, \u2026).'
4302
+ );
4303
+ resolvedTransport = dbOpts.engine;
4304
+ } else {
4305
+ resolvedTransport = "rest";
4306
+ }
4307
+ const transport = resolveTransport(resolvedTransport, dbOpts, config);
4175
4308
  const dbId = dbOpts.dbId ?? "default";
4176
4309
  const dbName = dbOpts.dbName ?? `neetru-db__${config.productId ?? "sdk"}__${dbId}__${config.env}`;
4177
4310
  let _docsPromise = null;
@@ -4843,6 +4976,61 @@ var MockAuth = class {
4843
4976
  this._listeners.delete(listener);
4844
4977
  };
4845
4978
  }
4979
+ /**
4980
+ * Mock de `verifyToken` — decodifica o JWT sem verificar assinatura (pra testes).
4981
+ * Em dev, retorna o user atual do mock se já estiver logado. Aceita qualquer token
4982
+ * não-vazio sem chamar rede.
4983
+ *
4984
+ * Para simular falhas em testes, use `MockAuth.__mockVerifyToken(fn)`.
4985
+ */
4986
+ async verifyToken(token) {
4987
+ if (this._verifyTokenOverride) {
4988
+ return this._verifyTokenOverride(token);
4989
+ }
4990
+ if (!token) {
4991
+ throw Object.assign(new Error("Token inv\xE1lido"), { code: "token_invalid_signature" });
4992
+ }
4993
+ try {
4994
+ const parts = token.split(".");
4995
+ if (parts.length === 3) {
4996
+ const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
4997
+ const pad = "=".repeat((4 - b64.length % 4) % 4);
4998
+ const decoded = JSON.parse(
4999
+ typeof atob === "function" ? atob(b64 + pad) : Buffer.from(b64 + pad, "base64").toString("utf-8")
5000
+ );
5001
+ if (typeof decoded.sub === "string") {
5002
+ return {
5003
+ uid: decoded.sub,
5004
+ email: typeof decoded.email === "string" ? decoded.email : "",
5005
+ emailVerified: typeof decoded.email_verified === "boolean" ? decoded.email_verified : void 0,
5006
+ displayName: typeof decoded.name === "string" ? decoded.name : void 0,
5007
+ photoURL: typeof decoded.picture === "string" ? decoded.picture : void 0,
5008
+ isStaff: decoded.is_staff === true,
5009
+ isCustomer: decoded.is_customer === true,
5010
+ tenantId: typeof decoded.tenant_id === "string" ? decoded.tenant_id : void 0,
5011
+ ...decoded
5012
+ };
5013
+ }
5014
+ }
5015
+ } catch {
5016
+ }
5017
+ if (this._user) return this._user;
5018
+ throw Object.assign(new Error("Nenhum user mock dispon\xEDvel"), { code: "token_invalid_signature" });
5019
+ }
5020
+ _verifyTokenOverride = null;
5021
+ /**
5022
+ * Injeta override pra `verifyToken` em testes — permite simular expiração,
5023
+ * assinatura inválida etc sem precisar de JWT real.
5024
+ *
5025
+ * @example
5026
+ * ```ts
5027
+ * const mock = new MockAuth(null);
5028
+ * mock.__mockVerifyToken(async () => { throw new NeetruError('token_expired', '...'); });
5029
+ * ```
5030
+ */
5031
+ __mockVerifyToken(fn) {
5032
+ this._verifyTokenOverride = fn;
5033
+ }
4846
5034
  /** Helper de tests — força um user state arbitrário. */
4847
5035
  __setUser(user) {
4848
5036
  this._user = user;
@@ -5240,6 +5428,34 @@ function resolveEnv(configEnv) {
5240
5428
  }
5241
5429
  return "prod";
5242
5430
  }
5431
+ var _jwksCache = /* @__PURE__ */ new Map();
5432
+ var DEFAULT_JWKS_TTL_MS = 60 * 60 * 1e3;
5433
+ function _getJwks(jwksUrl, cacheTtlMs) {
5434
+ const now = Date.now();
5435
+ const cached = _jwksCache.get(jwksUrl);
5436
+ if (cached && now - cached.createdAt < cacheTtlMs) {
5437
+ return cached.jwks;
5438
+ }
5439
+ const jwks = createRemoteJWKSet(new URL(jwksUrl));
5440
+ _jwksCache.set(jwksUrl, { jwks, createdAt: now });
5441
+ return jwks;
5442
+ }
5443
+ function _jwtPayloadToUser(payload) {
5444
+ const sub = payload.sub ?? "";
5445
+ const email = typeof payload.email === "string" ? payload.email : "";
5446
+ return {
5447
+ uid: sub,
5448
+ email,
5449
+ emailVerified: typeof payload.email_verified === "boolean" ? payload.email_verified : void 0,
5450
+ displayName: typeof payload.name === "string" ? payload.name : void 0,
5451
+ photoURL: typeof payload.picture === "string" ? payload.picture : void 0,
5452
+ isStaff: payload.is_staff === true,
5453
+ isCustomer: payload.is_customer === true,
5454
+ tenantId: typeof payload.tenant_id === "string" ? payload.tenant_id : void 0,
5455
+ // Spreads todos os claims originais (aud, iss, iat, exp, etc).
5456
+ ...payload
5457
+ };
5458
+ }
5243
5459
  function createOidcAuthNamespace(config) {
5244
5460
  const STORAGE_KEY = "neetru_id_token";
5245
5461
  const listeners = /* @__PURE__ */ new Set();
@@ -5347,6 +5563,45 @@ function createOidcAuthNamespace(config) {
5347
5563
  return () => {
5348
5564
  listeners.delete(listener);
5349
5565
  };
5566
+ },
5567
+ async verifyToken(token, options) {
5568
+ if (!token || typeof token !== "string") {
5569
+ throw new NeetruError("token_invalid_signature", "token must be a non-empty string");
5570
+ }
5571
+ const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
5572
+ const idpOrigin = overrideAuthUrl ?? config.baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
5573
+ const issuer = idpOrigin;
5574
+ const jwksUrl = `${idpOrigin}/api/v1/oauth/.well-known/jwks.json`;
5575
+ const cacheTtlMs = options?.jwksCacheTtlMs ?? DEFAULT_JWKS_TTL_MS;
5576
+ const audience = config.apiKey ? config.apiKey.split("_")[1] ?? void 0 : void 0;
5577
+ const jwks = _getJwks(jwksUrl, cacheTtlMs);
5578
+ try {
5579
+ const { payload } = await jwtVerify(token, jwks, {
5580
+ issuer,
5581
+ ...audience ? { audience } : {},
5582
+ algorithms: ["RS256"]
5583
+ });
5584
+ return _jwtPayloadToUser(payload);
5585
+ } catch (err) {
5586
+ const errName = err?.code ?? err?.name ?? "";
5587
+ const errMsg = err?.message ?? String(err);
5588
+ if (errName === "ERR_JWT_EXPIRED") {
5589
+ throw new NeetruError("token_expired", `Token expired: ${errMsg}`);
5590
+ }
5591
+ if (errName === "ERR_JWS_SIGNATURE_VERIFICATION_FAILED") {
5592
+ throw new NeetruError("token_invalid_signature", `Token signature invalid: ${errMsg}`);
5593
+ }
5594
+ if (errName === "ERR_JWT_CLAIM_VALIDATION_FAILED") {
5595
+ if (errMsg.includes('"aud"') || errMsg.includes("audience")) {
5596
+ throw new NeetruError("token_invalid_audience", `Token audience mismatch: ${errMsg}`);
5597
+ }
5598
+ if (errMsg.includes('"iss"') || errMsg.includes("issuer")) {
5599
+ throw new NeetruError("token_invalid_issuer", `Token issuer mismatch: ${errMsg}`);
5600
+ }
5601
+ throw new NeetruError("token_invalid_signature", `Token claim validation failed: ${errMsg}`);
5602
+ }
5603
+ throw new NeetruError("token_invalid_signature", `Token verification failed: ${errMsg}`);
5604
+ }
5350
5605
  }
5351
5606
  };
5352
5607
  }