@betterstart/cli 0.1.81 → 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.
Files changed (33) hide show
  1. package/dist/cli.js +176 -305
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/init/components/data-table/data-table.tsx +1 -1
  5. package/templates/init/components/layout/cms-search.tsx +6 -5
  6. package/templates/init/components/layout/cms-sidebar.tsx +3 -7
  7. package/templates/init/components/shared/page-header.tsx +5 -5
  8. package/templates/init/data/navigation.ts +6 -6
  9. package/templates/init/lib/actions/profile.ts +4 -0
  10. package/templates/init/lib/auth/auth.ts +17 -0
  11. package/templates/init/pages/dashboard-page.tsx +1 -1
  12. package/templates/init/pages/forgot-password-form.tsx +130 -0
  13. package/templates/init/pages/forgot-password-page.tsx +20 -0
  14. package/templates/init/pages/login-form.tsx +17 -1
  15. package/templates/init/pages/login-page.tsx +12 -2
  16. package/templates/init/pages/profile/profile-form.tsx +65 -137
  17. package/templates/init/pages/reset-password-form.tsx +159 -0
  18. package/templates/init/pages/reset-password-page.tsx +20 -0
  19. package/templates/init/pages/users/columns.tsx +13 -10
  20. package/templates/init/pages/users/users-page-content.tsx +9 -2
  21. package/templates/init/pages/users/users-page.tsx +1 -1
  22. package/templates/init/pages/users/users-table.tsx +2 -2
  23. package/templates/ui/badge.tsx +2 -2
  24. package/templates/ui/button.tsx +2 -2
  25. package/templates/ui/card.tsx +2 -2
  26. package/templates/ui/curriculum-editor.tsx +2 -2
  27. package/templates/ui/image-upload-field.tsx +2 -2
  28. package/templates/ui/input.tsx +5 -4
  29. package/templates/ui/media-upload-field.tsx +2 -2
  30. package/templates/ui/placeholder.tsx +1 -1
  31. package/templates/ui/sidebar.tsx +3 -3
  32. package/templates/ui/table.tsx +10 -4
  33. package/templates/ui/video-upload-field.tsx +2 -2
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-4" />
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-4" />
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-4" />
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-4" />
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
  `;
@@ -6064,7 +6064,7 @@ ${indent} key={item.id}
6064
6064
  ${indent} value={\`item-\${index + 1}\`}
6065
6065
  ${indent} className="p-0 border-none"
6066
6066
  ${indent} >
6067
- ${indent} <div className="space-y-5 rounded-lg border p-4 bg-secondary/50 [&_h3]:m-0 w-full">
6067
+ ${indent} <div className="space-y-5 rounded-lg border p-4 bg-background [&_h3]:m-0 w-full">
6068
6068
  ${indent} <AccordionTrigger className="flex items-center p-0 justify-between w-full">
6069
6069
  ${indent} <h4 className="text-sm font-medium w-full">
6070
6070
  ${indent} ${accordionTitle}
@@ -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>
@@ -7804,7 +7804,7 @@ ${filterLogic}` : ""}`;
7804
7804
  name="search"
7805
7805
  placeholder="Search ${schema.label.toLowerCase()}..."
7806
7806
  defaultValue={search}
7807
- className="w-64 pl-9 bg-white rounded-lg"
7807
+ className="w-64 pl-9 bg-white"
7808
7808
  />
7809
7809
  <CornerDownLeft className="text-muted-foreground/70 pointer-events-none absolute top-1/2 right-3 size-4 -translate-y-1/2" />
7810
7810
  </form>`;
