@better-auth/cli 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/LICENSE.md +17 -0
  2. package/dist/index.mjs +610 -0
  3. package/package.json +39 -0
package/LICENSE.md ADDED
@@ -0,0 +1,17 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2024 - present, Bereket Engida
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
6
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
7
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
8
+ is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all copies or
11
+ substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/dist/index.mjs ADDED
@@ -0,0 +1,610 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Command as Command3 } from "commander";
5
+
6
+ // src/commands/migrate.ts
7
+ import { Command } from "commander";
8
+ import { z } from "zod";
9
+ import { existsSync } from "fs";
10
+ import path2 from "path";
11
+ import yoctoSpinner from "yocto-spinner";
12
+ import chalk from "chalk";
13
+ import prompts from "prompts";
14
+ import { logger as logger2 } from "better-auth";
15
+ import { getAdapter, getMigrations } from "better-auth/db";
16
+
17
+ // src/utils/get-config.ts
18
+ import { loadConfig } from "c12";
19
+ import { logger } from "better-auth";
20
+ import path from "path";
21
+ import babelPresetTypescript from "@babel/preset-typescript";
22
+ import babelPresetReact from "@babel/preset-react";
23
+ import fs from "fs";
24
+ import { BetterAuthError } from "better-auth";
25
+
26
+ // src/utils/add-svelte-kit-env-modules.ts
27
+ function addSvelteKitEnvModules(aliases) {
28
+ aliases["$env/dynamic/private"] = createDataUriModule(
29
+ createDynamicEnvModule()
30
+ );
31
+ aliases["$env/dynamic/public"] = createDataUriModule(
32
+ createDynamicEnvModule()
33
+ );
34
+ aliases["$env/static/private"] = createDataUriModule(
35
+ createStaticEnvModule(filterPrivateEnv("PUBLIC_", ""))
36
+ );
37
+ aliases["$env/static/public"] = createDataUriModule(
38
+ createStaticEnvModule(filterPublicEnv("PUBLIC_", ""))
39
+ );
40
+ }
41
+ function createDataUriModule(module) {
42
+ return `data:text/javascript;charset=utf-8,${encodeURIComponent(module)}`;
43
+ }
44
+ function createStaticEnvModule(env) {
45
+ const declarations = Object.keys(env).filter((k) => validIdentifier.test(k) && !reserved.has(k)).map((k) => `export const ${k} = ${JSON.stringify(env[k])};`);
46
+ return `
47
+ ${declarations.join("\n")}
48
+ // jiti dirty hack: .unknown
49
+ `;
50
+ }
51
+ function createDynamicEnvModule() {
52
+ return `
53
+ export const env = process.env;
54
+ // jiti dirty hack: .unknown
55
+ `;
56
+ }
57
+ function filterPrivateEnv(publicPrefix, privatePrefix) {
58
+ return Object.fromEntries(
59
+ Object.entries(process.env).filter(
60
+ ([k]) => k.startsWith(privatePrefix) && (publicPrefix === "" || !k.startsWith(publicPrefix))
61
+ )
62
+ );
63
+ }
64
+ function filterPublicEnv(publicPrefix, privatePrefix) {
65
+ return Object.fromEntries(
66
+ Object.entries(process.env).filter(
67
+ ([k]) => k.startsWith(publicPrefix) && (privatePrefix === "" || !k.startsWith(privatePrefix))
68
+ )
69
+ );
70
+ }
71
+ var validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
72
+ var reserved = /* @__PURE__ */ new Set([
73
+ "do",
74
+ "if",
75
+ "in",
76
+ "for",
77
+ "let",
78
+ "new",
79
+ "try",
80
+ "var",
81
+ "case",
82
+ "else",
83
+ "enum",
84
+ "eval",
85
+ "null",
86
+ "this",
87
+ "true",
88
+ "void",
89
+ "with",
90
+ "await",
91
+ "break",
92
+ "catch",
93
+ "class",
94
+ "const",
95
+ "false",
96
+ "super",
97
+ "throw",
98
+ "while",
99
+ "yield",
100
+ "delete",
101
+ "export",
102
+ "import",
103
+ "public",
104
+ "return",
105
+ "static",
106
+ "switch",
107
+ "typeof",
108
+ "default",
109
+ "extends",
110
+ "finally",
111
+ "package",
112
+ "private",
113
+ "continue",
114
+ "debugger",
115
+ "function",
116
+ "arguments",
117
+ "interface",
118
+ "protected",
119
+ "implements",
120
+ "instanceof"
121
+ ]);
122
+
123
+ // src/utils/get-config.ts
124
+ var possiblePaths = ["auth.ts", "auth.tsx"];
125
+ possiblePaths = [
126
+ ...possiblePaths,
127
+ ...possiblePaths.map((it) => `lib/server${it}`),
128
+ ...possiblePaths.map((it) => `lib/${it}`),
129
+ ...possiblePaths.map((it) => `utils/${it}`)
130
+ ];
131
+ possiblePaths = [
132
+ ...possiblePaths,
133
+ ...possiblePaths.map((it) => `src/${it}`),
134
+ ...possiblePaths.map((it) => `app/${it}`)
135
+ ];
136
+ function stripJsonComments(jsonString) {
137
+ return jsonString.replace(
138
+ /\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g,
139
+ (m, g) => g ? "" : m
140
+ );
141
+ }
142
+ function getPathAliases(cwd) {
143
+ const tsConfigPath = path.join(cwd, "tsconfig.json");
144
+ if (!fs.existsSync(tsConfigPath)) {
145
+ logger.warn("[#better-auth]: tsconfig.json not found.");
146
+ return null;
147
+ }
148
+ try {
149
+ const tsConfigContent = fs.readFileSync(tsConfigPath, "utf8");
150
+ const strippedTsConfigContent = stripJsonComments(tsConfigContent);
151
+ const tsConfig = JSON.parse(strippedTsConfigContent);
152
+ const { paths = {} } = tsConfig.compilerOptions || {};
153
+ const result = {};
154
+ const obj = Object.entries(paths);
155
+ for (const [alias, aliasPaths] of obj) {
156
+ for (const _ of aliasPaths) {
157
+ result[alias[0] || ""] = "../";
158
+ }
159
+ }
160
+ addSvelteKitEnvModules(result);
161
+ return result;
162
+ } catch (error) {
163
+ console.error(error);
164
+ throw new BetterAuthError("Error parsing tsconfig.json");
165
+ }
166
+ }
167
+ var jitiOptions = (cwd) => {
168
+ const alias = getPathAliases(cwd) || {};
169
+ return {
170
+ transformOptions: {
171
+ babel: {
172
+ presets: [
173
+ [
174
+ babelPresetTypescript,
175
+ {
176
+ isTSX: true,
177
+ allExtensions: true
178
+ }
179
+ ],
180
+ [babelPresetReact, { runtime: "automatic" }]
181
+ ]
182
+ }
183
+ },
184
+ extensions: [".ts", ".tsx", ".js", ".jsx"],
185
+ alias
186
+ };
187
+ };
188
+ async function getConfig({
189
+ cwd,
190
+ configPath
191
+ }) {
192
+ try {
193
+ let configFile = null;
194
+ if (configPath) {
195
+ const { config } = await loadConfig({
196
+ configFile: path.join(cwd, configPath),
197
+ dotenv: true,
198
+ jitiOptions: jitiOptions(cwd)
199
+ });
200
+ if (!config.auth && !config.default) {
201
+ logger.error(
202
+ "[#better-auth]: Couldn't read your auth config. Make sure to default export your auth instance or to export as a variable named auth."
203
+ );
204
+ process.exit(1);
205
+ }
206
+ configFile = config.auth?.options || config.default?.options || null;
207
+ }
208
+ if (!configFile) {
209
+ for (const possiblePath of possiblePaths) {
210
+ try {
211
+ const { config } = await loadConfig({
212
+ configFile: possiblePath,
213
+ jitiOptions: jitiOptions(cwd)
214
+ });
215
+ const hasConfig = Object.keys(config).length > 0;
216
+ if (hasConfig) {
217
+ configFile = config.auth?.options || config.default?.options || null;
218
+ if (!configFile) {
219
+ logger.error("[#better-auth]: Couldn't read your auth config.");
220
+ logger.break();
221
+ logger.info(
222
+ "[#better-auth]: Make sure to default export your auth instance or to export as a variable named auth."
223
+ );
224
+ process.exit(1);
225
+ }
226
+ break;
227
+ }
228
+ } catch (e) {
229
+ logger.error("[#better-auth]: Couldn't read your auth config.", e);
230
+ process.exit(1);
231
+ }
232
+ }
233
+ }
234
+ return configFile;
235
+ } catch (e) {
236
+ logger.error("Couldn't read your auth config.");
237
+ process.exit(1);
238
+ }
239
+ }
240
+
241
+ // src/commands/migrate.ts
242
+ var migrate = new Command("migrate").option(
243
+ "-c, --cwd <cwd>",
244
+ "the working directory. defaults to the current directory.",
245
+ process.cwd()
246
+ ).option(
247
+ "--config <config>",
248
+ "the path to the configuration file. defaults to the first configuration file found."
249
+ ).option("--y", "").action(async (opts) => {
250
+ const options = z.object({
251
+ cwd: z.string(),
252
+ config: z.string().optional()
253
+ }).parse(opts);
254
+ const cwd = path2.resolve(options.cwd);
255
+ if (!existsSync(cwd)) {
256
+ logger2.error(`The directory "${cwd}" does not exist.`);
257
+ process.exit(1);
258
+ }
259
+ const config = await getConfig({
260
+ cwd,
261
+ configPath: options.config
262
+ });
263
+ if (!config) {
264
+ logger2.error(
265
+ "No configuration file found. Add a `auth.ts` file to your project or pass the path to the configuration file using the `--config` flag."
266
+ );
267
+ return;
268
+ }
269
+ const db = await getAdapter(config, true);
270
+ if (!db) {
271
+ logger2.error(
272
+ "Invalid database configuration. Make sure you're not using adapters. Migrate command only works with built-in Kysely adapter."
273
+ );
274
+ process.exit(1);
275
+ }
276
+ if (db.id !== "kysely") {
277
+ logger2.error("Migrate command only works with built-in Kysely adapter.");
278
+ process.exit(1);
279
+ }
280
+ const spinner = yoctoSpinner({ text: "preparing migration..." }).start();
281
+ const { toBeAdded, toBeCreated, runMigrations } = await getMigrations(config);
282
+ if (!toBeAdded.length && !toBeCreated.length) {
283
+ spinner.stop();
284
+ logger2.success("\u{1F680} No migrations needed.");
285
+ process.exit(0);
286
+ }
287
+ spinner.stop();
288
+ logger2.info(`\u{1F511} The migration will affect the following:`);
289
+ for (const table of [...toBeCreated, ...toBeAdded]) {
290
+ console.log(
291
+ "->",
292
+ chalk.magenta(Object.keys(table.fields).join(", ")),
293
+ chalk.white("fields on"),
294
+ chalk.yellow(`${table.table}`),
295
+ chalk.white("table.")
296
+ );
297
+ }
298
+ const { migrate: migrate2 } = await prompts({
299
+ type: "confirm",
300
+ name: "migrate",
301
+ message: "Are you sure you want to run these migrations?",
302
+ initial: false
303
+ });
304
+ if (!migrate2) {
305
+ logger2.info("Migration cancelled.");
306
+ process.exit(0);
307
+ }
308
+ spinner?.start("migrating...");
309
+ await runMigrations();
310
+ spinner.stop();
311
+ logger2.success("\u{1F680} migration was completed successfully!");
312
+ process.exit(0);
313
+ });
314
+
315
+ // src/commands/generate.ts
316
+ import { Command as Command2 } from "commander";
317
+ import { z as z2 } from "zod";
318
+ import { existsSync as existsSync4 } from "fs";
319
+ import path4 from "path";
320
+ import { logger as logger4 } from "better-auth";
321
+ import yoctoSpinner2 from "yocto-spinner";
322
+ import prompts2 from "prompts";
323
+ import fs3 from "fs/promises";
324
+ import chalk2 from "chalk";
325
+ import { getAdapter as getAdapter2 } from "better-auth/db";
326
+
327
+ // src/generators/index.ts
328
+ import { logger as logger3 } from "better-auth";
329
+
330
+ // src/generators/drizzle.ts
331
+ import { getAuthTables } from "better-auth/db";
332
+ import { existsSync as existsSync2 } from "fs";
333
+ var generateDrizzleSchema = async ({
334
+ options,
335
+ file,
336
+ adapter
337
+ }) => {
338
+ const tables = getAuthTables(options);
339
+ const filePath = file || "./auth-schema.ts";
340
+ const databaseType = adapter.options?.provider;
341
+ const timestampAndBoolean = databaseType !== "sqlite" ? "timestamp, boolean" : "";
342
+ const int = databaseType === "mysql" ? "int" : "integer";
343
+ let code = `import { ${databaseType}Table, text, ${int}, ${timestampAndBoolean} } from "drizzle-orm/${databaseType}-core";
344
+ `;
345
+ const fileExist = existsSync2(filePath);
346
+ for (const table in tables) {
347
+ let getType2 = function(name, type) {
348
+ if (type === "string") {
349
+ return `text('${name}')`;
350
+ }
351
+ if (type === "number") {
352
+ return `${int}('${name}')`;
353
+ }
354
+ if (type === "boolean") {
355
+ if (databaseType === "sqlite") {
356
+ return `integer('${name}', {
357
+ mode: "boolean"
358
+ })`;
359
+ }
360
+ return `boolean('${name}')`;
361
+ }
362
+ if (type === "date") {
363
+ if (databaseType === "sqlite") {
364
+ return `integer('${name}', {
365
+ mode: "timestamp"
366
+ })`;
367
+ }
368
+ return `timestamp('${name}')`;
369
+ }
370
+ };
371
+ var getType = getType2;
372
+ const tableName = tables[table].tableName;
373
+ const fields = tables[table].fields;
374
+ const schema = `export const ${table} = ${databaseType}Table("${tableName}", {
375
+ id: text("id").primaryKey(),
376
+ ${Object.keys(fields).map((field) => {
377
+ const attr = fields[field];
378
+ return `${field}: ${getType2(field, attr.type)}${attr.required ? ".notNull()" : ""}${attr.unique ? ".unique()" : ""}${attr.references ? `.references(()=> ${attr.references.model}.${attr.references.field})` : ""}`;
379
+ }).join(",\n ")}
380
+ });`;
381
+ code += `
382
+ ${schema}
383
+ `;
384
+ }
385
+ return {
386
+ code,
387
+ fileName: filePath,
388
+ overwrite: fileExist
389
+ };
390
+ };
391
+
392
+ // src/generators/prisma.ts
393
+ import { getAuthTables as getAuthTables2 } from "better-auth/db";
394
+ import { produceSchema } from "@mrleebo/prisma-ast";
395
+ import { existsSync as existsSync3 } from "fs";
396
+ import path3 from "path";
397
+ import fs2 from "fs/promises";
398
+ import { capitalizeFirstLetter } from "better-auth";
399
+ var generatePrismaSchema = async ({
400
+ adapter,
401
+ options,
402
+ file
403
+ }) => {
404
+ const provider = adapter.options?.provider || "pg";
405
+ const tables = getAuthTables2(options);
406
+ const filePath = file || "./prisma/schema.prisma";
407
+ const schemaPrismaExist = existsSync3(path3.join(process.cwd(), filePath));
408
+ let schemaPrisma = "";
409
+ if (schemaPrismaExist) {
410
+ schemaPrisma = await fs2.readFile(
411
+ path3.join(process.cwd(), filePath),
412
+ "utf-8"
413
+ );
414
+ } else {
415
+ schemaPrisma = getNewPrisma(provider);
416
+ }
417
+ const schema = produceSchema(schemaPrisma, (builder) => {
418
+ for (const table in tables) {
419
+ let getType2 = function(type, isOptional) {
420
+ if (type === "string") {
421
+ return isOptional ? "String?" : "String";
422
+ }
423
+ if (type === "number") {
424
+ return isOptional ? "Int?" : "Int";
425
+ }
426
+ if (type === "boolean") {
427
+ return isOptional ? "Boolean?" : "Boolean";
428
+ }
429
+ if (type === "date") {
430
+ return isOptional ? "DateTime?" : "DateTime";
431
+ }
432
+ };
433
+ var getType = getType2;
434
+ const fields = tables[table]?.fields;
435
+ const originalTable = tables[table]?.tableName;
436
+ const tableName = capitalizeFirstLetter(originalTable || "");
437
+ const prismaModel = builder.findByType("model", {
438
+ name: tableName
439
+ });
440
+ !prismaModel && builder.model(tableName).field("id", "String").attribute("id");
441
+ for (const field in fields) {
442
+ const attr = fields[field];
443
+ if (prismaModel) {
444
+ const isAlreadyExist = builder.findByType("field", {
445
+ name: field,
446
+ within: prismaModel.properties
447
+ });
448
+ if (isAlreadyExist) {
449
+ continue;
450
+ }
451
+ }
452
+ builder.model(tableName).field(field, getType2(attr.type, !attr?.required));
453
+ if (attr.unique) {
454
+ builder.model(tableName).blockAttribute(`unique([${field}])`);
455
+ }
456
+ if (attr.references) {
457
+ builder.model(tableName).field(
458
+ `${attr.references.model.toLowerCase()}`,
459
+ capitalizeFirstLetter(attr.references.model)
460
+ ).attribute(
461
+ `relation(fields: [${field}], references: [${attr.references.field}], onDelete: Cascade)`
462
+ );
463
+ }
464
+ }
465
+ const hasAttribute = builder.findByType("attribute", {
466
+ name: "map",
467
+ within: prismaModel?.properties
468
+ });
469
+ if (originalTable !== tableName && !hasAttribute) {
470
+ builder.model(tableName).blockAttribute("map", originalTable);
471
+ }
472
+ }
473
+ });
474
+ return {
475
+ code: schema.trim() === schemaPrisma.trim() ? "" : schema,
476
+ fileName: filePath
477
+ };
478
+ };
479
+ var getNewPrisma = (provider) => `generator client {
480
+ provider = "prisma-client-js"
481
+ }
482
+
483
+ datasource db {
484
+ provider = "${provider}"
485
+ url = ${provider === "sqlite" ? `"file:./dev.db"` : `env("DATABASE_URL")`}
486
+ }`;
487
+
488
+ // src/generators/index.ts
489
+ var adapters = {
490
+ prisma: generatePrismaSchema,
491
+ drizzle: generateDrizzleSchema
492
+ };
493
+ var getGenerator = (opts) => {
494
+ const adapter = opts.adapter;
495
+ const generator = adapter.id in adapters ? adapters[adapter.id] : null;
496
+ if (!generator) {
497
+ logger3.error(`${adapter.id} is not supported.`);
498
+ process.exit(1);
499
+ }
500
+ return generator(opts);
501
+ };
502
+
503
+ // src/commands/generate.ts
504
+ var generate = new Command2("generate").option(
505
+ "-c, --cwd <cwd>",
506
+ "the working directory. defaults to the current directory.",
507
+ process.cwd()
508
+ ).option(
509
+ "--config <config>",
510
+ "the path to the configuration file. defaults to the first configuration file found."
511
+ ).option("--output <output>", "the file to output to the generated schema").option("--y", "").action(async (opts) => {
512
+ const options = z2.object({
513
+ cwd: z2.string(),
514
+ config: z2.string().optional(),
515
+ output: z2.string().optional()
516
+ }).parse(opts);
517
+ const cwd = path4.resolve(options.cwd);
518
+ if (!existsSync4(cwd)) {
519
+ logger4.error(`The directory "${cwd}" does not exist.`);
520
+ process.exit(1);
521
+ }
522
+ const config = await getConfig({
523
+ cwd,
524
+ configPath: options.config
525
+ });
526
+ if (!config) {
527
+ logger4.error(
528
+ "No configuration file found. Add a `auth.ts` file to your project or pass the path to the configuration file using the `--config` flag."
529
+ );
530
+ return;
531
+ }
532
+ const spinner = yoctoSpinner2({ text: "preparing schema..." }).start();
533
+ const adapter = await getAdapter2(config, true).catch((e) => {
534
+ logger4.error(e.message);
535
+ process.exit(1);
536
+ });
537
+ const schema = await getGenerator({
538
+ adapter,
539
+ file: options.output,
540
+ options: config
541
+ });
542
+ spinner.stop();
543
+ if (!schema.code) {
544
+ logger4.success("Your schema is already up to date.");
545
+ process.exit(0);
546
+ }
547
+ if (schema.append || schema.overwrite) {
548
+ const { confirm: confirm2 } = await prompts2({
549
+ type: "confirm",
550
+ name: "confirm",
551
+ message: `The file ${schema.fileName} already exists. Do you want to ${chalk2.yellow(
552
+ `${schema.overwrite ? "overwrite" : "append"}`
553
+ )} the schema to the file?`
554
+ });
555
+ if (confirm2) {
556
+ const exist = existsSync4(path4.join(cwd, schema.fileName));
557
+ if (!exist) {
558
+ await fs3.mkdir(path4.dirname(path4.join(cwd, schema.fileName)), {
559
+ recursive: true
560
+ });
561
+ }
562
+ if (schema.overwrite) {
563
+ await fs3.writeFile(path4.join(cwd, schema.fileName), schema.code);
564
+ } else {
565
+ await fs3.appendFile(path4.join(cwd, schema.fileName), schema.code);
566
+ }
567
+ logger4.success(`\u{1F680} schema was appended successfully!`);
568
+ process.exit(0);
569
+ } else {
570
+ logger4.error("Schema generation aborted.");
571
+ process.exit(1);
572
+ }
573
+ }
574
+ const { confirm } = await prompts2({
575
+ type: "confirm",
576
+ name: "confirm",
577
+ message: `Do you want to generate the schema to ${chalk2.yellow(
578
+ schema.fileName
579
+ )}?`
580
+ });
581
+ if (!confirm) {
582
+ logger4.error("Schema generation aborted.");
583
+ process.exit(1);
584
+ }
585
+ if (!options.output) {
586
+ const dirExist = existsSync4(
587
+ path4.dirname(path4.join(cwd, schema.fileName))
588
+ );
589
+ if (!dirExist) {
590
+ await fs3.mkdir(path4.dirname(path4.join(cwd, schema.fileName)), {
591
+ recursive: true
592
+ });
593
+ }
594
+ }
595
+ await fs3.writeFile(
596
+ options.output || path4.join(cwd, schema.fileName),
597
+ schema.code
598
+ );
599
+ logger4.success(`\u{1F680} schema was generated successfully!`);
600
+ process.exit(0);
601
+ });
602
+
603
+ // src/index.ts
604
+ import "dotenv/config";
605
+ async function main() {
606
+ const program = new Command3();
607
+ program.name("better-auth").addCommand(migrate).addCommand(generate).version("0.0.1").description("Better Auth CLI");
608
+ program.parse();
609
+ }
610
+ main();
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@better-auth/cli",
3
+ "version": "0.0.1",
4
+ "description": "The CLI for BetterAuth",
5
+ "module": "dist/index.mjs",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/better-auth/better-auth",
9
+ "directory": "packages/cli"
10
+ },
11
+ "main": "./dist/index.mjs",
12
+ "bin": "./dist/index.mjs",
13
+ "devDependencies": {
14
+ "tsup": "^8.2.4",
15
+ "typescript": "^5.6.3"
16
+ },
17
+ "dependencies": {
18
+ "@babel/preset-react": "^7.24.7",
19
+ "@babel/preset-typescript": "^7.24.7",
20
+ "@mrleebo/prisma-ast": "^0.12.0",
21
+ "@types/prompts": "^2.4.9",
22
+ "c12": "^2.0.1",
23
+ "chalk": "^5.3.0",
24
+ "commander": "^12.1.0",
25
+ "dotenv": "^16.4.5",
26
+ "prompts": "^2.4.2",
27
+ "tinyexec": "^0.3.0",
28
+ "yocto-spinner": "^0.1.1",
29
+ "zod": "^3.23.8",
30
+ "better-auth": "0.4.9-beta.7"
31
+ },
32
+ "files": [
33
+ "dist"
34
+ ],
35
+ "scripts": {
36
+ "dev": "tsup --watch --sourcemap",
37
+ "build": "tsup --clean"
38
+ }
39
+ }