betterstart-cli 0.0.79 → 0.0.80

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 CHANGED
@@ -31,7 +31,7 @@ import * as p from "@clack/prompts";
31
31
  import fs from "fs";
32
32
  import path from "path";
33
33
  import { fileURLToPath } from "url";
34
- var CONFIG_FILE_NAME = "admin.config.ts";
34
+ var CONFIG_FILE_NAME = "betterstart.config.ts";
35
35
  function findConfigFile(cwd) {
36
36
  const filePath = path.join(cwd, CONFIG_FILE_NAME);
37
37
  return fs.existsSync(filePath) ? filePath : void 0;
@@ -159,8 +159,180 @@ import path27 from "path";
159
159
  import * as p4 from "@clack/prompts";
160
160
 
161
161
  // core-engine/config/serialize.ts
162
+ import fs3 from "fs";
163
+ import path4 from "path";
164
+
165
+ // core-engine/snapshots/store.ts
166
+ import crypto from "crypto";
162
167
  import fs2 from "fs";
163
168
  import path3 from "path";
169
+
170
+ // core-engine/utils/json-format.ts
171
+ function stringifyProjectJson(value) {
172
+ return `${compactShortStringArrays(JSON.stringify(value, null, 2))}
173
+ `;
174
+ }
175
+ function compactShortStringArrays(json) {
176
+ return json.replace(
177
+ /\[\n((?:[ \t]+"(?:[^"\\]|\\.)*",?\n)+)([ \t]*)\]/g,
178
+ (match, entries) => {
179
+ const values = entries.trim().split("\n").map((line) => line.trim());
180
+ const inline = `[${values.map((entry) => entry.replace(/,$/, "")).join(", ")}]`;
181
+ return inline.length <= 70 ? inline : match;
182
+ }
183
+ );
184
+ }
185
+
186
+ // core-engine/snapshots/store.ts
187
+ var BARREL_SCOPE = "_barrels";
188
+ var REMOVED_SCOPE = "_removed";
189
+ function normalizeLineEndings(content) {
190
+ return content.replace(/\r\n/g, "\n");
191
+ }
192
+ function hashContent(content) {
193
+ return `sha256-${crypto.createHash("sha256").update(normalizeLineEndings(content)).digest("hex")}`;
194
+ }
195
+ function snapshotRoot(cwd) {
196
+ return path3.join(cwd, ".betterstart", "snapshots");
197
+ }
198
+ function scopeDir(cwd, scope) {
199
+ return path3.join(snapshotRoot(cwd), scope);
200
+ }
201
+ function manifestPath(cwd, scope) {
202
+ return path3.join(scopeDir(cwd, scope), "manifest.json");
203
+ }
204
+ function filesDir(cwd, scope) {
205
+ return path3.join(scopeDir(cwd, scope), "files");
206
+ }
207
+ function snapshotFilePath(cwd, scope, filePath) {
208
+ return path3.join(filesDir(cwd, scope), ...filePath.split("/"));
209
+ }
210
+ function removedDir(cwd) {
211
+ return path3.join(snapshotRoot(cwd), REMOVED_SCOPE);
212
+ }
213
+ function tombstonePath(cwd, scope) {
214
+ return path3.join(removedDir(cwd), scope);
215
+ }
216
+ function loadManifest(cwd, scope) {
217
+ const filePath = manifestPath(cwd, scope);
218
+ if (!fs2.existsSync(filePath)) {
219
+ return null;
220
+ }
221
+ return JSON.parse(fs2.readFileSync(filePath, "utf-8"));
222
+ }
223
+ function saveManifest(cwd, scope, manifest) {
224
+ fs2.mkdirSync(scopeDir(cwd, scope), { recursive: true });
225
+ fs2.writeFileSync(manifestPath(cwd, scope), stringifyProjectJson(manifest), "utf-8");
226
+ }
227
+ function writeSnapshotFiles(cwd, scope, files) {
228
+ const dir = filesDir(cwd, scope);
229
+ fs2.rmSync(dir, { recursive: true, force: true });
230
+ fs2.mkdirSync(dir, { recursive: true });
231
+ return files.map((file) => {
232
+ const outputPath = snapshotFilePath(cwd, scope, file.path);
233
+ fs2.mkdirSync(path3.dirname(outputPath), { recursive: true });
234
+ fs2.writeFileSync(outputPath, file.content, "utf-8");
235
+ return {
236
+ path: file.path,
237
+ hash: hashContent(file.content)
238
+ };
239
+ });
240
+ }
241
+ function readSnapshotFiles(cwd, scope, manifest) {
242
+ return manifest.files.filter((entry) => fs2.existsSync(snapshotFilePath(cwd, scope, entry.path))).map((entry) => ({
243
+ path: entry.path,
244
+ content: fs2.readFileSync(snapshotFilePath(cwd, scope, entry.path), "utf-8")
245
+ }));
246
+ }
247
+ function deleteSnapshot(cwd, scope) {
248
+ fs2.rmSync(scopeDir(cwd, scope), { recursive: true, force: true });
249
+ }
250
+ function hasSnapshotFiles(cwd, scope) {
251
+ return fs2.existsSync(filesDir(cwd, scope));
252
+ }
253
+ function writeTombstone(cwd, scope) {
254
+ fs2.mkdirSync(removedDir(cwd), { recursive: true });
255
+ fs2.writeFileSync(tombstonePath(cwd, scope), "", "utf-8");
256
+ }
257
+ function hasTombstone(cwd, scope) {
258
+ return fs2.existsSync(tombstonePath(cwd, scope));
259
+ }
260
+ function clearTombstone(cwd, scope) {
261
+ fs2.rmSync(tombstonePath(cwd, scope), { force: true });
262
+ }
263
+ function listSnapshotScopes(cwd) {
264
+ const dir = snapshotRoot(cwd);
265
+ if (!fs2.existsSync(dir)) {
266
+ return [];
267
+ }
268
+ return fs2.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => name !== REMOVED_SCOPE).sort();
269
+ }
270
+ function createManifest(scope, schemaJson, cliVersion, files, skipped) {
271
+ return {
272
+ schemaName: scope,
273
+ schemaHash: hashContent(JSON.stringify(schemaJson)),
274
+ schemaJson,
275
+ cliVersion,
276
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
277
+ files: files.map((file) => ({
278
+ path: file.path,
279
+ hash: hashContent(file.content)
280
+ })),
281
+ skipped: [...skipped].sort()
282
+ };
283
+ }
284
+ function snapshotRootExists(cwd) {
285
+ return fs2.existsSync(snapshotRoot(cwd));
286
+ }
287
+ function manifestFilesByPath(manifest) {
288
+ return new Map(manifest.files.map((file) => [file.path, file]));
289
+ }
290
+ function loadAllManifests(cwd) {
291
+ return listSnapshotScopes(cwd).filter((scope) => scope !== BARREL_SCOPE).map((scope) => ({ scope, manifest: loadManifest(cwd, scope) })).filter(
292
+ (entry) => entry.manifest !== null
293
+ );
294
+ }
295
+ function snapshotTargetPath(cwd, filePath) {
296
+ return path3.join(cwd, ...filePath.split("/"));
297
+ }
298
+ function getCurrentCliVersion() {
299
+ let currentDir = path3.dirname(new URL(import.meta.url).pathname);
300
+ for (let depth = 0; depth < 6; depth++) {
301
+ const packagePath = path3.join(currentDir, "package.json");
302
+ if (fs2.existsSync(packagePath)) {
303
+ try {
304
+ const pkg = JSON.parse(fs2.readFileSync(packagePath, "utf-8"));
305
+ if (pkg.name === "betterstart-cli" && pkg.version) {
306
+ return pkg.version;
307
+ }
308
+ } catch {
309
+ }
310
+ }
311
+ const parentDir = path3.dirname(currentDir);
312
+ if (parentDir === currentDir) {
313
+ break;
314
+ }
315
+ currentDir = parentDir;
316
+ }
317
+ return "0.0.0";
318
+ }
319
+ function getAllTrackedFilePaths(cwd) {
320
+ const paths = /* @__PURE__ */ new Set();
321
+ for (const { manifest } of loadAllManifests(cwd)) {
322
+ for (const file of manifest.files) {
323
+ paths.add(file.path);
324
+ }
325
+ }
326
+ const barrelManifest = loadManifest(cwd, BARREL_SCOPE);
327
+ if (barrelManifest) {
328
+ for (const file of barrelManifest.files) {
329
+ paths.add(file.path);
330
+ }
331
+ }
332
+ return Array.from(paths).sort();
333
+ }
334
+
335
+ // core-engine/config/serialize.ts
164
336
  function quote(value) {
165
337
  return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
166
338
  }
@@ -176,6 +348,7 @@ function serializeConfig(config) {
176
348
 
177
349
  export default defineConfig({
178
350
  framework: 'next',
351
+ cliVersion: ${quote(getCurrentCliVersion())},
179
352
 
180
353
  frameworkConfig: {
181
354
  next: {
@@ -224,13 +397,13 @@ export default defineConfig({
224
397
  `;
225
398
  }
226
399
  function writeConfigFile(cwd, config) {
227
- fs2.writeFileSync(path3.join(cwd, "admin.config.ts"), serializeConfig(config), "utf-8");
400
+ fs3.writeFileSync(path4.join(cwd, CONFIG_FILE_NAME), serializeConfig(config), "utf-8");
228
401
  }
229
402
 
230
403
  // core-engine/utils/package-manager.ts
231
404
  import { execFileSync } from "child_process";
232
- import fs3 from "fs";
233
- import path4 from "path";
405
+ import fs4 from "fs";
406
+ import path5 from "path";
234
407
  var LOCKFILE_MAP = {
235
408
  "pnpm-lock.yaml": "pnpm",
236
409
  "package-lock.json": "npm",
@@ -239,18 +412,18 @@ var LOCKFILE_MAP = {
239
412
  "bun.lock": "bun"
240
413
  };
241
414
  function detectPackageManager(cwd) {
242
- let dir = path4.resolve(cwd);
243
- const root = path4.parse(dir).root;
415
+ let dir = path5.resolve(cwd);
416
+ const root = path5.parse(dir).root;
244
417
  while (dir !== root) {
245
418
  for (const [lockfile, pm] of Object.entries(LOCKFILE_MAP)) {
246
- if (fs3.existsSync(path4.join(dir, lockfile))) {
419
+ if (fs4.existsSync(path5.join(dir, lockfile))) {
247
420
  return pm;
248
421
  }
249
422
  }
250
- const pkgPath = path4.join(dir, "package.json");
251
- if (fs3.existsSync(pkgPath)) {
423
+ const pkgPath = path5.join(dir, "package.json");
424
+ if (fs4.existsSync(pkgPath)) {
252
425
  try {
253
- const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
426
+ const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
254
427
  if (typeof pkg.packageManager === "string") {
255
428
  const name = pkg.packageManager.split("@")[0];
256
429
  if (name === "pnpm" || name === "npm" || name === "yarn" || name === "bun") {
@@ -260,7 +433,7 @@ function detectPackageManager(cwd) {
260
433
  } catch {
261
434
  }
262
435
  }
263
- dir = path4.dirname(dir);
436
+ dir = path5.dirname(dir);
264
437
  }
265
438
  return "npm";
266
439
  }
@@ -284,25 +457,25 @@ function createNextAppCommand() {
284
457
  }
285
458
 
286
459
  // adapters/next/config.ts
287
- import fs5 from "fs";
288
- import path6 from "path";
460
+ import fs6 from "fs";
461
+ import path7 from "path";
289
462
 
290
463
  // adapters/next/config/detect.ts
291
- import fs4 from "fs";
292
- import path5 from "path";
464
+ import fs5 from "fs";
465
+ import path6 from "path";
293
466
  var NEXT_CONFIG_FILES = ["next.config.ts", "next.config.js", "next.config.mjs"];
294
467
  function detectProjectName(cwd) {
295
- const pkgPath = path5.join(cwd, "package.json");
296
- if (fs4.existsSync(pkgPath)) {
468
+ const pkgPath = path6.join(cwd, "package.json");
469
+ if (fs5.existsSync(pkgPath)) {
297
470
  try {
298
- const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
471
+ const pkg = JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
299
472
  if (typeof pkg.name === "string" && pkg.name.length > 0) {
300
473
  return formatProjectName(pkg.name);
301
474
  }
302
475
  } catch {
303
476
  }
304
477
  }
305
- return formatProjectName(path5.basename(cwd));
478
+ return formatProjectName(path6.basename(cwd));
306
479
  }
307
480
  function formatProjectName(name) {
308
481
  const base = name.includes("/") ? name.split("/").pop() : name;
@@ -310,21 +483,21 @@ function formatProjectName(name) {
310
483
  }
311
484
  function detectProject(cwd, namespaceValue = DEFAULT_ADMIN_NAMESPACE) {
312
485
  const namespace = validateAdminNamespace(namespaceValue);
313
- const isExisting = NEXT_CONFIG_FILES.some((f) => fs4.existsSync(path5.join(cwd, f)));
314
- const hasSrcDir = fs4.existsSync(path5.join(cwd, "src"));
315
- const hasTypeScript = fs4.existsSync(path5.join(cwd, "tsconfig.json")) || fs4.existsSync(path5.join(cwd, "tsconfig.app.json"));
486
+ const isExisting = NEXT_CONFIG_FILES.some((f) => fs5.existsSync(path6.join(cwd, f)));
487
+ const hasSrcDir = fs5.existsSync(path6.join(cwd, "src"));
488
+ const hasTypeScript = fs5.existsSync(path6.join(cwd, "tsconfig.json")) || fs5.existsSync(path6.join(cwd, "tsconfig.app.json"));
316
489
  const hasTailwind = detectTailwind(cwd);
317
490
  const linter = detectLinter(cwd);
318
491
  const conflicts = [];
319
492
  if (isExisting) {
320
- if (fs4.existsSync(path5.join(cwd, namespace))) {
493
+ if (fs5.existsSync(path6.join(cwd, namespace))) {
321
494
  conflicts.push(`${namespace}/ directory already exists`);
322
495
  }
323
- if (fs4.existsSync(path5.join(cwd, "admin.config.ts"))) {
324
- conflicts.push("admin.config.ts already exists");
496
+ if (fs5.existsSync(path6.join(cwd, CONFIG_FILE_NAME))) {
497
+ conflicts.push(`${CONFIG_FILE_NAME} already exists`);
325
498
  }
326
499
  const appBase = hasSrcDir ? "src/app" : "app";
327
- if (fs4.existsSync(path5.join(cwd, appBase, `(${namespace})`))) {
500
+ if (fs5.existsSync(path6.join(cwd, appBase, `(${namespace})`))) {
328
501
  conflicts.push(`${appBase}/(${namespace})/ route group already exists`);
329
502
  }
330
503
  if (hasTsconfigAdminAliases(cwd, namespace)) {
@@ -348,19 +521,19 @@ var ESLINT_CONFIG_FILES = [
348
521
  ];
349
522
  function detectLinter(cwd) {
350
523
  for (const f of BIOME_CONFIG_FILES) {
351
- if (fs4.existsSync(path5.join(cwd, f))) {
524
+ if (fs5.existsSync(path6.join(cwd, f))) {
352
525
  return { type: "biome", configFile: f };
353
526
  }
354
527
  }
355
528
  for (const f of ESLINT_CONFIG_FILES) {
356
- if (fs4.existsSync(path5.join(cwd, f))) {
529
+ if (fs5.existsSync(path6.join(cwd, f))) {
357
530
  return { type: "eslint", configFile: f };
358
531
  }
359
532
  }
360
- const pkgPath = path5.join(cwd, "package.json");
361
- if (fs4.existsSync(pkgPath)) {
533
+ const pkgPath = path6.join(cwd, "package.json");
534
+ if (fs5.existsSync(pkgPath)) {
362
535
  try {
363
- const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
536
+ const pkg = JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
364
537
  if (pkg.eslintConfig) {
365
538
  return { type: "eslint", configFile: "package.json (eslintConfig)" };
366
539
  }
@@ -371,14 +544,14 @@ function detectLinter(cwd) {
371
544
  }
372
545
  function detectTailwind(cwd) {
373
546
  const cssFiles = ["globals.css", "app.css", "index.css"].flatMap((f) => [
374
- path5.join(cwd, "src", "app", f),
375
- path5.join(cwd, "app", f),
376
- path5.join(cwd, "src", f),
377
- path5.join(cwd, f)
547
+ path6.join(cwd, "src", "app", f),
548
+ path6.join(cwd, "app", f),
549
+ path6.join(cwd, "src", f),
550
+ path6.join(cwd, f)
378
551
  ]);
379
552
  for (const cssFile of cssFiles) {
380
- if (fs4.existsSync(cssFile)) {
381
- const content = fs4.readFileSync(cssFile, "utf-8");
553
+ if (fs5.existsSync(cssFile)) {
554
+ const content = fs5.readFileSync(cssFile, "utf-8");
382
555
  if (content.includes('@import "tailwindcss"') || content.includes("@import 'tailwindcss'") || content.includes("@theme")) {
383
556
  return true;
384
557
  }
@@ -386,8 +559,8 @@ function detectTailwind(cwd) {
386
559
  }
387
560
  const postcssFiles = ["postcss.config.js", "postcss.config.mjs", "postcss.config.cjs"];
388
561
  for (const f of postcssFiles) {
389
- if (fs4.existsSync(path5.join(cwd, f))) {
390
- const content = fs4.readFileSync(path5.join(cwd, f), "utf-8");
562
+ if (fs5.existsSync(path6.join(cwd, f))) {
563
+ const content = fs5.readFileSync(path6.join(cwd, f), "utf-8");
391
564
  if (content.includes("tailwindcss") || content.includes("@tailwindcss")) {
392
565
  return true;
393
566
  }
@@ -396,20 +569,20 @@ function detectTailwind(cwd) {
396
569
  return false;
397
570
  }
398
571
  function hasTsconfigAdminAliases(cwd, namespace) {
399
- const tsconfigPath = path5.join(cwd, "tsconfig.json");
400
- if (!fs4.existsSync(tsconfigPath)) return false;
572
+ const tsconfigPath = path6.join(cwd, "tsconfig.json");
573
+ if (!fs5.existsSync(tsconfigPath)) return false;
401
574
  try {
402
- const content = fs4.readFileSync(tsconfigPath, "utf-8");
575
+ const content = fs5.readFileSync(tsconfigPath, "utf-8");
403
576
  return content.includes(`@${namespace}/`);
404
577
  } catch {
405
578
  return false;
406
579
  }
407
580
  }
408
581
  function detectNextMajorVersion(cwd) {
409
- const pkgPath = path5.join(cwd, "package.json");
410
- if (!fs4.existsSync(pkgPath)) return 16;
582
+ const pkgPath = path6.join(cwd, "package.json");
583
+ if (!fs5.existsSync(pkgPath)) return 16;
411
584
  try {
412
- const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
585
+ const pkg = JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
413
586
  const version2 = pkg.dependencies?.next ?? pkg.devDependencies?.next;
414
587
  if (typeof version2 !== "string") return 16;
415
588
  const match = version2.match(/(\d+)/);
@@ -421,7 +594,7 @@ function detectNextMajorVersion(cwd) {
421
594
  }
422
595
 
423
596
  // adapters/next/config.ts
424
- var unsupportedStateMessage = 'admin.config.ts must use the current BetterStart config shape with framework: "next" and frameworkConfig.next. Old top-level srcDir, nextMajorVersion, and paths config is no longer supported.';
597
+ var unsupportedStateMessage = 'betterstart.config.ts must use the current BetterStart config shape with framework: "next" and frameworkConfig.next. Old top-level srcDir, nextMajorVersion, and paths config is no longer supported.';
425
598
  function getDefaultConfig(srcDir, nextMajorVersion = 16) {
426
599
  const namespace = DEFAULT_ADMIN_NAMESPACE;
427
600
  const paths = deriveNamespacePaths(namespace, srcDir);
@@ -472,7 +645,7 @@ async function resolveConfig(cwd) {
472
645
  const workingDir = cwd ?? process.cwd();
473
646
  const configPath = findConfigFile(workingDir);
474
647
  const nextMajorVersion = detectNextMajorVersion(workingDir);
475
- const hasSrc = fs5.existsSync(path6.join(workingDir, "src"));
648
+ const hasSrc = fs6.existsSync(path7.join(workingDir, "src"));
476
649
  const defaultConfig = getDefaultConfig(hasSrc, nextMajorVersion);
477
650
  if (!configPath) {
478
651
  return defaultConfig;
@@ -524,176 +697,6 @@ import { execFileSync as execFileSync2 } from "child_process";
524
697
  import fs8 from "fs";
525
698
  import path10 from "path";
526
699
 
527
- // core-engine/snapshots/store.ts
528
- import crypto from "crypto";
529
- import fs6 from "fs";
530
- import path7 from "path";
531
-
532
- // core-engine/utils/json-format.ts
533
- function stringifyProjectJson(value) {
534
- return `${compactShortStringArrays(JSON.stringify(value, null, 2))}
535
- `;
536
- }
537
- function compactShortStringArrays(json) {
538
- return json.replace(
539
- /\[\n((?:[ \t]+"(?:[^"\\]|\\.)*",?\n)+)([ \t]*)\]/g,
540
- (match, entries) => {
541
- const values = entries.trim().split("\n").map((line) => line.trim());
542
- const inline = `[${values.map((entry) => entry.replace(/,$/, "")).join(", ")}]`;
543
- return inline.length <= 70 ? inline : match;
544
- }
545
- );
546
- }
547
-
548
- // core-engine/snapshots/store.ts
549
- var BARREL_SCOPE = "_barrels";
550
- var REMOVED_SCOPE = "_removed";
551
- function normalizeLineEndings(content) {
552
- return content.replace(/\r\n/g, "\n");
553
- }
554
- function hashContent(content) {
555
- return `sha256-${crypto.createHash("sha256").update(normalizeLineEndings(content)).digest("hex")}`;
556
- }
557
- function snapshotRoot(cwd) {
558
- return path7.join(cwd, ".betterstart", "snapshots");
559
- }
560
- function scopeDir(cwd, scope) {
561
- return path7.join(snapshotRoot(cwd), scope);
562
- }
563
- function manifestPath(cwd, scope) {
564
- return path7.join(scopeDir(cwd, scope), "manifest.json");
565
- }
566
- function filesDir(cwd, scope) {
567
- return path7.join(scopeDir(cwd, scope), "files");
568
- }
569
- function snapshotFilePath(cwd, scope, filePath) {
570
- return path7.join(filesDir(cwd, scope), ...filePath.split("/"));
571
- }
572
- function removedDir(cwd) {
573
- return path7.join(snapshotRoot(cwd), REMOVED_SCOPE);
574
- }
575
- function tombstonePath(cwd, scope) {
576
- return path7.join(removedDir(cwd), scope);
577
- }
578
- function loadManifest(cwd, scope) {
579
- const filePath = manifestPath(cwd, scope);
580
- if (!fs6.existsSync(filePath)) {
581
- return null;
582
- }
583
- return JSON.parse(fs6.readFileSync(filePath, "utf-8"));
584
- }
585
- function saveManifest(cwd, scope, manifest) {
586
- fs6.mkdirSync(scopeDir(cwd, scope), { recursive: true });
587
- fs6.writeFileSync(manifestPath(cwd, scope), stringifyProjectJson(manifest), "utf-8");
588
- }
589
- function writeSnapshotFiles(cwd, scope, files) {
590
- const dir = filesDir(cwd, scope);
591
- fs6.rmSync(dir, { recursive: true, force: true });
592
- fs6.mkdirSync(dir, { recursive: true });
593
- return files.map((file) => {
594
- const outputPath = snapshotFilePath(cwd, scope, file.path);
595
- fs6.mkdirSync(path7.dirname(outputPath), { recursive: true });
596
- fs6.writeFileSync(outputPath, file.content, "utf-8");
597
- return {
598
- path: file.path,
599
- hash: hashContent(file.content)
600
- };
601
- });
602
- }
603
- function readSnapshotFiles(cwd, scope, manifest) {
604
- return manifest.files.filter((entry) => fs6.existsSync(snapshotFilePath(cwd, scope, entry.path))).map((entry) => ({
605
- path: entry.path,
606
- content: fs6.readFileSync(snapshotFilePath(cwd, scope, entry.path), "utf-8")
607
- }));
608
- }
609
- function deleteSnapshot(cwd, scope) {
610
- fs6.rmSync(scopeDir(cwd, scope), { recursive: true, force: true });
611
- }
612
- function hasSnapshotFiles(cwd, scope) {
613
- return fs6.existsSync(filesDir(cwd, scope));
614
- }
615
- function writeTombstone(cwd, scope) {
616
- fs6.mkdirSync(removedDir(cwd), { recursive: true });
617
- fs6.writeFileSync(tombstonePath(cwd, scope), "", "utf-8");
618
- }
619
- function hasTombstone(cwd, scope) {
620
- return fs6.existsSync(tombstonePath(cwd, scope));
621
- }
622
- function clearTombstone(cwd, scope) {
623
- fs6.rmSync(tombstonePath(cwd, scope), { force: true });
624
- }
625
- function listSnapshotScopes(cwd) {
626
- const dir = snapshotRoot(cwd);
627
- if (!fs6.existsSync(dir)) {
628
- return [];
629
- }
630
- return fs6.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => name !== REMOVED_SCOPE).sort();
631
- }
632
- function createManifest(scope, schemaJson, cliVersion, files, skipped) {
633
- return {
634
- schemaName: scope,
635
- schemaHash: hashContent(JSON.stringify(schemaJson)),
636
- schemaJson,
637
- cliVersion,
638
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
639
- files: files.map((file) => ({
640
- path: file.path,
641
- hash: hashContent(file.content)
642
- })),
643
- skipped: [...skipped].sort()
644
- };
645
- }
646
- function snapshotRootExists(cwd) {
647
- return fs6.existsSync(snapshotRoot(cwd));
648
- }
649
- function manifestFilesByPath(manifest) {
650
- return new Map(manifest.files.map((file) => [file.path, file]));
651
- }
652
- function loadAllManifests(cwd) {
653
- return listSnapshotScopes(cwd).filter((scope) => scope !== BARREL_SCOPE).map((scope) => ({ scope, manifest: loadManifest(cwd, scope) })).filter(
654
- (entry) => entry.manifest !== null
655
- );
656
- }
657
- function snapshotTargetPath(cwd, filePath) {
658
- return path7.join(cwd, ...filePath.split("/"));
659
- }
660
- function getCurrentCliVersion() {
661
- let currentDir = path7.dirname(new URL(import.meta.url).pathname);
662
- for (let depth = 0; depth < 6; depth++) {
663
- const packagePath = path7.join(currentDir, "package.json");
664
- if (fs6.existsSync(packagePath)) {
665
- try {
666
- const pkg = JSON.parse(fs6.readFileSync(packagePath, "utf-8"));
667
- if (pkg.name === "betterstart-cli" && pkg.version) {
668
- return pkg.version;
669
- }
670
- } catch {
671
- }
672
- }
673
- const parentDir = path7.dirname(currentDir);
674
- if (parentDir === currentDir) {
675
- break;
676
- }
677
- currentDir = parentDir;
678
- }
679
- return "0.0.0";
680
- }
681
- function getAllTrackedFilePaths(cwd) {
682
- const paths = /* @__PURE__ */ new Set();
683
- for (const { manifest } of loadAllManifests(cwd)) {
684
- for (const file of manifest.files) {
685
- paths.add(file.path);
686
- }
687
- }
688
- const barrelManifest = loadManifest(cwd, BARREL_SCOPE);
689
- if (barrelManifest) {
690
- for (const file of barrelManifest.files) {
691
- paths.add(file.path);
692
- }
693
- }
694
- return Array.from(paths).sort();
695
- }
696
-
697
700
  // adapters/next/init/scaffolders/dependencies.ts
698
701
  import { spawn } from "child_process";
699
702
  import fs7 from "fs";
@@ -22696,13 +22699,13 @@ import { spawn as spawn3 } from "child_process";
22696
22699
  import fs27 from "fs";
22697
22700
  import path33 from "path";
22698
22701
  var LOCAL_PROTOCOL_PATTERN = /^(workspace|link|file|portal):/;
22699
- var ADMIN_CONFIG_IMPORT_PATTERN = /^import\s+\{[^}]*\bdefineConfig\b[^}]*\}\s+from\s+['"]betterstart-cli['"];?[^\S\n]*$/m;
22700
- var ADMIN_CONFIG_IMPORT_SHIM = "const defineConfig = <T>(config: T): T => config";
22702
+ var CONFIG_IMPORT_PATTERN = /^import\s+\{[^}]*\bdefineConfig\b[^}]*\}\s+from\s+['"]betterstart-cli['"];?[^\S\n]*$/m;
22703
+ var CONFIG_IMPORT_SHIM = "const defineConfig = <T>(config: T): T => config";
22701
22704
  var LOCKFILE_REFRESH_TIMEOUT_MS = 12e4;
22702
22705
  async function guardProjectForDeploy(cwd, refreshLockfile = runPnpmLockfileOnly) {
22703
22706
  const restores = [];
22704
22707
  const { localSpecDeps, removedCliDep } = guardPackageJson(cwd, restores);
22705
- guardAdminConfig(cwd, restores);
22708
+ guardBetterstartConfig(cwd, restores);
22706
22709
  const lockfile = removedCliDep ? await guardPnpmLockfile(cwd, restores, refreshLockfile) : "not-needed";
22707
22710
  return {
22708
22711
  localSpecDeps,
@@ -22776,17 +22779,13 @@ function runPnpmLockfileOnly(cwd) {
22776
22779
  });
22777
22780
  });
22778
22781
  }
22779
- function guardAdminConfig(cwd, restores) {
22780
- const adminConfigPath = path33.join(cwd, "admin.config.ts");
22781
- if (!fs27.existsSync(adminConfigPath)) return;
22782
- const original = fs27.readFileSync(adminConfigPath, "utf-8");
22783
- if (!ADMIN_CONFIG_IMPORT_PATTERN.test(original)) return;
22784
- fs27.writeFileSync(
22785
- adminConfigPath,
22786
- original.replace(ADMIN_CONFIG_IMPORT_PATTERN, ADMIN_CONFIG_IMPORT_SHIM),
22787
- "utf-8"
22788
- );
22789
- restores.push(() => fs27.writeFileSync(adminConfigPath, original, "utf-8"));
22782
+ function guardBetterstartConfig(cwd, restores) {
22783
+ const configPath = path33.join(cwd, CONFIG_FILE_NAME);
22784
+ if (!fs27.existsSync(configPath)) return;
22785
+ const original = fs27.readFileSync(configPath, "utf-8");
22786
+ if (!CONFIG_IMPORT_PATTERN.test(original)) return;
22787
+ fs27.writeFileSync(configPath, original.replace(CONFIG_IMPORT_PATTERN, CONFIG_IMPORT_SHIM), "utf-8");
22788
+ restores.push(() => fs27.writeFileSync(configPath, original, "utf-8"));
22790
22789
  }
22791
22790
 
22792
22791
  // adapters/next/init/railway/project.ts
@@ -23908,8 +23907,8 @@ function scaffoldBase({
23908
23907
  ensureDir(path38.resolve(cwd, dir));
23909
23908
  }
23910
23909
  const configContent = serializeConfig(config);
23911
- if (safeWriteFile(path38.resolve(cwd, "admin.config.ts"), configContent)) {
23912
- created.push("admin.config.ts");
23910
+ if (safeWriteFile(path38.resolve(cwd, CONFIG_FILE_NAME), configContent)) {
23911
+ created.push(CONFIG_FILE_NAME);
23913
23912
  }
23914
23913
  return created;
23915
23914
  }
@@ -26976,7 +26975,7 @@ function resolveNonInteractiveProject(name) {
26976
26975
  return { projectName };
26977
26976
  }
26978
26977
  async function readExistingConfigNamespace(cwd) {
26979
- const configPath = path52.resolve(cwd, "admin.config.ts");
26978
+ const configPath = path52.resolve(cwd, CONFIG_FILE_NAME);
26980
26979
  if (!fs41.existsSync(configPath)) {
26981
26980
  return;
26982
26981
  }
@@ -26993,7 +26992,7 @@ async function readExistingConfigNamespace(cwd) {
26993
26992
  }
26994
26993
  async function resolveForceInitNamespaces(cwd, targetNamespace) {
26995
26994
  const namespaces = /* @__PURE__ */ new Set([validateAdminNamespace(targetNamespace)]);
26996
- const hasConfig = fs41.existsSync(path52.resolve(cwd, "admin.config.ts"));
26995
+ const hasConfig = fs41.existsSync(path52.resolve(cwd, CONFIG_FILE_NAME));
26997
26996
  const existingNamespace = await readExistingConfigNamespace(cwd);
26998
26997
  if (existingNamespace) {
26999
26998
  namespaces.add(existingNamespace);
@@ -27015,7 +27014,7 @@ function removeExistingAdminPaths(cwd, namespaces) {
27015
27014
  ...segments.flatMap((segment) => [segment, `app/(${segment})`, `src/app/(${segment})`]),
27016
27015
  ".betterstart"
27017
27016
  ];
27018
- const nukeFiles = ["admin.config.ts", "ADMIN.md", "drizzle.config.ts"];
27017
+ const nukeFiles = [CONFIG_FILE_NAME, "ADMIN.md", "drizzle.config.ts"];
27019
27018
  let removed = 0;
27020
27019
  for (const dir of nukeDirs) {
27021
27020
  const fullPath = path52.resolve(cwd, dir);
@@ -27772,7 +27771,7 @@ async function runInitCommand(name, options) {
27772
27771
  }
27773
27772
  }
27774
27773
  if (seedResult.success) {
27775
- const seedSuccessMessage = seedOverwriteMode === "admin" ? `Admin user replaced` : `Admin user ${pc9.green(seedEmail)} successfully created`;
27774
+ const seedSuccessMessage = seedOverwriteMode === "admin" ? `Admin user replaced` : `Admin user ${pc9.green(seedEmail)} created`;
27776
27775
  s.stop(seedSuccessMessage);
27777
27776
  rowsBelowCredentialPrompts += clackLogRows(seedSuccessMessage);
27778
27777
  eraseRowsAbove(credentialPromptRows, rowsBelowCredentialPrompts);
@@ -28837,7 +28836,7 @@ function buildUninstallPlan(cwd, namespaceValue) {
28837
28836
  const configFiles = [];
28838
28837
  const configPaths = [];
28839
28838
  const candidates = [
28840
- ["admin.config.ts", path57.join(cwd, "admin.config.ts")],
28839
+ [CONFIG_FILE_NAME, path57.join(cwd, CONFIG_FILE_NAME)],
28841
28840
  ["drizzle.config.ts", path57.join(cwd, "drizzle.config.ts")],
28842
28841
  ["ADMIN.md", path57.join(cwd, "ADMIN.md")]
28843
28842
  ];