@better-auth/cli 1.3.8-beta.3 → 1.3.8-beta.5

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 +447 -25
  2. package/package.json +4 -10
package/dist/index.mjs CHANGED
@@ -4,13 +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$2, { 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
- import fs from 'fs-extra';
11
10
  import chalk from 'chalk';
12
11
  import { intro, log, outro, confirm, isCancel, cancel, spinner, text, select, multiselect } from '@clack/prompts';
13
- import { exec } from 'child_process';
12
+ import { exec, execSync } from 'child_process';
14
13
  import { logger, BetterAuthError, createTelemetry, getTelemetryAuthConfig, capitalizeFirstLetter } from 'better-auth';
15
14
  import Crypto from 'crypto';
16
15
  import yoctoSpinner from 'yocto-spinner';
@@ -28,11 +27,7 @@ import 'dotenv/config';
28
27
 
29
28
  function getPackageInfo(cwd) {
30
29
  const packageJsonPath = cwd ? path.join(cwd, "package.json") : path.join("package.json");
31
- try {
32
- return fs.readJSONSync(packageJsonPath);
33
- } catch (error) {
34
- throw error;
35
- }
30
+ return JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
36
31
  }
37
32
 
38
33
  function installDependencies({
@@ -1074,7 +1069,7 @@ async function initAction(opts) {
1074
1069
  process.exit(0);
1075
1070
  }
1076
1071
  if (packageManagerPreference === void 0) {
1077
- packageManagerPreference = await getPackageManager();
1072
+ packageManagerPreference = await getPackageManager$1();
1078
1073
  }
1079
1074
  if (shouldInstallBetterAuthDep) {
1080
1075
  s2.start(
@@ -1114,7 +1109,7 @@ async function initAction(opts) {
1114
1109
  }
1115
1110
  if (shouldInstallBetterAuthDep) {
1116
1111
  if (packageManagerPreference === void 0) {
1117
- packageManagerPreference = await getPackageManager();
1112
+ packageManagerPreference = await getPackageManager$1();
1118
1113
  }
1119
1114
  const s2 = spinner({ indicator: "dots" });
1120
1115
  s2.start(
@@ -1342,7 +1337,7 @@ async function initAction(opts) {
1342
1337
  if (shouldInstallDeps) {
1343
1338
  const s2 = spinner({ indicator: "dots" });
1344
1339
  if (packageManagerPreference === void 0) {
1345
- packageManagerPreference = await getPackageManager();
1340
+ packageManagerPreference = await getPackageManager$1();
1346
1341
  }
1347
1342
  s2.start(
1348
1343
  `Installing dependencies using ${chalk.bold(
@@ -1591,7 +1586,7 @@ async function getLatestNpmVersion(packageName) {
1591
1586
  throw error?.message;
1592
1587
  }
1593
1588
  }
1594
- async function getPackageManager() {
1589
+ async function getPackageManager$1() {
1595
1590
  const { hasBun, hasPnpm } = await checkPackageManagers();
1596
1591
  if (!hasBun && !hasPnpm) return "npm";
1597
1592
  const packageManagerOptions = [];
@@ -1694,9 +1689,9 @@ function getSvelteKitPathAliases(cwd) {
1694
1689
  const svelteConfigPath = path.join(cwd, "svelte.config.js");
1695
1690
  const svelteConfigTsPath = path.join(cwd, "svelte.config.ts");
1696
1691
  let isSvelteKitProject = false;
1697
- if (fs$2.existsSync(packageJsonPath)) {
1692
+ if (fs.existsSync(packageJsonPath)) {
1698
1693
  try {
1699
- const packageJson = JSON.parse(fs$2.readFileSync(packageJsonPath, "utf-8"));
1694
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
1700
1695
  const deps = {
1701
1696
  ...packageJson.dependencies,
1702
1697
  ...packageJson.devDependencies
@@ -1706,19 +1701,19 @@ function getSvelteKitPathAliases(cwd) {
1706
1701
  }
1707
1702
  }
1708
1703
  if (!isSvelteKitProject) {
1709
- isSvelteKitProject = fs$2.existsSync(svelteConfigPath) || fs$2.existsSync(svelteConfigTsPath);
1704
+ isSvelteKitProject = fs.existsSync(svelteConfigPath) || fs.existsSync(svelteConfigTsPath);
1710
1705
  }
1711
1706
  if (!isSvelteKitProject) {
1712
1707
  return aliases;
1713
1708
  }
1714
1709
  const libPaths = [path.join(cwd, "src", "lib"), path.join(cwd, "lib")];
1715
1710
  for (const libPath of libPaths) {
1716
- if (fs$2.existsSync(libPath)) {
1711
+ if (fs.existsSync(libPath)) {
1717
1712
  aliases["$lib"] = libPath;
1718
1713
  const commonSubPaths = ["server", "utils", "components", "stores"];
1719
1714
  for (const subPath of commonSubPaths) {
1720
1715
  const subDir = path.join(libPath, subPath);
1721
- if (fs$2.existsSync(subDir)) {
1716
+ if (fs.existsSync(subDir)) {
1722
1717
  aliases[`$lib/${subPath}`] = subDir;
1723
1718
  }
1724
1719
  }
@@ -1737,9 +1732,9 @@ function getSvelteConfigAliases(cwd) {
1737
1732
  path.join(cwd, "svelte.config.ts")
1738
1733
  ];
1739
1734
  for (const configPath of configPaths) {
1740
- if (fs$2.existsSync(configPath)) {
1735
+ if (fs.existsSync(configPath)) {
1741
1736
  try {
1742
- const content = fs$2.readFileSync(configPath, "utf-8");
1737
+ const content = fs.readFileSync(configPath, "utf-8");
1743
1738
  const aliasMatch = content.match(/alias\s*:\s*\{([^}]+)\}/);
1744
1739
  if (aliasMatch && aliasMatch[1]) {
1745
1740
  const aliasContent = aliasMatch[1];
@@ -1875,9 +1870,9 @@ function resolveReferencePath(configDir, refPath) {
1875
1870
  if (refPath.endsWith(".json")) {
1876
1871
  return resolvedPath;
1877
1872
  }
1878
- if (fs$2.existsSync(resolvedPath)) {
1873
+ if (fs.existsSync(resolvedPath)) {
1879
1874
  try {
1880
- const stats = fs$2.statSync(resolvedPath);
1875
+ const stats = fs.statSync(resolvedPath);
1881
1876
  if (stats.isFile()) {
1882
1877
  return resolvedPath;
1883
1878
  }
@@ -1891,7 +1886,7 @@ function getPathAliasesRecursive(tsconfigPath, visited = /* @__PURE__ */ new Set
1891
1886
  return {};
1892
1887
  }
1893
1888
  visited.add(tsconfigPath);
1894
- if (!fs$2.existsSync(tsconfigPath)) {
1889
+ if (!fs.existsSync(tsconfigPath)) {
1895
1890
  logger.warn(`Referenced tsconfig not found: ${tsconfigPath}`);
1896
1891
  return {};
1897
1892
  }
@@ -1928,7 +1923,7 @@ function getPathAliasesRecursive(tsconfigPath, visited = /* @__PURE__ */ new Set
1928
1923
  }
1929
1924
  function getPathAliases(cwd) {
1930
1925
  const tsConfigPath = path.join(cwd, "tsconfig.json");
1931
- if (!fs$2.existsSync(tsConfigPath)) {
1926
+ if (!fs.existsSync(tsConfigPath)) {
1932
1927
  return null;
1933
1928
  }
1934
1929
  try {
@@ -2342,8 +2337,13 @@ const generateDrizzleSchema = async ({
2342
2337
  type += `.default(${attr.defaultValue})`;
2343
2338
  }
2344
2339
  }
2340
+ if (attr.onUpdate && attr.type === "date") {
2341
+ if (typeof attr.onUpdate === "function") {
2342
+ type += `.$onUpdate(${attr.onUpdate})`;
2343
+ }
2344
+ }
2345
2345
  return `${field}: ${type}${attr.required ? ".notNull()" : ""}${attr.unique ? ".unique()" : ""}${attr.references ? `.references(()=> ${getModelName(
2346
- attr.references.model,
2346
+ tables[attr.references.model]?.modelName || attr.references.model,
2347
2347
  adapter.options
2348
2348
  )}.${attr.references.field}, { onDelete: '${attr.references.onDelete || "cascade"}' })` : ""}`;
2349
2349
  }).join(",\n ")}
@@ -2899,6 +2899,11 @@ async function loginAction(opts) {
2899
2899
  "\n\u{1F4DD} Note: This was a demo authentication for testing purposes."
2900
2900
  )
2901
2901
  );
2902
+ console.log(
2903
+ chalk.blue(
2904
+ "\nFor more information, visit: https://better-auth.com/docs/plugins/device-authorization"
2905
+ )
2906
+ );
2902
2907
  }
2903
2908
  } catch (err) {
2904
2909
  spinner.stop();
@@ -2998,6 +3003,423 @@ const login = new Command("login").description(
2998
3003
  "Demo: Test device authorization flow with Better Auth demo server"
2999
3004
  ).option("--server-url <url>", "The Better Auth server URL", DEMO_URL).option("--client-id <id>", "The OAuth client ID", CLIENT_ID).action(loginAction);
3000
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
+
3001
3423
  process.on("SIGINT", () => process.exit(0));
3002
3424
  process.on("SIGTERM", () => process.exit(0));
3003
3425
  async function main() {
@@ -3007,7 +3429,7 @@ async function main() {
3007
3429
  packageInfo = await getPackageInfo();
3008
3430
  } catch (error) {
3009
3431
  }
3010
- 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());
3011
3433
  program.parse();
3012
3434
  }
3013
3435
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/cli",
3
- "version": "1.3.8-beta.3",
3
+ "version": "1.3.8-beta.5",
4
4
  "description": "The CLI for Better Auth",
5
5
  "module": "dist/index.mjs",
6
6
  "repository": {
@@ -26,12 +26,9 @@
26
26
  "exports": "./dist/index.mjs",
27
27
  "bin": "./dist/index.mjs",
28
28
  "devDependencies": {
29
- "@types/diff": "^7.0.1",
30
- "@types/fs-extra": "^11.0.4",
31
29
  "tsx": "^4.20.4",
32
30
  "typescript": "^5.9.2",
33
- "unbuild": "^3.5.0",
34
- "zod": "^4.0.0"
31
+ "unbuild": "^3.5.0"
35
32
  },
36
33
  "dependencies": {
37
34
  "@babel/core": "^7.0.0",
@@ -48,7 +45,6 @@
48
45
  "commander": "^12.1.0",
49
46
  "dotenv": "^16.4.7",
50
47
  "drizzle-orm": "^0.33.0",
51
- "fs-extra": "^11.3.0",
52
48
  "get-tsconfig": "^4.8.1",
53
49
  "open": "^10.1.0",
54
50
  "prettier": "^3.4.2",
@@ -57,10 +53,8 @@
57
53
  "semver": "^7.7.1",
58
54
  "tinyexec": "^0.3.1",
59
55
  "yocto-spinner": "^0.1.1",
60
- "better-auth": "1.3.8-beta.3"
61
- },
62
- "peerDependencies": {
63
- "zod": "3.25.0 || ^4.0.0"
56
+ "zod": "^4.0.0",
57
+ "better-auth": "1.3.8-beta.5"
64
58
  },
65
59
  "files": [
66
60
  "dist"