@neetru/sdk 2.1.0 → 2.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 +94 -1
- package/dist/auth.cjs +156 -7
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +5 -3
- package/dist/auth.d.ts +5 -3
- package/dist/auth.mjs +156 -8
- package/dist/auth.mjs.map +1 -1
- 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.map +1 -1
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.d.cts +2 -2
- package/dist/checkout.d.ts +2 -2
- package/dist/checkout.mjs.map +1 -1
- package/dist/{collection-ref-BBvTTXoG.d.cts → collection-ref-DqAAhuhX.d.cts} +56 -7
- package/dist/{collection-ref-BBvTTXoG.d.ts → collection-ref-DqAAhuhX.d.ts} +56 -7
- package/dist/db-react.d.cts +1 -1
- package/dist/db-react.d.ts +1 -1
- package/dist/db.cjs +29 -7
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +2 -2
- package/dist/db.d.ts +2 -2
- package/dist/db.mjs +29 -7
- package/dist/db.mjs.map +1 -1
- package/dist/entitlements.cjs.map +1 -1
- package/dist/entitlements.d.cts +2 -2
- package/dist/entitlements.d.ts +2 -2
- 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 +172 -21
- 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 +172 -21
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.cjs +75 -14
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.cts +22 -2
- package/dist/mocks.d.ts +22 -2
- package/dist/mocks.mjs +75 -14
- package/dist/mocks.mjs.map +1 -1
- package/dist/notifications.cjs.map +1 -1
- package/dist/notifications.d.cts +2 -2
- package/dist/notifications.d.ts +2 -2
- package/dist/notifications.mjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/support.cjs.map +1 -1
- package/dist/support.d.cts +2 -2
- package/dist/support.d.ts +2 -2
- package/dist/support.mjs.map +1 -1
- package/dist/telemetry.cjs.map +1 -1
- package/dist/telemetry.d.cts +2 -2
- package/dist/telemetry.d.ts +2 -2
- package/dist/telemetry.mjs.map +1 -1
- package/dist/{types-B1jylbMC.d.ts → types-CvTje138.d.ts} +46 -2
- package/dist/{types-Kmt4y1FQ.d.cts → types-DlDxttiG.d.cts} +46 -2
- package/dist/usage.cjs.map +1 -1
- package/dist/usage.d.cts +2 -2
- package/dist/usage.d.ts +2 -2
- package/dist/usage.mjs.map +1 -1
- package/dist/webhooks.cjs.map +1 -1
- package/dist/webhooks.d.cts +2 -2
- package/dist/webhooks.d.ts +2 -2
- package/dist/webhooks.mjs.map +1 -1
- package/package.json +3 -2
package/dist/auth.d.cts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { o as NeetruClientConfig, N as NeetruClient } from './types-
|
|
2
|
-
import './collection-ref-
|
|
1
|
+
import { o as NeetruClientConfig, N as NeetruClient } from './types-DlDxttiG.cjs';
|
|
2
|
+
import './collection-ref-DqAAhuhX.cjs';
|
|
3
3
|
import '@neetru/realtime-protocol';
|
|
4
4
|
import 'drizzle-orm/node-postgres';
|
|
5
5
|
import './errors.cjs';
|
|
6
6
|
|
|
7
|
+
/** Limpa o cache de JWKS — uso exclusivo em testes. */
|
|
8
|
+
declare function __resetJwksCacheForTests(): void;
|
|
7
9
|
/**
|
|
8
10
|
* Cria uma instância imutável do cliente Neetru SDK.
|
|
9
11
|
*
|
|
@@ -26,4 +28,4 @@ import './errors.cjs';
|
|
|
26
28
|
*/
|
|
27
29
|
declare function createNeetruClient(config?: NeetruClientConfig): NeetruClient;
|
|
28
30
|
|
|
29
|
-
export { createNeetruClient };
|
|
31
|
+
export { __resetJwksCacheForTests, createNeetruClient };
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { o as NeetruClientConfig, N as NeetruClient } from './types-
|
|
2
|
-
import './collection-ref-
|
|
1
|
+
import { o as NeetruClientConfig, N as NeetruClient } from './types-CvTje138.js';
|
|
2
|
+
import './collection-ref-DqAAhuhX.js';
|
|
3
3
|
import '@neetru/realtime-protocol';
|
|
4
4
|
import 'drizzle-orm/node-postgres';
|
|
5
5
|
import './errors.js';
|
|
6
6
|
|
|
7
|
+
/** Limpa o cache de JWKS — uso exclusivo em testes. */
|
|
8
|
+
declare function __resetJwksCacheForTests(): void;
|
|
7
9
|
/**
|
|
8
10
|
* Cria uma instância imutável do cliente Neetru SDK.
|
|
9
11
|
*
|
|
@@ -26,4 +28,4 @@ import './errors.js';
|
|
|
26
28
|
*/
|
|
27
29
|
declare function createNeetruClient(config?: NeetruClientConfig): NeetruClient;
|
|
28
30
|
|
|
29
|
-
export { createNeetruClient };
|
|
31
|
+
export { __resetJwksCacheForTests, createNeetruClient };
|
package/dist/auth.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;
|
|
@@ -2954,10 +2955,9 @@ var DbCollectionRefImpl = class {
|
|
|
2954
2955
|
const batchId = `batch-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
2955
2956
|
const busChanges = [];
|
|
2956
2957
|
for (const op of ops) {
|
|
2957
|
-
const
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
if (op.op === "add") {
|
|
2958
|
+
const collection = this._collection;
|
|
2959
|
+
if (op.kind === "add") {
|
|
2960
|
+
const data = op.data;
|
|
2961
2961
|
const mutation = await this._queue.enqueue({
|
|
2962
2962
|
collection,
|
|
2963
2963
|
op: "add",
|
|
@@ -2981,7 +2981,9 @@ var DbCollectionRefImpl = class {
|
|
|
2981
2981
|
}
|
|
2982
2982
|
});
|
|
2983
2983
|
busChanges.push({ type: "added", collection, doc: { id: docId, data } });
|
|
2984
|
-
} else if (op.
|
|
2984
|
+
} else if (op.kind === "set") {
|
|
2985
|
+
const id = op.id;
|
|
2986
|
+
const data = op.data;
|
|
2985
2987
|
const existing = await this._store.getDoc(collection, id);
|
|
2986
2988
|
const mutation = await this._queue.enqueue({
|
|
2987
2989
|
collection,
|
|
@@ -3010,7 +3012,9 @@ var DbCollectionRefImpl = class {
|
|
|
3010
3012
|
collection,
|
|
3011
3013
|
doc: { id, data }
|
|
3012
3014
|
});
|
|
3013
|
-
} else if (op.
|
|
3015
|
+
} else if (op.kind === "update") {
|
|
3016
|
+
const id = op.id;
|
|
3017
|
+
const data = op.data;
|
|
3014
3018
|
const existing = await this._store.getDoc(collection, id);
|
|
3015
3019
|
const merged = { ...existing?.data ?? {}, ...data };
|
|
3016
3020
|
const mutation = await this._queue.enqueue({
|
|
@@ -3039,7 +3043,8 @@ var DbCollectionRefImpl = class {
|
|
|
3039
3043
|
}
|
|
3040
3044
|
});
|
|
3041
3045
|
busChanges.push({ type: "modified", collection, doc: { id, data: merged } });
|
|
3042
|
-
} else if (op.
|
|
3046
|
+
} else if (op.kind === "remove") {
|
|
3047
|
+
const id = op.id;
|
|
3043
3048
|
const existing = await this._store.getDoc(collection, id);
|
|
3044
3049
|
await this._queue.enqueue({
|
|
3045
3050
|
collection,
|
|
@@ -3148,6 +3153,15 @@ var DbCollectionRefImpl = class {
|
|
|
3148
3153
|
assertValidId(id);
|
|
3149
3154
|
const self = this;
|
|
3150
3155
|
return {
|
|
3156
|
+
get id() {
|
|
3157
|
+
return id;
|
|
3158
|
+
},
|
|
3159
|
+
get path() {
|
|
3160
|
+
return `${self._collection}/${id}`;
|
|
3161
|
+
},
|
|
3162
|
+
get collection() {
|
|
3163
|
+
return self._collection;
|
|
3164
|
+
},
|
|
3151
3165
|
async get() {
|
|
3152
3166
|
return self._buildGetResult(id);
|
|
3153
3167
|
},
|
|
@@ -4281,6 +4295,15 @@ function createLazyCollectionRef(name, getDocsPromise) {
|
|
|
4281
4295
|
},
|
|
4282
4296
|
doc(id) {
|
|
4283
4297
|
return {
|
|
4298
|
+
get id() {
|
|
4299
|
+
return id;
|
|
4300
|
+
},
|
|
4301
|
+
get path() {
|
|
4302
|
+
return `${name}/${id}`;
|
|
4303
|
+
},
|
|
4304
|
+
get collection() {
|
|
4305
|
+
return name;
|
|
4306
|
+
},
|
|
4284
4307
|
async get() {
|
|
4285
4308
|
return (await getRef()).doc(id).get();
|
|
4286
4309
|
},
|
|
@@ -4821,6 +4844,61 @@ var MockAuth = class {
|
|
|
4821
4844
|
this._listeners.delete(listener);
|
|
4822
4845
|
};
|
|
4823
4846
|
}
|
|
4847
|
+
/**
|
|
4848
|
+
* Mock de `verifyToken` — decodifica o JWT sem verificar assinatura (pra testes).
|
|
4849
|
+
* Em dev, retorna o user atual do mock se já estiver logado. Aceita qualquer token
|
|
4850
|
+
* não-vazio sem chamar rede.
|
|
4851
|
+
*
|
|
4852
|
+
* Para simular falhas em testes, use `MockAuth.__mockVerifyToken(fn)`.
|
|
4853
|
+
*/
|
|
4854
|
+
async verifyToken(token) {
|
|
4855
|
+
if (this._verifyTokenOverride) {
|
|
4856
|
+
return this._verifyTokenOverride(token);
|
|
4857
|
+
}
|
|
4858
|
+
if (!token) {
|
|
4859
|
+
throw Object.assign(new Error("Token inv\xE1lido"), { code: "token_invalid_signature" });
|
|
4860
|
+
}
|
|
4861
|
+
try {
|
|
4862
|
+
const parts = token.split(".");
|
|
4863
|
+
if (parts.length === 3) {
|
|
4864
|
+
const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
4865
|
+
const pad = "=".repeat((4 - b64.length % 4) % 4);
|
|
4866
|
+
const decoded = JSON.parse(
|
|
4867
|
+
typeof atob === "function" ? atob(b64 + pad) : Buffer.from(b64 + pad, "base64").toString("utf-8")
|
|
4868
|
+
);
|
|
4869
|
+
if (typeof decoded.sub === "string") {
|
|
4870
|
+
return {
|
|
4871
|
+
uid: decoded.sub,
|
|
4872
|
+
email: typeof decoded.email === "string" ? decoded.email : "",
|
|
4873
|
+
emailVerified: typeof decoded.email_verified === "boolean" ? decoded.email_verified : void 0,
|
|
4874
|
+
displayName: typeof decoded.name === "string" ? decoded.name : void 0,
|
|
4875
|
+
photoURL: typeof decoded.picture === "string" ? decoded.picture : void 0,
|
|
4876
|
+
isStaff: decoded.is_staff === true,
|
|
4877
|
+
isCustomer: decoded.is_customer === true,
|
|
4878
|
+
tenantId: typeof decoded.tenant_id === "string" ? decoded.tenant_id : void 0,
|
|
4879
|
+
...decoded
|
|
4880
|
+
};
|
|
4881
|
+
}
|
|
4882
|
+
}
|
|
4883
|
+
} catch {
|
|
4884
|
+
}
|
|
4885
|
+
if (this._user) return this._user;
|
|
4886
|
+
throw Object.assign(new Error("Nenhum user mock dispon\xEDvel"), { code: "token_invalid_signature" });
|
|
4887
|
+
}
|
|
4888
|
+
_verifyTokenOverride = null;
|
|
4889
|
+
/**
|
|
4890
|
+
* Injeta override pra `verifyToken` em testes — permite simular expiração,
|
|
4891
|
+
* assinatura inválida etc sem precisar de JWT real.
|
|
4892
|
+
*
|
|
4893
|
+
* @example
|
|
4894
|
+
* ```ts
|
|
4895
|
+
* const mock = new MockAuth(null);
|
|
4896
|
+
* mock.__mockVerifyToken(async () => { throw new NeetruError('token_expired', '...'); });
|
|
4897
|
+
* ```
|
|
4898
|
+
*/
|
|
4899
|
+
__mockVerifyToken(fn) {
|
|
4900
|
+
this._verifyTokenOverride = fn;
|
|
4901
|
+
}
|
|
4824
4902
|
/** Helper de tests — força um user state arbitrário. */
|
|
4825
4903
|
__setUser(user) {
|
|
4826
4904
|
this._user = user;
|
|
@@ -4994,6 +5072,37 @@ function resolveEnv(configEnv) {
|
|
|
4994
5072
|
}
|
|
4995
5073
|
return "prod";
|
|
4996
5074
|
}
|
|
5075
|
+
var _jwksCache = /* @__PURE__ */ new Map();
|
|
5076
|
+
var DEFAULT_JWKS_TTL_MS = 60 * 60 * 1e3;
|
|
5077
|
+
function _getJwks(jwksUrl, cacheTtlMs) {
|
|
5078
|
+
const now = Date.now();
|
|
5079
|
+
const cached = _jwksCache.get(jwksUrl);
|
|
5080
|
+
if (cached && now - cached.createdAt < cacheTtlMs) {
|
|
5081
|
+
return cached.jwks;
|
|
5082
|
+
}
|
|
5083
|
+
const jwks = createRemoteJWKSet(new URL(jwksUrl));
|
|
5084
|
+
_jwksCache.set(jwksUrl, { jwks, createdAt: now });
|
|
5085
|
+
return jwks;
|
|
5086
|
+
}
|
|
5087
|
+
function __resetJwksCacheForTests() {
|
|
5088
|
+
_jwksCache.clear();
|
|
5089
|
+
}
|
|
5090
|
+
function _jwtPayloadToUser(payload) {
|
|
5091
|
+
const sub = payload.sub ?? "";
|
|
5092
|
+
const email = typeof payload.email === "string" ? payload.email : "";
|
|
5093
|
+
return {
|
|
5094
|
+
uid: sub,
|
|
5095
|
+
email,
|
|
5096
|
+
emailVerified: typeof payload.email_verified === "boolean" ? payload.email_verified : void 0,
|
|
5097
|
+
displayName: typeof payload.name === "string" ? payload.name : void 0,
|
|
5098
|
+
photoURL: typeof payload.picture === "string" ? payload.picture : void 0,
|
|
5099
|
+
isStaff: payload.is_staff === true,
|
|
5100
|
+
isCustomer: payload.is_customer === true,
|
|
5101
|
+
tenantId: typeof payload.tenant_id === "string" ? payload.tenant_id : void 0,
|
|
5102
|
+
// Spreads todos os claims originais (aud, iss, iat, exp, etc).
|
|
5103
|
+
...payload
|
|
5104
|
+
};
|
|
5105
|
+
}
|
|
4997
5106
|
function createOidcAuthNamespace(config) {
|
|
4998
5107
|
const STORAGE_KEY = "neetru_id_token";
|
|
4999
5108
|
const listeners = /* @__PURE__ */ new Set();
|
|
@@ -5101,6 +5210,45 @@ function createOidcAuthNamespace(config) {
|
|
|
5101
5210
|
return () => {
|
|
5102
5211
|
listeners.delete(listener);
|
|
5103
5212
|
};
|
|
5213
|
+
},
|
|
5214
|
+
async verifyToken(token, options) {
|
|
5215
|
+
if (!token || typeof token !== "string") {
|
|
5216
|
+
throw new NeetruError("token_invalid_signature", "token must be a non-empty string");
|
|
5217
|
+
}
|
|
5218
|
+
const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
|
|
5219
|
+
const idpOrigin = overrideAuthUrl ?? config.baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
|
|
5220
|
+
const issuer = idpOrigin;
|
|
5221
|
+
const jwksUrl = `${idpOrigin}/api/v1/oauth/.well-known/jwks.json`;
|
|
5222
|
+
const cacheTtlMs = options?.jwksCacheTtlMs ?? DEFAULT_JWKS_TTL_MS;
|
|
5223
|
+
const audience = config.apiKey ? config.apiKey.split("_")[1] ?? void 0 : void 0;
|
|
5224
|
+
const jwks = _getJwks(jwksUrl, cacheTtlMs);
|
|
5225
|
+
try {
|
|
5226
|
+
const { payload } = await jwtVerify(token, jwks, {
|
|
5227
|
+
issuer,
|
|
5228
|
+
...audience ? { audience } : {},
|
|
5229
|
+
algorithms: ["RS256"]
|
|
5230
|
+
});
|
|
5231
|
+
return _jwtPayloadToUser(payload);
|
|
5232
|
+
} catch (err) {
|
|
5233
|
+
const errName = err?.code ?? err?.name ?? "";
|
|
5234
|
+
const errMsg = err?.message ?? String(err);
|
|
5235
|
+
if (errName === "ERR_JWT_EXPIRED") {
|
|
5236
|
+
throw new NeetruError("token_expired", `Token expired: ${errMsg}`);
|
|
5237
|
+
}
|
|
5238
|
+
if (errName === "ERR_JWS_SIGNATURE_VERIFICATION_FAILED") {
|
|
5239
|
+
throw new NeetruError("token_invalid_signature", `Token signature invalid: ${errMsg}`);
|
|
5240
|
+
}
|
|
5241
|
+
if (errName === "ERR_JWT_CLAIM_VALIDATION_FAILED") {
|
|
5242
|
+
if (errMsg.includes('"aud"') || errMsg.includes("audience")) {
|
|
5243
|
+
throw new NeetruError("token_invalid_audience", `Token audience mismatch: ${errMsg}`);
|
|
5244
|
+
}
|
|
5245
|
+
if (errMsg.includes('"iss"') || errMsg.includes("issuer")) {
|
|
5246
|
+
throw new NeetruError("token_invalid_issuer", `Token issuer mismatch: ${errMsg}`);
|
|
5247
|
+
}
|
|
5248
|
+
throw new NeetruError("token_invalid_signature", `Token claim validation failed: ${errMsg}`);
|
|
5249
|
+
}
|
|
5250
|
+
throw new NeetruError("token_invalid_signature", `Token verification failed: ${errMsg}`);
|
|
5251
|
+
}
|
|
5104
5252
|
}
|
|
5105
5253
|
};
|
|
5106
5254
|
}
|
|
@@ -5147,6 +5295,6 @@ function createNeetruClient(config = {}) {
|
|
|
5147
5295
|
return client;
|
|
5148
5296
|
}
|
|
5149
5297
|
|
|
5150
|
-
export { createNeetruClient };
|
|
5298
|
+
export { __resetJwksCacheForTests, createNeetruClient };
|
|
5151
5299
|
//# sourceMappingURL=auth.mjs.map
|
|
5152
5300
|
//# sourceMappingURL=auth.mjs.map
|