@better-auth/infra 0.2.14 → 0.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 +39 -0
- package/dist/client.mjs +65 -49
- package/dist/{constants-CLYqEwMV.mjs → constants-vBiGTmGf.mjs} +1 -1
- package/dist/crypto-DjtrPUlP.mjs +51 -0
- package/dist/email.mjs +1 -1
- package/dist/index.d.mts +1941 -154
- package/dist/index.mjs +675 -596
- package/dist/native.mjs +62 -43
- package/dist/{pow-retry-D2RRftJr.mjs → pow-retry-24lSgXId.mjs} +3 -17
- package/package.json +8 -9
- package/dist/fetch-Bl0S3xUi.mjs +0 -26
package/dist/native.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import "./
|
|
2
|
-
import { n as
|
|
3
|
-
import { a as resolveSentinelClientIdentifyUrl, c as bytesToHex, i as solvePoWChallenge, n as decodePoWChallenge, r as encodePoWSolution, s as identify, t as createPowRetryTimeout, u as dashClient } from "./pow-retry-D2RRftJr.mjs";
|
|
1
|
+
import { o as createKV, t as bytesToHex } from "./crypto-DjtrPUlP.mjs";
|
|
2
|
+
import { a as resolveSentinelClientIdentifyUrl, c as dashClient, i as solvePoWChallenge, n as decodePoWChallenge, r as encodePoWSolution, s as identify, t as createPowRetryTimeout } from "./pow-retry-24lSgXId.mjs";
|
|
4
3
|
import { env } from "@better-auth/core/env";
|
|
5
4
|
import { Dimensions, InteractionManager, PixelRatio, Platform } from "react-native";
|
|
6
5
|
//#region src/sentinel/native/components.ts
|
|
@@ -100,9 +99,19 @@ const NATIVE_IDENTIFY_CONTEXT_URL = "react-native://identify";
|
|
|
100
99
|
function createNativeFingerprintRuntime(deps) {
|
|
101
100
|
let cached = null;
|
|
102
101
|
let pending = null;
|
|
103
|
-
let
|
|
104
|
-
let
|
|
105
|
-
let
|
|
102
|
+
let identifySucceeded = false;
|
|
103
|
+
let identifyExpiresAt = null;
|
|
104
|
+
let identifyInFlight = null;
|
|
105
|
+
async function expireIdentifySessionIfStale() {
|
|
106
|
+
if (!identifySucceeded || identifyExpiresAt === null) return;
|
|
107
|
+
if (Date.now() < identifyExpiresAt) return;
|
|
108
|
+
identifySucceeded = false;
|
|
109
|
+
identifyExpiresAt = null;
|
|
110
|
+
if (cached) cached = {
|
|
111
|
+
...cached,
|
|
112
|
+
requestId: await generateRequestId()
|
|
113
|
+
};
|
|
114
|
+
}
|
|
106
115
|
async function getFingerprint() {
|
|
107
116
|
if (cached != null) return cached;
|
|
108
117
|
if (pending != null) return pending;
|
|
@@ -127,39 +136,42 @@ function createNativeFingerprintRuntime(deps) {
|
|
|
127
136
|
return pending;
|
|
128
137
|
}
|
|
129
138
|
async function sendIdentify() {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
139
|
+
await expireIdentifySessionIfStale();
|
|
140
|
+
if (identifySucceeded) return true;
|
|
141
|
+
if (identifyInFlight !== null) return identifyInFlight;
|
|
142
|
+
identifyInFlight = (async () => {
|
|
143
|
+
const fingerprint = await getFingerprint();
|
|
144
|
+
if (!fingerprint) return false;
|
|
145
|
+
const payload = {
|
|
146
|
+
visitorId: fingerprint.visitorId,
|
|
147
|
+
requestId: fingerprint.requestId,
|
|
148
|
+
confidence: fingerprint.confidence,
|
|
149
|
+
components: fingerprint.components,
|
|
150
|
+
url: NATIVE_IDENTIFY_CONTEXT_URL,
|
|
151
|
+
incognito: false
|
|
152
|
+
};
|
|
153
|
+
try {
|
|
154
|
+
const result = await identify(deps.$kv, payload);
|
|
155
|
+
identifySucceeded = true;
|
|
156
|
+
identifyExpiresAt = result.expiresAt ?? null;
|
|
157
|
+
return true;
|
|
158
|
+
} catch (error) {
|
|
159
|
+
console.warn("[Sentinel native] Identify request failed:", error);
|
|
160
|
+
return false;
|
|
161
|
+
} finally {
|
|
162
|
+
identifyInFlight = null;
|
|
163
|
+
}
|
|
164
|
+
})();
|
|
165
|
+
return identifyInFlight;
|
|
153
166
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
await Promise.race([identifyComplete, new Promise((resolve) => setTimeout(resolve, ms))]);
|
|
167
|
+
function appendIdentification(headers, fingerprint) {
|
|
168
|
+
headers.set("X-Visitor-Id", fingerprint.visitorId);
|
|
169
|
+
if (identifySucceeded) headers.set("X-Request-Id", fingerprint.requestId);
|
|
158
170
|
}
|
|
159
171
|
return {
|
|
160
172
|
getFingerprint,
|
|
161
173
|
sendIdentify,
|
|
162
|
-
|
|
174
|
+
appendIdentification
|
|
163
175
|
};
|
|
164
176
|
}
|
|
165
177
|
const VISITOR_STORAGE_KEY = "better-auth.infra.sentinel.visitorId";
|
|
@@ -219,6 +231,19 @@ const sentinelNativeClient = (options) => {
|
|
|
219
231
|
envKvUrl: env.BETTER_AUTH_KV_URL
|
|
220
232
|
}),
|
|
221
233
|
kvTimeout: options?.kvTimeout
|
|
234
|
+
}, {
|
|
235
|
+
throw: true,
|
|
236
|
+
retry: {
|
|
237
|
+
type: "exponential",
|
|
238
|
+
attempts: 2,
|
|
239
|
+
baseDelay: 400,
|
|
240
|
+
maxDelay: 600,
|
|
241
|
+
shouldRetry(response) {
|
|
242
|
+
if (response === null) return true;
|
|
243
|
+
if (response.status === 429) return true;
|
|
244
|
+
return response.status >= 500;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
222
247
|
}),
|
|
223
248
|
getOrCreateVisitorId: () => getOrCreateVisitorId(options?.storage)
|
|
224
249
|
});
|
|
@@ -231,14 +256,11 @@ const sentinelNativeClient = (options) => {
|
|
|
231
256
|
id: "sentinel-fingerprint",
|
|
232
257
|
name: "sentinel-fingerprint",
|
|
233
258
|
hooks: { async onRequest(context) {
|
|
234
|
-
await runtime.
|
|
259
|
+
await runtime.sendIdentify();
|
|
235
260
|
const fingerprint = await runtime.getFingerprint();
|
|
236
261
|
if (!fingerprint) return context;
|
|
237
262
|
const headers = context.headers || new Headers();
|
|
238
|
-
if (headers instanceof Headers)
|
|
239
|
-
headers.set("X-Visitor-Id", fingerprint.visitorId);
|
|
240
|
-
headers.set("X-Request-Id", fingerprint.requestId);
|
|
241
|
-
}
|
|
263
|
+
if (headers instanceof Headers) runtime.appendIdentification(headers, fingerprint);
|
|
242
264
|
return {
|
|
243
265
|
...context,
|
|
244
266
|
headers
|
|
@@ -270,10 +292,7 @@ const sentinelNativeClient = (options) => {
|
|
|
270
292
|
const fingerprint = await runtime.getFingerprint();
|
|
271
293
|
const retryHeaders = new Headers();
|
|
272
294
|
retryHeaders.set("X-PoW-Solution", encodePoWSolution(solution));
|
|
273
|
-
if (fingerprint)
|
|
274
|
-
retryHeaders.set("X-Visitor-Id", fingerprint.visitorId);
|
|
275
|
-
retryHeaders.set("X-Request-Id", fingerprint.requestId);
|
|
276
|
-
}
|
|
295
|
+
if (fingerprint) runtime.appendIdentification(retryHeaders, fingerprint);
|
|
277
296
|
retryHeaders.set("Content-Type", "application/json");
|
|
278
297
|
const powRetry = createPowRetryTimeout(req.timeout);
|
|
279
298
|
try {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { i as randomBytes, n as hash, t as bytesToHex } from "./crypto-DjtrPUlP.mjs";
|
|
1
2
|
//#region src/dash-client.ts
|
|
2
3
|
function resolveDashUserId(input, options) {
|
|
3
4
|
return input.userId || options?.resolveUserId?.({
|
|
@@ -45,28 +46,13 @@ const dashClient = (options) => {
|
|
|
45
46
|
};
|
|
46
47
|
};
|
|
47
48
|
//#endregion
|
|
48
|
-
//#region src/crypto.ts
|
|
49
|
-
function randomBytes(length) {
|
|
50
|
-
const bytes = new Uint8Array(length);
|
|
51
|
-
crypto.getRandomValues(bytes);
|
|
52
|
-
return bytes;
|
|
53
|
-
}
|
|
54
|
-
function bytesToHex(bytes) {
|
|
55
|
-
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
56
|
-
}
|
|
57
|
-
async function hash(message) {
|
|
58
|
-
const msgBuffer = new TextEncoder().encode(message);
|
|
59
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer);
|
|
60
|
-
return bytesToHex(new Uint8Array(hashBuffer));
|
|
61
|
-
}
|
|
62
|
-
//#endregion
|
|
63
49
|
//#region src/identification-client.ts
|
|
64
50
|
function generateRequestId() {
|
|
65
51
|
const hex = bytesToHex(randomBytes(16));
|
|
66
52
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
67
53
|
}
|
|
68
54
|
async function identify($kv, payload) {
|
|
69
|
-
await $kv("/identify", {
|
|
55
|
+
return await $kv("/identify", {
|
|
70
56
|
method: "POST",
|
|
71
57
|
body: payload
|
|
72
58
|
});
|
|
@@ -181,4 +167,4 @@ function createPowRetryTimeout(timeoutMs) {
|
|
|
181
167
|
};
|
|
182
168
|
}
|
|
183
169
|
//#endregion
|
|
184
|
-
export { resolveSentinelClientIdentifyUrl as a,
|
|
170
|
+
export { resolveSentinelClientIdentifyUrl as a, dashClient as c, solvePoWChallenge as i, decodePoWChallenge as n, generateRequestId as o, encodePoWSolution as r, identify as s, createPowRetryTimeout as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/infra",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Dashboard and analytics plugin for Better Auth",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -54,21 +54,21 @@
|
|
|
54
54
|
"license": "MIT",
|
|
55
55
|
"repository": {
|
|
56
56
|
"type": "git",
|
|
57
|
-
"url": "git+https://github.com/better-auth/
|
|
57
|
+
"url": "git+https://github.com/better-auth/infrastructure.git",
|
|
58
58
|
"directory": "packages/infra"
|
|
59
59
|
},
|
|
60
60
|
"bugs": {
|
|
61
|
-
"url": "https://github.com/better-auth/
|
|
61
|
+
"url": "https://github.com/better-auth/infrastructure/issues"
|
|
62
62
|
},
|
|
63
63
|
"homepage": "https://better-auth.com",
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@better-auth/scim": "1.
|
|
66
|
-
"@better-auth/sso": "1.
|
|
65
|
+
"@better-auth/scim": "1.7.0-beta.8",
|
|
66
|
+
"@better-auth/sso": "1.7.0-beta.8",
|
|
67
67
|
"@infra/mocks": "0.0.0",
|
|
68
68
|
"@infra/utils": "0.0.0",
|
|
69
69
|
"@types/bun": "latest",
|
|
70
70
|
"@types/node": "^24.12.0",
|
|
71
|
-
"better-auth": "1.
|
|
71
|
+
"better-auth": "1.7.0-beta.8",
|
|
72
72
|
"expo-crypto": "^14.0.2",
|
|
73
73
|
"happy-dom": "^20.9.0",
|
|
74
74
|
"msw": "^2.14.6",
|
|
@@ -77,8 +77,8 @@
|
|
|
77
77
|
"zod": "^4.3.6"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@better-auth/utils": "^0.4.
|
|
81
|
-
"@better-fetch/fetch": "
|
|
80
|
+
"@better-auth/utils": "^0.4.2",
|
|
81
|
+
"@better-fetch/fetch": "1.3.1",
|
|
82
82
|
"better-call": "^1.3.2",
|
|
83
83
|
"jose": "^6.1.0",
|
|
84
84
|
"libphonenumber-js": "^1.13.3"
|
|
@@ -87,7 +87,6 @@
|
|
|
87
87
|
"better-auth": ">=1.4.0",
|
|
88
88
|
"zod": ">=4.1.12",
|
|
89
89
|
"@better-auth/core": ">=1.4.0",
|
|
90
|
-
"@better-auth/sso": ">=1.4.0",
|
|
91
90
|
"react-native": ">=0.74.0",
|
|
92
91
|
"@react-native-async-storage/async-storage": ">=1.21.0",
|
|
93
92
|
"expo-constants": ">=16.0.0",
|
package/dist/fetch-Bl0S3xUi.mjs
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { i as INFRA_USER_AGENT } from "./constants-CLYqEwMV.mjs";
|
|
2
|
-
import { createFetch } from "@better-fetch/fetch";
|
|
3
|
-
//#region src/fetch.ts
|
|
4
|
-
function createAPI(options, fetchOptions) {
|
|
5
|
-
return createFetch({
|
|
6
|
-
baseURL: options.apiUrl,
|
|
7
|
-
headers: {
|
|
8
|
-
"user-agent": INFRA_USER_AGENT,
|
|
9
|
-
"x-api-key": options.apiKey
|
|
10
|
-
},
|
|
11
|
-
timeout: options.apiTimeout,
|
|
12
|
-
...fetchOptions
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
function createKV(options, fetchOptions) {
|
|
16
|
-
const headers = { "user-agent": INFRA_USER_AGENT };
|
|
17
|
-
if (options.apiKey) headers["x-api-key"] = options.apiKey;
|
|
18
|
-
return createFetch({
|
|
19
|
-
baseURL: options.kvUrl,
|
|
20
|
-
headers,
|
|
21
|
-
timeout: options.kvTimeout ?? 1e3,
|
|
22
|
-
...fetchOptions
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
//#endregion
|
|
26
|
-
export { createKV as n, createAPI as t };
|