create-velocity-astro 1.8.0 → 1.8.1

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/index.js CHANGED
@@ -474,8 +474,8 @@ function showSuccess(message) {
474
474
  }
475
475
 
476
476
  // src/scaffold.ts
477
- import { existsSync as existsSync5, mkdirSync as mkdirSync3, readdirSync as readdirSync2, copyFileSync as copyFileSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3, rmSync } from "fs";
478
- import { join as join4, dirname as dirname3 } from "path";
477
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readdirSync as readdirSync3, copyFileSync as copyFileSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3, rmSync } from "fs";
478
+ import { join as join5, dirname as dirname3 } from "path";
479
479
  import * as p2 from "@clack/prompts";
480
480
  import { execa as execa2 } from "execa";
481
481
  import { downloadTemplate } from "giget";
@@ -808,6 +808,110 @@ function createInitialConfig(options, version) {
808
808
  };
809
809
  }
810
810
 
811
+ // src/utils/diff.ts
812
+ import { createHash } from "crypto";
813
+ import { existsSync as existsSync5, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
814
+ import { join as join4, relative } from "path";
815
+ function hashFile(filePath) {
816
+ const content = readFileSync3(filePath);
817
+ return createHash("sha256").update(content).digest("hex");
818
+ }
819
+ function computeFileHashes(baseDir, paths) {
820
+ const hashes = {};
821
+ const expanded = expandPaths(paths, baseDir);
822
+ for (const filePath of expanded) {
823
+ const fullPath = join4(baseDir, filePath);
824
+ if (existsSync5(fullPath) && !statSync2(fullPath).isDirectory()) {
825
+ hashes[filePath] = hashFile(fullPath);
826
+ }
827
+ }
828
+ return hashes;
829
+ }
830
+ function walkDir(dir, baseDir) {
831
+ const results = [];
832
+ if (!existsSync5(dir)) return results;
833
+ const entries = readdirSync2(dir, { withFileTypes: true });
834
+ for (const entry of entries) {
835
+ const fullPath = join4(dir, entry.name);
836
+ if (entry.isDirectory()) {
837
+ results.push(...walkDir(fullPath, baseDir));
838
+ } else {
839
+ results.push(relative(baseDir, fullPath));
840
+ }
841
+ }
842
+ return results;
843
+ }
844
+ function expandPaths(paths, freshDir) {
845
+ const files = [];
846
+ for (const p6 of paths) {
847
+ const fullPath = join4(freshDir, p6);
848
+ if (p6.endsWith("/") || existsSync5(fullPath) && statSync2(fullPath).isDirectory()) {
849
+ files.push(...walkDir(fullPath, freshDir));
850
+ } else {
851
+ files.push(p6);
852
+ }
853
+ }
854
+ return [...new Set(files)];
855
+ }
856
+ function normalizePath(filePath) {
857
+ return filePath.replace(/\\/g, "/");
858
+ }
859
+ function diffProjects(currentDir, freshDir, manifest, storedHashes) {
860
+ const diffs = [];
861
+ const safeFiles = expandPaths(manifest.files.safe, freshDir);
862
+ for (const filePath of safeFiles) {
863
+ const currentPath = join4(currentDir, filePath);
864
+ const freshPath = join4(freshDir, filePath);
865
+ const normalizedPath = normalizePath(filePath);
866
+ if (!existsSync5(freshPath)) continue;
867
+ if (!existsSync5(currentPath)) {
868
+ diffs.push({ path: filePath, status: "added", category: "safe" });
869
+ } else {
870
+ const currentContent = readFileSync3(currentPath);
871
+ const freshContent = readFileSync3(freshPath);
872
+ if (Buffer.compare(currentContent, freshContent) === 0) {
873
+ diffs.push({ path: filePath, status: "unchanged", category: "safe" });
874
+ } else {
875
+ const storedHash = storedHashes?.[normalizedPath];
876
+ if (storedHash) {
877
+ const currentHash = createHash("sha256").update(currentContent).digest("hex");
878
+ if (currentHash !== storedHash) {
879
+ diffs.push({ path: filePath, status: "conflict", category: "safe" });
880
+ } else {
881
+ diffs.push({ path: filePath, status: "modified", category: "safe" });
882
+ }
883
+ } else {
884
+ diffs.push({ path: filePath, status: "modified", category: "safe" });
885
+ }
886
+ }
887
+ }
888
+ }
889
+ return diffs;
890
+ }
891
+ function summarizeDiffs(diffs) {
892
+ let added = 0;
893
+ let modified = 0;
894
+ let unchanged = 0;
895
+ let conflict = 0;
896
+ for (const diff of diffs) {
897
+ switch (diff.status) {
898
+ case "added":
899
+ added++;
900
+ break;
901
+ case "modified":
902
+ modified++;
903
+ break;
904
+ case "unchanged":
905
+ unchanged++;
906
+ break;
907
+ case "conflict":
908
+ conflict++;
909
+ break;
910
+ }
911
+ }
912
+ return { added, modified, unchanged, conflict };
913
+ }
914
+
811
915
  // src/scaffold.ts
812
916
  var TEMPLATE_REPO = "github:southwellmedia/velocity";
813
917
  var CLEANUP_ITEMS = [
@@ -845,13 +949,13 @@ var OPTIONAL_COMPONENT_DIRS = [
845
949
  "src/components/hero"
846
950
  ];
847
951
  function copyTemplateFiles(src, dest) {
848
- if (!existsSync5(dest)) {
952
+ if (!existsSync6(dest)) {
849
953
  mkdirSync3(dest, { recursive: true });
850
954
  }
851
- const entries = readdirSync2(src, { withFileTypes: true });
955
+ const entries = readdirSync3(src, { withFileTypes: true });
852
956
  for (const entry of entries) {
853
- const srcPath = join4(src, entry.name);
854
- const destPath = join4(dest, entry.name);
957
+ const srcPath = join5(src, entry.name);
958
+ const destPath = join5(dest, entry.name);
855
959
  if (entry.isDirectory()) {
856
960
  copyTemplateFiles(srcPath, destPath);
857
961
  } else {
@@ -861,8 +965,8 @@ function copyTemplateFiles(src, dest) {
861
965
  }
862
966
  function removeItems(targetDir, items) {
863
967
  for (const item of items) {
864
- const itemPath = join4(targetDir, item);
865
- if (existsSync5(itemPath)) {
968
+ const itemPath = join5(targetDir, item);
969
+ if (existsSync6(itemPath)) {
866
970
  try {
867
971
  rmSync(itemPath, { recursive: true, force: true });
868
972
  } catch {
@@ -872,10 +976,10 @@ function removeItems(targetDir, items) {
872
976
  }
873
977
  function walkFilesRelative(absDir, relativeBase) {
874
978
  const results = [];
875
- if (!existsSync5(absDir)) return results;
876
- const entries = readdirSync2(absDir, { withFileTypes: true });
979
+ if (!existsSync6(absDir)) return results;
980
+ const entries = readdirSync3(absDir, { withFileTypes: true });
877
981
  for (const entry of entries) {
878
- const absPath = join4(absDir, entry.name);
982
+ const absPath = join5(absDir, entry.name);
879
983
  const relPath = `${relativeBase}/${entry.name}`;
880
984
  if (entry.isDirectory()) {
881
985
  results.push(...walkFilesRelative(absPath, relPath));
@@ -886,14 +990,14 @@ function walkFilesRelative(absDir, relativeBase) {
886
990
  return results;
887
991
  }
888
992
  function removeEmptyDirs(dir) {
889
- if (!existsSync5(dir)) return;
890
- const entries = readdirSync2(dir, { withFileTypes: true });
993
+ if (!existsSync6(dir)) return;
994
+ const entries = readdirSync3(dir, { withFileTypes: true });
891
995
  for (const entry of entries) {
892
996
  if (entry.isDirectory()) {
893
- removeEmptyDirs(join4(dir, entry.name));
997
+ removeEmptyDirs(join5(dir, entry.name));
894
998
  }
895
999
  }
896
- const remaining = readdirSync2(dir);
1000
+ const remaining = readdirSync3(dir);
897
1001
  if (remaining.length === 0) {
898
1002
  try {
899
1003
  rmSync(dir, { recursive: true, force: true });
@@ -908,13 +1012,13 @@ function keepOnlyFiles(targetDir, filesToKeep) {
908
1012
  "src/components/hero"
909
1013
  ];
910
1014
  for (const dir of componentDirs) {
911
- const dirPath = join4(targetDir, dir);
912
- if (!existsSync5(dirPath)) continue;
1015
+ const dirPath = join5(targetDir, dir);
1016
+ if (!existsSync6(dirPath)) continue;
913
1017
  const allFiles = walkFilesRelative(dirPath, dir);
914
1018
  for (const relativePath of allFiles) {
915
1019
  if (!filesToKeep.has(relativePath)) {
916
1020
  try {
917
- rmSync(join4(targetDir, relativePath), { force: true });
1021
+ rmSync(join5(targetDir, relativePath), { force: true });
918
1022
  } catch {
919
1023
  }
920
1024
  }
@@ -923,11 +1027,11 @@ function keepOnlyFiles(targetDir, filesToKeep) {
923
1027
  }
924
1028
  }
925
1029
  function updatePackageJson(targetDir, projectName) {
926
- const pkgPath = join4(targetDir, "package.json");
927
- if (!existsSync5(pkgPath)) {
1030
+ const pkgPath = join5(targetDir, "package.json");
1031
+ if (!existsSync6(pkgPath)) {
928
1032
  throw new Error("package.json not found in template");
929
1033
  }
930
- const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
1034
+ const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
931
1035
  pkg.name = projectName;
932
1036
  pkg.version = "0.1.0";
933
1037
  delete pkg.repository;
@@ -937,7 +1041,7 @@ function updatePackageJson(targetDir, projectName) {
937
1041
  }
938
1042
  function applyBaseTemplate(targetDir) {
939
1043
  const baseTemplate = getBaseTemplatePath();
940
- if (existsSync5(baseTemplate)) {
1044
+ if (existsSync6(baseTemplate)) {
941
1045
  copyTemplateFiles(baseTemplate, targetDir);
942
1046
  }
943
1047
  }
@@ -950,10 +1054,10 @@ function createContentDirectories(targetDir) {
950
1054
  "src/content/blog"
951
1055
  ];
952
1056
  for (const dir of contentDirs) {
953
- const dirPath = join4(targetDir, dir);
954
- if (!existsSync5(dirPath)) {
1057
+ const dirPath = join5(targetDir, dir);
1058
+ if (!existsSync6(dirPath)) {
955
1059
  mkdirSync3(dirPath, { recursive: true });
956
- writeFileSync3(join4(dirPath, ".gitkeep"), "");
1060
+ writeFileSync3(join5(dirPath, ".gitkeep"), "");
957
1061
  }
958
1062
  }
959
1063
  }
@@ -976,9 +1080,9 @@ async function applyComponentSelection(targetDir, selection) {
976
1080
  const filesToKeep = new Set(resolved.files);
977
1081
  keepOnlyFiles(targetDir, filesToKeep);
978
1082
  if (resolved.utilities.includes("cn")) {
979
- const cnPath = join4(targetDir, "src/lib/cn.ts");
1083
+ const cnPath = join5(targetDir, "src/lib/cn.ts");
980
1084
  const cnDir = dirname3(cnPath);
981
- if (!existsSync5(cnDir)) {
1085
+ if (!existsSync6(cnDir)) {
982
1086
  mkdirSync3(cnDir, { recursive: true });
983
1087
  }
984
1088
  }
@@ -1048,16 +1152,22 @@ ${error instanceof Error ? error.message : ""}`
1048
1152
  }
1049
1153
  try {
1050
1154
  let templateVersion = "0.1.0-beta";
1051
- const manifestPath = join4(targetDir, "velocity-manifest.json");
1052
- const pkgPath = join4(targetDir, "package.json");
1053
- if (existsSync5(manifestPath)) {
1155
+ const manifestPath = join5(targetDir, "velocity-manifest.json");
1156
+ const pkgPath = join5(targetDir, "package.json");
1157
+ if (existsSync6(manifestPath)) {
1054
1158
  const manifest = readJson(manifestPath);
1055
1159
  if (manifest.version) templateVersion = manifest.version;
1056
- } else if (existsSync5(pkgPath)) {
1160
+ } else if (existsSync6(pkgPath)) {
1057
1161
  const pkg = readJson(pkgPath);
1058
1162
  if (pkg.version) templateVersion = pkg.version;
1059
1163
  }
1060
1164
  const velocityConfig = createInitialConfig(options, templateVersion);
1165
+ if (existsSync6(manifestPath)) {
1166
+ const manifest = readJson(manifestPath);
1167
+ if (manifest.files?.safe) {
1168
+ velocityConfig.fileHashes = computeFileHashes(targetDir, manifest.files.safe);
1169
+ }
1170
+ }
1061
1171
  writeVelocityConfig(targetDir, velocityConfig);
1062
1172
  } catch {
1063
1173
  }
@@ -1082,84 +1192,14 @@ ${error instanceof Error ? error.message : ""}`
1082
1192
  }
1083
1193
 
1084
1194
  // src/upgrade.ts
1085
- import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, copyFileSync as copyFileSync3, readdirSync as readdirSync4, rmSync as rmSync2, statSync as statSync4 } from "fs";
1195
+ import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, copyFileSync as copyFileSync3, readdirSync as readdirSync4, rmSync as rmSync2, statSync as statSync3 } from "fs";
1086
1196
  import { execSync } from "child_process";
1087
- import { join as join6, dirname as dirname4, relative as relative3 } from "path";
1197
+ import { join as join6, dirname as dirname4, relative as relative2 } from "path";
1088
1198
  import { tmpdir } from "os";
1089
1199
  import * as p4 from "@clack/prompts";
1090
1200
  import pc3 from "picocolors";
1091
1201
  import { downloadTemplate as downloadTemplate2 } from "giget";
1092
1202
 
1093
- // src/utils/diff.ts
1094
- import { existsSync as existsSync6, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
1095
- import { join as join5, relative as relative2 } from "path";
1096
- function walkDir(dir, baseDir) {
1097
- const results = [];
1098
- if (!existsSync6(dir)) return results;
1099
- const entries = readdirSync3(dir, { withFileTypes: true });
1100
- for (const entry of entries) {
1101
- const fullPath = join5(dir, entry.name);
1102
- if (entry.isDirectory()) {
1103
- results.push(...walkDir(fullPath, baseDir));
1104
- } else {
1105
- results.push(relative2(baseDir, fullPath));
1106
- }
1107
- }
1108
- return results;
1109
- }
1110
- function expandPaths(paths, freshDir) {
1111
- const files = [];
1112
- for (const p6 of paths) {
1113
- const fullPath = join5(freshDir, p6);
1114
- if (p6.endsWith("/") || existsSync6(fullPath) && statSync3(fullPath).isDirectory()) {
1115
- files.push(...walkDir(fullPath, freshDir));
1116
- } else {
1117
- files.push(p6);
1118
- }
1119
- }
1120
- return [...new Set(files)];
1121
- }
1122
- function diffProjects(currentDir, freshDir, manifest) {
1123
- const diffs = [];
1124
- const safeFiles = expandPaths(manifest.files.safe, freshDir);
1125
- for (const filePath of safeFiles) {
1126
- const currentPath = join5(currentDir, filePath);
1127
- const freshPath = join5(freshDir, filePath);
1128
- if (!existsSync6(freshPath)) continue;
1129
- if (!existsSync6(currentPath)) {
1130
- diffs.push({ path: filePath, status: "added", category: "safe" });
1131
- } else {
1132
- const currentContent = readFileSync4(currentPath);
1133
- const freshContent = readFileSync4(freshPath);
1134
- if (Buffer.compare(currentContent, freshContent) === 0) {
1135
- diffs.push({ path: filePath, status: "unchanged", category: "safe" });
1136
- } else {
1137
- diffs.push({ path: filePath, status: "modified", category: "safe" });
1138
- }
1139
- }
1140
- }
1141
- return diffs;
1142
- }
1143
- function summarizeDiffs(diffs) {
1144
- let added = 0;
1145
- let modified = 0;
1146
- let unchanged = 0;
1147
- for (const diff of diffs) {
1148
- switch (diff.status) {
1149
- case "added":
1150
- added++;
1151
- break;
1152
- case "modified":
1153
- modified++;
1154
- break;
1155
- case "unchanged":
1156
- unchanged++;
1157
- break;
1158
- }
1159
- }
1160
- return { added, modified, unchanged };
1161
- }
1162
-
1163
1203
  // src/upgrade-prompts.ts
1164
1204
  import * as p3 from "@clack/prompts";
1165
1205
  import pc2 from "picocolors";
@@ -1172,9 +1212,16 @@ Latest version: ${pc2.green(`v${latestVersion}`)}`
1172
1212
  );
1173
1213
  }
1174
1214
  function showChangeSummary(diffs, manifest) {
1175
- const { added, modified } = summarizeDiffs(diffs);
1215
+ const { added, modified, conflict } = summarizeDiffs(diffs);
1176
1216
  const migrationCount = manifest.migrations.length;
1177
1217
  const lines = [];
1218
+ const conflictFiles = diffs.filter((d) => d.status === "conflict");
1219
+ if (conflictFiles.length > 0) {
1220
+ lines.push(pc2.bold(pc2.yellow(" Conflicts (user-modified files that also changed in template):")));
1221
+ for (const f of conflictFiles) {
1222
+ lines.push(` ${pc2.yellow("\u26A0")} ${f.path} ${pc2.dim("\u2192 backup created, template version applied")}`);
1223
+ }
1224
+ }
1178
1225
  const modifiedFiles = diffs.filter((d) => d.status === "modified");
1179
1226
  const addedFiles = diffs.filter((d) => d.status === "added");
1180
1227
  if (modifiedFiles.length > 0) {
@@ -1210,6 +1257,7 @@ function showChangeSummary(diffs, manifest) {
1210
1257
  const summary = [];
1211
1258
  if (modified > 0) summary.push(`${modified} updated`);
1212
1259
  if (added > 0) summary.push(`${added} added`);
1260
+ if (conflict > 0) summary.push(`${pc2.yellow(`${conflict} conflicts`)}`);
1213
1261
  summary.push(`${manifest.files.protected.length} protected ${pc2.dim("(not touched)")}`);
1214
1262
  lines.push("");
1215
1263
  lines.push(` ${pc2.dim("Totals: " + summary.join(", "))}`);
@@ -1231,11 +1279,29 @@ function showProtectedNotice(manifest) {
1231
1279
  lines.push(pc2.dim("If the upgrade requires changes to these files, they will appear in the manual steps below."));
1232
1280
  p3.log.info(lines.join("\n"));
1233
1281
  }
1234
- async function confirmUpgrade(dryRun) {
1282
+ function showConflictNotice(backupDir, conflicts) {
1283
+ if (conflicts.length === 0) return;
1284
+ const lines = [
1285
+ pc2.yellow(`${conflicts.length} file${conflicts.length !== 1 ? "s were" : " was"} backed up because you modified ${conflicts.length !== 1 ? "them" : "it"}:`),
1286
+ ""
1287
+ ];
1288
+ for (const f of conflicts) {
1289
+ lines.push(` ${pc2.yellow("\u26A0")} ${f.path}`);
1290
+ }
1291
+ lines.push("");
1292
+ lines.push(`Your versions are saved in: ${pc2.cyan(backupDir)}`);
1293
+ lines.push(pc2.dim("Compare your backup against the new version and merge your customizations back in."));
1294
+ p3.log.warning(lines.join("\n"));
1295
+ }
1296
+ async function confirmUpgrade(dryRun, yes) {
1235
1297
  if (dryRun) {
1236
1298
  p3.log.info(pc2.dim("Dry run \u2014 no changes will be made."));
1237
1299
  return false;
1238
1300
  }
1301
+ if (yes) {
1302
+ p3.log.info(pc2.dim("Proceeding with upgrade (--yes)."));
1303
+ return true;
1304
+ }
1239
1305
  const proceed = await p3.confirm({
1240
1306
  message: "Proceed with upgrade?",
1241
1307
  initialValue: true
@@ -1359,7 +1425,7 @@ function scanForMigrationPatterns(targetDir, migrations) {
1359
1425
  try {
1360
1426
  const content = readFileSync5(file, "utf-8");
1361
1427
  if (regex.test(content)) {
1362
- matches.push(relative3(targetDir, file));
1428
+ matches.push(relative2(targetDir, file));
1363
1429
  }
1364
1430
  } catch {
1365
1431
  }
@@ -1372,7 +1438,7 @@ function scanForMigrationPatterns(targetDir, migrations) {
1372
1438
  function walkFiles(dir) {
1373
1439
  const results = [];
1374
1440
  if (!existsSync7(dir)) return results;
1375
- const stat = statSync4(dir);
1441
+ const stat = statSync3(dir);
1376
1442
  if (!stat.isDirectory()) {
1377
1443
  return [dir];
1378
1444
  }
@@ -1416,6 +1482,21 @@ function mergePackageJsonDeps(targetDir, manifest) {
1416
1482
  }
1417
1483
  writeFileSync4(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
1418
1484
  }
1485
+ function backupConflicts(targetDir, conflicts, fromVersion) {
1486
+ const backupDir = join6(targetDir, ".velocity-backup", fromVersion);
1487
+ for (const conflict of conflicts) {
1488
+ const srcPath = join6(targetDir, conflict.path);
1489
+ const destPath = join6(backupDir, conflict.path);
1490
+ const destDir = dirname4(destPath);
1491
+ if (!existsSync7(destDir)) {
1492
+ mkdirSync4(destDir, { recursive: true });
1493
+ }
1494
+ if (existsSync7(srcPath)) {
1495
+ copyFileSync3(srcPath, destPath);
1496
+ }
1497
+ }
1498
+ return backupDir;
1499
+ }
1419
1500
  async function upgrade(options) {
1420
1501
  const { targetDir, dryRun, yes } = options;
1421
1502
  const config = readVelocityConfig(targetDir);
@@ -1479,7 +1560,7 @@ async function upgrade(options) {
1479
1560
  migrations: []
1480
1561
  };
1481
1562
  }
1482
- if (isVersionLessThan("1.8.0", manifest.minCliVersion)) {
1563
+ if (isVersionLessThan("1.8.1", manifest.minCliVersion)) {
1483
1564
  p4.log.error(
1484
1565
  pc3.red(
1485
1566
  `This upgrade requires create-velocity-astro >= ${manifest.minCliVersion}.
@@ -1497,9 +1578,9 @@ Run \`npm update -g create-velocity-astro\` to update.`
1497
1578
  cleanup(tempDir);
1498
1579
  return;
1499
1580
  }
1500
- const diffs = diffProjects(targetDir, tempDir, manifest);
1501
- const { added, modified } = summarizeDiffs(diffs);
1502
- if (added === 0 && modified === 0 && Object.keys(manifest.dependencies.update).length === 0 && manifest.dependencies.remove.length === 0 && Object.keys(manifest.dependencies.add).length === 0) {
1581
+ const diffs = diffProjects(targetDir, tempDir, manifest, config.fileHashes);
1582
+ const { added, modified, conflict } = summarizeDiffs(diffs);
1583
+ if (added === 0 && modified === 0 && conflict === 0 && Object.keys(manifest.dependencies.update).length === 0 && manifest.dependencies.remove.length === 0 && Object.keys(manifest.dependencies.add).length === 0) {
1503
1584
  showUpgradeIntro(config.version, manifest.version);
1504
1585
  p4.log.info(pc3.green("All files are up to date. Updating version marker only."));
1505
1586
  if (!dryRun) {
@@ -1515,7 +1596,7 @@ Run \`npm update -g create-velocity-astro\` to update.`
1515
1596
  }
1516
1597
  showUpgradeIntro(config.version, manifest.version);
1517
1598
  showChangeSummary(diffs, manifest);
1518
- const shouldProceed = await confirmUpgrade(dryRun);
1599
+ const shouldProceed = await confirmUpgrade(dryRun, yes);
1519
1600
  if (dryRun) {
1520
1601
  showProtectedNotice(manifest);
1521
1602
  const matchResults2 = scanForMigrationPatterns(targetDir, manifest.migrations);
@@ -1529,7 +1610,14 @@ Run \`npm update -g create-velocity-astro\` to update.`
1529
1610
  return;
1530
1611
  }
1531
1612
  spinner3.start("Applying changes...");
1532
- const changedDiffs = diffs.filter((d) => d.status === "added" || d.status === "modified");
1613
+ const conflictDiffs = diffs.filter((d) => d.status === "conflict");
1614
+ let backupDir = "";
1615
+ if (conflictDiffs.length > 0) {
1616
+ backupDir = backupConflicts(targetDir, conflictDiffs, config.version);
1617
+ }
1618
+ const changedDiffs = diffs.filter(
1619
+ (d) => d.status === "added" || d.status === "modified" || d.status === "conflict"
1620
+ );
1533
1621
  for (const diff of changedDiffs) {
1534
1622
  const src = join6(tempDir, diff.path);
1535
1623
  const dest = join6(targetDir, diff.path);
@@ -1543,10 +1631,12 @@ Run \`npm update -g create-velocity-astro\` to update.`
1543
1631
  if (hasDepChanges) {
1544
1632
  mergePackageJsonDeps(targetDir, manifest);
1545
1633
  }
1634
+ const newHashes = computeFileHashes(targetDir, manifest.files.safe);
1546
1635
  writeVelocityConfig(targetDir, {
1547
1636
  ...config,
1548
1637
  version: manifest.version,
1549
- updatedAt: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
1638
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
1639
+ fileHashes: newHashes
1550
1640
  });
1551
1641
  spinner3.stop("Changes applied");
1552
1642
  if (modified > 0) {
@@ -1559,6 +1649,9 @@ Run \`npm update -g create-velocity-astro\` to update.`
1559
1649
  p4.log.success(pc3.green("Updated package.json dependencies"));
1560
1650
  }
1561
1651
  p4.log.success(pc3.green("Updated .velocity.json"));
1652
+ if (conflictDiffs.length > 0) {
1653
+ showConflictNotice(backupDir, conflictDiffs);
1654
+ }
1562
1655
  showProtectedNotice(manifest);
1563
1656
  const matchResults = scanForMigrationPatterns(targetDir, manifest.migrations);
1564
1657
  showManualSteps(manifest.migrations, matchResults);
@@ -1613,7 +1706,7 @@ ${pc4.bold("Examples:")}
1613
1706
  pnpm create velocity-astro upgrade
1614
1707
  pnpm create velocity-astro upgrade --dry-run
1615
1708
  `;
1616
- var VERSION = "1.8.0";
1709
+ var VERSION = "1.8.1";
1617
1710
  function parseComponentsFlag(value) {
1618
1711
  if (value === void 0) {
1619
1712
  return void 0;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/prompts.ts","../src/utils/validate.ts","../src/utils/package-manager.ts","../src/registry/fetcher.ts","../src/registry/resolver.ts","../src/scaffold.ts","../src/template.ts","../src/utils/git.ts","../src/features/pages.ts","../src/utils/velocity-config.ts","../src/utils/fs.ts","../src/upgrade.ts","../src/utils/diff.ts","../src/upgrade-prompts.ts","../src/index.ts"],"sourcesContent":["import mri from 'mri';\r\nimport { resolve } from 'node:path';\r\nimport { existsSync } from 'node:fs';\r\nimport * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport type { CliOptions } from './types.js';\r\nimport type { ComponentSelection } from './registry/types.js';\r\nimport { runPrompts, showIntro, showOutro, showError } from './prompts.js';\r\nimport { scaffold } from './scaffold.js';\r\nimport { upgrade } from './upgrade.js';\r\nimport { isEmptyDir } from './utils/fs.js';\r\nimport { toValidProjectName } from './utils/validate.js';\r\n\r\ndeclare const CLI_VERSION: string;\r\n\r\nconst HELP_TEXT = `\r\n${pc.bold('create-velocity-astro')} - Create and upgrade Velocity projects\r\n\r\n${pc.bold('Usage:')}\r\n npm create velocity-astro@latest [project-name] [options]\r\n pnpm create velocity-astro [project-name] [options]\r\n\r\n${pc.bold('Commands:')}\r\n ${pc.cyan('upgrade')} Upgrade an existing Velocity project to the latest version\r\n --dry-run Preview changes without applying them\r\n --yes, -y Skip confirmation prompts\r\n\r\n${pc.bold('Options:')}\r\n --demo Include demo landing page and sample content\r\n --components Include all components (default: prompt for selection)\r\n --components=none Exclude all components\r\n --components=ui,patterns Include specific categories\r\n --i18n Add internationalization support\r\n --pages Prompt for starter pages to generate\r\n --yes, -y Skip prompts and use defaults\r\n --help, -h Show this help message\r\n --version, -v Show version number\r\n\r\n${pc.bold('Component Categories:')}\r\n ui UI components (buttons, forms, cards, dialogs) - 31 components\r\n patterns Form patterns (contact form, newsletter, search) - 7 components\r\n hero Flexible hero section component - 1 component\r\n\r\n${pc.bold('Examples:')}\r\n npm create velocity-astro@latest my-site\r\n npm create velocity-astro@latest my-site --demo --components\r\n npm create velocity-astro@latest my-site --components=ui,patterns\r\n pnpm create velocity-astro my-site -y\r\n\r\n ${pc.dim('# Upgrade an existing project')}\r\n pnpm create velocity-astro upgrade\r\n pnpm create velocity-astro upgrade --dry-run\r\n`;\r\n\r\nconst VERSION = CLI_VERSION;\r\n\r\n/**\r\n * Parses the --components flag into a ComponentSelection\r\n */\r\nfunction parseComponentsFlag(value: string | boolean | undefined): ComponentSelection | undefined {\r\n // Not specified - will prompt user\r\n if (value === undefined) {\r\n return undefined;\r\n }\r\n\r\n // --components (boolean true) - include all\r\n if (value === true) {\r\n return { mode: 'all' };\r\n }\r\n\r\n // --components=false or explicit false\r\n if (value === false) {\r\n return { mode: 'none' };\r\n }\r\n\r\n // --components=none\r\n if (value === 'none' || value === 'false') {\r\n return { mode: 'none' };\r\n }\r\n\r\n // --components=all\r\n if (value === 'all' || value === 'true') {\r\n return { mode: 'all' };\r\n }\r\n\r\n // --components=ui,patterns,hero (category list)\r\n const categories = value.split(',').map((s) => s.trim().toLowerCase());\r\n const validCategories = ['ui', 'patterns', 'hero'];\r\n const filtered = categories.filter((c) => validCategories.includes(c));\r\n\r\n if (filtered.length === 0) {\r\n return { mode: 'all' }; // Fall back to all if no valid categories\r\n }\r\n\r\n return { mode: 'categories', categories: filtered };\r\n}\r\n\r\nexport async function run(argv: string[]): Promise<void> {\r\n const args = mri<CliOptions>(argv, {\r\n boolean: ['demo', 'i18n', 'pages', 'help', 'version', 'yes', 'dry-run'],\r\n string: ['components'],\r\n alias: {\r\n h: 'help',\r\n v: 'version',\r\n y: 'yes',\r\n },\r\n });\r\n\r\n // Handle help\r\n if (args.help) {\r\n console.log(HELP_TEXT);\r\n return;\r\n }\r\n\r\n // Handle version\r\n if (args.version) {\r\n console.log(VERSION);\r\n return;\r\n }\r\n\r\n // Handle upgrade subcommand\r\n const subcommand = args._[0] as string | undefined;\r\n if (subcommand === 'upgrade') {\r\n const targetDir = resolve(process.cwd());\r\n await upgrade({\r\n targetDir,\r\n dryRun: (args as unknown as Record<string, unknown>)['dry-run'] as boolean || false,\r\n yes: args.yes || false,\r\n });\r\n return;\r\n }\r\n\r\n showIntro();\r\n\r\n // Get project name from args or prompt\r\n const argProjectName = args._[0] as string | undefined;\r\n\r\n // Parse component selection from CLI\r\n const componentSelection = parseComponentsFlag(args.components);\r\n\r\n // Skip prompts mode\r\n if (args.yes) {\r\n const projectName = toValidProjectName(argProjectName || 'my-velocity-site');\r\n const targetDir = resolve(process.cwd(), projectName);\r\n\r\n if (existsSync(targetDir) && !isEmptyDir(targetDir)) {\r\n showError(`Directory \"${projectName}\" already exists and is not empty.`);\r\n process.exit(1);\r\n }\r\n\r\n await scaffold({\r\n projectName,\r\n targetDir,\r\n demo: args.demo || false,\r\n componentSelection: componentSelection || { mode: 'all' },\r\n i18n: args.i18n || false,\r\n pages: [],\r\n pageLayout: 'page',\r\n packageManager: 'pnpm',\r\n });\r\n\r\n showOutro(projectName, 'pnpm');\r\n return;\r\n }\r\n\r\n // Interactive mode\r\n const answers = await runPrompts({\r\n projectName: argProjectName,\r\n demo: args.demo,\r\n componentSelection: componentSelection,\r\n i18n: args.i18n,\r\n pages: args.pages,\r\n });\r\n\r\n // User cancelled\r\n if (typeof answers === 'symbol') {\r\n return;\r\n }\r\n\r\n const { projectName, demo, componentSelection: selectedComponents, i18n, pages, pageLayout, packageManager } = answers;\r\n const targetDir = resolve(process.cwd(), projectName);\r\n\r\n // Check if directory exists and is not empty\r\n if (existsSync(targetDir) && !isEmptyDir(targetDir)) {\r\n const shouldOverwrite = await p.confirm({\r\n message: `Directory \"${projectName}\" already exists. Continue and overwrite?`,\r\n initialValue: false,\r\n });\r\n\r\n if (!shouldOverwrite || p.isCancel(shouldOverwrite)) {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // Run scaffold\r\n try {\r\n await scaffold({\r\n projectName,\r\n targetDir,\r\n demo,\r\n componentSelection: selectedComponents,\r\n i18n,\r\n pages,\r\n pageLayout,\r\n packageManager,\r\n });\r\n\r\n showOutro(projectName, packageManager);\r\n } catch (error) {\r\n showError(error instanceof Error ? error.message : 'An unexpected error occurred');\r\n process.exit(1);\r\n }\r\n}\r\n","import * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport type { PackageManager, PageLayout, PromptAnswers } from './types.js';\r\nimport type { ComponentSelection, ComponentRegistry, ComponentSelectionMode } from './registry/types.js';\r\nimport { validateProjectName, toValidProjectName } from './utils/validate.js';\r\nimport { detectPackageManager } from './utils/package-manager.js';\r\nimport { fetchRegistry } from './registry/fetcher.js';\r\nimport { getComponentsByCategory, resolveDependencies, getSelectionStats } from './registry/resolver.js';\r\n\r\ninterface PromptDefaults {\r\n projectName?: string;\r\n demo?: boolean;\r\n componentSelection?: ComponentSelection;\r\n i18n?: boolean;\r\n pages?: boolean;\r\n}\r\n\r\n/**\r\n * Parses comma-separated page names into an array of valid page slugs\r\n */\r\nfunction parsePageNames(input: string): string[] {\r\n if (!input.trim()) return [];\r\n\r\n return input\r\n .split(',')\r\n .map((name) => name.trim().toLowerCase())\r\n .filter((name) => name.length > 0)\r\n .map((name) => name.replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, ''))\r\n .filter((name) => name.length > 0 && !['index', 'blog', '404', 'rss'].includes(name));\r\n}\r\n\r\n/**\r\n * Prompts user for component selection mode\r\n */\r\nasync function promptComponentMode(): Promise<ComponentSelectionMode> {\r\n const result = await p.select({\r\n message: 'Include optional components?',\r\n options: [\r\n {\r\n value: 'all' as ComponentSelectionMode,\r\n label: 'All',\r\n hint: 'Include all 24 optional components',\r\n },\r\n {\r\n value: 'categories' as ComponentSelectionMode,\r\n label: 'Select categories',\r\n hint: 'Choose component groups',\r\n },\r\n {\r\n value: 'individual' as ComponentSelectionMode,\r\n label: 'Select individual',\r\n hint: 'Pick specific components',\r\n },\r\n {\r\n value: 'none' as ComponentSelectionMode,\r\n label: 'None',\r\n hint: 'Minimal template',\r\n },\r\n ],\r\n initialValue: 'all' as ComponentSelectionMode,\r\n });\r\n\r\n if (p.isCancel(result)) {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Prompts user to select component categories\r\n */\r\nasync function promptCategories(registry: ComponentRegistry): Promise<string[]> {\r\n const categoryOptions = Object.entries(registry.categories).map(([id, cat]) => {\r\n const componentCount = getComponentsByCategory(id, registry).length;\r\n return {\r\n value: id,\r\n label: cat.name,\r\n hint: `${componentCount} components - ${cat.description}`,\r\n };\r\n });\r\n\r\n const result = await p.multiselect({\r\n message: 'Select component categories:',\r\n options: categoryOptions,\r\n required: true,\r\n });\r\n\r\n if (p.isCancel(result)) {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n }\r\n\r\n return result as string[];\r\n}\r\n\r\n/**\r\n * Prompts user to select individual components\r\n */\r\nasync function promptComponents(registry: ComponentRegistry): Promise<string[]> {\r\n // Group components by category for better UX\r\n const componentsByCategory: Record<string, { value: string; label: string; hint: string }[]> = {};\r\n\r\n for (const [id, comp] of Object.entries(registry.components)) {\r\n if (!componentsByCategory[comp.category]) {\r\n componentsByCategory[comp.category] = [];\r\n }\r\n const depCount = comp.dependencies.components.length;\r\n const depHint = depCount > 0 ? ` (requires ${depCount} dep${depCount > 1 ? 's' : ''})` : '';\r\n const categoryName = registry.categories[comp.category]?.name ?? comp.category;\r\n componentsByCategory[comp.category]!.push({\r\n value: id,\r\n label: comp.name,\r\n hint: `${categoryName}${depHint}`,\r\n });\r\n }\r\n\r\n // Flatten into options with category headers\r\n const options: { value: string; label: string; hint?: string }[] = [];\r\n for (const [categoryId, components] of Object.entries(componentsByCategory)) {\r\n const categoryName = registry.categories[categoryId]?.name || categoryId;\r\n // Add all components from this category\r\n for (const comp of components) {\r\n options.push({\r\n ...comp,\r\n hint: categoryName,\r\n });\r\n }\r\n }\r\n\r\n const result = await p.multiselect({\r\n message: 'Select components (dependencies auto-included):',\r\n options,\r\n required: true,\r\n });\r\n\r\n if (p.isCancel(result)) {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n }\r\n\r\n return result as string[];\r\n}\r\n\r\n/**\r\n * Gets component selection from user prompts\r\n */\r\nasync function getComponentSelection(\r\n defaultSelection?: ComponentSelection\r\n): Promise<ComponentSelection> {\r\n if (defaultSelection) {\r\n return defaultSelection;\r\n }\r\n\r\n let registry: ComponentRegistry;\r\n try {\r\n registry = await fetchRegistry();\r\n } catch {\r\n // Fallback to simple yes/no if registry unavailable\r\n const useComponents = await p.select({\r\n message: 'Include UI component library?',\r\n options: [\r\n { value: true, label: 'Yes', hint: 'Buttons, forms, cards, dialogs, etc.' },\r\n { value: false, label: 'No', hint: 'Just the basics' },\r\n ],\r\n initialValue: true,\r\n });\r\n\r\n if (p.isCancel(useComponents)) {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n }\r\n\r\n return { mode: useComponents ? 'all' : 'none' };\r\n }\r\n\r\n const mode = await promptComponentMode();\r\n\r\n switch (mode) {\r\n case 'none':\r\n return { mode: 'none' };\r\n\r\n case 'all':\r\n return { mode: 'all' };\r\n\r\n case 'categories': {\r\n const categories = await promptCategories(registry);\r\n // Show what will be included\r\n const selection: ComponentSelection = { mode: 'categories', categories };\r\n const resolved = resolveDependencies(selection, registry);\r\n const stats = getSelectionStats(resolved, registry);\r\n p.log.info(\r\n pc.dim(`Selected ${stats.componentCount} components (${resolved.files.length} files)`)\r\n );\r\n return selection;\r\n }\r\n\r\n case 'individual': {\r\n const components = await promptComponents(registry);\r\n // Show what will be included (with dependencies)\r\n const selection: ComponentSelection = { mode: 'individual', components };\r\n const resolved = resolveDependencies(selection, registry);\r\n const stats = getSelectionStats(resolved, registry);\r\n if (resolved.components.length > components.length) {\r\n p.log.info(\r\n pc.dim(\r\n `Selected ${components.length} components + ${resolved.components.length - components.length} dependencies (${resolved.files.length} files)`\r\n )\r\n );\r\n } else {\r\n p.log.info(\r\n pc.dim(`Selected ${stats.componentCount} components (${resolved.files.length} files)`)\r\n );\r\n }\r\n return selection;\r\n }\r\n }\r\n}\r\n\r\nexport async function runPrompts(defaults: PromptDefaults = {}): Promise<PromptAnswers | symbol> {\r\n const detectedPm = detectPackageManager();\r\n\r\n const answers = await p.group(\r\n {\r\n projectName: () =>\r\n p.text({\r\n message: 'What is your project name?',\r\n placeholder: defaults.projectName || 'my-velocity-site',\r\n defaultValue: defaults.projectName,\r\n validate: (value) => {\r\n const name = value || defaults.projectName || 'my-velocity-site';\r\n const result = validateProjectName(toValidProjectName(name));\r\n if (!result.valid) return result.message;\r\n },\r\n }),\r\n\r\n demo:\r\n defaults.demo !== undefined\r\n ? () => Promise.resolve(defaults.demo)\r\n : () =>\r\n p.select({\r\n message: 'Include demo landing page and sample content?',\r\n options: [\r\n {\r\n value: false,\r\n label: 'No',\r\n hint: 'Minimal starter with basic pages',\r\n },\r\n {\r\n value: true,\r\n label: 'Yes',\r\n hint: 'Full demo with landing page, blog posts',\r\n },\r\n ],\r\n initialValue: false,\r\n }),\r\n\r\n componentSelection: () => getComponentSelection(defaults.componentSelection),\r\n\r\n i18n:\r\n defaults.i18n !== undefined\r\n ? () => Promise.resolve(defaults.i18n)\r\n : () =>\r\n p.select({\r\n message: 'Add internationalization (i18n)?',\r\n options: [\r\n {\r\n value: false,\r\n label: 'No',\r\n hint: 'English only',\r\n },\r\n {\r\n value: true,\r\n label: 'Yes',\r\n hint: 'Locale routing, translations',\r\n },\r\n ],\r\n initialValue: false,\r\n }),\r\n\r\n generatePages:\r\n defaults.pages !== undefined\r\n ? () => Promise.resolve(defaults.pages)\r\n : () =>\r\n p.select({\r\n message: 'Generate starter pages?',\r\n options: [\r\n {\r\n value: false,\r\n label: 'No',\r\n hint: 'Create pages manually later',\r\n },\r\n {\r\n value: true,\r\n label: 'Yes',\r\n hint: 'Auto-generate page files with layout',\r\n },\r\n ],\r\n initialValue: false,\r\n }),\r\n\r\n pageNames: ({ results }) =>\r\n results.generatePages\r\n ? p.text({\r\n message: 'Enter page names (comma-separated):',\r\n placeholder: 'about, pricing, faq, contact',\r\n validate: (value) => {\r\n const pages = parsePageNames(value);\r\n if (pages.length === 0) {\r\n return 'Please enter at least one valid page name';\r\n }\r\n },\r\n })\r\n : Promise.resolve(''),\r\n\r\n pageLayout: ({ results }) =>\r\n results.generatePages\r\n ? results.demo\r\n ? p.select({\r\n message: 'Select layout for pages:',\r\n options: [\r\n {\r\n value: 'page' as PageLayout,\r\n label: 'PageLayout',\r\n hint: 'Standard content pages (Header + Footer)',\r\n },\r\n {\r\n value: 'landing' as PageLayout,\r\n label: 'LandingLayout',\r\n hint: 'Marketing pages (Navbar + LandingFooter)',\r\n },\r\n ],\r\n initialValue: 'page' as PageLayout,\r\n })\r\n : Promise.resolve('page' as PageLayout) // Force PageLayout when demo=No\r\n : Promise.resolve('page' as PageLayout),\r\n\r\n packageManager: () =>\r\n p.select({\r\n message: 'Which package manager?',\r\n options: [\r\n {\r\n value: 'pnpm' as PackageManager,\r\n label: 'pnpm',\r\n hint: detectedPm === 'pnpm' ? 'detected' : 'recommended',\r\n },\r\n {\r\n value: 'npm' as PackageManager,\r\n label: 'npm',\r\n hint: detectedPm === 'npm' ? 'detected' : undefined,\r\n },\r\n {\r\n value: 'yarn' as PackageManager,\r\n label: 'yarn',\r\n hint: detectedPm === 'yarn' ? 'detected' : undefined,\r\n },\r\n {\r\n value: 'bun' as PackageManager,\r\n label: 'bun',\r\n hint: detectedPm === 'bun' ? 'detected' : undefined,\r\n },\r\n ],\r\n initialValue: detectedPm,\r\n }),\r\n },\r\n {\r\n onCancel: () => {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n },\r\n }\r\n );\r\n\r\n return {\r\n projectName: toValidProjectName(answers.projectName || defaults.projectName || 'my-velocity-site'),\r\n demo: answers.demo as boolean,\r\n componentSelection: answers.componentSelection as ComponentSelection,\r\n i18n: answers.i18n as boolean,\r\n pages: parsePageNames(answers.pageNames as string),\r\n pageLayout: (answers.pageLayout as PageLayout) || 'page',\r\n packageManager: answers.packageManager as PackageManager,\r\n };\r\n}\r\n\r\nexport function showIntro(): void {\r\n console.log();\r\n p.intro(pc.bgCyan(pc.black(' Create Velocity ')));\r\n}\r\n\r\nexport function showOutro(projectName: string, packageManager: PackageManager): void {\r\n const runCmd = packageManager === 'npm' ? 'npm run' : packageManager;\r\n\r\n p.note(\r\n [\r\n `cd ${projectName}`,\r\n `${runCmd} dev`,\r\n ].join('\\n'),\r\n 'Next steps'\r\n );\r\n\r\n p.outro(pc.green('Happy building!'));\r\n}\r\n\r\nexport function showError(message: string): void {\r\n p.log.error(pc.red(message));\r\n}\r\n\r\nexport function showWarning(message: string): void {\r\n p.log.warn(pc.yellow(message));\r\n}\r\n\r\nexport function showSuccess(message: string): void {\r\n p.log.success(pc.green(message));\r\n}\r\n\r\nexport function showStep(message: string): void {\r\n p.log.step(message);\r\n}\r\n","/**\n * Validates a project name for npm package naming conventions\n */\nexport function validateProjectName(name: string): { valid: boolean; message?: string } {\n if (!name || name.trim() === '') {\n return { valid: false, message: 'Project name cannot be empty' };\n }\n\n // Must be lowercase\n if (name !== name.toLowerCase()) {\n return { valid: false, message: 'Project name must be lowercase' };\n }\n\n // Cannot start with . or _\n if (name.startsWith('.') || name.startsWith('_')) {\n return { valid: false, message: 'Project name cannot start with . or _' };\n }\n\n // Cannot contain spaces\n if (/\\s/.test(name)) {\n return { valid: false, message: 'Project name cannot contain spaces' };\n }\n\n // Cannot contain special characters except - and @/\n if (!/^(@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name)) {\n return {\n valid: false,\n message: 'Project name can only contain lowercase letters, numbers, hyphens, and underscores',\n };\n }\n\n // Length check\n if (name.length > 214) {\n return { valid: false, message: 'Project name must be 214 characters or fewer' };\n }\n\n return { valid: true };\n}\n\n/**\n * Sanitizes a string to be a valid project name\n */\nexport function toValidProjectName(name: string): string {\n return name\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-_~.]/g, '-')\n .replace(/^[-._]+/, '')\n .replace(/[-._]+$/, '')\n .replace(/-+/g, '-');\n}\n","import type { PackageManager } from '../types.js';\n\n/**\n * Detects the package manager used to run this command\n */\nexport function detectPackageManager(): PackageManager {\n const userAgent = process.env.npm_config_user_agent || '';\n\n if (userAgent.startsWith('pnpm')) return 'pnpm';\n if (userAgent.startsWith('yarn')) return 'yarn';\n if (userAgent.startsWith('bun')) return 'bun';\n return 'npm';\n}\n\n/**\n * Gets the install command for a package manager\n */\nexport function getInstallCommand(pm: PackageManager): string {\n switch (pm) {\n case 'pnpm':\n return 'pnpm install';\n case 'yarn':\n return 'yarn';\n case 'bun':\n return 'bun install';\n case 'npm':\n default:\n return 'npm install';\n }\n}\n\n/**\n * Gets the run command for a package manager\n */\nexport function getRunCommand(pm: PackageManager): string {\n switch (pm) {\n case 'pnpm':\n return 'pnpm';\n case 'yarn':\n return 'yarn';\n case 'bun':\n return 'bun';\n case 'npm':\n default:\n return 'npm run';\n }\n}\n","/**\n * Registry Fetcher\n * Fetches the component registry from GitHub\n */\n\nimport type { ComponentRegistry } from './types.js';\n\nconst REGISTRY_URL = 'https://raw.githubusercontent.com/southwellmedia/velocity/main/component-registry.json';\n\nlet cachedRegistry: ComponentRegistry | null = null;\n\n/**\n * Fetches the component registry from GitHub\n * Results are cached for the duration of the process\n */\nexport async function fetchRegistry(): Promise<ComponentRegistry> {\n if (cachedRegistry) {\n return cachedRegistry;\n }\n\n try {\n const response = await fetch(REGISTRY_URL);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch registry: ${response.status} ${response.statusText}`);\n }\n\n cachedRegistry = await response.json() as ComponentRegistry;\n return cachedRegistry;\n } catch (error) {\n throw new Error(\n `Could not fetch component registry. Please check your internet connection.\\n${error instanceof Error ? error.message : ''}`\n );\n }\n}\n\n/**\n * Fetches a single file from the velocity repository\n */\nexport async function fetchComponentFile(filePath: string): Promise<string> {\n const url = `https://raw.githubusercontent.com/southwellmedia/velocity/main/${filePath}`;\n\n try {\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch file: ${response.status} ${response.statusText}`);\n }\n\n return response.text();\n } catch (error) {\n throw new Error(\n `Could not fetch file: ${filePath}\\n${error instanceof Error ? error.message : ''}`\n );\n }\n}\n\n/**\n * Clears the cached registry\n */\nexport function clearRegistryCache(): void {\n cachedRegistry = null;\n}\n","/**\n * Dependency Resolver\n * Resolves component dependencies and collects all required files\n */\n\nimport type { ComponentRegistry, ComponentSelection, ResolvedComponents } from './types.js';\n\n/**\n * Resolves dependencies for requested components\n * Returns all components, utilities, files, and npm packages needed\n */\nexport function resolveDependencies(\n selection: ComponentSelection,\n registry: ComponentRegistry\n): ResolvedComponents {\n const resolved = new Set<string>();\n const utilities = new Set<string>();\n const files = new Set<string>();\n const npmPackages = new Set<string>();\n\n // Handle different selection modes\n let requestedComponents: string[] = [];\n\n switch (selection.mode) {\n case 'none':\n return { components: [], utilities: [], files: [], npmPackages: [] };\n\n case 'all':\n requestedComponents = Object.keys(registry.components);\n break;\n\n case 'categories':\n if (selection.categories) {\n requestedComponents = Object.entries(registry.components)\n .filter(([, comp]) => selection.categories!.includes(comp.category))\n .map(([id]) => id);\n }\n break;\n\n case 'individual':\n requestedComponents = selection.components || [];\n break;\n }\n\n // Recursively resolve each component's dependencies\n function resolve(componentId: string): void {\n if (resolved.has(componentId)) return;\n\n const component = registry.components[componentId];\n if (!component) {\n console.warn(`Component not found: ${componentId}`);\n return;\n }\n\n // Resolve component dependencies first (recursive)\n for (const dep of component.dependencies.components) {\n resolve(dep);\n }\n\n // Collect utilities\n for (const util of component.dependencies.utilities) {\n utilities.add(util);\n }\n\n // Collect files\n for (const file of component.files) {\n files.add(file);\n }\n\n resolved.add(componentId);\n }\n\n // Resolve all requested components\n for (const componentId of requestedComponents) {\n resolve(componentId);\n }\n\n // Collect utility files and npm packages\n for (const utilId of utilities) {\n const utility = registry.utilities[utilId];\n if (utility) {\n for (const file of utility.files) {\n files.add(file);\n }\n for (const pkg of utility.npm) {\n npmPackages.add(pkg);\n }\n }\n }\n\n return {\n components: [...resolved],\n utilities: [...utilities],\n files: [...files],\n npmPackages: [...npmPackages],\n };\n}\n\n/**\n * Gets all components in a category\n */\nexport function getComponentsByCategory(\n categoryId: string,\n registry: ComponentRegistry\n): string[] {\n return Object.entries(registry.components)\n .filter(([, comp]) => comp.category === categoryId)\n .map(([id]) => id);\n}\n\n/**\n * Gets the dependency tree for a component (for visualization)\n */\nexport function getDependencyTree(\n componentId: string,\n registry: ComponentRegistry,\n visited = new Set<string>()\n): { id: string; name: string; deps: ReturnType<typeof getDependencyTree>[] } | null {\n if (visited.has(componentId)) return null;\n visited.add(componentId);\n\n const component = registry.components[componentId];\n if (!component) return null;\n\n const deps = component.dependencies.components\n .map((dep) => getDependencyTree(dep, registry, visited))\n .filter((d): d is NonNullable<typeof d> => d !== null);\n\n return {\n id: componentId,\n name: component.name,\n deps,\n };\n}\n\n/**\n * Validates that all components exist in the registry\n */\nexport function validateComponents(\n componentIds: string[],\n registry: ComponentRegistry\n): { valid: boolean; invalid: string[] } {\n const invalid = componentIds.filter((id) => !registry.components[id]);\n return {\n valid: invalid.length === 0,\n invalid,\n };\n}\n\n/**\n * Validates that all categories exist in the registry\n */\nexport function validateCategories(\n categoryIds: string[],\n registry: ComponentRegistry\n): { valid: boolean; invalid: string[] } {\n const invalid = categoryIds.filter((id) => !registry.categories[id]);\n return {\n valid: invalid.length === 0,\n invalid,\n };\n}\n\n/**\n * Gets summary stats for a component selection\n */\nexport function getSelectionStats(\n resolved: ResolvedComponents,\n registry: ComponentRegistry\n): { componentCount: number; fileCount: number; categories: string[] } {\n const categories = new Set<string>();\n\n for (const componentId of resolved.components) {\n const component = registry.components[componentId];\n if (component) {\n categories.add(component.category);\n }\n }\n\n return {\n componentCount: resolved.components.length,\n fileCount: resolved.files.length,\n categories: [...categories],\n };\n}\n","import { existsSync, mkdirSync, readdirSync, copyFileSync, readFileSync, writeFileSync, rmSync, statSync } from 'node:fs';\r\nimport { join, dirname, relative } from 'node:path';\r\nimport * as p from '@clack/prompts';\r\nimport { execa } from 'execa';\r\nimport { downloadTemplate } from 'giget';\r\nimport type { ScaffoldOptions } from './types.js';\r\nimport type { ComponentSelection, ResolvedComponents } from './registry/types.js';\r\nimport { getI18nTemplatePath, getBaseTemplatePath } from './template.js';\r\nimport { getInstallCommand } from './utils/package-manager.js';\r\nimport { initGit } from './utils/git.js';\r\nimport { showSuccess, showWarning } from './prompts.js';\r\nimport { generatePages } from './features/pages.js';\r\nimport { fetchRegistry } from './registry/fetcher.js';\r\nimport { resolveDependencies } from './registry/resolver.js';\r\nimport { createInitialConfig, writeVelocityConfig } from './utils/velocity-config.js';\r\nimport { readJson } from './utils/fs.js';\r\n\r\n// GitHub repository for the Velocity template\r\nconst TEMPLATE_REPO = 'github:southwellmedia/velocity';\r\n\r\n// Files/directories to remove after download\r\nconst CLEANUP_ITEMS = [\r\n 'pnpm-lock.yaml',\r\n 'package-lock.json',\r\n 'yarn.lock',\r\n 'bun.lockb',\r\n '.git',\r\n];\r\n\r\n// Demo-specific content to remove when --demo is false\r\n// Includes both base paths and i18n paths to handle all scenarios\r\nconst DEMO_CONTENT = [\r\n // Landing page components\r\n 'src/components/landing',\r\n 'src/components/hero',\r\n // Landing-specific pages (base paths)\r\n 'src/pages/index.astro',\r\n 'src/pages/about.astro',\r\n 'src/pages/contact.astro',\r\n 'src/pages/components.astro',\r\n // Landing-specific pages (i18n paths)\r\n 'src/pages/[lang]/index.astro',\r\n 'src/pages/[lang]/[...about].astro',\r\n 'src/pages/[lang]/[...contact].astro',\r\n 'src/pages/[lang]/[...components].astro',\r\n // Landing layout (depends on Navbar from landing components)\r\n 'src/layouts/LandingLayout.astro',\r\n // Demo content\r\n 'src/content/blog',\r\n 'src/content/faqs',\r\n 'src/content/authors',\r\n 'src/content/pages',\r\n];\r\n\r\n// Optional component directories (for removal when mode='none')\r\n// Note: layout, seo, landing, blog are core template - not optional\r\nconst OPTIONAL_COMPONENT_DIRS = [\r\n 'src/components/ui',\r\n 'src/components/patterns',\r\n 'src/components/hero',\r\n];\r\n\r\n/**\r\n * Copies template files recursively\r\n */\r\nfunction copyTemplateFiles(src: string, dest: string): void {\r\n if (!existsSync(dest)) {\r\n mkdirSync(dest, { recursive: true });\r\n }\r\n\r\n const entries = readdirSync(src, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const srcPath = join(src, entry.name);\r\n const destPath = join(dest, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n copyTemplateFiles(srcPath, destPath);\r\n } else {\r\n copyFileSync(srcPath, destPath);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Removes files/directories from the target\r\n */\r\nfunction removeItems(targetDir: string, items: string[]): void {\r\n for (const item of items) {\r\n const itemPath = join(targetDir, item);\r\n if (existsSync(itemPath)) {\r\n try {\r\n rmSync(itemPath, { recursive: true, force: true });\r\n } catch {\r\n // Ignore errors - item may not exist or be locked\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Recursively collects all file paths relative to the project root\r\n */\r\nfunction walkFilesRelative(absDir: string, relativeBase: string): string[] {\r\n const results: string[] = [];\r\n if (!existsSync(absDir)) return results;\r\n\r\n const entries = readdirSync(absDir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const absPath = join(absDir, entry.name);\r\n const relPath = `${relativeBase}/${entry.name}`;\r\n if (entry.isDirectory()) {\r\n results.push(...walkFilesRelative(absPath, relPath));\r\n } else {\r\n results.push(relPath);\r\n }\r\n }\r\n return results;\r\n}\r\n\r\n/**\r\n * Recursively removes empty directories bottom-up\r\n */\r\nfunction removeEmptyDirs(dir: string): void {\r\n if (!existsSync(dir)) return;\r\n\r\n const entries = readdirSync(dir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n if (entry.isDirectory()) {\r\n removeEmptyDirs(join(dir, entry.name));\r\n }\r\n }\r\n\r\n // Re-read after cleaning children\r\n const remaining = readdirSync(dir);\r\n if (remaining.length === 0) {\r\n try {\r\n rmSync(dir, { recursive: true, force: true });\r\n } catch {\r\n // Ignore errors\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Keeps only specified files, removes everything else in optional component directories.\r\n * Walks recursively to handle nested subcategory folders (e.g. ui/form/Button/).\r\n */\r\nfunction keepOnlyFiles(targetDir: string, filesToKeep: Set<string>): void {\r\n // Only filter optional component directories - core template dirs are untouched\r\n const componentDirs = [\r\n 'src/components/ui',\r\n 'src/components/patterns',\r\n 'src/components/hero',\r\n ];\r\n\r\n for (const dir of componentDirs) {\r\n const dirPath = join(targetDir, dir);\r\n if (!existsSync(dirPath)) continue;\r\n\r\n // Recursively walk all files in the directory\r\n const allFiles = walkFilesRelative(dirPath, dir);\r\n for (const relativePath of allFiles) {\r\n if (!filesToKeep.has(relativePath)) {\r\n try {\r\n rmSync(join(targetDir, relativePath), { force: true });\r\n } catch {\r\n // Ignore errors\r\n }\r\n }\r\n }\r\n\r\n // Clean up empty directories (bottom-up)\r\n removeEmptyDirs(dirPath);\r\n }\r\n}\r\n\r\n/**\r\n * Updates the package.json with the new project name\r\n */\r\nfunction updatePackageJson(targetDir: string, projectName: string): void {\r\n const pkgPath = join(targetDir, 'package.json');\r\n\r\n if (!existsSync(pkgPath)) {\r\n throw new Error('package.json not found in template');\r\n }\r\n\r\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\r\n pkg.name = projectName;\r\n pkg.version = '0.1.0';\r\n delete pkg.repository;\r\n delete pkg.bugs;\r\n delete pkg.homepage;\r\n\r\n writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\r\n}\r\n\r\n/**\r\n * Applies base template (minimal pages) when demo is not selected\r\n */\r\nfunction applyBaseTemplate(targetDir: string): void {\r\n const baseTemplate = getBaseTemplatePath();\r\n if (existsSync(baseTemplate)) {\r\n copyTemplateFiles(baseTemplate, targetDir);\r\n }\r\n}\r\n\r\n/**\r\n * Applies the i18n overlay to the project\r\n */\r\nfunction applyI18nOverlay(targetDir: string): void {\r\n const i18nTemplate = getI18nTemplatePath();\r\n copyTemplateFiles(i18nTemplate, targetDir);\r\n}\r\n\r\n/**\r\n * Creates empty content directories with .gitkeep files\r\n */\r\nfunction createContentDirectories(targetDir: string): void {\r\n const contentDirs = [\r\n 'src/content/blog',\r\n ];\r\n\r\n for (const dir of contentDirs) {\r\n const dirPath = join(targetDir, dir);\r\n if (!existsSync(dirPath)) {\r\n mkdirSync(dirPath, { recursive: true });\r\n writeFileSync(join(dirPath, '.gitkeep'), '');\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Applies selective component filtering based on registry resolution\r\n */\r\nasync function applyComponentSelection(\r\n targetDir: string,\r\n selection: ComponentSelection\r\n): Promise<void> {\r\n // Handle 'all' mode - keep everything\r\n if (selection.mode === 'all') {\r\n return;\r\n }\r\n\r\n // Handle 'none' mode - remove optional components only\r\n if (selection.mode === 'none') {\r\n removeItems(targetDir, OPTIONAL_COMPONENT_DIRS);\r\n return;\r\n }\r\n\r\n // For 'categories' and 'individual' modes, we need the registry\r\n let resolved: ResolvedComponents;\r\n try {\r\n const registry = await fetchRegistry();\r\n resolved = resolveDependencies(selection, registry);\r\n } catch {\r\n // If registry fetch fails, fall back to keeping all components\r\n console.warn('Could not fetch component registry, keeping all components');\r\n return;\r\n }\r\n\r\n // Create set of files to keep\r\n const filesToKeep = new Set(resolved.files);\r\n\r\n // Keep only the resolved files\r\n keepOnlyFiles(targetDir, filesToKeep);\r\n\r\n // Ensure utility files are present if needed\r\n if (resolved.utilities.includes('cn')) {\r\n const cnPath = join(targetDir, 'src/lib/cn.ts');\r\n const cnDir = dirname(cnPath);\r\n if (!existsSync(cnDir)) {\r\n mkdirSync(cnDir, { recursive: true });\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Main scaffold function\r\n *\r\n * IMPORTANT: Step order matters for option combinations\r\n * - i18n overlay is applied BEFORE demo removal\r\n * - This ensures demo=Yes + i18n=Yes gets full translated demo\r\n * - And demo=No + i18n=Yes gets i18n routing without demo pages\r\n */\r\nexport async function scaffold(options: ScaffoldOptions): Promise<void> {\r\n const { projectName, targetDir, demo, componentSelection, i18n, pages, pageLayout, packageManager } = options;\r\n const spinner = p.spinner();\r\n\r\n // Step 1: Download base template from GitHub\r\n spinner.start('Downloading template from GitHub...');\r\n\r\n try {\r\n await downloadTemplate(TEMPLATE_REPO, {\r\n dir: targetDir,\r\n force: true,\r\n });\r\n removeItems(targetDir, CLEANUP_ITEMS);\r\n spinner.stop('Template downloaded');\r\n } catch (error) {\r\n spinner.stop('Failed to download template');\r\n throw new Error(\r\n `Could not download template from GitHub. Please check your internet connection.\\n${error instanceof Error ? error.message : ''}`\r\n );\r\n }\r\n\r\n // Step 2: Apply component selection\r\n if (componentSelection.mode !== 'all') {\r\n spinner.start('Configuring components...');\r\n try {\r\n await applyComponentSelection(targetDir, componentSelection);\r\n spinner.stop('Components configured');\r\n } catch (error) {\r\n spinner.stop('Failed to configure components');\r\n throw error;\r\n }\r\n }\r\n\r\n // Step 3: Apply i18n overlay if requested (BEFORE demo removal)\r\n // This ensures demo=Yes + i18n=Yes gets translated demo pages\r\n if (i18n) {\r\n spinner.start('Adding i18n support...');\r\n try {\r\n applyI18nOverlay(targetDir);\r\n spinner.stop('i18n support added');\r\n } catch (error) {\r\n spinner.stop('Failed to add i18n support');\r\n throw error;\r\n }\r\n }\r\n\r\n // Step 4: Remove demo content LAST (handles both base and i18n paths)\r\n // This runs after i18n overlay so it can remove i18n demo pages if needed\r\n if (!demo) {\r\n spinner.start('Configuring minimal template...');\r\n removeItems(targetDir, DEMO_CONTENT);\r\n applyBaseTemplate(targetDir);\r\n createContentDirectories(targetDir);\r\n spinner.stop('Minimal template configured');\r\n }\r\n\r\n // Step 5: Generate starter pages if requested\r\n if (pages.length > 0) {\r\n spinner.start(`Generating ${pages.length} starter page${pages.length > 1 ? 's' : ''}...`);\r\n try {\r\n const generatedFiles = await generatePages(targetDir, pages, pageLayout, i18n);\r\n spinner.stop(`Generated ${generatedFiles.length} page file${generatedFiles.length > 1 ? 's' : ''}`);\r\n } catch (error) {\r\n spinner.stop('Failed to generate pages');\r\n throw error;\r\n }\r\n }\r\n\r\n // Step 6: Update package.json\r\n spinner.start('Configuring project...');\r\n try {\r\n updatePackageJson(targetDir, projectName);\r\n spinner.stop('Project configured');\r\n } catch (error) {\r\n spinner.stop('Failed to configure project');\r\n throw error;\r\n }\r\n\r\n // Step 6.5: Write .velocity.json\r\n try {\r\n let templateVersion = '0.1.0-beta';\r\n const manifestPath = join(targetDir, 'velocity-manifest.json');\r\n const pkgPath = join(targetDir, 'package.json');\r\n\r\n if (existsSync(manifestPath)) {\r\n const manifest = readJson<{ version?: string }>(manifestPath);\r\n if (manifest.version) templateVersion = manifest.version;\r\n } else if (existsSync(pkgPath)) {\r\n const pkg = readJson<{ version?: string }>(pkgPath);\r\n if (pkg.version) templateVersion = pkg.version;\r\n }\r\n\r\n const velocityConfig = createInitialConfig(options, templateVersion);\r\n writeVelocityConfig(targetDir, velocityConfig);\r\n } catch {\r\n // Non-fatal — project still usable without .velocity.json\r\n }\r\n\r\n // Step 7: Initialize git\r\n spinner.start('Initializing git repository...');\r\n const gitInitialized = await initGit(targetDir);\r\n if (gitInitialized) {\r\n spinner.stop('Git repository initialized');\r\n } else {\r\n spinner.stop('Git not available, skipping');\r\n }\r\n\r\n // Step 8: Install dependencies\r\n spinner.start(`Installing dependencies with ${packageManager}...`);\r\n try {\r\n const installCmd = getInstallCommand(packageManager);\r\n const [cmd, ...args] = installCmd.split(' ');\r\n await execa(cmd!, args, { cwd: targetDir });\r\n spinner.stop('Dependencies installed');\r\n } catch {\r\n spinner.stop('Failed to install dependencies');\r\n showWarning(`Run \"${getInstallCommand(packageManager)}\" manually to install dependencies`);\r\n }\r\n\r\n showSuccess(`Project \"${projectName}\" created successfully!`);\r\n}\r\n","import { existsSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Resolves the path to the base template (minimal pages)\n */\nexport function getBaseTemplatePath(): string {\n const templatePath = resolve(__dirname, '..', 'templates', 'base');\n\n if (existsSync(templatePath)) {\n return templatePath;\n }\n\n throw new Error('Could not find base template. Package may be corrupted.');\n}\n\n/**\n * Resolves the path to the i18n overlay template\n */\nexport function getI18nTemplatePath(): string {\n const templatePath = resolve(__dirname, '..', 'templates', 'i18n');\n\n if (existsSync(templatePath)) {\n return templatePath;\n }\n\n throw new Error('Could not find i18n template. Package may be corrupted.');\n}\n","import { execa } from 'execa';\n\n/**\n * Initializes a git repository in the target directory\n */\nexport async function initGit(targetDir: string): Promise<boolean> {\n try {\n await execa('git', ['init'], { cwd: targetDir });\n await execa('git', ['add', '-A'], { cwd: targetDir });\n await execa('git', ['commit', '-m', 'Initial commit from create-velocity'], {\n cwd: targetDir,\n });\n return true;\n } catch {\n // Git may not be installed or configured\n return false;\n }\n}\n\n/**\n * Checks if git is available\n */\nexport async function isGitInstalled(): Promise<boolean> {\n try {\n await execa('git', ['--version']);\n return true;\n } catch {\n return false;\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport type { PageLayout } from '../types.js';\r\n\r\n/**\r\n * Converts a page slug to a display title\r\n * e.g., 'about-us' -> 'About Us'\r\n */\r\nfunction toTitle(slug: string): string {\r\n return slug\r\n .split('-')\r\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\r\n .join(' ');\r\n}\r\n\r\n/**\r\n * Converts a page slug to a route ID (snake_case)\r\n * e.g., 'about-us' -> 'about_us'\r\n */\r\nfunction toRouteId(slug: string): string {\r\n return slug.replace(/-/g, '_');\r\n}\r\n\r\n/**\r\n * Calculates the next available nav order by finding the highest existing order\r\n */\r\nfunction getNextNavOrder(content: string): number {\r\n // Match all order values in nav configs\r\n const orderMatches = [...content.matchAll(/order:\\s*(\\d+)/g)];\r\n let maxOrder = 0;\r\n\r\n for (const match of orderMatches) {\r\n const orderStr = match[1];\r\n if (orderStr) {\r\n const order = parseInt(orderStr, 10);\r\n if (order > maxOrder) {\r\n maxOrder = order;\r\n }\r\n }\r\n }\r\n\r\n // Return the next order (10 more than current max for room to insert)\r\n return maxOrder + 10;\r\n}\r\n\r\n/**\r\n * Adds a new nav entry to nav.config.ts (non-i18n projects)\r\n * So the generated page appears in site navigation\r\n */\r\nfunction addNavEntry(targetDir: string, pageName: string): void {\r\n const navConfigPath = join(targetDir, 'src', 'config', 'nav.config.ts');\r\n\r\n if (!existsSync(navConfigPath)) {\r\n return; // nav.config.ts doesn't exist, skip\r\n }\r\n\r\n const title = toTitle(pageName);\r\n const content = readFileSync(navConfigPath, 'utf-8');\r\n\r\n // Check if entry already exists\r\n if (content.includes(`href: '/${pageName}'`)) {\r\n return; // Nav entry already defined\r\n }\r\n\r\n // Calculate the next nav order\r\n const navOrder = getNextNavOrder(content);\r\n\r\n // Find the closing bracket of the navItems array\r\n const insertPoint = content.indexOf('];');\r\n if (insertPoint === -1) {\r\n return; // Can't find insertion point\r\n }\r\n\r\n const newEntry = ` { label: '${title}', href: '/${pageName}', order: ${navOrder} },\\n`;\r\n\r\n const newContent = content.slice(0, insertPoint) + newEntry + content.slice(insertPoint);\r\n writeFileSync(navConfigPath, newContent);\r\n}\r\n\r\n/**\r\n * Adds a new route entry to i18n routes.ts\r\n * Creates the route with the same English slug for all locales (user customizes later)\r\n * Includes nav config so the page appears in navigation\r\n */\r\nfunction addI18nRouteEntry(targetDir: string, pageName: string): void {\r\n const routesPath = join(targetDir, 'src', 'i18n', 'routes.ts');\r\n\r\n if (!existsSync(routesPath)) {\r\n return; // routes.ts doesn't exist, skip\r\n }\r\n\r\n const routeId = toRouteId(pageName);\r\n const content = readFileSync(routesPath, 'utf-8');\r\n\r\n // Check if route already exists\r\n if (content.includes(`${routeId}:`)) {\r\n return; // Route already defined\r\n }\r\n\r\n // Find the closing of routes object (before \"} as const satisfies\")\r\n const insertPoint = content.indexOf('} as const satisfies');\r\n if (insertPoint === -1) {\r\n return; // Can't find insertion point\r\n }\r\n\r\n // Calculate the next nav order\r\n const navOrder = getNextNavOrder(content);\r\n\r\n // Create new route entry with nav config\r\n // Uses the route ID as the translation key (user should add translation)\r\n const title = toTitle(pageName);\r\n const newRoute = `\r\n // Custom page: ${pageName}\r\n ${routeId}: {\r\n en: '${pageName}', es: '${pageName}', fr: '${pageName}',\r\n nav: { show: true, order: ${navOrder}, label: 'nav.${routeId}' },\r\n },\r\n`;\r\n\r\n const newContent = content.slice(0, insertPoint) + newRoute + content.slice(insertPoint);\r\n writeFileSync(routesPath, newContent);\r\n\r\n // Also add translation keys to translation files\r\n addI18nTranslationKeys(targetDir, routeId, title);\r\n}\r\n\r\n/**\r\n * Adds translation keys for a new route to all i18n translation files\r\n */\r\nfunction addI18nTranslationKeys(targetDir: string, routeId: string, title: string): void {\r\n const locales = ['en', 'es', 'fr'];\r\n\r\n for (const locale of locales) {\r\n const translationPath = join(targetDir, 'src', 'i18n', 'translations', `${locale}.ts`);\r\n\r\n if (!existsSync(translationPath)) {\r\n continue;\r\n }\r\n\r\n let content = readFileSync(translationPath, 'utf-8');\r\n\r\n // Add nav translation if not exists\r\n if (!content.includes(`${routeId}:`)) {\r\n // Find the nav section and add the key\r\n const navSectionMatch = content.match(/nav:\\s*\\{([^}]+)\\}/);\r\n if (navSectionMatch) {\r\n const navSection = navSectionMatch[0];\r\n const insertPoint = navSection.lastIndexOf('}');\r\n const newNavSection =\r\n navSection.slice(0, insertPoint) +\r\n ` ${routeId}: '${title}',\\n ` +\r\n navSection.slice(insertPoint);\r\n content = content.replace(navSection, newNavSection);\r\n }\r\n }\r\n\r\n // Add page-specific translations if not exists\r\n const pageKeyPattern = new RegExp(`^\\\\s*${routeId}:\\\\s*\\\\{`, 'm');\r\n if (!pageKeyPattern.test(content)) {\r\n // Find a good insertion point (before the closing export)\r\n const insertPoint = content.lastIndexOf('} as const');\r\n if (insertPoint !== -1) {\r\n const pageTranslations = `\r\n // ${title} page\r\n ${routeId}: {\r\n title: '${title}',\r\n description: 'Add your ${title.toLowerCase()} page description here.',\r\n },\r\n\r\n`;\r\n content = content.slice(0, insertPoint) + pageTranslations + content.slice(insertPoint);\r\n }\r\n }\r\n\r\n writeFileSync(translationPath, content);\r\n }\r\n}\r\n\r\n/**\r\n * Generates the standard page template (non-i18n)\r\n */\r\nfunction generatePageTemplate(pageName: string, layout: PageLayout): string {\r\n const title = toTitle(pageName);\r\n const layoutName = layout === 'landing' ? 'LandingLayout' : 'PageLayout';\r\n\r\n return `---\r\nimport ${layoutName} from '@/layouts/${layoutName}.astro';\r\n---\r\n\r\n<${layoutName}\r\n title=\"${title}\"\r\n description=\"Add your description here\"\r\n>\r\n <!-- Hero Section -->\r\n <section class=\"py-20 bg-secondary\">\r\n <div class=\"container\">\r\n <h1 class=\"text-4xl font-bold text-foreground\">${title}</h1>\r\n <p class=\"mt-4 text-foreground-muted max-w-2xl\">\r\n Add your content here.\r\n </p>\r\n </div>\r\n </section>\r\n\r\n <!-- Content Section -->\r\n <section class=\"py-16\">\r\n <div class=\"container\">\r\n <!-- Your content -->\r\n </div>\r\n </section>\r\n</${layoutName}>\r\n`;\r\n}\r\n\r\n/**\r\n * Generates the i18n-aware page template with translated URL support\r\n */\r\nfunction generateI18nPageTemplate(pageName: string, layout: PageLayout): string {\r\n const title = toTitle(pageName);\r\n const layoutName = layout === 'landing' ? 'LandingLayout' : 'PageLayout';\r\n const routeId = toRouteId(pageName);\r\n const titleKey = `${routeId}.title`;\r\n const descKey = `${routeId}.description`;\r\n\r\n return `---\r\nimport ${layoutName} from '@/layouts/${layoutName}.astro';\r\nimport { locales, isValidLocale, defaultLocale, type Locale } from '@/i18n/config';\r\nimport { useTranslations } from '@/i18n/index';\r\nimport { routes } from '@/i18n/routes';\r\n\r\nexport function getStaticPaths() {\r\n return locales\r\n .filter((lang) => lang !== defaultLocale)\r\n .map((lang) => ({\r\n params: {\r\n lang,\r\n ${routeId}: routes.${routeId}[lang],\r\n },\r\n }));\r\n}\r\n\r\nconst { lang } = Astro.params;\r\n\r\nif (!lang || !isValidLocale(lang)) {\r\n return Astro.redirect('/');\r\n}\r\n\r\nconst locale = lang as Locale;\r\nconst t = useTranslations(locale);\r\n---\r\n\r\n<${layoutName}\r\n title={t('${titleKey}') || '${title}'}\r\n description={t('${descKey}') || 'Add your description here'}\r\n lang={locale}\r\n routeId=\"${routeId}\"\r\n>\r\n <!-- Hero Section -->\r\n <section class=\"py-20 bg-secondary\">\r\n <div class=\"container\">\r\n <h1 class=\"text-4xl font-bold text-foreground\">\r\n {t('${titleKey}') || '${title}'}\r\n </h1>\r\n <p class=\"mt-4 text-foreground-muted max-w-2xl\">\r\n {t('${descKey}') || 'Add your content here.'}\r\n </p>\r\n </div>\r\n </section>\r\n\r\n <!-- Content Section -->\r\n <section class=\"py-16\">\r\n <div class=\"container\">\r\n <!-- Your content -->\r\n </div>\r\n </section>\r\n</${layoutName}>\r\n`;\r\n}\r\n\r\n/**\r\n * Generates pages in the target directory\r\n */\r\nexport async function generatePages(\r\n targetDir: string,\r\n pages: string[],\r\n layout: PageLayout,\r\n isI18n: boolean\r\n): Promise<string[]> {\r\n const generatedFiles: string[] = [];\r\n\r\n if (pages.length === 0) {\r\n return generatedFiles;\r\n }\r\n\r\n // Ensure pages directory exists\r\n const pagesDir = join(targetDir, 'src', 'pages');\r\n if (!existsSync(pagesDir)) {\r\n mkdirSync(pagesDir, { recursive: true });\r\n }\r\n\r\n // Generate standard pages (English / default locale)\r\n for (const pageName of pages) {\r\n const filePath = join(pagesDir, `${pageName}.astro`);\r\n const template = generatePageTemplate(pageName, layout);\r\n writeFileSync(filePath, template);\r\n generatedFiles.push(`src/pages/${pageName}.astro`);\r\n\r\n // Add nav entry to nav.config.ts (for non-i18n nav)\r\n if (!isI18n) {\r\n addNavEntry(targetDir, pageName);\r\n }\r\n }\r\n\r\n // Generate i18n pages if enabled\r\n if (isI18n) {\r\n const langDir = join(pagesDir, '[lang]');\r\n if (!existsSync(langDir)) {\r\n mkdirSync(langDir, { recursive: true });\r\n }\r\n\r\n for (const pageName of pages) {\r\n const routeId = toRouteId(pageName);\r\n // Use rest parameter syntax for translated URL slugs\r\n const filePath = join(langDir, `[...${routeId}].astro`);\r\n const template = generateI18nPageTemplate(pageName, layout);\r\n writeFileSync(filePath, template);\r\n generatedFiles.push(`src/pages/[lang]/[...${routeId}].astro`);\r\n\r\n // Add route entry to i18n routes.ts\r\n addI18nRouteEntry(targetDir, pageName);\r\n }\r\n }\r\n\r\n return generatedFiles;\r\n}\r\n\r\n/**\r\n * List of page-related files that could be generated\r\n */\r\nexport const PAGES_FILES = [\r\n 'src/pages/{pageName}.astro',\r\n 'src/pages/[lang]/[...{routeId}].astro',\r\n];\r\n","import { existsSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport type { VelocityConfig, ScaffoldOptions } from '../types.js';\r\nimport { readJson, writeJson } from './fs.js';\r\n\r\nconst CONFIG_FILENAME = '.velocity.json';\r\n\r\n/**\r\n * Reads .velocity.json from a project directory.\r\n * Returns null if the file doesn't exist.\r\n */\r\nexport function readVelocityConfig(projectDir: string): VelocityConfig | null {\r\n const configPath = join(projectDir, CONFIG_FILENAME);\r\n if (!existsSync(configPath)) {\r\n return null;\r\n }\r\n return readJson<VelocityConfig>(configPath);\r\n}\r\n\r\n/**\r\n * Writes .velocity.json to a project directory.\r\n */\r\nexport function writeVelocityConfig(projectDir: string, config: VelocityConfig): void {\r\n const configPath = join(projectDir, CONFIG_FILENAME);\r\n writeJson(configPath, config);\r\n}\r\n\r\n/**\r\n * Builds a VelocityConfig from scaffold options for initial project creation.\r\n */\r\nexport function createInitialConfig(options: ScaffoldOptions, version: string): VelocityConfig {\r\n const today = new Date().toISOString().slice(0, 10);\r\n\r\n let componentsValue: string;\r\n switch (options.componentSelection.mode) {\r\n case 'all':\r\n componentsValue = 'all';\r\n break;\r\n case 'none':\r\n componentsValue = 'none';\r\n break;\r\n case 'categories':\r\n componentsValue = `categories:${options.componentSelection.categories?.join(',') ?? ''}`;\r\n break;\r\n case 'individual':\r\n componentsValue = `individual:${options.componentSelection.components?.join(',') ?? ''}`;\r\n break;\r\n }\r\n\r\n return {\r\n version,\r\n createdAt: today,\r\n updatedAt: today,\r\n features: {\r\n demo: options.demo,\r\n i18n: options.i18n,\r\n components: componentsValue,\r\n },\r\n };\r\n}\r\n","import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\n\n/**\n * Recursively copies a directory\n */\nexport function copyDirectory(src: string, dest: string, overwrite = false): void {\n if (!existsSync(src)) {\n throw new Error(`Source directory does not exist: ${src}`);\n }\n\n if (!existsSync(dest)) {\n mkdirSync(dest, { recursive: true });\n }\n\n const entries = readdirSync(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(src, entry.name);\n const destPath = join(dest, entry.name);\n\n if (entry.isDirectory()) {\n copyDirectory(srcPath, destPath, overwrite);\n } else {\n if (overwrite || !existsSync(destPath)) {\n const destDir = dirname(destPath);\n if (!existsSync(destDir)) {\n mkdirSync(destDir, { recursive: true });\n }\n copyFileSync(srcPath, destPath);\n }\n }\n }\n}\n\n/**\n * Checks if a directory is empty\n */\nexport function isEmptyDir(path: string): boolean {\n if (!existsSync(path)) return true;\n const files = readdirSync(path);\n return files.length === 0 || (files.length === 1 && files[0] === '.git');\n}\n\n/**\n * Reads a JSON file and parses it\n */\nexport function readJson<T = Record<string, unknown>>(path: string): T {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content) as T;\n}\n\n/**\n * Writes an object as JSON to a file\n */\nexport function writeJson(path: string, data: unknown): void {\n writeFileSync(path, JSON.stringify(data, null, 2) + '\\n');\n}\n\n/**\n * Checks if path exists and is a directory\n */\nexport function isDirectory(path: string): boolean {\n return existsSync(path) && statSync(path).isDirectory();\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, readdirSync, rmSync, statSync } from 'node:fs';\r\nimport { execSync } from 'node:child_process';\r\nimport { join, dirname, relative } from 'node:path';\r\nimport { tmpdir } from 'node:os';\r\nimport * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport { downloadTemplate } from 'giget';\r\nimport type { UpgradeOptions, UpgradeManifest, MigrationStep } from './types.js';\r\nimport { readVelocityConfig, writeVelocityConfig } from './utils/velocity-config.js';\r\nimport { readJson } from './utils/fs.js';\r\nimport { diffProjects, summarizeDiffs } from './utils/diff.js';\r\nimport {\r\n showUpgradeIntro,\r\n showChangeSummary,\r\n confirmUpgrade,\r\n showManualSteps,\r\n showProtectedNotice,\r\n showUpgradeOutro,\r\n warnDirtyGit,\r\n} from './upgrade-prompts.js';\r\n\r\ndeclare const CLI_VERSION: string;\r\n\r\nconst TEMPLATE_REPO = 'github:southwellmedia/velocity';\r\n\r\n// Hardcoded fallback safe list if manifest is missing from template\r\nconst FALLBACK_SAFE_FILES = [\r\n 'src/components/ui/',\r\n 'src/components/seo/',\r\n 'src/components/layout/',\r\n 'src/layouts/',\r\n 'src/lib/',\r\n 'src/styles/tokens/',\r\n 'src/styles/themes/',\r\n 'src/styles/global.css',\r\n 'src/content.config.ts',\r\n 'src/config/nav.config.ts',\r\n 'tsconfig.json',\r\n 'eslint.config.js',\r\n '.prettierrc',\r\n '.prettierignore',\r\n '.gitignore',\r\n 'vercel.json',\r\n 'netlify.toml',\r\n 'wrangler.toml',\r\n];\r\n\r\n/**\r\n * Checks if the project has uncommitted git changes.\r\n */\r\nfunction hasUncommittedChanges(targetDir: string): boolean {\r\n try {\r\n const result = execSync('git status --porcelain', {\r\n cwd: targetDir,\r\n encoding: 'utf-8',\r\n });\r\n return result.trim().length > 0;\r\n } catch {\r\n // Not a git repo or git not available — skip the check\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Compares two semver-like version strings.\r\n * Returns true if `current` < `required`.\r\n */\r\nfunction isVersionLessThan(current: string, required: string): boolean {\r\n const parse = (v: string) =>\r\n v.replace(/^v/, '').split(/[-.]/).map((p) => {\r\n const n = parseInt(p, 10);\r\n return isNaN(n) ? 0 : n;\r\n });\r\n\r\n const a = parse(current);\r\n const b = parse(required);\r\n const len = Math.max(a.length, b.length);\r\n\r\n for (let i = 0; i < len; i++) {\r\n const av = a[i] ?? 0;\r\n const bv = b[i] ?? 0;\r\n if (av < bv) return true;\r\n if (av > bv) return false;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Filters migrations to only those applicable for the user's version range.\r\n * A migration applies if:\r\n * - No fromVersion/toVersion: always applies (legacy behavior)\r\n * - If toVersion is set and user's current version is NOT less than toVersion, skip (user already past this migration)\r\n * - If fromVersion is set and user's current version IS less than fromVersion, skip (user hasn't reached the version where this migration matters)\r\n * - Otherwise, include it\r\n */\r\nfunction filterMigrations(migrations: MigrationStep[], currentVersion: string): MigrationStep[] {\r\n return migrations.filter((m) => {\r\n // No version constraints — always show (legacy)\r\n if (!m.fromVersion && !m.toVersion) return true;\r\n\r\n // User already past this migration's target version\r\n if (m.toVersion && !isVersionLessThan(currentVersion, m.toVersion)) return false;\r\n\r\n // User hasn't reached the starting version for this migration\r\n if (m.fromVersion && isVersionLessThan(currentVersion, m.fromVersion)) return false;\r\n\r\n return true;\r\n });\r\n}\r\n\r\n/**\r\n * Scans user files for migration patterns and returns matches.\r\n */\r\nfunction scanForMigrationPatterns(\r\n targetDir: string,\r\n migrations: MigrationStep[]\r\n): Map<string, string[]> {\r\n const results = new Map<string, string[]>();\r\n\r\n for (const migration of migrations) {\r\n if (!migration.pattern) {\r\n results.set(migration.title, []);\r\n continue;\r\n }\r\n\r\n const regex = new RegExp(migration.pattern);\r\n const matches: string[] = [];\r\n\r\n // Determine search paths\r\n const searchPaths = migration.searchPaths?.length\r\n ? migration.searchPaths\r\n : ['src/'];\r\n\r\n for (const searchPath of searchPaths) {\r\n const fullPath = join(targetDir, searchPath);\r\n if (!existsSync(fullPath)) continue;\r\n\r\n const files = walkFiles(fullPath);\r\n for (const file of files) {\r\n try {\r\n const content = readFileSync(file, 'utf-8');\r\n if (regex.test(content)) {\r\n matches.push(relative(targetDir, file));\r\n }\r\n } catch {\r\n // Skip unreadable files\r\n }\r\n }\r\n }\r\n\r\n results.set(migration.title, matches);\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * Recursively walks a directory and returns all file paths.\r\n */\r\nfunction walkFiles(dir: string): string[] {\r\n const results: string[] = [];\r\n if (!existsSync(dir)) return results;\r\n\r\n const stat = statSync(dir);\r\n if (!stat.isDirectory()) {\r\n return [dir];\r\n }\r\n\r\n const entries = readdirSync(dir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const fullPath = join(dir, entry.name);\r\n if (entry.isDirectory()) {\r\n // Skip node_modules and .git\r\n if (entry.name === 'node_modules' || entry.name === '.git') continue;\r\n results.push(...walkFiles(fullPath));\r\n } else {\r\n results.push(fullPath);\r\n }\r\n }\r\n return results;\r\n}\r\n\r\n/**\r\n * Merges dependency changes into the project's package.json.\r\n */\r\nfunction mergePackageJsonDeps(\r\n targetDir: string,\r\n manifest: UpgradeManifest\r\n): void {\r\n const pkgPath = join(targetDir, 'package.json');\r\n if (!existsSync(pkgPath)) return;\r\n\r\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\r\n\r\n // Update dependencies\r\n for (const [name, version] of Object.entries(manifest.dependencies.update)) {\r\n if (pkg.dependencies?.[name] !== undefined) {\r\n pkg.dependencies[name] = version;\r\n } else if (pkg.devDependencies?.[name] !== undefined) {\r\n pkg.devDependencies[name] = version;\r\n } else {\r\n // Default to dependencies\r\n if (!pkg.dependencies) pkg.dependencies = {};\r\n pkg.dependencies[name] = version;\r\n }\r\n }\r\n\r\n // Remove dependencies\r\n for (const name of manifest.dependencies.remove) {\r\n if (pkg.dependencies?.[name] !== undefined) {\r\n delete pkg.dependencies[name];\r\n }\r\n if (pkg.devDependencies?.[name] !== undefined) {\r\n delete pkg.devDependencies[name];\r\n }\r\n }\r\n\r\n // Add new dependencies\r\n for (const [name, version] of Object.entries(manifest.dependencies.add)) {\r\n if (!pkg.dependencies) pkg.dependencies = {};\r\n pkg.dependencies[name] = version;\r\n }\r\n\r\n writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\r\n}\r\n\r\n/**\r\n * Main upgrade orchestration function.\r\n */\r\nexport async function upgrade(options: UpgradeOptions): Promise<void> {\r\n const { targetDir, dryRun, yes } = options;\r\n\r\n // 1. Read .velocity.json\r\n const config = readVelocityConfig(targetDir);\r\n if (!config) {\r\n p.log.error(\r\n pc.red(\r\n \"This doesn't appear to be a Velocity project.\\n\" +\r\n 'Run this command from a project created with create-velocity-astro.'\r\n )\r\n );\r\n process.exit(1);\r\n }\r\n\r\n // Check for dirty git state\r\n if (hasUncommittedChanges(targetDir)) {\r\n const proceed = await warnDirtyGit(yes);\r\n if (!proceed) return;\r\n }\r\n\r\n // 2. Download latest template to temp dir\r\n const spinner = p.spinner();\r\n spinner.start('Downloading latest template...');\r\n\r\n const tempDir = join(tmpdir(), `velocity-upgrade-${Date.now()}`);\r\n\r\n try {\r\n await downloadTemplate(TEMPLATE_REPO, {\r\n dir: tempDir,\r\n force: true,\r\n });\r\n spinner.stop('Template downloaded');\r\n } catch (error) {\r\n spinner.stop('Failed to download template');\r\n p.log.error(\r\n pc.red(\r\n 'Could not download template. Check your internet connection.\\n' +\r\n (error instanceof Error ? error.message : '')\r\n )\r\n );\r\n cleanup(tempDir);\r\n process.exit(1);\r\n }\r\n\r\n // 3. Read velocity-manifest.json from fresh template\r\n let manifest: UpgradeManifest;\r\n const manifestPath = join(tempDir, 'velocity-manifest.json');\r\n\r\n if (existsSync(manifestPath)) {\r\n manifest = readJson<UpgradeManifest>(manifestPath);\r\n } else {\r\n // Fallback: use hardcoded safe list\r\n p.log.warn(pc.yellow('Manifest not found in template. Using fallback file list.'));\r\n\r\n // Try to read version from template's package.json\r\n let templateVersion = config.version;\r\n const templatePkgPath = join(tempDir, 'package.json');\r\n if (existsSync(templatePkgPath)) {\r\n const templatePkg = readJson<{ version?: string }>(templatePkgPath);\r\n if (templatePkg.version) {\r\n templateVersion = templatePkg.version;\r\n }\r\n }\r\n\r\n manifest = {\r\n version: templateVersion,\r\n minCliVersion: '1.0.0',\r\n files: {\r\n safe: FALLBACK_SAFE_FILES,\r\n protected: [],\r\n },\r\n dependencies: {\r\n update: {},\r\n remove: [],\r\n add: {},\r\n },\r\n migrations: [],\r\n };\r\n }\r\n\r\n // Check CLI version requirement\r\n if (isVersionLessThan(CLI_VERSION, manifest.minCliVersion)) {\r\n p.log.error(\r\n pc.red(\r\n `This upgrade requires create-velocity-astro >= ${manifest.minCliVersion}.\\n` +\r\n 'Run `npm update -g create-velocity-astro` to update.'\r\n )\r\n );\r\n cleanup(tempDir);\r\n process.exit(1);\r\n }\r\n\r\n // Filter migrations to only those relevant to the user's current version\r\n manifest.migrations = filterMigrations(manifest.migrations, config.version);\r\n\r\n // Check if already on latest version\r\n if (config.version === manifest.version) {\r\n showUpgradeIntro(config.version, manifest.version);\r\n p.log.info(pc.green(`Already on v${manifest.version}. Nothing to upgrade.`));\r\n p.outro('');\r\n cleanup(tempDir);\r\n return;\r\n }\r\n\r\n // 4. Diff safe files\r\n const diffs = diffProjects(targetDir, tempDir, manifest);\r\n const { added, modified } = summarizeDiffs(diffs);\r\n\r\n // If no changes at all\r\n if (added === 0 && modified === 0 &&\r\n Object.keys(manifest.dependencies.update).length === 0 &&\r\n manifest.dependencies.remove.length === 0 &&\r\n Object.keys(manifest.dependencies.add).length === 0) {\r\n showUpgradeIntro(config.version, manifest.version);\r\n p.log.info(pc.green('All files are up to date. Updating version marker only.'));\r\n if (!dryRun) {\r\n writeVelocityConfig(targetDir, {\r\n ...config,\r\n version: manifest.version,\r\n updatedAt: new Date().toISOString().slice(0, 10),\r\n });\r\n }\r\n p.outro('');\r\n cleanup(tempDir);\r\n return;\r\n }\r\n\r\n // 5. Show summary and confirm\r\n showUpgradeIntro(config.version, manifest.version);\r\n showChangeSummary(diffs, manifest);\r\n\r\n const shouldProceed = await confirmUpgrade(dryRun);\r\n\r\n if (dryRun) {\r\n // In dry-run mode, still show protected notice and manual migration steps\r\n showProtectedNotice(manifest);\r\n const matchResults = scanForMigrationPatterns(targetDir, manifest.migrations);\r\n showManualSteps(manifest.migrations, matchResults);\r\n p.outro(pc.dim('Dry run complete. No changes were made.'));\r\n cleanup(tempDir);\r\n return;\r\n }\r\n\r\n if (!shouldProceed) {\r\n cleanup(tempDir);\r\n return;\r\n }\r\n\r\n // 6. Apply changes\r\n spinner.start('Applying changes...');\r\n\r\n // 6a. Copy modified/added safe files\r\n const changedDiffs = diffs.filter((d) => d.status === 'added' || d.status === 'modified');\r\n for (const diff of changedDiffs) {\r\n const src = join(tempDir, diff.path);\r\n const dest = join(targetDir, diff.path);\r\n const destDir = dirname(dest);\r\n\r\n if (!existsSync(destDir)) {\r\n mkdirSync(destDir, { recursive: true });\r\n }\r\n\r\n copyFileSync(src, dest);\r\n }\r\n\r\n // 6b. Merge package.json dependencies\r\n const hasDepChanges =\r\n Object.keys(manifest.dependencies.update).length > 0 ||\r\n manifest.dependencies.remove.length > 0 ||\r\n Object.keys(manifest.dependencies.add).length > 0;\r\n\r\n if (hasDepChanges) {\r\n mergePackageJsonDeps(targetDir, manifest);\r\n }\r\n\r\n // 6c. Update .velocity.json\r\n writeVelocityConfig(targetDir, {\r\n ...config,\r\n version: manifest.version,\r\n updatedAt: new Date().toISOString().slice(0, 10),\r\n });\r\n\r\n spinner.stop('Changes applied');\r\n\r\n // Report results\r\n if (modified > 0) {\r\n p.log.success(pc.green(`Updated ${modified} framework file${modified !== 1 ? 's' : ''}`));\r\n }\r\n if (added > 0) {\r\n p.log.success(pc.green(`Added ${added} new file${added !== 1 ? 's' : ''}`));\r\n }\r\n if (hasDepChanges) {\r\n p.log.success(pc.green('Updated package.json dependencies'));\r\n }\r\n p.log.success(pc.green('Updated .velocity.json'));\r\n\r\n // 7. Show protected file notice\r\n showProtectedNotice(manifest);\r\n\r\n // 8. Scan for migration patterns and show manual steps\r\n const matchResults = scanForMigrationPatterns(targetDir, manifest.migrations);\r\n showManualSteps(manifest.migrations, matchResults);\r\n\r\n // 9. Show outro\r\n showUpgradeOutro(hasDepChanges);\r\n\r\n cleanup(tempDir);\r\n}\r\n\r\n/**\r\n * Cleans up temporary directory.\r\n */\r\nfunction cleanup(tempDir: string): void {\r\n try {\r\n if (existsSync(tempDir)) {\r\n rmSync(tempDir, { recursive: true, force: true });\r\n }\r\n } catch {\r\n // Ignore cleanup errors\r\n }\r\n}\r\n","import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';\r\nimport { join, relative } from 'node:path';\r\nimport type { UpgradeManifest, FileDiff } from '../types.js';\r\n\r\n/**\r\n * Recursively collects all file paths under a directory, relative to baseDir.\r\n */\r\nfunction walkDir(dir: string, baseDir: string): string[] {\r\n const results: string[] = [];\r\n if (!existsSync(dir)) return results;\r\n\r\n const entries = readdirSync(dir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const fullPath = join(dir, entry.name);\r\n if (entry.isDirectory()) {\r\n results.push(...walkDir(fullPath, baseDir));\r\n } else {\r\n results.push(relative(baseDir, fullPath));\r\n }\r\n }\r\n return results;\r\n}\r\n\r\n/**\r\n * Expands a list of file/directory paths into individual file paths.\r\n * If a path ends with \"/\" or is a directory in freshDir, expands to all files within.\r\n */\r\nfunction expandPaths(paths: string[], freshDir: string): string[] {\r\n const files: string[] = [];\r\n\r\n for (const p of paths) {\r\n const fullPath = join(freshDir, p);\r\n\r\n if (p.endsWith('/') || (existsSync(fullPath) && statSync(fullPath).isDirectory())) {\r\n files.push(...walkDir(fullPath, freshDir));\r\n } else {\r\n files.push(p);\r\n }\r\n }\r\n\r\n return [...new Set(files)];\r\n}\r\n\r\n/**\r\n * Compares files between the current project and a fresh template download.\r\n * Only examines files listed in the manifest's \"safe\" list.\r\n */\r\nexport function diffProjects(\r\n currentDir: string,\r\n freshDir: string,\r\n manifest: UpgradeManifest\r\n): FileDiff[] {\r\n const diffs: FileDiff[] = [];\r\n const safeFiles = expandPaths(manifest.files.safe, freshDir);\r\n\r\n for (const filePath of safeFiles) {\r\n const currentPath = join(currentDir, filePath);\r\n const freshPath = join(freshDir, filePath);\r\n\r\n // Fresh template file doesn't exist (shouldn't happen, but handle gracefully)\r\n if (!existsSync(freshPath)) continue;\r\n\r\n if (!existsSync(currentPath)) {\r\n diffs.push({ path: filePath, status: 'added', category: 'safe' });\r\n } else {\r\n const currentContent = readFileSync(currentPath);\r\n const freshContent = readFileSync(freshPath);\r\n\r\n if (Buffer.compare(currentContent, freshContent) === 0) {\r\n diffs.push({ path: filePath, status: 'unchanged', category: 'safe' });\r\n } else {\r\n diffs.push({ path: filePath, status: 'modified', category: 'safe' });\r\n }\r\n }\r\n }\r\n\r\n return diffs;\r\n}\r\n\r\n/**\r\n * Returns a summary count of diff statuses.\r\n */\r\nexport function summarizeDiffs(diffs: FileDiff[]): {\r\n added: number;\r\n modified: number;\r\n unchanged: number;\r\n} {\r\n let added = 0;\r\n let modified = 0;\r\n let unchanged = 0;\r\n\r\n for (const diff of diffs) {\r\n switch (diff.status) {\r\n case 'added':\r\n added++;\r\n break;\r\n case 'modified':\r\n modified++;\r\n break;\r\n case 'unchanged':\r\n unchanged++;\r\n break;\r\n }\r\n }\r\n\r\n return { added, modified, unchanged };\r\n}\r\n","import * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport type { FileDiff, MigrationStep, UpgradeManifest } from './types.js';\r\nimport { summarizeDiffs } from './utils/diff.js';\r\n\r\n/**\r\n * Shows the upgrade intro with version info.\r\n */\r\nexport function showUpgradeIntro(currentVersion: string, latestVersion: string): void {\r\n console.log();\r\n p.intro(pc.bgCyan(pc.black(' Velocity Upgrade ')));\r\n p.log.info(\r\n `Current version: ${pc.dim(`v${currentVersion}`)}\\n` +\r\n `Latest version: ${pc.green(`v${latestVersion}`)}`\r\n );\r\n}\r\n\r\n/**\r\n * Shows a summary of changes that will be applied.\r\n */\r\nexport function showChangeSummary(\r\n diffs: FileDiff[],\r\n manifest: UpgradeManifest\r\n): void {\r\n const { added, modified } = summarizeDiffs(diffs);\r\n const migrationCount = manifest.migrations.length;\r\n\r\n const lines: string[] = [];\r\n\r\n // List specific files that will be modified\r\n const modifiedFiles = diffs.filter((d) => d.status === 'modified');\r\n const addedFiles = diffs.filter((d) => d.status === 'added');\r\n\r\n if (modifiedFiles.length > 0) {\r\n lines.push(pc.bold(' Files to update:'));\r\n for (const f of modifiedFiles) {\r\n lines.push(` ${pc.yellow('~')} ${f.path}`);\r\n }\r\n }\r\n if (addedFiles.length > 0) {\r\n lines.push(pc.bold(' New files:'));\r\n for (const f of addedFiles) {\r\n lines.push(` ${pc.green('+')} ${f.path}`);\r\n }\r\n }\r\n\r\n // List specific dependency changes\r\n const depUpdates = Object.entries(manifest.dependencies.update);\r\n const depRemoves = manifest.dependencies.remove;\r\n const depAdds = Object.entries(manifest.dependencies.add);\r\n\r\n if (depUpdates.length > 0 || depRemoves.length > 0 || depAdds.length > 0) {\r\n lines.push(pc.bold(' Dependency changes:'));\r\n for (const [name, version] of depUpdates) {\r\n lines.push(` ${pc.cyan('~')} ${name} → ${version}`);\r\n }\r\n for (const name of depRemoves) {\r\n lines.push(` ${pc.red('-')} ${name}`);\r\n }\r\n for (const [name, version] of depAdds) {\r\n lines.push(` ${pc.green('+')} ${name}@${version}`);\r\n }\r\n }\r\n\r\n if (migrationCount > 0) {\r\n lines.push(` ${pc.yellow(`${migrationCount}`)} manual migration step${migrationCount !== 1 ? 's' : ''} ${pc.dim('(shown after upgrade)')}`);\r\n }\r\n\r\n // Summary counts\r\n const summary = [];\r\n if (modified > 0) summary.push(`${modified} updated`);\r\n if (added > 0) summary.push(`${added} added`);\r\n summary.push(`${manifest.files.protected.length} protected ${pc.dim('(not touched)')}`);\r\n\r\n lines.push('');\r\n lines.push(` ${pc.dim('Totals: ' + summary.join(', '))}`);\r\n\r\n if (lines.length > 0) {\r\n p.log.message(pc.bold('Changes to apply:') + '\\n' + lines.join('\\n'));\r\n }\r\n}\r\n\r\n/**\r\n * Shows a notice about protected files that may need manual attention.\r\n */\r\nexport function showProtectedNotice(manifest: UpgradeManifest): void {\r\n const protectedFiles = manifest.files.protected;\r\n if (protectedFiles.length === 0) return;\r\n\r\n const lines = [\r\n `The following files were ${pc.bold('not modified')} to preserve your customizations:`,\r\n '',\r\n ];\r\n\r\n for (const f of protectedFiles) {\r\n lines.push(` ${pc.dim('-')} ${f}`);\r\n }\r\n\r\n lines.push('');\r\n lines.push(pc.dim('If the upgrade requires changes to these files, they will appear in the manual steps below.'));\r\n\r\n p.log.info(lines.join('\\n'));\r\n}\r\n\r\n/**\r\n * Asks user to confirm the upgrade. Returns true to proceed.\r\n * In dry-run mode, shows what would happen without asking.\r\n */\r\nexport async function confirmUpgrade(dryRun: boolean): Promise<boolean> {\r\n if (dryRun) {\r\n p.log.info(pc.dim('Dry run — no changes will be made.'));\r\n return false;\r\n }\r\n\r\n const proceed = await p.confirm({\r\n message: 'Proceed with upgrade?',\r\n initialValue: true,\r\n });\r\n\r\n if (p.isCancel(proceed) || !proceed) {\r\n p.cancel('Upgrade cancelled.');\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Shows manual migration steps with file matches.\r\n */\r\nexport function showManualSteps(\r\n migrations: MigrationStep[],\r\n matchResults: Map<string, string[]>\r\n): void {\r\n if (migrations.length === 0) return;\r\n\r\n const lines: string[] = [];\r\n\r\n for (let i = 0; i < migrations.length; i++) {\r\n const step = migrations[i]!;\r\n const matches = matchResults.get(step.title) ?? [];\r\n\r\n lines.push(`${pc.bold(`${i + 1}. ${step.title}`)}`);\r\n lines.push(` ${step.description}`);\r\n\r\n if (matches.length > 0) {\r\n lines.push(` ${pc.yellow('⚠')} Found matches in: ${matches.join(', ')}`);\r\n }\r\n\r\n lines.push('');\r\n }\r\n\r\n p.log.warning(pc.bold('Manual steps required:') + '\\n\\n' + lines.join('\\n'));\r\n}\r\n\r\n/**\r\n * Shows the upgrade completion message.\r\n */\r\nexport function showUpgradeOutro(hasDepChanges: boolean): void {\r\n if (hasDepChanges) {\r\n p.log.info(`Run ${pc.cyan('pnpm install')} to update dependencies.`);\r\n }\r\n p.outro(pc.green('Upgrade complete! Review the manual steps above.'));\r\n}\r\n\r\n/**\r\n * Warns about dirty git state.\r\n */\r\nexport async function warnDirtyGit(yes: boolean): Promise<boolean> {\r\n if (yes) {\r\n p.log.warn(pc.yellow('You have uncommitted changes. Proceeding anyway (--yes).'));\r\n return true;\r\n }\r\n\r\n p.log.warn(pc.yellow('You have uncommitted changes. We recommend committing or stashing first.'));\r\n\r\n const proceed = await p.confirm({\r\n message: 'Continue anyway?',\r\n initialValue: false,\r\n });\r\n\r\n if (p.isCancel(proceed) || !proceed) {\r\n p.cancel('Upgrade cancelled.');\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n","import { run } from './cli.js';\n\nrun(process.argv.slice(2)).catch((error) => {\n console.error(error);\n process.exit(1);\n});\n"],"mappings":"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","names":["resolve","existsSync","p","pc","resolve","existsSync","mkdirSync","readdirSync","copyFileSync","readFileSync","writeFileSync","join","dirname","p","execa","__dirname","existsSync","existsSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","join","dirname","existsSync","readFileSync","writeFileSync","join","existsSync","existsSync","mkdirSync","readdirSync","join","copyFileSync","readFileSync","writeFileSync","dirname","spinner","execa","existsSync","readFileSync","writeFileSync","mkdirSync","copyFileSync","readdirSync","rmSync","statSync","join","dirname","relative","p","pc","downloadTemplate","existsSync","readFileSync","readdirSync","statSync","join","relative","p","p","pc","pc","TEMPLATE_REPO","p","join","existsSync","readFileSync","relative","statSync","readdirSync","writeFileSync","pc","spinner","downloadTemplate","matchResults","dirname","mkdirSync","copyFileSync","rmSync","pc","targetDir","resolve","projectName","existsSync"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/prompts.ts","../src/utils/validate.ts","../src/utils/package-manager.ts","../src/registry/fetcher.ts","../src/registry/resolver.ts","../src/scaffold.ts","../src/template.ts","../src/utils/git.ts","../src/features/pages.ts","../src/utils/velocity-config.ts","../src/utils/fs.ts","../src/utils/diff.ts","../src/upgrade.ts","../src/upgrade-prompts.ts","../src/index.ts"],"sourcesContent":["import mri from 'mri';\r\nimport { resolve } from 'node:path';\r\nimport { existsSync } from 'node:fs';\r\nimport * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport type { CliOptions } from './types.js';\r\nimport type { ComponentSelection } from './registry/types.js';\r\nimport { runPrompts, showIntro, showOutro, showError } from './prompts.js';\r\nimport { scaffold } from './scaffold.js';\r\nimport { upgrade } from './upgrade.js';\r\nimport { isEmptyDir } from './utils/fs.js';\r\nimport { toValidProjectName } from './utils/validate.js';\r\n\r\ndeclare const CLI_VERSION: string;\r\n\r\nconst HELP_TEXT = `\r\n${pc.bold('create-velocity-astro')} - Create and upgrade Velocity projects\r\n\r\n${pc.bold('Usage:')}\r\n npm create velocity-astro@latest [project-name] [options]\r\n pnpm create velocity-astro [project-name] [options]\r\n\r\n${pc.bold('Commands:')}\r\n ${pc.cyan('upgrade')} Upgrade an existing Velocity project to the latest version\r\n --dry-run Preview changes without applying them\r\n --yes, -y Skip confirmation prompts\r\n\r\n${pc.bold('Options:')}\r\n --demo Include demo landing page and sample content\r\n --components Include all components (default: prompt for selection)\r\n --components=none Exclude all components\r\n --components=ui,patterns Include specific categories\r\n --i18n Add internationalization support\r\n --pages Prompt for starter pages to generate\r\n --yes, -y Skip prompts and use defaults\r\n --help, -h Show this help message\r\n --version, -v Show version number\r\n\r\n${pc.bold('Component Categories:')}\r\n ui UI components (buttons, forms, cards, dialogs) - 31 components\r\n patterns Form patterns (contact form, newsletter, search) - 7 components\r\n hero Flexible hero section component - 1 component\r\n\r\n${pc.bold('Examples:')}\r\n npm create velocity-astro@latest my-site\r\n npm create velocity-astro@latest my-site --demo --components\r\n npm create velocity-astro@latest my-site --components=ui,patterns\r\n pnpm create velocity-astro my-site -y\r\n\r\n ${pc.dim('# Upgrade an existing project')}\r\n pnpm create velocity-astro upgrade\r\n pnpm create velocity-astro upgrade --dry-run\r\n`;\r\n\r\nconst VERSION = CLI_VERSION;\r\n\r\n/**\r\n * Parses the --components flag into a ComponentSelection\r\n */\r\nfunction parseComponentsFlag(value: string | boolean | undefined): ComponentSelection | undefined {\r\n // Not specified - will prompt user\r\n if (value === undefined) {\r\n return undefined;\r\n }\r\n\r\n // --components (boolean true) - include all\r\n if (value === true) {\r\n return { mode: 'all' };\r\n }\r\n\r\n // --components=false or explicit false\r\n if (value === false) {\r\n return { mode: 'none' };\r\n }\r\n\r\n // --components=none\r\n if (value === 'none' || value === 'false') {\r\n return { mode: 'none' };\r\n }\r\n\r\n // --components=all\r\n if (value === 'all' || value === 'true') {\r\n return { mode: 'all' };\r\n }\r\n\r\n // --components=ui,patterns,hero (category list)\r\n const categories = value.split(',').map((s) => s.trim().toLowerCase());\r\n const validCategories = ['ui', 'patterns', 'hero'];\r\n const filtered = categories.filter((c) => validCategories.includes(c));\r\n\r\n if (filtered.length === 0) {\r\n return { mode: 'all' }; // Fall back to all if no valid categories\r\n }\r\n\r\n return { mode: 'categories', categories: filtered };\r\n}\r\n\r\nexport async function run(argv: string[]): Promise<void> {\r\n const args = mri<CliOptions>(argv, {\r\n boolean: ['demo', 'i18n', 'pages', 'help', 'version', 'yes', 'dry-run'],\r\n string: ['components'],\r\n alias: {\r\n h: 'help',\r\n v: 'version',\r\n y: 'yes',\r\n },\r\n });\r\n\r\n // Handle help\r\n if (args.help) {\r\n console.log(HELP_TEXT);\r\n return;\r\n }\r\n\r\n // Handle version\r\n if (args.version) {\r\n console.log(VERSION);\r\n return;\r\n }\r\n\r\n // Handle upgrade subcommand\r\n const subcommand = args._[0] as string | undefined;\r\n if (subcommand === 'upgrade') {\r\n const targetDir = resolve(process.cwd());\r\n await upgrade({\r\n targetDir,\r\n dryRun: (args as unknown as Record<string, unknown>)['dry-run'] as boolean || false,\r\n yes: args.yes || false,\r\n });\r\n return;\r\n }\r\n\r\n showIntro();\r\n\r\n // Get project name from args or prompt\r\n const argProjectName = args._[0] as string | undefined;\r\n\r\n // Parse component selection from CLI\r\n const componentSelection = parseComponentsFlag(args.components);\r\n\r\n // Skip prompts mode\r\n if (args.yes) {\r\n const projectName = toValidProjectName(argProjectName || 'my-velocity-site');\r\n const targetDir = resolve(process.cwd(), projectName);\r\n\r\n if (existsSync(targetDir) && !isEmptyDir(targetDir)) {\r\n showError(`Directory \"${projectName}\" already exists and is not empty.`);\r\n process.exit(1);\r\n }\r\n\r\n await scaffold({\r\n projectName,\r\n targetDir,\r\n demo: args.demo || false,\r\n componentSelection: componentSelection || { mode: 'all' },\r\n i18n: args.i18n || false,\r\n pages: [],\r\n pageLayout: 'page',\r\n packageManager: 'pnpm',\r\n });\r\n\r\n showOutro(projectName, 'pnpm');\r\n return;\r\n }\r\n\r\n // Interactive mode\r\n const answers = await runPrompts({\r\n projectName: argProjectName,\r\n demo: args.demo,\r\n componentSelection: componentSelection,\r\n i18n: args.i18n,\r\n pages: args.pages,\r\n });\r\n\r\n // User cancelled\r\n if (typeof answers === 'symbol') {\r\n return;\r\n }\r\n\r\n const { projectName, demo, componentSelection: selectedComponents, i18n, pages, pageLayout, packageManager } = answers;\r\n const targetDir = resolve(process.cwd(), projectName);\r\n\r\n // Check if directory exists and is not empty\r\n if (existsSync(targetDir) && !isEmptyDir(targetDir)) {\r\n const shouldOverwrite = await p.confirm({\r\n message: `Directory \"${projectName}\" already exists. Continue and overwrite?`,\r\n initialValue: false,\r\n });\r\n\r\n if (!shouldOverwrite || p.isCancel(shouldOverwrite)) {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // Run scaffold\r\n try {\r\n await scaffold({\r\n projectName,\r\n targetDir,\r\n demo,\r\n componentSelection: selectedComponents,\r\n i18n,\r\n pages,\r\n pageLayout,\r\n packageManager,\r\n });\r\n\r\n showOutro(projectName, packageManager);\r\n } catch (error) {\r\n showError(error instanceof Error ? error.message : 'An unexpected error occurred');\r\n process.exit(1);\r\n }\r\n}\r\n","import * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport type { PackageManager, PageLayout, PromptAnswers } from './types.js';\r\nimport type { ComponentSelection, ComponentRegistry, ComponentSelectionMode } from './registry/types.js';\r\nimport { validateProjectName, toValidProjectName } from './utils/validate.js';\r\nimport { detectPackageManager } from './utils/package-manager.js';\r\nimport { fetchRegistry } from './registry/fetcher.js';\r\nimport { getComponentsByCategory, resolveDependencies, getSelectionStats } from './registry/resolver.js';\r\n\r\ninterface PromptDefaults {\r\n projectName?: string;\r\n demo?: boolean;\r\n componentSelection?: ComponentSelection;\r\n i18n?: boolean;\r\n pages?: boolean;\r\n}\r\n\r\n/**\r\n * Parses comma-separated page names into an array of valid page slugs\r\n */\r\nfunction parsePageNames(input: string): string[] {\r\n if (!input.trim()) return [];\r\n\r\n return input\r\n .split(',')\r\n .map((name) => name.trim().toLowerCase())\r\n .filter((name) => name.length > 0)\r\n .map((name) => name.replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, ''))\r\n .filter((name) => name.length > 0 && !['index', 'blog', '404', 'rss'].includes(name));\r\n}\r\n\r\n/**\r\n * Prompts user for component selection mode\r\n */\r\nasync function promptComponentMode(): Promise<ComponentSelectionMode> {\r\n const result = await p.select({\r\n message: 'Include optional components?',\r\n options: [\r\n {\r\n value: 'all' as ComponentSelectionMode,\r\n label: 'All',\r\n hint: 'Include all 24 optional components',\r\n },\r\n {\r\n value: 'categories' as ComponentSelectionMode,\r\n label: 'Select categories',\r\n hint: 'Choose component groups',\r\n },\r\n {\r\n value: 'individual' as ComponentSelectionMode,\r\n label: 'Select individual',\r\n hint: 'Pick specific components',\r\n },\r\n {\r\n value: 'none' as ComponentSelectionMode,\r\n label: 'None',\r\n hint: 'Minimal template',\r\n },\r\n ],\r\n initialValue: 'all' as ComponentSelectionMode,\r\n });\r\n\r\n if (p.isCancel(result)) {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Prompts user to select component categories\r\n */\r\nasync function promptCategories(registry: ComponentRegistry): Promise<string[]> {\r\n const categoryOptions = Object.entries(registry.categories).map(([id, cat]) => {\r\n const componentCount = getComponentsByCategory(id, registry).length;\r\n return {\r\n value: id,\r\n label: cat.name,\r\n hint: `${componentCount} components - ${cat.description}`,\r\n };\r\n });\r\n\r\n const result = await p.multiselect({\r\n message: 'Select component categories:',\r\n options: categoryOptions,\r\n required: true,\r\n });\r\n\r\n if (p.isCancel(result)) {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n }\r\n\r\n return result as string[];\r\n}\r\n\r\n/**\r\n * Prompts user to select individual components\r\n */\r\nasync function promptComponents(registry: ComponentRegistry): Promise<string[]> {\r\n // Group components by category for better UX\r\n const componentsByCategory: Record<string, { value: string; label: string; hint: string }[]> = {};\r\n\r\n for (const [id, comp] of Object.entries(registry.components)) {\r\n if (!componentsByCategory[comp.category]) {\r\n componentsByCategory[comp.category] = [];\r\n }\r\n const depCount = comp.dependencies.components.length;\r\n const depHint = depCount > 0 ? ` (requires ${depCount} dep${depCount > 1 ? 's' : ''})` : '';\r\n const categoryName = registry.categories[comp.category]?.name ?? comp.category;\r\n componentsByCategory[comp.category]!.push({\r\n value: id,\r\n label: comp.name,\r\n hint: `${categoryName}${depHint}`,\r\n });\r\n }\r\n\r\n // Flatten into options with category headers\r\n const options: { value: string; label: string; hint?: string }[] = [];\r\n for (const [categoryId, components] of Object.entries(componentsByCategory)) {\r\n const categoryName = registry.categories[categoryId]?.name || categoryId;\r\n // Add all components from this category\r\n for (const comp of components) {\r\n options.push({\r\n ...comp,\r\n hint: categoryName,\r\n });\r\n }\r\n }\r\n\r\n const result = await p.multiselect({\r\n message: 'Select components (dependencies auto-included):',\r\n options,\r\n required: true,\r\n });\r\n\r\n if (p.isCancel(result)) {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n }\r\n\r\n return result as string[];\r\n}\r\n\r\n/**\r\n * Gets component selection from user prompts\r\n */\r\nasync function getComponentSelection(\r\n defaultSelection?: ComponentSelection\r\n): Promise<ComponentSelection> {\r\n if (defaultSelection) {\r\n return defaultSelection;\r\n }\r\n\r\n let registry: ComponentRegistry;\r\n try {\r\n registry = await fetchRegistry();\r\n } catch {\r\n // Fallback to simple yes/no if registry unavailable\r\n const useComponents = await p.select({\r\n message: 'Include UI component library?',\r\n options: [\r\n { value: true, label: 'Yes', hint: 'Buttons, forms, cards, dialogs, etc.' },\r\n { value: false, label: 'No', hint: 'Just the basics' },\r\n ],\r\n initialValue: true,\r\n });\r\n\r\n if (p.isCancel(useComponents)) {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n }\r\n\r\n return { mode: useComponents ? 'all' : 'none' };\r\n }\r\n\r\n const mode = await promptComponentMode();\r\n\r\n switch (mode) {\r\n case 'none':\r\n return { mode: 'none' };\r\n\r\n case 'all':\r\n return { mode: 'all' };\r\n\r\n case 'categories': {\r\n const categories = await promptCategories(registry);\r\n // Show what will be included\r\n const selection: ComponentSelection = { mode: 'categories', categories };\r\n const resolved = resolveDependencies(selection, registry);\r\n const stats = getSelectionStats(resolved, registry);\r\n p.log.info(\r\n pc.dim(`Selected ${stats.componentCount} components (${resolved.files.length} files)`)\r\n );\r\n return selection;\r\n }\r\n\r\n case 'individual': {\r\n const components = await promptComponents(registry);\r\n // Show what will be included (with dependencies)\r\n const selection: ComponentSelection = { mode: 'individual', components };\r\n const resolved = resolveDependencies(selection, registry);\r\n const stats = getSelectionStats(resolved, registry);\r\n if (resolved.components.length > components.length) {\r\n p.log.info(\r\n pc.dim(\r\n `Selected ${components.length} components + ${resolved.components.length - components.length} dependencies (${resolved.files.length} files)`\r\n )\r\n );\r\n } else {\r\n p.log.info(\r\n pc.dim(`Selected ${stats.componentCount} components (${resolved.files.length} files)`)\r\n );\r\n }\r\n return selection;\r\n }\r\n }\r\n}\r\n\r\nexport async function runPrompts(defaults: PromptDefaults = {}): Promise<PromptAnswers | symbol> {\r\n const detectedPm = detectPackageManager();\r\n\r\n const answers = await p.group(\r\n {\r\n projectName: () =>\r\n p.text({\r\n message: 'What is your project name?',\r\n placeholder: defaults.projectName || 'my-velocity-site',\r\n defaultValue: defaults.projectName,\r\n validate: (value) => {\r\n const name = value || defaults.projectName || 'my-velocity-site';\r\n const result = validateProjectName(toValidProjectName(name));\r\n if (!result.valid) return result.message;\r\n },\r\n }),\r\n\r\n demo:\r\n defaults.demo !== undefined\r\n ? () => Promise.resolve(defaults.demo)\r\n : () =>\r\n p.select({\r\n message: 'Include demo landing page and sample content?',\r\n options: [\r\n {\r\n value: false,\r\n label: 'No',\r\n hint: 'Minimal starter with basic pages',\r\n },\r\n {\r\n value: true,\r\n label: 'Yes',\r\n hint: 'Full demo with landing page, blog posts',\r\n },\r\n ],\r\n initialValue: false,\r\n }),\r\n\r\n componentSelection: () => getComponentSelection(defaults.componentSelection),\r\n\r\n i18n:\r\n defaults.i18n !== undefined\r\n ? () => Promise.resolve(defaults.i18n)\r\n : () =>\r\n p.select({\r\n message: 'Add internationalization (i18n)?',\r\n options: [\r\n {\r\n value: false,\r\n label: 'No',\r\n hint: 'English only',\r\n },\r\n {\r\n value: true,\r\n label: 'Yes',\r\n hint: 'Locale routing, translations',\r\n },\r\n ],\r\n initialValue: false,\r\n }),\r\n\r\n generatePages:\r\n defaults.pages !== undefined\r\n ? () => Promise.resolve(defaults.pages)\r\n : () =>\r\n p.select({\r\n message: 'Generate starter pages?',\r\n options: [\r\n {\r\n value: false,\r\n label: 'No',\r\n hint: 'Create pages manually later',\r\n },\r\n {\r\n value: true,\r\n label: 'Yes',\r\n hint: 'Auto-generate page files with layout',\r\n },\r\n ],\r\n initialValue: false,\r\n }),\r\n\r\n pageNames: ({ results }) =>\r\n results.generatePages\r\n ? p.text({\r\n message: 'Enter page names (comma-separated):',\r\n placeholder: 'about, pricing, faq, contact',\r\n validate: (value) => {\r\n const pages = parsePageNames(value);\r\n if (pages.length === 0) {\r\n return 'Please enter at least one valid page name';\r\n }\r\n },\r\n })\r\n : Promise.resolve(''),\r\n\r\n pageLayout: ({ results }) =>\r\n results.generatePages\r\n ? results.demo\r\n ? p.select({\r\n message: 'Select layout for pages:',\r\n options: [\r\n {\r\n value: 'page' as PageLayout,\r\n label: 'PageLayout',\r\n hint: 'Standard content pages (Header + Footer)',\r\n },\r\n {\r\n value: 'landing' as PageLayout,\r\n label: 'LandingLayout',\r\n hint: 'Marketing pages (Navbar + LandingFooter)',\r\n },\r\n ],\r\n initialValue: 'page' as PageLayout,\r\n })\r\n : Promise.resolve('page' as PageLayout) // Force PageLayout when demo=No\r\n : Promise.resolve('page' as PageLayout),\r\n\r\n packageManager: () =>\r\n p.select({\r\n message: 'Which package manager?',\r\n options: [\r\n {\r\n value: 'pnpm' as PackageManager,\r\n label: 'pnpm',\r\n hint: detectedPm === 'pnpm' ? 'detected' : 'recommended',\r\n },\r\n {\r\n value: 'npm' as PackageManager,\r\n label: 'npm',\r\n hint: detectedPm === 'npm' ? 'detected' : undefined,\r\n },\r\n {\r\n value: 'yarn' as PackageManager,\r\n label: 'yarn',\r\n hint: detectedPm === 'yarn' ? 'detected' : undefined,\r\n },\r\n {\r\n value: 'bun' as PackageManager,\r\n label: 'bun',\r\n hint: detectedPm === 'bun' ? 'detected' : undefined,\r\n },\r\n ],\r\n initialValue: detectedPm,\r\n }),\r\n },\r\n {\r\n onCancel: () => {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n },\r\n }\r\n );\r\n\r\n return {\r\n projectName: toValidProjectName(answers.projectName || defaults.projectName || 'my-velocity-site'),\r\n demo: answers.demo as boolean,\r\n componentSelection: answers.componentSelection as ComponentSelection,\r\n i18n: answers.i18n as boolean,\r\n pages: parsePageNames(answers.pageNames as string),\r\n pageLayout: (answers.pageLayout as PageLayout) || 'page',\r\n packageManager: answers.packageManager as PackageManager,\r\n };\r\n}\r\n\r\nexport function showIntro(): void {\r\n console.log();\r\n p.intro(pc.bgCyan(pc.black(' Create Velocity ')));\r\n}\r\n\r\nexport function showOutro(projectName: string, packageManager: PackageManager): void {\r\n const runCmd = packageManager === 'npm' ? 'npm run' : packageManager;\r\n\r\n p.note(\r\n [\r\n `cd ${projectName}`,\r\n `${runCmd} dev`,\r\n ].join('\\n'),\r\n 'Next steps'\r\n );\r\n\r\n p.outro(pc.green('Happy building!'));\r\n}\r\n\r\nexport function showError(message: string): void {\r\n p.log.error(pc.red(message));\r\n}\r\n\r\nexport function showWarning(message: string): void {\r\n p.log.warn(pc.yellow(message));\r\n}\r\n\r\nexport function showSuccess(message: string): void {\r\n p.log.success(pc.green(message));\r\n}\r\n\r\nexport function showStep(message: string): void {\r\n p.log.step(message);\r\n}\r\n","/**\n * Validates a project name for npm package naming conventions\n */\nexport function validateProjectName(name: string): { valid: boolean; message?: string } {\n if (!name || name.trim() === '') {\n return { valid: false, message: 'Project name cannot be empty' };\n }\n\n // Must be lowercase\n if (name !== name.toLowerCase()) {\n return { valid: false, message: 'Project name must be lowercase' };\n }\n\n // Cannot start with . or _\n if (name.startsWith('.') || name.startsWith('_')) {\n return { valid: false, message: 'Project name cannot start with . or _' };\n }\n\n // Cannot contain spaces\n if (/\\s/.test(name)) {\n return { valid: false, message: 'Project name cannot contain spaces' };\n }\n\n // Cannot contain special characters except - and @/\n if (!/^(@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name)) {\n return {\n valid: false,\n message: 'Project name can only contain lowercase letters, numbers, hyphens, and underscores',\n };\n }\n\n // Length check\n if (name.length > 214) {\n return { valid: false, message: 'Project name must be 214 characters or fewer' };\n }\n\n return { valid: true };\n}\n\n/**\n * Sanitizes a string to be a valid project name\n */\nexport function toValidProjectName(name: string): string {\n return name\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-_~.]/g, '-')\n .replace(/^[-._]+/, '')\n .replace(/[-._]+$/, '')\n .replace(/-+/g, '-');\n}\n","import type { PackageManager } from '../types.js';\n\n/**\n * Detects the package manager used to run this command\n */\nexport function detectPackageManager(): PackageManager {\n const userAgent = process.env.npm_config_user_agent || '';\n\n if (userAgent.startsWith('pnpm')) return 'pnpm';\n if (userAgent.startsWith('yarn')) return 'yarn';\n if (userAgent.startsWith('bun')) return 'bun';\n return 'npm';\n}\n\n/**\n * Gets the install command for a package manager\n */\nexport function getInstallCommand(pm: PackageManager): string {\n switch (pm) {\n case 'pnpm':\n return 'pnpm install';\n case 'yarn':\n return 'yarn';\n case 'bun':\n return 'bun install';\n case 'npm':\n default:\n return 'npm install';\n }\n}\n\n/**\n * Gets the run command for a package manager\n */\nexport function getRunCommand(pm: PackageManager): string {\n switch (pm) {\n case 'pnpm':\n return 'pnpm';\n case 'yarn':\n return 'yarn';\n case 'bun':\n return 'bun';\n case 'npm':\n default:\n return 'npm run';\n }\n}\n","/**\n * Registry Fetcher\n * Fetches the component registry from GitHub\n */\n\nimport type { ComponentRegistry } from './types.js';\n\nconst REGISTRY_URL = 'https://raw.githubusercontent.com/southwellmedia/velocity/main/component-registry.json';\n\nlet cachedRegistry: ComponentRegistry | null = null;\n\n/**\n * Fetches the component registry from GitHub\n * Results are cached for the duration of the process\n */\nexport async function fetchRegistry(): Promise<ComponentRegistry> {\n if (cachedRegistry) {\n return cachedRegistry;\n }\n\n try {\n const response = await fetch(REGISTRY_URL);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch registry: ${response.status} ${response.statusText}`);\n }\n\n cachedRegistry = await response.json() as ComponentRegistry;\n return cachedRegistry;\n } catch (error) {\n throw new Error(\n `Could not fetch component registry. Please check your internet connection.\\n${error instanceof Error ? error.message : ''}`\n );\n }\n}\n\n/**\n * Fetches a single file from the velocity repository\n */\nexport async function fetchComponentFile(filePath: string): Promise<string> {\n const url = `https://raw.githubusercontent.com/southwellmedia/velocity/main/${filePath}`;\n\n try {\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch file: ${response.status} ${response.statusText}`);\n }\n\n return response.text();\n } catch (error) {\n throw new Error(\n `Could not fetch file: ${filePath}\\n${error instanceof Error ? error.message : ''}`\n );\n }\n}\n\n/**\n * Clears the cached registry\n */\nexport function clearRegistryCache(): void {\n cachedRegistry = null;\n}\n","/**\n * Dependency Resolver\n * Resolves component dependencies and collects all required files\n */\n\nimport type { ComponentRegistry, ComponentSelection, ResolvedComponents } from './types.js';\n\n/**\n * Resolves dependencies for requested components\n * Returns all components, utilities, files, and npm packages needed\n */\nexport function resolveDependencies(\n selection: ComponentSelection,\n registry: ComponentRegistry\n): ResolvedComponents {\n const resolved = new Set<string>();\n const utilities = new Set<string>();\n const files = new Set<string>();\n const npmPackages = new Set<string>();\n\n // Handle different selection modes\n let requestedComponents: string[] = [];\n\n switch (selection.mode) {\n case 'none':\n return { components: [], utilities: [], files: [], npmPackages: [] };\n\n case 'all':\n requestedComponents = Object.keys(registry.components);\n break;\n\n case 'categories':\n if (selection.categories) {\n requestedComponents = Object.entries(registry.components)\n .filter(([, comp]) => selection.categories!.includes(comp.category))\n .map(([id]) => id);\n }\n break;\n\n case 'individual':\n requestedComponents = selection.components || [];\n break;\n }\n\n // Recursively resolve each component's dependencies\n function resolve(componentId: string): void {\n if (resolved.has(componentId)) return;\n\n const component = registry.components[componentId];\n if (!component) {\n console.warn(`Component not found: ${componentId}`);\n return;\n }\n\n // Resolve component dependencies first (recursive)\n for (const dep of component.dependencies.components) {\n resolve(dep);\n }\n\n // Collect utilities\n for (const util of component.dependencies.utilities) {\n utilities.add(util);\n }\n\n // Collect files\n for (const file of component.files) {\n files.add(file);\n }\n\n resolved.add(componentId);\n }\n\n // Resolve all requested components\n for (const componentId of requestedComponents) {\n resolve(componentId);\n }\n\n // Collect utility files and npm packages\n for (const utilId of utilities) {\n const utility = registry.utilities[utilId];\n if (utility) {\n for (const file of utility.files) {\n files.add(file);\n }\n for (const pkg of utility.npm) {\n npmPackages.add(pkg);\n }\n }\n }\n\n return {\n components: [...resolved],\n utilities: [...utilities],\n files: [...files],\n npmPackages: [...npmPackages],\n };\n}\n\n/**\n * Gets all components in a category\n */\nexport function getComponentsByCategory(\n categoryId: string,\n registry: ComponentRegistry\n): string[] {\n return Object.entries(registry.components)\n .filter(([, comp]) => comp.category === categoryId)\n .map(([id]) => id);\n}\n\n/**\n * Gets the dependency tree for a component (for visualization)\n */\nexport function getDependencyTree(\n componentId: string,\n registry: ComponentRegistry,\n visited = new Set<string>()\n): { id: string; name: string; deps: ReturnType<typeof getDependencyTree>[] } | null {\n if (visited.has(componentId)) return null;\n visited.add(componentId);\n\n const component = registry.components[componentId];\n if (!component) return null;\n\n const deps = component.dependencies.components\n .map((dep) => getDependencyTree(dep, registry, visited))\n .filter((d): d is NonNullable<typeof d> => d !== null);\n\n return {\n id: componentId,\n name: component.name,\n deps,\n };\n}\n\n/**\n * Validates that all components exist in the registry\n */\nexport function validateComponents(\n componentIds: string[],\n registry: ComponentRegistry\n): { valid: boolean; invalid: string[] } {\n const invalid = componentIds.filter((id) => !registry.components[id]);\n return {\n valid: invalid.length === 0,\n invalid,\n };\n}\n\n/**\n * Validates that all categories exist in the registry\n */\nexport function validateCategories(\n categoryIds: string[],\n registry: ComponentRegistry\n): { valid: boolean; invalid: string[] } {\n const invalid = categoryIds.filter((id) => !registry.categories[id]);\n return {\n valid: invalid.length === 0,\n invalid,\n };\n}\n\n/**\n * Gets summary stats for a component selection\n */\nexport function getSelectionStats(\n resolved: ResolvedComponents,\n registry: ComponentRegistry\n): { componentCount: number; fileCount: number; categories: string[] } {\n const categories = new Set<string>();\n\n for (const componentId of resolved.components) {\n const component = registry.components[componentId];\n if (component) {\n categories.add(component.category);\n }\n }\n\n return {\n componentCount: resolved.components.length,\n fileCount: resolved.files.length,\n categories: [...categories],\n };\n}\n","import { existsSync, mkdirSync, readdirSync, copyFileSync, readFileSync, writeFileSync, rmSync } from 'node:fs';\r\nimport { join, dirname } from 'node:path';\r\nimport * as p from '@clack/prompts';\r\nimport { execa } from 'execa';\r\nimport { downloadTemplate } from 'giget';\r\nimport type { ScaffoldOptions } from './types.js';\r\nimport type { ComponentSelection, ResolvedComponents } from './registry/types.js';\r\nimport { getI18nTemplatePath, getBaseTemplatePath } from './template.js';\r\nimport { getInstallCommand } from './utils/package-manager.js';\r\nimport { initGit } from './utils/git.js';\r\nimport { showSuccess, showWarning } from './prompts.js';\r\nimport { generatePages } from './features/pages.js';\r\nimport { fetchRegistry } from './registry/fetcher.js';\r\nimport { resolveDependencies } from './registry/resolver.js';\r\nimport { createInitialConfig, writeVelocityConfig } from './utils/velocity-config.js';\r\nimport { readJson } from './utils/fs.js';\r\nimport { computeFileHashes } from './utils/diff.js';\r\n\r\n// GitHub repository for the Velocity template\r\nconst TEMPLATE_REPO = 'github:southwellmedia/velocity';\r\n\r\n// Files/directories to remove after download\r\nconst CLEANUP_ITEMS = [\r\n 'pnpm-lock.yaml',\r\n 'package-lock.json',\r\n 'yarn.lock',\r\n 'bun.lockb',\r\n '.git',\r\n];\r\n\r\n// Demo-specific content to remove when --demo is false\r\n// Includes both base paths and i18n paths to handle all scenarios\r\nconst DEMO_CONTENT = [\r\n // Landing page components\r\n 'src/components/landing',\r\n 'src/components/hero',\r\n // Landing-specific pages (base paths)\r\n 'src/pages/index.astro',\r\n 'src/pages/about.astro',\r\n 'src/pages/contact.astro',\r\n 'src/pages/components.astro',\r\n // Landing-specific pages (i18n paths)\r\n 'src/pages/[lang]/index.astro',\r\n 'src/pages/[lang]/[...about].astro',\r\n 'src/pages/[lang]/[...contact].astro',\r\n 'src/pages/[lang]/[...components].astro',\r\n // Landing layout (depends on Navbar from landing components)\r\n 'src/layouts/LandingLayout.astro',\r\n // Demo content\r\n 'src/content/blog',\r\n 'src/content/faqs',\r\n 'src/content/authors',\r\n 'src/content/pages',\r\n];\r\n\r\n// Optional component directories (for removal when mode='none')\r\n// Note: layout, seo, landing, blog are core template - not optional\r\nconst OPTIONAL_COMPONENT_DIRS = [\r\n 'src/components/ui',\r\n 'src/components/patterns',\r\n 'src/components/hero',\r\n];\r\n\r\n/**\r\n * Copies template files recursively\r\n */\r\nfunction copyTemplateFiles(src: string, dest: string): void {\r\n if (!existsSync(dest)) {\r\n mkdirSync(dest, { recursive: true });\r\n }\r\n\r\n const entries = readdirSync(src, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const srcPath = join(src, entry.name);\r\n const destPath = join(dest, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n copyTemplateFiles(srcPath, destPath);\r\n } else {\r\n copyFileSync(srcPath, destPath);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Removes files/directories from the target\r\n */\r\nfunction removeItems(targetDir: string, items: string[]): void {\r\n for (const item of items) {\r\n const itemPath = join(targetDir, item);\r\n if (existsSync(itemPath)) {\r\n try {\r\n rmSync(itemPath, { recursive: true, force: true });\r\n } catch {\r\n // Ignore errors - item may not exist or be locked\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Recursively collects all file paths relative to the project root\r\n */\r\nfunction walkFilesRelative(absDir: string, relativeBase: string): string[] {\r\n const results: string[] = [];\r\n if (!existsSync(absDir)) return results;\r\n\r\n const entries = readdirSync(absDir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const absPath = join(absDir, entry.name);\r\n const relPath = `${relativeBase}/${entry.name}`;\r\n if (entry.isDirectory()) {\r\n results.push(...walkFilesRelative(absPath, relPath));\r\n } else {\r\n results.push(relPath);\r\n }\r\n }\r\n return results;\r\n}\r\n\r\n/**\r\n * Recursively removes empty directories bottom-up\r\n */\r\nfunction removeEmptyDirs(dir: string): void {\r\n if (!existsSync(dir)) return;\r\n\r\n const entries = readdirSync(dir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n if (entry.isDirectory()) {\r\n removeEmptyDirs(join(dir, entry.name));\r\n }\r\n }\r\n\r\n // Re-read after cleaning children\r\n const remaining = readdirSync(dir);\r\n if (remaining.length === 0) {\r\n try {\r\n rmSync(dir, { recursive: true, force: true });\r\n } catch {\r\n // Ignore errors\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Keeps only specified files, removes everything else in optional component directories.\r\n * Walks recursively to handle nested subcategory folders (e.g. ui/form/Button/).\r\n */\r\nfunction keepOnlyFiles(targetDir: string, filesToKeep: Set<string>): void {\r\n // Only filter optional component directories - core template dirs are untouched\r\n const componentDirs = [\r\n 'src/components/ui',\r\n 'src/components/patterns',\r\n 'src/components/hero',\r\n ];\r\n\r\n for (const dir of componentDirs) {\r\n const dirPath = join(targetDir, dir);\r\n if (!existsSync(dirPath)) continue;\r\n\r\n // Recursively walk all files in the directory\r\n const allFiles = walkFilesRelative(dirPath, dir);\r\n for (const relativePath of allFiles) {\r\n if (!filesToKeep.has(relativePath)) {\r\n try {\r\n rmSync(join(targetDir, relativePath), { force: true });\r\n } catch {\r\n // Ignore errors\r\n }\r\n }\r\n }\r\n\r\n // Clean up empty directories (bottom-up)\r\n removeEmptyDirs(dirPath);\r\n }\r\n}\r\n\r\n/**\r\n * Updates the package.json with the new project name\r\n */\r\nfunction updatePackageJson(targetDir: string, projectName: string): void {\r\n const pkgPath = join(targetDir, 'package.json');\r\n\r\n if (!existsSync(pkgPath)) {\r\n throw new Error('package.json not found in template');\r\n }\r\n\r\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\r\n pkg.name = projectName;\r\n pkg.version = '0.1.0';\r\n delete pkg.repository;\r\n delete pkg.bugs;\r\n delete pkg.homepage;\r\n\r\n writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\r\n}\r\n\r\n/**\r\n * Applies base template (minimal pages) when demo is not selected\r\n */\r\nfunction applyBaseTemplate(targetDir: string): void {\r\n const baseTemplate = getBaseTemplatePath();\r\n if (existsSync(baseTemplate)) {\r\n copyTemplateFiles(baseTemplate, targetDir);\r\n }\r\n}\r\n\r\n/**\r\n * Applies the i18n overlay to the project\r\n */\r\nfunction applyI18nOverlay(targetDir: string): void {\r\n const i18nTemplate = getI18nTemplatePath();\r\n copyTemplateFiles(i18nTemplate, targetDir);\r\n}\r\n\r\n/**\r\n * Creates empty content directories with .gitkeep files\r\n */\r\nfunction createContentDirectories(targetDir: string): void {\r\n const contentDirs = [\r\n 'src/content/blog',\r\n ];\r\n\r\n for (const dir of contentDirs) {\r\n const dirPath = join(targetDir, dir);\r\n if (!existsSync(dirPath)) {\r\n mkdirSync(dirPath, { recursive: true });\r\n writeFileSync(join(dirPath, '.gitkeep'), '');\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Applies selective component filtering based on registry resolution\r\n */\r\nasync function applyComponentSelection(\r\n targetDir: string,\r\n selection: ComponentSelection\r\n): Promise<void> {\r\n // Handle 'all' mode - keep everything\r\n if (selection.mode === 'all') {\r\n return;\r\n }\r\n\r\n // Handle 'none' mode - remove optional components only\r\n if (selection.mode === 'none') {\r\n removeItems(targetDir, OPTIONAL_COMPONENT_DIRS);\r\n return;\r\n }\r\n\r\n // For 'categories' and 'individual' modes, we need the registry\r\n let resolved: ResolvedComponents;\r\n try {\r\n const registry = await fetchRegistry();\r\n resolved = resolveDependencies(selection, registry);\r\n } catch {\r\n // If registry fetch fails, fall back to keeping all components\r\n console.warn('Could not fetch component registry, keeping all components');\r\n return;\r\n }\r\n\r\n // Create set of files to keep\r\n const filesToKeep = new Set(resolved.files);\r\n\r\n // Keep only the resolved files\r\n keepOnlyFiles(targetDir, filesToKeep);\r\n\r\n // Ensure utility files are present if needed\r\n if (resolved.utilities.includes('cn')) {\r\n const cnPath = join(targetDir, 'src/lib/cn.ts');\r\n const cnDir = dirname(cnPath);\r\n if (!existsSync(cnDir)) {\r\n mkdirSync(cnDir, { recursive: true });\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Main scaffold function\r\n *\r\n * IMPORTANT: Step order matters for option combinations\r\n * - i18n overlay is applied BEFORE demo removal\r\n * - This ensures demo=Yes + i18n=Yes gets full translated demo\r\n * - And demo=No + i18n=Yes gets i18n routing without demo pages\r\n */\r\nexport async function scaffold(options: ScaffoldOptions): Promise<void> {\r\n const { projectName, targetDir, demo, componentSelection, i18n, pages, pageLayout, packageManager } = options;\r\n const spinner = p.spinner();\r\n\r\n // Step 1: Download base template from GitHub\r\n spinner.start('Downloading template from GitHub...');\r\n\r\n try {\r\n await downloadTemplate(TEMPLATE_REPO, {\r\n dir: targetDir,\r\n force: true,\r\n });\r\n removeItems(targetDir, CLEANUP_ITEMS);\r\n spinner.stop('Template downloaded');\r\n } catch (error) {\r\n spinner.stop('Failed to download template');\r\n throw new Error(\r\n `Could not download template from GitHub. Please check your internet connection.\\n${error instanceof Error ? error.message : ''}`\r\n );\r\n }\r\n\r\n // Step 2: Apply component selection\r\n if (componentSelection.mode !== 'all') {\r\n spinner.start('Configuring components...');\r\n try {\r\n await applyComponentSelection(targetDir, componentSelection);\r\n spinner.stop('Components configured');\r\n } catch (error) {\r\n spinner.stop('Failed to configure components');\r\n throw error;\r\n }\r\n }\r\n\r\n // Step 3: Apply i18n overlay if requested (BEFORE demo removal)\r\n // This ensures demo=Yes + i18n=Yes gets translated demo pages\r\n if (i18n) {\r\n spinner.start('Adding i18n support...');\r\n try {\r\n applyI18nOverlay(targetDir);\r\n spinner.stop('i18n support added');\r\n } catch (error) {\r\n spinner.stop('Failed to add i18n support');\r\n throw error;\r\n }\r\n }\r\n\r\n // Step 4: Remove demo content LAST (handles both base and i18n paths)\r\n // This runs after i18n overlay so it can remove i18n demo pages if needed\r\n if (!demo) {\r\n spinner.start('Configuring minimal template...');\r\n removeItems(targetDir, DEMO_CONTENT);\r\n applyBaseTemplate(targetDir);\r\n createContentDirectories(targetDir);\r\n spinner.stop('Minimal template configured');\r\n }\r\n\r\n // Step 5: Generate starter pages if requested\r\n if (pages.length > 0) {\r\n spinner.start(`Generating ${pages.length} starter page${pages.length > 1 ? 's' : ''}...`);\r\n try {\r\n const generatedFiles = await generatePages(targetDir, pages, pageLayout, i18n);\r\n spinner.stop(`Generated ${generatedFiles.length} page file${generatedFiles.length > 1 ? 's' : ''}`);\r\n } catch (error) {\r\n spinner.stop('Failed to generate pages');\r\n throw error;\r\n }\r\n }\r\n\r\n // Step 6: Update package.json\r\n spinner.start('Configuring project...');\r\n try {\r\n updatePackageJson(targetDir, projectName);\r\n spinner.stop('Project configured');\r\n } catch (error) {\r\n spinner.stop('Failed to configure project');\r\n throw error;\r\n }\r\n\r\n // Step 6.5: Write .velocity.json\r\n try {\r\n let templateVersion = '0.1.0-beta';\r\n const manifestPath = join(targetDir, 'velocity-manifest.json');\r\n const pkgPath = join(targetDir, 'package.json');\r\n\r\n if (existsSync(manifestPath)) {\r\n const manifest = readJson<{ version?: string }>(manifestPath);\r\n if (manifest.version) templateVersion = manifest.version;\r\n } else if (existsSync(pkgPath)) {\r\n const pkg = readJson<{ version?: string }>(pkgPath);\r\n if (pkg.version) templateVersion = pkg.version;\r\n }\r\n\r\n const velocityConfig = createInitialConfig(options, templateVersion);\r\n\r\n // Compute file hashes for upgrade conflict detection\r\n if (existsSync(manifestPath)) {\r\n const manifest = readJson<{ files?: { safe?: string[] } }>(manifestPath);\r\n if (manifest.files?.safe) {\r\n velocityConfig.fileHashes = computeFileHashes(targetDir, manifest.files.safe);\r\n }\r\n }\r\n\r\n writeVelocityConfig(targetDir, velocityConfig);\r\n } catch {\r\n // Non-fatal — project still usable without .velocity.json\r\n }\r\n\r\n // Step 7: Initialize git\r\n spinner.start('Initializing git repository...');\r\n const gitInitialized = await initGit(targetDir);\r\n if (gitInitialized) {\r\n spinner.stop('Git repository initialized');\r\n } else {\r\n spinner.stop('Git not available, skipping');\r\n }\r\n\r\n // Step 8: Install dependencies\r\n spinner.start(`Installing dependencies with ${packageManager}...`);\r\n try {\r\n const installCmd = getInstallCommand(packageManager);\r\n const [cmd, ...args] = installCmd.split(' ');\r\n await execa(cmd!, args, { cwd: targetDir });\r\n spinner.stop('Dependencies installed');\r\n } catch {\r\n spinner.stop('Failed to install dependencies');\r\n showWarning(`Run \"${getInstallCommand(packageManager)}\" manually to install dependencies`);\r\n }\r\n\r\n showSuccess(`Project \"${projectName}\" created successfully!`);\r\n}\r\n","import { existsSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Resolves the path to the base template (minimal pages)\n */\nexport function getBaseTemplatePath(): string {\n const templatePath = resolve(__dirname, '..', 'templates', 'base');\n\n if (existsSync(templatePath)) {\n return templatePath;\n }\n\n throw new Error('Could not find base template. Package may be corrupted.');\n}\n\n/**\n * Resolves the path to the i18n overlay template\n */\nexport function getI18nTemplatePath(): string {\n const templatePath = resolve(__dirname, '..', 'templates', 'i18n');\n\n if (existsSync(templatePath)) {\n return templatePath;\n }\n\n throw new Error('Could not find i18n template. Package may be corrupted.');\n}\n","import { execa } from 'execa';\n\n/**\n * Initializes a git repository in the target directory\n */\nexport async function initGit(targetDir: string): Promise<boolean> {\n try {\n await execa('git', ['init'], { cwd: targetDir });\n await execa('git', ['add', '-A'], { cwd: targetDir });\n await execa('git', ['commit', '-m', 'Initial commit from create-velocity'], {\n cwd: targetDir,\n });\n return true;\n } catch {\n // Git may not be installed or configured\n return false;\n }\n}\n\n/**\n * Checks if git is available\n */\nexport async function isGitInstalled(): Promise<boolean> {\n try {\n await execa('git', ['--version']);\n return true;\n } catch {\n return false;\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport type { PageLayout } from '../types.js';\r\n\r\n/**\r\n * Converts a page slug to a display title\r\n * e.g., 'about-us' -> 'About Us'\r\n */\r\nfunction toTitle(slug: string): string {\r\n return slug\r\n .split('-')\r\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\r\n .join(' ');\r\n}\r\n\r\n/**\r\n * Converts a page slug to a route ID (snake_case)\r\n * e.g., 'about-us' -> 'about_us'\r\n */\r\nfunction toRouteId(slug: string): string {\r\n return slug.replace(/-/g, '_');\r\n}\r\n\r\n/**\r\n * Calculates the next available nav order by finding the highest existing order\r\n */\r\nfunction getNextNavOrder(content: string): number {\r\n // Match all order values in nav configs\r\n const orderMatches = [...content.matchAll(/order:\\s*(\\d+)/g)];\r\n let maxOrder = 0;\r\n\r\n for (const match of orderMatches) {\r\n const orderStr = match[1];\r\n if (orderStr) {\r\n const order = parseInt(orderStr, 10);\r\n if (order > maxOrder) {\r\n maxOrder = order;\r\n }\r\n }\r\n }\r\n\r\n // Return the next order (10 more than current max for room to insert)\r\n return maxOrder + 10;\r\n}\r\n\r\n/**\r\n * Adds a new nav entry to nav.config.ts (non-i18n projects)\r\n * So the generated page appears in site navigation\r\n */\r\nfunction addNavEntry(targetDir: string, pageName: string): void {\r\n const navConfigPath = join(targetDir, 'src', 'config', 'nav.config.ts');\r\n\r\n if (!existsSync(navConfigPath)) {\r\n return; // nav.config.ts doesn't exist, skip\r\n }\r\n\r\n const title = toTitle(pageName);\r\n const content = readFileSync(navConfigPath, 'utf-8');\r\n\r\n // Check if entry already exists\r\n if (content.includes(`href: '/${pageName}'`)) {\r\n return; // Nav entry already defined\r\n }\r\n\r\n // Calculate the next nav order\r\n const navOrder = getNextNavOrder(content);\r\n\r\n // Find the closing bracket of the navItems array\r\n const insertPoint = content.indexOf('];');\r\n if (insertPoint === -1) {\r\n return; // Can't find insertion point\r\n }\r\n\r\n const newEntry = ` { label: '${title}', href: '/${pageName}', order: ${navOrder} },\\n`;\r\n\r\n const newContent = content.slice(0, insertPoint) + newEntry + content.slice(insertPoint);\r\n writeFileSync(navConfigPath, newContent);\r\n}\r\n\r\n/**\r\n * Adds a new route entry to i18n routes.ts\r\n * Creates the route with the same English slug for all locales (user customizes later)\r\n * Includes nav config so the page appears in navigation\r\n */\r\nfunction addI18nRouteEntry(targetDir: string, pageName: string): void {\r\n const routesPath = join(targetDir, 'src', 'i18n', 'routes.ts');\r\n\r\n if (!existsSync(routesPath)) {\r\n return; // routes.ts doesn't exist, skip\r\n }\r\n\r\n const routeId = toRouteId(pageName);\r\n const content = readFileSync(routesPath, 'utf-8');\r\n\r\n // Check if route already exists\r\n if (content.includes(`${routeId}:`)) {\r\n return; // Route already defined\r\n }\r\n\r\n // Find the closing of routes object (before \"} as const satisfies\")\r\n const insertPoint = content.indexOf('} as const satisfies');\r\n if (insertPoint === -1) {\r\n return; // Can't find insertion point\r\n }\r\n\r\n // Calculate the next nav order\r\n const navOrder = getNextNavOrder(content);\r\n\r\n // Create new route entry with nav config\r\n // Uses the route ID as the translation key (user should add translation)\r\n const title = toTitle(pageName);\r\n const newRoute = `\r\n // Custom page: ${pageName}\r\n ${routeId}: {\r\n en: '${pageName}', es: '${pageName}', fr: '${pageName}',\r\n nav: { show: true, order: ${navOrder}, label: 'nav.${routeId}' },\r\n },\r\n`;\r\n\r\n const newContent = content.slice(0, insertPoint) + newRoute + content.slice(insertPoint);\r\n writeFileSync(routesPath, newContent);\r\n\r\n // Also add translation keys to translation files\r\n addI18nTranslationKeys(targetDir, routeId, title);\r\n}\r\n\r\n/**\r\n * Adds translation keys for a new route to all i18n translation files\r\n */\r\nfunction addI18nTranslationKeys(targetDir: string, routeId: string, title: string): void {\r\n const locales = ['en', 'es', 'fr'];\r\n\r\n for (const locale of locales) {\r\n const translationPath = join(targetDir, 'src', 'i18n', 'translations', `${locale}.ts`);\r\n\r\n if (!existsSync(translationPath)) {\r\n continue;\r\n }\r\n\r\n let content = readFileSync(translationPath, 'utf-8');\r\n\r\n // Add nav translation if not exists\r\n if (!content.includes(`${routeId}:`)) {\r\n // Find the nav section and add the key\r\n const navSectionMatch = content.match(/nav:\\s*\\{([^}]+)\\}/);\r\n if (navSectionMatch) {\r\n const navSection = navSectionMatch[0];\r\n const insertPoint = navSection.lastIndexOf('}');\r\n const newNavSection =\r\n navSection.slice(0, insertPoint) +\r\n ` ${routeId}: '${title}',\\n ` +\r\n navSection.slice(insertPoint);\r\n content = content.replace(navSection, newNavSection);\r\n }\r\n }\r\n\r\n // Add page-specific translations if not exists\r\n const pageKeyPattern = new RegExp(`^\\\\s*${routeId}:\\\\s*\\\\{`, 'm');\r\n if (!pageKeyPattern.test(content)) {\r\n // Find a good insertion point (before the closing export)\r\n const insertPoint = content.lastIndexOf('} as const');\r\n if (insertPoint !== -1) {\r\n const pageTranslations = `\r\n // ${title} page\r\n ${routeId}: {\r\n title: '${title}',\r\n description: 'Add your ${title.toLowerCase()} page description here.',\r\n },\r\n\r\n`;\r\n content = content.slice(0, insertPoint) + pageTranslations + content.slice(insertPoint);\r\n }\r\n }\r\n\r\n writeFileSync(translationPath, content);\r\n }\r\n}\r\n\r\n/**\r\n * Generates the standard page template (non-i18n)\r\n */\r\nfunction generatePageTemplate(pageName: string, layout: PageLayout): string {\r\n const title = toTitle(pageName);\r\n const layoutName = layout === 'landing' ? 'LandingLayout' : 'PageLayout';\r\n\r\n return `---\r\nimport ${layoutName} from '@/layouts/${layoutName}.astro';\r\n---\r\n\r\n<${layoutName}\r\n title=\"${title}\"\r\n description=\"Add your description here\"\r\n>\r\n <!-- Hero Section -->\r\n <section class=\"py-20 bg-secondary\">\r\n <div class=\"container\">\r\n <h1 class=\"text-4xl font-bold text-foreground\">${title}</h1>\r\n <p class=\"mt-4 text-foreground-muted max-w-2xl\">\r\n Add your content here.\r\n </p>\r\n </div>\r\n </section>\r\n\r\n <!-- Content Section -->\r\n <section class=\"py-16\">\r\n <div class=\"container\">\r\n <!-- Your content -->\r\n </div>\r\n </section>\r\n</${layoutName}>\r\n`;\r\n}\r\n\r\n/**\r\n * Generates the i18n-aware page template with translated URL support\r\n */\r\nfunction generateI18nPageTemplate(pageName: string, layout: PageLayout): string {\r\n const title = toTitle(pageName);\r\n const layoutName = layout === 'landing' ? 'LandingLayout' : 'PageLayout';\r\n const routeId = toRouteId(pageName);\r\n const titleKey = `${routeId}.title`;\r\n const descKey = `${routeId}.description`;\r\n\r\n return `---\r\nimport ${layoutName} from '@/layouts/${layoutName}.astro';\r\nimport { locales, isValidLocale, defaultLocale, type Locale } from '@/i18n/config';\r\nimport { useTranslations } from '@/i18n/index';\r\nimport { routes } from '@/i18n/routes';\r\n\r\nexport function getStaticPaths() {\r\n return locales\r\n .filter((lang) => lang !== defaultLocale)\r\n .map((lang) => ({\r\n params: {\r\n lang,\r\n ${routeId}: routes.${routeId}[lang],\r\n },\r\n }));\r\n}\r\n\r\nconst { lang } = Astro.params;\r\n\r\nif (!lang || !isValidLocale(lang)) {\r\n return Astro.redirect('/');\r\n}\r\n\r\nconst locale = lang as Locale;\r\nconst t = useTranslations(locale);\r\n---\r\n\r\n<${layoutName}\r\n title={t('${titleKey}') || '${title}'}\r\n description={t('${descKey}') || 'Add your description here'}\r\n lang={locale}\r\n routeId=\"${routeId}\"\r\n>\r\n <!-- Hero Section -->\r\n <section class=\"py-20 bg-secondary\">\r\n <div class=\"container\">\r\n <h1 class=\"text-4xl font-bold text-foreground\">\r\n {t('${titleKey}') || '${title}'}\r\n </h1>\r\n <p class=\"mt-4 text-foreground-muted max-w-2xl\">\r\n {t('${descKey}') || 'Add your content here.'}\r\n </p>\r\n </div>\r\n </section>\r\n\r\n <!-- Content Section -->\r\n <section class=\"py-16\">\r\n <div class=\"container\">\r\n <!-- Your content -->\r\n </div>\r\n </section>\r\n</${layoutName}>\r\n`;\r\n}\r\n\r\n/**\r\n * Generates pages in the target directory\r\n */\r\nexport async function generatePages(\r\n targetDir: string,\r\n pages: string[],\r\n layout: PageLayout,\r\n isI18n: boolean\r\n): Promise<string[]> {\r\n const generatedFiles: string[] = [];\r\n\r\n if (pages.length === 0) {\r\n return generatedFiles;\r\n }\r\n\r\n // Ensure pages directory exists\r\n const pagesDir = join(targetDir, 'src', 'pages');\r\n if (!existsSync(pagesDir)) {\r\n mkdirSync(pagesDir, { recursive: true });\r\n }\r\n\r\n // Generate standard pages (English / default locale)\r\n for (const pageName of pages) {\r\n const filePath = join(pagesDir, `${pageName}.astro`);\r\n const template = generatePageTemplate(pageName, layout);\r\n writeFileSync(filePath, template);\r\n generatedFiles.push(`src/pages/${pageName}.astro`);\r\n\r\n // Add nav entry to nav.config.ts (for non-i18n nav)\r\n if (!isI18n) {\r\n addNavEntry(targetDir, pageName);\r\n }\r\n }\r\n\r\n // Generate i18n pages if enabled\r\n if (isI18n) {\r\n const langDir = join(pagesDir, '[lang]');\r\n if (!existsSync(langDir)) {\r\n mkdirSync(langDir, { recursive: true });\r\n }\r\n\r\n for (const pageName of pages) {\r\n const routeId = toRouteId(pageName);\r\n // Use rest parameter syntax for translated URL slugs\r\n const filePath = join(langDir, `[...${routeId}].astro`);\r\n const template = generateI18nPageTemplate(pageName, layout);\r\n writeFileSync(filePath, template);\r\n generatedFiles.push(`src/pages/[lang]/[...${routeId}].astro`);\r\n\r\n // Add route entry to i18n routes.ts\r\n addI18nRouteEntry(targetDir, pageName);\r\n }\r\n }\r\n\r\n return generatedFiles;\r\n}\r\n\r\n/**\r\n * List of page-related files that could be generated\r\n */\r\nexport const PAGES_FILES = [\r\n 'src/pages/{pageName}.astro',\r\n 'src/pages/[lang]/[...{routeId}].astro',\r\n];\r\n","import { existsSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport type { VelocityConfig, ScaffoldOptions } from '../types.js';\r\nimport { readJson, writeJson } from './fs.js';\r\n\r\nconst CONFIG_FILENAME = '.velocity.json';\r\n\r\n/**\r\n * Reads .velocity.json from a project directory.\r\n * Returns null if the file doesn't exist.\r\n */\r\nexport function readVelocityConfig(projectDir: string): VelocityConfig | null {\r\n const configPath = join(projectDir, CONFIG_FILENAME);\r\n if (!existsSync(configPath)) {\r\n return null;\r\n }\r\n return readJson<VelocityConfig>(configPath);\r\n}\r\n\r\n/**\r\n * Writes .velocity.json to a project directory.\r\n */\r\nexport function writeVelocityConfig(projectDir: string, config: VelocityConfig): void {\r\n const configPath = join(projectDir, CONFIG_FILENAME);\r\n writeJson(configPath, config);\r\n}\r\n\r\n/**\r\n * Builds a VelocityConfig from scaffold options for initial project creation.\r\n */\r\nexport function createInitialConfig(options: ScaffoldOptions, version: string): VelocityConfig {\r\n const today = new Date().toISOString().slice(0, 10);\r\n\r\n let componentsValue: string;\r\n switch (options.componentSelection.mode) {\r\n case 'all':\r\n componentsValue = 'all';\r\n break;\r\n case 'none':\r\n componentsValue = 'none';\r\n break;\r\n case 'categories':\r\n componentsValue = `categories:${options.componentSelection.categories?.join(',') ?? ''}`;\r\n break;\r\n case 'individual':\r\n componentsValue = `individual:${options.componentSelection.components?.join(',') ?? ''}`;\r\n break;\r\n }\r\n\r\n return {\r\n version,\r\n createdAt: today,\r\n updatedAt: today,\r\n features: {\r\n demo: options.demo,\r\n i18n: options.i18n,\r\n components: componentsValue,\r\n },\r\n };\r\n}\r\n","import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\n\n/**\n * Recursively copies a directory\n */\nexport function copyDirectory(src: string, dest: string, overwrite = false): void {\n if (!existsSync(src)) {\n throw new Error(`Source directory does not exist: ${src}`);\n }\n\n if (!existsSync(dest)) {\n mkdirSync(dest, { recursive: true });\n }\n\n const entries = readdirSync(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(src, entry.name);\n const destPath = join(dest, entry.name);\n\n if (entry.isDirectory()) {\n copyDirectory(srcPath, destPath, overwrite);\n } else {\n if (overwrite || !existsSync(destPath)) {\n const destDir = dirname(destPath);\n if (!existsSync(destDir)) {\n mkdirSync(destDir, { recursive: true });\n }\n copyFileSync(srcPath, destPath);\n }\n }\n }\n}\n\n/**\n * Checks if a directory is empty\n */\nexport function isEmptyDir(path: string): boolean {\n if (!existsSync(path)) return true;\n const files = readdirSync(path);\n return files.length === 0 || (files.length === 1 && files[0] === '.git');\n}\n\n/**\n * Reads a JSON file and parses it\n */\nexport function readJson<T = Record<string, unknown>>(path: string): T {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content) as T;\n}\n\n/**\n * Writes an object as JSON to a file\n */\nexport function writeJson(path: string, data: unknown): void {\n writeFileSync(path, JSON.stringify(data, null, 2) + '\\n');\n}\n\n/**\n * Checks if path exists and is a directory\n */\nexport function isDirectory(path: string): boolean {\n return existsSync(path) && statSync(path).isDirectory();\n}\n","import { createHash } from 'node:crypto';\r\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';\r\nimport { join, relative } from 'node:path';\r\nimport type { UpgradeManifest, FileDiff } from '../types.js';\r\n\r\n/**\r\n * Computes SHA-256 hash of a file's contents.\r\n */\r\nexport function hashFile(filePath: string): string {\r\n const content = readFileSync(filePath);\r\n return createHash('sha256').update(content).digest('hex');\r\n}\r\n\r\n/**\r\n * Computes hashes for all files under the given paths, relative to baseDir.\r\n */\r\nexport function computeFileHashes(\r\n baseDir: string,\r\n paths: string[]\r\n): Record<string, string> {\r\n const hashes: Record<string, string> = {};\r\n const expanded = expandPaths(paths, baseDir);\r\n\r\n for (const filePath of expanded) {\r\n const fullPath = join(baseDir, filePath);\r\n if (existsSync(fullPath) && !statSync(fullPath).isDirectory()) {\r\n hashes[filePath] = hashFile(fullPath);\r\n }\r\n }\r\n\r\n return hashes;\r\n}\r\n\r\n/**\r\n * Recursively collects all file paths under a directory, relative to baseDir.\r\n */\r\nfunction walkDir(dir: string, baseDir: string): string[] {\r\n const results: string[] = [];\r\n if (!existsSync(dir)) return results;\r\n\r\n const entries = readdirSync(dir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const fullPath = join(dir, entry.name);\r\n if (entry.isDirectory()) {\r\n results.push(...walkDir(fullPath, baseDir));\r\n } else {\r\n results.push(relative(baseDir, fullPath));\r\n }\r\n }\r\n return results;\r\n}\r\n\r\n/**\r\n * Expands a list of file/directory paths into individual file paths.\r\n * If a path ends with \"/\" or is a directory in freshDir, expands to all files within.\r\n */\r\nfunction expandPaths(paths: string[], freshDir: string): string[] {\r\n const files: string[] = [];\r\n\r\n for (const p of paths) {\r\n const fullPath = join(freshDir, p);\r\n\r\n if (p.endsWith('/') || (existsSync(fullPath) && statSync(fullPath).isDirectory())) {\r\n files.push(...walkDir(fullPath, freshDir));\r\n } else {\r\n files.push(p);\r\n }\r\n }\r\n\r\n return [...new Set(files)];\r\n}\r\n\r\n/**\r\n * Normalizes path separators to forward slashes for consistent hash lookups\r\n * across Windows and Unix.\r\n */\r\nfunction normalizePath(filePath: string): string {\r\n return filePath.replace(/\\\\/g, '/');\r\n}\r\n\r\n/**\r\n * Compares files between the current project and a fresh template download.\r\n * Only examines files listed in the manifest's \"safe\" list.\r\n *\r\n * Uses stored file hashes (from .velocity.json) to detect user modifications:\r\n * - If the user's file matches its stored hash → user hasn't modified it → safe to overwrite\r\n * - If the user's file differs from its stored hash → user customized it → conflict\r\n * - If no stored hash exists (pre-hash upgrade) → falls back to overwrite (legacy behavior)\r\n */\r\nexport function diffProjects(\r\n currentDir: string,\r\n freshDir: string,\r\n manifest: UpgradeManifest,\r\n storedHashes?: Record<string, string>\r\n): FileDiff[] {\r\n const diffs: FileDiff[] = [];\r\n const safeFiles = expandPaths(manifest.files.safe, freshDir);\r\n\r\n for (const filePath of safeFiles) {\r\n const currentPath = join(currentDir, filePath);\r\n const freshPath = join(freshDir, filePath);\r\n const normalizedPath = normalizePath(filePath);\r\n\r\n // Fresh template file doesn't exist (shouldn't happen, but handle gracefully)\r\n if (!existsSync(freshPath)) continue;\r\n\r\n if (!existsSync(currentPath)) {\r\n diffs.push({ path: filePath, status: 'added', category: 'safe' });\r\n } else {\r\n const currentContent = readFileSync(currentPath);\r\n const freshContent = readFileSync(freshPath);\r\n\r\n if (Buffer.compare(currentContent, freshContent) === 0) {\r\n diffs.push({ path: filePath, status: 'unchanged', category: 'safe' });\r\n } else {\r\n // Template changed this file. Check if the user also modified it.\r\n const storedHash = storedHashes?.[normalizedPath];\r\n\r\n if (storedHash) {\r\n const currentHash = createHash('sha256').update(currentContent).digest('hex');\r\n if (currentHash !== storedHash) {\r\n // User modified this file AND template changed it → conflict\r\n diffs.push({ path: filePath, status: 'conflict', category: 'safe' });\r\n } else {\r\n // User hasn't touched it, only template changed → safe to overwrite\r\n diffs.push({ path: filePath, status: 'modified', category: 'safe' });\r\n }\r\n } else {\r\n // No stored hash (legacy project or first hash-aware upgrade).\r\n // Fall back to overwrite, but mark as modified so it shows in summary.\r\n diffs.push({ path: filePath, status: 'modified', category: 'safe' });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return diffs;\r\n}\r\n\r\n/**\r\n * Returns a summary count of diff statuses.\r\n */\r\nexport function summarizeDiffs(diffs: FileDiff[]): {\r\n added: number;\r\n modified: number;\r\n unchanged: number;\r\n conflict: number;\r\n} {\r\n let added = 0;\r\n let modified = 0;\r\n let unchanged = 0;\r\n let conflict = 0;\r\n\r\n for (const diff of diffs) {\r\n switch (diff.status) {\r\n case 'added':\r\n added++;\r\n break;\r\n case 'modified':\r\n modified++;\r\n break;\r\n case 'unchanged':\r\n unchanged++;\r\n break;\r\n case 'conflict':\r\n conflict++;\r\n break;\r\n }\r\n }\r\n\r\n return { added, modified, unchanged, conflict };\r\n}\r\n","import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, readdirSync, rmSync, statSync } from 'node:fs';\r\nimport { execSync } from 'node:child_process';\r\nimport { join, dirname, relative } from 'node:path';\r\nimport { tmpdir } from 'node:os';\r\nimport * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport { downloadTemplate } from 'giget';\r\nimport type { UpgradeOptions, UpgradeManifest, MigrationStep } from './types.js';\r\nimport { readVelocityConfig, writeVelocityConfig } from './utils/velocity-config.js';\r\nimport { readJson } from './utils/fs.js';\r\nimport { diffProjects, summarizeDiffs, computeFileHashes } from './utils/diff.js';\r\nimport {\r\n showUpgradeIntro,\r\n showChangeSummary,\r\n confirmUpgrade,\r\n showManualSteps,\r\n showProtectedNotice,\r\n showConflictNotice,\r\n showUpgradeOutro,\r\n warnDirtyGit,\r\n} from './upgrade-prompts.js';\r\n\r\ndeclare const CLI_VERSION: string;\r\n\r\nconst TEMPLATE_REPO = 'github:southwellmedia/velocity';\r\n\r\n// Hardcoded fallback safe list if manifest is missing from template\r\nconst FALLBACK_SAFE_FILES = [\r\n 'src/components/ui/',\r\n 'src/components/seo/',\r\n 'src/components/layout/',\r\n 'src/layouts/',\r\n 'src/lib/',\r\n 'src/styles/tokens/',\r\n 'src/styles/themes/',\r\n 'src/styles/global.css',\r\n 'src/content.config.ts',\r\n 'src/config/nav.config.ts',\r\n 'tsconfig.json',\r\n 'eslint.config.js',\r\n '.prettierrc',\r\n '.prettierignore',\r\n '.gitignore',\r\n 'vercel.json',\r\n 'netlify.toml',\r\n 'wrangler.toml',\r\n];\r\n\r\n/**\r\n * Checks if the project has uncommitted git changes.\r\n */\r\nfunction hasUncommittedChanges(targetDir: string): boolean {\r\n try {\r\n const result = execSync('git status --porcelain', {\r\n cwd: targetDir,\r\n encoding: 'utf-8',\r\n });\r\n return result.trim().length > 0;\r\n } catch {\r\n // Not a git repo or git not available — skip the check\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Compares two semver-like version strings.\r\n * Returns true if `current` < `required`.\r\n */\r\nfunction isVersionLessThan(current: string, required: string): boolean {\r\n const parse = (v: string) =>\r\n v.replace(/^v/, '').split(/[-.]/).map((p) => {\r\n const n = parseInt(p, 10);\r\n return isNaN(n) ? 0 : n;\r\n });\r\n\r\n const a = parse(current);\r\n const b = parse(required);\r\n const len = Math.max(a.length, b.length);\r\n\r\n for (let i = 0; i < len; i++) {\r\n const av = a[i] ?? 0;\r\n const bv = b[i] ?? 0;\r\n if (av < bv) return true;\r\n if (av > bv) return false;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Filters migrations to only those applicable for the user's version range.\r\n * A migration applies if:\r\n * - No fromVersion/toVersion: always applies (legacy behavior)\r\n * - If toVersion is set and user's current version is NOT less than toVersion, skip (user already past this migration)\r\n * - If fromVersion is set and user's current version IS less than fromVersion, skip (user hasn't reached the version where this migration matters)\r\n * - Otherwise, include it\r\n */\r\nfunction filterMigrations(migrations: MigrationStep[], currentVersion: string): MigrationStep[] {\r\n return migrations.filter((m) => {\r\n // No version constraints — always show (legacy)\r\n if (!m.fromVersion && !m.toVersion) return true;\r\n\r\n // User already past this migration's target version\r\n if (m.toVersion && !isVersionLessThan(currentVersion, m.toVersion)) return false;\r\n\r\n // User hasn't reached the starting version for this migration\r\n if (m.fromVersion && isVersionLessThan(currentVersion, m.fromVersion)) return false;\r\n\r\n return true;\r\n });\r\n}\r\n\r\n/**\r\n * Scans user files for migration patterns and returns matches.\r\n */\r\nfunction scanForMigrationPatterns(\r\n targetDir: string,\r\n migrations: MigrationStep[]\r\n): Map<string, string[]> {\r\n const results = new Map<string, string[]>();\r\n\r\n for (const migration of migrations) {\r\n if (!migration.pattern) {\r\n results.set(migration.title, []);\r\n continue;\r\n }\r\n\r\n const regex = new RegExp(migration.pattern);\r\n const matches: string[] = [];\r\n\r\n // Determine search paths\r\n const searchPaths = migration.searchPaths?.length\r\n ? migration.searchPaths\r\n : ['src/'];\r\n\r\n for (const searchPath of searchPaths) {\r\n const fullPath = join(targetDir, searchPath);\r\n if (!existsSync(fullPath)) continue;\r\n\r\n const files = walkFiles(fullPath);\r\n for (const file of files) {\r\n try {\r\n const content = readFileSync(file, 'utf-8');\r\n if (regex.test(content)) {\r\n matches.push(relative(targetDir, file));\r\n }\r\n } catch {\r\n // Skip unreadable files\r\n }\r\n }\r\n }\r\n\r\n results.set(migration.title, matches);\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * Recursively walks a directory and returns all file paths.\r\n */\r\nfunction walkFiles(dir: string): string[] {\r\n const results: string[] = [];\r\n if (!existsSync(dir)) return results;\r\n\r\n const stat = statSync(dir);\r\n if (!stat.isDirectory()) {\r\n return [dir];\r\n }\r\n\r\n const entries = readdirSync(dir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const fullPath = join(dir, entry.name);\r\n if (entry.isDirectory()) {\r\n // Skip node_modules and .git\r\n if (entry.name === 'node_modules' || entry.name === '.git') continue;\r\n results.push(...walkFiles(fullPath));\r\n } else {\r\n results.push(fullPath);\r\n }\r\n }\r\n return results;\r\n}\r\n\r\n/**\r\n * Merges dependency changes into the project's package.json.\r\n */\r\nfunction mergePackageJsonDeps(\r\n targetDir: string,\r\n manifest: UpgradeManifest\r\n): void {\r\n const pkgPath = join(targetDir, 'package.json');\r\n if (!existsSync(pkgPath)) return;\r\n\r\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\r\n\r\n // Update dependencies\r\n for (const [name, version] of Object.entries(manifest.dependencies.update)) {\r\n if (pkg.dependencies?.[name] !== undefined) {\r\n pkg.dependencies[name] = version;\r\n } else if (pkg.devDependencies?.[name] !== undefined) {\r\n pkg.devDependencies[name] = version;\r\n } else {\r\n // Default to dependencies\r\n if (!pkg.dependencies) pkg.dependencies = {};\r\n pkg.dependencies[name] = version;\r\n }\r\n }\r\n\r\n // Remove dependencies\r\n for (const name of manifest.dependencies.remove) {\r\n if (pkg.dependencies?.[name] !== undefined) {\r\n delete pkg.dependencies[name];\r\n }\r\n if (pkg.devDependencies?.[name] !== undefined) {\r\n delete pkg.devDependencies[name];\r\n }\r\n }\r\n\r\n // Add new dependencies\r\n for (const [name, version] of Object.entries(manifest.dependencies.add)) {\r\n if (!pkg.dependencies) pkg.dependencies = {};\r\n pkg.dependencies[name] = version;\r\n }\r\n\r\n writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\r\n}\r\n\r\n/**\r\n * Backs up conflicting files to .velocity-backup/<version>/.\r\n * Returns the backup directory path.\r\n */\r\nfunction backupConflicts(\r\n targetDir: string,\r\n conflicts: { path: string }[],\r\n fromVersion: string\r\n): string {\r\n const backupDir = join(targetDir, '.velocity-backup', fromVersion);\r\n\r\n for (const conflict of conflicts) {\r\n const srcPath = join(targetDir, conflict.path);\r\n const destPath = join(backupDir, conflict.path);\r\n const destDir = dirname(destPath);\r\n\r\n if (!existsSync(destDir)) {\r\n mkdirSync(destDir, { recursive: true });\r\n }\r\n\r\n if (existsSync(srcPath)) {\r\n copyFileSync(srcPath, destPath);\r\n }\r\n }\r\n\r\n return backupDir;\r\n}\r\n\r\n/**\r\n * Main upgrade orchestration function.\r\n */\r\nexport async function upgrade(options: UpgradeOptions): Promise<void> {\r\n const { targetDir, dryRun, yes } = options;\r\n\r\n // 1. Read .velocity.json\r\n const config = readVelocityConfig(targetDir);\r\n if (!config) {\r\n p.log.error(\r\n pc.red(\r\n \"This doesn't appear to be a Velocity project.\\n\" +\r\n 'Run this command from a project created with create-velocity-astro.'\r\n )\r\n );\r\n process.exit(1);\r\n }\r\n\r\n // Check for dirty git state\r\n if (hasUncommittedChanges(targetDir)) {\r\n const proceed = await warnDirtyGit(yes);\r\n if (!proceed) return;\r\n }\r\n\r\n // 2. Download latest template to temp dir\r\n const spinner = p.spinner();\r\n spinner.start('Downloading latest template...');\r\n\r\n const tempDir = join(tmpdir(), `velocity-upgrade-${Date.now()}`);\r\n\r\n try {\r\n await downloadTemplate(TEMPLATE_REPO, {\r\n dir: tempDir,\r\n force: true,\r\n });\r\n spinner.stop('Template downloaded');\r\n } catch (error) {\r\n spinner.stop('Failed to download template');\r\n p.log.error(\r\n pc.red(\r\n 'Could not download template. Check your internet connection.\\n' +\r\n (error instanceof Error ? error.message : '')\r\n )\r\n );\r\n cleanup(tempDir);\r\n process.exit(1);\r\n }\r\n\r\n // 3. Read velocity-manifest.json from fresh template\r\n let manifest: UpgradeManifest;\r\n const manifestPath = join(tempDir, 'velocity-manifest.json');\r\n\r\n if (existsSync(manifestPath)) {\r\n manifest = readJson<UpgradeManifest>(manifestPath);\r\n } else {\r\n // Fallback: use hardcoded safe list\r\n p.log.warn(pc.yellow('Manifest not found in template. Using fallback file list.'));\r\n\r\n // Try to read version from template's package.json\r\n let templateVersion = config.version;\r\n const templatePkgPath = join(tempDir, 'package.json');\r\n if (existsSync(templatePkgPath)) {\r\n const templatePkg = readJson<{ version?: string }>(templatePkgPath);\r\n if (templatePkg.version) {\r\n templateVersion = templatePkg.version;\r\n }\r\n }\r\n\r\n manifest = {\r\n version: templateVersion,\r\n minCliVersion: '1.0.0',\r\n files: {\r\n safe: FALLBACK_SAFE_FILES,\r\n protected: [],\r\n },\r\n dependencies: {\r\n update: {},\r\n remove: [],\r\n add: {},\r\n },\r\n migrations: [],\r\n };\r\n }\r\n\r\n // Check CLI version requirement\r\n if (isVersionLessThan(CLI_VERSION, manifest.minCliVersion)) {\r\n p.log.error(\r\n pc.red(\r\n `This upgrade requires create-velocity-astro >= ${manifest.minCliVersion}.\\n` +\r\n 'Run `npm update -g create-velocity-astro` to update.'\r\n )\r\n );\r\n cleanup(tempDir);\r\n process.exit(1);\r\n }\r\n\r\n // Filter migrations to only those relevant to the user's current version\r\n manifest.migrations = filterMigrations(manifest.migrations, config.version);\r\n\r\n // Check if already on latest version\r\n if (config.version === manifest.version) {\r\n showUpgradeIntro(config.version, manifest.version);\r\n p.log.info(pc.green(`Already on v${manifest.version}. Nothing to upgrade.`));\r\n p.outro('');\r\n cleanup(tempDir);\r\n return;\r\n }\r\n\r\n // 4. Diff safe files, passing stored hashes for user-modification detection\r\n const diffs = diffProjects(targetDir, tempDir, manifest, config.fileHashes);\r\n const { added, modified, conflict } = summarizeDiffs(diffs);\r\n\r\n // If no changes at all\r\n if (added === 0 && modified === 0 && conflict === 0 &&\r\n Object.keys(manifest.dependencies.update).length === 0 &&\r\n manifest.dependencies.remove.length === 0 &&\r\n Object.keys(manifest.dependencies.add).length === 0) {\r\n showUpgradeIntro(config.version, manifest.version);\r\n p.log.info(pc.green('All files are up to date. Updating version marker only.'));\r\n if (!dryRun) {\r\n writeVelocityConfig(targetDir, {\r\n ...config,\r\n version: manifest.version,\r\n updatedAt: new Date().toISOString().slice(0, 10),\r\n });\r\n }\r\n p.outro('');\r\n cleanup(tempDir);\r\n return;\r\n }\r\n\r\n // 5. Show summary and confirm\r\n showUpgradeIntro(config.version, manifest.version);\r\n showChangeSummary(diffs, manifest);\r\n\r\n const shouldProceed = await confirmUpgrade(dryRun, yes);\r\n\r\n if (dryRun) {\r\n // In dry-run mode, still show protected notice and manual migration steps\r\n showProtectedNotice(manifest);\r\n const matchResults = scanForMigrationPatterns(targetDir, manifest.migrations);\r\n showManualSteps(manifest.migrations, matchResults);\r\n p.outro(pc.dim('Dry run complete. No changes were made.'));\r\n cleanup(tempDir);\r\n return;\r\n }\r\n\r\n if (!shouldProceed) {\r\n cleanup(tempDir);\r\n return;\r\n }\r\n\r\n // 6. Apply changes\r\n spinner.start('Applying changes...');\r\n\r\n // 6a. Back up conflicting files before overwriting\r\n const conflictDiffs = diffs.filter((d) => d.status === 'conflict');\r\n let backupDir = '';\r\n if (conflictDiffs.length > 0) {\r\n backupDir = backupConflicts(targetDir, conflictDiffs, config.version);\r\n }\r\n\r\n // 6b. Copy modified, added, and conflicting safe files (conflicts get template version)\r\n const changedDiffs = diffs.filter(\r\n (d) => d.status === 'added' || d.status === 'modified' || d.status === 'conflict'\r\n );\r\n for (const diff of changedDiffs) {\r\n const src = join(tempDir, diff.path);\r\n const dest = join(targetDir, diff.path);\r\n const destDir = dirname(dest);\r\n\r\n if (!existsSync(destDir)) {\r\n mkdirSync(destDir, { recursive: true });\r\n }\r\n\r\n copyFileSync(src, dest);\r\n }\r\n\r\n // 6c. Merge package.json dependencies\r\n const hasDepChanges =\r\n Object.keys(manifest.dependencies.update).length > 0 ||\r\n manifest.dependencies.remove.length > 0 ||\r\n Object.keys(manifest.dependencies.add).length > 0;\r\n\r\n if (hasDepChanges) {\r\n mergePackageJsonDeps(targetDir, manifest);\r\n }\r\n\r\n // 6d. Compute and store file hashes for the new state\r\n const newHashes = computeFileHashes(targetDir, manifest.files.safe);\r\n\r\n // 6e. Update .velocity.json with new version and file hashes\r\n writeVelocityConfig(targetDir, {\r\n ...config,\r\n version: manifest.version,\r\n updatedAt: new Date().toISOString().slice(0, 10),\r\n fileHashes: newHashes,\r\n });\r\n\r\n spinner.stop('Changes applied');\r\n\r\n // Report results\r\n if (modified > 0) {\r\n p.log.success(pc.green(`Updated ${modified} framework file${modified !== 1 ? 's' : ''}`));\r\n }\r\n if (added > 0) {\r\n p.log.success(pc.green(`Added ${added} new file${added !== 1 ? 's' : ''}`));\r\n }\r\n if (hasDepChanges) {\r\n p.log.success(pc.green('Updated package.json dependencies'));\r\n }\r\n p.log.success(pc.green('Updated .velocity.json'));\r\n\r\n // 7. Show conflict notice (before protected notice, as it's more urgent)\r\n if (conflictDiffs.length > 0) {\r\n showConflictNotice(backupDir, conflictDiffs);\r\n }\r\n\r\n // 8. Show protected file notice\r\n showProtectedNotice(manifest);\r\n\r\n // 9. Scan for migration patterns and show manual steps\r\n const matchResults = scanForMigrationPatterns(targetDir, manifest.migrations);\r\n showManualSteps(manifest.migrations, matchResults);\r\n\r\n // 10. Show outro\r\n showUpgradeOutro(hasDepChanges);\r\n\r\n cleanup(tempDir);\r\n}\r\n\r\n/**\r\n * Cleans up temporary directory.\r\n */\r\nfunction cleanup(tempDir: string): void {\r\n try {\r\n if (existsSync(tempDir)) {\r\n rmSync(tempDir, { recursive: true, force: true });\r\n }\r\n } catch {\r\n // Ignore cleanup errors\r\n }\r\n}\r\n","import * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport type { FileDiff, MigrationStep, UpgradeManifest } from './types.js';\r\nimport { summarizeDiffs } from './utils/diff.js';\r\n\r\n/**\r\n * Shows the upgrade intro with version info.\r\n */\r\nexport function showUpgradeIntro(currentVersion: string, latestVersion: string): void {\r\n console.log();\r\n p.intro(pc.bgCyan(pc.black(' Velocity Upgrade ')));\r\n p.log.info(\r\n `Current version: ${pc.dim(`v${currentVersion}`)}\\n` +\r\n `Latest version: ${pc.green(`v${latestVersion}`)}`\r\n );\r\n}\r\n\r\n/**\r\n * Shows a summary of changes that will be applied.\r\n */\r\nexport function showChangeSummary(\r\n diffs: FileDiff[],\r\n manifest: UpgradeManifest\r\n): void {\r\n const { added, modified, conflict } = summarizeDiffs(diffs);\r\n const migrationCount = manifest.migrations.length;\r\n\r\n const lines: string[] = [];\r\n\r\n // List conflict files first (most important)\r\n const conflictFiles = diffs.filter((d) => d.status === 'conflict');\r\n if (conflictFiles.length > 0) {\r\n lines.push(pc.bold(pc.yellow(' Conflicts (user-modified files that also changed in template):')));\r\n for (const f of conflictFiles) {\r\n lines.push(` ${pc.yellow('⚠')} ${f.path} ${pc.dim('→ backup created, template version applied')}`);\r\n }\r\n }\r\n\r\n // List specific files that will be modified\r\n const modifiedFiles = diffs.filter((d) => d.status === 'modified');\r\n const addedFiles = diffs.filter((d) => d.status === 'added');\r\n\r\n if (modifiedFiles.length > 0) {\r\n lines.push(pc.bold(' Files to update:'));\r\n for (const f of modifiedFiles) {\r\n lines.push(` ${pc.yellow('~')} ${f.path}`);\r\n }\r\n }\r\n if (addedFiles.length > 0) {\r\n lines.push(pc.bold(' New files:'));\r\n for (const f of addedFiles) {\r\n lines.push(` ${pc.green('+')} ${f.path}`);\r\n }\r\n }\r\n\r\n // List specific dependency changes\r\n const depUpdates = Object.entries(manifest.dependencies.update);\r\n const depRemoves = manifest.dependencies.remove;\r\n const depAdds = Object.entries(manifest.dependencies.add);\r\n\r\n if (depUpdates.length > 0 || depRemoves.length > 0 || depAdds.length > 0) {\r\n lines.push(pc.bold(' Dependency changes:'));\r\n for (const [name, version] of depUpdates) {\r\n lines.push(` ${pc.cyan('~')} ${name} → ${version}`);\r\n }\r\n for (const name of depRemoves) {\r\n lines.push(` ${pc.red('-')} ${name}`);\r\n }\r\n for (const [name, version] of depAdds) {\r\n lines.push(` ${pc.green('+')} ${name}@${version}`);\r\n }\r\n }\r\n\r\n if (migrationCount > 0) {\r\n lines.push(` ${pc.yellow(`${migrationCount}`)} manual migration step${migrationCount !== 1 ? 's' : ''} ${pc.dim('(shown after upgrade)')}`);\r\n }\r\n\r\n // Summary counts\r\n const summary = [];\r\n if (modified > 0) summary.push(`${modified} updated`);\r\n if (added > 0) summary.push(`${added} added`);\r\n if (conflict > 0) summary.push(`${pc.yellow(`${conflict} conflicts`)}`);\r\n summary.push(`${manifest.files.protected.length} protected ${pc.dim('(not touched)')}`);\r\n\r\n lines.push('');\r\n lines.push(` ${pc.dim('Totals: ' + summary.join(', '))}`);\r\n\r\n if (lines.length > 0) {\r\n p.log.message(pc.bold('Changes to apply:') + '\\n' + lines.join('\\n'));\r\n }\r\n}\r\n\r\n/**\r\n * Shows a notice about protected files that may need manual attention.\r\n */\r\nexport function showProtectedNotice(manifest: UpgradeManifest): void {\r\n const protectedFiles = manifest.files.protected;\r\n if (protectedFiles.length === 0) return;\r\n\r\n const lines = [\r\n `The following files were ${pc.bold('not modified')} to preserve your customizations:`,\r\n '',\r\n ];\r\n\r\n for (const f of protectedFiles) {\r\n lines.push(` ${pc.dim('-')} ${f}`);\r\n }\r\n\r\n lines.push('');\r\n lines.push(pc.dim('If the upgrade requires changes to these files, they will appear in the manual steps below.'));\r\n\r\n p.log.info(lines.join('\\n'));\r\n}\r\n\r\n/**\r\n * Shows a notice about conflict files that were backed up.\r\n */\r\nexport function showConflictNotice(backupDir: string, conflicts: FileDiff[]): void {\r\n if (conflicts.length === 0) return;\r\n\r\n const lines = [\r\n pc.yellow(`${conflicts.length} file${conflicts.length !== 1 ? 's were' : ' was'} backed up because you modified ${conflicts.length !== 1 ? 'them' : 'it'}:`),\r\n '',\r\n ];\r\n\r\n for (const f of conflicts) {\r\n lines.push(` ${pc.yellow('⚠')} ${f.path}`);\r\n }\r\n\r\n lines.push('');\r\n lines.push(`Your versions are saved in: ${pc.cyan(backupDir)}`);\r\n lines.push(pc.dim('Compare your backup against the new version and merge your customizations back in.'));\r\n\r\n p.log.warning(lines.join('\\n'));\r\n}\r\n\r\n/**\r\n * Asks user to confirm the upgrade. Returns true to proceed.\r\n * In dry-run mode, shows what would happen without asking.\r\n * With --yes flag, skips the interactive prompt.\r\n */\r\nexport async function confirmUpgrade(dryRun: boolean, yes: boolean): Promise<boolean> {\r\n if (dryRun) {\r\n p.log.info(pc.dim('Dry run — no changes will be made.'));\r\n return false;\r\n }\r\n\r\n if (yes) {\r\n p.log.info(pc.dim('Proceeding with upgrade (--yes).'));\r\n return true;\r\n }\r\n\r\n const proceed = await p.confirm({\r\n message: 'Proceed with upgrade?',\r\n initialValue: true,\r\n });\r\n\r\n if (p.isCancel(proceed) || !proceed) {\r\n p.cancel('Upgrade cancelled.');\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Shows manual migration steps with file matches.\r\n */\r\nexport function showManualSteps(\r\n migrations: MigrationStep[],\r\n matchResults: Map<string, string[]>\r\n): void {\r\n if (migrations.length === 0) return;\r\n\r\n const lines: string[] = [];\r\n\r\n for (let i = 0; i < migrations.length; i++) {\r\n const step = migrations[i]!;\r\n const matches = matchResults.get(step.title) ?? [];\r\n\r\n lines.push(`${pc.bold(`${i + 1}. ${step.title}`)}`);\r\n lines.push(` ${step.description}`);\r\n\r\n if (matches.length > 0) {\r\n lines.push(` ${pc.yellow('⚠')} Found matches in: ${matches.join(', ')}`);\r\n }\r\n\r\n lines.push('');\r\n }\r\n\r\n p.log.warning(pc.bold('Manual steps required:') + '\\n\\n' + lines.join('\\n'));\r\n}\r\n\r\n/**\r\n * Shows the upgrade completion message.\r\n */\r\nexport function showUpgradeOutro(hasDepChanges: boolean): void {\r\n if (hasDepChanges) {\r\n p.log.info(`Run ${pc.cyan('pnpm install')} to update dependencies.`);\r\n }\r\n p.outro(pc.green('Upgrade complete! Review the manual steps above.'));\r\n}\r\n\r\n/**\r\n * Warns about dirty git state.\r\n */\r\nexport async function warnDirtyGit(yes: boolean): Promise<boolean> {\r\n if (yes) {\r\n p.log.warn(pc.yellow('You have uncommitted changes. Proceeding anyway (--yes).'));\r\n return true;\r\n }\r\n\r\n p.log.warn(pc.yellow('You have uncommitted changes. We recommend committing or stashing first.'));\r\n\r\n const proceed = await p.confirm({\r\n message: 'Continue anyway?',\r\n initialValue: false,\r\n });\r\n\r\n if (p.isCancel(proceed) || !proceed) {\r\n p.cancel('Upgrade cancelled.');\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n","import { run } from './cli.js';\n\nrun(process.argv.slice(2)).catch((error) => {\n console.error(error);\n process.exit(1);\n});\n"],"mappings":"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","names":["resolve","existsSync","p","pc","resolve","existsSync","mkdirSync","readdirSync","copyFileSync","readFileSync","writeFileSync","join","dirname","p","execa","__dirname","existsSync","existsSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","join","dirname","existsSync","readFileSync","writeFileSync","join","existsSync","existsSync","readFileSync","readdirSync","statSync","join","p","existsSync","mkdirSync","readdirSync","join","copyFileSync","readFileSync","writeFileSync","dirname","spinner","execa","existsSync","readFileSync","writeFileSync","mkdirSync","copyFileSync","readdirSync","rmSync","statSync","join","dirname","relative","p","pc","downloadTemplate","p","pc","pc","TEMPLATE_REPO","p","join","existsSync","readFileSync","relative","statSync","readdirSync","writeFileSync","dirname","mkdirSync","copyFileSync","pc","spinner","downloadTemplate","matchResults","rmSync","pc","targetDir","resolve","projectName","existsSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-velocity-astro",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Create Velocity - A CLI to scaffold production-ready Astro 6 + Tailwind v4 projects",
5
5
  "type": "module",
6
6
  "license": "MIT",