@better-auth/cli 1.5.0-beta.1 → 1.5.0-beta.11

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 CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { i as getPackageInfo, n as generateSchema } from "./generators-BA4_Oq0Q.mjs";
2
3
  import { Command } from "commander";
3
4
  import * as fs$2 from "node:fs";
4
5
  import fs, { existsSync, readFileSync } from "node:fs";
@@ -6,15 +7,13 @@ import fs$1 from "node:fs/promises";
6
7
  import * as path$1 from "node:path";
7
8
  import path from "node:path";
8
9
  import { createTelemetry, getTelemetryAuthConfig } from "@better-auth/telemetry";
9
- import { getAdapter, getAuthTables, getMigrations } from "better-auth/db";
10
+ import { getAdapter } from "better-auth/db/adapter";
10
11
  import chalk from "chalk";
11
12
  import prompts from "prompts";
12
13
  import yoctoSpinner from "yocto-spinner";
13
14
  import * as z from "zod/v4";
14
- import { initGetFieldName, initGetModelName } from "better-auth/adapters";
15
- import prettier, { format } from "prettier";
16
- import { capitalizeFirstLetter } from "@better-auth/core/utils";
17
- import { produceSchema } from "@mrleebo/prisma-ast";
15
+ import { format } from "prettier";
16
+ import { getMigrations } from "better-auth/db/migration";
18
17
  import babelPresetReact from "@babel/preset-react";
19
18
  import babelPresetTypeScript from "@babel/preset-typescript";
20
19
  import { BetterAuthError } from "@better-auth/core/error";
@@ -32,568 +31,6 @@ import open from "open";
32
31
  import { base64 } from "@better-auth/utils/base64";
33
32
  import "dotenv/config";
34
33
 
