@betterstart/cli 0.1.82 → 0.1.83
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 +161 -303
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/templates/init/components/data-table/data-table.tsx +1 -1
- package/templates/init/components/shared/page-header.tsx +5 -5
- package/templates/init/pages/dashboard-page.tsx +1 -1
- package/templates/init/pages/users/columns.tsx +13 -10
- package/templates/init/pages/users/users-page-content.tsx +9 -2
- package/templates/init/pages/users/users-page.tsx +1 -1
- package/templates/init/pages/users/users-table.tsx +2 -2
- package/templates/ui/badge.tsx +2 -2
- package/templates/ui/button.tsx +1 -1
- package/templates/ui/sidebar.tsx +2 -2
- package/templates/ui/table.tsx +10 -4
package/dist/cli.js
CHANGED
|
@@ -717,7 +717,7 @@ function generateColumnDef(col) {
|
|
|
717
717
|
className="hover:bg-muted/50 px-0!"
|
|
718
718
|
>
|
|
719
719
|
${col.header}
|
|
720
|
-
<ArrowUpDown className="size-
|
|
720
|
+
<ArrowUpDown className="size-3" />
|
|
721
721
|
</Button>
|
|
722
722
|
)` : `header: '${col.header}'`;
|
|
723
723
|
let cellDef;
|
|
@@ -771,7 +771,7 @@ function generateColumns(fields, pascal, kebab, camel, customColumns) {
|
|
|
771
771
|
className="hover:bg-muted/50 px-0!"
|
|
772
772
|
>
|
|
773
773
|
${f.label}
|
|
774
|
-
<ArrowUpDown className="size-
|
|
774
|
+
<ArrowUpDown className="size-3" />
|
|
775
775
|
</Button>
|
|
776
776
|
),
|
|
777
777
|
cell: ({ row }) => {
|
|
@@ -4694,7 +4694,7 @@ function generateColumnDef2(column, fields) {
|
|
|
4694
4694
|
aria-sort={sortDirection === 'asc' ? 'ascending' : sortDirection === 'desc' ? 'descending' : 'none'}
|
|
4695
4695
|
>
|
|
4696
4696
|
${column.header}
|
|
4697
|
-
<ArrowUpDown className="size-
|
|
4697
|
+
<ArrowUpDown className="size-3" />
|
|
4698
4698
|
</Button>
|
|
4699
4699
|
)
|
|
4700
4700
|
}` : `header: '${column.header}'`;
|
|
@@ -4842,7 +4842,7 @@ function generateFirstColumnDef(column, fields, schemaName) {
|
|
|
4842
4842
|
aria-sort={sortDirection === 'asc' ? 'ascending' : sortDirection === 'desc' ? 'descending' : 'none'}
|
|
4843
4843
|
>
|
|
4844
4844
|
${column.header}
|
|
4845
|
-
<ArrowUpDown className="size-
|
|
4845
|
+
<ArrowUpDown className="size-3" />
|
|
4846
4846
|
</Button>
|
|
4847
4847
|
</div>
|
|
4848
4848
|
)
|
|
@@ -5483,12 +5483,12 @@ export default async function Create${Singular}Page() {
|
|
|
5483
5483
|
await connection()
|
|
5484
5484
|
|
|
5485
5485
|
return (
|
|
5486
|
-
|
|
5486
|
+
<div className="flex flex-col pt-14">
|
|
5487
5487
|
<PageHeader title="Create ${singLabel}" back={<Button variant="ghost" size="icon" asChild><Link href="/cms/${schema.name}"><ChevronLeft /></Link></Button>} />
|
|
5488
5488
|
<main className="container mx-auto max-w-5xl pt-10 pb-20 w-full">
|
|
5489
5489
|
<${Singular}Form key={Date.now()} />
|
|
5490
5490
|
</main>
|
|
5491
|
-
|
|
5491
|
+
</div>
|
|
5492
5492
|
)
|
|
5493
5493
|
}
|
|
5494
5494
|
`;
|
|
@@ -5779,12 +5779,12 @@ export default async function Edit${Singular}Page({ params }: PageProps) {
|
|
|
5779
5779
|
}
|
|
5780
5780
|
|
|
5781
5781
|
return (
|
|
5782
|
-
|
|
5782
|
+
<div className="flex flex-col pt-14">
|
|
5783
5783
|
<PageHeader title="Edit ${Singular}" back={<Button variant="ghost" size="icon" asChild><Link href="/cms/${schema.name}"><ChevronLeft /></Link></Button>} />
|
|
5784
5784
|
<main className="container mx-auto max-w-5xl pt-10 pb-20 w-full">
|
|
5785
5785
|
<${Singular}Form key={${camelSingular}.id} initialData={${camelSingular}} />
|
|
5786
5786
|
</main>
|
|
5787
|
-
|
|
5787
|
+
</div>
|
|
5788
5788
|
)
|
|
5789
5789
|
}
|
|
5790
5790
|
`;
|
|
@@ -7591,7 +7591,7 @@ export default function ${Plural}Page() {
|
|
|
7591
7591
|
</div>
|
|
7592
7592
|
}
|
|
7593
7593
|
>
|
|
7594
|
-
<div className="flex flex-col">
|
|
7594
|
+
<div className="flex flex-col pt-14">
|
|
7595
7595
|
<${Plural}PageContent columns={columns} />
|
|
7596
7596
|
</div>
|
|
7597
7597
|
</React.Suspense>
|
|
@@ -7862,12 +7862,12 @@ export function ${Plural}PageContent<TValue>({
|
|
|
7862
7862
|
const queryClient = useQueryClient()
|
|
7863
7863
|
${searchLogic}${deleteLogic}
|
|
7864
7864
|
return (
|
|
7865
|
-
|
|
7865
|
+
<div className="flex flex-col pt-14">
|
|
7866
7866
|
<PageHeader title="${schema.label}" back={<Button variant="ghost" size="icon" onClick={() => router.back()}><ChevronLeft /></Button>} search={${searchInput}} actions={<div className="flex items-center gap-2">${deleteButton} ${createButton}</div>} />
|
|
7867
7867
|
<main className="space-y-6 p-6">
|
|
7868
7868
|
<${Plural}Table ${tableProps} />
|
|
7869
7869
|
</main>
|
|
7870
|
-
|
|
7870
|
+
</div>
|
|
7871
7871
|
)
|
|
7872
7872
|
}
|
|
7873
7873
|
`;
|
|
@@ -7902,12 +7902,12 @@ export default async function ${PageName}Page() {
|
|
|
7902
7902
|
const data = await get${Singular}()
|
|
7903
7903
|
|
|
7904
7904
|
return (
|
|
7905
|
-
|
|
7905
|
+
<div className="flex flex-col pt-14">
|
|
7906
7906
|
<PageHeader title="${schema.label}" />
|
|
7907
7907
|
<main className="container mx-auto max-w-5xl pt-10 pb-20 w-full">
|
|
7908
7908
|
<${Singular}Form initialData={data} />
|
|
7909
7909
|
</main>
|
|
7910
|
-
|
|
7910
|
+
</div>
|
|
7911
7911
|
)
|
|
7912
7912
|
}
|
|
7913
7913
|
`;
|
|
@@ -8203,7 +8203,7 @@ export function ${Plural}Table<TValue>({ columns, selectedIds, setSelectedIds, $
|
|
|
8203
8203
|
|
|
8204
8204
|
<div className="bg-card border overflow-hidden rounded-lg">
|
|
8205
8205
|
<Table>
|
|
8206
|
-
<TableHeader
|
|
8206
|
+
<TableHeader>
|
|
8207
8207
|
{table.getHeaderGroups().map((headerGroup) => (
|
|
8208
8208
|
<TableRow key={headerGroup.id}>
|
|
8209
8209
|
{headerGroup.headers.map((header) => {
|
|
@@ -8831,7 +8831,7 @@ async function generateAll(cwd, options) {
|
|
|
8831
8831
|
|
|
8832
8832
|
// src/commands/init.ts
|
|
8833
8833
|
import { execFileSync as execFileSync4, spawn as spawn2 } from "child_process";
|
|
8834
|
-
import
|
|
8834
|
+
import fs39 from "fs";
|
|
8835
8835
|
import path45 from "path";
|
|
8836
8836
|
import * as p4 from "@clack/prompts";
|
|
8837
8837
|
import { Command as Command3 } from "commander";
|
|
@@ -9027,7 +9027,6 @@ function scaffoldAuth({ cwd, config }) {
|
|
|
9027
9027
|
}
|
|
9028
9028
|
|
|
9029
9029
|
// src/init/scaffolders/base.ts
|
|
9030
|
-
import fs31 from "fs";
|
|
9031
9030
|
import path34 from "path";
|
|
9032
9031
|
function scaffoldBase({ cwd, config }) {
|
|
9033
9032
|
const created = [];
|
|
@@ -9069,16 +9068,8 @@ function scaffoldBase({ cwd, config }) {
|
|
|
9069
9068
|
if (safeWriteFile(path34.resolve(cwd, "cms.config.ts"), configContent)) {
|
|
9070
9069
|
created.push("cms.config.ts");
|
|
9071
9070
|
}
|
|
9072
|
-
const cmsDoc = generateCmsDoc(config, {});
|
|
9073
|
-
if (safeWriteFile(path34.resolve(cwd, "CMS.md"), cmsDoc)) {
|
|
9074
|
-
created.push("CMS.md");
|
|
9075
|
-
}
|
|
9076
9071
|
return created;
|
|
9077
9072
|
}
|
|
9078
|
-
function regenerateCmsDoc(cwd, config, options) {
|
|
9079
|
-
const content = generateCmsDoc(config, options);
|
|
9080
|
-
fs31.writeFileSync(path34.resolve(cwd, "CMS.md"), content, "utf-8");
|
|
9081
|
-
}
|
|
9082
9073
|
function generateConfigFile(config) {
|
|
9083
9074
|
return `import { defineConfig } from '@betterstart/cli'
|
|
9084
9075
|
|
|
@@ -9112,126 +9103,9 @@ export default defineConfig({
|
|
|
9112
9103
|
})
|
|
9113
9104
|
`;
|
|
9114
9105
|
}
|
|
9115
|
-
function generateCmsDoc(config, options) {
|
|
9116
|
-
const sections = [];
|
|
9117
|
-
sections.push(`# CMS
|
|
9118
|
-
|
|
9119
|
-
> Auto-generated by [BetterStart CLI](https://github.com/betterstart/cli).
|
|
9120
|
-
> Regenerated on each \`betterstart init\`.`);
|
|
9121
|
-
if (options.preset) {
|
|
9122
|
-
sections.push(`## Preset
|
|
9123
|
-
|
|
9124
|
-
This project was initialized with the **${options.preset}** preset.`);
|
|
9125
|
-
}
|
|
9126
|
-
sections.push(`## Directory Structure
|
|
9127
|
-
|
|
9128
|
-
| Path | Description |
|
|
9129
|
-
|------|-------------|
|
|
9130
|
-
| \`cms/\` | All CMS source code (you own this) |
|
|
9131
|
-
| \`cms/schemas/\` | Entity JSON schemas |
|
|
9132
|
-
| \`cms/schemas/forms/\` | Form JSON schemas |
|
|
9133
|
-
| \`cms/db/\` | Database client, schema, drizzle config |
|
|
9134
|
-
| \`cms/lib/actions/\` | Server actions (CRUD) |
|
|
9135
|
-
| \`cms/lib/auth/\` | Better Auth configuration |
|
|
9136
|
-
| \`cms/lib/cache/\` | Cache tags, queries, revalidation |
|
|
9137
|
-
| \`cms/lib/emails/\` | React Email templates |
|
|
9138
|
-
| \`cms/hooks/\` | React Query hooks |
|
|
9139
|
-
| \`cms/components/\` | UI components (shadcn-style) |
|
|
9140
|
-
| \`cms/utils/\` | Utility functions |
|
|
9141
|
-
| \`${config.paths.pages}/\` | Admin pages (auth-gated) |
|
|
9142
|
-
| \`${config.paths.login}/\` | Login page |
|
|
9143
|
-
| \`${config.paths.api}/\` | CMS API routes |`);
|
|
9144
|
-
if (options.schemas && options.schemas.length > 0 || options.forms && options.forms.length > 0) {
|
|
9145
|
-
const lines = ["## Generated Content", ""];
|
|
9146
|
-
if (options.schemas && options.schemas.length > 0) {
|
|
9147
|
-
lines.push("### Entities");
|
|
9148
|
-
for (const s of options.schemas) {
|
|
9149
|
-
lines.push(`- **${s}** \u2014 \`cms/schemas/${s}.json\` \u2192 admin at \`/cms/${s}\``);
|
|
9150
|
-
}
|
|
9151
|
-
}
|
|
9152
|
-
if (options.forms && options.forms.length > 0) {
|
|
9153
|
-
lines.push("");
|
|
9154
|
-
lines.push("### Forms");
|
|
9155
|
-
for (const f of options.forms) {
|
|
9156
|
-
lines.push(`- **${f}** \u2014 \`cms/schemas/forms/${f}.json\` \u2192 admin at \`/cms/forms/${f}\``);
|
|
9157
|
-
}
|
|
9158
|
-
}
|
|
9159
|
-
sections.push(lines.join("\n"));
|
|
9160
|
-
}
|
|
9161
|
-
sections.push(`## Commands
|
|
9162
|
-
|
|
9163
|
-
\`\`\`bash
|
|
9164
|
-
# Generate entity CRUD from a schema
|
|
9165
|
-
npx betterstart generate <schema-name>
|
|
9166
|
-
|
|
9167
|
-
# Generate with force overwrite
|
|
9168
|
-
npx betterstart generate <schema-name> --force
|
|
9169
|
-
|
|
9170
|
-
# Remove all generated files for an entity/form
|
|
9171
|
-
npx betterstart remove <schema-name>
|
|
9172
|
-
|
|
9173
|
-
# Create initial admin user
|
|
9174
|
-
npx betterstart seed
|
|
9175
|
-
\`\`\``);
|
|
9176
|
-
sections.push(`## Schema Format
|
|
9177
|
-
|
|
9178
|
-
### Entity Schema (\`cms/schemas/<name>.json\`)
|
|
9179
|
-
|
|
9180
|
-
\`\`\`json
|
|
9181
|
-
{
|
|
9182
|
-
"name": "posts",
|
|
9183
|
-
"label": "Posts",
|
|
9184
|
-
"icon": "FileText",
|
|
9185
|
-
"fields": [
|
|
9186
|
-
{ "name": "title", "type": "string", "label": "Title", "required": true },
|
|
9187
|
-
{ "name": "content", "type": "richtext", "label": "Content" }
|
|
9188
|
-
]
|
|
9189
|
-
}
|
|
9190
|
-
\`\`\`
|
|
9191
|
-
|
|
9192
|
-
Field types: \`string\`, \`text\`, \`richtext\`, \`number\`, \`boolean\`, \`date\`, \`image\`, \`select\`, \`relationship\`.
|
|
9193
|
-
|
|
9194
|
-
### Form Schema (\`cms/schemas/forms/<name>.json\`)
|
|
9195
|
-
|
|
9196
|
-
\`\`\`json
|
|
9197
|
-
{
|
|
9198
|
-
"name": "contact",
|
|
9199
|
-
"label": "Contact Form",
|
|
9200
|
-
"submitButtonText": "Send Message",
|
|
9201
|
-
"fields": [
|
|
9202
|
-
{ "name": "email", "type": "email", "label": "Email", "required": true },
|
|
9203
|
-
{ "name": "message", "type": "textarea", "label": "Message", "required": true }
|
|
9204
|
-
]
|
|
9205
|
-
}
|
|
9206
|
-
\`\`\`
|
|
9207
|
-
|
|
9208
|
-
Field types: \`text\`, \`textarea\`, \`email\`, \`phone\`, \`number\`, \`url\`, \`date\`, \`select\`, \`radio\`, \`checkbox\`, \`multiselect\`, \`file\`.`);
|
|
9209
|
-
sections.push(`## Path Aliases
|
|
9210
|
-
|
|
9211
|
-
| Alias | Resolves to |
|
|
9212
|
-
|-------|-------------|
|
|
9213
|
-
| \`@cms/*\` | \`${config.paths.cms}/*\` |`);
|
|
9214
|
-
sections.push(`## Environment Variables
|
|
9215
|
-
|
|
9216
|
-
Required variables in \`.env.local\`:
|
|
9217
|
-
|
|
9218
|
-
| Variable | Description |
|
|
9219
|
-
|----------|-------------|
|
|
9220
|
-
| \`BETTERSTART_DATABASE_URL\` | PostgreSQL connection string |
|
|
9221
|
-
| \`BETTERSTART_AUTH_SECRET\` | Auth secret (\`openssl rand -base64 32\`) |
|
|
9222
|
-
| \`BETTERSTART_AUTH_URL\` | App URL (e.g. \`http://localhost:3000\`) |
|
|
9223
|
-
| \`BETTERSTART_R2_*\` | Cloudflare R2 storage credentials |
|
|
9224
|
-
| \`BETTERSTART_RESEND_API_KEY\` | Resend API key (if email enabled) |
|
|
9225
|
-
| \`NOTIFICATION_EMAIL\` | Fallback notification email address |`);
|
|
9226
|
-
sections.push(`## Configuration
|
|
9227
|
-
|
|
9228
|
-
Edit \`cms.config.ts\` to customize paths, database provider, and features.`);
|
|
9229
|
-
return `${sections.join("\n\n")}
|
|
9230
|
-
`;
|
|
9231
|
-
}
|
|
9232
9106
|
|
|
9233
9107
|
// src/init/scaffolders/biome.ts
|
|
9234
|
-
import
|
|
9108
|
+
import fs31 from "fs";
|
|
9235
9109
|
import path35 from "path";
|
|
9236
9110
|
function scaffoldBiome(cwd, linter) {
|
|
9237
9111
|
if (linter.type !== "none") {
|
|
@@ -9241,7 +9115,7 @@ function scaffoldBiome(cwd, linter) {
|
|
|
9241
9115
|
};
|
|
9242
9116
|
}
|
|
9243
9117
|
const configPath = path35.join(cwd, "biome.json");
|
|
9244
|
-
if (
|
|
9118
|
+
if (fs31.existsSync(configPath)) {
|
|
9245
9119
|
return { installed: false, skippedReason: "biome.json already exists" };
|
|
9246
9120
|
}
|
|
9247
9121
|
const config = {
|
|
@@ -9292,24 +9166,24 @@ function scaffoldBiome(cwd, linter) {
|
|
|
9292
9166
|
]
|
|
9293
9167
|
}
|
|
9294
9168
|
};
|
|
9295
|
-
|
|
9169
|
+
fs31.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
9296
9170
|
`, "utf-8");
|
|
9297
9171
|
return { installed: true, skippedReason: null };
|
|
9298
9172
|
}
|
|
9299
9173
|
|
|
9300
9174
|
// src/init/scaffolders/components.ts
|
|
9301
9175
|
import path37 from "path";
|
|
9302
|
-
import
|
|
9176
|
+
import fs33 from "fs-extra";
|
|
9303
9177
|
|
|
9304
9178
|
// src/utils/detect.ts
|
|
9305
|
-
import
|
|
9179
|
+
import fs32 from "fs";
|
|
9306
9180
|
import path36 from "path";
|
|
9307
9181
|
var NEXT_CONFIG_FILES = ["next.config.ts", "next.config.js", "next.config.mjs"];
|
|
9308
9182
|
function detectProjectName(cwd) {
|
|
9309
9183
|
const pkgPath = path36.join(cwd, "package.json");
|
|
9310
|
-
if (
|
|
9184
|
+
if (fs32.existsSync(pkgPath)) {
|
|
9311
9185
|
try {
|
|
9312
|
-
const pkg = JSON.parse(
|
|
9186
|
+
const pkg = JSON.parse(fs32.readFileSync(pkgPath, "utf-8"));
|
|
9313
9187
|
if (typeof pkg.name === "string" && pkg.name.length > 0) {
|
|
9314
9188
|
return formatProjectName(pkg.name);
|
|
9315
9189
|
}
|
|
@@ -9323,21 +9197,21 @@ function formatProjectName(name) {
|
|
|
9323
9197
|
return base.replace(/[-_]+/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()).trim();
|
|
9324
9198
|
}
|
|
9325
9199
|
function detectProject(cwd) {
|
|
9326
|
-
const isExisting = NEXT_CONFIG_FILES.some((f) =>
|
|
9327
|
-
const hasSrcDir =
|
|
9328
|
-
const hasTypeScript =
|
|
9200
|
+
const isExisting = NEXT_CONFIG_FILES.some((f) => fs32.existsSync(path36.join(cwd, f)));
|
|
9201
|
+
const hasSrcDir = fs32.existsSync(path36.join(cwd, "src"));
|
|
9202
|
+
const hasTypeScript = fs32.existsSync(path36.join(cwd, "tsconfig.json")) || fs32.existsSync(path36.join(cwd, "tsconfig.app.json"));
|
|
9329
9203
|
const hasTailwind = detectTailwind(cwd);
|
|
9330
9204
|
const linter = detectLinter(cwd);
|
|
9331
9205
|
const conflicts = [];
|
|
9332
9206
|
if (isExisting) {
|
|
9333
|
-
if (
|
|
9207
|
+
if (fs32.existsSync(path36.join(cwd, "cms"))) {
|
|
9334
9208
|
conflicts.push("cms/ directory already exists");
|
|
9335
9209
|
}
|
|
9336
|
-
if (
|
|
9210
|
+
if (fs32.existsSync(path36.join(cwd, "cms.config.ts"))) {
|
|
9337
9211
|
conflicts.push("cms.config.ts already exists");
|
|
9338
9212
|
}
|
|
9339
9213
|
const appBase = hasSrcDir ? "src/app" : "app";
|
|
9340
|
-
if (
|
|
9214
|
+
if (fs32.existsSync(path36.join(cwd, appBase, "(cms)"))) {
|
|
9341
9215
|
conflicts.push(`${appBase}/(cms)/ route group already exists`);
|
|
9342
9216
|
}
|
|
9343
9217
|
if (hasTsconfigCmsAliases(cwd)) {
|
|
@@ -9364,19 +9238,19 @@ var ESLINT_CONFIG_FILES = [
|
|
|
9364
9238
|
];
|
|
9365
9239
|
function detectLinter(cwd) {
|
|
9366
9240
|
for (const f of BIOME_CONFIG_FILES) {
|
|
9367
|
-
if (
|
|
9241
|
+
if (fs32.existsSync(path36.join(cwd, f))) {
|
|
9368
9242
|
return { type: "biome", configFile: f };
|
|
9369
9243
|
}
|
|
9370
9244
|
}
|
|
9371
9245
|
for (const f of ESLINT_CONFIG_FILES) {
|
|
9372
|
-
if (
|
|
9246
|
+
if (fs32.existsSync(path36.join(cwd, f))) {
|
|
9373
9247
|
return { type: "eslint", configFile: f };
|
|
9374
9248
|
}
|
|
9375
9249
|
}
|
|
9376
9250
|
const pkgPath = path36.join(cwd, "package.json");
|
|
9377
|
-
if (
|
|
9251
|
+
if (fs32.existsSync(pkgPath)) {
|
|
9378
9252
|
try {
|
|
9379
|
-
const pkg = JSON.parse(
|
|
9253
|
+
const pkg = JSON.parse(fs32.readFileSync(pkgPath, "utf-8"));
|
|
9380
9254
|
if (pkg.eslintConfig) {
|
|
9381
9255
|
return { type: "eslint", configFile: "package.json (eslintConfig)" };
|
|
9382
9256
|
}
|
|
@@ -9393,8 +9267,8 @@ function detectTailwind(cwd) {
|
|
|
9393
9267
|
path36.join(cwd, f)
|
|
9394
9268
|
]);
|
|
9395
9269
|
for (const cssFile of cssFiles) {
|
|
9396
|
-
if (
|
|
9397
|
-
const content =
|
|
9270
|
+
if (fs32.existsSync(cssFile)) {
|
|
9271
|
+
const content = fs32.readFileSync(cssFile, "utf-8");
|
|
9398
9272
|
if (content.includes('@import "tailwindcss"') || content.includes("@import 'tailwindcss'") || content.includes("@theme")) {
|
|
9399
9273
|
return true;
|
|
9400
9274
|
}
|
|
@@ -9402,8 +9276,8 @@ function detectTailwind(cwd) {
|
|
|
9402
9276
|
}
|
|
9403
9277
|
const postcssFiles = ["postcss.config.js", "postcss.config.mjs", "postcss.config.cjs"];
|
|
9404
9278
|
for (const f of postcssFiles) {
|
|
9405
|
-
if (
|
|
9406
|
-
const content =
|
|
9279
|
+
if (fs32.existsSync(path36.join(cwd, f))) {
|
|
9280
|
+
const content = fs32.readFileSync(path36.join(cwd, f), "utf-8");
|
|
9407
9281
|
if (content.includes("tailwindcss") || content.includes("@tailwindcss")) {
|
|
9408
9282
|
return true;
|
|
9409
9283
|
}
|
|
@@ -9413,9 +9287,9 @@ function detectTailwind(cwd) {
|
|
|
9413
9287
|
}
|
|
9414
9288
|
function hasTsconfigCmsAliases(cwd) {
|
|
9415
9289
|
const tsconfigPath = path36.join(cwd, "tsconfig.json");
|
|
9416
|
-
if (!
|
|
9290
|
+
if (!fs32.existsSync(tsconfigPath)) return false;
|
|
9417
9291
|
try {
|
|
9418
|
-
const content =
|
|
9292
|
+
const content = fs32.readFileSync(tsconfigPath, "utf-8");
|
|
9419
9293
|
return content.includes("@cms/");
|
|
9420
9294
|
} catch {
|
|
9421
9295
|
return false;
|
|
@@ -9423,9 +9297,9 @@ function hasTsconfigCmsAliases(cwd) {
|
|
|
9423
9297
|
}
|
|
9424
9298
|
function hasEnvBetterstartVars(cwd) {
|
|
9425
9299
|
const envPath = path36.join(cwd, ".env.local");
|
|
9426
|
-
if (!
|
|
9300
|
+
if (!fs32.existsSync(envPath)) return false;
|
|
9427
9301
|
try {
|
|
9428
|
-
const content =
|
|
9302
|
+
const content = fs32.readFileSync(envPath, "utf-8");
|
|
9429
9303
|
return content.includes("BETTERSTART_");
|
|
9430
9304
|
} catch {
|
|
9431
9305
|
return false;
|
|
@@ -9499,14 +9373,14 @@ function copyUiTemplates(cwd, config) {
|
|
|
9499
9373
|
const destDir = path37.resolve(cwd, config.paths.cms, "components", "ui");
|
|
9500
9374
|
const cliRoot = findCliRoot();
|
|
9501
9375
|
const srcDir = path37.join(cliRoot, "templates", "ui");
|
|
9502
|
-
if (!
|
|
9376
|
+
if (!fs33.existsSync(srcDir)) {
|
|
9503
9377
|
return created;
|
|
9504
9378
|
}
|
|
9505
|
-
const files =
|
|
9379
|
+
const files = fs33.readdirSync(srcDir).filter((f) => f.endsWith(".tsx") || f.endsWith(".ts"));
|
|
9506
9380
|
for (const file of files) {
|
|
9507
9381
|
const destPath = path37.join(destDir, file);
|
|
9508
|
-
if (!
|
|
9509
|
-
|
|
9382
|
+
if (!fs33.existsSync(destPath)) {
|
|
9383
|
+
fs33.copyFileSync(path37.join(srcDir, file), destPath);
|
|
9510
9384
|
created.push(path37.join(config.paths.cms, "components", "ui", file));
|
|
9511
9385
|
}
|
|
9512
9386
|
}
|
|
@@ -9517,22 +9391,22 @@ function copyTiptapTemplates(cwd, config) {
|
|
|
9517
9391
|
const cliRoot = findCliRoot();
|
|
9518
9392
|
const srcDir = path37.join(cliRoot, "templates", "tiptap");
|
|
9519
9393
|
const destDir = path37.resolve(cwd, config.paths.cms, "components", "ui", "tiptap");
|
|
9520
|
-
if (!
|
|
9394
|
+
if (!fs33.existsSync(srcDir)) {
|
|
9521
9395
|
return created;
|
|
9522
9396
|
}
|
|
9523
9397
|
copyDirRecursive(srcDir, destDir, config.paths.cms, created);
|
|
9524
9398
|
return created;
|
|
9525
9399
|
}
|
|
9526
9400
|
function copyDirRecursive(src, dest, cmsPrefix, created) {
|
|
9527
|
-
|
|
9528
|
-
const entries =
|
|
9401
|
+
fs33.ensureDirSync(dest);
|
|
9402
|
+
const entries = fs33.readdirSync(src, { withFileTypes: true });
|
|
9529
9403
|
for (const entry of entries) {
|
|
9530
9404
|
const srcPath = path37.join(src, entry.name);
|
|
9531
9405
|
const destPath = path37.join(dest, entry.name);
|
|
9532
9406
|
if (entry.isDirectory()) {
|
|
9533
9407
|
copyDirRecursive(srcPath, destPath, cmsPrefix, created);
|
|
9534
|
-
} else if (!
|
|
9535
|
-
|
|
9408
|
+
} else if (!fs33.existsSync(destPath)) {
|
|
9409
|
+
fs33.copyFileSync(srcPath, destPath);
|
|
9536
9410
|
const relFromCms = path37.relative(path37.resolve(dest, "..", "..", "..", ".."), destPath);
|
|
9537
9411
|
created.push(relFromCms);
|
|
9538
9412
|
}
|
|
@@ -9543,9 +9417,9 @@ function copySchemaMetaschema(cwd, config) {
|
|
|
9543
9417
|
const cliRoot = findCliRoot();
|
|
9544
9418
|
const srcPath = path37.join(cliRoot, "templates", "schema.json");
|
|
9545
9419
|
const destPath = path37.resolve(cwd, config.paths.schemas, "schema.json");
|
|
9546
|
-
if (
|
|
9547
|
-
|
|
9548
|
-
|
|
9420
|
+
if (fs33.existsSync(srcPath) && !fs33.existsSync(destPath)) {
|
|
9421
|
+
fs33.ensureDirSync(path37.dirname(destPath));
|
|
9422
|
+
fs33.copyFileSync(srcPath, destPath);
|
|
9549
9423
|
created.push(path37.join(config.paths.schemas, "schema.json"));
|
|
9550
9424
|
}
|
|
9551
9425
|
return created;
|
|
@@ -9596,7 +9470,7 @@ var CORE_DEPS = [
|
|
|
9596
9470
|
"clsx",
|
|
9597
9471
|
"tailwind-merge",
|
|
9598
9472
|
// Icons
|
|
9599
|
-
"lucide-react",
|
|
9473
|
+
"lucide-react@1.7.0",
|
|
9600
9474
|
// Storage (R2)
|
|
9601
9475
|
"@aws-sdk/client-s3",
|
|
9602
9476
|
// Radix UI (unified package + legacy scoped packages)
|
|
@@ -9738,11 +9612,11 @@ import { existsSync, readFileSync } from "fs";
|
|
|
9738
9612
|
import { join } from "path";
|
|
9739
9613
|
|
|
9740
9614
|
// src/utils/env.ts
|
|
9741
|
-
import
|
|
9615
|
+
import fs34 from "fs";
|
|
9742
9616
|
import path39 from "path";
|
|
9743
9617
|
function appendEnvVars(cwd, sections, overwrite) {
|
|
9744
9618
|
const envPath = path39.join(cwd, ".env.local");
|
|
9745
|
-
let existing =
|
|
9619
|
+
let existing = fs34.existsSync(envPath) ? fs34.readFileSync(envPath, "utf-8") : "";
|
|
9746
9620
|
const existingKeys = new Set(
|
|
9747
9621
|
existing.split("\n").filter((line) => line.trim() && !line.trim().startsWith("#")).map((line) => line.split("=")[0]?.trim()).filter(Boolean)
|
|
9748
9622
|
);
|
|
@@ -9786,7 +9660,7 @@ function appendEnvVars(cwd, sections, overwrite) {
|
|
|
9786
9660
|
const header = existing.trim() ? "" : "# ============================================\n# BetterStart CMS\n# ============================================\n";
|
|
9787
9661
|
const content = existing.trim() ? `${existing.trimEnd()}
|
|
9788
9662
|
${lines.join("\n")}` : header + lines.join("\n");
|
|
9789
|
-
|
|
9663
|
+
fs34.writeFileSync(envPath, content);
|
|
9790
9664
|
}
|
|
9791
9665
|
return { added, skipped, updated };
|
|
9792
9666
|
}
|
|
@@ -9906,7 +9780,7 @@ function scaffoldLayout({ cwd, config }) {
|
|
|
9906
9780
|
}
|
|
9907
9781
|
|
|
9908
9782
|
// src/init/scaffolders/preset.ts
|
|
9909
|
-
import
|
|
9783
|
+
import fs35 from "fs";
|
|
9910
9784
|
import path41 from "path";
|
|
9911
9785
|
|
|
9912
9786
|
// src/init/templates/presets/blog-categories.ts
|
|
@@ -10331,10 +10205,10 @@ function scaffoldPreset({
|
|
|
10331
10205
|
for (const ps of presetSchemas) {
|
|
10332
10206
|
const filePath = path41.join(schemasDir, ps.filename);
|
|
10333
10207
|
const dir = path41.dirname(filePath);
|
|
10334
|
-
if (!
|
|
10335
|
-
|
|
10208
|
+
if (!fs35.existsSync(dir)) {
|
|
10209
|
+
fs35.mkdirSync(dir, { recursive: true });
|
|
10336
10210
|
}
|
|
10337
|
-
|
|
10211
|
+
fs35.writeFileSync(filePath, ps.content, "utf-8");
|
|
10338
10212
|
result.schemas.push(ps.filename);
|
|
10339
10213
|
}
|
|
10340
10214
|
for (const ps of presetSchemas) {
|
|
@@ -10375,7 +10249,7 @@ function scaffoldPreset({
|
|
|
10375
10249
|
}
|
|
10376
10250
|
|
|
10377
10251
|
// src/init/scaffolders/tailwind.ts
|
|
10378
|
-
import
|
|
10252
|
+
import fs36 from "fs";
|
|
10379
10253
|
import path42 from "path";
|
|
10380
10254
|
var SOURCE_LINES = ['@source "../cms/**/*.{ts,tsx}";', '@source "./(cms)/**/*.{ts,tsx}";'];
|
|
10381
10255
|
var SOURCE_LINES_SRC = ['@source "../../cms/**/*.{ts,tsx}";', '@source "./(cms)/**/*.{ts,tsx}";'];
|
|
@@ -10432,7 +10306,7 @@ function findMainCss(cwd) {
|
|
|
10432
10306
|
];
|
|
10433
10307
|
for (const candidate of candidates) {
|
|
10434
10308
|
const filePath = path42.join(cwd, candidate);
|
|
10435
|
-
if (
|
|
10309
|
+
if (fs36.existsSync(filePath)) {
|
|
10436
10310
|
return filePath;
|
|
10437
10311
|
}
|
|
10438
10312
|
}
|
|
@@ -10443,7 +10317,7 @@ function scaffoldTailwind(cwd, hasSrcDir) {
|
|
|
10443
10317
|
if (!cssFile) {
|
|
10444
10318
|
return { file: null, appended: false };
|
|
10445
10319
|
}
|
|
10446
|
-
let content =
|
|
10320
|
+
let content = fs36.readFileSync(cssFile, "utf-8");
|
|
10447
10321
|
let changed = false;
|
|
10448
10322
|
const sourceLines = hasSrcDir ? SOURCE_LINES_SRC : SOURCE_LINES;
|
|
10449
10323
|
const missingLines = sourceLines.filter((sl) => !content.includes(sl));
|
|
@@ -10495,13 +10369,13 @@ ${CMS_THEME_BLOCK}
|
|
|
10495
10369
|
}
|
|
10496
10370
|
}
|
|
10497
10371
|
if (changed) {
|
|
10498
|
-
|
|
10372
|
+
fs36.writeFileSync(cssFile, content, "utf-8");
|
|
10499
10373
|
}
|
|
10500
10374
|
return { file: cssFile, appended: changed };
|
|
10501
10375
|
}
|
|
10502
10376
|
|
|
10503
10377
|
// src/init/scaffolders/tsconfig.ts
|
|
10504
|
-
import
|
|
10378
|
+
import fs37 from "fs";
|
|
10505
10379
|
import path43 from "path";
|
|
10506
10380
|
function stripJsonComments(input) {
|
|
10507
10381
|
let result = "";
|
|
@@ -10555,11 +10429,11 @@ function scaffoldTsconfig(cwd) {
|
|
|
10555
10429
|
const tsconfigPath = path43.join(cwd, "tsconfig.json");
|
|
10556
10430
|
const added = [];
|
|
10557
10431
|
const skipped = [];
|
|
10558
|
-
if (!
|
|
10432
|
+
if (!fs37.existsSync(tsconfigPath)) {
|
|
10559
10433
|
skipped.push("tsconfig.json not found");
|
|
10560
10434
|
return { added, skipped };
|
|
10561
10435
|
}
|
|
10562
|
-
const raw =
|
|
10436
|
+
const raw = fs37.readFileSync(tsconfigPath, "utf-8");
|
|
10563
10437
|
const stripped = stripJsonComments(raw).replace(/,\s*([\]}])/g, "$1");
|
|
10564
10438
|
let tsconfig;
|
|
10565
10439
|
try {
|
|
@@ -10580,13 +10454,13 @@ function scaffoldTsconfig(cwd) {
|
|
|
10580
10454
|
}
|
|
10581
10455
|
compilerOptions.paths = paths;
|
|
10582
10456
|
tsconfig.compilerOptions = compilerOptions;
|
|
10583
|
-
|
|
10457
|
+
fs37.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
|
|
10584
10458
|
`, "utf-8");
|
|
10585
10459
|
return { added, skipped };
|
|
10586
10460
|
}
|
|
10587
10461
|
|
|
10588
10462
|
// src/commands/seed.ts
|
|
10589
|
-
import
|
|
10463
|
+
import fs38 from "fs";
|
|
10590
10464
|
import path44 from "path";
|
|
10591
10465
|
import * as clack from "@clack/prompts";
|
|
10592
10466
|
import { Command as Command2 } from "commander";
|
|
@@ -10748,10 +10622,10 @@ var seedCommand = new Command2("seed").description("Create the initial admin use
|
|
|
10748
10622
|
}
|
|
10749
10623
|
const scriptsDir = path44.join(cwd, cmsDir, "scripts");
|
|
10750
10624
|
const seedPath = path44.join(scriptsDir, "seed.ts");
|
|
10751
|
-
if (!
|
|
10752
|
-
|
|
10625
|
+
if (!fs38.existsSync(scriptsDir)) {
|
|
10626
|
+
fs38.mkdirSync(scriptsDir, { recursive: true });
|
|
10753
10627
|
}
|
|
10754
|
-
|
|
10628
|
+
fs38.writeFileSync(seedPath, buildSeedScript(), "utf-8");
|
|
10755
10629
|
const { execFile } = await import("child_process");
|
|
10756
10630
|
const tsxBin = path44.join(cwd, "node_modules", ".bin", "tsx");
|
|
10757
10631
|
const runSeed2 = (overwrite) => new Promise((resolve, reject) => {
|
|
@@ -10792,7 +10666,7 @@ var seedCommand = new Command2("seed").description("Create the initial admin use
|
|
|
10792
10666
|
if (clack.isCancel(overwrite) || !overwrite) {
|
|
10793
10667
|
clack.cancel("Seed cancelled.");
|
|
10794
10668
|
try {
|
|
10795
|
-
|
|
10669
|
+
fs38.unlinkSync(seedPath);
|
|
10796
10670
|
} catch {
|
|
10797
10671
|
}
|
|
10798
10672
|
process.exit(0);
|
|
@@ -10815,9 +10689,9 @@ var seedCommand = new Command2("seed").description("Create the initial admin use
|
|
|
10815
10689
|
process.exit(1);
|
|
10816
10690
|
}
|
|
10817
10691
|
try {
|
|
10818
|
-
|
|
10819
|
-
if (
|
|
10820
|
-
|
|
10692
|
+
fs38.unlinkSync(seedPath);
|
|
10693
|
+
if (fs38.existsSync(scriptsDir) && fs38.readdirSync(scriptsDir).length === 0) {
|
|
10694
|
+
fs38.rmdirSync(scriptsDir);
|
|
10821
10695
|
}
|
|
10822
10696
|
} catch {
|
|
10823
10697
|
}
|
|
@@ -10825,7 +10699,7 @@ var seedCommand = new Command2("seed").description("Create the initial admin use
|
|
|
10825
10699
|
});
|
|
10826
10700
|
|
|
10827
10701
|
// src/commands/init.ts
|
|
10828
|
-
var initCommand = new Command3("init").description("Scaffold CMS into a new or existing Next.js project").argument("[name]", "Project name (creates new directory if fresh project)").option("--preset <preset>", "Starter preset: blank, blog, or full", "blog").option("-y, --yes", "Skip all prompts (accept defaults)").option(
|
|
10702
|
+
var initCommand = new Command3("init").description("Scaffold CMS into a new or existing Next.js project").argument("[name]", "Project name (creates new directory if fresh project)").option("--preset <preset>", "Starter preset: blank, blog, or full", "blog").option("-y, --yes", "Skip all prompts (accept defaults)").option("--skip-migration", "Skip running drizzle-kit push after scaffolding").option("--skip-admin-creation", "Skip prompting to create the initial admin user").option("--skip-dev-server-start", "Skip prompting to start the development server").option(
|
|
10829
10703
|
"--database-url <url>",
|
|
10830
10704
|
"PostgreSQL database connection string (postgres:// or postgresql://)"
|
|
10831
10705
|
).option("--force", "Overwrite all existing CMS files (nuclear option)").action(
|
|
@@ -10849,15 +10723,15 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
|
|
|
10849
10723
|
let nuked = 0;
|
|
10850
10724
|
for (const dir of nukeDirs) {
|
|
10851
10725
|
const fullPath = path45.resolve(cwd, dir);
|
|
10852
|
-
if (
|
|
10853
|
-
|
|
10726
|
+
if (fs39.existsSync(fullPath)) {
|
|
10727
|
+
fs39.rmSync(fullPath, { recursive: true, force: true });
|
|
10854
10728
|
nuked++;
|
|
10855
10729
|
}
|
|
10856
10730
|
}
|
|
10857
10731
|
for (const file of nukeFiles) {
|
|
10858
10732
|
const fullPath = path45.resolve(cwd, file);
|
|
10859
|
-
if (
|
|
10860
|
-
|
|
10733
|
+
if (fs39.existsSync(fullPath)) {
|
|
10734
|
+
fs39.unlinkSync(fullPath);
|
|
10861
10735
|
nuked++;
|
|
10862
10736
|
}
|
|
10863
10737
|
}
|
|
@@ -10937,9 +10811,9 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
|
|
|
10937
10811
|
process.exit(1);
|
|
10938
10812
|
}
|
|
10939
10813
|
cwd = path45.resolve(cwd, projectPrompt.projectName);
|
|
10940
|
-
const hasPackageJson =
|
|
10814
|
+
const hasPackageJson = fs39.existsSync(path45.join(cwd, "package.json"));
|
|
10941
10815
|
const hasNextConfig = ["next.config.ts", "next.config.js", "next.config.mjs"].some(
|
|
10942
|
-
(f) =>
|
|
10816
|
+
(f) => fs39.existsSync(path45.join(cwd, f))
|
|
10943
10817
|
);
|
|
10944
10818
|
if (!hasPackageJson || !hasNextConfig) {
|
|
10945
10819
|
p4.log.error(
|
|
@@ -11041,10 +10915,10 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
|
|
|
11041
10915
|
process.stdout.write("\x1B[2A\x1B[J");
|
|
11042
10916
|
p4.note(noteLines.join("\n"), "Scaffolded CMS");
|
|
11043
10917
|
const drizzleConfigPath = path45.join(cwd, "drizzle.config.ts");
|
|
11044
|
-
if (!dbFiles.includes("drizzle.config.ts") &&
|
|
10918
|
+
if (!dbFiles.includes("drizzle.config.ts") && fs39.existsSync(drizzleConfigPath)) {
|
|
11045
10919
|
if (options.force) {
|
|
11046
10920
|
const { readTemplate: readTemplate2 } = await import("./reader-2T45D7JZ.js");
|
|
11047
|
-
|
|
10921
|
+
fs39.writeFileSync(drizzleConfigPath, readTemplate2("drizzle.config.ts"), "utf-8");
|
|
11048
10922
|
p4.log.success("Updated drizzle.config.ts");
|
|
11049
10923
|
} else if (!options.yes) {
|
|
11050
10924
|
const overwrite = await p4.confirm({
|
|
@@ -11053,7 +10927,7 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
|
|
|
11053
10927
|
});
|
|
11054
10928
|
if (!p4.isCancel(overwrite) && overwrite) {
|
|
11055
10929
|
const { readTemplate: readTemplate2 } = await import("./reader-2T45D7JZ.js");
|
|
11056
|
-
|
|
10930
|
+
fs39.writeFileSync(drizzleConfigPath, readTemplate2("drizzle.config.ts"), "utf-8");
|
|
11057
10931
|
p4.log.success("Updated drizzle.config.ts");
|
|
11058
10932
|
}
|
|
11059
10933
|
}
|
|
@@ -11083,27 +10957,6 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
|
|
|
11083
10957
|
}
|
|
11084
10958
|
s.start(`Applying ${features.preset} preset`);
|
|
11085
10959
|
const presetResult = scaffoldPreset({ cwd, config, preset: features.preset });
|
|
11086
|
-
{
|
|
11087
|
-
const entityNames = [];
|
|
11088
|
-
const formNames = [];
|
|
11089
|
-
const schemasDir = path45.join(cwd, config.paths.schemas);
|
|
11090
|
-
const formsDir = path45.join(schemasDir, "forms");
|
|
11091
|
-
if (fs40.existsSync(schemasDir)) {
|
|
11092
|
-
for (const f of fs40.readdirSync(schemasDir)) {
|
|
11093
|
-
if (f.endsWith(".json")) entityNames.push(f.replace(".json", ""));
|
|
11094
|
-
}
|
|
11095
|
-
}
|
|
11096
|
-
if (fs40.existsSync(formsDir)) {
|
|
11097
|
-
for (const f of fs40.readdirSync(formsDir)) {
|
|
11098
|
-
if (f.endsWith(".json")) formNames.push(f.replace(".json", ""));
|
|
11099
|
-
}
|
|
11100
|
-
}
|
|
11101
|
-
regenerateCmsDoc(cwd, config, {
|
|
11102
|
-
preset: features.preset,
|
|
11103
|
-
schemas: entityNames,
|
|
11104
|
-
forms: formNames
|
|
11105
|
-
});
|
|
11106
|
-
}
|
|
11107
10960
|
s.stop("");
|
|
11108
10961
|
process.stdout.write("\x1B[2A\x1B[J");
|
|
11109
10962
|
const installLines = [];
|
|
@@ -11126,7 +10979,9 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
|
|
|
11126
10979
|
}
|
|
11127
10980
|
p4.note(installLines.join("\n"), "Installed");
|
|
11128
10981
|
let dbPushed = false;
|
|
11129
|
-
if (depsResult.success && hasDbUrl(cwd)) {
|
|
10982
|
+
if (depsResult.success && options.skipMigration && hasDbUrl(cwd)) {
|
|
10983
|
+
p4.log.info(`Skipping database schema push ${pc2.dim("(--skip-migration)")}`);
|
|
10984
|
+
} else if (depsResult.success && hasDbUrl(cwd)) {
|
|
11130
10985
|
s.start("Pushing database schema (drizzle-kit push)");
|
|
11131
10986
|
const pushResult = await runDrizzlePush(cwd);
|
|
11132
10987
|
if (pushResult.success) {
|
|
@@ -11141,7 +10996,10 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
|
|
|
11141
10996
|
let seedEmail;
|
|
11142
10997
|
let seedPassword;
|
|
11143
10998
|
let seedSuccess = false;
|
|
11144
|
-
if (dbPushed &&
|
|
10999
|
+
if (dbPushed && options.skipAdminCreation) {
|
|
11000
|
+
p4.log.info(`Skipping admin user creation ${pc2.dim("(use npx betterstart seed later)")}`);
|
|
11001
|
+
}
|
|
11002
|
+
if (dbPushed && !options.yes && !options.skipAdminCreation) {
|
|
11145
11003
|
p4.note(pc2.dim("Create your first admin user to access the CMS."), "Admin account");
|
|
11146
11004
|
const credentials = await p4.group(
|
|
11147
11005
|
{
|
|
@@ -11253,7 +11111,7 @@ Run manually: ${pc2.cyan("npx betterstart seed")}`,
|
|
|
11253
11111
|
);
|
|
11254
11112
|
summaryLines.push("", "Next steps:", ...nextSteps);
|
|
11255
11113
|
p4.note(summaryLines.join("\n"), "CMS scaffolded successfully");
|
|
11256
|
-
if (!options.yes) {
|
|
11114
|
+
if (!options.yes && !options.skipDevServerStart) {
|
|
11257
11115
|
const devCmd = runCommand(pm, "dev");
|
|
11258
11116
|
const startDev = await p4.confirm({
|
|
11259
11117
|
message: "Start the development server?",
|
|
@@ -11274,8 +11132,8 @@ function isValidDbUrl(url) {
|
|
|
11274
11132
|
}
|
|
11275
11133
|
function readExistingDbUrl(cwd) {
|
|
11276
11134
|
const envPath = path45.join(cwd, ".env.local");
|
|
11277
|
-
if (!
|
|
11278
|
-
const content =
|
|
11135
|
+
if (!fs39.existsSync(envPath)) return void 0;
|
|
11136
|
+
const content = fs39.readFileSync(envPath, "utf-8");
|
|
11279
11137
|
for (const line of content.split("\n")) {
|
|
11280
11138
|
const trimmed = line.trim();
|
|
11281
11139
|
if (trimmed.startsWith("#") || !trimmed.includes("=")) continue;
|
|
@@ -11299,8 +11157,8 @@ function maskDbUrl(url) {
|
|
|
11299
11157
|
}
|
|
11300
11158
|
function hasDbUrl(cwd) {
|
|
11301
11159
|
const envPath = path45.join(cwd, ".env.local");
|
|
11302
|
-
if (!
|
|
11303
|
-
const content =
|
|
11160
|
+
if (!fs39.existsSync(envPath)) return false;
|
|
11161
|
+
const content = fs39.readFileSync(envPath, "utf-8");
|
|
11304
11162
|
for (const line of content.split("\n")) {
|
|
11305
11163
|
const trimmed = line.trim();
|
|
11306
11164
|
if (trimmed.startsWith("#") || !trimmed.includes("=")) continue;
|
|
@@ -11316,15 +11174,15 @@ function hasDbUrl(cwd) {
|
|
|
11316
11174
|
function runSeed(cwd, cmsDir, email, password4, overwrite = false) {
|
|
11317
11175
|
const scriptsDir = path45.join(cwd, cmsDir, "scripts");
|
|
11318
11176
|
const seedPath = path45.join(scriptsDir, "seed.ts");
|
|
11319
|
-
if (!
|
|
11320
|
-
|
|
11177
|
+
if (!fs39.existsSync(scriptsDir)) {
|
|
11178
|
+
fs39.mkdirSync(scriptsDir, { recursive: true });
|
|
11321
11179
|
}
|
|
11322
|
-
|
|
11180
|
+
fs39.writeFileSync(seedPath, buildSeedScript(), "utf-8");
|
|
11323
11181
|
const cleanup = () => {
|
|
11324
11182
|
try {
|
|
11325
|
-
|
|
11326
|
-
if (
|
|
11327
|
-
|
|
11183
|
+
fs39.unlinkSync(seedPath);
|
|
11184
|
+
if (fs39.existsSync(scriptsDir) && fs39.readdirSync(scriptsDir).length === 0) {
|
|
11185
|
+
fs39.rmdirSync(scriptsDir);
|
|
11328
11186
|
}
|
|
11329
11187
|
} catch {
|
|
11330
11188
|
}
|
|
@@ -11416,7 +11274,7 @@ function runDrizzlePush(cwd) {
|
|
|
11416
11274
|
}
|
|
11417
11275
|
|
|
11418
11276
|
// src/commands/remove.ts
|
|
11419
|
-
import
|
|
11277
|
+
import fs40 from "fs";
|
|
11420
11278
|
import path46 from "path";
|
|
11421
11279
|
import readline from "readline";
|
|
11422
11280
|
import { Command as Command4 } from "commander";
|
|
@@ -11448,8 +11306,8 @@ function findTableEnd3(content, startIndex) {
|
|
|
11448
11306
|
return content.length;
|
|
11449
11307
|
}
|
|
11450
11308
|
function removeTableFromSchema(schemaFilePath, name) {
|
|
11451
|
-
if (!
|
|
11452
|
-
let content =
|
|
11309
|
+
if (!fs40.existsSync(schemaFilePath)) return false;
|
|
11310
|
+
let content = fs40.readFileSync(schemaFilePath, "utf-8");
|
|
11453
11311
|
const variableName = toCamelCase(name);
|
|
11454
11312
|
let changed = false;
|
|
11455
11313
|
if (content.includes(`export const ${variableName} =`)) {
|
|
@@ -11477,13 +11335,13 @@ function removeTableFromSchema(schemaFilePath, name) {
|
|
|
11477
11335
|
}
|
|
11478
11336
|
if (changed) {
|
|
11479
11337
|
content = content.replace(/\n{3,}/g, "\n\n");
|
|
11480
|
-
|
|
11338
|
+
fs40.writeFileSync(schemaFilePath, content, "utf-8");
|
|
11481
11339
|
}
|
|
11482
11340
|
return changed;
|
|
11483
11341
|
}
|
|
11484
11342
|
function removeFromNavigation(navFilePath, name) {
|
|
11485
|
-
if (!
|
|
11486
|
-
const content =
|
|
11343
|
+
if (!fs40.existsSync(navFilePath)) return false;
|
|
11344
|
+
const content = fs40.readFileSync(navFilePath, "utf-8");
|
|
11487
11345
|
const href = `/cms/${name}`;
|
|
11488
11346
|
if (!content.includes(`'${href}'`)) return false;
|
|
11489
11347
|
const lines = content.split("\n");
|
|
@@ -11514,7 +11372,7 @@ function removeFromNavigation(navFilePath, name) {
|
|
|
11514
11372
|
if (startLine === -1 || endLine === -1) return false;
|
|
11515
11373
|
lines.splice(startLine, endLine - startLine + 1);
|
|
11516
11374
|
const updated = lines.join("\n").replace(/,\s*,/g, ",").replace(/\[\s*,/, "[");
|
|
11517
|
-
|
|
11375
|
+
fs40.writeFileSync(navFilePath, updated, "utf-8");
|
|
11518
11376
|
return true;
|
|
11519
11377
|
}
|
|
11520
11378
|
async function promptConfirm(message) {
|
|
@@ -11544,7 +11402,7 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
|
|
|
11544
11402
|
const kebabName = toKebabCase(schemaName);
|
|
11545
11403
|
const targets = [];
|
|
11546
11404
|
const entityPagesDir = path46.join(cwd, pagesDir, schemaName);
|
|
11547
|
-
if (
|
|
11405
|
+
if (fs40.existsSync(entityPagesDir)) {
|
|
11548
11406
|
targets.push({
|
|
11549
11407
|
path: entityPagesDir,
|
|
11550
11408
|
label: `${path46.join(pagesDir, schemaName)}/`,
|
|
@@ -11553,13 +11411,13 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
|
|
|
11553
11411
|
}
|
|
11554
11412
|
const actionsDir = path46.join(cwd, cmsDir, "lib", "actions", kebabName);
|
|
11555
11413
|
const actionsFile = path46.join(cwd, cmsDir, "lib", "actions", `${kebabName}.ts`);
|
|
11556
|
-
if (
|
|
11414
|
+
if (fs40.existsSync(actionsDir)) {
|
|
11557
11415
|
targets.push({
|
|
11558
11416
|
path: actionsDir,
|
|
11559
11417
|
label: `${path46.join(cmsDir, "lib", "actions", kebabName)}/`,
|
|
11560
11418
|
isDir: true
|
|
11561
11419
|
});
|
|
11562
|
-
} else if (
|
|
11420
|
+
} else if (fs40.existsSync(actionsFile)) {
|
|
11563
11421
|
targets.push({
|
|
11564
11422
|
path: actionsFile,
|
|
11565
11423
|
label: path46.join(cmsDir, "lib", "actions", `${kebabName}.ts`),
|
|
@@ -11567,7 +11425,7 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
|
|
|
11567
11425
|
});
|
|
11568
11426
|
}
|
|
11569
11427
|
const hookFile = path46.join(cwd, cmsDir, "hooks", `use-${kebabName}.ts`);
|
|
11570
|
-
if (
|
|
11428
|
+
if (fs40.existsSync(hookFile)) {
|
|
11571
11429
|
targets.push({
|
|
11572
11430
|
path: hookFile,
|
|
11573
11431
|
label: path46.join(cmsDir, "hooks", `use-${kebabName}.ts`),
|
|
@@ -11575,9 +11433,9 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
|
|
|
11575
11433
|
});
|
|
11576
11434
|
}
|
|
11577
11435
|
const schemaFilePath = path46.join(cwd, cmsDir, "db", "schema.ts");
|
|
11578
|
-
const hasTable =
|
|
11436
|
+
const hasTable = fs40.existsSync(schemaFilePath) && fs40.readFileSync(schemaFilePath, "utf-8").includes(`export const ${toCamelCase(schemaName)} =`);
|
|
11579
11437
|
const navFilePath = path46.join(cwd, cmsDir, "data", "navigation.ts");
|
|
11580
|
-
const hasNavEntry =
|
|
11438
|
+
const hasNavEntry = fs40.existsSync(navFilePath) && fs40.readFileSync(navFilePath, "utf-8").includes(`'/cms/${schemaName}'`);
|
|
11581
11439
|
if (targets.length === 0 && !hasTable && !hasNavEntry) {
|
|
11582
11440
|
console.log(` No generated files found for: ${schemaName}`);
|
|
11583
11441
|
return;
|
|
@@ -11603,9 +11461,9 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
|
|
|
11603
11461
|
console.log("");
|
|
11604
11462
|
for (const t of targets) {
|
|
11605
11463
|
if (t.isDir) {
|
|
11606
|
-
|
|
11464
|
+
fs40.rmSync(t.path, { recursive: true, force: true });
|
|
11607
11465
|
} else {
|
|
11608
|
-
|
|
11466
|
+
fs40.unlinkSync(t.path);
|
|
11609
11467
|
}
|
|
11610
11468
|
console.log(` Removed: ${t.label}`);
|
|
11611
11469
|
}
|
|
@@ -11627,7 +11485,7 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
|
|
|
11627
11485
|
|
|
11628
11486
|
// src/commands/setup-r2.ts
|
|
11629
11487
|
import { execFileSync as execFileSync5, spawnSync } from "child_process";
|
|
11630
|
-
import
|
|
11488
|
+
import fs41 from "fs";
|
|
11631
11489
|
import os from "os";
|
|
11632
11490
|
import path47 from "path";
|
|
11633
11491
|
import * as p5 from "@clack/prompts";
|
|
@@ -11827,7 +11685,7 @@ var setupR2Command = new Command5("setup-r2").description("Create a Cloudflare R
|
|
|
11827
11685
|
});
|
|
11828
11686
|
function findWrangler(cwd) {
|
|
11829
11687
|
const localBin = path47.join(cwd, "node_modules", ".bin", "wrangler");
|
|
11830
|
-
if (
|
|
11688
|
+
if (fs41.existsSync(localBin)) return { bin: localBin, prefix: [] };
|
|
11831
11689
|
const result = spawnSync("which", ["wrangler"], { stdio: "pipe", timeout: 5e3 });
|
|
11832
11690
|
if (result.status === 0) {
|
|
11833
11691
|
const found = result.stdout?.toString().trim();
|
|
@@ -11875,9 +11733,9 @@ function readWranglerToken() {
|
|
|
11875
11733
|
);
|
|
11876
11734
|
}
|
|
11877
11735
|
for (const configPath of candidates) {
|
|
11878
|
-
if (!
|
|
11736
|
+
if (!fs41.existsSync(configPath)) continue;
|
|
11879
11737
|
try {
|
|
11880
|
-
const content =
|
|
11738
|
+
const content = fs41.readFileSync(configPath, "utf-8");
|
|
11881
11739
|
const match = content.match(/^oauth_token\s*=\s*"([^"]+)"/m);
|
|
11882
11740
|
if (match) return match[1];
|
|
11883
11741
|
} catch {
|
|
@@ -11909,14 +11767,14 @@ async function enablePublicDomain(accountId, bucketName, token) {
|
|
|
11909
11767
|
}
|
|
11910
11768
|
|
|
11911
11769
|
// src/commands/uninstall.ts
|
|
11912
|
-
import
|
|
11770
|
+
import fs43 from "fs";
|
|
11913
11771
|
import path48 from "path";
|
|
11914
11772
|
import * as p6 from "@clack/prompts";
|
|
11915
11773
|
import { Command as Command6 } from "commander";
|
|
11916
11774
|
import pc4 from "picocolors";
|
|
11917
11775
|
|
|
11918
11776
|
// src/commands/uninstall-cleaners.ts
|
|
11919
|
-
import
|
|
11777
|
+
import fs42 from "fs";
|
|
11920
11778
|
function stripJsonComments2(input) {
|
|
11921
11779
|
let result = "";
|
|
11922
11780
|
let i = 0;
|
|
@@ -11950,8 +11808,8 @@ function stripJsonComments2(input) {
|
|
|
11950
11808
|
return result;
|
|
11951
11809
|
}
|
|
11952
11810
|
function cleanTsconfig(tsconfigPath) {
|
|
11953
|
-
if (!
|
|
11954
|
-
const raw =
|
|
11811
|
+
if (!fs42.existsSync(tsconfigPath)) return [];
|
|
11812
|
+
const raw = fs42.readFileSync(tsconfigPath, "utf-8");
|
|
11955
11813
|
const stripped = stripJsonComments2(raw).replace(/,\s*([\]}])/g, "$1");
|
|
11956
11814
|
let tsconfig;
|
|
11957
11815
|
try {
|
|
@@ -11975,13 +11833,13 @@ function cleanTsconfig(tsconfigPath) {
|
|
|
11975
11833
|
compilerOptions.paths = paths;
|
|
11976
11834
|
}
|
|
11977
11835
|
tsconfig.compilerOptions = compilerOptions;
|
|
11978
|
-
|
|
11836
|
+
fs42.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
|
|
11979
11837
|
`, "utf-8");
|
|
11980
11838
|
return removed;
|
|
11981
11839
|
}
|
|
11982
11840
|
function cleanCss(cssPath) {
|
|
11983
|
-
if (!
|
|
11984
|
-
const content =
|
|
11841
|
+
if (!fs42.existsSync(cssPath)) return [];
|
|
11842
|
+
const content = fs42.readFileSync(cssPath, "utf-8");
|
|
11985
11843
|
const lines = content.split("\n");
|
|
11986
11844
|
const sourcePattern = /^@source\s+"[^"]*cms[^"]*";\s*$/;
|
|
11987
11845
|
const removed = [];
|
|
@@ -11995,12 +11853,12 @@ function cleanCss(cssPath) {
|
|
|
11995
11853
|
}
|
|
11996
11854
|
if (removed.length === 0) return [];
|
|
11997
11855
|
const cleaned = kept.join("\n").replace(/\n{3,}/g, "\n\n");
|
|
11998
|
-
|
|
11856
|
+
fs42.writeFileSync(cssPath, cleaned, "utf-8");
|
|
11999
11857
|
return removed;
|
|
12000
11858
|
}
|
|
12001
11859
|
function cleanEnvFile(envPath) {
|
|
12002
|
-
if (!
|
|
12003
|
-
const content =
|
|
11860
|
+
if (!fs42.existsSync(envPath)) return [];
|
|
11861
|
+
const content = fs42.readFileSync(envPath, "utf-8");
|
|
12004
11862
|
const lines = content.split("\n");
|
|
12005
11863
|
const removed = [];
|
|
12006
11864
|
const kept = [];
|
|
@@ -12033,9 +11891,9 @@ function cleanEnvFile(envPath) {
|
|
|
12033
11891
|
if (removed.length === 0) return [];
|
|
12034
11892
|
const result = kept.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
12035
11893
|
if (result === "") {
|
|
12036
|
-
|
|
11894
|
+
fs42.unlinkSync(envPath);
|
|
12037
11895
|
} else {
|
|
12038
|
-
|
|
11896
|
+
fs42.writeFileSync(envPath, `${result}
|
|
12039
11897
|
`, "utf-8");
|
|
12040
11898
|
}
|
|
12041
11899
|
return removed;
|
|
@@ -12062,14 +11920,14 @@ function findMainCss2(cwd) {
|
|
|
12062
11920
|
];
|
|
12063
11921
|
for (const candidate of candidates) {
|
|
12064
11922
|
const filePath = path48.join(cwd, candidate);
|
|
12065
|
-
if (
|
|
11923
|
+
if (fs43.existsSync(filePath)) return filePath;
|
|
12066
11924
|
}
|
|
12067
11925
|
return void 0;
|
|
12068
11926
|
}
|
|
12069
11927
|
function isCLICreatedBiome(biomePath) {
|
|
12070
|
-
if (!
|
|
11928
|
+
if (!fs43.existsSync(biomePath)) return false;
|
|
12071
11929
|
try {
|
|
12072
|
-
const content = JSON.parse(
|
|
11930
|
+
const content = JSON.parse(fs43.readFileSync(biomePath, "utf-8"));
|
|
12073
11931
|
return content.$schema?.includes("biomejs.dev") && content.formatter?.indentStyle === "space" && content.javascript?.formatter?.quoteStyle === "single" && Array.isArray(content.files?.ignore) && content.files.ignore.includes(".next");
|
|
12074
11932
|
} catch {
|
|
12075
11933
|
return false;
|
|
@@ -12077,13 +11935,13 @@ function isCLICreatedBiome(biomePath) {
|
|
|
12077
11935
|
}
|
|
12078
11936
|
function buildUninstallPlan(cwd) {
|
|
12079
11937
|
const steps = [];
|
|
12080
|
-
const hasSrc =
|
|
11938
|
+
const hasSrc = fs43.existsSync(path48.join(cwd, "src"));
|
|
12081
11939
|
const appBase = hasSrc ? "src/app" : "app";
|
|
12082
11940
|
const dirs = [];
|
|
12083
11941
|
const cmsDir = path48.join(cwd, "cms");
|
|
12084
11942
|
const cmsRouteGroup = path48.join(cwd, appBase, "(cms)");
|
|
12085
|
-
if (
|
|
12086
|
-
if (
|
|
11943
|
+
if (fs43.existsSync(cmsDir)) dirs.push("cms/");
|
|
11944
|
+
if (fs43.existsSync(cmsRouteGroup)) dirs.push(`${appBase}/(cms)/`);
|
|
12087
11945
|
if (dirs.length > 0) {
|
|
12088
11946
|
steps.push({
|
|
12089
11947
|
label: "CMS directories",
|
|
@@ -12091,8 +11949,8 @@ function buildUninstallPlan(cwd) {
|
|
|
12091
11949
|
count: dirs.length,
|
|
12092
11950
|
unit: dirs.length === 1 ? "directory" : "directories",
|
|
12093
11951
|
execute() {
|
|
12094
|
-
if (
|
|
12095
|
-
if (
|
|
11952
|
+
if (fs43.existsSync(cmsDir)) fs43.rmSync(cmsDir, { recursive: true, force: true });
|
|
11953
|
+
if (fs43.existsSync(cmsRouteGroup)) fs43.rmSync(cmsRouteGroup, { recursive: true, force: true });
|
|
12096
11954
|
}
|
|
12097
11955
|
});
|
|
12098
11956
|
}
|
|
@@ -12104,7 +11962,7 @@ function buildUninstallPlan(cwd) {
|
|
|
12104
11962
|
["CMS.md", path48.join(cwd, "CMS.md")]
|
|
12105
11963
|
];
|
|
12106
11964
|
for (const [label, fullPath] of candidates) {
|
|
12107
|
-
if (
|
|
11965
|
+
if (fs43.existsSync(fullPath)) {
|
|
12108
11966
|
configFiles.push(label);
|
|
12109
11967
|
configPaths.push(fullPath);
|
|
12110
11968
|
}
|
|
@@ -12122,14 +11980,14 @@ function buildUninstallPlan(cwd) {
|
|
|
12122
11980
|
unit: configFiles.length === 1 ? "file" : "files",
|
|
12123
11981
|
execute() {
|
|
12124
11982
|
for (const p7 of configPaths) {
|
|
12125
|
-
if (
|
|
11983
|
+
if (fs43.existsSync(p7)) fs43.unlinkSync(p7);
|
|
12126
11984
|
}
|
|
12127
11985
|
}
|
|
12128
11986
|
});
|
|
12129
11987
|
}
|
|
12130
11988
|
const tsconfigPath = path48.join(cwd, "tsconfig.json");
|
|
12131
|
-
if (
|
|
12132
|
-
const content =
|
|
11989
|
+
if (fs43.existsSync(tsconfigPath)) {
|
|
11990
|
+
const content = fs43.readFileSync(tsconfigPath, "utf-8");
|
|
12133
11991
|
const aliasMatches = content.match(/"@cms\//g);
|
|
12134
11992
|
if (aliasMatches && aliasMatches.length > 0) {
|
|
12135
11993
|
const aliasCount = aliasMatches.length;
|
|
@@ -12146,7 +12004,7 @@ function buildUninstallPlan(cwd) {
|
|
|
12146
12004
|
}
|
|
12147
12005
|
const cssFile = findMainCss2(cwd);
|
|
12148
12006
|
if (cssFile) {
|
|
12149
|
-
const cssContent =
|
|
12007
|
+
const cssContent = fs43.readFileSync(cssFile, "utf-8");
|
|
12150
12008
|
const sourceLines = cssContent.split("\n").filter((l) => /^@source\s+"[^"]*cms[^"]*";\s*$/.test(l));
|
|
12151
12009
|
if (sourceLines.length > 0) {
|
|
12152
12010
|
const relCss = path48.relative(cwd, cssFile);
|
|
@@ -12162,8 +12020,8 @@ function buildUninstallPlan(cwd) {
|
|
|
12162
12020
|
}
|
|
12163
12021
|
}
|
|
12164
12022
|
const envPath = path48.join(cwd, ".env.local");
|
|
12165
|
-
if (
|
|
12166
|
-
const envContent =
|
|
12023
|
+
if (fs43.existsSync(envPath)) {
|
|
12024
|
+
const envContent = fs43.readFileSync(envPath, "utf-8");
|
|
12167
12025
|
const bsVars = envContent.split("\n").filter((l) => l.trim().match(/^BETTERSTART_\w+=/)).map((l) => l.split("=")[0]);
|
|
12168
12026
|
if (bsVars.length > 0) {
|
|
12169
12027
|
steps.push({
|
|
@@ -12217,7 +12075,7 @@ var uninstallCommand = new Command6("uninstall").description("Remove all CMS fil
|
|
|
12217
12075
|
});
|
|
12218
12076
|
|
|
12219
12077
|
// src/commands/update-component.ts
|
|
12220
|
-
import
|
|
12078
|
+
import fs44 from "fs";
|
|
12221
12079
|
import path49 from "path";
|
|
12222
12080
|
import * as clack2 from "@clack/prompts";
|
|
12223
12081
|
import { Command as Command7 } from "commander";
|
|
@@ -12284,8 +12142,8 @@ var TEMPLATE_REGISTRY = {
|
|
|
12284
12142
|
function getStaticUiComponents() {
|
|
12285
12143
|
const cliRoot = findCliRoot();
|
|
12286
12144
|
const uiDir = path49.join(cliRoot, "templates", "ui");
|
|
12287
|
-
if (!
|
|
12288
|
-
return
|
|
12145
|
+
if (!fs44.existsSync(uiDir)) return [];
|
|
12146
|
+
return fs44.readdirSync(uiDir).filter((f) => f.endsWith(".tsx") || f.endsWith(".ts")).map((f) => f.replace(/\.(tsx|ts)$/, ""));
|
|
12289
12147
|
}
|
|
12290
12148
|
function getAllComponentNames() {
|
|
12291
12149
|
const staticUi = getStaticUiComponents();
|
|
@@ -12329,7 +12187,7 @@ var updateComponentCommand = new Command7("update").alias("update-component").de
|
|
|
12329
12187
|
}
|
|
12330
12188
|
const config = await resolveConfig(cwd);
|
|
12331
12189
|
const cms = path49.resolve(cwd, config.paths.cms);
|
|
12332
|
-
if (!
|
|
12190
|
+
if (!fs44.existsSync(cms)) {
|
|
12333
12191
|
clack2.cancel(`CMS directory not found at ${config.paths.cms}. Run 'betterstart init' first.`);
|
|
12334
12192
|
process.exit(1);
|
|
12335
12193
|
}
|
|
@@ -12345,18 +12203,18 @@ var updateComponentCommand = new Command7("update").alias("update-component").de
|
|
|
12345
12203
|
const baseDir = entry.base === "cwd" ? cwd : cms;
|
|
12346
12204
|
const destPath = path49.join(baseDir, entry.relPath);
|
|
12347
12205
|
fsExtra.ensureDirSync(path49.dirname(destPath));
|
|
12348
|
-
|
|
12206
|
+
fs44.writeFileSync(destPath, entry.content(), "utf-8");
|
|
12349
12207
|
clack2.log.success(`Updated ${entry.relPath}`);
|
|
12350
12208
|
updated++;
|
|
12351
12209
|
continue;
|
|
12352
12210
|
}
|
|
12353
|
-
const uiFile =
|
|
12211
|
+
const uiFile = fs44.readdirSync(uiDir).find(
|
|
12354
12212
|
(f) => f.replace(/\.(tsx|ts)$/, "") === name
|
|
12355
12213
|
);
|
|
12356
12214
|
if (uiFile) {
|
|
12357
12215
|
const destPath = path49.join(cms, "components", "ui", uiFile);
|
|
12358
12216
|
fsExtra.ensureDirSync(path49.dirname(destPath));
|
|
12359
|
-
|
|
12217
|
+
fs44.copyFileSync(path49.join(uiDir, uiFile), destPath);
|
|
12360
12218
|
clack2.log.success(`Updated components/ui/${uiFile}`);
|
|
12361
12219
|
updated++;
|
|
12362
12220
|
continue;
|
|
@@ -12364,7 +12222,7 @@ var updateComponentCommand = new Command7("update").alias("update-component").de
|
|
|
12364
12222
|
if (name === "tiptap") {
|
|
12365
12223
|
const srcDir = path49.join(cliRoot, "templates", "tiptap");
|
|
12366
12224
|
const destDir = path49.join(cms, "components", "ui", "tiptap");
|
|
12367
|
-
if (
|
|
12225
|
+
if (fs44.existsSync(srcDir)) {
|
|
12368
12226
|
fsExtra.copySync(srcDir, destDir, { overwrite: true });
|
|
12369
12227
|
clack2.log.success("Updated components/ui/tiptap/ (all files)");
|
|
12370
12228
|
updated++;
|
|
@@ -12410,7 +12268,7 @@ var updateDepsCommand = new Command8("update-deps").description("Install or upda
|
|
|
12410
12268
|
});
|
|
12411
12269
|
|
|
12412
12270
|
// src/commands/update-styles.ts
|
|
12413
|
-
import
|
|
12271
|
+
import fs45 from "fs";
|
|
12414
12272
|
import path51 from "path";
|
|
12415
12273
|
import * as clack4 from "@clack/prompts";
|
|
12416
12274
|
import { Command as Command9 } from "commander";
|
|
@@ -12420,11 +12278,11 @@ var updateStylesCommand = new Command9("update-styles").description("Replace cms
|
|
|
12420
12278
|
const config = await resolveConfig(cwd);
|
|
12421
12279
|
const cmsDir = config.paths?.cms ?? "./cms";
|
|
12422
12280
|
const targetPath = path51.join(cwd, cmsDir, "cms-globals.css");
|
|
12423
|
-
if (!
|
|
12281
|
+
if (!fs45.existsSync(targetPath)) {
|
|
12424
12282
|
clack4.cancel(`cms-globals.css not found at ${path51.relative(cwd, targetPath)}`);
|
|
12425
12283
|
process.exit(1);
|
|
12426
12284
|
}
|
|
12427
|
-
|
|
12285
|
+
fs45.writeFileSync(targetPath, readTemplate("cms-globals.css"), "utf-8");
|
|
12428
12286
|
clack4.log.success(`Updated ${path51.relative(cwd, targetPath)}`);
|
|
12429
12287
|
clack4.outro("Styles updated");
|
|
12430
12288
|
});
|