@better-auth/cli 1.4.0-beta.6 → 1.4.0-beta.7
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.mjs +271 -76
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -4,8 +4,10 @@ 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
|
|
8
|
-
import
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import fs__default, { existsSync, readFileSync } from 'fs';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import path__default from 'path';
|
|
9
11
|
import fs$1 from 'fs/promises';
|
|
10
12
|
import chalk from 'chalk';
|
|
11
13
|
import { intro, log, outro, confirm, isCancel, cancel, spinner, text, select, multiselect } from '@clack/prompts';
|
|
@@ -22,12 +24,14 @@ import { produceSchema } from '@mrleebo/prisma-ast';
|
|
|
22
24
|
import { createAuthClient } from 'better-auth/client';
|
|
23
25
|
import { deviceAuthorizationClient } from 'better-auth/client/plugins';
|
|
24
26
|
import open from 'open';
|
|
25
|
-
import os from 'os';
|
|
27
|
+
import * as os from 'os';
|
|
28
|
+
import os__default from 'os';
|
|
29
|
+
import { base64 } from '@better-auth/utils/base64';
|
|
26
30
|
import 'dotenv/config';
|
|
27
31
|
|
|
28
32
|
function getPackageInfo(cwd) {
|
|
29
|
-
const packageJsonPath = cwd ?
|
|
30
|
-
return JSON.parse(
|
|
33
|
+
const packageJsonPath = cwd ? path__default.join(cwd, "package.json") : path__default.join("package.json");
|
|
34
|
+
return JSON.parse(fs__default.readFileSync(packageJsonPath, "utf-8"));
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
function installDependencies({
|
|
@@ -678,10 +682,10 @@ function getTsconfigInfo(cwd, flatPath) {
|
|
|
678
682
|
if (flatPath) {
|
|
679
683
|
tsConfigPath = flatPath;
|
|
680
684
|
} else {
|
|
681
|
-
tsConfigPath = cwd ?
|
|
685
|
+
tsConfigPath = cwd ? path__default.join(cwd, "tsconfig.json") : path__default.join("tsconfig.json");
|
|
682
686
|
}
|
|
683
687
|
try {
|
|
684
|
-
const text =
|
|
688
|
+
const text = fs__default.readFileSync(tsConfigPath, "utf-8");
|
|
685
689
|
return JSON.parse(stripJsonComments(text));
|
|
686
690
|
} catch (error) {
|
|
687
691
|
throw error;
|
|
@@ -965,7 +969,7 @@ async function initAction(opts) {
|
|
|
965
969
|
console.log();
|
|
966
970
|
intro("\u{1F44B} Initializing Better Auth");
|
|
967
971
|
const options = optionsSchema.parse(opts);
|
|
968
|
-
const cwd =
|
|
972
|
+
const cwd = path__default.resolve(options.cwd);
|
|
969
973
|
let packageManagerPreference = void 0;
|
|
970
974
|
let config_path = "";
|
|
971
975
|
let framework = "vanilla";
|
|
@@ -995,7 +999,7 @@ async function initAction(opts) {
|
|
|
995
999
|
else targetEnvFile = "none";
|
|
996
1000
|
let tsconfigInfo;
|
|
997
1001
|
try {
|
|
998
|
-
const tsconfigPath = options.tsconfig !== void 0 ?
|
|
1002
|
+
const tsconfigPath = options.tsconfig !== void 0 ? path__default.resolve(cwd, options.tsconfig) : path__default.join(cwd, "tsconfig.json");
|
|
999
1003
|
tsconfigInfo = await getTsconfigInfo(cwd, tsconfigPath);
|
|
1000
1004
|
} catch (error) {
|
|
1001
1005
|
log.error(`\u274C Couldn't read your tsconfig.json file. (dir: ${cwd})`);
|
|
@@ -1018,7 +1022,7 @@ async function initAction(opts) {
|
|
|
1018
1022
|
if (shouldAdd) {
|
|
1019
1023
|
try {
|
|
1020
1024
|
await fs$1.writeFile(
|
|
1021
|
-
|
|
1025
|
+
path__default.join(cwd, "tsconfig.json"),
|
|
1022
1026
|
await format(
|
|
1023
1027
|
JSON.stringify(
|
|
1024
1028
|
Object.assign(tsconfigInfo, {
|
|
@@ -1157,12 +1161,12 @@ async function initAction(opts) {
|
|
|
1157
1161
|
...possiblePaths.map((it) => `app/${it}`)
|
|
1158
1162
|
];
|
|
1159
1163
|
if (options.config) {
|
|
1160
|
-
config_path =
|
|
1164
|
+
config_path = path__default.join(cwd, options.config);
|
|
1161
1165
|
} else {
|
|
1162
1166
|
for (const possiblePath of possiblePaths) {
|
|
1163
|
-
const doesExist = existsSync(
|
|
1167
|
+
const doesExist = existsSync(path__default.join(cwd, possiblePath));
|
|
1164
1168
|
if (doesExist) {
|
|
1165
|
-
config_path =
|
|
1169
|
+
config_path = path__default.join(cwd, possiblePath);
|
|
1166
1170
|
break;
|
|
1167
1171
|
}
|
|
1168
1172
|
}
|
|
@@ -1232,7 +1236,7 @@ async function initAction(opts) {
|
|
|
1232
1236
|
".next/server/next.config.mjs"
|
|
1233
1237
|
];
|
|
1234
1238
|
for (const possible_next_config_path of possible_next_config_paths) {
|
|
1235
|
-
if (existsSync(
|
|
1239
|
+
if (existsSync(path__default.join(cwd, possible_next_config_path))) {
|
|
1236
1240
|
framework = "nextjs";
|
|
1237
1241
|
break;
|
|
1238
1242
|
}
|
|
@@ -1255,7 +1259,7 @@ async function initAction(opts) {
|
|
|
1255
1259
|
}
|
|
1256
1260
|
}
|
|
1257
1261
|
}
|
|
1258
|
-
const filePath =
|
|
1262
|
+
const filePath = path__default.join(cwd, "auth.ts");
|
|
1259
1263
|
config_path = filePath;
|
|
1260
1264
|
log.info(`Creating auth config file: ${filePath}`);
|
|
1261
1265
|
try {
|
|
@@ -1289,7 +1293,7 @@ async function initAction(opts) {
|
|
|
1289
1293
|
const filesToUpdate = await multiselect({
|
|
1290
1294
|
message: "Select the .env files you want to update",
|
|
1291
1295
|
options: envFiles.map((x) => ({
|
|
1292
|
-
value:
|
|
1296
|
+
value: path__default.join(cwd, x),
|
|
1293
1297
|
label: x
|
|
1294
1298
|
})),
|
|
1295
1299
|
required: false
|
|
@@ -1397,9 +1401,9 @@ async function initAction(opts) {
|
|
|
1397
1401
|
];
|
|
1398
1402
|
let authClientConfigPath = null;
|
|
1399
1403
|
for (const possiblePath of possibleClientPaths) {
|
|
1400
|
-
const doesExist = existsSync(
|
|
1404
|
+
const doesExist = existsSync(path__default.join(cwd, possiblePath));
|
|
1401
1405
|
if (doesExist) {
|
|
1402
|
-
authClientConfigPath =
|
|
1406
|
+
authClientConfigPath = path__default.join(cwd, possiblePath);
|
|
1403
1407
|
break;
|
|
1404
1408
|
}
|
|
1405
1409
|
}
|
|
@@ -1416,11 +1420,11 @@ async function initAction(opts) {
|
|
|
1416
1420
|
process.exit(0);
|
|
1417
1421
|
}
|
|
1418
1422
|
if (choice === "yes") {
|
|
1419
|
-
authClientConfigPath =
|
|
1423
|
+
authClientConfigPath = path__default.join(cwd, "auth-client.ts");
|
|
1420
1424
|
log.info(`Creating auth client config file: ${authClientConfigPath}`);
|
|
1421
1425
|
try {
|
|
1422
1426
|
let contents = await getDefaultAuthClientConfig({
|
|
1423
|
-
auth_config_path: ("./" +
|
|
1427
|
+
auth_config_path: ("./" + path__default.join(config_path.replace(cwd, ""))).replace(".//", "./"),
|
|
1424
1428
|
clientPlugins: add_plugins.filter((x) => x.clientName).map((plugin) => {
|
|
1425
1429
|
let contents2 = "";
|
|
1426
1430
|
if (plugin.id === "one-tap") {
|
|
@@ -1462,7 +1466,7 @@ async function initAction(opts) {
|
|
|
1462
1466
|
if (targetEnvFile !== "none") {
|
|
1463
1467
|
try {
|
|
1464
1468
|
const fileContents = await fs$1.readFile(
|
|
1465
|
-
|
|
1469
|
+
path__default.join(cwd, targetEnvFile),
|
|
1466
1470
|
"utf8"
|
|
1467
1471
|
);
|
|
1468
1472
|
const parsed = parse(fileContents);
|
|
@@ -1501,7 +1505,7 @@ async function initAction(opts) {
|
|
|
1501
1505
|
if (shouldAdd === "yes") {
|
|
1502
1506
|
try {
|
|
1503
1507
|
await updateEnvs({
|
|
1504
|
-
files: [
|
|
1508
|
+
files: [path__default.join(cwd, targetEnvFile)],
|
|
1505
1509
|
envs,
|
|
1506
1510
|
isCommented: false
|
|
1507
1511
|
});
|
|
@@ -1526,7 +1530,7 @@ async function initAction(opts) {
|
|
|
1526
1530
|
const envFilesToUpdate = await multiselect({
|
|
1527
1531
|
message: "Select the .env files you want to update",
|
|
1528
1532
|
options: envFiles.map((x) => ({
|
|
1529
|
-
value:
|
|
1533
|
+
value: path__default.join(cwd, x),
|
|
1530
1534
|
label: x
|
|
1531
1535
|
})),
|
|
1532
1536
|
required: false
|
|
@@ -1678,13 +1682,13 @@ function addSvelteKitEnvModules(aliases, cwd) {
|
|
|
1678
1682
|
}
|
|
1679
1683
|
function getSvelteKitPathAliases(cwd) {
|
|
1680
1684
|
const aliases = {};
|
|
1681
|
-
const packageJsonPath =
|
|
1682
|
-
const svelteConfigPath =
|
|
1683
|
-
const svelteConfigTsPath =
|
|
1685
|
+
const packageJsonPath = path__default.join(cwd, "package.json");
|
|
1686
|
+
const svelteConfigPath = path__default.join(cwd, "svelte.config.js");
|
|
1687
|
+
const svelteConfigTsPath = path__default.join(cwd, "svelte.config.ts");
|
|
1684
1688
|
let isSvelteKitProject = false;
|
|
1685
|
-
if (
|
|
1689
|
+
if (fs__default.existsSync(packageJsonPath)) {
|
|
1686
1690
|
try {
|
|
1687
|
-
const packageJson = JSON.parse(
|
|
1691
|
+
const packageJson = JSON.parse(fs__default.readFileSync(packageJsonPath, "utf-8"));
|
|
1688
1692
|
const deps = {
|
|
1689
1693
|
...packageJson.dependencies,
|
|
1690
1694
|
...packageJson.devDependencies
|
|
@@ -1694,19 +1698,19 @@ function getSvelteKitPathAliases(cwd) {
|
|
|
1694
1698
|
}
|
|
1695
1699
|
}
|
|
1696
1700
|
if (!isSvelteKitProject) {
|
|
1697
|
-
isSvelteKitProject =
|
|
1701
|
+
isSvelteKitProject = fs__default.existsSync(svelteConfigPath) || fs__default.existsSync(svelteConfigTsPath);
|
|
1698
1702
|
}
|
|
1699
1703
|
if (!isSvelteKitProject) {
|
|
1700
1704
|
return aliases;
|
|
1701
1705
|
}
|
|
1702
|
-
const libPaths = [
|
|
1706
|
+
const libPaths = [path__default.join(cwd, "src", "lib"), path__default.join(cwd, "lib")];
|
|
1703
1707
|
for (const libPath of libPaths) {
|
|
1704
|
-
if (
|
|
1708
|
+
if (fs__default.existsSync(libPath)) {
|
|
1705
1709
|
aliases["$lib"] = libPath;
|
|
1706
1710
|
const commonSubPaths = ["server", "utils", "components", "stores"];
|
|
1707
1711
|
for (const subPath of commonSubPaths) {
|
|
1708
|
-
const subDir =
|
|
1709
|
-
if (
|
|
1712
|
+
const subDir = path__default.join(libPath, subPath);
|
|
1713
|
+
if (fs__default.existsSync(subDir)) {
|
|
1710
1714
|
aliases[`$lib/${subPath}`] = subDir;
|
|
1711
1715
|
}
|
|
1712
1716
|
}
|
|
@@ -1721,13 +1725,13 @@ function getSvelteKitPathAliases(cwd) {
|
|
|
1721
1725
|
function getSvelteConfigAliases(cwd) {
|
|
1722
1726
|
const aliases = {};
|
|
1723
1727
|
const configPaths = [
|
|
1724
|
-
|
|
1725
|
-
|
|
1728
|
+
path__default.join(cwd, "svelte.config.js"),
|
|
1729
|
+
path__default.join(cwd, "svelte.config.ts")
|
|
1726
1730
|
];
|
|
1727
1731
|
for (const configPath of configPaths) {
|
|
1728
|
-
if (
|
|
1732
|
+
if (fs__default.existsSync(configPath)) {
|
|
1729
1733
|
try {
|
|
1730
|
-
const content =
|
|
1734
|
+
const content = fs__default.readFileSync(configPath, "utf-8");
|
|
1731
1735
|
const aliasMatch = content.match(/alias\s*:\s*\{([^}]+)\}/);
|
|
1732
1736
|
if (aliasMatch && aliasMatch[1]) {
|
|
1733
1737
|
const aliasContent = aliasMatch[1];
|
|
@@ -1737,8 +1741,8 @@ function getSvelteConfigAliases(cwd) {
|
|
|
1737
1741
|
for (const match of aliasMatches) {
|
|
1738
1742
|
const [, alias, target] = match;
|
|
1739
1743
|
if (alias && target) {
|
|
1740
|
-
aliases[alias + "/*"] =
|
|
1741
|
-
aliases[alias] =
|
|
1744
|
+
aliases[alias + "/*"] = path__default.resolve(cwd, target) + "/*";
|
|
1745
|
+
aliases[alias] = path__default.resolve(cwd, target);
|
|
1742
1746
|
}
|
|
1743
1747
|
}
|
|
1744
1748
|
}
|
|
@@ -1859,27 +1863,27 @@ possiblePaths = [
|
|
|
1859
1863
|
...possiblePaths.map((it) => `app/${it}`)
|
|
1860
1864
|
];
|
|
1861
1865
|
function resolveReferencePath(configDir, refPath) {
|
|
1862
|
-
const resolvedPath =
|
|
1866
|
+
const resolvedPath = path__default.resolve(configDir, refPath);
|
|
1863
1867
|
if (refPath.endsWith(".json")) {
|
|
1864
1868
|
return resolvedPath;
|
|
1865
1869
|
}
|
|
1866
|
-
if (
|
|
1870
|
+
if (fs__default.existsSync(resolvedPath)) {
|
|
1867
1871
|
try {
|
|
1868
|
-
const stats =
|
|
1872
|
+
const stats = fs__default.statSync(resolvedPath);
|
|
1869
1873
|
if (stats.isFile()) {
|
|
1870
1874
|
return resolvedPath;
|
|
1871
1875
|
}
|
|
1872
1876
|
} catch {
|
|
1873
1877
|
}
|
|
1874
1878
|
}
|
|
1875
|
-
return
|
|
1879
|
+
return path__default.resolve(configDir, refPath, "tsconfig.json");
|
|
1876
1880
|
}
|
|
1877
1881
|
function getPathAliasesRecursive(tsconfigPath, visited = /* @__PURE__ */ new Set()) {
|
|
1878
1882
|
if (visited.has(tsconfigPath)) {
|
|
1879
1883
|
return {};
|
|
1880
1884
|
}
|
|
1881
1885
|
visited.add(tsconfigPath);
|
|
1882
|
-
if (!
|
|
1886
|
+
if (!fs__default.existsSync(tsconfigPath)) {
|
|
1883
1887
|
logger.warn(`Referenced tsconfig not found: ${tsconfigPath}`);
|
|
1884
1888
|
return {};
|
|
1885
1889
|
}
|
|
@@ -1887,14 +1891,14 @@ function getPathAliasesRecursive(tsconfigPath, visited = /* @__PURE__ */ new Set
|
|
|
1887
1891
|
const tsConfig = getTsconfigInfo(void 0, tsconfigPath);
|
|
1888
1892
|
const { paths = {}, baseUrl = "." } = tsConfig.compilerOptions || {};
|
|
1889
1893
|
const result = {};
|
|
1890
|
-
const configDir =
|
|
1894
|
+
const configDir = path__default.dirname(tsconfigPath);
|
|
1891
1895
|
const obj = Object.entries(paths);
|
|
1892
1896
|
for (const [alias, aliasPaths] of obj) {
|
|
1893
1897
|
for (const aliasedPath of aliasPaths) {
|
|
1894
|
-
const resolvedBaseUrl =
|
|
1898
|
+
const resolvedBaseUrl = path__default.resolve(configDir, baseUrl);
|
|
1895
1899
|
const finalAlias = alias.slice(-1) === "*" ? alias.slice(0, -1) : alias;
|
|
1896
1900
|
const finalAliasedPath = aliasedPath.slice(-1) === "*" ? aliasedPath.slice(0, -1) : aliasedPath;
|
|
1897
|
-
result[finalAlias || ""] =
|
|
1901
|
+
result[finalAlias || ""] = path__default.join(resolvedBaseUrl, finalAliasedPath);
|
|
1898
1902
|
}
|
|
1899
1903
|
}
|
|
1900
1904
|
if (tsConfig.references) {
|
|
@@ -1915,8 +1919,8 @@ function getPathAliasesRecursive(tsconfigPath, visited = /* @__PURE__ */ new Set
|
|
|
1915
1919
|
}
|
|
1916
1920
|
}
|
|
1917
1921
|
function getPathAliases(cwd) {
|
|
1918
|
-
const tsConfigPath =
|
|
1919
|
-
if (!
|
|
1922
|
+
const tsConfigPath = path__default.join(cwd, "tsconfig.json");
|
|
1923
|
+
if (!fs__default.existsSync(tsConfigPath)) {
|
|
1920
1924
|
return null;
|
|
1921
1925
|
}
|
|
1922
1926
|
try {
|
|
@@ -1960,7 +1964,7 @@ async function getConfig({
|
|
|
1960
1964
|
try {
|
|
1961
1965
|
let configFile = null;
|
|
1962
1966
|
if (configPath) {
|
|
1963
|
-
let resolvedPath =
|
|
1967
|
+
let resolvedPath = path__default.join(cwd, configPath);
|
|
1964
1968
|
if (existsSync(configPath)) resolvedPath = configPath;
|
|
1965
1969
|
const { config } = await loadConfig({
|
|
1966
1970
|
configFile: resolvedPath,
|
|
@@ -2057,7 +2061,7 @@ async function migrateAction(opts) {
|
|
|
2057
2061
|
y: z.boolean().optional(),
|
|
2058
2062
|
yes: z.boolean().optional()
|
|
2059
2063
|
}).parse(opts);
|
|
2060
|
-
const cwd =
|
|
2064
|
+
const cwd = path__default.resolve(options.cwd);
|
|
2061
2065
|
if (!existsSync(cwd)) {
|
|
2062
2066
|
logger.error(`The directory "${cwd}" does not exist.`);
|
|
2063
2067
|
process.exit(1);
|
|
@@ -2452,11 +2456,11 @@ const generatePrismaSchema = async ({
|
|
|
2452
2456
|
const provider = adapter.options?.provider || "postgresql";
|
|
2453
2457
|
const tables = getAuthTables(options);
|
|
2454
2458
|
const filePath = file || "./prisma/schema.prisma";
|
|
2455
|
-
const schemaPrismaExist = existsSync(
|
|
2459
|
+
const schemaPrismaExist = existsSync(path__default.join(process.cwd(), filePath));
|
|
2456
2460
|
let schemaPrisma = "";
|
|
2457
2461
|
if (schemaPrismaExist) {
|
|
2458
2462
|
schemaPrisma = await fs$1.readFile(
|
|
2459
|
-
|
|
2463
|
+
path__default.join(process.cwd(), filePath),
|
|
2460
2464
|
"utf-8"
|
|
2461
2465
|
);
|
|
2462
2466
|
} else {
|
|
@@ -2693,7 +2697,7 @@ async function generateAction(opts) {
|
|
|
2693
2697
|
y: z.boolean().optional(),
|
|
2694
2698
|
yes: z.boolean().optional()
|
|
2695
2699
|
}).parse(opts);
|
|
2696
|
-
const cwd =
|
|
2700
|
+
const cwd = path__default.resolve(options.cwd);
|
|
2697
2701
|
if (!existsSync(cwd)) {
|
|
2698
2702
|
logger.error(`The directory "${cwd}" does not exist.`);
|
|
2699
2703
|
process.exit(1);
|
|
@@ -2750,16 +2754,16 @@ async function generateAction(opts) {
|
|
|
2750
2754
|
confirm2 = response.confirm;
|
|
2751
2755
|
}
|
|
2752
2756
|
if (confirm2) {
|
|
2753
|
-
const exist = existsSync(
|
|
2757
|
+
const exist = existsSync(path__default.join(cwd, schema.fileName));
|
|
2754
2758
|
if (!exist) {
|
|
2755
|
-
await fs$1.mkdir(
|
|
2759
|
+
await fs$1.mkdir(path__default.dirname(path__default.join(cwd, schema.fileName)), {
|
|
2756
2760
|
recursive: true
|
|
2757
2761
|
});
|
|
2758
2762
|
}
|
|
2759
2763
|
if (schema.overwrite) {
|
|
2760
|
-
await fs$1.writeFile(
|
|
2764
|
+
await fs$1.writeFile(path__default.join(cwd, schema.fileName), schema.code);
|
|
2761
2765
|
} else {
|
|
2762
|
-
await fs$1.appendFile(
|
|
2766
|
+
await fs$1.appendFile(path__default.join(cwd, schema.fileName), schema.code);
|
|
2763
2767
|
}
|
|
2764
2768
|
logger.success(
|
|
2765
2769
|
`\u{1F680} Schema was ${schema.overwrite ? "overwritten" : "appended"} successfully!`
|
|
@@ -2820,15 +2824,15 @@ async function generateAction(opts) {
|
|
|
2820
2824
|
process.exit(1);
|
|
2821
2825
|
}
|
|
2822
2826
|
if (!options.output) {
|
|
2823
|
-
const dirExist = existsSync(
|
|
2827
|
+
const dirExist = existsSync(path__default.dirname(path__default.join(cwd, schema.fileName)));
|
|
2824
2828
|
if (!dirExist) {
|
|
2825
|
-
await fs$1.mkdir(
|
|
2829
|
+
await fs$1.mkdir(path__default.dirname(path__default.join(cwd, schema.fileName)), {
|
|
2826
2830
|
recursive: true
|
|
2827
2831
|
});
|
|
2828
2832
|
}
|
|
2829
2833
|
}
|
|
2830
2834
|
await fs$1.writeFile(
|
|
2831
|
-
options.output ||
|
|
2835
|
+
options.output || path__default.join(cwd, schema.fileName),
|
|
2832
2836
|
schema.code
|
|
2833
2837
|
);
|
|
2834
2838
|
logger.success(`\u{1F680} Schema was generated successfully!`);
|
|
@@ -2853,8 +2857,8 @@ const generate = new Command("generate").option(
|
|
|
2853
2857
|
|
|
2854
2858
|
const DEMO_URL = "https://demo.better-auth.com";
|
|
2855
2859
|
const CLIENT_ID = "better-auth-cli";
|
|
2856
|
-
const CONFIG_DIR =
|
|
2857
|
-
const TOKEN_FILE =
|
|
2860
|
+
const CONFIG_DIR = path__default.join(os__default.homedir(), ".better-auth");
|
|
2861
|
+
const TOKEN_FILE = path__default.join(CONFIG_DIR, "token.json");
|
|
2858
2862
|
async function loginAction(opts) {
|
|
2859
2863
|
const options = z.object({
|
|
2860
2864
|
serverUrl: z.string().optional(),
|
|
@@ -3059,13 +3063,13 @@ const login = new Command("login").description(
|
|
|
3059
3063
|
).option("--server-url <url>", "The Better Auth server URL", DEMO_URL).option("--client-id <id>", "The OAuth client ID", CLIENT_ID).action(loginAction);
|
|
3060
3064
|
|
|
3061
3065
|
function getSystemInfo() {
|
|
3062
|
-
const platform =
|
|
3063
|
-
const arch =
|
|
3064
|
-
const version =
|
|
3065
|
-
const release =
|
|
3066
|
-
const cpus =
|
|
3067
|
-
const memory =
|
|
3068
|
-
const freeMemory =
|
|
3066
|
+
const platform = os__default.platform();
|
|
3067
|
+
const arch = os__default.arch();
|
|
3068
|
+
const version = os__default.version();
|
|
3069
|
+
const release = os__default.release();
|
|
3070
|
+
const cpus = os__default.cpus();
|
|
3071
|
+
const memory = os__default.totalmem();
|
|
3072
|
+
const freeMemory = os__default.freemem();
|
|
3069
3073
|
return {
|
|
3070
3074
|
platform,
|
|
3071
3075
|
arch,
|
|
@@ -3105,7 +3109,7 @@ function getVersion(command) {
|
|
|
3105
3109
|
}
|
|
3106
3110
|
}
|
|
3107
3111
|
function getFrameworkInfo(projectRoot) {
|
|
3108
|
-
const packageJsonPath =
|
|
3112
|
+
const packageJsonPath = path__default.join(projectRoot, "package.json");
|
|
3109
3113
|
if (!existsSync(packageJsonPath)) {
|
|
3110
3114
|
return null;
|
|
3111
3115
|
}
|
|
@@ -3137,7 +3141,7 @@ function getFrameworkInfo(projectRoot) {
|
|
|
3137
3141
|
}
|
|
3138
3142
|
}
|
|
3139
3143
|
function getDatabaseInfo(projectRoot) {
|
|
3140
|
-
const packageJsonPath =
|
|
3144
|
+
const packageJsonPath = path__default.join(projectRoot, "package.json");
|
|
3141
3145
|
if (!existsSync(packageJsonPath)) {
|
|
3142
3146
|
return null;
|
|
3143
3147
|
}
|
|
@@ -3362,7 +3366,7 @@ ${formatOutput(value, indent + 2)}`;
|
|
|
3362
3366
|
return `${spaces}${JSON.stringify(data)}`;
|
|
3363
3367
|
}
|
|
3364
3368
|
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) => {
|
|
3365
|
-
const projectRoot =
|
|
3369
|
+
const projectRoot = path__default.resolve(options.cwd || process.cwd());
|
|
3366
3370
|
const systemInfo = getSystemInfo();
|
|
3367
3371
|
const nodeInfo = getNodeInfo();
|
|
3368
3372
|
const packageManager = getPackageManager();
|
|
@@ -3386,7 +3390,7 @@ const info = new Command("info").description("Display system and Better Auth con
|
|
|
3386
3390
|
console.log(jsonOutput);
|
|
3387
3391
|
if (options.copy) {
|
|
3388
3392
|
try {
|
|
3389
|
-
const platform =
|
|
3393
|
+
const platform = os__default.platform();
|
|
3390
3394
|
if (platform === "darwin") {
|
|
3391
3395
|
execSync("pbcopy", { input: jsonOutput });
|
|
3392
3396
|
console.log(chalk.green("\n\u2713 Copied to clipboard"));
|
|
@@ -3459,7 +3463,7 @@ Better Auth:
|
|
|
3459
3463
|
${JSON.stringify(betterAuthInfo, null, 2)}
|
|
3460
3464
|
`;
|
|
3461
3465
|
try {
|
|
3462
|
-
const platform =
|
|
3466
|
+
const platform = os__default.platform();
|
|
3463
3467
|
if (platform === "darwin") {
|
|
3464
3468
|
execSync("pbcopy", { input: textOutput });
|
|
3465
3469
|
console.log(chalk.green("\u2713 Copied to clipboard"));
|
|
@@ -3476,6 +3480,197 @@ ${JSON.stringify(betterAuthInfo, null, 2)}
|
|
|
3476
3480
|
}
|
|
3477
3481
|
});
|
|
3478
3482
|
|
|
3483
|
+
async function mcpAction(options) {
|
|
3484
|
+
const mcpUrl = "https://mcp.chonkie.ai/better-auth/better-auth-builder/mcp";
|
|
3485
|
+
const mcpName = "Better Auth";
|
|
3486
|
+
if (options.cursor) {
|
|
3487
|
+
await handleCursorAction(mcpUrl, mcpName);
|
|
3488
|
+
} else if (options.claudeCode) {
|
|
3489
|
+
handleClaudeCodeAction(mcpUrl);
|
|
3490
|
+
} else if (options.openCode) {
|
|
3491
|
+
handleOpenCodeAction(mcpUrl);
|
|
3492
|
+
} else if (options.manual) {
|
|
3493
|
+
handleManualAction(mcpUrl, mcpName);
|
|
3494
|
+
} else {
|
|
3495
|
+
showAllOptions();
|
|
3496
|
+
}
|
|
3497
|
+
}
|
|
3498
|
+
async function handleCursorAction(mcpUrl, mcpName) {
|
|
3499
|
+
const mcpConfig = {
|
|
3500
|
+
url: mcpUrl
|
|
3501
|
+
};
|
|
3502
|
+
const encodedConfig = base64.encode(
|
|
3503
|
+
new TextEncoder().encode(JSON.stringify(mcpConfig))
|
|
3504
|
+
);
|
|
3505
|
+
const deeplinkUrl = `cursor://anysphere.cursor-deeplink/mcp/install?name=${encodeURIComponent(mcpName)}&config=${encodedConfig}`;
|
|
3506
|
+
console.log(chalk.bold.blue("\u{1F680} Adding Better Auth MCP to Cursor..."));
|
|
3507
|
+
try {
|
|
3508
|
+
const platform = os.platform();
|
|
3509
|
+
let command;
|
|
3510
|
+
switch (platform) {
|
|
3511
|
+
case "darwin":
|
|
3512
|
+
command = `open "${deeplinkUrl}"`;
|
|
3513
|
+
break;
|
|
3514
|
+
case "win32":
|
|
3515
|
+
command = `start "" "${deeplinkUrl}"`;
|
|
3516
|
+
break;
|
|
3517
|
+
case "linux":
|
|
3518
|
+
command = `xdg-open "${deeplinkUrl}"`;
|
|
3519
|
+
break;
|
|
3520
|
+
default:
|
|
3521
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
3522
|
+
}
|
|
3523
|
+
execSync(command, { stdio: "inherit" });
|
|
3524
|
+
console.log(chalk.green("\n\u2713 Cursor MCP installed successfully!"));
|
|
3525
|
+
} catch (error) {
|
|
3526
|
+
console.log(
|
|
3527
|
+
chalk.yellow(
|
|
3528
|
+
"\n\u26A0 Could not automatically open Cursor. Please copy the deeplink URL above and open it manually."
|
|
3529
|
+
)
|
|
3530
|
+
);
|
|
3531
|
+
console.log(
|
|
3532
|
+
chalk.gray(
|
|
3533
|
+
"\nYou can also manually add this configuration to your Cursor MCP settings:"
|
|
3534
|
+
)
|
|
3535
|
+
);
|
|
3536
|
+
console.log(chalk.gray(JSON.stringify(mcpConfig, null, 2)));
|
|
3537
|
+
}
|
|
3538
|
+
console.log(chalk.bold.white("\n\u2728 Next Steps:"));
|
|
3539
|
+
console.log(
|
|
3540
|
+
chalk.gray("\u2022 The MCP server will be added to your Cursor configuration")
|
|
3541
|
+
);
|
|
3542
|
+
console.log(
|
|
3543
|
+
chalk.gray("\u2022 You can now use Better Auth features directly in Cursor")
|
|
3544
|
+
);
|
|
3545
|
+
}
|
|
3546
|
+
function handleClaudeCodeAction(mcpUrl) {
|
|
3547
|
+
console.log(chalk.bold.blue("\u{1F916} Adding Better Auth MCP to Claude Code..."));
|
|
3548
|
+
const command = `claude mcp add --transport http better-auth ${mcpUrl}`;
|
|
3549
|
+
try {
|
|
3550
|
+
execSync(command, { stdio: "inherit" });
|
|
3551
|
+
console.log(chalk.green("\n\u2713 Claude Code MCP installed successfully!"));
|
|
3552
|
+
} catch (error) {
|
|
3553
|
+
console.log(
|
|
3554
|
+
chalk.yellow(
|
|
3555
|
+
"\n\u26A0 Could not automatically add to Claude Code. Please run this command manually:"
|
|
3556
|
+
)
|
|
3557
|
+
);
|
|
3558
|
+
console.log(chalk.cyan(command));
|
|
3559
|
+
}
|
|
3560
|
+
console.log(chalk.bold.white("\n\u2728 Next Steps:"));
|
|
3561
|
+
console.log(
|
|
3562
|
+
chalk.gray(
|
|
3563
|
+
"\u2022 The MCP server will be added to your Claude Code configuration"
|
|
3564
|
+
)
|
|
3565
|
+
);
|
|
3566
|
+
console.log(
|
|
3567
|
+
chalk.gray(
|
|
3568
|
+
"\u2022 You can now use Better Auth features directly in Claude Code"
|
|
3569
|
+
)
|
|
3570
|
+
);
|
|
3571
|
+
}
|
|
3572
|
+
function handleOpenCodeAction(mcpUrl) {
|
|
3573
|
+
console.log(chalk.bold.blue("\u{1F527} Adding Better Auth MCP to Open Code..."));
|
|
3574
|
+
const openCodeConfig = {
|
|
3575
|
+
$schema: "https://opencode.ai/config.json",
|
|
3576
|
+
mcp: {
|
|
3577
|
+
"Better Auth": {
|
|
3578
|
+
type: "remote",
|
|
3579
|
+
url: mcpUrl,
|
|
3580
|
+
enabled: true
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3583
|
+
};
|
|
3584
|
+
const configPath = path.join(process.cwd(), "opencode.json");
|
|
3585
|
+
try {
|
|
3586
|
+
let existingConfig = {};
|
|
3587
|
+
if (fs.existsSync(configPath)) {
|
|
3588
|
+
const existingContent = fs.readFileSync(configPath, "utf8");
|
|
3589
|
+
existingConfig = JSON.parse(existingContent);
|
|
3590
|
+
}
|
|
3591
|
+
const mergedConfig = {
|
|
3592
|
+
...existingConfig,
|
|
3593
|
+
...openCodeConfig,
|
|
3594
|
+
mcp: {
|
|
3595
|
+
...existingConfig.mcp,
|
|
3596
|
+
...openCodeConfig.mcp
|
|
3597
|
+
}
|
|
3598
|
+
};
|
|
3599
|
+
fs.writeFileSync(configPath, JSON.stringify(mergedConfig, null, 2));
|
|
3600
|
+
console.log(
|
|
3601
|
+
chalk.green(`
|
|
3602
|
+
\u2713 Open Code configuration written to ${configPath}`)
|
|
3603
|
+
);
|
|
3604
|
+
console.log(chalk.green("\u2713 Better Auth MCP added successfully!"));
|
|
3605
|
+
} catch (error) {
|
|
3606
|
+
console.log(
|
|
3607
|
+
chalk.yellow(
|
|
3608
|
+
"\n\u26A0 Could not automatically write opencode.json. Please add this configuration manually:"
|
|
3609
|
+
)
|
|
3610
|
+
);
|
|
3611
|
+
console.log(chalk.cyan(JSON.stringify(openCodeConfig, null, 2)));
|
|
3612
|
+
}
|
|
3613
|
+
console.log(chalk.bold.white("\n\u2728 Next Steps:"));
|
|
3614
|
+
console.log(chalk.gray("\u2022 Restart Open Code to load the new MCP server"));
|
|
3615
|
+
console.log(
|
|
3616
|
+
chalk.gray("\u2022 You can now use Better Auth features directly in Open Code")
|
|
3617
|
+
);
|
|
3618
|
+
}
|
|
3619
|
+
function handleManualAction(mcpUrl, mcpName) {
|
|
3620
|
+
console.log(chalk.bold.blue("\u{1F4DD} Adding Better Auth MCP Configuration..."));
|
|
3621
|
+
const manualConfig = {
|
|
3622
|
+
[mcpName]: {
|
|
3623
|
+
url: mcpUrl
|
|
3624
|
+
}
|
|
3625
|
+
};
|
|
3626
|
+
const configPath = path.join(process.cwd(), "mcp.json");
|
|
3627
|
+
try {
|
|
3628
|
+
let existingConfig = {};
|
|
3629
|
+
if (fs.existsSync(configPath)) {
|
|
3630
|
+
const existingContent = fs.readFileSync(configPath, "utf8");
|
|
3631
|
+
existingConfig = JSON.parse(existingContent);
|
|
3632
|
+
}
|
|
3633
|
+
const mergedConfig = {
|
|
3634
|
+
...existingConfig,
|
|
3635
|
+
...manualConfig
|
|
3636
|
+
};
|
|
3637
|
+
fs.writeFileSync(configPath, JSON.stringify(mergedConfig, null, 2));
|
|
3638
|
+
console.log(chalk.green(`
|
|
3639
|
+
\u2713 MCP configuration written to ${configPath}`));
|
|
3640
|
+
console.log(chalk.green("\u2713 Better Auth MCP added successfully!"));
|
|
3641
|
+
} catch (error) {
|
|
3642
|
+
console.log(
|
|
3643
|
+
chalk.yellow(
|
|
3644
|
+
"\n\u26A0 Could not automatically write mcp.json. Please add this configuration manually:"
|
|
3645
|
+
)
|
|
3646
|
+
);
|
|
3647
|
+
console.log(chalk.cyan(JSON.stringify(manualConfig, null, 2)));
|
|
3648
|
+
}
|
|
3649
|
+
console.log(chalk.bold.white("\n\u2728 Next Steps:"));
|
|
3650
|
+
console.log(chalk.gray("\u2022 Restart your MCP client to load the new server"));
|
|
3651
|
+
console.log(
|
|
3652
|
+
chalk.gray(
|
|
3653
|
+
"\u2022 You can now use Better Auth features directly in your MCP client"
|
|
3654
|
+
)
|
|
3655
|
+
);
|
|
3656
|
+
}
|
|
3657
|
+
function showAllOptions(mcpUrl, mcpName) {
|
|
3658
|
+
console.log(chalk.bold.blue("\u{1F50C} Better Auth MCP Server"));
|
|
3659
|
+
console.log(chalk.gray("Choose your MCP client to get started:"));
|
|
3660
|
+
console.log();
|
|
3661
|
+
console.log(chalk.bold.white("Available Commands:"));
|
|
3662
|
+
console.log(chalk.cyan(" --cursor ") + chalk.gray("Add to Cursor"));
|
|
3663
|
+
console.log(
|
|
3664
|
+
chalk.cyan(" --claude-code ") + chalk.gray("Add to Claude Code")
|
|
3665
|
+
);
|
|
3666
|
+
console.log(chalk.cyan(" --open-code ") + chalk.gray("Add to Open Code"));
|
|
3667
|
+
console.log(
|
|
3668
|
+
chalk.cyan(" --manual ") + chalk.gray("Manual configuration")
|
|
3669
|
+
);
|
|
3670
|
+
console.log();
|
|
3671
|
+
}
|
|
3672
|
+
const mcp = new Command("mcp").description("Add Better Auth MCP server to MCP Clients").option("--cursor", "Automatically open Cursor with the MCP configuration").option("--claude-code", "Show Claude Code MCP configuration command").option("--open-code", "Show Open Code MCP configuration").option("--manual", "Show manual MCP configuration for mcp.json").action(mcpAction);
|
|
3673
|
+
|
|
3479
3674
|
process.on("SIGINT", () => process.exit(0));
|
|
3480
3675
|
process.on("SIGTERM", () => process.exit(0));
|
|
3481
3676
|
async function main() {
|
|
@@ -3485,7 +3680,7 @@ async function main() {
|
|
|
3485
3680
|
packageInfo = await getPackageInfo();
|
|
3486
3681
|
} catch (error) {
|
|
3487
3682
|
}
|
|
3488
|
-
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());
|
|
3683
|
+
program.addCommand(init).addCommand(migrate).addCommand(generate).addCommand(generateSecret).addCommand(info).addCommand(login).addCommand(mcp).version(packageInfo.version || "1.1.2").description("Better Auth CLI").action(() => program.help());
|
|
3489
3684
|
program.parse();
|
|
3490
3685
|
}
|
|
3491
3686
|
main().catch((error) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/cli",
|
|
3
|
-
"version": "1.4.0-beta.
|
|
3
|
+
"version": "1.4.0-beta.7",
|
|
4
4
|
"description": "The CLI for Better Auth",
|
|
5
5
|
"module": "dist/index.mjs",
|
|
6
6
|
"repository": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"@babel/core": "^7.28.4",
|
|
36
36
|
"@babel/preset-react": "^7.27.1",
|
|
37
37
|
"@babel/preset-typescript": "^7.27.1",
|
|
38
|
+
"@better-auth/utils": "0.3.0",
|
|
38
39
|
"@clack/prompts": "^0.11.0",
|
|
39
40
|
"@mrleebo/prisma-ast": "^0.13.0",
|
|
40
41
|
"@prisma/client": "^5.22.0",
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
"tinyexec": "^0.3.2",
|
|
57
58
|
"yocto-spinner": "^0.2.3",
|
|
58
59
|
"zod": "^4.1.5",
|
|
59
|
-
"better-auth": "1.4.0-beta.
|
|
60
|
+
"better-auth": "1.4.0-beta.7"
|
|
60
61
|
},
|
|
61
62
|
"files": [
|
|
62
63
|
"dist"
|