35
- //#region src/generators/drizzle.ts
36
- function convertToSnakeCase(str, camelCase) {
37
- if (camelCase) return str;
38
- return str.replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").toLowerCase();
39
- }
40
- const generateDrizzleSchema = async ({ options, file, adapter }) => {
41
- const tables = getAuthTables(options);
42
- const filePath = file || "./auth-schema.ts";
43
- const databaseType = adapter.options?.provider;
44
- if (!databaseType) throw new Error(`Database provider type is undefined during Drizzle schema generation. Please define a \`provider\` in the Drizzle adapter config. Read more at https://better-auth.com/docs/adapters/drizzle`);
45
- const fileExist = existsSync(filePath);
46
- let code = generateImport({
47
- databaseType,
48
- tables,
49
- options
50
- });
51
- const getModelName = initGetModelName({
52
- schema: tables,
53
- usePlural: adapter.options?.adapterConfig?.usePlural
54
- });
55
- const getFieldName = initGetFieldName({
56
- schema: tables,
57
- usePlural: adapter.options?.adapterConfig?.usePlural
58
- });
59
- for (const tableKey in tables) {
60
- const table = tables[tableKey];
61
- const modelName = getModelName(tableKey);
62
- const fields = table.fields;
63
- function getType(name, field) {
64
- if (!databaseType) throw new Error(`Database provider type is undefined during Drizzle schema generation. Please define a \`provider\` in the Drizzle adapter config. Read more at https://better-auth.com/docs/adapters/drizzle`);
65
- name = convertToSnakeCase(name, adapter.options?.camelCase);
66
- if (field.references?.field === "id") {
67
- const useNumberId$1 = options.advanced?.database?.useNumberId || options.advanced?.database?.generateId === "serial";
68
- const useUUIDs = options.advanced?.database?.generateId === "uuid";
69
- if (useNumberId$1) if (databaseType === "pg") return `integer('${name}')`;
70
- else if (databaseType === "mysql") return `int('${name}')`;
71
- else return `integer('${name}')`;
72
- if (useUUIDs && databaseType === "pg") return `uuid('${name}')`;
73
- if (field.references.field) {
74
- if (databaseType === "mysql") return `varchar('${name}', { length: 36 })`;
75
- }
76
- return `text('${name}')`;
77
- }
78
- const type = field.type;
79
- if (typeof type !== "string") if (Array.isArray(type) && type.every((x) => typeof x === "string")) return {
80
- sqlite: `text({ enum: [${type.map((x) => `'${x}'`).join(", ")}] })`,
81
- pg: `text('${name}', { enum: [${type.map((x) => `'${x}'`).join(", ")}] })`,
82
- mysql: `mysqlEnum([${type.map((x) => `'${x}'`).join(", ")}])`
83
- }[databaseType];
84
- else throw new TypeError(`Invalid field type for field ${name} in model ${modelName}`);
85
- const dbTypeMap = {
86
- string: {
87
- sqlite: `text('${name}')`,
88
- pg: `text('${name}')`,
89
- mysql: field.unique ? `varchar('${name}', { length: 255 })` : field.references ? `varchar('${name}', { length: 36 })` : field.sortable ? `varchar('${name}', { length: 255 })` : field.index ? `varchar('${name}', { length: 255 })` : `text('${name}')`
90
- },
91
- boolean: {
92
- sqlite: `integer('${name}', { mode: 'boolean' })`,
93
- pg: `boolean('${name}')`,
94
- mysql: `boolean('${name}')`
95
- },
96
- number: {
97
- sqlite: `integer('${name}')`,
98
- pg: field.bigint ? `bigint('${name}', { mode: 'number' })` : `integer('${name}')`,
99
- mysql: field.bigint ? `bigint('${name}', { mode: 'number' })` : `int('${name}')`
100
- },
101
- date: {
102
- sqlite: `integer('${name}', { mode: 'timestamp_ms' })`,
103
- pg: `timestamp('${name}')`,
104
- mysql: `timestamp('${name}', { fsp: 3 })`
105
- },
106
- "number[]": {
107
- sqlite: `text('${name}', { mode: "json" })`,
108
- pg: field.bigint ? `bigint('${name}', { mode: 'number' }).array()` : `integer('${name}').array()`,
109
- mysql: `text('${name}', { mode: 'json' })`
110
- },
111
- "string[]": {
112
- sqlite: `text('${name}', { mode: "json" })`,
113
- pg: `text('${name}').array()`,
114
- mysql: `text('${name}', { mode: "json" })`
115
- },
116
- json: {
117
- sqlite: `text('${name}', { mode: "json" })`,
118
- pg: `jsonb('${name}')`,
119
- mysql: `json('${name}', { mode: "json" })`
120
- }
121
- }[type];
122
- if (!dbTypeMap) throw new Error(`Unsupported field type '${field.type}' for field '${name}'.`);
123
- return dbTypeMap[databaseType];
124
- }
125
- let id = "";
126
- const useNumberId = options.advanced?.database?.useNumberId || options.advanced?.database?.generateId === "serial";
127
- if (options.advanced?.database?.generateId === "uuid" && databaseType === "pg") id = `uuid("id").default(sql\`pg_catalog.gen_random_uuid()\`).primaryKey()`;
128
- else if (useNumberId) if (databaseType === "pg") id = `integer("id").generatedByDefaultAsIdentity().primaryKey()`;
129
- else if (databaseType === "sqlite") id = `integer("id", { mode: "number" }).primaryKey({ autoIncrement: true })`;
130
- else id = `int("id").autoincrement().primaryKey()`;
131
- else if (databaseType === "mysql") id = `varchar('id', { length: 36 }).primaryKey()`;
132
- else if (databaseType === "pg") id = `text('id').primaryKey()`;
133
- else id = `text('id').primaryKey()`;
134
- let indexes = [];
135
- const assignIndexes = (indexes$1) => {
136
- if (!indexes$1.length) return "";
137
- let code$1 = [`, (table) => [`];
138
- for (const index of indexes$1) code$1.push(` ${index.type}("${index.name}").on(table.${index.on}),`);
139
- code$1.push(`]`);
140
- return code$1.join("\n");
141
- };
142
- const schema = `export const ${modelName} = ${databaseType}Table("${convertToSnakeCase(modelName, adapter.options?.camelCase)}", {
143
- id: ${id},
144
- ${Object.keys(fields).map((field) => {
145
- const attr = fields[field];
146
- const fieldName = attr.fieldName || field;
147
- let type = getType(fieldName, attr);
148
- if (attr.index && !attr.unique) indexes.push({
149
- type: "index",
150
- name: `${modelName}_${fieldName}_idx`,
151
- on: fieldName
152
- });
153
- else if (attr.index && attr.unique) indexes.push({
154
- type: "uniqueIndex",
155
- name: `${modelName}_${fieldName}_uidx`,
156
- on: fieldName
157
- });
158
- if (attr.defaultValue !== null && typeof attr.defaultValue !== "undefined") if (typeof attr.defaultValue === "function") {
159
- if (attr.type === "date" && attr.defaultValue.toString().includes("new Date()")) if (databaseType === "sqlite") type += `.default(sql\`(cast(unixepoch('subsecond') * 1000 as integer))\`)`;
160
- else type += `.defaultNow()`;
161
- } else if (typeof attr.defaultValue === "string") type += `.default("${attr.defaultValue}")`;
162
- else type += `.default(${attr.defaultValue})`;
163
- if (attr.onUpdate && attr.type === "date") {
164
- if (typeof attr.onUpdate === "function") type += `.$onUpdate(${attr.onUpdate})`;
165
- }
166
- return `${fieldName}: ${type}${attr.required ? ".notNull()" : ""}${attr.unique ? ".unique()" : ""}${attr.references ? `.references(()=> ${getModelName(attr.references.model)}.${getFieldName({
167
- model: attr.references.model,
168
- field: attr.references.field
169
- })}, { onDelete: '${attr.references.onDelete || "cascade"}' })` : ""}`;
170
- }).join(",\n ")}
171
- }${assignIndexes(indexes)});`;
172
- code += `\n${schema}\n`;
173
- }
174
- let relationsString = "";
175
- for (const tableKey in tables) {
176
- const table = tables[tableKey];
177
- const modelName = getModelName(tableKey);
178
- const oneRelations = [];
179
- const manyRelations = [];
180
- const manyRelationsSet = /* @__PURE__ */ new Set();
181
- const foreignFields = Object.entries(table.fields).filter(([_, field]) => field.references);
182
- for (const [fieldName, field] of foreignFields) {
183
- const referencedModel = field.references.model;
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,
195
- model: getModelName(referencedModel),
196
- type: "one",
197
- reference: {
198
- field: fieldRef,
199
- references: referenceRef,
200
- fieldName
201
- }
202
- });
203
- }
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) {
207
- const foreignKeysPointingHere = Object.entries(otherTable.fields).filter(([_, field]) => field.references?.model === tableKey || field.references?.model === getModelName(tableKey));
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, 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({
224
- key: relationKey,
225
- model: getModelName(modelName$1),
226
- type: relationType
227
- });
228
- }
229
- }
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 ")}
267
- }))`;
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
- }
275
- }
276
- code += `\n${relationsString}`;
277
- return {
278
- code: await prettier.format(code, { parser: "typescript" }),
279
- fileName: filePath,
280
- overwrite: fileExist
281
- };
282
- };
283
- function generateImport({ databaseType, tables, options }) {
284
- const rootImports = ["relations"];
285
- const coreImports = [];
286
- let hasBigint = false;
287
- let hasJson = false;
288
- for (const table of Object.values(tables)) {
289
- for (const field of Object.values(table.fields)) {
290
- if (field.bigint) hasBigint = true;
291
- if (field.type === "json") hasJson = true;
292
- }
293
- if (hasJson && hasBigint) break;
294
- }
295
- const useNumberId = options.advanced?.database?.useNumberId || options.advanced?.database?.generateId === "serial";
296
- const useUUIDs = options.advanced?.database?.generateId === "uuid";
297
- coreImports.push(`${databaseType}Table`);
298
- coreImports.push(databaseType === "mysql" ? "varchar, text" : databaseType === "pg" ? "text" : "text");
299
- coreImports.push(hasBigint ? databaseType !== "sqlite" ? "bigint" : "" : "");
300
- coreImports.push(databaseType !== "sqlite" ? "timestamp, boolean" : "");
301
- if (databaseType === "mysql") {
302
- const hasNonBigintNumber = Object.values(tables).some((table) => Object.values(table.fields).some((field) => (field.type === "number" || field.type === "number[]") && !field.bigint));
303
- if (!!useNumberId || hasNonBigintNumber) coreImports.push("int");
304
- if (Object.values(tables).some((table) => Object.values(table.fields).some((field) => typeof field.type !== "string" && Array.isArray(field.type) && field.type.every((x) => typeof x === "string")))) coreImports.push("mysqlEnum");
305
- } else if (databaseType === "pg") {
306
- if (useUUIDs) rootImports.push("sql");
307
- const hasNonBigintNumber = Object.values(tables).some((table) => Object.values(table.fields).some((field) => (field.type === "number" || field.type === "number[]") && !field.bigint));
308
- const hasFkToId = Object.values(tables).some((table) => Object.values(table.fields).some((field) => field.references?.field === "id"));
309
- if (hasNonBigintNumber || (options.advanced?.database?.useNumberId || options.advanced?.database?.generateId === "serial") && hasFkToId) coreImports.push("integer");
310
- } else coreImports.push("integer");
311
- if (databaseType === "pg" && useUUIDs) coreImports.push("uuid");
312
- if (hasJson) {
313
- if (databaseType === "pg") coreImports.push("jsonb");
314
- if (databaseType === "mysql") coreImports.push("json");
315
- }
316
- if (databaseType === "sqlite" && Object.values(tables).some((table) => Object.values(table.fields).some((field) => field.type === "date" && field.defaultValue && typeof field.defaultValue === "function" && field.defaultValue.toString().includes("new Date()")))) rootImports.push("sql");
317
- const hasIndexes = Object.values(tables).some((table) => Object.values(table.fields).some((field) => field.index && !field.unique));
318
- const hasUniqueIndexes = Object.values(tables).some((table) => Object.values(table.fields).some((field) => field.unique && field.index));
319
- if (hasIndexes) coreImports.push("index");
320
- if (hasUniqueIndexes) coreImports.push("uniqueIndex");
321
- return `${rootImports.length > 0 ? `import { ${rootImports.join(", ")} } from "drizzle-orm";\n` : ""}import { ${coreImports.map((x) => x.trim()).filter((x) => x !== "").join(", ")} } from "drizzle-orm/${databaseType}-core";\n`;
322
- }
323
-
324
- //#endregion
325
- //#region src/generators/kysely.ts
326
- const generateMigrations = async ({ options, file }) => {
327
- const { compileMigrations } = await getMigrations(options);
328
- const migrations = await compileMigrations();
329
- return {
330
- code: migrations.trim() === ";" ? "" : migrations,
331
- fileName: file || `./better-auth_migrations/${(/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-")}.sql`
332
- };
333
- };
334
-
335
- //#endregion
336
- //#region src/utils/get-package-info.ts
337
- function getPackageInfo(cwd) {
338
- const packageJsonPath = cwd ? path.join(cwd, "package.json") : path.join("package.json");
339
- return JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
340
- }
341
- function getPrismaVersion(cwd) {
342
- try {
343
- const packageInfo = getPackageInfo(cwd);
344
- const prismaVersion = packageInfo.dependencies?.prisma || packageInfo.devDependencies?.prisma || packageInfo.dependencies?.["@prisma/client"] || packageInfo.devDependencies?.["@prisma/client"];
345
- if (!prismaVersion) return null;
346
- const match = prismaVersion.match(/(\d+)/);
347
- return match ? parseInt(match[1], 10) : null;
348
- } catch {
349
- return null;
350
- }
351
- }
352
-
353
- //#endregion
354
- //#region src/generators/prisma.ts
355
- const generatePrismaSchema = async ({ adapter, options, file }) => {
356
- const provider = adapter.options?.provider || "postgresql";
357
- const tables = getAuthTables(options);
358
- const filePath = file || "./prisma/schema.prisma";
359
- const schemaPrismaExist = existsSync(path.join(process.cwd(), filePath));
360
- const getModelName = initGetModelName({
361
- schema: getAuthTables(options),
362
- usePlural: adapter.options?.adapterConfig?.usePlural
363
- });
364
- const getFieldName = initGetFieldName({
365
- schema: getAuthTables(options),
366
- usePlural: false
367
- });
368
- let schemaPrisma = "";
369
- if (schemaPrismaExist) schemaPrisma = await fs$1.readFile(path.join(process.cwd(), filePath), "utf-8");
370
- else schemaPrisma = getNewPrisma(provider, process.cwd());
371
- const prismaVersion = getPrismaVersion(process.cwd());
372
- if (prismaVersion && prismaVersion >= 7 && schemaPrismaExist) schemaPrisma = produceSchema(schemaPrisma, (builder) => {
373
- const generator = builder.findByType("generator", { name: "client" });
374
- if (generator && generator.properties) {
375
- const providerProp = generator.properties.find((prop) => prop.type === "assignment" && prop.key === "provider");
376
- if (providerProp && providerProp.value === "\"prisma-client-js\"") providerProp.value = "\"prisma-client\"";
377
- }
378
- });
379
- const manyToManyRelations = /* @__PURE__ */ new Map();
380
- for (const table in tables) {
381
- const fields = tables[table]?.fields;
382
- for (const field in fields) {
383
- const attr = fields[field];
384
- if (attr.references) {
385
- const referencedOriginalModel = attr.references.model;
386
- const referencedModelNameCap = capitalizeFirstLetter(getModelName(tables[referencedOriginalModel]?.modelName || referencedOriginalModel));
387
- if (!manyToManyRelations.has(referencedModelNameCap)) manyToManyRelations.set(referencedModelNameCap, /* @__PURE__ */ new Set());
388
- const currentModelNameCap = capitalizeFirstLetter(getModelName(tables[table]?.modelName || table));
389
- manyToManyRelations.get(referencedModelNameCap).add(currentModelNameCap);
390
- }
391
- }
392
- }
393
- const indexedFields = /* @__PURE__ */ new Map();
394
- for (const table in tables) {
395
- const fields = tables[table]?.fields;
396
- const modelName = capitalizeFirstLetter(getModelName(tables[table]?.modelName || table));
397
- indexedFields.set(modelName, []);
398
- for (const field in fields) {
399
- const attr = fields[field];
400
- if (attr.index && !attr.unique) {
401
- const fieldName = attr.fieldName || field;
402
- indexedFields.get(modelName).push(fieldName);
403
- }
404
- }
405
- }
406
- const schema = produceSchema(schemaPrisma, (builder) => {
407
- for (const table in tables) {
408
- const originalTableName = table;
409
- const customModelName = tables[table]?.modelName || table;
410
- const modelName = capitalizeFirstLetter(getModelName(customModelName));
411
- const fields = tables[table]?.fields;
412
- function getType({ isBigint, isOptional, type }) {
413
- if (type === "string") return isOptional ? "String?" : "String";
414
- if (type === "number" && isBigint) return isOptional ? "BigInt?" : "BigInt";
415
- if (type === "number") return isOptional ? "Int?" : "Int";
416
- if (type === "boolean") return isOptional ? "Boolean?" : "Boolean";
417
- if (type === "date") return isOptional ? "DateTime?" : "DateTime";
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
- }
430
- }
431
- const prismaModel = builder.findByType("model", { name: modelName });
432
- if (!prismaModel) if (provider === "mongodb") builder.model(modelName).field("id", "String").attribute("id").attribute(`map("_id")`);
433
- else {
434
- const useNumberId = options.advanced?.database?.useNumberId || options.advanced?.database?.generateId === "serial";
435
- const useUUIDs = options.advanced?.database?.generateId === "uuid";
436
- if (useNumberId) builder.model(modelName).field("id", "Int").attribute("id").attribute("default(autoincrement())");
437
- else if (useUUIDs && provider === "postgresql") builder.model(modelName).field("id", "String").attribute("id").attribute("default(dbgenerated(\"pg_catalog.gen_random_uuid()\"))").attribute("db.Uuid");
438
- else builder.model(modelName).field("id", "String").attribute("id");
439
- }
440
- for (const field in fields) {
441
- const attr = fields[field];
442
- const fieldName = attr.fieldName || field;
443
- if (prismaModel) {
444
- if (builder.findByType("field", {
445
- name: fieldName,
446
- within: prismaModel.properties
447
- })) continue;
448
- }
449
- const useUUIDs = options.advanced?.database?.generateId === "uuid";
450
- const useNumberId = options.advanced?.database?.useNumberId || options.advanced?.database?.generateId === "serial";
451
- const fieldBuilder = builder.model(modelName).field(fieldName, field === "id" && useNumberId ? getType({
452
- isBigint: false,
453
- isOptional: false,
454
- type: "number"
455
- }) : getType({
456
- isBigint: attr?.bigint || false,
457
- isOptional: !attr?.required,
458
- type: attr.references?.field === "id" ? useNumberId ? "number" : "string" : attr.type
459
- }));
460
- if (field === "id") {
461
- fieldBuilder.attribute("id");
462
- if (provider === "mongodb") fieldBuilder.attribute(`map("_id")`);
463
- }
464
- if (attr.unique) builder.model(modelName).blockAttribute(`unique([${fieldName}])`);
465
- if (attr.defaultValue !== void 0) {
466
- if (Array.isArray(attr.defaultValue)) {
467
- if (attr.type === "json") {
468
- if (Object.prototype.toString.call(attr.defaultValue[0]) === "[object Object]") {
469
- fieldBuilder.attribute(`default("${JSON.stringify(attr.defaultValue).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}")`);
470
- continue;
471
- }
472
- let jsonArray = [];
473
- for (const value of attr.defaultValue) jsonArray.push(value);
474
- fieldBuilder.attribute(`default("${JSON.stringify(jsonArray).replace(/"/g, "\\\"")}")`);
475
- continue;
476
- }
477
- if (attr.defaultValue.length === 0) {
478
- fieldBuilder.attribute(`default([])`);
479
- continue;
480
- } else if (typeof attr.defaultValue[0] === "string" && attr.type === "string[]") {
481
- let valueArray = [];
482
- for (const value of attr.defaultValue) valueArray.push(JSON.stringify(value));
483
- fieldBuilder.attribute(`default([${valueArray}])`);
484
- } else if (typeof attr.defaultValue[0] === "number") {
485
- let valueArray = [];
486
- for (const value of attr.defaultValue) valueArray.push(`${value}`);
487
- fieldBuilder.attribute(`default([${valueArray}])`);
488
- }
489
- } else if (typeof attr.defaultValue === "object" && !Array.isArray(attr.defaultValue) && attr.defaultValue !== null) {
490
- if (Object.entries(attr.defaultValue).length === 0) {
491
- fieldBuilder.attribute(`default("{}")`);
492
- continue;
493
- }
494
- fieldBuilder.attribute(`default("${JSON.stringify(attr.defaultValue).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}")`);
495
- }
496
- if (field === "createdAt") fieldBuilder.attribute("default(now())");
497
- else if (typeof attr.defaultValue === "string" && provider !== "mysql") fieldBuilder.attribute(`default("${attr.defaultValue}")`);
498
- else if (typeof attr.defaultValue === "boolean" || typeof attr.defaultValue === "number") fieldBuilder.attribute(`default(${attr.defaultValue})`);
499
- else if (typeof attr.defaultValue === "function") {}
500
- }
501
- if (field === "updatedAt" && attr.onUpdate) fieldBuilder.attribute("updatedAt");
502
- else if (attr.onUpdate) {}
503
- if (attr.references) {
504
- if (useUUIDs && provider === "postgresql" && attr.references?.field === "id") builder.model(modelName).field(fieldName).attribute(`db.Uuid`);
505
- const referencedOriginalModelName = getModelName(attr.references.model);
506
- const referencedCustomModelName = tables[referencedOriginalModelName]?.modelName || referencedOriginalModelName;
507
- let action = "Cascade";
508
- if (attr.references.onDelete === "no action") action = "NoAction";
509
- else if (attr.references.onDelete === "set null") action = "SetNull";
510
- else if (attr.references.onDelete === "set default") action = "SetDefault";
511
- else if (attr.references.onDelete === "restrict") action = "Restrict";
512
- const relationField = `relation(fields: [${getFieldName({
513
- model: originalTableName,
514
- field: fieldName
515
- })}], references: [${getFieldName({
516
- model: attr.references.model,
517
- field: attr.references.field
518
- })}], onDelete: ${action})`;
519
- builder.model(modelName).field(referencedCustomModelName.toLowerCase(), `${capitalizeFirstLetter(referencedCustomModelName)}${!attr.required ? "?" : ""}`).attribute(relationField);
520
- }
521
- if (!attr.unique && !attr.references && provider === "mysql" && attr.type === "string") builder.model(modelName).field(fieldName).attribute("db.Text");
522
- }
523
- if (manyToManyRelations.has(modelName)) for (const relatedModel of manyToManyRelations.get(modelName)) {
524
- const relatedTableName = Object.keys(tables).find((key) => capitalizeFirstLetter(tables[key]?.modelName || key) === relatedModel);
525
- const relatedFields = relatedTableName ? tables[relatedTableName]?.fields : {};
526
- const [_fieldKey, fkFieldAttr] = Object.entries(relatedFields || {}).find(([_fieldName, fieldAttr]) => fieldAttr.references && getModelName(fieldAttr.references.model) === getModelName(originalTableName)) || [];
527
- const isUnique = fkFieldAttr?.unique === true;
528
- const fieldName = isUnique || adapter.options?.usePlural === true ? `${relatedModel.toLowerCase()}` : `${relatedModel.toLowerCase()}s`;
529
- if (!builder.findByType("field", {
530
- name: fieldName,
531
- within: prismaModel?.properties
532
- })) builder.model(modelName).field(fieldName, `${relatedModel}${isUnique ? "?" : "[]"}`);
533
- }
534
- const indexedFieldsForModel = indexedFields.get(modelName);
535
- if (indexedFieldsForModel && indexedFieldsForModel.length > 0) for (const fieldName of indexedFieldsForModel) {
536
- if (prismaModel) {
537
- if (prismaModel.properties.some((v) => v.type === "attribute" && v.name === "index" && JSON.stringify(v.args[0]?.value).includes(fieldName))) continue;
538
- }
539
- const field = Object.entries(fields).find(([key, attr]) => (attr.fieldName || key) === fieldName)?.[1];
540
- let indexField = fieldName;
541
- if (provider === "mysql" && field && field.type === "string") {
542
- const useNumberId = options.advanced?.database?.useNumberId || options.advanced?.database?.generateId === "serial";
543
- const useUUIDs = options.advanced?.database?.generateId === "uuid";
544
- if (field.references?.field === "id" && (useNumberId || useUUIDs)) indexField = `${fieldName}`;
545
- else indexField = `${fieldName}(length: 191)`;
546
- }
547
- builder.model(modelName).blockAttribute(`index([${indexField}])`);
548
- }
549
- const hasAttribute = builder.findByType("attribute", {
550
- name: "map",
551
- within: prismaModel?.properties
552
- });
553
- const hasChanged = customModelName !== originalTableName;
554
- if (!hasAttribute) builder.model(modelName).blockAttribute("map", `${getModelName(hasChanged ? customModelName : originalTableName)}`);
555
- }
556
- });
557
- const schemaChanged = schema.trim() !== schemaPrisma.trim();
558
- return {
559
- code: schemaChanged ? schema : "",
560
- fileName: filePath,
561
- overwrite: schemaPrismaExist && schemaChanged
562
- };
563
- };
564
- const getNewPrisma = (provider, cwd) => {
565
- const prismaVersion = getPrismaVersion(cwd);
566
- return `generator client {
567
- provider = "${prismaVersion && prismaVersion >= 7 ? "prisma-client" : "prisma-client-js"}"
568
- }
569
-
570
- datasource db {
571
- provider = "${provider}"
572
- url = ${provider === "sqlite" ? `"file:./dev.db"` : `env("DATABASE_URL")`}
573
- }`;
574
- };
575
-
576
- //#endregion
577
- //#region src/generators/index.ts
578
- const adapters = {
579
- prisma: generatePrismaSchema,
580
- drizzle: generateDrizzleSchema,
581
- kysely: generateMigrations
582
- };
583
- const generateSchema = (opts) => {
584
- const adapter = opts.adapter;
585
- const generator = adapter.id in adapters ? adapters[adapter.id] : null;
586
- if (generator) return generator(opts);
587
- if (adapter.createSchema) return adapter.createSchema(opts.options, opts.file).then(({ code, path: fileName, overwrite }) => ({
588
- code,
589
- fileName,
590
- overwrite
591
- }));
592
- console.error(`${adapter.id} is not supported. If it is a custom adapter, please request the maintainer to implement createSchema`);
593
- process.exit(1);
594
- };
595
-
596
- //#endregion
597
34
  //#region src/utils/add-cloudflare-modules.ts