@@ -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 className="bg-secondary">
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 fs40 from "fs";
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 fs32 from "fs";
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 (fs32.existsSync(configPath)) {
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
- fs32.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
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 fs34 from "fs-extra";
9176
+ import fs33 from "fs-extra";
9303
9177
 
9304
9178
  // src/utils/detect.ts
9305
- import fs33 from "fs";
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 (fs33.existsSync(pkgPath)) {
9184
+ if (fs32.existsSync(pkgPath)) {
9311
9185
  try {
9312
- const pkg = JSON.parse(fs33.readFileSync(pkgPath, "utf-8"));
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) => fs33.existsSync(path36.join(cwd, f)));
9327
- const hasSrcDir = fs33.existsSync(path36.join(cwd, "src"));
9328
- const hasTypeScript = fs33.existsSync(path36.join(cwd, "tsconfig.json")) || fs33.existsSync(path36.join(cwd, "tsconfig.app.json"));
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 (fs33.existsSync(path36.join(cwd, "cms"))) {
9207
+ if (fs32.existsSync(path36.join(cwd, "cms"))) {
9334
9208
  conflicts.push("cms/ directory already exists");
9335
9209
  }
9336
- if (fs33.existsSync(path36.join(cwd, "cms.config.ts"))) {
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 (fs33.existsSync(path36.join(cwd, appBase, "(cms)"))) {
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 (fs33.existsSync(path36.join(cwd, f))) {
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 (fs33.existsSync(path36.join(cwd, f))) {
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 (fs33.existsSync(pkgPath)) {
9251
+ if (fs32.existsSync(pkgPath)) {
9378
9252
  try {
9379
- const pkg = JSON.parse(fs33.readFileSync(pkgPath, "utf-8"));
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 (fs33.existsSync(cssFile)) {
9397
- const content = fs33.readFileSync(cssFile, "utf-8");
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 (fs33.existsSync(path36.join(cwd, f))) {
9406
- const content = fs33.readFileSync(path36.join(cwd, f), "utf-8");
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 (!fs33.existsSync(tsconfigPath)) return false;
9290
+ if (!fs32.existsSync(tsconfigPath)) return false;
9417
9291
  try {
9418
- const content = fs33.readFileSync(tsconfigPath, "utf-8");
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 (!fs33.existsSync(envPath)) return false;
9300
+ if (!fs32.existsSync(envPath)) return false;
9427
9301
  try {
9428
- const content = fs33.readFileSync(envPath, "utf-8");
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 (!fs34.existsSync(srcDir)) {
9376
+ if (!fs33.existsSync(srcDir)) {
9503
9377
  return created;
9504
9378
  }
9505
- const files = fs34.readdirSync(srcDir).filter((f) => f.endsWith(".tsx") || f.endsWith(".ts"));
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 (!fs34.existsSync(destPath)) {
9509
- fs34.copyFileSync(path37.join(srcDir, file), destPath);
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 (!fs34.existsSync(srcDir)) {
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
- fs34.ensureDirSync(dest);
9528
- const entries = fs34.readdirSync(src, { withFileTypes: true });
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 (!fs34.existsSync(destPath)) {
9535
- fs34.copyFileSync(srcPath, destPath);
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 (fs34.existsSync(srcPath) && !fs34.existsSync(destPath)) {
9547
- fs34.ensureDirSync(path37.dirname(destPath));
9548
- fs34.copyFileSync(srcPath, destPath);
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 fs35 from "fs";
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 = fs35.existsSync(envPath) ? fs35.readFileSync(envPath, "utf-8") : "";
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
- fs35.writeFileSync(envPath, content);
9663
+ fs34.writeFileSync(envPath, content);
9790
9664
  }
9791
9665
  return { added, skipped, updated };
9792
9666
  }
@@ -9880,6 +9754,12 @@ function scaffoldLayout({ cwd, config }) {
9880
9754
  write(path40.join(config.paths.pages, "layout.tsx"), readTemplate("pages/authenticated-layout.tsx"));
9881
9755
  write(path40.join(config.paths.login, "page.tsx"), readTemplate("pages/login-page.tsx"));
9882
9756
  write(path40.join(config.paths.login, "login-form.tsx"), readTemplate("pages/login-form.tsx"));
9757
+ const forgotPasswordDir = path40.join(cmsDir, "forgot-password");
9758
+ write(path40.join(forgotPasswordDir, "page.tsx"), readTemplate("pages/forgot-password-page.tsx"));
9759
+ write(path40.join(forgotPasswordDir, "forgot-password-form.tsx"), readTemplate("pages/forgot-password-form.tsx"));
9760
+ const resetPasswordDir = path40.join(cmsDir, "reset-password");
9761
+ write(path40.join(resetPasswordDir, "page.tsx"), readTemplate("pages/reset-password-page.tsx"));
9762
+ write(path40.join(resetPasswordDir, "reset-password-form.tsx"), readTemplate("pages/reset-password-form.tsx"));
9883
9763
  write(path40.join(config.paths.pages, "page.tsx"), readTemplate("pages/dashboard-page.tsx"));
9884
9764
  const usersDir = path40.join(config.paths.pages, "users");
9885
9765
  write(path40.join(usersDir, "page.tsx"), readTemplate("pages/users/users-page.tsx"));
@@ -9900,7 +9780,7 @@ function scaffoldLayout({ cwd, config }) {
9900
9780
  }
9901
9781
 
9902
9782
  // src/init/scaffolders/preset.ts
9903
- import fs36 from "fs";
9783
+ import fs35 from "fs";
9904
9784
  import path41 from "path";
9905
9785
 
9906
9786
  // src/init/templates/presets/blog-categories.ts
@@ -10325,10 +10205,10 @@ function scaffoldPreset({
10325
10205
  for (const ps of presetSchemas) {
10326
10206
  const filePath = path41.join(schemasDir, ps.filename);
10327
10207
  const dir = path41.dirname(filePath);
10328
- if (!fs36.existsSync(dir)) {
10329
- fs36.mkdirSync(dir, { recursive: true });
10208
+ if (!fs35.existsSync(dir)) {
10209
+ fs35.mkdirSync(dir, { recursive: true });
10330
10210
  }
10331
- fs36.writeFileSync(filePath, ps.content, "utf-8");
10211
+ fs35.writeFileSync(filePath, ps.content, "utf-8");
10332
10212
  result.schemas.push(ps.filename);
10333
10213
  }
10334
10214
  for (const ps of presetSchemas) {
@@ -10369,7 +10249,7 @@ function scaffoldPreset({
10369
10249
  }
10370
10250
 
10371
10251
  // src/init/scaffolders/tailwind.ts
10372
- import fs37 from "fs";
10252
+ import fs36 from "fs";
10373
10253
  import path42 from "path";
10374
10254
  var SOURCE_LINES = ['@source "../cms/**/*.{ts,tsx}";', '@source "./(cms)/**/*.{ts,tsx}";'];
10375
10255
  var SOURCE_LINES_SRC = ['@source "../../cms/**/*.{ts,tsx}";', '@source "./(cms)/**/*.{ts,tsx}";'];
@@ -10426,7 +10306,7 @@ function findMainCss(cwd) {
10426
10306
  ];
10427
10307
  for (const candidate of candidates) {
10428
10308
  const filePath = path42.join(cwd, candidate);
10429
- if (fs37.existsSync(filePath)) {
10309
+ if (fs36.existsSync(filePath)) {
10430
10310
  return filePath;
10431
10311
  }
10432
10312
  }
@@ -10437,7 +10317,7 @@ function scaffoldTailwind(cwd, hasSrcDir) {
10437
10317
  if (!cssFile) {
10438
10318
  return { file: null, appended: false };
10439
10319
  }
10440
- let content = fs37.readFileSync(cssFile, "utf-8");
10320
+ let content = fs36.readFileSync(cssFile, "utf-8");
10441
10321
  let changed = false;
10442
10322
  const sourceLines = hasSrcDir ? SOURCE_LINES_SRC : SOURCE_LINES;
10443
10323
  const missingLines = sourceLines.filter((sl) => !content.includes(sl));
@@ -10489,13 +10369,13 @@ ${CMS_THEME_BLOCK}
10489
10369
  }
10490
10370
  }
10491
10371
  if (changed) {
10492
- fs37.writeFileSync(cssFile, content, "utf-8");
10372
+ fs36.writeFileSync(cssFile, content, "utf-8");
10493
10373
  }
10494
10374
  return { file: cssFile, appended: changed };
10495
10375
  }
10496
10376
 
10497
10377
  // src/init/scaffolders/tsconfig.ts
10498
- import fs38 from "fs";
10378
+ import fs37 from "fs";
10499
10379
  import path43 from "path";
10500
10380
  function stripJsonComments(input) {
10501
10381
  let result = "";
@@ -10549,11 +10429,11 @@ function scaffoldTsconfig(cwd) {
10549
10429
  const tsconfigPath = path43.join(cwd, "tsconfig.json");
10550
10430
  const added = [];
10551
10431
  const skipped = [];
10552
- if (!fs38.existsSync(tsconfigPath)) {
10432
+ if (!fs37.existsSync(tsconfigPath)) {
10553
10433
  skipped.push("tsconfig.json not found");
10554
10434
  return { added, skipped };
10555
10435
  }
10556
- const raw = fs38.readFileSync(tsconfigPath, "utf-8");
10436
+ const raw = fs37.readFileSync(tsconfigPath, "utf-8");
10557
10437
  const stripped = stripJsonComments(raw).replace(/,\s*([\]}])/g, "$1");
10558
10438
  let tsconfig;
10559
10439
  try {
@@ -10574,13 +10454,13 @@ function scaffoldTsconfig(cwd) {
10574
10454
  }
10575
10455
  compilerOptions.paths = paths;
10576
10456
  tsconfig.compilerOptions = compilerOptions;
10577
- fs38.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
10457
+ fs37.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
10578
10458
  `, "utf-8");
10579
10459
  return { added, skipped };
10580
10460
  }
10581
10461
 
10582
10462
  // src/commands/seed.ts
10583
- import fs39 from "fs";
10463
+ import fs38 from "fs";
10584
10464
  import path44 from "path";
10585
10465
  import * as clack from "@clack/prompts";
10586
10466
  import { Command as Command2 } from "commander";
@@ -10742,10 +10622,10 @@ var seedCommand = new Command2("seed").description("Create the initial admin use
10742
10622
  }
10743
10623
  const scriptsDir = path44.join(cwd, cmsDir, "scripts");
10744
10624
  const seedPath = path44.join(scriptsDir, "seed.ts");
10745
- if (!fs39.existsSync(scriptsDir)) {
10746
- fs39.mkdirSync(scriptsDir, { recursive: true });
10625
+ if (!fs38.existsSync(scriptsDir)) {
10626
+ fs38.mkdirSync(scriptsDir, { recursive: true });
10747
10627
  }
10748
- fs39.writeFileSync(seedPath, buildSeedScript(), "utf-8");
10628
+ fs38.writeFileSync(seedPath, buildSeedScript(), "utf-8");
10749
10629
  const { execFile } = await import("child_process");
10750
10630
  const tsxBin = path44.join(cwd, "node_modules", ".bin", "tsx");
10751
10631
  const runSeed2 = (overwrite) => new Promise((resolve, reject) => {
@@ -10786,7 +10666,7 @@ var seedCommand = new Command2("seed").description("Create the initial admin use
10786
10666
  if (clack.isCancel(overwrite) || !overwrite) {
10787
10667
  clack.cancel("Seed cancelled.");
10788
10668
  try {
10789
- fs39.unlinkSync(seedPath);
10669
+ fs38.unlinkSync(seedPath);
10790
10670
  } catch {
10791
10671
  }
10792
10672
  process.exit(0);
@@ -10809,9 +10689,9 @@ var seedCommand = new Command2("seed").description("Create the initial admin use
10809
10689
  process.exit(1);
10810
10690
  }
10811
10691
  try {
10812
- fs39.unlinkSync(seedPath);
10813
- if (fs39.existsSync(scriptsDir) && fs39.readdirSync(scriptsDir).length === 0) {
10814
- fs39.rmdirSync(scriptsDir);
10692
+ fs38.unlinkSync(seedPath);
10693
+ if (fs38.existsSync(scriptsDir) && fs38.readdirSync(scriptsDir).length === 0) {
10694
+ fs38.rmdirSync(scriptsDir);
10815
10695
  }
10816
10696
  } catch {
10817
10697
  }
@@ -10819,7 +10699,7 @@ var seedCommand = new Command2("seed").description("Create the initial admin use
10819
10699
  });
10820
10700
 
10821
10701
  // src/commands/init.ts
10822
- 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(
10823
10703
  "--database-url <url>",
10824
10704
  "PostgreSQL database connection string (postgres:// or postgresql://)"
10825
10705
  ).option("--force", "Overwrite all existing CMS files (nuclear option)").action(
@@ -10843,15 +10723,15 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
10843
10723
  let nuked = 0;
10844
10724
  for (const dir of nukeDirs) {
10845
10725
  const fullPath = path45.resolve(cwd, dir);
10846
- if (fs40.existsSync(fullPath)) {
10847
- fs40.rmSync(fullPath, { recursive: true, force: true });
10726
+ if (fs39.existsSync(fullPath)) {
10727
+ fs39.rmSync(fullPath, { recursive: true, force: true });
10848
10728
  nuked++;
10849
10729
  }
10850
10730
  }
10851
10731
  for (const file of nukeFiles) {
10852
10732
  const fullPath = path45.resolve(cwd, file);
10853
- if (fs40.existsSync(fullPath)) {
10854
- fs40.unlinkSync(fullPath);
10733
+ if (fs39.existsSync(fullPath)) {
10734
+ fs39.unlinkSync(fullPath);
10855
10735
  nuked++;
10856
10736
  }
10857
10737
  }
@@ -10931,9 +10811,9 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
10931
10811
  process.exit(1);
10932
10812
  }
10933
10813
  cwd = path45.resolve(cwd, projectPrompt.projectName);
10934
- const hasPackageJson = fs40.existsSync(path45.join(cwd, "package.json"));
10814
+ const hasPackageJson = fs39.existsSync(path45.join(cwd, "package.json"));
10935
10815
  const hasNextConfig = ["next.config.ts", "next.config.js", "next.config.mjs"].some(
10936
- (f) => fs40.existsSync(path45.join(cwd, f))
10816
+ (f) => fs39.existsSync(path45.join(cwd, f))
10937
10817
  );
10938
10818
  if (!hasPackageJson || !hasNextConfig) {
10939
10819
  p4.log.error(
@@ -11035,10 +10915,10 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
11035
10915
  process.stdout.write("\x1B[2A\x1B[J");
11036
10916
  p4.note(noteLines.join("\n"), "Scaffolded CMS");
11037
10917
  const drizzleConfigPath = path45.join(cwd, "drizzle.config.ts");
11038
- if (!dbFiles.includes("drizzle.config.ts") && fs40.existsSync(drizzleConfigPath)) {
10918
+ if (!dbFiles.includes("drizzle.config.ts") && fs39.existsSync(drizzleConfigPath)) {
11039
10919
  if (options.force) {
11040
10920
  const { readTemplate: readTemplate2 } = await import("./reader-2T45D7JZ.js");
11041
- fs40.writeFileSync(drizzleConfigPath, readTemplate2("drizzle.config.ts"), "utf-8");
10921
+ fs39.writeFileSync(drizzleConfigPath, readTemplate2("drizzle.config.ts"), "utf-8");
11042
10922
  p4.log.success("Updated drizzle.config.ts");
11043
10923
  } else if (!options.yes) {
11044
10924
  const overwrite = await p4.confirm({
@@ -11047,7 +10927,7 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
11047
10927
  });
11048
10928
  if (!p4.isCancel(overwrite) && overwrite) {
11049
10929
  const { readTemplate: readTemplate2 } = await import("./reader-2T45D7JZ.js");
11050
- fs40.writeFileSync(drizzleConfigPath, readTemplate2("drizzle.config.ts"), "utf-8");
10930
+ fs39.writeFileSync(drizzleConfigPath, readTemplate2("drizzle.config.ts"), "utf-8");
11051
10931
  p4.log.success("Updated drizzle.config.ts");
11052
10932
  }
11053
10933
  }
@@ -11077,27 +10957,6 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
11077
10957
  }
11078
10958
  s.start(`Applying ${features.preset} preset`);
11079
10959
  const presetResult = scaffoldPreset({ cwd, config, preset: features.preset });
11080
- {
11081
- const entityNames = [];
11082
- const formNames = [];
11083
- const schemasDir = path45.join(cwd, config.paths.schemas);
11084
- const formsDir = path45.join(schemasDir, "forms");
11085
- if (fs40.existsSync(schemasDir)) {
11086
- for (const f of fs40.readdirSync(schemasDir)) {
11087
- if (f.endsWith(".json")) entityNames.push(f.replace(".json", ""));
11088
- }
11089
- }
11090
- if (fs40.existsSync(formsDir)) {
11091
- for (const f of fs40.readdirSync(formsDir)) {
11092
- if (f.endsWith(".json")) formNames.push(f.replace(".json", ""));
11093
- }
11094
- }
11095
- regenerateCmsDoc(cwd, config, {
11096
- preset: features.preset,
11097
- schemas: entityNames,
11098
- forms: formNames
11099
- });
11100
- }
11101
10960
  s.stop("");
11102
10961
  process.stdout.write("\x1B[2A\x1B[J");
11103
10962
  const installLines = [];
@@ -11120,7 +10979,9 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
11120
10979
  }
11121
10980
  p4.note(installLines.join("\n"), "Installed");
11122
10981
  let dbPushed = false;
11123
- 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)) {
11124
10985
  s.start("Pushing database schema (drizzle-kit push)");
11125
10986
  const pushResult = await runDrizzlePush(cwd);
11126
10987
  if (pushResult.success) {
@@ -11135,7 +10996,10 @@ var initCommand = new Command3("init").description("Scaffold CMS into a new or e
11135
10996
  let seedEmail;
11136
10997
  let seedPassword;
11137
10998
  let seedSuccess = false;
11138
- if (dbPushed && !options.yes) {
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) {
11139
11003
  p4.note(pc2.dim("Create your first admin user to access the CMS."), "Admin account");
11140
11004
  const credentials = await p4.group(
11141
11005
  {
@@ -11247,7 +11111,7 @@ Run manually: ${pc2.cyan("npx betterstart seed")}`,
11247
11111
  );
11248
11112
  summaryLines.push("", "Next steps:", ...nextSteps);
11249
11113
  p4.note(summaryLines.join("\n"), "CMS scaffolded successfully");
11250
- if (!options.yes) {
11114
+ if (!options.yes && !options.skipDevServerStart) {
11251
11115
  const devCmd = runCommand(pm, "dev");
11252
11116
  const startDev = await p4.confirm({
11253
11117
  message: "Start the development server?",
@@ -11268,8 +11132,8 @@ function isValidDbUrl(url) {
11268
11132
  }
11269
11133
  function readExistingDbUrl(cwd) {
11270
11134
  const envPath = path45.join(cwd, ".env.local");
11271
- if (!fs40.existsSync(envPath)) return void 0;
11272
- const content = fs40.readFileSync(envPath, "utf-8");
11135
+ if (!fs39.existsSync(envPath)) return void 0;
11136
+ const content = fs39.readFileSync(envPath, "utf-8");
11273
11137
  for (const line of content.split("\n")) {
11274
11138
  const trimmed = line.trim();
11275
11139
  if (trimmed.startsWith("#") || !trimmed.includes("=")) continue;
@@ -11293,8 +11157,8 @@ function maskDbUrl(url) {
11293
11157
  }
11294
11158
  function hasDbUrl(cwd) {
11295
11159
  const envPath = path45.join(cwd, ".env.local");
11296
- if (!fs40.existsSync(envPath)) return false;
11297
- const content = fs40.readFileSync(envPath, "utf-8");
11160
+ if (!fs39.existsSync(envPath)) return false;
11161
+ const content = fs39.readFileSync(envPath, "utf-8");
11298
11162
  for (const line of content.split("\n")) {
11299
11163
  const trimmed = line.trim();
11300
11164
  if (trimmed.startsWith("#") || !trimmed.includes("=")) continue;
@@ -11310,15 +11174,15 @@ function hasDbUrl(cwd) {
11310
11174
  function runSeed(cwd, cmsDir, email, password4, overwrite = false) {
11311
11175
  const scriptsDir = path45.join(cwd, cmsDir, "scripts");
11312
11176
  const seedPath = path45.join(scriptsDir, "seed.ts");
11313
- if (!fs40.existsSync(scriptsDir)) {
11314
- fs40.mkdirSync(scriptsDir, { recursive: true });
11177
+ if (!fs39.existsSync(scriptsDir)) {
11178
+ fs39.mkdirSync(scriptsDir, { recursive: true });
11315
11179
  }
11316
- fs40.writeFileSync(seedPath, buildSeedScript(), "utf-8");
11180
+ fs39.writeFileSync(seedPath, buildSeedScript(), "utf-8");
11317
11181
  const cleanup = () => {
11318
11182
  try {
11319
- fs40.unlinkSync(seedPath);
11320
- if (fs40.existsSync(scriptsDir) && fs40.readdirSync(scriptsDir).length === 0) {
11321
- fs40.rmdirSync(scriptsDir);
11183
+ fs39.unlinkSync(seedPath);
11184
+ if (fs39.existsSync(scriptsDir) && fs39.readdirSync(scriptsDir).length === 0) {
11185
+ fs39.rmdirSync(scriptsDir);
11322
11186
  }
11323
11187
  } catch {
11324
11188
  }
@@ -11410,7 +11274,7 @@ function runDrizzlePush(cwd) {
11410
11274
  }
11411
11275
 
11412
11276
  // src/commands/remove.ts
11413
- import fs41 from "fs";
11277
+ import fs40 from "fs";
11414
11278
  import path46 from "path";
11415
11279
  import readline from "readline";
11416
11280
  import { Command as Command4 } from "commander";
@@ -11442,8 +11306,8 @@ function findTableEnd3(content, startIndex) {
11442
11306
  return content.length;
11443
11307
  }
11444
11308
  function removeTableFromSchema(schemaFilePath, name) {
11445
- if (!fs41.existsSync(schemaFilePath)) return false;
11446
- let content = fs41.readFileSync(schemaFilePath, "utf-8");
11309
+ if (!fs40.existsSync(schemaFilePath)) return false;
11310
+ let content = fs40.readFileSync(schemaFilePath, "utf-8");
11447
11311
  const variableName = toCamelCase(name);
11448
11312
  let changed = false;
11449
11313
  if (content.includes(`export const ${variableName} =`)) {
@@ -11471,13 +11335,13 @@ function removeTableFromSchema(schemaFilePath, name) {
11471
11335
  }
11472
11336
  if (changed) {
11473
11337
  content = content.replace(/\n{3,}/g, "\n\n");
11474
- fs41.writeFileSync(schemaFilePath, content, "utf-8");
11338
+ fs40.writeFileSync(schemaFilePath, content, "utf-8");
11475
11339
  }
11476
11340
  return changed;
11477
11341
  }
11478
11342
  function removeFromNavigation(navFilePath, name) {
11479
- if (!fs41.existsSync(navFilePath)) return false;
11480
- const content = fs41.readFileSync(navFilePath, "utf-8");
11343
+ if (!fs40.existsSync(navFilePath)) return false;
11344
+ const content = fs40.readFileSync(navFilePath, "utf-8");
11481
11345
  const href = `/cms/${name}`;
11482
11346
  if (!content.includes(`'${href}'`)) return false;
11483
11347
  const lines = content.split("\n");
@@ -11508,7 +11372,7 @@ function removeFromNavigation(navFilePath, name) {
11508
11372
  if (startLine === -1 || endLine === -1) return false;
11509
11373
  lines.splice(startLine, endLine - startLine + 1);
11510
11374
  const updated = lines.join("\n").replace(/,\s*,/g, ",").replace(/\[\s*,/, "[");
11511
- fs41.writeFileSync(navFilePath, updated, "utf-8");
11375
+ fs40.writeFileSync(navFilePath, updated, "utf-8");
11512
11376
  return true;
11513
11377
  }
11514
11378
  async function promptConfirm(message) {
@@ -11538,7 +11402,7 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
11538
11402
  const kebabName = toKebabCase(schemaName);
11539
11403
  const targets = [];
11540
11404
  const entityPagesDir = path46.join(cwd, pagesDir, schemaName);
11541
- if (fs41.existsSync(entityPagesDir)) {
11405
+ if (fs40.existsSync(entityPagesDir)) {
11542
11406
  targets.push({
11543
11407
  path: entityPagesDir,
11544
11408
  label: `${path46.join(pagesDir, schemaName)}/`,
@@ -11547,13 +11411,13 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
11547
11411
  }
11548
11412
  const actionsDir = path46.join(cwd, cmsDir, "lib", "actions", kebabName);
11549
11413
  const actionsFile = path46.join(cwd, cmsDir, "lib", "actions", `${kebabName}.ts`);
11550
- if (fs41.existsSync(actionsDir)) {
11414
+ if (fs40.existsSync(actionsDir)) {
11551
11415
  targets.push({
11552
11416
  path: actionsDir,
11553
11417
  label: `${path46.join(cmsDir, "lib", "actions", kebabName)}/`,
11554
11418
  isDir: true
11555
11419
  });
11556
- } else if (fs41.existsSync(actionsFile)) {
11420
+ } else if (fs40.existsSync(actionsFile)) {
11557
11421
  targets.push({
11558
11422
  path: actionsFile,
11559
11423
  label: path46.join(cmsDir, "lib", "actions", `${kebabName}.ts`),
@@ -11561,7 +11425,7 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
11561
11425
  });
11562
11426
  }
11563
11427
  const hookFile = path46.join(cwd, cmsDir, "hooks", `use-${kebabName}.ts`);
11564
- if (fs41.existsSync(hookFile)) {
11428
+ if (fs40.existsSync(hookFile)) {
11565
11429
  targets.push({
11566
11430
  path: hookFile,
11567
11431
  label: path46.join(cmsDir, "hooks", `use-${kebabName}.ts`),
@@ -11569,9 +11433,9 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
11569
11433
  });
11570
11434
  }
11571
11435
  const schemaFilePath = path46.join(cwd, cmsDir, "db", "schema.ts");
11572
- const hasTable = fs41.existsSync(schemaFilePath) && fs41.readFileSync(schemaFilePath, "utf-8").includes(`export const ${toCamelCase(schemaName)} =`);
11436
+ const hasTable = fs40.existsSync(schemaFilePath) && fs40.readFileSync(schemaFilePath, "utf-8").includes(`export const ${toCamelCase(schemaName)} =`);
11573
11437
  const navFilePath = path46.join(cwd, cmsDir, "data", "navigation.ts");
11574
- const hasNavEntry = fs41.existsSync(navFilePath) && fs41.readFileSync(navFilePath, "utf-8").includes(`'/cms/${schemaName}'`);
11438
+ const hasNavEntry = fs40.existsSync(navFilePath) && fs40.readFileSync(navFilePath, "utf-8").includes(`'/cms/${schemaName}'`);
11575
11439
  if (targets.length === 0 && !hasTable && !hasNavEntry) {
11576
11440
  console.log(` No generated files found for: ${schemaName}`);
11577
11441
  return;
@@ -11597,9 +11461,9 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
11597
11461
  console.log("");
11598
11462
  for (const t of targets) {
11599
11463
  if (t.isDir) {
11600
- fs41.rmSync(t.path, { recursive: true, force: true });
11464
+ fs40.rmSync(t.path, { recursive: true, force: true });
11601
11465
  } else {
11602
- fs41.unlinkSync(t.path);
11466
+ fs40.unlinkSync(t.path);
11603
11467
  }
11604
11468
  console.log(` Removed: ${t.label}`);
11605
11469
  }
@@ -11621,7 +11485,7 @@ var removeCommand = new Command4("remove").alias("rm").description("Remove all g
11621
11485
 
11622
11486
  // src/commands/setup-r2.ts
11623
11487
  import { execFileSync as execFileSync5, spawnSync } from "child_process";
11624
- import fs42 from "fs";
11488
+ import fs41 from "fs";
11625
11489
  import os from "os";
11626
11490
  import path47 from "path";
11627
11491
  import * as p5 from "@clack/prompts";
@@ -11821,7 +11685,7 @@ var setupR2Command = new Command5("setup-r2").description("Create a Cloudflare R
11821
11685
  });
11822
11686
  function findWrangler(cwd) {
11823
11687
  const localBin = path47.join(cwd, "node_modules", ".bin", "wrangler");
11824
- if (fs42.existsSync(localBin)) return { bin: localBin, prefix: [] };
11688
+ if (fs41.existsSync(localBin)) return { bin: localBin, prefix: [] };
11825
11689
  const result = spawnSync("which", ["wrangler"], { stdio: "pipe", timeout: 5e3 });
11826
11690
  if (result.status === 0) {
11827
11691
  const found = result.stdout?.toString().trim();
@@ -11869,9 +11733,9 @@ function readWranglerToken() {
11869
11733
  );
11870
11734
  }
11871
11735
  for (const configPath of candidates) {
11872
- if (!fs42.existsSync(configPath)) continue;
11736
+ if (!fs41.existsSync(configPath)) continue;
11873
11737
  try {
11874
- const content = fs42.readFileSync(configPath, "utf-8");
11738
+ const content = fs41.readFileSync(configPath, "utf-8");
11875
11739
  const match = content.match(/^oauth_token\s*=\s*"([^"]+)"/m);
11876
11740
  if (match) return match[1];
11877
11741
  } catch {
@@ -11903,14 +11767,14 @@ async function enablePublicDomain(accountId, bucketName, token) {
11903
11767
  }
11904
11768
 
11905
11769
  // src/commands/uninstall.ts
11906
- import fs44 from "fs";
11770
+ import fs43 from "fs";
11907
11771
  import path48 from "path";
11908
11772
  import * as p6 from "@clack/prompts";
11909
11773
  import { Command as Command6 } from "commander";
11910
11774
  import pc4 from "picocolors";
11911
11775
 
11912
11776
  // src/commands/uninstall-cleaners.ts
11913
- import fs43 from "fs";
11777
+ import fs42 from "fs";
11914
11778
  function stripJsonComments2(input) {
11915
11779
  let result = "";
11916
11780
  let i = 0;
@@ -11944,8 +11808,8 @@ function stripJsonComments2(input) {
11944
11808
  return result;
11945
11809
  }
11946
11810
  function cleanTsconfig(tsconfigPath) {
11947
- if (!fs43.existsSync(tsconfigPath)) return [];
11948
- const raw = fs43.readFileSync(tsconfigPath, "utf-8");
11811
+ if (!fs42.existsSync(tsconfigPath)) return [];
11812
+ const raw = fs42.readFileSync(tsconfigPath, "utf-8");
11949
11813
  const stripped = stripJsonComments2(raw).replace(/,\s*([\]}])/g, "$1");
11950
11814
  let tsconfig;
11951
11815
  try {
@@ -11969,13 +11833,13 @@ function cleanTsconfig(tsconfigPath) {
11969
11833
  compilerOptions.paths = paths;
11970
11834
  }
11971
11835
  tsconfig.compilerOptions = compilerOptions;
11972
- fs43.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
11836
+ fs42.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
11973
11837
  `, "utf-8");
11974
11838
  return removed;
11975
11839
  }
11976
11840
  function cleanCss(cssPath) {
11977
- if (!fs43.existsSync(cssPath)) return [];
11978
- const content = fs43.readFileSync(cssPath, "utf-8");
11841
+ if (!fs42.existsSync(cssPath)) return [];
11842
+ const content = fs42.readFileSync(cssPath, "utf-8");
11979
11843
  const lines = content.split("\n");
11980
11844
  const sourcePattern = /^@source\s+"[^"]*cms[^"]*";\s*$/;
11981
11845
  const removed = [];
@@ -11989,12 +11853,12 @@ function cleanCss(cssPath) {
11989
11853
  }
11990
11854
  if (removed.length === 0) return [];
11991
11855
  const cleaned = kept.join("\n").replace(/\n{3,}/g, "\n\n");
11992
- fs43.writeFileSync(cssPath, cleaned, "utf-8");
11856
+ fs42.writeFileSync(cssPath, cleaned, "utf-8");
11993
11857
  return removed;
11994
11858
  }
11995
11859
  function cleanEnvFile(envPath) {
11996
- if (!fs43.existsSync(envPath)) return [];
11997
- const content = fs43.readFileSync(envPath, "utf-8");
11860
+ if (!fs42.existsSync(envPath)) return [];
11861
+ const content = fs42.readFileSync(envPath, "utf-8");
11998
11862
  const lines = content.split("\n");
11999
11863
  const removed = [];
12000
11864
  const kept = [];
@@ -12027,9 +11891,9 @@ function cleanEnvFile(envPath) {
12027
11891
  if (removed.length === 0) return [];
12028
11892
  const result = kept.join("\n").replace(/\n{3,}/g, "\n\n").trim();
12029
11893
  if (result === "") {
12030
- fs43.unlinkSync(envPath);
11894
+ fs42.unlinkSync(envPath);
12031
11895
  } else {
12032
- fs43.writeFileSync(envPath, `${result}
11896
+ fs42.writeFileSync(envPath, `${result}
12033
11897
  `, "utf-8");
12034
11898
  }
12035
11899
  return removed;
@@ -12056,14 +11920,14 @@ function findMainCss2(cwd) {
12056
11920
  ];
12057
11921
  for (const candidate of candidates) {
12058
11922
  const filePath = path48.join(cwd, candidate);
12059
- if (fs44.existsSync(filePath)) return filePath;
11923
+ if (fs43.existsSync(filePath)) return filePath;
12060
11924
  }
12061
11925
  return void 0;
12062
11926
  }
12063
11927
  function isCLICreatedBiome(biomePath) {
12064
- if (!fs44.existsSync(biomePath)) return false;
11928
+ if (!fs43.existsSync(biomePath)) return false;
12065
11929
  try {
12066
- const content = JSON.parse(fs44.readFileSync(biomePath, "utf-8"));
11930
+ const content = JSON.parse(fs43.readFileSync(biomePath, "utf-8"));
12067
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");
12068
11932
  } catch {
12069
11933
  return false;
@@ -12071,13 +11935,13 @@ function isCLICreatedBiome(biomePath) {
12071
11935
  }
12072
11936
  function buildUninstallPlan(cwd) {
12073
11937
  const steps = [];
12074
- const hasSrc = fs44.existsSync(path48.join(cwd, "src"));
11938
+ const hasSrc = fs43.existsSync(path48.join(cwd, "src"));
12075
11939
  const appBase = hasSrc ? "src/app" : "app";
12076
11940
  const dirs = [];
12077
11941
  const cmsDir = path48.join(cwd, "cms");
12078
11942
  const cmsRouteGroup = path48.join(cwd, appBase, "(cms)");
12079
- if (fs44.existsSync(cmsDir)) dirs.push("cms/");
12080
- if (fs44.existsSync(cmsRouteGroup)) dirs.push(`${appBase}/(cms)/`);
11943
+ if (fs43.existsSync(cmsDir)) dirs.push("cms/");
11944
+ if (fs43.existsSync(cmsRouteGroup)) dirs.push(`${appBase}/(cms)/`);
12081
11945
  if (dirs.length > 0) {
12082
11946
  steps.push({
12083
11947
  label: "CMS directories",
@@ -12085,8 +11949,8 @@ function buildUninstallPlan(cwd) {
12085
11949
  count: dirs.length,
12086
11950
  unit: dirs.length === 1 ? "directory" : "directories",
12087
11951
  execute() {
12088
- if (fs44.existsSync(cmsDir)) fs44.rmSync(cmsDir, { recursive: true, force: true });
12089
- if (fs44.existsSync(cmsRouteGroup)) fs44.rmSync(cmsRouteGroup, { recursive: true, force: true });
11952
+ if (fs43.existsSync(cmsDir)) fs43.rmSync(cmsDir, { recursive: true, force: true });
11953
+ if (fs43.existsSync(cmsRouteGroup)) fs43.rmSync(cmsRouteGroup, { recursive: true, force: true });
12090
11954
  }
12091
11955
  });
12092
11956
  }
@@ -12098,7 +11962,7 @@ function buildUninstallPlan(cwd) {
12098
11962
  ["CMS.md", path48.join(cwd, "CMS.md")]
12099
11963
  ];
12100
11964
  for (const [label, fullPath] of candidates) {
12101
- if (fs44.existsSync(fullPath)) {
11965
+ if (fs43.existsSync(fullPath)) {
12102
11966
  configFiles.push(label);
12103
11967
  configPaths.push(fullPath);
12104
11968
  }
@@ -12116,14 +11980,14 @@ function buildUninstallPlan(cwd) {
12116
11980
  unit: configFiles.length === 1 ? "file" : "files",
12117
11981
  execute() {
12118
11982
  for (const p7 of configPaths) {
12119
- if (fs44.existsSync(p7)) fs44.unlinkSync(p7);
11983
+ if (fs43.existsSync(p7)) fs43.unlinkSync(p7);
12120
11984
  }
12121
11985
  }
12122
11986
  });
12123
11987
  }
12124
11988
  const tsconfigPath = path48.join(cwd, "tsconfig.json");
12125
- if (fs44.existsSync(tsconfigPath)) {
12126
- const content = fs44.readFileSync(tsconfigPath, "utf-8");
11989
+ if (fs43.existsSync(tsconfigPath)) {
11990
+ const content = fs43.readFileSync(tsconfigPath, "utf-8");
12127
11991
  const aliasMatches = content.match(/"@cms\//g);
12128
11992
  if (aliasMatches && aliasMatches.length > 0) {
12129
11993
  const aliasCount = aliasMatches.length;
@@ -12140,7 +12004,7 @@ function buildUninstallPlan(cwd) {
12140
12004
  }
12141
12005
  const cssFile = findMainCss2(cwd);
12142
12006
  if (cssFile) {
12143
- const cssContent = fs44.readFileSync(cssFile, "utf-8");
12007
+ const cssContent = fs43.readFileSync(cssFile, "utf-8");
12144
12008
  const sourceLines = cssContent.split("\n").filter((l) => /^@source\s+"[^"]*cms[^"]*";\s*$/.test(l));
12145
12009
  if (sourceLines.length > 0) {
12146
12010
  const relCss = path48.relative(cwd, cssFile);
@@ -12156,8 +12020,8 @@ function buildUninstallPlan(cwd) {
12156
12020
  }
12157
12021
  }
12158
12022
  const envPath = path48.join(cwd, ".env.local");
12159
- if (fs44.existsSync(envPath)) {
12160
- const envContent = fs44.readFileSync(envPath, "utf-8");
12023
+ if (fs43.existsSync(envPath)) {
12024
+ const envContent = fs43.readFileSync(envPath, "utf-8");
12161
12025
  const bsVars = envContent.split("\n").filter((l) => l.trim().match(/^BETTERSTART_\w+=/)).map((l) => l.split("=")[0]);
12162
12026
  if (bsVars.length > 0) {
12163
12027
  steps.push({
@@ -12211,7 +12075,7 @@ var uninstallCommand = new Command6("uninstall").description("Remove all CMS fil
12211
12075
  });
12212
12076
 
12213
12077
  // src/commands/update-component.ts
12214
- import fs45 from "fs";
12078
+ import fs44 from "fs";
12215
12079
  import path49 from "path";
12216
12080
  import * as clack2 from "@clack/prompts";
12217
12081
  import { Command as Command7 } from "commander";
@@ -12257,6 +12121,13 @@ var TEMPLATE_REGISTRY = {
12257
12121
  "account-layout": { relPath: "app/(cms)/cms/(account)/layout.tsx", content: () => readTemplate("pages/account-layout.tsx"), base: "cwd" },
12258
12122
  "profile-page": { relPath: "app/(cms)/cms/(account)/profile/page.tsx", content: () => readTemplate("pages/profile/profile-page.tsx"), base: "cwd" },
12259
12123
  "profile-form": { relPath: "app/(cms)/cms/(account)/profile/profile-form.tsx", content: () => readTemplate("pages/profile/profile-form.tsx"), base: "cwd" },
12124
+ // Password reset
12125
+ "login-page": { relPath: "app/(cms)/cms/login/page.tsx", content: () => readTemplate("pages/login-page.tsx"), base: "cwd" },
12126
+ "login-form": { relPath: "app/(cms)/cms/login/login-form.tsx", content: () => readTemplate("pages/login-form.tsx"), base: "cwd" },
12127
+ "forgot-password-page": { relPath: "app/(cms)/cms/forgot-password/page.tsx", content: () => readTemplate("pages/forgot-password-page.tsx"), base: "cwd" },
12128
+ "forgot-password-form": { relPath: "app/(cms)/cms/forgot-password/forgot-password-form.tsx", content: () => readTemplate("pages/forgot-password-form.tsx"), base: "cwd" },
12129
+ "reset-password-page": { relPath: "app/(cms)/cms/reset-password/page.tsx", content: () => readTemplate("pages/reset-password-page.tsx"), base: "cwd" },
12130
+ "reset-password-form": { relPath: "app/(cms)/cms/reset-password/reset-password-form.tsx", content: () => readTemplate("pages/reset-password-form.tsx"), base: "cwd" },
12260
12131
  // Lib
12261
12132
  r2: { relPath: "lib/r2.ts", content: () => readTemplate("lib/r2.ts") },
12262
12133
  "form-settings-action": { relPath: "lib/actions/form-settings.ts", content: () => readTemplate("lib/actions/form-settings.ts") },
@@ -12271,8 +12142,8 @@ var TEMPLATE_REGISTRY = {
12271
12142
  function getStaticUiComponents() {
12272
12143
  const cliRoot = findCliRoot();
12273
12144
  const uiDir = path49.join(cliRoot, "templates", "ui");
12274
- if (!fs45.existsSync(uiDir)) return [];
12275
- return fs45.readdirSync(uiDir).filter((f) => f.endsWith(".tsx") || f.endsWith(".ts")).map((f) => f.replace(/\.(tsx|ts)$/, ""));
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)$/, ""));
12276
12147
  }
12277
12148
  function getAllComponentNames() {
12278
12149
  const staticUi = getStaticUiComponents();
@@ -12316,7 +12187,7 @@ var updateComponentCommand = new Command7("update").alias("update-component").de
12316
12187
  }
12317
12188
  const config = await resolveConfig(cwd);
12318
12189
  const cms = path49.resolve(cwd, config.paths.cms);
12319
- if (!fs45.existsSync(cms)) {
12190
+ if (!fs44.existsSync(cms)) {
12320
12191
  clack2.cancel(`CMS directory not found at ${config.paths.cms}. Run 'betterstart init' first.`);
12321
12192
  process.exit(1);
12322
12193
  }
@@ -12332,18 +12203,18 @@ var updateComponentCommand = new Command7("update").alias("update-component").de
12332
12203
  const baseDir = entry.base === "cwd" ? cwd : cms;
12333
12204
  const destPath = path49.join(baseDir, entry.relPath);
12334
12205
  fsExtra.ensureDirSync(path49.dirname(destPath));
12335
- fs45.writeFileSync(destPath, entry.content(), "utf-8");
12206
+ fs44.writeFileSync(destPath, entry.content(), "utf-8");
12336
12207
  clack2.log.success(`Updated ${entry.relPath}`);
12337
12208
  updated++;
12338
12209
  continue;
12339
12210
  }
12340
- const uiFile = fs45.readdirSync(uiDir).find(
12211
+ const uiFile = fs44.readdirSync(uiDir).find(
12341
12212
  (f) => f.replace(/\.(tsx|ts)$/, "") === name
12342
12213
  );
12343
12214
  if (uiFile) {
12344
12215
  const destPath = path49.join(cms, "components", "ui", uiFile);
12345
12216
  fsExtra.ensureDirSync(path49.dirname(destPath));
12346
- fs45.copyFileSync(path49.join(uiDir, uiFile), destPath);
12217
+ fs44.copyFileSync(path49.join(uiDir, uiFile), destPath);
12347
12218
  clack2.log.success(`Updated components/ui/${uiFile}`);
12348
12219
  updated++;
12349
12220
  continue;
@@ -12351,7 +12222,7 @@ var updateComponentCommand = new Command7("update").alias("update-component").de
12351
12222
  if (name === "tiptap") {
12352
12223
  const srcDir = path49.join(cliRoot, "templates", "tiptap");
12353
12224
  const destDir = path49.join(cms, "components", "ui", "tiptap");
12354
- if (fs45.existsSync(srcDir)) {
12225
+ if (fs44.existsSync(srcDir)) {
12355
12226
  fsExtra.copySync(srcDir, destDir, { overwrite: true });
12356
12227
  clack2.log.success("Updated components/ui/tiptap/ (all files)");
12357
12228
  updated++;
@@ -12397,7 +12268,7 @@ var updateDepsCommand = new Command8("update-deps").description("Install or upda
12397
12268
  });
12398
12269
 
12399
12270
  // src/commands/update-styles.ts
12400
- import fs46 from "fs";
12271
+ import fs45 from "fs";
12401
12272
  import path51 from "path";
12402
12273
  import * as clack4 from "@clack/prompts";
12403
12274
  import { Command as Command9 } from "commander";
@@ -12407,11 +12278,11 @@ var updateStylesCommand = new Command9("update-styles").description("Replace cms
12407
12278
  const config = await resolveConfig(cwd);
12408
12279
  const cmsDir = config.paths?.cms ?? "./cms";
12409
12280
  const targetPath = path51.join(cwd, cmsDir, "cms-globals.css");
12410
- if (!fs46.existsSync(targetPath)) {
12281
+ if (!fs45.existsSync(targetPath)) {
12411
12282
  clack4.cancel(`cms-globals.css not found at ${path51.relative(cwd, targetPath)}`);
12412
12283
  process.exit(1);
12413
12284
  }
12414
- fs46.writeFileSync(targetPath, readTemplate("cms-globals.css"), "utf-8");
12285
+ fs45.writeFileSync(targetPath, readTemplate("cms-globals.css"), "utf-8");
12415
12286
  clack4.log.success(`Updated ${path51.relative(cwd, targetPath)}`);
12416
12287
  clack4.outro("Styles updated");
12417
12288
  });