@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/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
+ }