598
35
  const createModule = () => {
599
36
  return `data:text/javascript;charset=utf-8,${encodeURIComponent(`
@@ -829,8 +266,8 @@ function getTsconfigInfo(cwd, flatPath) {
829
266
  if (flatPath) tsConfigPath = flatPath;
830
267
  else tsConfigPath = cwd ? path.join(cwd, "tsconfig.json") : path.join("tsconfig.json");
831
268
  try {
832
- const text$1 = fs.readFileSync(tsConfigPath, "utf-8");
833
- return JSON.parse(stripJsonComments(text$1));
269
+ const text = fs.readFileSync(tsConfigPath, "utf-8");
270
+ return JSON.parse(stripJsonComments(text));
834
271
  } catch (error) {
835
272
  throw error;
836
273
  }
@@ -904,7 +341,8 @@ function getPathAliasesRecursive(tsconfigPath, visited = /* @__PURE__ */ new Set
904
341
  }
905
342
  }
906
343
  function getPathAliases(cwd) {
907
- const tsConfigPath = path.join(cwd, "tsconfig.json");
344
+ let tsConfigPath = path.join(cwd, "tsconfig.json");
345
+ if (!fs.existsSync(tsConfigPath)) tsConfigPath = path.join(cwd, "jsconfig.json");
908
346
  if (!fs.existsSync(tsConfigPath)) return null;
909
347
  try {
910
348
  const result = getPathAliasesRecursive(tsConfigPath);
@@ -1024,13 +462,13 @@ async function generateAction(opts) {
1024
462
  console.error(e.message);
1025
463
  process.exit(1);
1026
464
  });
1027
- const spinner$1 = yoctoSpinner({ text: "preparing schema..." }).start();
465
+ const spinner = yoctoSpinner({ text: "preparing schema..." }).start();
1028
466
  const schema = await generateSchema({
1029
467
  adapter,
1030
468
  file: options.output,
1031
469
  options: config
1032
470
  });
1033
- spinner$1.stop();
471
+ spinner.stop();
1034
472
  if (!schema.code) {
1035
473
  console.log("Your schema is already up to date.");
1036
474
  try {
@@ -1048,13 +486,13 @@ async function generateAction(opts) {
1048
486
  process.exit(0);
1049
487
  }
1050
488
  if (schema.overwrite) {
1051
- let confirm$2 = options.y || options.yes;
1052
- if (!confirm$2) confirm$2 = (await prompts({
489
+ let confirm = options.y || options.yes;
490
+ if (!confirm) confirm = (await prompts({
1053
491
  type: "confirm",
1054
492
  name: "confirm",
1055
493
  message: `The file ${schema.fileName} already exists. Do you want to ${chalk.yellow(`${schema.overwrite ? "overwrite" : "append"}`)} the schema to the file?`
1056
494
  })).confirm;
1057
- if (confirm$2) {
495
+ if (confirm) {
1058
496
  if (!existsSync(path.join(cwd, schema.fileName))) await fs$1.mkdir(path.dirname(path.join(cwd, schema.fileName)), { recursive: true });
1059
497
  if (schema.overwrite) await fs$1.writeFile(path.join(cwd, schema.fileName), schema.code);
1060
498
  else await fs$1.appendFile(path.join(cwd, schema.fileName), schema.code);
@@ -1087,13 +525,13 @@ async function generateAction(opts) {
1087
525
  console.warn("WARNING: --y is deprecated. Consider -y or --yes");
1088
526
  options.yes = true;
1089
527
  }
1090
- let confirm$1 = options.yes;
1091
- if (!confirm$1) confirm$1 = (await prompts({
528
+ let confirm = options.yes;
529
+ if (!confirm) confirm = (await prompts({
1092
530
  type: "confirm",
1093
531
  name: "confirm",
1094
532
  message: `Do you want to generate the schema to ${chalk.yellow(schema.fileName)}?`
1095
533
  })).confirm;
1096
- if (!confirm$1) {
534
+ if (!confirm) {
1097
535
  console.error("Schema generation aborted.");
1098
536
  try {
1099
537
  await (await createTelemetry(config)).publish({
@@ -1489,7 +927,7 @@ ${JSON.stringify(betterAuthInfo, null, 2)}
1489
927
 
1490
928
  //#endregion
1491
929
  //#region src/generators/auth-config.ts
1492
- async function generateAuthConfig({ format: format$1, current_user_config, spinner: spinner$1, plugins, database }) {
930
+ async function generateAuthConfig({ format, current_user_config, spinner, plugins, database }) {
1493
931
  const common_indexes = {
1494
932
  START_OF_PLUGINS: { START_OF_PLUGINS: {
1495
933
  type: "regex",
@@ -1514,9 +952,9 @@ async function generateAuthConfig({ format: format$1, current_user_config, spinn
1514
952
  };
1515
953
  const config_generation = {
1516
954
  add_plugin: async (opts) => {
1517
- let start_of_plugins = getGroupInfo(opts.config, common_indexes.START_OF_PLUGINS, {});
955
+ const start_of_plugins = getGroupInfo(opts.config, common_indexes.START_OF_PLUGINS, {});
1518
956
  if (!start_of_plugins) throw new Error("Couldn't find start of your plugins array in your auth config file.");
1519
- let end_of_plugins = getGroupInfo(opts.config, common_indexes.END_OF_PLUGINS, { start_of_plugins: start_of_plugins.index });
957
+ const end_of_plugins = getGroupInfo(opts.config, common_indexes.END_OF_PLUGINS, { start_of_plugins: start_of_plugins.index });
1520
958
  if (!end_of_plugins) throw new Error("Couldn't find end of your plugins array in your auth config file.");
1521
959
  let new_content;
1522
960
  if (opts.direction_in_plugins_array === "prepend") new_content = insertContent({
@@ -1538,7 +976,7 @@ async function generateAuthConfig({ format: format$1, current_user_config, spinn
1538
976
  });
1539
977
  }
1540
978
  try {
1541
- new_content = await format$1(new_content);
979
+ new_content = await format(new_content);
1542
980
  } catch (error) {
1543
981
  console.error(error);
1544
982
  throw new Error(`Failed to generate new auth config during plugin addition phase.`);
@@ -1555,7 +993,7 @@ async function generateAuthConfig({ format: format$1, current_user_config, spinn
1555
993
  else importString += `import ${import_.variables.asType ? "type " : ""}${import_.variables.name}${import_.variables.as ? ` as ${import_.variables.as}` : ""} from "${import_.path}";\n`;
1556
994
  try {
1557
995
  return {
1558
- code: await format$1(importString + opts.config),
996
+ code: await format(importString + opts.config),
1559
997
  dependencies: [],
1560
998
  envs: []
1561
999
  };
@@ -1570,10 +1008,10 @@ async function generateAuthConfig({ format: format$1, current_user_config, spinn
1570
1008
  let database_code_str = "";
1571
1009
  async function add_db({ db_code, dependencies, envs, imports, code_before_betterAuth }) {
1572
1010
  if (code_before_betterAuth) {
1573
- let start_of_betterauth$1 = getGroupInfo(opts.config, common_indexes.START_OF_BETTERAUTH, {});
1574
- if (!start_of_betterauth$1) throw new Error("Couldn't find start of betterAuth() function.");
1011
+ const start_of_betterauth = getGroupInfo(opts.config, common_indexes.START_OF_BETTERAUTH, {});
1012
+ if (!start_of_betterauth) throw new Error("Couldn't find start of betterAuth() function.");
1575
1013
  opts.config = insertContent({
1576
- line: start_of_betterauth$1.line - 1,
1014
+ line: start_of_betterauth.line - 1,
1577
1015
  character: 0,
1578
1016
  content: opts.config,
1579
1017
  insert_content: `\n${code_before_betterAuth}\n`
@@ -1718,7 +1156,7 @@ async function generateAuthConfig({ format: format$1, current_user_config, spinn
1718
1156
  variables: [{ name: "MongoClient" }]
1719
1157
  }]
1720
1158
  });
1721
- let start_of_betterauth = getGroupInfo(opts.config, common_indexes.START_OF_BETTERAUTH, {});
1159
+ const start_of_betterauth = getGroupInfo(opts.config, common_indexes.START_OF_BETTERAUTH, {});
1722
1160
  if (!start_of_betterauth) throw new Error("Couldn't find start of betterAuth() function.");
1723
1161
  let new_content;
1724
1162
  new_content = insertContent({
@@ -1728,7 +1166,7 @@ async function generateAuthConfig({ format: format$1, current_user_config, spinn
1728
1166
  insert_content: `database: ${database_code_str},`
1729
1167
  });
1730
1168
  try {
1731
- new_content = await format$1(new_content);
1169
+ new_content = await format(new_content);
1732
1170
  return {
1733
1171
  code: new_content,
1734
1172
  dependencies: required_deps,
@@ -1740,9 +1178,9 @@ async function generateAuthConfig({ format: format$1, current_user_config, spinn
1740
1178
  }
1741
1179
  }
1742
1180
  };
1743
- let new_user_config = await format$1(current_user_config);
1744
- let total_dependencies = [];
1745
- let total_envs = [];
1181
+ let new_user_config = await format(current_user_config);
1182
+ const total_dependencies = [];
1183
+ const total_envs = [];
1746
1184
  if (plugins.length !== 0) {
1747
1185
  const imports = [];
1748
1186
  for await (const plugin of plugins) {
@@ -1785,7 +1223,7 @@ async function generateAuthConfig({ format: format$1, current_user_config, spinn
1785
1223
  total_envs.push(...envs);
1786
1224
  total_dependencies.push(...dependencies);
1787
1225
  } catch (error) {
1788
- spinner$1.stop(`Something went wrong while generating/updating your new auth config file.`, 1);
1226
+ spinner.stop(`Something went wrong while generating/updating your new auth config file.`, 1);
1789
1227
  console.error(error.message);
1790
1228
  process.exit(1);
1791
1229
  }
@@ -1798,7 +1236,7 @@ async function generateAuthConfig({ format: format$1, current_user_config, spinn
1798
1236
  total_dependencies.push(...dependencies);
1799
1237
  total_envs.push(...envs);
1800
1238
  } catch (error) {
1801
- spinner$1.stop(`Something went wrong while generating/updating your new auth config file.`, 1);
1239
+ spinner.stop(`Something went wrong while generating/updating your new auth config file.`, 1);
1802
1240
  console.error(error.message);
1803
1241
  process.exit(1);
1804
1242
  }
@@ -2186,7 +1624,7 @@ const getDefaultAuthClientConfig = async ({ auth_config_path, framework, clientP
2186
1624
  }
2187
1625
  return result;
2188
1626
  }
2189
- let imports = groupImportVariables();
1627
+ const imports = groupImportVariables();
2190
1628
  let importString = "";
2191
1629
  for (const import_ of imports) if (Array.isArray(import_.variables)) importString += `import { ${import_.variables.map((x) => `${x.asType ? "type " : ""}${x.name}${x.as ? ` as ${x.as}` : ""}`).join(", ")} } from "${import_.path}";\n`;
2192
1630
  else importString += `import ${import_.variables.asType ? "type " : ""}${import_.variables.name}${import_.variables.as ? ` as ${import_.variables.as}` : ""} from "${import_.path}";\n`;
@@ -2316,8 +1754,8 @@ async function initAction(opts) {
2316
1754
  }
2317
1755
  if (shouldInstallBetterAuthDep) {
2318
1756
  if (packageManagerPreference === void 0) packageManagerPreference = await getPackageManager();
2319
- const s$1 = spinner({ indicator: "dots" });
2320
- s$1.start(`Updating Better Auth using ${chalk.bold(packageManagerPreference)}`);
1757
+ const s = spinner({ indicator: "dots" });
1758
+ s.start(`Updating Better Auth using ${chalk.bold(packageManagerPreference)}`);
2321
1759
  try {
2322
1760
  const start = Date.now();
2323
1761
  await installDependencies({
@@ -2325,9 +1763,9 @@ async function initAction(opts) {
2325
1763
  packageManager: packageManagerPreference,
2326
1764
  cwd
2327
1765
  });
2328
- s$1.stop(`Better Auth updated ${chalk.greenBright(`successfully`)}! ${chalk.gray(`(${formatMilliseconds(Date.now() - start)})`)}`);
1766
+ s.stop(`Better Auth updated ${chalk.greenBright(`successfully`)}! ${chalk.gray(`(${formatMilliseconds(Date.now() - start)})`)}`);
2329
1767
  } catch (error) {
2330
- s$1.stop(`Failed to update Better Auth:`);
1768
+ s.stop(`Failed to update Better Auth:`);
2331
1769
  log.error(error.message);
2332
1770
  process.exit(1);
2333
1771
  }
@@ -2343,26 +1781,26 @@ async function initAction(opts) {
2343
1781
  }
2344
1782
  appName = newAppName;
2345
1783
  } else appName = packageJson.name;
2346
- let possiblePaths$1 = [
1784
+ let possiblePaths = [
2347
1785
  "auth.ts",
2348
1786
  "auth.tsx",
2349
1787
  "auth.js",
2350
1788
  "auth.jsx"
2351
1789
  ];
2352
- possiblePaths$1 = [
2353
- ...possiblePaths$1,
2354
- ...possiblePaths$1.map((it) => `lib/server/${it}`),
2355
- ...possiblePaths$1.map((it) => `server/${it}`),
2356
- ...possiblePaths$1.map((it) => `lib/${it}`),
2357
- ...possiblePaths$1.map((it) => `utils/${it}`)
1790
+ possiblePaths = [
1791
+ ...possiblePaths,
1792
+ ...possiblePaths.map((it) => `lib/server/${it}`),
1793
+ ...possiblePaths.map((it) => `server/${it}`),
1794
+ ...possiblePaths.map((it) => `lib/${it}`),
1795
+ ...possiblePaths.map((it) => `utils/${it}`)
2358
1796
  ];
2359
- possiblePaths$1 = [
2360
- ...possiblePaths$1,
2361
- ...possiblePaths$1.map((it) => `src/${it}`),
2362
- ...possiblePaths$1.map((it) => `app/${it}`)
1797
+ possiblePaths = [
1798
+ ...possiblePaths,
1799
+ ...possiblePaths.map((it) => `src/${it}`),
1800
+ ...possiblePaths.map((it) => `app/${it}`)
2363
1801
  ];
2364
1802
  if (options.config) config_path = path.join(cwd, options.config);
2365
- else for (const possiblePath of possiblePaths$1) if (existsSync(path.join(cwd, possiblePath))) {
1803
+ else for (const possiblePath of possiblePaths) if (existsSync(path.join(cwd, possiblePath))) {
2366
1804
  config_path = path.join(cwd, possiblePath);
2367
1805
  break;
2368
1806
  }
@@ -2509,9 +1947,9 @@ async function initAction(opts) {
2509
1947
  process.exit(0);
2510
1948
  }
2511
1949
  if (shouldInstallDeps) {
2512
- const s$1 = spinner({ indicator: "dots" });
1950
+ const s = spinner({ indicator: "dots" });
2513
1951
  if (packageManagerPreference === void 0) packageManagerPreference = await getPackageManager();
2514
- s$1.start(`Installing dependencies using ${chalk.bold(packageManagerPreference)}...`);
1952
+ s.start(`Installing dependencies using ${chalk.bold(packageManagerPreference)}...`);
2515
1953
  try {
2516
1954
  const start = Date.now();
2517
1955
  await installDependencies({
@@ -2519,9 +1957,9 @@ async function initAction(opts) {
2519
1957
  packageManager: packageManagerPreference,
2520
1958
  cwd
2521
1959
  });
2522
- s$1.stop(`Dependencies installed ${chalk.greenBright(`successfully`)} ${chalk.gray(`(${formatMilliseconds(Date.now() - start)})`)}`);
1960
+ s.stop(`Dependencies installed ${chalk.greenBright(`successfully`)} ${chalk.gray(`(${formatMilliseconds(Date.now() - start)})`)}`);
2523
1961
  } catch (error) {
2524
- s$1.stop(`Failed to install dependencies using ${packageManagerPreference}:`);
1962
+ s.stop(`Failed to install dependencies using ${packageManagerPreference}:`);
2525
1963
  log.error(error.message);
2526
1964
  process.exit(1);
2527
1965
  }
@@ -2584,13 +2022,13 @@ async function initAction(opts) {
2584
2022
  authClientConfigPath = path.join(cwd, "auth-client.ts");
2585
2023
  log.info(`Creating auth client config file: ${authClientConfigPath}`);
2586
2024
  try {
2587
- let contents = await getDefaultAuthClientConfig({
2025
+ const contents = await getDefaultAuthClientConfig({
2588
2026
  auth_config_path: ("./" + path.join(config_path.replace(cwd, ""))).replace(".//", "./"),
2589
2027
  clientPlugins: add_plugins.filter((x) => x.clientName).map((plugin) => {
2590
- let contents$1 = "";
2591
- if (plugin.id === "one-tap") contents$1 = `{ clientId: "MY_CLIENT_ID" }`;
2028
+ let contents = "";
2029
+ if (plugin.id === "one-tap") contents = `{ clientId: "MY_CLIENT_ID" }`;
2592
2030
  return {
2593
- contents: contents$1,
2031
+ contents,
2594
2032
  id: plugin.id,
2595
2033
  name: plugin.clientName,
2596
2034
  imports: [{
@@ -2643,7 +2081,7 @@ async function initAction(opts) {
2643
2081
  cancel(`✋ Operation cancelled.`);
2644
2082
  process.exit(0);
2645
2083
  }
2646
- let envs = [];
2084
+ const envs = [];
2647
2085
  if (isMissingSecret) envs.push("BETTER_AUTH_SECRET");
2648
2086
  if (isMissingUrl) envs.push("BETTER_AUTH_URL");
2649
2087
  if (shouldAdd === "yes") {
@@ -2727,7 +2165,7 @@ async function getPackageManager() {
2727
2165
  value: "npm",
2728
2166
  hint: "not recommended"
2729
2167
  });
2730
- let packageManager = await select({
2168
+ const packageManager = await select({
2731
2169
  message: "Choose a package manager",
2732
2170
  options: packageManagerOptions
2733
2171
  });
@@ -2794,14 +2232,14 @@ async function loginAction(opts) {
2794
2232
  baseURL: serverUrl,
2795
2233
  plugins: [deviceAuthorizationClient()]
2796
2234
  });
2797
- const spinner$1 = yoctoSpinner({ text: "Requesting device authorization..." });
2798
- spinner$1.start();
2235
+ const spinner = yoctoSpinner({ text: "Requesting device authorization..." });
2236
+ spinner.start();
2799
2237
  try {
2800
2238
  const { data, error } = await authClient.device.code({
2801
2239
  client_id: clientId,
2802
2240
  scope: "openid profile email"
2803
2241
  });
2804
- spinner$1.stop();
2242
+ spinner.stop();
2805
2243
  if (error || !data) {
2806
2244
  console.error(`Failed to request device authorization: ${error?.error_description || "Unknown error"}`);
2807
2245
  process.exit(1);
@@ -2828,14 +2266,14 @@ async function loginAction(opts) {
2828
2266
  console.log(chalk.blue("\nFor more information, visit: https://better-auth.com/docs/plugins/device-authorization"));
2829
2267
  }
2830
2268
  } catch (err) {
2831
- spinner$1.stop();
2269
+ spinner.stop();
2832
2270
  console.error(`Login failed: ${err instanceof Error ? err.message : "Unknown error"}`);
2833
2271
  process.exit(1);
2834
2272
  }
2835
2273
  }
2836
2274
  async function pollForToken(authClient, deviceCode, clientId, initialInterval) {
2837
2275
  let pollingInterval = initialInterval;
2838
- const spinner$1 = yoctoSpinner({
2276
+ const spinner = yoctoSpinner({
2839
2277
  text: "",
2840
2278
  color: "cyan"
2841
2279
  });
@@ -2843,8 +2281,8 @@ async function pollForToken(authClient, deviceCode, clientId, initialInterval) {
2843
2281
  return new Promise((resolve, reject) => {
2844
2282
  const poll = async () => {
2845
2283
  dots = (dots + 1) % 4;
2846
- spinner$1.text = chalk.gray(`Polling for authorization${".".repeat(dots)}${" ".repeat(3 - dots)}`);
2847
- if (!spinner$1.isSpinning) spinner$1.start();
2284
+ spinner.text = chalk.gray(`Polling for authorization${".".repeat(dots)}${" ".repeat(3 - dots)}`);
2285
+ if (!spinner.isSpinning) spinner.start();
2848
2286
  try {
2849
2287
  const { data, error } = await authClient.device.token({
2850
2288
  grant_type: "urn:ietf:params:oauth:grant-type:device_code",
@@ -2853,32 +2291,32 @@ async function pollForToken(authClient, deviceCode, clientId, initialInterval) {
2853
2291
  fetchOptions: { headers: { "user-agent": `Better Auth CLI` } }
2854
2292
  });
2855
2293
  if (data?.access_token) {
2856
- spinner$1.stop();
2294
+ spinner.stop();
2857
2295
  resolve(data);
2858
2296
  return;
2859
2297
  } else if (error) switch (error.error) {
2860
2298
  case "authorization_pending": break;
2861
2299
  case "slow_down":
2862
2300
  pollingInterval += 5;
2863
- spinner$1.text = chalk.yellow(`Slowing down polling to ${pollingInterval}s`);
2301
+ spinner.text = chalk.yellow(`Slowing down polling to ${pollingInterval}s`);
2864
2302
  break;
2865
2303
  case "access_denied":
2866
- spinner$1.stop();
2304
+ spinner.stop();
2867
2305
  console.error("Access was denied by the user");
2868
2306
  process.exit(1);
2869
2307
  break;
2870
2308
  case "expired_token":
2871
- spinner$1.stop();
2309
+ spinner.stop();
2872
2310
  console.error("The device code has expired. Please try again.");
2873
2311
  process.exit(1);
2874
2312
  break;
2875
2313
  default:
2876
- spinner$1.stop();
2314
+ spinner.stop();
2877
2315
  console.error(`Error: ${error.error_description}`);
2878
2316
  process.exit(1);
2879
2317
  }
2880
2318
  } catch (err) {
2881
- spinner$1.stop();
2319
+ spinner.stop();
2882
2320
  console.error(`Network error: ${err instanceof Error ? err.message : "Unknown error"}`);
2883
2321
  process.exit(1);
2884
2322
  }
@@ -2913,52 +2351,50 @@ const login = new Command("login").description("Demo: Test device authorization
2913
2351
 
2914
2352
  //#endregion
2915
2353
  //#region src/commands/mcp.ts
2354
+ const REMOTE_MCP_URL = "https://mcp.inkeep.com/better-auth/mcp";
2916
2355
  async function mcpAction(options) {
2917
- const mcpUrl = "https://mcp.chonkie.ai/better-auth/better-auth-builder/mcp";
2918
- const mcpName = "Better Auth";
2919
- if (options.cursor) await handleCursorAction(mcpUrl, mcpName);
2920
- else if (options.claudeCode) handleClaudeCodeAction(mcpUrl);
2921
- else if (options.openCode) handleOpenCodeAction(mcpUrl);
2922
- else if (options.manual) handleManualAction(mcpUrl, mcpName);
2923
- else showAllOptions(mcpUrl, mcpName);
2356
+ if (options.cursor) await handleCursorAction();
2357
+ else if (options.claudeCode) handleClaudeCodeAction();
2358
+ else if (options.openCode) handleOpenCodeAction();
2359
+ else if (options.manual) handleManualAction();
2360
+ else showAllOptions();
2924
2361
  }
2925
- async function handleCursorAction(mcpUrl, mcpName) {
2926
- const mcpConfig = { url: mcpUrl };
2927
- const encodedConfig = base64.encode(new TextEncoder().encode(JSON.stringify(mcpConfig)));
2928
- const deeplinkUrl = `cursor://anysphere.cursor-deeplink/mcp/install?name=${encodeURIComponent(mcpName)}&config=${encodedConfig}`;
2362
+ async function handleCursorAction() {
2929
2363
  console.log(chalk.bold.blue("🚀 Adding Better Auth MCP to Cursor..."));
2364
+ const platform = os$1.platform();
2365
+ let openCommand;
2366
+ switch (platform) {
2367
+ case "darwin":
2368
+ openCommand = "open";
2369
+ break;
2370
+ case "win32":
2371
+ openCommand = "start";
2372
+ break;
2373
+ case "linux":
2374
+ openCommand = "xdg-open";
2375
+ break;
2376
+ default: throw new Error(`Unsupported platform: ${platform}`);
2377
+ }
2378
+ const remoteConfig = { url: REMOTE_MCP_URL };
2379
+ const encodedRemote = base64.encode(new TextEncoder().encode(JSON.stringify(remoteConfig)));
2380
+ const remoteDeeplink = `cursor://anysphere.cursor-deeplink/mcp/install?name=${encodeURIComponent("better-auth")}&config=${encodedRemote}`;
2930
2381
  try {
2931
- const platform = os$1.platform();
2932
- let command;
2933
- switch (platform) {
2934
- case "darwin":
2935
- command = `open "${deeplinkUrl}"`;
2936
- break;
2937
- case "win32":
2938
- command = `start "" "${deeplinkUrl}"`;
2939
- break;
2940
- case "linux":
2941
- command = `xdg-open "${deeplinkUrl}"`;
2942
- break;
2943
- default: throw new Error(`Unsupported platform: ${platform}`);
2944
- }
2945
- execSync(command, { stdio: "inherit" });
2946
- console.log(chalk.green("\n✓ Cursor MCP installed successfully!"));
2382
+ execSync(platform === "win32" ? `start "" "${remoteDeeplink}"` : `${openCommand} "${remoteDeeplink}"`, { stdio: "inherit" });
2383
+ console.log(chalk.green("\n✓ Better Auth MCP server installed!"));
2947
2384
  } catch {
2948
- console.log(chalk.yellow("\n⚠ Could not automatically open Cursor. Please copy the deeplink URL above and open it manually."));
2949
- console.log(chalk.gray("\nYou can also manually add this configuration to your Cursor MCP settings:"));
2950
- console.log(chalk.gray(JSON.stringify(mcpConfig, null, 2)));
2385
+ console.log(chalk.yellow("\n⚠ Could not automatically open Cursor for MCP installation."));
2951
2386
  }
2952
2387
  console.log(chalk.bold.white("\n✨ Next Steps:"));
2953
2388
  console.log(chalk.gray("• The MCP server will be added to your Cursor configuration"));
2954
2389
  console.log(chalk.gray("• You can now use Better Auth features directly in Cursor"));
2390
+ console.log(chalk.gray("• Try: \"Set up Better Auth with Google login\" or \"Help me debug my auth\""));
2955
2391
  }
2956
- function handleClaudeCodeAction(mcpUrl) {
2392
+ function handleClaudeCodeAction() {
2957
2393
  console.log(chalk.bold.blue("🤖 Adding Better Auth MCP to Claude Code..."));
2958
- const command = `claude mcp add --transport http better-auth ${mcpUrl}`;
2394
+ const command = `claude mcp add --transport http better-auth ${REMOTE_MCP_URL}`;
2959
2395
  try {
2960
2396
  execSync(command, { stdio: "inherit" });
2961
- console.log(chalk.green("\n✓ Claude Code MCP installed successfully!"));
2397
+ console.log(chalk.green("\n✓ Claude Code MCP configured!"));
2962
2398
  } catch {
2963
2399
  console.log(chalk.yellow("\n⚠ Could not automatically add to Claude Code. Please run this command manually:"));
2964
2400
  console.log(chalk.cyan(command));
@@ -2967,13 +2403,13 @@ function handleClaudeCodeAction(mcpUrl) {
2967
2403
  console.log(chalk.gray("• The MCP server will be added to your Claude Code configuration"));
2968
2404
  console.log(chalk.gray("• You can now use Better Auth features directly in Claude Code"));
2969
2405
  }
2970
- function handleOpenCodeAction(mcpUrl) {
2406
+ function handleOpenCodeAction() {
2971
2407
  console.log(chalk.bold.blue("🔧 Adding Better Auth MCP to Open Code..."));
2972
2408
  const openCodeConfig = {
2973
2409
  $schema: "https://opencode.ai/config.json",
2974
- mcp: { "Better Auth": {
2410
+ mcp: { "better-auth": {
2975
2411
  type: "remote",
2976
- url: mcpUrl,
2412
+ url: REMOTE_MCP_URL,
2977
2413
  enabled: true
2978
2414
  } }
2979
2415
  };
@@ -2994,7 +2430,7 @@ function handleOpenCodeAction(mcpUrl) {
2994
2430
  };
2995
2431
  fs$2.writeFileSync(configPath, JSON.stringify(mergedConfig, null, 2));
2996
2432
  console.log(chalk.green(`\n✓ Open Code configuration written to ${configPath}`));
2997
- console.log(chalk.green("✓ Better Auth MCP added successfully!"));
2433
+ console.log(chalk.green("✓ Better Auth MCP server added successfully!"));
2998
2434
  } catch {
2999
2435
  console.log(chalk.yellow("\n⚠ Could not automatically write opencode.json. Please add this configuration manually:"));
3000
2436
  console.log(chalk.cyan(JSON.stringify(openCodeConfig, null, 2)));
@@ -3003,9 +2439,9 @@ function handleOpenCodeAction(mcpUrl) {
3003
2439
  console.log(chalk.gray("• Restart Open Code to load the new MCP server"));
3004
2440
  console.log(chalk.gray("• You can now use Better Auth features directly in Open Code"));
3005
2441
  }
3006
- function handleManualAction(mcpUrl, mcpName) {
3007
- console.log(chalk.bold.blue("📝 Adding Better Auth MCP Configuration..."));
3008
- const manualConfig = { [mcpName]: { url: mcpUrl } };
2442
+ function handleManualAction() {
2443
+ console.log(chalk.bold.blue("📝 Better Auth MCP Configuration..."));
2444
+ const manualConfig = { "better-auth": { url: REMOTE_MCP_URL } };
3009
2445
  const configPath = path$1.join(process.cwd(), "mcp.json");
3010
2446
  try {
3011
2447
  let existingConfig = {};
@@ -3019,7 +2455,7 @@ function handleManualAction(mcpUrl, mcpName) {
3019
2455
  };
3020
2456
  fs$2.writeFileSync(configPath, JSON.stringify(mergedConfig, null, 2));
3021
2457
  console.log(chalk.green(`\n✓ MCP configuration written to ${configPath}`));
3022
- console.log(chalk.green("✓ Better Auth MCP added successfully!"));
2458
+ console.log(chalk.green("✓ Better Auth MCP server added successfully!"));
3023
2459
  } catch {
3024
2460
  console.log(chalk.yellow("\n⚠ Could not automatically write mcp.json. Please add this configuration manually:"));
3025
2461
  console.log(chalk.cyan(JSON.stringify(manualConfig, null, 2)));
@@ -3028,16 +2464,19 @@ function handleManualAction(mcpUrl, mcpName) {
3028
2464
  console.log(chalk.gray("• Restart your MCP client to load the new server"));
3029
2465
  console.log(chalk.gray("• You can now use Better Auth features directly in your MCP client"));
3030
2466
  }
3031
- function showAllOptions(mcpUrl, mcpName) {
2467
+ function showAllOptions() {
3032
2468
  console.log(chalk.bold.blue("🔌 Better Auth MCP Server"));
3033
2469
  console.log(chalk.gray("Choose your MCP client to get started:"));
3034
2470
  console.log();
3035
- console.log(chalk.bold.white("Available Commands:"));
2471
+ console.log(chalk.bold.white("MCP Clients:"));
3036
2472
  console.log(chalk.cyan(" --cursor ") + chalk.gray("Add to Cursor"));
3037
2473
  console.log(chalk.cyan(" --claude-code ") + chalk.gray("Add to Claude Code"));
3038
2474
  console.log(chalk.cyan(" --open-code ") + chalk.gray("Add to Open Code"));
3039
2475
  console.log(chalk.cyan(" --manual ") + chalk.gray("Manual configuration"));
3040
2476
  console.log();
2477
+ console.log(chalk.bold.white("Server:"));
2478
+ console.log(chalk.gray(" • ") + chalk.white("better-auth") + chalk.gray(" - Search documentation, code examples, setup assistance"));
2479
+ console.log();
3041
2480
  }
3042
2481
  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);
3043
2482
 
@@ -3111,10 +2550,10 @@ async function migrateAction(opts) {
3111
2550
  } catch {}
3112
2551
  process.exit(1);
3113
2552
  }
3114
- const spinner$1 = yoctoSpinner({ text: "preparing migration..." }).start();
2553
+ const spinner = yoctoSpinner({ text: "preparing migration..." }).start();
3115
2554
  const { toBeAdded, toBeCreated, runMigrations } = await getMigrations(config);
3116
2555
  if (!toBeAdded.length && !toBeCreated.length) {
3117
- spinner$1.stop();
2556
+ spinner.stop();
3118
2557
  console.log("🚀 No migrations needed.");
3119
2558
  try {
3120
2559
  await (await createTelemetry(config)).publish({
@@ -3127,21 +2566,21 @@ async function migrateAction(opts) {
3127
2566
  } catch {}
3128
2567
  process.exit(0);
3129
2568
  }
3130
- spinner$1.stop();
2569
+ spinner.stop();
3131
2570
  console.log(`🔑 The migration will affect the following:`);
3132
2571
  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."));
3133
2572
  if (options.y) {
3134
2573
  console.warn("WARNING: --y is deprecated. Consider -y or --yes");
3135
2574
  options.yes = true;
3136
2575
  }
3137
- let migrate$1 = options.yes;
3138
- if (!migrate$1) migrate$1 = (await prompts({
2576
+ let migrate = options.yes;
2577
+ if (!migrate) migrate = (await prompts({
3139
2578
  type: "confirm",
3140
2579
  name: "migrate",
3141
2580
  message: "Are you sure you want to run these migrations?",
3142
2581
  initial: false
3143
2582
  })).migrate;
3144
- if (!migrate$1) {
2583
+ if (!migrate) {
3145
2584
  console.log("Migration cancelled.");
3146
2585
  try {
3147
2586
  await (await createTelemetry(config)).publish({
@@ -3154,9 +2593,9 @@ async function migrateAction(opts) {
3154
2593
  } catch {}
3155
2594
  process.exit(0);
3156
2595
  }
3157
- spinner$1?.start("migrating...");
2596
+ spinner?.start("migrating...");
3158
2597
  await runMigrations();
3159
- spinner$1.stop();
2598
+ spinner.stop();
3160
2599
  console.log("🚀 migration was completed successfully!");
3161
2600
  try {
3162
2601
  await (await createTelemetry(config)).publish({
@@ -3190,4 +2629,5 @@ main().catch((error) => {
3190
2629
  });
3191
2630
 
3192
2631
  //#endregion
3193
- export { };
2632
+ export { };
2633
+ //# sourceMappingURL=index.mjs.map