@better-auth/cli 1.3.8-beta.4 → 1.3.8-beta.6

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.
Files changed (2) hide show
  1. package/dist/index.mjs +424 -7
  2. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -4,12 +4,12 @@ import { parse } from 'dotenv';
4
4
  import semver from 'semver';
5
5
  import prettier, { format } from 'prettier';
6
6
  import * as z from 'zod/v4';
7
- import fs, { existsSync } from 'fs';
7
+ import fs, { existsSync, readFileSync } from 'fs';
8
8
  import path from 'path';
9
9
  import fs$1 from 'fs/promises';
10
10
  import chalk from 'chalk';
11
11
  import { intro, log, outro, confirm, isCancel, cancel, spinner, text, select, multiselect } from '@clack/prompts';
12
- import { exec } from 'child_process';
12
+ import { exec, execSync } from 'child_process';
13
13
  import { logger, BetterAuthError, createTelemetry, getTelemetryAuthConfig, capitalizeFirstLetter } from 'better-auth';
14
14
  import Crypto from 'crypto';
15
15
  import yoctoSpinner from 'yocto-spinner';
@@ -1069,7 +1069,7 @@ async function initAction(opts) {
1069
1069
  process.exit(0);
1070
1070
  }
1071
1071
  if (packageManagerPreference === void 0) {
1072
- packageManagerPreference = await getPackageManager();
1072
+ packageManagerPreference = await getPackageManager$1();
1073
1073
  }
