@betterstart/cli 0.1.26 → 0.1.27
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/cli.js +83 -105
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7640,9 +7640,6 @@ function detectPackageManager(cwd) {
|
|
|
7640
7640
|
}
|
|
7641
7641
|
return "npm";
|
|
7642
7642
|
}
|
|
7643
|
-
function installCommand(pm) {
|
|
7644
|
-
return pm === "yarn" ? "yarn" : `${pm} install`;
|
|
7645
|
-
}
|
|
7646
7643
|
function runCommand(pm, script) {
|
|
7647
7644
|
switch (pm) {
|
|
7648
7645
|
case "pnpm":
|
|
@@ -11678,7 +11675,6 @@ var CORE_DEPS = [
|
|
|
11678
11675
|
"input-otp",
|
|
11679
11676
|
"react-resizable-panels",
|
|
11680
11677
|
"recharts",
|
|
11681
|
-
"shadcn",
|
|
11682
11678
|
"tw-animate-css",
|
|
11683
11679
|
"usehooks-ts",
|
|
11684
11680
|
"vaul"
|
|
@@ -12021,6 +12017,7 @@ import { authClient } from '@cms/auth/client'
|
|
|
12021
12017
|
import { Button } from '@cms/components/ui/button'
|
|
12022
12018
|
import { Input } from '@cms/components/ui/input'
|
|
12023
12019
|
import { Label } from '@cms/components/ui/label'
|
|
12020
|
+
import { LoaderCircle } from 'lucide-react'
|
|
12024
12021
|
import { useRouter } from 'next/navigation'
|
|
12025
12022
|
import * as React from 'react'
|
|
12026
12023
|
|
|
@@ -12093,6 +12090,7 @@ export function LoginForm() {
|
|
|
12093
12090
|
</div>
|
|
12094
12091
|
|
|
12095
12092
|
<Button type="submit" className="w-full" size="lg" disabled={isLoading}>
|
|
12093
|
+
{isLoading && <LoaderCircle className="animate-spin" />}
|
|
12096
12094
|
{isLoading ? 'Signing in...' : 'Sign In'}
|
|
12097
12095
|
</Button>
|
|
12098
12096
|
</form>
|
|
@@ -13513,9 +13511,32 @@ const auth = betterAuth({
|
|
|
13513
13511
|
const EMAIL = process.env.SEED_EMAIL!
|
|
13514
13512
|
const PASSWORD = process.env.SEED_PASSWORD!
|
|
13515
13513
|
const NAME = process.env.SEED_NAME || 'Admin'
|
|
13514
|
+
const OVERWRITE = process.env.SEED_OVERWRITE === 'true'
|
|
13516
13515
|
|
|
13517
13516
|
async function main() {
|
|
13518
|
-
|
|
13517
|
+
// Check if user already exists
|
|
13518
|
+
const existing = await db
|
|
13519
|
+
.select({ id: schema.user.id, name: schema.user.name })
|
|
13520
|
+
.from(schema.user)
|
|
13521
|
+
.where(eq(schema.user.email, EMAIL))
|
|
13522
|
+
.then((rows: { id: string; name: string }[]) => rows[0])
|
|
13523
|
+
|
|
13524
|
+
if (existing && !OVERWRITE) {
|
|
13525
|
+
// Exit code 2 signals "user exists" to the CLI
|
|
13526
|
+
console.log(\`EXISTING_USER:\${existing.name}\`)
|
|
13527
|
+
process.exit(2)
|
|
13528
|
+
}
|
|
13529
|
+
|
|
13530
|
+
if (existing && OVERWRITE) {
|
|
13531
|
+
console.log('\\n Replacing existing admin user...')
|
|
13532
|
+
// Remove existing account + session rows first (foreign key refs)
|
|
13533
|
+
await db.delete(schema.session).where(eq(schema.session.userId, existing.id))
|
|
13534
|
+
await db.delete(schema.account).where(eq(schema.account.userId, existing.id))
|
|
13535
|
+
await db.delete(schema.user).where(eq(schema.user.id, existing.id))
|
|
13536
|
+
} else {
|
|
13537
|
+
console.log('\\n Creating admin user...')
|
|
13538
|
+
}
|
|
13539
|
+
|
|
13519
13540
|
console.log(\` Email: \${EMAIL}\\n\`)
|
|
13520
13541
|
|
|
13521
13542
|
const result = await auth.api.signUpEmail({
|
|
@@ -13532,7 +13553,7 @@ async function main() {
|
|
|
13532
13553
|
.set({ role: 'admin' })
|
|
13533
13554
|
.where(eq(schema.user.id, result.user.id))
|
|
13534
13555
|
|
|
13535
|
-
console.log(\` Admin user created: \${EMAIL}\`)
|
|
13556
|
+
console.log(\` Admin user \${existing ? 'replaced' : 'created'}: \${EMAIL}\`)
|
|
13536
13557
|
console.log(' Role: admin\\n')
|
|
13537
13558
|
process.exit(0)
|
|
13538
13559
|
}
|
|
@@ -13590,22 +13611,52 @@ var seedCommand = new Command2("seed").description("Create the initial admin use
|
|
|
13590
13611
|
fs31.mkdirSync(scriptsDir, { recursive: true });
|
|
13591
13612
|
}
|
|
13592
13613
|
fs31.writeFileSync(seedPath, buildSeedScript(), "utf-8");
|
|
13593
|
-
const
|
|
13594
|
-
|
|
13595
|
-
|
|
13596
|
-
|
|
13597
|
-
const tsxBin = path36.join(cwd, "node_modules", ".bin", "tsx");
|
|
13598
|
-
execFileSync5(tsxBin, [seedPath], {
|
|
13614
|
+
const { execFile } = await import("child_process");
|
|
13615
|
+
const tsxBin = path36.join(cwd, "node_modules", ".bin", "tsx");
|
|
13616
|
+
const runSeed2 = (overwrite) => new Promise((resolve, reject) => {
|
|
13617
|
+
execFile(tsxBin, [seedPath], {
|
|
13599
13618
|
cwd,
|
|
13600
|
-
stdio: "pipe",
|
|
13601
13619
|
env: {
|
|
13602
13620
|
...process.env,
|
|
13603
13621
|
SEED_EMAIL: email,
|
|
13604
13622
|
SEED_PASSWORD: password3,
|
|
13605
|
-
SEED_NAME: name || "Admin"
|
|
13623
|
+
SEED_NAME: name || "Admin",
|
|
13624
|
+
...overwrite ? { SEED_OVERWRITE: "true" } : {}
|
|
13625
|
+
}
|
|
13626
|
+
}, (err, stdout, stderr) => {
|
|
13627
|
+
if (err && "code" in err && err.code === 2) {
|
|
13628
|
+
resolve({ code: 2, stdout });
|
|
13629
|
+
} else if (err) {
|
|
13630
|
+
reject(new Error(stderr || err.message));
|
|
13631
|
+
} else {
|
|
13632
|
+
resolve({ code: 0, stdout });
|
|
13606
13633
|
}
|
|
13607
13634
|
});
|
|
13608
|
-
|
|
13635
|
+
});
|
|
13636
|
+
const spinner4 = clack.spinner();
|
|
13637
|
+
spinner4.start("Creating admin user...");
|
|
13638
|
+
try {
|
|
13639
|
+
const result = await runSeed2(false);
|
|
13640
|
+
if (result.code === 2) {
|
|
13641
|
+
const existingName = result.stdout.split("\n").find((l) => l.startsWith("EXISTING_USER:"))?.replace("EXISTING_USER:", "")?.trim() || "unknown";
|
|
13642
|
+
spinner4.stop(`Account already exists for ${email}`);
|
|
13643
|
+
const overwrite = await clack.confirm({
|
|
13644
|
+
message: `An admin account (${existingName}) already exists with this email. Replace it?`
|
|
13645
|
+
});
|
|
13646
|
+
if (clack.isCancel(overwrite) || !overwrite) {
|
|
13647
|
+
clack.cancel("Seed cancelled.");
|
|
13648
|
+
try {
|
|
13649
|
+
fs31.unlinkSync(seedPath);
|
|
13650
|
+
} catch {
|
|
13651
|
+
}
|
|
13652
|
+
process.exit(0);
|
|
13653
|
+
}
|
|
13654
|
+
spinner4.start("Replacing admin user...");
|
|
13655
|
+
await runSeed2(true);
|
|
13656
|
+
spinner4.stop("Admin user replaced");
|
|
13657
|
+
} else {
|
|
13658
|
+
spinner4.stop("Admin user created");
|
|
13659
|
+
}
|
|
13609
13660
|
} catch (err) {
|
|
13610
13661
|
spinner4.stop("Failed to create admin user");
|
|
13611
13662
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -14481,44 +14532,6 @@ function findNextNonEmptyLine(lines, startIndex) {
|
|
|
14481
14532
|
}
|
|
14482
14533
|
return null;
|
|
14483
14534
|
}
|
|
14484
|
-
function cleanPackageJsonDeps(pkgPath, allDeps, allDevDeps) {
|
|
14485
|
-
if (!fs34.existsSync(pkgPath)) return { removed: [], removedDev: [] };
|
|
14486
|
-
const content = fs34.readFileSync(pkgPath, "utf-8");
|
|
14487
|
-
let pkg;
|
|
14488
|
-
try {
|
|
14489
|
-
pkg = JSON.parse(content);
|
|
14490
|
-
} catch {
|
|
14491
|
-
return { removed: [], removedDev: [] };
|
|
14492
|
-
}
|
|
14493
|
-
const deps = pkg.dependencies ?? {};
|
|
14494
|
-
const devDeps = pkg.devDependencies ?? {};
|
|
14495
|
-
const depNames = new Set(allDeps.map((d) => d.split("@").slice(0, d.startsWith("@") ? 2 : 1).join("@")));
|
|
14496
|
-
const devDepNames = new Set(
|
|
14497
|
-
allDevDeps.map((d) => d.split("@").slice(0, d.startsWith("@") ? 2 : 1).join("@"))
|
|
14498
|
-
);
|
|
14499
|
-
const removed = [];
|
|
14500
|
-
for (const name of Object.keys(deps)) {
|
|
14501
|
-
if (depNames.has(name)) {
|
|
14502
|
-
delete deps[name];
|
|
14503
|
-
removed.push(name);
|
|
14504
|
-
}
|
|
14505
|
-
}
|
|
14506
|
-
const removedDev = [];
|
|
14507
|
-
for (const name of Object.keys(devDeps)) {
|
|
14508
|
-
if (devDepNames.has(name)) {
|
|
14509
|
-
delete devDeps[name];
|
|
14510
|
-
removedDev.push(name);
|
|
14511
|
-
}
|
|
14512
|
-
}
|
|
14513
|
-
if (removed.length === 0 && removedDev.length === 0) {
|
|
14514
|
-
return { removed: [], removedDev: [] };
|
|
14515
|
-
}
|
|
14516
|
-
pkg.dependencies = deps;
|
|
14517
|
-
pkg.devDependencies = devDeps;
|
|
14518
|
-
fs34.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
14519
|
-
`, "utf-8");
|
|
14520
|
-
return { removed, removedDev };
|
|
14521
|
-
}
|
|
14522
14535
|
|
|
14523
14536
|
// src/commands/uninstall.ts
|
|
14524
14537
|
function findMainCss2(cwd) {
|
|
@@ -14637,32 +14650,6 @@ function buildUninstallPlan(cwd) {
|
|
|
14637
14650
|
});
|
|
14638
14651
|
}
|
|
14639
14652
|
}
|
|
14640
|
-
const pkgPath = path40.join(cwd, "package.json");
|
|
14641
|
-
if (fs35.existsSync(pkgPath)) {
|
|
14642
|
-
const allCoreDeps = [...CORE_DEPS, ...EMAIL_DEPS];
|
|
14643
|
-
const allDevDeps = [...DEV_DEPS, ...BIOME_DEV_DEPS];
|
|
14644
|
-
const coreNames = new Set(
|
|
14645
|
-
allCoreDeps.map((d) => d.split("@").slice(0, d.startsWith("@") ? 2 : 1).join("@"))
|
|
14646
|
-
);
|
|
14647
|
-
const devNames = new Set(
|
|
14648
|
-
allDevDeps.map((d) => d.split("@").slice(0, d.startsWith("@") ? 2 : 1).join("@"))
|
|
14649
|
-
);
|
|
14650
|
-
const pkgContent = JSON.parse(fs35.readFileSync(pkgPath, "utf-8"));
|
|
14651
|
-
const deps = Object.keys(pkgContent.dependencies ?? {}).filter((n) => coreNames.has(n));
|
|
14652
|
-
const devDeps = Object.keys(pkgContent.devDependencies ?? {}).filter((n) => devNames.has(n));
|
|
14653
|
-
if (deps.length > 0 || devDeps.length > 0) {
|
|
14654
|
-
const items = [];
|
|
14655
|
-
if (deps.length > 0) items.push(`${deps.length} dependencies`);
|
|
14656
|
-
if (devDeps.length > 0) items.push(`${devDeps.length} devDependencies`);
|
|
14657
|
-
steps.push({
|
|
14658
|
-
label: "package.json dependencies",
|
|
14659
|
-
items,
|
|
14660
|
-
execute() {
|
|
14661
|
-
cleanPackageJsonDeps(pkgPath, allCoreDeps, allDevDeps);
|
|
14662
|
-
}
|
|
14663
|
-
});
|
|
14664
|
-
}
|
|
14665
|
-
}
|
|
14666
14653
|
return steps;
|
|
14667
14654
|
}
|
|
14668
14655
|
var uninstallCommand = new Command6("uninstall").description("Remove all CMS files and undo modifications made by betterstart init").option("-f, --force", "Skip all confirmation prompts", false).option("--cwd <path>", "Project root path").action(async (options) => {
|
|
@@ -14674,30 +14661,26 @@ var uninstallCommand = new Command6("uninstall").description("Remove all CMS fil
|
|
|
14674
14661
|
p5.outro("Done");
|
|
14675
14662
|
return;
|
|
14676
14663
|
}
|
|
14677
|
-
p5.log.warn(
|
|
14678
|
-
`Found ${steps.length} ${steps.length === 1 ? "area" : "areas"} to clean up:`
|
|
14679
|
-
);
|
|
14680
|
-
let completedCount = 0;
|
|
14664
|
+
p5.log.warn("The following will be removed/modified:\n");
|
|
14681
14665
|
for (const step of steps) {
|
|
14682
|
-
p5.log.message(
|
|
14683
|
-
p5.log.step(pc3.bold(step.label));
|
|
14666
|
+
p5.log.message(` ${pc3.bold(step.label)}`);
|
|
14684
14667
|
for (const item of step.items) {
|
|
14685
|
-
p5.log.message(`
|
|
14668
|
+
p5.log.message(` ${pc3.red("\xD7")} ${pc3.dim(item)}`);
|
|
14686
14669
|
}
|
|
14687
|
-
|
|
14688
|
-
|
|
14689
|
-
|
|
14690
|
-
|
|
14691
|
-
})
|
|
14692
|
-
|
|
14693
|
-
|
|
14694
|
-
|
|
14695
|
-
|
|
14696
|
-
|
|
14697
|
-
p5.log.info(pc3.dim(`Skipped: ${step.label}`));
|
|
14698
|
-
continue;
|
|
14699
|
-
}
|
|
14670
|
+
p5.log.message("");
|
|
14671
|
+
}
|
|
14672
|
+
if (!options.force) {
|
|
14673
|
+
const confirmed = await p5.confirm({
|
|
14674
|
+
message: `Proceed with uninstall? (${steps.length} ${steps.length === 1 ? "area" : "areas"})`,
|
|
14675
|
+
initialValue: false
|
|
14676
|
+
});
|
|
14677
|
+
if (p5.isCancel(confirmed) || !confirmed) {
|
|
14678
|
+
p5.cancel("Uninstall cancelled.");
|
|
14679
|
+
process.exit(0);
|
|
14700
14680
|
}
|
|
14681
|
+
}
|
|
14682
|
+
let completedCount = 0;
|
|
14683
|
+
for (const step of steps) {
|
|
14701
14684
|
step.execute();
|
|
14702
14685
|
completedCount++;
|
|
14703
14686
|
p5.log.success(`Removed: ${step.label}`);
|
|
@@ -14706,13 +14689,8 @@ var uninstallCommand = new Command6("uninstall").description("Remove all CMS fil
|
|
|
14706
14689
|
if (completedCount === 0) {
|
|
14707
14690
|
p5.log.info("No changes were made.");
|
|
14708
14691
|
} else {
|
|
14709
|
-
const pm = detectPackageManager(cwd);
|
|
14710
14692
|
p5.note(
|
|
14711
|
-
|
|
14712
|
-
`Run ${pc3.cyan(installCommand(pm))} to clean up node_modules.`,
|
|
14713
|
-
"",
|
|
14714
|
-
pc3.dim("Database tables were NOT dropped \u2014 drop them manually if needed.")
|
|
14715
|
-
].join("\n"),
|
|
14693
|
+
pc3.dim("Database tables were NOT dropped \u2014 drop them manually if needed."),
|
|
14716
14694
|
"Next steps"
|
|
14717
14695
|
);
|
|
14718
14696
|
}
|