@betterstart/cli 0.1.50 → 0.1.52
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 +208 -35
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-6JCWMKSY.js";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
|
-
import { Command as
|
|
7
|
+
import { Command as Command10 } from "commander";
|
|
8
8
|
|
|
9
9
|
// src/commands/generate.ts
|
|
10
10
|
import path30 from "path";
|
|
@@ -2539,13 +2539,18 @@ ${selectItems}
|
|
|
2539
2539
|
return ` <div className="space-y-4">
|
|
2540
2540
|
<FormLabel className="text-sm font-medium leading-none">${label}${requiredStar}</FormLabel>${hintJSX}
|
|
2541
2541
|
{${name}FieldArray.fields.map((item, index) => (
|
|
2542
|
-
<div key={item.id} className="
|
|
2543
|
-
<
|
|
2542
|
+
<div key={item.id} className="relative rounded-lg border p-4">
|
|
2543
|
+
<button
|
|
2544
|
+
type="button"
|
|
2545
|
+
onClick={() => ${name}FieldArray.remove(index)}
|
|
2546
|
+
className="absolute right-2 top-2 inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:bg-destructive/10 hover:text-destructive"
|
|
2547
|
+
>
|
|
2548
|
+
<Trash2 className="h-4 w-4" />
|
|
2549
|
+
<span className="sr-only">Remove</span>
|
|
2550
|
+
</button>
|
|
2551
|
+
<div className="space-y-4 pr-8">
|
|
2544
2552
|
${nestedFieldsJSX}
|
|
2545
2553
|
</div>
|
|
2546
|
-
<Button type="button" variant="ghost" size="sm" onClick={() => ${name}FieldArray.remove(index)}>
|
|
2547
|
-
Remove
|
|
2548
|
-
</Button>
|
|
2549
2554
|
</div>
|
|
2550
2555
|
))}
|
|
2551
2556
|
<Button
|
|
@@ -2575,10 +2580,10 @@ function generateMultiStepForm(schema, cwd, cmsDir, options) {
|
|
|
2575
2580
|
const zodFields = buildZodFields(allFields);
|
|
2576
2581
|
const defaults = buildDefaultValues(allFields);
|
|
2577
2582
|
const listFields = getListFields(allFields);
|
|
2578
|
-
const
|
|
2583
|
+
const hasListFields2 = listFields.length > 0;
|
|
2579
2584
|
const { setup: watchSetup } = buildWatchDecls(allFields);
|
|
2580
|
-
const rhfImport =
|
|
2581
|
-
const fieldArraySetup =
|
|
2585
|
+
const rhfImport = hasListFields2 ? `import { useFieldArray, useForm } from 'react-hook-form'` : `import { useForm } from 'react-hook-form'`;
|
|
2586
|
+
const fieldArraySetup = hasListFields2 ? `
|
|
2582
2587
|
${buildFieldArrayDecls(listFields)}
|
|
2583
2588
|
` : "";
|
|
2584
2589
|
const stepsConst = buildStepsConstant(steps, schema);
|
|
@@ -2661,7 +2666,7 @@ export function ${p7.pascal}Form() {
|
|
|
2661
2666
|
return `'use client'
|
|
2662
2667
|
|
|
2663
2668
|
import { zodResolver } from '@hookform/resolvers/zod'
|
|
2664
|
-
import { Check, ChevronLeft, ChevronRight } from 'lucide-react'
|
|
2669
|
+
import { Check, ChevronLeft, ChevronRight${hasListFields ? ", Trash2" : ""} } from 'lucide-react'
|
|
2665
2670
|
import { parseAsInteger, parseAsArrayOf, useQueryState } from 'nuqs'
|
|
2666
2671
|
import { useState } from 'react'
|
|
2667
2672
|
${p7.rhfImport}
|
|
@@ -2868,14 +2873,14 @@ function generateSingleStepForm(schema, cwd, cmsDir, options) {
|
|
|
2868
2873
|
const zodFields = buildZodFields(fields);
|
|
2869
2874
|
const defaults = buildDefaultValues(fields);
|
|
2870
2875
|
const listFields = getListFields(fields);
|
|
2871
|
-
const
|
|
2876
|
+
const hasListFields2 = listFields.length > 0;
|
|
2872
2877
|
const { setup: watchSetup } = buildWatchDecls(fields);
|
|
2873
2878
|
const rawFields = schema.fields || [];
|
|
2874
2879
|
const fieldJSX = renderFieldsJSX(rawFields);
|
|
2875
2880
|
const submitText = schema.submitButtonText || "Submit";
|
|
2876
2881
|
const successMessage = escapeJsx(schema.successMessage || "Form submitted successfully!");
|
|
2877
|
-
const rhfImport =
|
|
2878
|
-
const fieldArraySetup =
|
|
2882
|
+
const rhfImport = hasListFields2 ? `import { useFieldArray, useForm } from 'react-hook-form'` : `import { useForm } from 'react-hook-form'`;
|
|
2883
|
+
const fieldArraySetup = hasListFields2 ? `
|
|
2879
2884
|
${buildFieldArrayDecls(listFields)}
|
|
2880
2885
|
` : "";
|
|
2881
2886
|
const hasRadio = fields.some((f) => f.type === "radio");
|
|
@@ -2902,9 +2907,11 @@ export function ${pascal}Form() {
|
|
|
2902
2907
|
)
|
|
2903
2908
|
}
|
|
2904
2909
|
` : "";
|
|
2910
|
+
const lucideImport = hasListFields2 ? `
|
|
2911
|
+
import { Trash2 } from 'lucide-react'` : "";
|
|
2905
2912
|
const content = `'use client'
|
|
2906
2913
|
|
|
2907
|
-
import { zodResolver } from '@hookform/resolvers/zod'
|
|
2914
|
+
import { zodResolver } from '@hookform/resolvers/zod'${lucideImport}
|
|
2908
2915
|
import { useState } from 'react'
|
|
2909
2916
|
${rhfImport}
|
|
2910
2917
|
import { z } from 'zod/v3'${queryClientImport}
|
|
@@ -15521,18 +15528,183 @@ var uninstallCommand = new Command6("uninstall").description("Remove all CMS fil
|
|
|
15521
15528
|
p6.outro("Uninstall complete");
|
|
15522
15529
|
});
|
|
15523
15530
|
|
|
15524
|
-
// src/commands/update-
|
|
15531
|
+
// src/commands/update-component.ts
|
|
15532
|
+
import fs45 from "fs";
|
|
15525
15533
|
import path49 from "path";
|
|
15526
15534
|
import * as clack2 from "@clack/prompts";
|
|
15527
15535
|
import { Command as Command7 } from "commander";
|
|
15528
|
-
|
|
15536
|
+
import fsExtra from "fs-extra";
|
|
15537
|
+
var TEMPLATE_REGISTRY = {
|
|
15538
|
+
// CSS
|
|
15539
|
+
"cms-globals": { relPath: "cms-globals.css", content: cmsGlobalsCssTemplate },
|
|
15540
|
+
// Layout
|
|
15541
|
+
"cms-providers": { relPath: "components/layout/cms-providers.tsx", content: cmsProvidersTemplate },
|
|
15542
|
+
"cms-nav-link": { relPath: "components/layout/cms-nav-link.tsx", content: cmsNavLinkTemplate },
|
|
15543
|
+
"cms-sidebar": { relPath: "components/layout/cms-sidebar.tsx", content: cmsSidebarTemplate },
|
|
15544
|
+
"cms-header": { relPath: "components/layout/cms-header.tsx", content: cmsHeaderTemplate },
|
|
15545
|
+
"cms-search": { relPath: "components/layout/cms-search.tsx", content: cmsSearchTemplate },
|
|
15546
|
+
// Shared
|
|
15547
|
+
"page-header": { relPath: "components/shared/page-header.tsx", content: pageHeaderTemplate },
|
|
15548
|
+
"delete-dialog": { relPath: "components/shared/delete-dialog.tsx", content: deleteDialogTemplate },
|
|
15549
|
+
"status-badge": { relPath: "components/shared/status-badge.tsx", content: statusBadgeTemplate },
|
|
15550
|
+
// Data table
|
|
15551
|
+
"data-table": { relPath: "components/data-table/data-table.tsx", content: dataTableTemplate },
|
|
15552
|
+
"data-table-pagination": { relPath: "components/data-table/data-table-pagination.tsx", content: dataTablePaginationTemplate },
|
|
15553
|
+
"data-table-toolbar": { relPath: "components/data-table/data-table-toolbar.tsx", content: dataTableToolbarTemplate },
|
|
15554
|
+
// Hooks
|
|
15555
|
+
"use-upload": { relPath: "hooks/use-upload.ts", content: useUploadHookTemplate },
|
|
15556
|
+
"use-editor-image-upload": { relPath: "hooks/use-editor-image-upload.ts", content: useEditorImageUploadHookTemplate },
|
|
15557
|
+
"use-local-storage": { relPath: "hooks/use-local-storage.ts", content: useLocalStorageHookTemplate },
|
|
15558
|
+
"use-cms-theme": { relPath: "hooks/use-cms-theme.tsx", content: useCmsThemeTemplate },
|
|
15559
|
+
"use-users": { relPath: "hooks/use-users.ts", content: useUsersHookTemplate },
|
|
15560
|
+
"use-mobile": { relPath: "hooks/use-mobile.ts", content: useMobileHookTemplate },
|
|
15561
|
+
// Types
|
|
15562
|
+
"types-index": { relPath: "types/index.ts", content: typesIndexTemplate },
|
|
15563
|
+
"auth-types": { relPath: "types/auth.ts", content: authTypesTemplate },
|
|
15564
|
+
"table-meta": { relPath: "types/table-meta.ts", content: tableMetaTypesTemplate },
|
|
15565
|
+
// Utils
|
|
15566
|
+
cn: { relPath: "utils/cn.ts", content: cnUtilTemplate },
|
|
15567
|
+
seo: { relPath: "utils/seo.ts", content: seoUtilTemplate },
|
|
15568
|
+
validation: { relPath: "utils/validation.ts", content: validationUtilTemplate },
|
|
15569
|
+
webhook: { relPath: "utils/webhook.ts", content: webhookUtilTemplate },
|
|
15570
|
+
mailchimp: { relPath: "utils/mailchimp.ts", content: mailchimpUtilTemplate },
|
|
15571
|
+
// Lib
|
|
15572
|
+
r2: { relPath: "lib/r2.ts", content: r2ClientTemplate },
|
|
15573
|
+
"form-settings-action": { relPath: "lib/actions/form-settings.ts", content: formSettingsActionTemplate },
|
|
15574
|
+
"upload-action": { relPath: "lib/actions/upload.ts", content: uploadActionTemplate },
|
|
15575
|
+
"users-action": { relPath: "lib/actions/users.ts", content: usersActionTemplate },
|
|
15576
|
+
// Markdown
|
|
15577
|
+
"markdown-render": { relPath: "lib/markdown/render.ts", content: markdownRenderTemplate },
|
|
15578
|
+
"markdown-format": { relPath: "lib/markdown/format.ts", content: markdownFormatTemplate },
|
|
15579
|
+
"markdown-cached": { relPath: "lib/markdown/cached.ts", content: markdownCachedTemplate }
|
|
15580
|
+
};
|
|
15581
|
+
function findCliRoot2() {
|
|
15582
|
+
let dir = new URL(".", import.meta.url).pathname;
|
|
15583
|
+
for (let i = 0; i < 5; i++) {
|
|
15584
|
+
const pkgPath = path49.join(dir, "package.json");
|
|
15585
|
+
if (fs45.existsSync(pkgPath)) {
|
|
15586
|
+
try {
|
|
15587
|
+
const pkg = JSON.parse(fs45.readFileSync(pkgPath, "utf-8"));
|
|
15588
|
+
if (pkg.name === "@betterstart/cli") {
|
|
15589
|
+
return dir;
|
|
15590
|
+
}
|
|
15591
|
+
} catch {
|
|
15592
|
+
}
|
|
15593
|
+
}
|
|
15594
|
+
dir = path49.dirname(dir);
|
|
15595
|
+
}
|
|
15596
|
+
return path49.resolve(new URL(".", import.meta.url).pathname, "..", "..");
|
|
15597
|
+
}
|
|
15598
|
+
function getStaticUiComponents() {
|
|
15599
|
+
const cliRoot = findCliRoot2();
|
|
15600
|
+
const uiDir = path49.join(cliRoot, "templates", "ui");
|
|
15601
|
+
if (!fs45.existsSync(uiDir)) return [];
|
|
15602
|
+
return fs45.readdirSync(uiDir).filter((f) => f.endsWith(".tsx") || f.endsWith(".ts")).map((f) => f.replace(/\.(tsx|ts)$/, ""));
|
|
15603
|
+
}
|
|
15604
|
+
function getAllComponentNames() {
|
|
15605
|
+
const staticUi = getStaticUiComponents();
|
|
15606
|
+
const templateKeys = Object.keys(TEMPLATE_REGISTRY);
|
|
15607
|
+
return [.../* @__PURE__ */ new Set([...staticUi, ...templateKeys, "tiptap"])].sort();
|
|
15608
|
+
}
|
|
15609
|
+
var updateComponentCommand = new Command7("update-component").description("Update individual CMS components from the latest CLI templates").argument("[components...]", "Component names to update (e.g., media-upload-field button)").option("--list", "List all available components").option("--all", "Update all components").option("--cwd <path>", "Project root path").action(async (components, options) => {
|
|
15529
15610
|
const cwd = options.cwd ? path49.resolve(options.cwd) : process.cwd();
|
|
15530
|
-
|
|
15611
|
+
if (options.list) {
|
|
15612
|
+
const all = getAllComponentNames();
|
|
15613
|
+
clack2.intro("Available components");
|
|
15614
|
+
const uiComponents = getStaticUiComponents();
|
|
15615
|
+
const templateKeys = Object.keys(TEMPLATE_REGISTRY).sort();
|
|
15616
|
+
console.log();
|
|
15617
|
+
console.log(` UI Components (${uiComponents.length})`);
|
|
15618
|
+
console.log(` ${"\u2500".repeat(50)}`);
|
|
15619
|
+
console.log(` ${"Name".padEnd(28)} ${"Path"}`);
|
|
15620
|
+
console.log(` ${"\u2500".repeat(50)}`);
|
|
15621
|
+
for (const name of uiComponents) {
|
|
15622
|
+
console.log(` ${name.padEnd(28)} components/ui/${name}.tsx`);
|
|
15623
|
+
}
|
|
15624
|
+
console.log();
|
|
15625
|
+
console.log(` Template Components (${templateKeys.length})`);
|
|
15626
|
+
console.log(` ${"\u2500".repeat(56)}`);
|
|
15627
|
+
console.log(` ${"Name".padEnd(28)} ${"Path"}`);
|
|
15628
|
+
console.log(` ${"\u2500".repeat(56)}`);
|
|
15629
|
+
for (const name of templateKeys) {
|
|
15630
|
+
console.log(` ${name.padEnd(28)} ${TEMPLATE_REGISTRY[name].relPath}`);
|
|
15631
|
+
}
|
|
15632
|
+
console.log();
|
|
15633
|
+
console.log(` Special`);
|
|
15634
|
+
console.log(` ${"\u2500".repeat(56)}`);
|
|
15635
|
+
console.log(` ${"tiptap".padEnd(28)} components/ui/tiptap/ (all files)`);
|
|
15636
|
+
console.log();
|
|
15637
|
+
clack2.outro(`${all.length} components available`);
|
|
15638
|
+
return;
|
|
15639
|
+
}
|
|
15640
|
+
if (!options.all && components.length === 0) {
|
|
15641
|
+
clack2.log.error("Provide component names or use --all. Run with --list to see available components.");
|
|
15642
|
+
process.exit(1);
|
|
15643
|
+
}
|
|
15644
|
+
const config = await resolveConfig(cwd);
|
|
15645
|
+
const cms = path49.resolve(cwd, config.paths.cms);
|
|
15646
|
+
if (!fs45.existsSync(cms)) {
|
|
15647
|
+
clack2.cancel(`CMS directory not found at ${config.paths.cms}. Run 'betterstart init' first.`);
|
|
15648
|
+
process.exit(1);
|
|
15649
|
+
}
|
|
15650
|
+
clack2.intro("BetterStart Update Components");
|
|
15651
|
+
const toUpdate = options.all ? getAllComponentNames() : components;
|
|
15652
|
+
const cliRoot = findCliRoot2();
|
|
15653
|
+
const uiDir = path49.join(cliRoot, "templates", "ui");
|
|
15654
|
+
let updated = 0;
|
|
15655
|
+
let skipped = 0;
|
|
15656
|
+
for (const name of toUpdate) {
|
|
15657
|
+
if (TEMPLATE_REGISTRY[name]) {
|
|
15658
|
+
const entry = TEMPLATE_REGISTRY[name];
|
|
15659
|
+
const destPath = path49.join(cms, entry.relPath);
|
|
15660
|
+
fsExtra.ensureDirSync(path49.dirname(destPath));
|
|
15661
|
+
fs45.writeFileSync(destPath, entry.content(), "utf-8");
|
|
15662
|
+
clack2.log.success(`Updated ${entry.relPath}`);
|
|
15663
|
+
updated++;
|
|
15664
|
+
continue;
|
|
15665
|
+
}
|
|
15666
|
+
const uiFile = fs45.readdirSync(uiDir).find(
|
|
15667
|
+
(f) => f.replace(/\.(tsx|ts)$/, "") === name
|
|
15668
|
+
);
|
|
15669
|
+
if (uiFile) {
|
|
15670
|
+
const destPath = path49.join(cms, "components", "ui", uiFile);
|
|
15671
|
+
fsExtra.ensureDirSync(path49.dirname(destPath));
|
|
15672
|
+
fs45.copyFileSync(path49.join(uiDir, uiFile), destPath);
|
|
15673
|
+
clack2.log.success(`Updated components/ui/${uiFile}`);
|
|
15674
|
+
updated++;
|
|
15675
|
+
continue;
|
|
15676
|
+
}
|
|
15677
|
+
if (name === "tiptap") {
|
|
15678
|
+
const srcDir = path49.join(cliRoot, "templates", "tiptap");
|
|
15679
|
+
const destDir = path49.join(cms, "components", "ui", "tiptap");
|
|
15680
|
+
if (fs45.existsSync(srcDir)) {
|
|
15681
|
+
fsExtra.copySync(srcDir, destDir, { overwrite: true });
|
|
15682
|
+
clack2.log.success("Updated components/ui/tiptap/ (all files)");
|
|
15683
|
+
updated++;
|
|
15684
|
+
} else {
|
|
15685
|
+
clack2.log.warning("tiptap templates not found");
|
|
15686
|
+
skipped++;
|
|
15687
|
+
}
|
|
15688
|
+
continue;
|
|
15689
|
+
}
|
|
15690
|
+
clack2.log.warning(`Unknown component: ${name}`);
|
|
15691
|
+
skipped++;
|
|
15692
|
+
}
|
|
15693
|
+
clack2.outro(`Updated ${updated} component${updated !== 1 ? "s" : ""}${skipped > 0 ? `, ${skipped} skipped` : ""}`);
|
|
15694
|
+
});
|
|
15695
|
+
|
|
15696
|
+
// src/commands/update-deps.ts
|
|
15697
|
+
import path50 from "path";
|
|
15698
|
+
import * as clack3 from "@clack/prompts";
|
|
15699
|
+
import { Command as Command8 } from "commander";
|
|
15700
|
+
var updateDepsCommand = new Command8("update-deps").description("Install or update all CMS dependencies").option("--cwd <path>", "Project root path").action(async (options) => {
|
|
15701
|
+
const cwd = options.cwd ? path50.resolve(options.cwd) : process.cwd();
|
|
15702
|
+
clack3.intro("BetterStart Update Dependencies");
|
|
15531
15703
|
const pm = detectPackageManager(cwd);
|
|
15532
|
-
|
|
15704
|
+
clack3.log.info(`Package manager: ${pm}`);
|
|
15533
15705
|
const config = await resolveConfig(cwd);
|
|
15534
15706
|
const includeEmail = config.features?.email ?? true;
|
|
15535
|
-
const s =
|
|
15707
|
+
const s = clack3.spinner();
|
|
15536
15708
|
s.start("Installing dependencies...");
|
|
15537
15709
|
const result = await installDependenciesAsync({
|
|
15538
15710
|
cwd,
|
|
@@ -15544,34 +15716,34 @@ var updateDepsCommand = new Command7("update-deps").description("Install or upda
|
|
|
15544
15716
|
s.stop(`Installed ${result.coreDeps.length} deps + ${result.devDeps.length} dev deps`);
|
|
15545
15717
|
} else {
|
|
15546
15718
|
s.stop("Dependency install failed");
|
|
15547
|
-
|
|
15719
|
+
clack3.log.error(result.error ?? "Unknown error");
|
|
15548
15720
|
process.exit(1);
|
|
15549
15721
|
}
|
|
15550
|
-
|
|
15722
|
+
clack3.outro("Dependencies updated");
|
|
15551
15723
|
});
|
|
15552
15724
|
|
|
15553
15725
|
// src/commands/update-styles.ts
|
|
15554
|
-
import
|
|
15555
|
-
import
|
|
15556
|
-
import * as
|
|
15557
|
-
import { Command as
|
|
15558
|
-
var updateStylesCommand = new
|
|
15559
|
-
const cwd = options.cwd ?
|
|
15560
|
-
|
|
15726
|
+
import fs46 from "fs";
|
|
15727
|
+
import path51 from "path";
|
|
15728
|
+
import * as clack4 from "@clack/prompts";
|
|
15729
|
+
import { Command as Command9 } from "commander";
|
|
15730
|
+
var updateStylesCommand = new Command9("update-styles").description("Replace cms-globals.css with the latest version from the CLI").option("--cwd <path>", "Project root path").action(async (options) => {
|
|
15731
|
+
const cwd = options.cwd ? path51.resolve(options.cwd) : process.cwd();
|
|
15732
|
+
clack4.intro("BetterStart Update Styles");
|
|
15561
15733
|
const config = await resolveConfig(cwd);
|
|
15562
15734
|
const cmsDir = config.paths?.cms ?? "./cms";
|
|
15563
|
-
const targetPath =
|
|
15564
|
-
if (!
|
|
15565
|
-
|
|
15735
|
+
const targetPath = path51.join(cwd, cmsDir, "cms-globals.css");
|
|
15736
|
+
if (!fs46.existsSync(targetPath)) {
|
|
15737
|
+
clack4.cancel(`cms-globals.css not found at ${path51.relative(cwd, targetPath)}`);
|
|
15566
15738
|
process.exit(1);
|
|
15567
15739
|
}
|
|
15568
|
-
|
|
15569
|
-
|
|
15570
|
-
|
|
15740
|
+
fs46.writeFileSync(targetPath, cmsGlobalsCssTemplate(), "utf-8");
|
|
15741
|
+
clack4.log.success(`Updated ${path51.relative(cwd, targetPath)}`);
|
|
15742
|
+
clack4.outro("Styles updated");
|
|
15571
15743
|
});
|
|
15572
15744
|
|
|
15573
15745
|
// src/cli.ts
|
|
15574
|
-
var program = new
|
|
15746
|
+
var program = new Command10();
|
|
15575
15747
|
program.name("betterstart").description("Scaffold a full-featured CMS into any Next.js 16 application").version("0.1.0");
|
|
15576
15748
|
program.addCommand(initCommand);
|
|
15577
15749
|
program.addCommand(generateCommand);
|
|
@@ -15579,6 +15751,7 @@ program.addCommand(removeCommand);
|
|
|
15579
15751
|
program.addCommand(seedCommand);
|
|
15580
15752
|
program.addCommand(setupR2Command);
|
|
15581
15753
|
program.addCommand(uninstallCommand);
|
|
15754
|
+
program.addCommand(updateComponentCommand);
|
|
15582
15755
|
program.addCommand(updateDepsCommand);
|
|
15583
15756
|
program.addCommand(updateStylesCommand);
|
|
15584
15757
|
program.parse();
|