@better-auth/infra 0.2.5 → 0.2.7
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/dist/client.d.mts +7 -2
- package/dist/client.mjs +34 -20
- package/dist/{constants-DdWGfvz1.mjs → constants-CvriWQVc.mjs} +6 -2
- package/dist/{dash-client-hJHp7l_X.d.mts → dash-client-B6U89e1S.d.mts} +22 -1
- package/dist/email.d.mts +5 -0
- package/dist/email.mjs +33 -31
- package/dist/fetch-DiAhoiKA.mjs +26 -0
- package/dist/index.d.mts +70 -9
- package/dist/index.mjs +607 -461
- package/dist/native.d.mts +7 -2
- package/dist/native.mjs +28 -15
- package/dist/{pow-BUuN_EKw.mjs → pow-retry-BTL4g3RP.mjs} +56 -36
- package/package.json +6 -6
package/dist/native.d.mts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as DashGetAuditLogsInput, i as DashGetAllAuditLogsInput, n as DashAuditLogsResponse, o as dashClient, r as DashClientOptions, t as DashAuditLog } from "./dash-client-B6U89e1S.mjs";
|
|
2
2
|
import { BetterAuthClientPlugin } from "better-auth";
|
|
3
3
|
|
|
4
4
|
//#region src/sentinel/native/client.d.ts
|
|
5
5
|
interface SentinelNativeClientOptions {
|
|
6
6
|
identifyUrl?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Timeout for KV identify and related HTTP requests (milliseconds).
|
|
9
|
+
* @default 1000
|
|
10
|
+
*/
|
|
11
|
+
kvTimeout?: number;
|
|
7
12
|
autoSolveChallenge?: boolean;
|
|
8
13
|
onChallengeReceived?: (reason: string) => void;
|
|
9
14
|
onChallengeSolved?: (solveTimeMs: number) => void;
|
|
@@ -15,4 +20,4 @@ interface SentinelNativeClientOptions {
|
|
|
15
20
|
}
|
|
16
21
|
declare const sentinelNativeClient: (options?: SentinelNativeClientOptions) => BetterAuthClientPlugin;
|
|
17
22
|
//#endregion
|
|
18
|
-
export { type DashAuditLog, type DashAuditLogsResponse, type DashClientOptions, type DashGetAuditLogsInput, type SentinelNativeClientOptions, dashClient, sentinelNativeClient };
|
|
23
|
+
export { type DashAuditLog, type DashAuditLogsResponse, type DashClientOptions, type DashGetAllAuditLogsInput, type DashGetAuditLogsInput, type SentinelNativeClientOptions, dashClient, sentinelNativeClient };
|
package/dist/native.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "./constants-CvriWQVc.mjs";
|
|
2
|
+
import { n as createKV } from "./fetch-DiAhoiKA.mjs";
|
|
3
|
+
import { i as solvePoWChallenge, l as dashClient, n as decodePoWChallenge, o as identify, r as encodePoWSolution, s as bytesToHex, t as createPowRetryTimeout } from "./pow-retry-BTL4g3RP.mjs";
|
|
2
4
|
import { env } from "@better-auth/core/env";
|
|
3
5
|
import { Dimensions, InteractionManager, PixelRatio, Platform } from "react-native";
|
|
4
6
|
//#region src/sentinel/native/components.ts
|
|
@@ -141,7 +143,7 @@ function createNativeFingerprintRuntime(deps) {
|
|
|
141
143
|
incognito: false
|
|
142
144
|
};
|
|
143
145
|
try {
|
|
144
|
-
await identify(deps
|
|
146
|
+
await identify(deps.$kv, payload);
|
|
145
147
|
} catch (error) {
|
|
146
148
|
console.warn("[Sentinel native] Identify request failed:", error);
|
|
147
149
|
} finally {
|
|
@@ -149,9 +151,10 @@ function createNativeFingerprintRuntime(deps) {
|
|
|
149
151
|
identifyCompleteResolve = null;
|
|
150
152
|
}
|
|
151
153
|
}
|
|
152
|
-
async function waitForIdentify(timeoutMs
|
|
154
|
+
async function waitForIdentify(timeoutMs) {
|
|
153
155
|
if (!identifyComplete) return;
|
|
154
|
-
|
|
156
|
+
const ms = timeoutMs ?? 1e3;
|
|
157
|
+
await Promise.race([identifyComplete, new Promise((resolve) => setTimeout(resolve, ms))]);
|
|
155
158
|
}
|
|
156
159
|
return {
|
|
157
160
|
getFingerprint,
|
|
@@ -209,7 +212,10 @@ function scheduleIdentify(send) {
|
|
|
209
212
|
const sentinelNativeClient = (options) => {
|
|
210
213
|
const autoSolve = options?.autoSolveChallenge !== false;
|
|
211
214
|
const runtime = createNativeFingerprintRuntime({
|
|
212
|
-
|
|
215
|
+
$kv: createKV({
|
|
216
|
+
kvUrl: options?.identifyUrl ?? env.BETTER_AUTH_KV_URL ?? DEFAULT_IDENTIFY_URL,
|
|
217
|
+
kvTimeout: options?.kvTimeout
|
|
218
|
+
}),
|
|
213
219
|
getOrCreateVisitorId: () => getOrCreateVisitorId(options?.storage)
|
|
214
220
|
});
|
|
215
221
|
scheduleIdentify(() => {
|
|
@@ -221,7 +227,7 @@ const sentinelNativeClient = (options) => {
|
|
|
221
227
|
id: "sentinel-fingerprint",
|
|
222
228
|
name: "sentinel-fingerprint",
|
|
223
229
|
hooks: { async onRequest(context) {
|
|
224
|
-
await runtime.waitForIdentify(
|
|
230
|
+
await runtime.waitForIdentify(options?.kvTimeout);
|
|
225
231
|
const fingerprint = await runtime.getFingerprint();
|
|
226
232
|
if (!fingerprint) return context;
|
|
227
233
|
const headers = context.headers || new Headers();
|
|
@@ -262,15 +268,22 @@ const sentinelNativeClient = (options) => {
|
|
|
262
268
|
retryHeaders.set("Content-Type", "application/json");
|
|
263
269
|
let body;
|
|
264
270
|
if (context.request?.body) body = context.request._originalBody;
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
271
|
+
const req = context.request;
|
|
272
|
+
const powRetry = createPowRetryTimeout(req.timeout);
|
|
273
|
+
try {
|
|
274
|
+
const retryResponse = await fetch(originalUrl, {
|
|
275
|
+
method: req.method || "POST",
|
|
276
|
+
headers: retryHeaders,
|
|
277
|
+
body,
|
|
278
|
+
...powRetry.signal ? { signal: powRetry.signal } : {}
|
|
279
|
+
});
|
|
280
|
+
return {
|
|
281
|
+
...context,
|
|
282
|
+
response: retryResponse
|
|
283
|
+
};
|
|
284
|
+
} finally {
|
|
285
|
+
powRetry.cleanup?.();
|
|
286
|
+
}
|
|
274
287
|
} catch (err) {
|
|
275
288
|
console.error("[Sentinel native] Failed to solve PoW challenge:", err);
|
|
276
289
|
options?.onChallengeFailed?.(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import "./constants-DdWGfvz1.mjs";
|
|
2
1
|
//#region src/dash-client.ts
|
|
3
2
|
function resolveDashUserId(input, options) {
|
|
4
3
|
return input.userId || options?.resolveUserId?.({
|
|
@@ -10,21 +9,39 @@ function resolveDashUserId(input, options) {
|
|
|
10
9
|
const dashClient = (options) => {
|
|
11
10
|
return {
|
|
12
11
|
id: "dash",
|
|
13
|
-
getActions: ($fetch) => ({ dash: {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
12
|
+
getActions: ($fetch) => ({ dash: {
|
|
13
|
+
getAuditLogs: async (input = {}) => {
|
|
14
|
+
const userId = resolveDashUserId(input, options);
|
|
15
|
+
return $fetch("/events/audit-logs", {
|
|
16
|
+
method: "GET",
|
|
17
|
+
query: {
|
|
18
|
+
limit: input.limit,
|
|
19
|
+
offset: input.offset,
|
|
20
|
+
organizationId: input.organizationId,
|
|
21
|
+
identifier: input.identifier,
|
|
22
|
+
eventType: input.eventType,
|
|
23
|
+
userId
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
getAllAuditLogs: async (input = {}) => {
|
|
28
|
+
return $fetch("/events/all-audit-logs", {
|
|
29
|
+
method: "GET",
|
|
30
|
+
query: {
|
|
31
|
+
limit: input.limit,
|
|
32
|
+
offset: input.offset,
|
|
33
|
+
organizationId: input.organizationId,
|
|
34
|
+
userId: input.userId,
|
|
35
|
+
eventType: input.eventType,
|
|
36
|
+
identifier: input.identifier
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
} }),
|
|
41
|
+
pathMethods: {
|
|
42
|
+
"/events/audit-logs": "GET",
|
|
43
|
+
"/events/all-audit-logs": "GET"
|
|
44
|
+
}
|
|
28
45
|
};
|
|
29
46
|
};
|
|
30
47
|
//#endregion
|
|
@@ -43,31 +60,15 @@ async function hash(message) {
|
|
|
43
60
|
return bytesToHex(new Uint8Array(hashBuffer));
|
|
44
61
|
}
|
|
45
62
|
//#endregion
|
|
46
|
-
//#region src/abort-signal.ts
|
|
47
|
-
/**
|
|
48
|
-
* Returns an AbortSignal that aborts after `ms`.
|
|
49
|
-
* Uses `AbortSignal.timeout` when present; otherwise `AbortController` + `setTimeout`
|
|
50
|
-
* for React Native / older runtimes where `.timeout` is missing.
|
|
51
|
-
*/
|
|
52
|
-
function timeout(ms) {
|
|
53
|
-
if (typeof AbortSignal.timeout === "function") return AbortSignal.timeout(ms);
|
|
54
|
-
const controller = new AbortController();
|
|
55
|
-
setTimeout(() => controller.abort(), ms);
|
|
56
|
-
return controller.signal;
|
|
57
|
-
}
|
|
58
|
-
//#endregion
|
|
59
63
|
//#region src/identification-client.ts
|
|
60
64
|
function generateRequestId() {
|
|
61
65
|
const hex = bytesToHex(randomBytes(16));
|
|
62
66
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
63
67
|
}
|
|
64
|
-
async function identify(
|
|
65
|
-
|
|
66
|
-
await fetch(`${base}/identify`, {
|
|
68
|
+
async function identify($kv, payload) {
|
|
69
|
+
await $kv("/identify", {
|
|
67
70
|
method: "POST",
|
|
68
|
-
|
|
69
|
-
body: JSON.stringify(payload),
|
|
70
|
-
signal: signal ?? timeout(5e3)
|
|
71
|
+
body: payload
|
|
71
72
|
});
|
|
72
73
|
}
|
|
73
74
|
//#endregion
|
|
@@ -128,4 +129,23 @@ function encodePoWSolution(solution) {
|
|
|
128
129
|
return encodeUtf8ToBase64(JSON.stringify(solution));
|
|
129
130
|
}
|
|
130
131
|
//#endregion
|
|
131
|
-
|
|
132
|
+
//#region src/sentinel/pow-retry.ts
|
|
133
|
+
/**
|
|
134
|
+
* better-fetch clears its internal timeout once the first response is received.
|
|
135
|
+
* For the PoW retry we apply the same `timeout` value again so the second leg
|
|
136
|
+
* cannot exceed the client's configured limit.
|
|
137
|
+
*/
|
|
138
|
+
function createPowRetryTimeout(timeoutMs) {
|
|
139
|
+
if (typeof timeoutMs !== "number" || timeoutMs <= 0) return {
|
|
140
|
+
signal: void 0,
|
|
141
|
+
cleanup: void 0
|
|
142
|
+
};
|
|
143
|
+
const controller = new AbortController();
|
|
144
|
+
const id = setTimeout(() => controller.abort(), timeoutMs);
|
|
145
|
+
return {
|
|
146
|
+
signal: controller.signal,
|
|
147
|
+
cleanup: () => clearTimeout(id)
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
151
|
+
export { generateRequestId as a, hash as c, solvePoWChallenge as i, dashClient as l, decodePoWChallenge as n, identify as o, encodePoWSolution as r, bytesToHex as s, createPowRetryTimeout as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/infra",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Dashboard and analytics plugin for Better Auth",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
"build": "tsdown",
|
|
12
12
|
"dev": "tsdown --watch --no-clean",
|
|
13
13
|
"typecheck": "tsc --noEmit",
|
|
14
|
-
"test": "bun test",
|
|
14
|
+
"test": "bun test --parallel",
|
|
15
15
|
"test:watch": "bun test --watch",
|
|
16
|
-
"coverage": "bun test --coverage"
|
|
16
|
+
"coverage": "bun test --coverage --parallel"
|
|
17
17
|
},
|
|
18
18
|
"exports": {
|
|
19
19
|
".": {
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
"better-auth": "catalog:",
|
|
70
70
|
"expo-crypto": "^14.0.2",
|
|
71
71
|
"happy-dom": "^20.9.0",
|
|
72
|
-
"msw": "^2.
|
|
73
|
-
"tsdown": "^0.21.
|
|
72
|
+
"msw": "^2.14.3",
|
|
73
|
+
"tsdown": "^0.21.10",
|
|
74
74
|
"typescript": "catalog:",
|
|
75
75
|
"zod": "catalog:"
|
|
76
76
|
},
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"@better-fetch/fetch": "^1.1.21",
|
|
79
79
|
"better-call": "^1.3.3",
|
|
80
80
|
"jose": "^6.1.0",
|
|
81
|
-
"libphonenumber-js": "^1.12.
|
|
81
|
+
"libphonenumber-js": "^1.12.42"
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
84
|
"better-auth": ">=1.4.0",
|