@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.
- package/CHANGELOG.md +120 -1
- package/dist/auth.cjs +265 -6
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +4 -2
- package/dist/auth.d.ts +4 -2
- package/dist/auth.mjs +265 -7
- package/dist/auth.mjs.map +1 -1
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.mjs.map +1 -1
- 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.map +1 -1
- package/dist/db.cjs +138 -6
- 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 +138 -6
- package/dist/db.mjs.map +1 -1
- package/dist/entitlements.cjs.map +1 -1
- package/dist/entitlements.d.cts +1 -1
- package/dist/entitlements.d.ts +1 -1
- package/dist/entitlements.mjs.map +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.mjs.map +1 -1
- package/dist/index.cjs +261 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +261 -6
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.cjs +55 -0
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.cts +21 -1
- package/dist/mocks.d.ts +21 -1
- package/dist/mocks.mjs +55 -0
- package/dist/mocks.mjs.map +1 -1
- package/dist/notifications.cjs.map +1 -1
- package/dist/notifications.d.cts +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.mjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- 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.map +1 -1
- package/dist/telemetry.cjs.map +1 -1
- package/dist/telemetry.d.cts +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/telemetry.mjs.map +1 -1
- package/dist/{types-Cfb-qeDg.d.cts → types-B6YJrynl.d.cts} +91 -13
- package/dist/{types-V1EfjR1p.d.ts → types-DvhtZ4bi.d.ts} +91 -13
- 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.map +1 -1
- package/dist/webhooks.cjs.map +1 -1
- package/dist/webhooks.d.cts +1 -1
- package/dist/webhooks.d.ts +1 -1
- package/dist/webhooks.mjs.map +1 -1
- 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-
|
|
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
|
|
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-
|
|
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
|
|
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(
|
|
4143
|
+
function resolveTransport(transport, opts, config) {
|
|
4021
4144
|
if (opts._transport) {
|
|
4022
4145
|
return opts._transport;
|
|
4023
4146
|
}
|
|
4024
|
-
if (
|
|
4147
|
+
if (transport === "firestore") {
|
|
4025
4148
|
if (opts.firestoreTransport) {
|
|
4026
4149
|
return opts.firestoreTransport;
|
|
4027
4150
|
}
|
|
4028
4151
|
}
|
|
4029
|
-
if (
|
|
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
|
-
|
|
4174
|
-
|
|
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
|
}
|