@better-auth/cli 1.4.6-beta.2 → 1.4.6-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.
- package/dist/index.mjs +143 -77
- package/package.json +8 -7
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import fs, { existsSync, readFileSync } from "node:fs";
|
|
|
5
5
|
import fs$1 from "node:fs/promises";
|
|
6
6
|
import * as path$1 from "node:path";
|
|
7
7
|
import path from "node:path";
|
|
8
|
-
import {
|
|
8
|
+
import { createTelemetry, getTelemetryAuthConfig } from "@better-auth/telemetry";
|
|
9
9
|
import { getAdapter, getAuthTables, getMigrations } from "better-auth/db";
|
|
10
10
|
import chalk from "chalk";
|
|
11
11
|
import prompts from "prompts";
|
|
@@ -13,9 +13,11 @@ import yoctoSpinner from "yocto-spinner";
|
|
|
13
13
|
import * as z from "zod/v4";
|
|
14
14
|
import { initGetFieldName, initGetModelName } from "better-auth/adapters";
|
|
15
15
|
import prettier, { format } from "prettier";
|
|
16
|
+
import { capitalizeFirstLetter } from "@better-auth/core/utils";
|
|
16
17
|
import { produceSchema } from "@mrleebo/prisma-ast";
|
|
17
18
|
import babelPresetReact from "@babel/preset-react";
|
|
18
19
|
import babelPresetTypeScript from "@babel/preset-typescript";
|
|
20
|
+
import { BetterAuthError } from "@better-auth/core/error";
|
|
19
21
|
import { loadConfig } from "c12";
|
|
20
22
|
import { exec, execSync } from "node:child_process";
|
|
21
23
|
import * as os$1 from "node:os";
|
|
@@ -102,19 +104,19 @@ const generateDrizzleSchema = async ({ options, file, adapter }) => {
|
|
|
102
104
|
mysql: `timestamp('${name}', { fsp: 3 })`
|
|
103
105
|
},
|
|
104
106
|
"number[]": {
|
|
105
|
-
sqlite: `
|
|
107
|
+
sqlite: `text('${name}', { mode: "json" })`,
|
|
106
108
|
pg: field.bigint ? `bigint('${name}', { mode: 'number' }).array()` : `integer('${name}').array()`,
|
|
107
|
-
mysql:
|
|
109
|
+
mysql: `text('${name}', { mode: 'json' })`
|
|
108
110
|
},
|
|
109
111
|
"string[]": {
|
|
110
|
-
sqlite: `text('${name}')
|
|
112
|
+
sqlite: `text('${name}', { mode: "json" })`,
|
|
111
113
|
pg: `text('${name}').array()`,
|
|
112
|
-
mysql: `text('${name}')
|
|
114
|
+
mysql: `text('${name}', { mode: "json" })`
|
|
113
115
|
},
|
|
114
116
|
json: {
|
|
115
|
-
sqlite: `text('${name}')`,
|
|
117
|
+
sqlite: `text('${name}', { mode: "json" })`,
|
|
116
118
|
pg: `jsonb('${name}')`,
|
|
117
|
-
mysql: `json('${name}')`
|
|
119
|
+
mysql: `json('${name}', { mode: "json" })`
|
|
118
120
|
}
|
|
119
121
|
}[type];
|
|
120
122
|
if (!dbTypeMap) throw new Error(`Unsupported field type '${field.type}' for field '${name}'.`);
|
|
@@ -172,50 +174,104 @@ const generateDrizzleSchema = async ({ options, file, adapter }) => {
|
|
|
172
174
|
let relationsString = "";
|
|
173
175
|
for (const tableKey in tables) {
|
|
174
176
|
const table = tables[tableKey];
|
|
175
|
-
const
|
|
177
|
+
const modelName = getModelName(tableKey);
|
|
178
|
+
const oneRelations = [];
|
|
179
|
+
const manyRelations = [];
|
|
180
|
+
const manyRelationsSet = /* @__PURE__ */ new Set();
|
|
176
181
|
const foreignFields = Object.entries(table.fields).filter(([_, field]) => field.references);
|
|
177
182
|
for (const [fieldName, field] of foreignFields) {
|
|
178
183
|
const referencedModel = field.references.model;
|
|
179
|
-
|
|
180
|
-
|
|
184
|
+
const relationKey = getModelName(referencedModel);
|
|
185
|
+
const fieldRef = `${getModelName(tableKey)}.${getFieldName({
|
|
186
|
+
model: tableKey,
|
|
187
|
+
field: fieldName
|
|
188
|
+
})}`;
|
|
189
|
+
const referenceRef = `${getModelName(referencedModel)}.${getFieldName({
|
|
190
|
+
model: referencedModel,
|
|
191
|
+
field: field.references.field || "id"
|
|
192
|
+
})}`;
|
|
193
|
+
oneRelations.push({
|
|
194
|
+
key: relationKey,
|
|
181
195
|
model: getModelName(referencedModel),
|
|
182
196
|
type: "one",
|
|
183
197
|
reference: {
|
|
184
|
-
field:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
})}`,
|
|
188
|
-
references: `${getModelName(referencedModel)}.${getFieldName({
|
|
189
|
-
model: referencedModel,
|
|
190
|
-
field: field.references.field || "id"
|
|
191
|
-
})}`
|
|
198
|
+
field: fieldRef,
|
|
199
|
+
references: referenceRef,
|
|
200
|
+
fieldName
|
|
192
201
|
}
|
|
193
202
|
});
|
|
194
203
|
}
|
|
195
|
-
const otherModels = Object.entries(tables).filter(([modelName]) => modelName !== tableKey);
|
|
196
|
-
|
|
204
|
+
const otherModels = Object.entries(tables).filter(([modelName$1]) => modelName$1 !== tableKey);
|
|
205
|
+
const modelRelationsMap = /* @__PURE__ */ new Map();
|
|
206
|
+
for (const [modelName$1, otherTable] of otherModels) {
|
|
197
207
|
const foreignKeysPointingHere = Object.entries(otherTable.fields).filter(([_, field]) => field.references?.model === tableKey || field.references?.model === getModelName(tableKey));
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
208
|
+
if (foreignKeysPointingHere.length === 0) continue;
|
|
209
|
+
const hasUnique = foreignKeysPointingHere.some(([_, field]) => !!field.unique);
|
|
210
|
+
const hasMany$1 = foreignKeysPointingHere.some(([_, field]) => !field.unique);
|
|
211
|
+
modelRelationsMap.set(modelName$1, {
|
|
212
|
+
modelName: modelName$1,
|
|
213
|
+
hasUnique,
|
|
214
|
+
hasMany: hasMany$1
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
for (const { modelName: modelName$1, hasUnique, hasMany: hasMany$1 } of modelRelationsMap.values()) {
|
|
218
|
+
const relationType = hasMany$1 ? "many" : "one";
|
|
219
|
+
let relationKey = getModelName(modelName$1);
|
|
220
|
+
if (!adapter.options?.adapterConfig?.usePlural && relationType === "many") relationKey = `${relationKey}s`;
|
|
221
|
+
if (!manyRelationsSet.has(relationKey)) {
|
|
222
|
+
manyRelationsSet.add(relationKey);
|
|
223
|
+
manyRelations.push({
|
|
204
224
|
key: relationKey,
|
|
205
|
-
model,
|
|
206
|
-
type:
|
|
225
|
+
model: getModelName(modelName$1),
|
|
226
|
+
type: relationType
|
|
207
227
|
});
|
|
208
228
|
}
|
|
209
229
|
}
|
|
210
|
-
const
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
230
|
+
const relationsByModel = /* @__PURE__ */ new Map();
|
|
231
|
+
for (const relation of oneRelations) if (relation.reference) {
|
|
232
|
+
const modelKey = relation.key;
|
|
233
|
+
if (!relationsByModel.has(modelKey)) relationsByModel.set(modelKey, []);
|
|
234
|
+
relationsByModel.get(modelKey).push(relation);
|
|
235
|
+
}
|
|
236
|
+
const duplicateRelations = [];
|
|
237
|
+
const singleRelations = [];
|
|
238
|
+
for (const [modelKey, relations] of relationsByModel.entries()) if (relations.length > 1) duplicateRelations.push(...relations);
|
|
239
|
+
else singleRelations.push(relations[0]);
|
|
240
|
+
for (const relation of duplicateRelations) if (relation.reference) {
|
|
241
|
+
const fieldName = relation.reference.fieldName;
|
|
242
|
+
const tableRelation = `export const ${`${modelName}${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}Relations`} = relations(${getModelName(table.modelName)}, ({ one }) => ({
|
|
243
|
+
${relation.key}: one(${relation.model}, {
|
|
244
|
+
fields: [${relation.reference.field}],
|
|
245
|
+
references: [${relation.reference.references}],
|
|
246
|
+
})
|
|
247
|
+
}))`;
|
|
248
|
+
relationsString += `\n${tableRelation}\n`;
|
|
249
|
+
}
|
|
250
|
+
const hasOne = singleRelations.length > 0;
|
|
251
|
+
const hasMany = manyRelations.length > 0;
|
|
252
|
+
if (hasOne && hasMany) {
|
|
253
|
+
const tableRelation = `export const ${modelName}Relations = relations(${getModelName(table.modelName)}, ({ one, many }) => ({
|
|
254
|
+
${singleRelations.map((relation) => relation.reference ? ` ${relation.key}: one(${relation.model}, {
|
|
255
|
+
fields: [${relation.reference.field}],
|
|
256
|
+
references: [${relation.reference.references}],
|
|
257
|
+
})` : "").filter((x) => x !== "").join(",\n ")}${singleRelations.length > 0 && manyRelations.length > 0 ? "," : ""}
|
|
258
|
+
${manyRelations.map(({ key, model }) => ` ${key}: many(${model})`).join(",\n ")}
|
|
259
|
+
}))`;
|
|
260
|
+
relationsString += `\n${tableRelation}\n`;
|
|
261
|
+
} else if (hasOne) {
|
|
262
|
+
const tableRelation = `export const ${modelName}Relations = relations(${getModelName(table.modelName)}, ({ one }) => ({
|
|
263
|
+
${singleRelations.map((relation) => relation.reference ? ` ${relation.key}: one(${relation.model}, {
|
|
264
|
+
fields: [${relation.reference.field}],
|
|
265
|
+
references: [${relation.reference.references}],
|
|
266
|
+
})` : "").filter((x) => x !== "").join(",\n ")}
|
|
217
267
|
}))`;
|
|
218
|
-
|
|
268
|
+
relationsString += `\n${tableRelation}\n`;
|
|
269
|
+
} else if (hasMany) {
|
|
270
|
+
const tableRelation = `export const ${modelName}Relations = relations(${getModelName(table.modelName)}, ({ many }) => ({
|
|
271
|
+
${manyRelations.map(({ key, model }) => ` ${key}: many(${model})`).join(",\n ")}
|
|
272
|
+
}))`;
|
|
273
|
+
relationsString += `\n${tableRelation}\n`;
|
|
274
|
+
}
|
|
219
275
|
}
|
|
220
276
|
code += `\n${relationsString}`;
|
|
221
277
|
return {
|
|
@@ -359,9 +415,18 @@ const generatePrismaSchema = async ({ adapter, options, file }) => {
|
|
|
359
415
|
if (type === "number") return isOptional ? "Int?" : "Int";
|
|
360
416
|
if (type === "boolean") return isOptional ? "Boolean?" : "Boolean";
|
|
361
417
|
if (type === "date") return isOptional ? "DateTime?" : "DateTime";
|
|
362
|
-
if (type === "json")
|
|
363
|
-
|
|
364
|
-
|
|
418
|
+
if (type === "json") {
|
|
419
|
+
if (provider === "sqlite" || provider === "mysql") return isOptional ? "String?" : "String";
|
|
420
|
+
return isOptional ? "Json?" : "Json";
|
|
421
|
+
}
|
|
422
|
+
if (type === "string[]") {
|
|
423
|
+
if (provider === "sqlite" || provider === "mysql") return isOptional ? "String?" : "String";
|
|
424
|
+
return "String[]";
|
|
425
|
+
}
|
|
426
|
+
if (type === "number[]") {
|
|
427
|
+
if (provider === "sqlite" || provider === "mysql") return "String";
|
|
428
|
+
return "Int[]";
|
|
429
|
+
}
|
|
365
430
|
}
|
|
366
431
|
const prismaModel = builder.findByType("model", { name: modelName });
|
|
367
432
|
if (!prismaModel) if (provider === "mongodb") builder.model(modelName).field("id", "String").attribute("id").attribute(`map("_id")`);
|
|
@@ -524,7 +589,7 @@ const generateSchema = (opts) => {
|
|
|
524
589
|
fileName,
|
|
525
590
|
overwrite
|
|
526
591
|
}));
|
|
527
|
-
|
|
592
|
+
console.error(`${adapter.id} is not supported. If it is a custom adapter, please request the maintainer to implement createSchema`);
|
|
528
593
|
process.exit(1);
|
|
529
594
|
};
|
|
530
595
|
|
|
@@ -813,7 +878,7 @@ function getPathAliasesRecursive(tsconfigPath, visited = /* @__PURE__ */ new Set
|
|
|
813
878
|
if (visited.has(tsconfigPath)) return {};
|
|
814
879
|
visited.add(tsconfigPath);
|
|
815
880
|
if (!fs.existsSync(tsconfigPath)) {
|
|
816
|
-
|
|
881
|
+
console.warn(`Referenced tsconfig not found: ${tsconfigPath}`);
|
|
817
882
|
return {};
|
|
818
883
|
}
|
|
819
884
|
try {
|
|
@@ -834,7 +899,7 @@ function getPathAliasesRecursive(tsconfigPath, visited = /* @__PURE__ */ new Set
|
|
|
834
899
|
}
|
|
835
900
|
return result;
|
|
836
901
|
} catch (error) {
|
|
837
|
-
|
|
902
|
+
console.warn(`Error parsing tsconfig at ${tsconfigPath}: ${error}`);
|
|
838
903
|
return {};
|
|
839
904
|
}
|
|
840
905
|
}
|
|
@@ -886,7 +951,7 @@ async function getConfig({ cwd, configPath, shouldThrowOnError = false }) {
|
|
|
886
951
|
});
|
|
887
952
|
if (!("auth" in config) && !isDefaultExport(config)) {
|
|
888
953
|
if (shouldThrowOnError) throw new Error(`Couldn't read your auth config in ${resolvedPath}. Make sure to default export your auth instance or to export as a variable named auth.`);
|
|
889
|
-
|
|
954
|
+
console.error(`[#better-auth]: Couldn't read your auth config in ${resolvedPath}. Make sure to default export your auth instance or to export as a variable named auth.`);
|
|
890
955
|
process.exit(1);
|
|
891
956
|
}
|
|
892
957
|
configFile = "auth" in config ? config.auth?.options : config.options;
|
|
@@ -900,9 +965,9 @@ async function getConfig({ cwd, configPath, shouldThrowOnError = false }) {
|
|
|
900
965
|
configFile = config.auth?.options || config.default?.options || null;
|
|
901
966
|
if (!configFile) {
|
|
902
967
|
if (shouldThrowOnError) throw new Error("Couldn't read your auth config. Make sure to default export your auth instance or to export as a variable named auth.");
|
|
903
|
-
|
|
968
|
+
console.error("[#better-auth]: Couldn't read your auth config.");
|
|
904
969
|
console.log("");
|
|
905
|
-
|
|
970
|
+
console.log("[#better-auth]: Make sure to default export your auth instance or to export as a variable named auth.");
|
|
906
971
|
process.exit(1);
|
|
907
972
|
}
|
|
908
973
|
break;
|
|
@@ -910,22 +975,22 @@ async function getConfig({ cwd, configPath, shouldThrowOnError = false }) {
|
|
|
910
975
|
} catch (e) {
|
|
911
976
|
if (typeof e === "object" && e && "message" in e && typeof e.message === "string" && e.message.includes("This module cannot be imported from a Client Component module")) {
|
|
912
977
|
if (shouldThrowOnError) throw new Error(`Please remove import 'server-only' from your auth config file temporarily. The CLI cannot resolve the configuration with it included. You can re-add it after running the CLI.`);
|
|
913
|
-
|
|
978
|
+
console.error(`Please remove import 'server-only' from your auth config file temporarily. The CLI cannot resolve the configuration with it included. You can re-add it after running the CLI.`);
|
|
914
979
|
process.exit(1);
|
|
915
980
|
}
|
|
916
981
|
if (shouldThrowOnError) throw e;
|
|
917
|
-
|
|
982
|
+
console.error("[#better-auth]: Couldn't read your auth config.", e);
|
|
918
983
|
process.exit(1);
|
|
919
984
|
}
|
|
920
985
|
return configFile;
|
|
921
986
|
} catch (e) {
|
|
922
987
|
if (typeof e === "object" && e && "message" in e && typeof e.message === "string" && e.message.includes("This module cannot be imported from a Client Component module")) {
|
|
923
988
|
if (shouldThrowOnError) throw new Error(`Please remove import 'server-only' from your auth config file temporarily. The CLI cannot resolve the configuration with it included. You can re-add it after running the CLI.`);
|
|
924
|
-
|
|
989
|
+
console.error(`Please remove import 'server-only' from your auth config file temporarily. The CLI cannot resolve the configuration with it included. You can re-add it after running the CLI.`);
|
|
925
990
|
process.exit(1);
|
|
926
991
|
}
|
|
927
992
|
if (shouldThrowOnError) throw e;
|
|
928
|
-
|
|
993
|
+
console.error("Couldn't read your auth config.", e);
|
|
929
994
|
process.exit(1);
|
|
930
995
|
}
|
|
931
996
|
}
|
|
@@ -942,7 +1007,7 @@ async function generateAction(opts) {
|
|
|
942
1007
|
}).parse(opts);
|
|
943
1008
|
const cwd = path.resolve(options.cwd);
|
|
944
1009
|
if (!existsSync(cwd)) {
|
|
945
|
-
|
|
1010
|
+
console.error(`The directory "${cwd}" does not exist.`);
|
|
946
1011
|
process.exit(1);
|
|
947
1012
|
}
|
|
948
1013
|
const config = await getConfig({
|
|
@@ -950,11 +1015,11 @@ async function generateAction(opts) {
|
|
|
950
1015
|
configPath: options.config
|
|
951
1016
|
});
|
|
952
1017
|
if (!config) {
|
|
953
|
-
|
|
1018
|
+
console.error("No configuration file found. Add a `auth.ts` file to your project or pass the path to the configuration file using the `--config` flag.");
|
|
954
1019
|
return;
|
|
955
1020
|
}
|
|
956
1021
|
const adapter = await getAdapter(config).catch((e) => {
|
|
957
|
-
|
|
1022
|
+
console.error(e.message);
|
|
958
1023
|
process.exit(1);
|
|
959
1024
|
});
|
|
960
1025
|
const spinner$1 = yoctoSpinner({ text: "preparing schema..." }).start();
|
|
@@ -965,7 +1030,7 @@ async function generateAction(opts) {
|
|
|
965
1030
|
});
|
|
966
1031
|
spinner$1.stop();
|
|
967
1032
|
if (!schema.code) {
|
|
968
|
-
|
|
1033
|
+
console.log("Your schema is already up to date.");
|
|
969
1034
|
try {
|
|
970
1035
|
await (await createTelemetry(config)).publish({
|
|
971
1036
|
type: "cli_generate",
|
|
@@ -991,7 +1056,7 @@ async function generateAction(opts) {
|
|
|
991
1056
|
if (!existsSync(path.join(cwd, schema.fileName))) await fs$1.mkdir(path.dirname(path.join(cwd, schema.fileName)), { recursive: true });
|
|
992
1057
|
if (schema.overwrite) await fs$1.writeFile(path.join(cwd, schema.fileName), schema.code);
|
|
993
1058
|
else await fs$1.appendFile(path.join(cwd, schema.fileName), schema.code);
|
|
994
|
-
|
|
1059
|
+
console.log(`🚀 Schema was ${schema.overwrite ? "overwritten" : "appended"} successfully!`);
|
|
995
1060
|
try {
|
|
996
1061
|
await (await createTelemetry(config)).publish({
|
|
997
1062
|
type: "cli_generate",
|
|
@@ -1003,7 +1068,7 @@ async function generateAction(opts) {
|
|
|
1003
1068
|
} catch {}
|
|
1004
1069
|
process.exit(0);
|
|
1005
1070
|
} else {
|
|
1006
|
-
|
|
1071
|
+
console.error("Schema generation aborted.");
|
|
1007
1072
|
try {
|
|
1008
1073
|
await (await createTelemetry(config)).publish({
|
|
1009
1074
|
type: "cli_generate",
|
|
@@ -1027,7 +1092,7 @@ async function generateAction(opts) {
|
|
|
1027
1092
|
message: `Do you want to generate the schema to ${chalk.yellow(schema.fileName)}?`
|
|
1028
1093
|
})).confirm;
|
|
1029
1094
|
if (!confirm$1) {
|
|
1030
|
-
|
|
1095
|
+
console.error("Schema generation aborted.");
|
|
1031
1096
|
try {
|
|
1032
1097
|
await (await createTelemetry(config)).publish({
|
|
1033
1098
|
type: "cli_generate",
|
|
@@ -1043,7 +1108,7 @@ async function generateAction(opts) {
|
|
|
1043
1108
|
if (!existsSync(path.dirname(path.join(cwd, schema.fileName)))) await fs$1.mkdir(path.dirname(path.join(cwd, schema.fileName)), { recursive: true });
|
|
1044
1109
|
}
|
|
1045
1110
|
await fs$1.writeFile(options.output || path.join(cwd, schema.fileName), schema.code);
|
|
1046
|
-
|
|
1111
|
+
console.log(`🚀 Schema was generated successfully!`);
|
|
1047
1112
|
try {
|
|
1048
1113
|
await (await createTelemetry(config)).publish({
|
|
1049
1114
|
type: "cli_generate",
|
|
@@ -1719,7 +1784,7 @@ async function generateAuthConfig({ format: format$1, current_user_config, spinn
|
|
|
1719
1784
|
total_dependencies.push(...dependencies);
|
|
1720
1785
|
} catch (error) {
|
|
1721
1786
|
spinner$1.stop(`Something went wrong while generating/updating your new auth config file.`, 1);
|
|
1722
|
-
|
|
1787
|
+
console.error(error.message);
|
|
1723
1788
|
process.exit(1);
|
|
1724
1789
|
}
|
|
1725
1790
|
if (database) try {
|
|
@@ -1732,7 +1797,7 @@ async function generateAuthConfig({ format: format$1, current_user_config, spinn
|
|
|
1732
1797
|
total_envs.push(...envs);
|
|
1733
1798
|
} catch (error) {
|
|
1734
1799
|
spinner$1.stop(`Something went wrong while generating/updating your new auth config file.`, 1);
|
|
1735
|
-
|
|
1800
|
+
console.error(error.message);
|
|
1736
1801
|
process.exit(1);
|
|
1737
1802
|
}
|
|
1738
1803
|
return {
|
|
@@ -1892,7 +1957,7 @@ function installDependencies({ dependencies, packageManager, cwd }) {
|
|
|
1892
1957
|
//#region src/commands/secret.ts
|
|
1893
1958
|
const generateSecret = new Command("secret").action(() => {
|
|
1894
1959
|
const secret = generateSecretHash();
|
|
1895
|
-
|
|
1960
|
+
console.log(`\nAdd the following to your .env file:
|
|
1896
1961
|
${chalk.gray("# Auth Secret") + chalk.green(`\nBETTER_AUTH_SECRET=${secret}`)}`);
|
|
1897
1962
|
});
|
|
1898
1963
|
const generateSecretHash = () => {
|
|
@@ -2722,7 +2787,7 @@ async function loginAction(opts) {
|
|
|
2722
2787
|
});
|
|
2723
2788
|
spinner$1.stop();
|
|
2724
2789
|
if (error || !data) {
|
|
2725
|
-
|
|
2790
|
+
console.error(`Failed to request device authorization: ${error?.error_description || "Unknown error"}`);
|
|
2726
2791
|
process.exit(1);
|
|
2727
2792
|
}
|
|
2728
2793
|
const { device_code, user_code, verification_uri, verification_uri_complete, interval = 5, expires_in } = data;
|
|
@@ -2748,7 +2813,7 @@ async function loginAction(opts) {
|
|
|
2748
2813
|
}
|
|
2749
2814
|
} catch (err) {
|
|
2750
2815
|
spinner$1.stop();
|
|
2751
|
-
|
|
2816
|
+
console.error(`Login failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
2752
2817
|
process.exit(1);
|
|
2753
2818
|
}
|
|
2754
2819
|
}
|
|
@@ -2783,22 +2848,22 @@ async function pollForToken(authClient, deviceCode, clientId, initialInterval) {
|
|
|
2783
2848
|
break;
|
|
2784
2849
|
case "access_denied":
|
|
2785
2850
|
spinner$1.stop();
|
|
2786
|
-
|
|
2851
|
+
console.error("Access was denied by the user");
|
|
2787
2852
|
process.exit(1);
|
|
2788
2853
|
break;
|
|
2789
2854
|
case "expired_token":
|
|
2790
2855
|
spinner$1.stop();
|
|
2791
|
-
|
|
2856
|
+
console.error("The device code has expired. Please try again.");
|
|
2792
2857
|
process.exit(1);
|
|
2793
2858
|
break;
|
|
2794
2859
|
default:
|
|
2795
2860
|
spinner$1.stop();
|
|
2796
|
-
|
|
2861
|
+
console.error(`Error: ${error.error_description}`);
|
|
2797
2862
|
process.exit(1);
|
|
2798
2863
|
}
|
|
2799
2864
|
} catch (err) {
|
|
2800
2865
|
spinner$1.stop();
|
|
2801
|
-
|
|
2866
|
+
console.error(`Network error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
2802
2867
|
process.exit(1);
|
|
2803
2868
|
}
|
|
2804
2869
|
setTimeout(poll, pollingInterval * 1e3);
|
|
@@ -2817,7 +2882,7 @@ async function storeToken(token) {
|
|
|
2817
2882
|
};
|
|
2818
2883
|
await fs$1.writeFile(TOKEN_FILE, JSON.stringify(tokenData, null, 2), "utf-8");
|
|
2819
2884
|
} catch (error) {
|
|
2820
|
-
|
|
2885
|
+
console.warn("Failed to store authentication token locally");
|
|
2821
2886
|
}
|
|
2822
2887
|
}
|
|
2823
2888
|
async function getStoredToken() {
|
|
@@ -2962,6 +3027,7 @@ const mcp = new Command("mcp").description("Add Better Auth MCP server to MCP Cl
|
|
|
2962
3027
|
|
|
2963
3028
|
//#endregion
|
|
2964
3029
|
//#region src/commands/migrate.ts
|
|
3030
|
+
/** @internal */
|
|
2965
3031
|
async function migrateAction(opts) {
|
|
2966
3032
|
const options = z.object({
|
|
2967
3033
|
cwd: z.string(),
|
|
@@ -2971,7 +3037,7 @@ async function migrateAction(opts) {
|
|
|
2971
3037
|
}).parse(opts);
|
|
2972
3038
|
const cwd = path.resolve(options.cwd);
|
|
2973
3039
|
if (!existsSync(cwd)) {
|
|
2974
|
-
|
|
3040
|
+
console.error(`The directory "${cwd}" does not exist.`);
|
|
2975
3041
|
process.exit(1);
|
|
2976
3042
|
}
|
|
2977
3043
|
const config = await getConfig({
|
|
@@ -2979,17 +3045,17 @@ async function migrateAction(opts) {
|
|
|
2979
3045
|
configPath: options.config
|
|
2980
3046
|
});
|
|
2981
3047
|
if (!config) {
|
|
2982
|
-
|
|
3048
|
+
console.error("No configuration file found. Add a `auth.ts` file to your project or pass the path to the configuration file using the `--config` flag.");
|
|
2983
3049
|
return;
|
|
2984
3050
|
}
|
|
2985
3051
|
const db = await getAdapter(config);
|
|
2986
3052
|
if (!db) {
|
|
2987
|
-
|
|
3053
|
+
console.error("Invalid database configuration. Make sure you're not using adapters. Migrate command only works with built-in Kysely adapter.");
|
|
2988
3054
|
process.exit(1);
|
|
2989
3055
|
}
|
|
2990
3056
|
if (db.id !== "kysely") {
|
|
2991
3057
|
if (db.id === "prisma") {
|
|
2992
|
-
|
|
3058
|
+
console.error("The migrate command only works with the built-in Kysely adapter. For Prisma, run `npx @better-auth/cli generate` to create the schema, then use Prisma's migrate or push to apply it.");
|
|
2993
3059
|
try {
|
|
2994
3060
|
await (await createTelemetry(config)).publish({
|
|
2995
3061
|
type: "cli_migrate",
|
|
@@ -3003,7 +3069,7 @@ async function migrateAction(opts) {
|
|
|
3003
3069
|
process.exit(0);
|
|
3004
3070
|
}
|
|
3005
3071
|
if (db.id === "drizzle") {
|
|
3006
|
-
|
|
3072
|
+
console.error("The migrate command only works with the built-in Kysely adapter. For Drizzle, run `npx @better-auth/cli generate` to create the schema, then use Drizzle's migrate or push to apply it.");
|
|
3007
3073
|
try {
|
|
3008
3074
|
await (await createTelemetry(config)).publish({
|
|
3009
3075
|
type: "cli_migrate",
|
|
@@ -3016,7 +3082,7 @@ async function migrateAction(opts) {
|
|
|
3016
3082
|
} catch {}
|
|
3017
3083
|
process.exit(0);
|
|
3018
3084
|
}
|
|
3019
|
-
|
|
3085
|
+
console.error("Migrate command isn't supported for this adapter.");
|
|
3020
3086
|
try {
|
|
3021
3087
|
await (await createTelemetry(config)).publish({
|
|
3022
3088
|
type: "cli_migrate",
|
|
@@ -3033,7 +3099,7 @@ async function migrateAction(opts) {
|
|
|
3033
3099
|
const { toBeAdded, toBeCreated, runMigrations } = await getMigrations(config);
|
|
3034
3100
|
if (!toBeAdded.length && !toBeCreated.length) {
|
|
3035
3101
|
spinner$1.stop();
|
|
3036
|
-
|
|
3102
|
+
console.log("🚀 No migrations needed.");
|
|
3037
3103
|
try {
|
|
3038
3104
|
await (await createTelemetry(config)).publish({
|
|
3039
3105
|
type: "cli_migrate",
|
|
@@ -3046,7 +3112,7 @@ async function migrateAction(opts) {
|
|
|
3046
3112
|
process.exit(0);
|
|
3047
3113
|
}
|
|
3048
3114
|
spinner$1.stop();
|
|
3049
|
-
|
|
3115
|
+
console.log(`🔑 The migration will affect the following:`);
|
|
3050
3116
|
for (const table of [...toBeCreated, ...toBeAdded]) console.log("->", chalk.magenta(Object.keys(table.fields).join(", ")), chalk.white("fields on"), chalk.yellow(`${table.table}`), chalk.white("table."));
|
|
3051
3117
|
if (options.y) {
|
|
3052
3118
|
console.warn("WARNING: --y is deprecated. Consider -y or --yes");
|
|
@@ -3060,7 +3126,7 @@ async function migrateAction(opts) {
|
|
|
3060
3126
|
initial: false
|
|
3061
3127
|
})).migrate;
|
|
3062
3128
|
if (!migrate$1) {
|
|
3063
|
-
|
|
3129
|
+
console.log("Migration cancelled.");
|
|
3064
3130
|
try {
|
|
3065
3131
|
await (await createTelemetry(config)).publish({
|
|
3066
3132
|
type: "cli_migrate",
|
|
@@ -3075,7 +3141,7 @@ async function migrateAction(opts) {
|
|
|
3075
3141
|
spinner$1?.start("migrating...");
|
|
3076
3142
|
await runMigrations();
|
|
3077
3143
|
spinner$1.stop();
|
|
3078
|
-
|
|
3144
|
+
console.log("🚀 migration was completed successfully!");
|
|
3079
3145
|
try {
|
|
3080
3146
|
await (await createTelemetry(config)).publish({
|
|
3081
3147
|
type: "cli_migrate",
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/cli",
|
|
3
|
-
"version": "1.4.6-beta.
|
|
3
|
+
"version": "1.4.6-beta.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The CLI for Better Auth",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/better-auth/better-auth",
|
|
9
|
+
"url": "git+https://github.com/better-auth/better-auth.git",
|
|
10
10
|
"directory": "packages/cli"
|
|
11
11
|
},
|
|
12
12
|
"homepage": "https://www.better-auth.com/docs/concepts/cli",
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"@types/prompts": "^2.4.9",
|
|
34
34
|
"@types/semver": "^7.7.1",
|
|
35
35
|
"jiti": "^2.6.0",
|
|
36
|
-
"tsdown": "^0.
|
|
36
|
+
"tsdown": "^0.17.0",
|
|
37
37
|
"tsx": "^4.20.6",
|
|
38
38
|
"type-fest": "^5.2.0",
|
|
39
39
|
"typescript": "^5.9.3",
|
|
40
|
-
"@better-auth/passkey": "1.4.6-beta.
|
|
40
|
+
"@better-auth/passkey": "1.4.6-beta.6"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@babel/core": "^7.28.4",
|
|
@@ -57,13 +57,13 @@
|
|
|
57
57
|
"open": "^10.2.0",
|
|
58
58
|
"pg": "^8.16.3",
|
|
59
59
|
"prettier": "^3.6.2",
|
|
60
|
-
"prisma": "^5.22.0",
|
|
61
60
|
"prompts": "^2.4.2",
|
|
62
61
|
"semver": "^7.7.2",
|
|
63
62
|
"yocto-spinner": "^0.2.3",
|
|
64
63
|
"zod": "^4.1.12",
|
|
65
|
-
"@better-auth/
|
|
66
|
-
"better-auth": "1.4.6-beta.
|
|
64
|
+
"@better-auth/telemetry": "1.4.6-beta.6",
|
|
65
|
+
"@better-auth/core": "1.4.6-beta.6",
|
|
66
|
+
"better-auth": "^1.4.6-beta.6"
|
|
67
67
|
},
|
|
68
68
|
"files": [
|
|
69
69
|
"dist"
|
|
@@ -74,6 +74,7 @@
|
|
|
74
74
|
"lint:package": "publint run --strict",
|
|
75
75
|
"dev": "tsx ./src/index.ts",
|
|
76
76
|
"test": "vitest",
|
|
77
|
+
"coverage": "vitest run --coverage",
|
|
77
78
|
"typecheck": "tsc --project tsconfig.json"
|
|
78
79
|
}
|
|
79
80
|
}
|