1074
1074
  if (shouldInstallBetterAuthDep) {
1075
1075
  s2.start(
@@ -1109,7 +1109,7 @@ async function initAction(opts) {
1109
1109
  }
1110
1110
  if (shouldInstallBetterAuthDep) {
1111
1111
  if (packageManagerPreference === void 0) {
1112
- packageManagerPreference = await getPackageManager();
1112
+ packageManagerPreference = await getPackageManager$1();
1113
1113
  }
1114
1114
  const s2 = spinner({ indicator: "dots" });
1115
1115
  s2.start(
@@ -1337,7 +1337,7 @@ async function initAction(opts) {
1337
1337
  if (shouldInstallDeps) {
1338
1338
  const s2 = spinner({ indicator: "dots" });
1339
1339
  if (packageManagerPreference === void 0) {
1340
- packageManagerPreference = await getPackageManager();
1340
+ packageManagerPreference = await getPackageManager$1();
1341
1341
  }
1342
1342
  s2.start(
1343
1343
  `Installing dependencies using ${chalk.bold(
@@ -1586,7 +1586,7 @@ async function getLatestNpmVersion(packageName) {
1586
1586
  throw error?.message;
1587
1587
  }
1588
1588
  }
1589
- async function getPackageManager() {
1589
+ async function getPackageManager$1() {
1590
1590
  const { hasBun, hasPnpm } = await checkPackageManagers();
1591
1591
  if (!hasBun && !hasPnpm) return "npm";
1592
1592
  const packageManagerOptions = [];
@@ -3003,6 +3003,423 @@ const login = new Command("login").description(
3003
3003
  "Demo: Test device authorization flow with Better Auth demo server"
3004
3004
  ).option("--server-url <url>", "The Better Auth server URL", DEMO_URL).option("--client-id <id>", "The OAuth client ID", CLIENT_ID).action(loginAction);
3005
3005
 
3006
+ function getSystemInfo() {
3007
+ const platform = os.platform();
3008
+ const arch = os.arch();
3009
+ const version = os.version();
3010
+ const release = os.release();
3011
+ const cpus = os.cpus();
3012
+ const memory = os.totalmem();
3013
+ const freeMemory = os.freemem();
3014
+ return {
3015
+ platform,
3016
+ arch,
3017
+ version,
3018
+ release,
3019
+ cpuCount: cpus.length,
3020
+ cpuModel: cpus[0]?.model || "Unknown",
3021
+ totalMemory: `${(memory / 1024 / 1024 / 1024).toFixed(2)} GB`,
3022
+ freeMemory: `${(freeMemory / 1024 / 1024 / 1024).toFixed(2)} GB`
3023
+ };
3024
+ }
3025
+ function getNodeInfo() {
3026
+ return {
3027
+ version: process.version,
3028
+ env: process.env.NODE_ENV || "development"
3029
+ };
3030
+ }
3031
+ function getPackageManager() {
3032
+ const userAgent = process.env.npm_config_user_agent || "";
3033
+ if (userAgent.includes("yarn")) {
3034
+ return { name: "yarn", version: getVersion("yarn") };
3035
+ }
3036
+ if (userAgent.includes("pnpm")) {
3037
+ return { name: "pnpm", version: getVersion("pnpm") };
3038
+ }
3039
+ if (userAgent.includes("bun")) {
3040
+ return { name: "bun", version: getVersion("bun") };
3041
+ }
3042
+ return { name: "npm", version: getVersion("npm") };
3043
+ }
3044
+ function getVersion(command) {
3045
+ try {
3046
+ const output = execSync(`${command} --version`, { encoding: "utf8" });
3047
+ return output.trim();
3048
+ } catch {
3049
+ return "Not installed";
3050
+ }
3051
+ }
3052
+ function getFrameworkInfo(projectRoot) {
3053
+ const packageJsonPath = path.join(projectRoot, "package.json");
3054
+ if (!existsSync(packageJsonPath)) {
3055
+ return null;
3056
+ }
3057
+ try {
3058
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
3059
+ const deps = {
3060
+ ...packageJson.dependencies,
3061
+ ...packageJson.devDependencies
3062
+ };
3063
+ const frameworks = {
3064
+ next: deps["next"],
3065
+ react: deps["react"],
3066
+ vue: deps["vue"],
3067
+ nuxt: deps["nuxt"],
3068
+ svelte: deps["svelte"],
3069
+ "@sveltejs/kit": deps["@sveltejs/kit"],
3070
+ express: deps["express"],
3071
+ fastify: deps["fastify"],
3072
+ hono: deps["hono"],
3073
+ remix: deps["@remix-run/react"],
3074
+ astro: deps["astro"],
3075
+ solid: deps["solid-js"],
3076
+ qwik: deps["@builder.io/qwik"]
3077
+ };
3078
+ const installedFrameworks = Object.entries(frameworks).filter(([_, version]) => version).map(([name, version]) => ({ name, version }));
3079
+ return installedFrameworks.length > 0 ? installedFrameworks : null;
3080
+ } catch {
3081
+ return null;
3082
+ }
3083
+ }
3084
+ function getDatabaseInfo(projectRoot) {
3085
+ const packageJsonPath = path.join(projectRoot, "package.json");
3086
+ if (!existsSync(packageJsonPath)) {
3087
+ return null;
3088
+ }
3089
+ try {
3090
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
3091
+ const deps = {
3092
+ ...packageJson.dependencies,
3093
+ ...packageJson.devDependencies
3094
+ };
3095
+ const databases = {
3096
+ "better-sqlite3": deps["better-sqlite3"],
3097
+ "@libsql/client": deps["@libsql/client"],
3098
+ "@libsql/kysely-libsql": deps["@libsql/kysely-libsql"],
3099
+ mysql2: deps["mysql2"],
3100
+ pg: deps["pg"],
3101
+ postgres: deps["postgres"],
3102
+ "@prisma/client": deps["@prisma/client"],
3103
+ drizzle: deps["drizzle-orm"],
3104
+ kysely: deps["kysely"],
3105
+ mongodb: deps["mongodb"],
3106
+ "@neondatabase/serverless": deps["@neondatabase/serverless"],
3107
+ "@vercel/postgres": deps["@vercel/postgres"],
3108
+ "@planetscale/database": deps["@planetscale/database"]
3109
+ };
3110
+ const installedDatabases = Object.entries(databases).filter(([_, version]) => version).map(([name, version]) => ({ name, version }));
3111
+ return installedDatabases.length > 0 ? installedDatabases : null;
3112
+ } catch {
3113
+ return null;
3114
+ }
3115
+ }
3116
+ function sanitizeBetterAuthConfig(config) {
3117
+ if (!config) return null;
3118
+ const sanitized = JSON.parse(JSON.stringify(config));
3119
+ const sensitiveKeys = [
3120
+ "secret",
3121
+ "clientSecret",
3122
+ "clientId",
3123
+ "authToken",
3124
+ "apiKey",
3125
+ "apiSecret",
3126
+ "privateKey",
3127
+ "publicKey",
3128
+ "password",
3129
+ "token",
3130
+ "webhook",
3131
+ "connectionString",
3132
+ "databaseUrl",
3133
+ "databaseURL",
3134
+ "TURSO_AUTH_TOKEN",
3135
+ "TURSO_DATABASE_URL",
3136
+ "MYSQL_DATABASE_URL",
3137
+ "DATABASE_URL",
3138
+ "POSTGRES_URL",
3139
+ "MONGODB_URI",
3140
+ "stripeKey",
3141
+ "stripeWebhookSecret"
3142
+ ];
3143
+ const allowedKeys = [
3144
+ "baseURL",
3145
+ "callbackURL",
3146
+ "redirectURL",
3147
+ "trustedOrigins",
3148
+ "appName"
3149
+ ];
3150
+ function redactSensitive(obj, parentKey) {
3151
+ if (typeof obj !== "object" || obj === null) {
3152
+ if (parentKey && typeof obj === "string" && obj.length > 0) {
3153
+ if (allowedKeys.some(
3154
+ (allowed) => parentKey.toLowerCase() === allowed.toLowerCase()
3155
+ )) {
3156
+ return obj;
3157
+ }
3158
+ const lowerKey = parentKey.toLowerCase();
3159
+ if (sensitiveKeys.some((key) => {
3160
+ const lowerSensitiveKey = key.toLowerCase();
3161
+ return lowerKey === lowerSensitiveKey || lowerKey.endsWith(lowerSensitiveKey);
3162
+ })) {
3163
+ return "[REDACTED]";
3164
+ }
3165
+ }
3166
+ return obj;
3167
+ }
3168
+ if (Array.isArray(obj)) {
3169
+ return obj.map((item) => redactSensitive(item, parentKey));
3170
+ }
3171
+ const result = {};
3172
+ for (const [key, value] of Object.entries(obj)) {
3173
+ if (allowedKeys.some(
3174
+ (allowed) => key.toLowerCase() === allowed.toLowerCase()
3175
+ )) {
3176
+ result[key] = value;
3177
+ continue;
3178
+ }
3179
+ const lowerKey = key.toLowerCase();
3180
+ if (sensitiveKeys.some((sensitiveKey) => {
3181
+ const lowerSensitiveKey = sensitiveKey.toLowerCase();
3182
+ return lowerKey === lowerSensitiveKey || lowerKey.endsWith(lowerSensitiveKey);
3183
+ })) {
3184
+ if (typeof value === "string" && value.length > 0) {
3185
+ result[key] = "[REDACTED]";
3186
+ } else if (typeof value === "object" && value !== null) {
3187
+ result[key] = redactSensitive(value, key);
3188
+ } else {
3189
+ result[key] = value;
3190
+ }
3191
+ } else {
3192
+ result[key] = redactSensitive(value, key);
3193
+ }
3194
+ }
3195
+ return result;
3196
+ }
3197
+ if (sanitized.database) {
3198
+ if (typeof sanitized.database === "string") {
3199
+ sanitized.database = "[REDACTED]";
3200
+ } else if (sanitized.database.url) {
3201
+ sanitized.database.url = "[REDACTED]";
3202
+ }
3203
+ if (sanitized.database.authToken) {
3204
+ sanitized.database.authToken = "[REDACTED]";
3205
+ }
3206
+ }
3207
+ if (sanitized.socialProviders) {
3208
+ for (const provider in sanitized.socialProviders) {
3209
+ if (sanitized.socialProviders[provider]) {
3210
+ sanitized.socialProviders[provider] = redactSensitive(
3211
+ sanitized.socialProviders[provider],
3212
+ provider
3213
+ );
3214
+ }
3215
+ }
3216
+ }
3217
+ if (sanitized.emailAndPassword?.sendResetPassword) {
3218
+ sanitized.emailAndPassword.sendResetPassword = "[Function]";
3219
+ }
3220
+ if (sanitized.emailVerification?.sendVerificationEmail) {
3221
+ sanitized.emailVerification.sendVerificationEmail = "[Function]";
3222
+ }
3223
+ if (sanitized.plugins && Array.isArray(sanitized.plugins)) {
3224
+ sanitized.plugins = sanitized.plugins.map((plugin) => {
3225
+ if (typeof plugin === "function") {
3226
+ return "[Plugin Function]";
3227
+ }
3228
+ if (plugin && typeof plugin === "object") {
3229
+ const pluginName = plugin.id || plugin.name || "unknown";
3230
+ return {
3231
+ name: pluginName,
3232
+ config: redactSensitive(plugin.config || plugin)
3233
+ };
3234
+ }
3235
+ return plugin;
3236
+ });
3237
+ }
3238
+ return redactSensitive(sanitized);
3239
+ }
3240
+ async function getBetterAuthInfo(projectRoot, configPath, suppressLogs = false) {
3241
+ try {
3242
+ const originalLog = console.log;
3243
+ const originalWarn = console.warn;
3244
+ const originalError = console.error;
3245
+ if (suppressLogs) {
3246
+ console.log = () => {
3247
+ };
3248
+ console.warn = () => {
3249
+ };
3250
+ console.error = () => {
3251
+ };
3252
+ }
3253
+ try {
3254
+ const config = await getConfig({
3255
+ cwd: projectRoot,
3256
+ configPath,
3257
+ shouldThrowOnError: false
3258
+ });
3259
+ const packageInfo = await getPackageInfo();
3260
+ return {
3261
+ version: packageInfo.version || "Unknown",
3262
+ config: sanitizeBetterAuthConfig(config)
3263
+ };
3264
+ } finally {
3265
+ if (suppressLogs) {
3266
+ console.log = originalLog;
3267
+ console.warn = originalWarn;
3268
+ console.error = originalError;
3269
+ }
3270
+ }
3271
+ } catch (error) {
3272
+ return {
3273
+ version: "Unknown",
3274
+ config: null,
3275
+ error: error instanceof Error ? error.message : "Failed to load Better Auth config"
3276
+ };
3277
+ }
3278
+ }
3279
+ function formatOutput(data, indent = 0) {
3280
+ const spaces = " ".repeat(indent);
3281
+ if (data === null || data === void 0) {
3282
+ return `${spaces}${chalk.gray("N/A")}`;
3283
+ }
3284
+ if (typeof data === "string" || typeof data === "number" || typeof data === "boolean") {
3285
+ return `${spaces}${data}`;
3286
+ }
3287
+ if (Array.isArray(data)) {
3288
+ if (data.length === 0) {
3289
+ return `${spaces}${chalk.gray("[]")}`;
3290
+ }
3291
+ return data.map((item) => formatOutput(item, indent)).join("\n");
3292
+ }
3293
+ if (typeof data === "object") {
3294
+ const entries = Object.entries(data);
3295
+ if (entries.length === 0) {
3296
+ return `${spaces}${chalk.gray("{}")}`;
3297
+ }
3298
+ return entries.map(([key, value]) => {
3299
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
3300
+ return `${spaces}${chalk.cyan(key)}:
3301
+ ${formatOutput(value, indent + 2)}`;
3302
+ }
3303
+ return `${spaces}${chalk.cyan(key)}: ${formatOutput(value, 0)}`;
3304
+ }).join("\n");
3305
+ }
3306
+ return `${spaces}${JSON.stringify(data)}`;
3307
+ }
3308
+ const info = new Command("info").description("Display system and Better Auth configuration information").option("--cwd <cwd>", "The working directory", process.cwd()).option("--config <config>", "Path to the Better Auth configuration file").option("-j, --json", "Output as JSON").option("-c, --copy", "Copy output to clipboard (requires pbcopy/xclip)").action(async (options) => {
3309
+ const projectRoot = path.resolve(options.cwd || process.cwd());
3310
+ const systemInfo = getSystemInfo();
3311
+ const nodeInfo = getNodeInfo();
3312
+ const packageManager = getPackageManager();
3313
+ const frameworks = getFrameworkInfo(projectRoot);
3314
+ const databases = getDatabaseInfo(projectRoot);
3315
+ const betterAuthInfo = await getBetterAuthInfo(
3316
+ projectRoot,
3317
+ options.config,
3318
+ options.json
3319
+ );
3320
+ const fullInfo = {
3321
+ system: systemInfo,
3322
+ node: nodeInfo,
3323
+ packageManager,
3324
+ frameworks,
3325
+ databases,
3326
+ betterAuth: betterAuthInfo
3327
+ };
3328
+ if (options.json) {
3329
+ const jsonOutput = JSON.stringify(fullInfo, null, 2);
3330
+ console.log(jsonOutput);
3331
+ if (options.copy) {
3332
+ try {
3333
+ const platform = os.platform();
3334
+ if (platform === "darwin") {
3335
+ execSync("pbcopy", { input: jsonOutput });
3336
+ console.log(chalk.green("\n\u2713 Copied to clipboard"));
3337
+ } else if (platform === "linux") {
3338
+ execSync("xclip -selection clipboard", { input: jsonOutput });
3339
+ console.log(chalk.green("\n\u2713 Copied to clipboard"));
3340
+ } else if (platform === "win32") {
3341
+ execSync("clip", { input: jsonOutput });
3342
+ console.log(chalk.green("\n\u2713 Copied to clipboard"));
3343
+ }
3344
+ } catch {
3345
+ console.log(chalk.yellow("\n\u26A0 Could not copy to clipboard"));
3346
+ }
3347
+ }
3348
+ return;
3349
+ }
3350
+ console.log(chalk.bold("\n\u{1F4CA} Better Auth System Information\n"));
3351
+ console.log(chalk.gray("=".repeat(50)));
3352
+ console.log(chalk.bold.white("\n\u{1F5A5}\uFE0F System Information:"));
3353
+ console.log(formatOutput(systemInfo, 2));
3354
+ console.log(chalk.bold.white("\n\u{1F4E6} Node.js:"));
3355
+ console.log(formatOutput(nodeInfo, 2));
3356
+ console.log(chalk.bold.white("\n\u{1F4E6} Package Manager:"));
3357
+ console.log(formatOutput(packageManager, 2));
3358
+ if (frameworks) {
3359
+ console.log(chalk.bold.white("\n\u{1F680} Frameworks:"));
3360
+ console.log(formatOutput(frameworks, 2));
3361
+ }
3362
+ if (databases) {
3363
+ console.log(chalk.bold.white("\n\u{1F4BE} Database Clients:"));
3364
+ console.log(formatOutput(databases, 2));
3365
+ }
3366
+ console.log(chalk.bold.white("\n\u{1F510} Better Auth:"));
3367
+ if (betterAuthInfo.error) {
3368
+ console.log(` ${chalk.red("Error:")} ${betterAuthInfo.error}`);
3369
+ } else {
3370
+ console.log(` ${chalk.cyan("Version")}: ${betterAuthInfo.version}`);
3371
+ if (betterAuthInfo.config) {
3372
+ console.log(` ${chalk.cyan("Configuration")}:`);
3373
+ console.log(formatOutput(betterAuthInfo.config, 4));
3374
+ }
3375
+ }
3376
+ console.log(chalk.gray("\n" + "=".repeat(50)));
3377
+ console.log(chalk.gray("\n\u{1F4A1} Tip: Use --json flag for JSON output"));
3378
+ console.log(chalk.gray("\u{1F4A1} Use --copy flag to copy output to clipboard"));
3379
+ console.log(
3380
+ chalk.gray("\u{1F4A1} When reporting issues, include this information\n")
3381
+ );
3382
+ if (options.copy) {
3383
+ const textOutput = `
3384
+ Better Auth System Information
3385
+ ==============================
3386
+
3387
+ System Information:
3388
+ ${JSON.stringify(systemInfo, null, 2)}
3389
+
3390
+ Node.js:
3391
+ ${JSON.stringify(nodeInfo, null, 2)}
3392
+
3393
+ Package Manager:
3394
+ ${JSON.stringify(packageManager, null, 2)}
3395
+
3396
+ Frameworks:
3397
+ ${JSON.stringify(frameworks, null, 2)}
3398
+
3399
+ Database Clients:
3400
+ ${JSON.stringify(databases, null, 2)}
3401
+
3402
+ Better Auth:
3403
+ ${JSON.stringify(betterAuthInfo, null, 2)}
3404
+ `;
3405
+ try {
3406
+ const platform = os.platform();
3407
+ if (platform === "darwin") {
3408
+ execSync("pbcopy", { input: textOutput });
3409
+ console.log(chalk.green("\u2713 Copied to clipboard"));
3410
+ } else if (platform === "linux") {
3411
+ execSync("xclip -selection clipboard", { input: textOutput });
3412
+ console.log(chalk.green("\u2713 Copied to clipboard"));
3413
+ } else if (platform === "win32") {
3414
+ execSync("clip", { input: textOutput });
3415
+ console.log(chalk.green("\u2713 Copied to clipboard"));
3416
+ }
3417
+ } catch {
3418
+ console.log(chalk.yellow("\u26A0 Could not copy to clipboard"));
3419
+ }
3420
+ }
3421
+ });
3422
+
3006
3423
  process.on("SIGINT", () => process.exit(0));
3007
3424
  process.on("SIGTERM", () => process.exit(0));
3008
3425
  async function main() {
@@ -3012,7 +3429,7 @@ async function main() {
3012
3429
  packageInfo = await getPackageInfo();
3013
3430
  } catch (error) {
3014
3431
  }
3015
- program.addCommand(init).addCommand(migrate).addCommand(generate).addCommand(generateSecret).addCommand(login).version(packageInfo.version || "1.1.2").description("Better Auth CLI").action(() => program.help());
3432
+ program.addCommand(init).addCommand(migrate).addCommand(generate).addCommand(generateSecret).addCommand(info).addCommand(login).version(packageInfo.version || "1.1.2").description("Better Auth CLI").action(() => program.help());
3016
3433
  program.parse();
3017
3434
  }
3018
3435
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/cli",
3
- "version": "1.3.8-beta.4",
3
+ "version": "1.3.8-beta.6",
4
4
  "description": "The CLI for Better Auth",
5
5
  "module": "dist/index.mjs",
6
6
  "repository": {
@@ -54,7 +54,7 @@
54
54
  "tinyexec": "^0.3.1",
55
55
  "yocto-spinner": "^0.1.1",
56
56
  "zod": "^4.0.0",
57
- "better-auth": "1.3.8-beta.4"
57
+ "better-auth": "1.3.8-beta.6"
58
58
  },
59
59
  "files": [
60
60
  "dist"