@better-auth/telemetry 1.4.0-beta.9
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/.turbo/turbo-build.log +17 -0
- package/LICENSE.md +17 -0
- package/dist/index.cjs +541 -0
- package/dist/index.d.cts +311 -0
- package/dist/index.d.ts +311 -0
- package/dist/index.js +512 -0
- package/package.json +43 -0
- package/src/detectors/detect-auth-config.ts +200 -0
- package/src/detectors/detect-database.ts +22 -0
- package/src/detectors/detect-framework.ts +23 -0
- package/src/detectors/detect-project-info.ts +18 -0
- package/src/detectors/detect-runtime.ts +31 -0
- package/src/detectors/detect-system-info.ts +209 -0
- package/src/index.ts +82 -0
- package/src/project-id.ts +27 -0
- package/src/telemetry.test.ts +321 -0
- package/src/types.ts +46 -0
- package/src/utils/hash.ts +9 -0
- package/src/utils/id.ts +5 -0
- package/src/utils/import-util.ts +3 -0
- package/src/utils/package-json.ts +74 -0
- package/tsconfig.json +9 -0
- package/tsdown.config.ts +7 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
import { ENV, env, getBooleanEnvVar, getEnvVar, isTest, logger } from "@better-auth/core/env";
|
|
2
|
+
import { createRandomStringGenerator } from "@better-auth/utils/random";
|
|
3
|
+
import { createHash } from "@better-auth/utils/hash";
|
|
4
|
+
import { base64 } from "@better-auth/utils/base64";
|
|
5
|
+
import { betterFetch } from "@better-fetch/fetch";
|
|
6
|
+
|
|
7
|
+
//#region src/utils/id.ts
|
|
8
|
+
const generateId = (size) => {
|
|
9
|
+
return createRandomStringGenerator("a-z", "A-Z", "0-9")(size || 32);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/utils/hash.ts
|
|
14
|
+
async function hashToBase64(data) {
|
|
15
|
+
const buffer = await createHash("SHA-256").digest(data);
|
|
16
|
+
return base64.encode(buffer);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/utils/package-json.ts
|
|
21
|
+
let packageJSONCache;
|
|
22
|
+
async function readRootPackageJson() {
|
|
23
|
+
if (packageJSONCache) return packageJSONCache;
|
|
24
|
+
try {
|
|
25
|
+
const cwd = typeof process !== "undefined" && typeof process.cwd === "function" ? process.cwd() : "";
|
|
26
|
+
if (!cwd) return void 0;
|
|
27
|
+
const importRuntime$1 = (m) => Function("mm", "return import(mm)")(m);
|
|
28
|
+
const [{ default: fs }, { default: path }] = await Promise.all([importRuntime$1("fs/promises"), importRuntime$1("path")]);
|
|
29
|
+
const raw = await fs.readFile(path.join(cwd, "package.json"), "utf-8");
|
|
30
|
+
packageJSONCache = JSON.parse(raw);
|
|
31
|
+
return packageJSONCache;
|
|
32
|
+
} catch {}
|
|
33
|
+
}
|
|
34
|
+
async function getPackageVersion(pkg) {
|
|
35
|
+
if (packageJSONCache) return packageJSONCache.dependencies?.[pkg] || packageJSONCache.devDependencies?.[pkg] || packageJSONCache.peerDependencies?.[pkg];
|
|
36
|
+
try {
|
|
37
|
+
const cwd = typeof process !== "undefined" && typeof process.cwd === "function" ? process.cwd() : "";
|
|
38
|
+
if (!cwd) throw new Error("no-cwd");
|
|
39
|
+
const importRuntime$1 = (m) => Function("mm", "return import(mm)")(m);
|
|
40
|
+
const [{ default: fs }, { default: path }] = await Promise.all([importRuntime$1("fs/promises"), importRuntime$1("path")]);
|
|
41
|
+
const pkgJsonPath = path.join(cwd, "node_modules", pkg, "package.json");
|
|
42
|
+
const raw = await fs.readFile(pkgJsonPath, "utf-8");
|
|
43
|
+
return JSON.parse(raw).version || await getVersionFromLocalPackageJson(pkg) || void 0;
|
|
44
|
+
} catch {}
|
|
45
|
+
return await getVersionFromLocalPackageJson(pkg);
|
|
46
|
+
}
|
|
47
|
+
async function getVersionFromLocalPackageJson(pkg) {
|
|
48
|
+
const json = await readRootPackageJson();
|
|
49
|
+
if (!json) return void 0;
|
|
50
|
+
return {
|
|
51
|
+
...json.dependencies,
|
|
52
|
+
...json.devDependencies,
|
|
53
|
+
...json.peerDependencies
|
|
54
|
+
}[pkg];
|
|
55
|
+
}
|
|
56
|
+
async function getNameFromLocalPackageJson() {
|
|
57
|
+
return (await readRootPackageJson())?.name;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/project-id.ts
|
|
62
|
+
let projectIdCached = null;
|
|
63
|
+
async function getProjectId(baseUrl) {
|
|
64
|
+
if (projectIdCached) return projectIdCached;
|
|
65
|
+
const projectName = await getNameFromLocalPackageJson();
|
|
66
|
+
if (projectName) {
|
|
67
|
+
projectIdCached = await hashToBase64(baseUrl ? baseUrl + projectName : projectName);
|
|
68
|
+
return projectIdCached;
|
|
69
|
+
}
|
|
70
|
+
if (baseUrl) {
|
|
71
|
+
projectIdCached = await hashToBase64(baseUrl);
|
|
72
|
+
return projectIdCached;
|
|
73
|
+
}
|
|
74
|
+
projectIdCached = generateId(32);
|
|
75
|
+
return projectIdCached;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/utils/import-util.ts
|
|
80
|
+
const importRuntime = (m) => {
|
|
81
|
+
return Function("mm", "return import(mm)")(m);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
//#endregion
|
|
85
|
+
//#region src/detectors/detect-system-info.ts
|
|
86
|
+
function getVendor() {
|
|
87
|
+
const hasAny = (...keys) => keys.some((k) => Boolean(env[k]));
|
|
88
|
+
if (hasAny("CF_PAGES", "CF_PAGES_URL", "CF_ACCOUNT_ID") || typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers") return "cloudflare";
|
|
89
|
+
if (hasAny("VERCEL", "VERCEL_URL", "VERCEL_ENV")) return "vercel";
|
|
90
|
+
if (hasAny("NETLIFY", "NETLIFY_URL")) return "netlify";
|
|
91
|
+
if (hasAny("RENDER", "RENDER_URL", "RENDER_INTERNAL_HOSTNAME", "RENDER_SERVICE_ID")) return "render";
|
|
92
|
+
if (hasAny("AWS_LAMBDA_FUNCTION_NAME", "AWS_EXECUTION_ENV", "LAMBDA_TASK_ROOT")) return "aws";
|
|
93
|
+
if (hasAny("GOOGLE_CLOUD_FUNCTION_NAME", "GOOGLE_CLOUD_PROJECT", "GCP_PROJECT", "K_SERVICE")) return "gcp";
|
|
94
|
+
if (hasAny("AZURE_FUNCTION_NAME", "FUNCTIONS_WORKER_RUNTIME", "WEBSITE_INSTANCE_ID", "WEBSITE_SITE_NAME")) return "azure";
|
|
95
|
+
if (hasAny("DENO_DEPLOYMENT_ID", "DENO_REGION")) return "deno-deploy";
|
|
96
|
+
if (hasAny("FLY_APP_NAME", "FLY_REGION", "FLY_ALLOC_ID")) return "fly-io";
|
|
97
|
+
if (hasAny("RAILWAY_STATIC_URL", "RAILWAY_ENVIRONMENT_NAME")) return "railway";
|
|
98
|
+
if (hasAny("DYNO", "HEROKU_APP_NAME")) return "heroku";
|
|
99
|
+
if (hasAny("DO_DEPLOYMENT_ID", "DO_APP_NAME", "DIGITALOCEAN")) return "digitalocean";
|
|
100
|
+
if (hasAny("KOYEB", "KOYEB_DEPLOYMENT_ID", "KOYEB_APP_NAME")) return "koyeb";
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
async function detectSystemInfo() {
|
|
104
|
+
try {
|
|
105
|
+
if (getVendor() === "cloudflare") return "cloudflare";
|
|
106
|
+
const os = await importRuntime("os");
|
|
107
|
+
const cpus = os.cpus();
|
|
108
|
+
return {
|
|
109
|
+
deploymentVendor: getVendor(),
|
|
110
|
+
systemPlatform: os.platform(),
|
|
111
|
+
systemRelease: os.release(),
|
|
112
|
+
systemArchitecture: os.arch(),
|
|
113
|
+
cpuCount: cpus.length,
|
|
114
|
+
cpuModel: cpus.length ? cpus[0].model : null,
|
|
115
|
+
cpuSpeed: cpus.length ? cpus[0].speed : null,
|
|
116
|
+
memory: os.totalmem(),
|
|
117
|
+
isWSL: await isWsl(),
|
|
118
|
+
isDocker: await isDocker(),
|
|
119
|
+
isTTY: typeof process !== "undefined" && process.stdout ? process.stdout.isTTY : null
|
|
120
|
+
};
|
|
121
|
+
} catch (e) {
|
|
122
|
+
return {
|
|
123
|
+
systemPlatform: null,
|
|
124
|
+
systemRelease: null,
|
|
125
|
+
systemArchitecture: null,
|
|
126
|
+
cpuCount: null,
|
|
127
|
+
cpuModel: null,
|
|
128
|
+
cpuSpeed: null,
|
|
129
|
+
memory: null,
|
|
130
|
+
isWSL: null,
|
|
131
|
+
isDocker: null,
|
|
132
|
+
isTTY: null
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
let isDockerCached;
|
|
137
|
+
async function hasDockerEnv() {
|
|
138
|
+
if (getVendor() === "cloudflare") return false;
|
|
139
|
+
try {
|
|
140
|
+
(await importRuntime("fs")).statSync("/.dockerenv");
|
|
141
|
+
return true;
|
|
142
|
+
} catch {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async function hasDockerCGroup() {
|
|
147
|
+
if (getVendor() === "cloudflare") return false;
|
|
148
|
+
try {
|
|
149
|
+
return (await importRuntime("fs")).readFileSync("/proc/self/cgroup", "utf8").includes("docker");
|
|
150
|
+
} catch {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function isDocker() {
|
|
155
|
+
if (getVendor() === "cloudflare") return false;
|
|
156
|
+
if (isDockerCached === void 0) isDockerCached = await hasDockerEnv() || await hasDockerCGroup();
|
|
157
|
+
return isDockerCached;
|
|
158
|
+
}
|
|
159
|
+
async function isWsl() {
|
|
160
|
+
try {
|
|
161
|
+
if (getVendor() === "cloudflare") return false;
|
|
162
|
+
if (typeof process === "undefined" || process?.platform !== "linux") return false;
|
|
163
|
+
const fs = await importRuntime("fs");
|
|
164
|
+
if ((await importRuntime("os")).release().toLowerCase().includes("microsoft")) {
|
|
165
|
+
if (await isInsideContainer()) return false;
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
return fs.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !await isInsideContainer() : false;
|
|
169
|
+
} catch {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
let isInsideContainerCached;
|
|
174
|
+
const hasContainerEnv = async () => {
|
|
175
|
+
if (getVendor() === "cloudflare") return false;
|
|
176
|
+
try {
|
|
177
|
+
(await importRuntime("fs")).statSync("/run/.containerenv");
|
|
178
|
+
return true;
|
|
179
|
+
} catch {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
async function isInsideContainer() {
|
|
184
|
+
if (isInsideContainerCached === void 0) isInsideContainerCached = await hasContainerEnv() || await isDocker();
|
|
185
|
+
return isInsideContainerCached;
|
|
186
|
+
}
|
|
187
|
+
function isCI() {
|
|
188
|
+
return env.CI !== "false" && ("BUILD_ID" in env || "BUILD_NUMBER" in env || "CI" in env || "CI_APP_ID" in env || "CI_BUILD_ID" in env || "CI_BUILD_NUMBER" in env || "CI_NAME" in env || "CONTINUOUS_INTEGRATION" in env || "RUN_ID" in env);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
//#endregion
|
|
192
|
+
//#region src/detectors/detect-runtime.ts
|
|
193
|
+
function detectRuntime() {
|
|
194
|
+
if (typeof Deno !== "undefined") return {
|
|
195
|
+
name: "deno",
|
|
196
|
+
version: Deno?.version?.deno ?? null
|
|
197
|
+
};
|
|
198
|
+
if (typeof Bun !== "undefined") return {
|
|
199
|
+
name: "bun",
|
|
200
|
+
version: Bun?.version ?? null
|
|
201
|
+
};
|
|
202
|
+
if (typeof process !== "undefined" && process?.versions?.node) return {
|
|
203
|
+
name: "node",
|
|
204
|
+
version: process.versions.node ?? null
|
|
205
|
+
};
|
|
206
|
+
return {
|
|
207
|
+
name: "edge",
|
|
208
|
+
version: null
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function detectEnvironment() {
|
|
212
|
+
return getEnvVar("NODE_ENV") === "production" ? "production" : isCI() ? "ci" : isTest() ? "test" : "development";
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region src/detectors/detect-database.ts
|
|
217
|
+
const DATABASES = {
|
|
218
|
+
pg: "postgresql",
|
|
219
|
+
mysql: "mysql",
|
|
220
|
+
mariadb: "mariadb",
|
|
221
|
+
sqlite3: "sqlite",
|
|
222
|
+
"better-sqlite3": "sqlite",
|
|
223
|
+
"@prisma/client": "prisma",
|
|
224
|
+
mongoose: "mongodb",
|
|
225
|
+
mongodb: "mongodb",
|
|
226
|
+
"drizzle-orm": "drizzle"
|
|
227
|
+
};
|
|
228
|
+
async function detectDatabase() {
|
|
229
|
+
for (const [pkg, name] of Object.entries(DATABASES)) {
|
|
230
|
+
const version = await getPackageVersion(pkg);
|
|
231
|
+
if (version) return {
|
|
232
|
+
name,
|
|
233
|
+
version
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region src/detectors/detect-framework.ts
|
|
240
|
+
const FRAMEWORKS = {
|
|
241
|
+
next: "next",
|
|
242
|
+
nuxt: "nuxt",
|
|
243
|
+
"@remix-run/server-runtime": "remix",
|
|
244
|
+
astro: "astro",
|
|
245
|
+
"@sveltejs/kit": "sveltekit",
|
|
246
|
+
"solid-start": "solid-start",
|
|
247
|
+
"tanstack-start": "tanstack-start",
|
|
248
|
+
hono: "hono",
|
|
249
|
+
express: "express",
|
|
250
|
+
elysia: "elysia",
|
|
251
|
+
expo: "expo"
|
|
252
|
+
};
|
|
253
|
+
async function detectFramework() {
|
|
254
|
+
for (const [pkg, name] of Object.entries(FRAMEWORKS)) {
|
|
255
|
+
const version = await getPackageVersion(pkg);
|
|
256
|
+
if (version) return {
|
|
257
|
+
name,
|
|
258
|
+
version
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
//#endregion
|
|
264
|
+
//#region src/detectors/detect-project-info.ts
|
|
265
|
+
function detectPackageManager() {
|
|
266
|
+
const userAgent = env.npm_config_user_agent;
|
|
267
|
+
if (!userAgent) return;
|
|
268
|
+
const pmSpec = userAgent.split(" ")[0];
|
|
269
|
+
const separatorPos = pmSpec.lastIndexOf("/");
|
|
270
|
+
const name = pmSpec.substring(0, separatorPos);
|
|
271
|
+
return {
|
|
272
|
+
name: name === "npminstall" ? "cnpm" : name,
|
|
273
|
+
version: pmSpec.substring(separatorPos + 1)
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
//#endregion
|
|
278
|
+
//#region src/detectors/detect-auth-config.ts
|
|
279
|
+
function getTelemetryAuthConfig(options, context) {
|
|
280
|
+
return {
|
|
281
|
+
database: context?.database,
|
|
282
|
+
adapter: context?.adapter,
|
|
283
|
+
emailVerification: {
|
|
284
|
+
sendVerificationEmail: !!options.emailVerification?.sendVerificationEmail,
|
|
285
|
+
sendOnSignUp: !!options.emailVerification?.sendOnSignUp,
|
|
286
|
+
sendOnSignIn: !!options.emailVerification?.sendOnSignIn,
|
|
287
|
+
autoSignInAfterVerification: !!options.emailVerification?.autoSignInAfterVerification,
|
|
288
|
+
expiresIn: options.emailVerification?.expiresIn,
|
|
289
|
+
onEmailVerification: !!options.emailVerification?.onEmailVerification,
|
|
290
|
+
afterEmailVerification: !!options.emailVerification?.afterEmailVerification
|
|
291
|
+
},
|
|
292
|
+
emailAndPassword: {
|
|
293
|
+
enabled: !!options.emailAndPassword?.enabled,
|
|
294
|
+
disableSignUp: !!options.emailAndPassword?.disableSignUp,
|
|
295
|
+
requireEmailVerification: !!options.emailAndPassword?.requireEmailVerification,
|
|
296
|
+
maxPasswordLength: options.emailAndPassword?.maxPasswordLength,
|
|
297
|
+
minPasswordLength: options.emailAndPassword?.minPasswordLength,
|
|
298
|
+
sendResetPassword: !!options.emailAndPassword?.sendResetPassword,
|
|
299
|
+
resetPasswordTokenExpiresIn: options.emailAndPassword?.resetPasswordTokenExpiresIn,
|
|
300
|
+
onPasswordReset: !!options.emailAndPassword?.onPasswordReset,
|
|
301
|
+
password: {
|
|
302
|
+
hash: !!options.emailAndPassword?.password?.hash,
|
|
303
|
+
verify: !!options.emailAndPassword?.password?.verify
|
|
304
|
+
},
|
|
305
|
+
autoSignIn: !!options.emailAndPassword?.autoSignIn,
|
|
306
|
+
revokeSessionsOnPasswordReset: !!options.emailAndPassword?.revokeSessionsOnPasswordReset
|
|
307
|
+
},
|
|
308
|
+
socialProviders: Object.keys(options.socialProviders || {}).map((p) => {
|
|
309
|
+
const provider = options.socialProviders?.[p];
|
|
310
|
+
if (!provider) return {};
|
|
311
|
+
return {
|
|
312
|
+
id: p,
|
|
313
|
+
mapProfileToUser: !!provider.mapProfileToUser,
|
|
314
|
+
disableDefaultScope: !!provider.disableDefaultScope,
|
|
315
|
+
disableIdTokenSignIn: !!provider.disableIdTokenSignIn,
|
|
316
|
+
disableImplicitSignUp: provider.disableImplicitSignUp,
|
|
317
|
+
disableSignUp: provider.disableSignUp,
|
|
318
|
+
getUserInfo: !!provider.getUserInfo,
|
|
319
|
+
overrideUserInfoOnSignIn: !!provider.overrideUserInfoOnSignIn,
|
|
320
|
+
prompt: provider.prompt,
|
|
321
|
+
verifyIdToken: !!provider.verifyIdToken,
|
|
322
|
+
scope: provider.scope,
|
|
323
|
+
refreshAccessToken: !!provider.refreshAccessToken
|
|
324
|
+
};
|
|
325
|
+
}),
|
|
326
|
+
plugins: options.plugins?.map((p) => p.id.toString()),
|
|
327
|
+
user: {
|
|
328
|
+
modelName: options.user?.modelName,
|
|
329
|
+
fields: options.user?.fields,
|
|
330
|
+
additionalFields: options.user?.additionalFields,
|
|
331
|
+
changeEmail: {
|
|
332
|
+
enabled: options.user?.changeEmail?.enabled,
|
|
333
|
+
sendChangeEmailVerification: !!options.user?.changeEmail?.sendChangeEmailVerification
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
verification: {
|
|
337
|
+
modelName: options.verification?.modelName,
|
|
338
|
+
disableCleanup: options.verification?.disableCleanup,
|
|
339
|
+
fields: options.verification?.fields
|
|
340
|
+
},
|
|
341
|
+
session: {
|
|
342
|
+
modelName: options.session?.modelName,
|
|
343
|
+
additionalFields: options.session?.additionalFields,
|
|
344
|
+
cookieCache: {
|
|
345
|
+
enabled: options.session?.cookieCache?.enabled,
|
|
346
|
+
maxAge: options.session?.cookieCache?.maxAge
|
|
347
|
+
},
|
|
348
|
+
disableSessionRefresh: options.session?.disableSessionRefresh,
|
|
349
|
+
expiresIn: options.session?.expiresIn,
|
|
350
|
+
fields: options.session?.fields,
|
|
351
|
+
freshAge: options.session?.freshAge,
|
|
352
|
+
preserveSessionInDatabase: options.session?.preserveSessionInDatabase,
|
|
353
|
+
storeSessionInDatabase: options.session?.storeSessionInDatabase,
|
|
354
|
+
updateAge: options.session?.updateAge
|
|
355
|
+
},
|
|
356
|
+
account: {
|
|
357
|
+
modelName: options.account?.modelName,
|
|
358
|
+
fields: options.account?.fields,
|
|
359
|
+
encryptOAuthTokens: options.account?.encryptOAuthTokens,
|
|
360
|
+
updateAccountOnSignIn: options.account?.updateAccountOnSignIn,
|
|
361
|
+
accountLinking: {
|
|
362
|
+
enabled: options.account?.accountLinking?.enabled,
|
|
363
|
+
trustedProviders: options.account?.accountLinking?.trustedProviders,
|
|
364
|
+
updateUserInfoOnLink: options.account?.accountLinking?.updateUserInfoOnLink,
|
|
365
|
+
allowUnlinkingAll: options.account?.accountLinking?.allowUnlinkingAll
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
hooks: {
|
|
369
|
+
after: !!options.hooks?.after,
|
|
370
|
+
before: !!options.hooks?.before
|
|
371
|
+
},
|
|
372
|
+
secondaryStorage: !!options.secondaryStorage,
|
|
373
|
+
advanced: {
|
|
374
|
+
cookiePrefix: !!options.advanced?.cookiePrefix,
|
|
375
|
+
cookies: !!options.advanced?.cookies,
|
|
376
|
+
crossSubDomainCookies: {
|
|
377
|
+
domain: !!options.advanced?.crossSubDomainCookies?.domain,
|
|
378
|
+
enabled: options.advanced?.crossSubDomainCookies?.enabled,
|
|
379
|
+
additionalCookies: options.advanced?.crossSubDomainCookies?.additionalCookies
|
|
380
|
+
},
|
|
381
|
+
database: {
|
|
382
|
+
useNumberId: !!options.advanced?.database?.useNumberId,
|
|
383
|
+
generateId: options.advanced?.database?.generateId,
|
|
384
|
+
defaultFindManyLimit: options.advanced?.database?.defaultFindManyLimit
|
|
385
|
+
},
|
|
386
|
+
useSecureCookies: options.advanced?.useSecureCookies,
|
|
387
|
+
ipAddress: {
|
|
388
|
+
disableIpTracking: options.advanced?.ipAddress?.disableIpTracking,
|
|
389
|
+
ipAddressHeaders: options.advanced?.ipAddress?.ipAddressHeaders
|
|
390
|
+
},
|
|
391
|
+
disableCSRFCheck: options.advanced?.disableCSRFCheck,
|
|
392
|
+
cookieAttributes: {
|
|
393
|
+
expires: options.advanced?.defaultCookieAttributes?.expires,
|
|
394
|
+
secure: options.advanced?.defaultCookieAttributes?.secure,
|
|
395
|
+
sameSite: options.advanced?.defaultCookieAttributes?.sameSite,
|
|
396
|
+
domain: !!options.advanced?.defaultCookieAttributes?.domain,
|
|
397
|
+
path: options.advanced?.defaultCookieAttributes?.path,
|
|
398
|
+
httpOnly: options.advanced?.defaultCookieAttributes?.httpOnly
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
trustedOrigins: options.trustedOrigins?.length,
|
|
402
|
+
rateLimit: {
|
|
403
|
+
storage: options.rateLimit?.storage,
|
|
404
|
+
modelName: options.rateLimit?.modelName,
|
|
405
|
+
window: options.rateLimit?.window,
|
|
406
|
+
customStorage: !!options.rateLimit?.customStorage,
|
|
407
|
+
enabled: options.rateLimit?.enabled,
|
|
408
|
+
max: options.rateLimit?.max
|
|
409
|
+
},
|
|
410
|
+
onAPIError: {
|
|
411
|
+
errorURL: options.onAPIError?.errorURL,
|
|
412
|
+
onError: !!options.onAPIError?.onError,
|
|
413
|
+
throw: options.onAPIError?.throw
|
|
414
|
+
},
|
|
415
|
+
logger: {
|
|
416
|
+
disabled: options.logger?.disabled,
|
|
417
|
+
level: options.logger?.level,
|
|
418
|
+
log: !!options.logger?.log
|
|
419
|
+
},
|
|
420
|
+
databaseHooks: {
|
|
421
|
+
user: {
|
|
422
|
+
create: {
|
|
423
|
+
after: !!options.databaseHooks?.user?.create?.after,
|
|
424
|
+
before: !!options.databaseHooks?.user?.create?.before
|
|
425
|
+
},
|
|
426
|
+
update: {
|
|
427
|
+
after: !!options.databaseHooks?.user?.update?.after,
|
|
428
|
+
before: !!options.databaseHooks?.user?.update?.before
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
session: {
|
|
432
|
+
create: {
|
|
433
|
+
after: !!options.databaseHooks?.session?.create?.after,
|
|
434
|
+
before: !!options.databaseHooks?.session?.create?.before
|
|
435
|
+
},
|
|
436
|
+
update: {
|
|
437
|
+
after: !!options.databaseHooks?.session?.update?.after,
|
|
438
|
+
before: !!options.databaseHooks?.session?.update?.before
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
account: {
|
|
442
|
+
create: {
|
|
443
|
+
after: !!options.databaseHooks?.account?.create?.after,
|
|
444
|
+
before: !!options.databaseHooks?.account?.create?.before
|
|
445
|
+
},
|
|
446
|
+
update: {
|
|
447
|
+
after: !!options.databaseHooks?.account?.update?.after,
|
|
448
|
+
before: !!options.databaseHooks?.account?.update?.before
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
verification: {
|
|
452
|
+
create: {
|
|
453
|
+
after: !!options.databaseHooks?.verification?.create?.after,
|
|
454
|
+
before: !!options.databaseHooks?.verification?.create?.before
|
|
455
|
+
},
|
|
456
|
+
update: {
|
|
457
|
+
after: !!options.databaseHooks?.verification?.update?.after,
|
|
458
|
+
before: !!options.databaseHooks?.verification?.update?.before
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
//#endregion
|
|
466
|
+
//#region src/index.ts
|
|
467
|
+
async function createTelemetry(options, context) {
|
|
468
|
+
const debugEnabled = options.telemetry?.debug || getBooleanEnvVar("BETTER_AUTH_TELEMETRY_DEBUG", false);
|
|
469
|
+
const TELEMETRY_ENDPOINT = ENV.BETTER_AUTH_TELEMETRY_ENDPOINT;
|
|
470
|
+
const track = async (event) => {
|
|
471
|
+
if (context?.customTrack) await context.customTrack(event).catch(logger.error);
|
|
472
|
+
else if (debugEnabled) logger.info("telemetry event", JSON.stringify(event, null, 2));
|
|
473
|
+
else await betterFetch(TELEMETRY_ENDPOINT, {
|
|
474
|
+
method: "POST",
|
|
475
|
+
body: event
|
|
476
|
+
}).catch(logger.error);
|
|
477
|
+
};
|
|
478
|
+
const isEnabled = async () => {
|
|
479
|
+
const telemetryEnabled = options.telemetry?.enabled !== void 0 ? options.telemetry.enabled : false;
|
|
480
|
+
return (getBooleanEnvVar("BETTER_AUTH_TELEMETRY", false) || telemetryEnabled) && (context?.skipTestCheck || !isTest());
|
|
481
|
+
};
|
|
482
|
+
const enabled = await isEnabled();
|
|
483
|
+
let anonymousId;
|
|
484
|
+
if (enabled) {
|
|
485
|
+
anonymousId = await getProjectId(options.baseURL);
|
|
486
|
+
track({
|
|
487
|
+
type: "init",
|
|
488
|
+
payload: {
|
|
489
|
+
config: getTelemetryAuthConfig(options),
|
|
490
|
+
runtime: detectRuntime(),
|
|
491
|
+
database: await detectDatabase(),
|
|
492
|
+
framework: await detectFramework(),
|
|
493
|
+
environment: detectEnvironment(),
|
|
494
|
+
systemInfo: await detectSystemInfo(),
|
|
495
|
+
packageManager: detectPackageManager()
|
|
496
|
+
},
|
|
497
|
+
anonymousId
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
return { publish: async (event) => {
|
|
501
|
+
if (!enabled) return;
|
|
502
|
+
if (!anonymousId) anonymousId = await getProjectId(options.baseURL);
|
|
503
|
+
await track({
|
|
504
|
+
type: event.type,
|
|
505
|
+
payload: event.payload,
|
|
506
|
+
anonymousId
|
|
507
|
+
});
|
|
508
|
+
} };
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
//#endregion
|
|
512
|
+
export { createTelemetry, getTelemetryAuthConfig };
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@better-auth/telemetry",
|
|
3
|
+
"version": "1.4.0-beta.9",
|
|
4
|
+
"description": "Telemetry package for Better Auth",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/index.d.cts",
|
|
16
|
+
"default": "./dist/index.cjs"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"typesVersions": {
|
|
21
|
+
"*": {
|
|
22
|
+
"index": [
|
|
23
|
+
"dist/index.d.ts"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"tsdown": "^0.15.6",
|
|
29
|
+
"type-fest": "^4.31.0",
|
|
30
|
+
"@better-auth/core": "1.4.0-beta.9"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@better-auth/utils": "0.3.0",
|
|
34
|
+
"@better-fetch/fetch": "1.1.18"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"@better-auth/core": "1.4.0-beta.9"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsdown",
|
|
41
|
+
"typecheck": "tsc --project tsconfig.json"
|
|
42
|
+
}
|
|
43
|
+
}
|