prev-cli 0.24.4 → 0.24.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +241 -67
- package/dist/utils/debug.d.ts +42 -0
- package/dist/vite/config.d.ts +3 -0
- package/dist/vite/plugins/debug-plugin.d.ts +3 -0
- package/dist/vite/start.d.ts +2 -0
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { parseArgs } from "util";
|
|
5
|
-
import
|
|
6
|
-
import { existsSync as existsSync7, mkdirSync as
|
|
5
|
+
import path11 from "path";
|
|
6
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync3, writeFileSync as writeFileSync5, rmSync as rmSync3, readFileSync as readFileSync5 } from "fs";
|
|
7
7
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
8
8
|
|
|
9
9
|
// src/vite/start.ts
|
|
@@ -15,7 +15,7 @@ import react from "@vitejs/plugin-react";
|
|
|
15
15
|
import mdx from "@mdx-js/rollup";
|
|
16
16
|
import remarkGfm from "remark-gfm";
|
|
17
17
|
import rehypeHighlight from "rehype-highlight";
|
|
18
|
-
import
|
|
18
|
+
import path9 from "path";
|
|
19
19
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20
20
|
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
21
21
|
|
|
@@ -697,6 +697,56 @@ function createConfigPlugin(config) {
|
|
|
697
697
|
};
|
|
698
698
|
}
|
|
699
699
|
|
|
700
|
+
// src/vite/plugins/debug-plugin.ts
|
|
701
|
+
function debugPlugin(collector) {
|
|
702
|
+
return {
|
|
703
|
+
name: "prev-debug",
|
|
704
|
+
enforce: "pre",
|
|
705
|
+
configResolved() {
|
|
706
|
+
collector.startPhase("configResolved");
|
|
707
|
+
},
|
|
708
|
+
buildStart() {
|
|
709
|
+
collector.startPhase("buildStart");
|
|
710
|
+
},
|
|
711
|
+
resolveId(id, importer) {
|
|
712
|
+
const start = performance.now();
|
|
713
|
+
collector.trackFile(id, "resolve", start);
|
|
714
|
+
if (importer) {
|
|
715
|
+
collector.trackFile(`${id} <- ${importer}`, "resolve", start);
|
|
716
|
+
}
|
|
717
|
+
return null;
|
|
718
|
+
},
|
|
719
|
+
load(id) {
|
|
720
|
+
const start = performance.now();
|
|
721
|
+
collector.trackFile(id, "load", start);
|
|
722
|
+
return null;
|
|
723
|
+
},
|
|
724
|
+
transform(_code, id) {
|
|
725
|
+
const start = performance.now();
|
|
726
|
+
collector.trackFile(id, "transform", start);
|
|
727
|
+
return null;
|
|
728
|
+
},
|
|
729
|
+
configureServer(server) {
|
|
730
|
+
collector.startPhase("configureServer");
|
|
731
|
+
server.httpServer?.once("listening", () => {
|
|
732
|
+
collector.startPhase("serverListening");
|
|
733
|
+
});
|
|
734
|
+
server.middlewares.use((req, _res, next) => {
|
|
735
|
+
if (req.url && !req.url.startsWith("/@") && !req.url.includes("__")) {
|
|
736
|
+
collector.trackFile(req.url, "resolve", performance.now());
|
|
737
|
+
}
|
|
738
|
+
next();
|
|
739
|
+
});
|
|
740
|
+
},
|
|
741
|
+
handleHotUpdate({ file }) {
|
|
742
|
+
collector.trackFile(file, "transform", performance.now());
|
|
743
|
+
},
|
|
744
|
+
buildEnd() {
|
|
745
|
+
collector.endPhase("build");
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
|
|
700
750
|
// src/config/schema.ts
|
|
701
751
|
var defaultConfig = {
|
|
702
752
|
theme: "system",
|
|
@@ -778,6 +828,104 @@ function updateOrder(rootDir, pathKey, order) {
|
|
|
778
828
|
config.order[pathKey] = order;
|
|
779
829
|
saveConfig(rootDir, config);
|
|
780
830
|
}
|
|
831
|
+
// src/utils/debug.ts
|
|
832
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
833
|
+
import path8 from "path";
|
|
834
|
+
|
|
835
|
+
class DebugCollector {
|
|
836
|
+
startTime;
|
|
837
|
+
files = [];
|
|
838
|
+
phases = {};
|
|
839
|
+
currentPhase = "init";
|
|
840
|
+
rootDir;
|
|
841
|
+
constructor(rootDir) {
|
|
842
|
+
this.startTime = performance.now();
|
|
843
|
+
this.rootDir = rootDir;
|
|
844
|
+
this.startPhase("init");
|
|
845
|
+
}
|
|
846
|
+
startPhase(name) {
|
|
847
|
+
const now = performance.now();
|
|
848
|
+
if (this.phases[this.currentPhase] && !this.phases[this.currentPhase].endMs) {
|
|
849
|
+
this.phases[this.currentPhase].endMs = Math.round(now - this.startTime);
|
|
850
|
+
}
|
|
851
|
+
this.currentPhase = name;
|
|
852
|
+
this.phases[name] = { startMs: Math.round(now - this.startTime) };
|
|
853
|
+
}
|
|
854
|
+
endPhase(name) {
|
|
855
|
+
const phaseName = name || this.currentPhase;
|
|
856
|
+
const now = performance.now();
|
|
857
|
+
if (this.phases[phaseName]) {
|
|
858
|
+
this.phases[phaseName].endMs = Math.round(now - this.startTime);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
trackFile(filePath, event, startTime) {
|
|
862
|
+
const now = performance.now();
|
|
863
|
+
this.files.push({
|
|
864
|
+
path: filePath,
|
|
865
|
+
event,
|
|
866
|
+
ms: Math.round(now - startTime),
|
|
867
|
+
phase: this.currentPhase,
|
|
868
|
+
timestamp: Math.round(startTime - this.startTime)
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
generateSummary() {
|
|
872
|
+
const byDirectory = {};
|
|
873
|
+
const byEvent = { resolve: 0, load: 0, transform: 0 };
|
|
874
|
+
const fileTimeAccum = {};
|
|
875
|
+
for (const file of this.files) {
|
|
876
|
+
byEvent[file.event] = (byEvent[file.event] || 0) + 1;
|
|
877
|
+
fileTimeAccum[file.path] = (fileTimeAccum[file.path] || 0) + file.ms;
|
|
878
|
+
const relativePath = file.path.startsWith(this.rootDir) ? file.path.slice(this.rootDir.length) : file.path;
|
|
879
|
+
let dir;
|
|
880
|
+
if (relativePath.includes("node_modules")) {
|
|
881
|
+
const nmIndex = relativePath.indexOf("node_modules");
|
|
882
|
+
const prefix = relativePath.slice(0, nmIndex + "node_modules".length);
|
|
883
|
+
const afterNm = relativePath.slice(nmIndex + "node_modules/".length);
|
|
884
|
+
const pkgName = afterNm.split("/")[0].startsWith("@") ? afterNm.split("/").slice(0, 2).join("/") : afterNm.split("/")[0];
|
|
885
|
+
dir = `${prefix}/${pkgName}`;
|
|
886
|
+
} else {
|
|
887
|
+
const parts = relativePath.split("/").filter(Boolean);
|
|
888
|
+
dir = parts.length > 1 ? `/${parts[0]}` : "/";
|
|
889
|
+
}
|
|
890
|
+
byDirectory[dir] = (byDirectory[dir] || 0) + 1;
|
|
891
|
+
}
|
|
892
|
+
const slowest = Object.entries(fileTimeAccum).map(([path9, totalMs]) => ({ path: path9, totalMs })).sort((a, b) => b.totalMs - a.totalMs).slice(0, 20);
|
|
893
|
+
return {
|
|
894
|
+
totalFiles: this.files.length,
|
|
895
|
+
byDirectory,
|
|
896
|
+
byEvent,
|
|
897
|
+
slowest
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
writeReport() {
|
|
901
|
+
const now = performance.now();
|
|
902
|
+
const totalStartupMs = Math.round(now - this.startTime);
|
|
903
|
+
this.endPhase();
|
|
904
|
+
const report = {
|
|
905
|
+
timestamp: new Date().toISOString(),
|
|
906
|
+
totalStartupMs,
|
|
907
|
+
phases: this.phases,
|
|
908
|
+
files: this.files,
|
|
909
|
+
summary: this.generateSummary()
|
|
910
|
+
};
|
|
911
|
+
const debugDir = path8.join(this.rootDir, ".prev-debug");
|
|
912
|
+
mkdirSync2(debugDir, { recursive: true });
|
|
913
|
+
const date = new Date;
|
|
914
|
+
const filename = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}-${String(date.getHours()).padStart(2, "0")}-${String(date.getMinutes()).padStart(2, "0")}-${String(date.getSeconds()).padStart(2, "0")}.json`;
|
|
915
|
+
const filepath = path8.join(debugDir, filename);
|
|
916
|
+
writeFileSync4(filepath, JSON.stringify(report, null, 2));
|
|
917
|
+
return filepath;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
var currentCollector = null;
|
|
921
|
+
function createDebugCollector(rootDir) {
|
|
922
|
+
currentCollector = new DebugCollector(rootDir);
|
|
923
|
+
return currentCollector;
|
|
924
|
+
}
|
|
925
|
+
function getDebugCollector() {
|
|
926
|
+
return currentCollector;
|
|
927
|
+
}
|
|
928
|
+
|
|
781
929
|
// src/vite/config.ts
|
|
782
930
|
function createFriendlyLogger() {
|
|
783
931
|
const logger = createLogger("info", { allowClearScreen: false });
|
|
@@ -833,9 +981,9 @@ function createFriendlyLogger() {
|
|
|
833
981
|
};
|
|
834
982
|
}
|
|
835
983
|
function findCliRoot2() {
|
|
836
|
-
let dir =
|
|
984
|
+
let dir = path9.dirname(fileURLToPath2(import.meta.url));
|
|
837
985
|
for (let i = 0;i < 10; i++) {
|
|
838
|
-
const pkgPath =
|
|
986
|
+
const pkgPath = path9.join(dir, "package.json");
|
|
839
987
|
if (existsSync5(pkgPath)) {
|
|
840
988
|
try {
|
|
841
989
|
const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
@@ -844,24 +992,24 @@ function findCliRoot2() {
|
|
|
844
992
|
}
|
|
845
993
|
} catch {}
|
|
846
994
|
}
|
|
847
|
-
const parent =
|
|
995
|
+
const parent = path9.dirname(dir);
|
|
848
996
|
if (parent === dir)
|
|
849
997
|
break;
|
|
850
998
|
dir = parent;
|
|
851
999
|
}
|
|
852
|
-
return
|
|
1000
|
+
return path9.dirname(path9.dirname(fileURLToPath2(import.meta.url)));
|
|
853
1001
|
}
|
|
854
1002
|
function findNodeModules(cliRoot2) {
|
|
855
|
-
const localNodeModules =
|
|
856
|
-
if (existsSync5(
|
|
1003
|
+
const localNodeModules = path9.join(cliRoot2, "node_modules");
|
|
1004
|
+
if (existsSync5(path9.join(localNodeModules, "react"))) {
|
|
857
1005
|
return localNodeModules;
|
|
858
1006
|
}
|
|
859
1007
|
let dir = cliRoot2;
|
|
860
1008
|
for (let i = 0;i < 10; i++) {
|
|
861
|
-
const parent =
|
|
1009
|
+
const parent = path9.dirname(dir);
|
|
862
1010
|
if (parent === dir)
|
|
863
1011
|
break;
|
|
864
|
-
if (
|
|
1012
|
+
if (path9.basename(parent) === "node_modules" && existsSync5(path9.join(parent, "react"))) {
|
|
865
1013
|
return parent;
|
|
866
1014
|
}
|
|
867
1015
|
dir = parent;
|
|
@@ -870,11 +1018,15 @@ function findNodeModules(cliRoot2) {
|
|
|
870
1018
|
}
|
|
871
1019
|
var cliRoot2 = findCliRoot2();
|
|
872
1020
|
var cliNodeModules = findNodeModules(cliRoot2);
|
|
873
|
-
var srcRoot2 =
|
|
1021
|
+
var srcRoot2 = path9.join(cliRoot2, "src");
|
|
874
1022
|
async function createViteConfig(options) {
|
|
875
|
-
const { rootDir, mode, port, include, base } = options;
|
|
1023
|
+
const { rootDir, mode, port, include, base, debug } = options;
|
|
876
1024
|
const cacheDir = await ensureCacheDir(rootDir);
|
|
877
1025
|
const config = loadConfig(rootDir);
|
|
1026
|
+
const debugCollector = debug ? createDebugCollector(rootDir) : null;
|
|
1027
|
+
if (debugCollector) {
|
|
1028
|
+
debugCollector.startPhase("configLoad");
|
|
1029
|
+
}
|
|
878
1030
|
return {
|
|
879
1031
|
root: rootDir,
|
|
880
1032
|
mode,
|
|
@@ -885,13 +1037,14 @@ async function createViteConfig(options) {
|
|
|
885
1037
|
envDir: cliRoot2,
|
|
886
1038
|
envPrefix: "PREV_",
|
|
887
1039
|
plugins: [
|
|
1040
|
+
...debugCollector ? [debugPlugin(debugCollector)] : [],
|
|
888
1041
|
mdx({
|
|
889
1042
|
remarkPlugins: [remarkGfm],
|
|
890
1043
|
rehypePlugins: [rehypeHighlight],
|
|
891
1044
|
providerImportSource: "@mdx-js/react",
|
|
892
1045
|
include: [
|
|
893
|
-
|
|
894
|
-
|
|
1046
|
+
path9.join(rootDir, "**/*.md"),
|
|
1047
|
+
path9.join(rootDir, "**/*.mdx")
|
|
895
1048
|
],
|
|
896
1049
|
exclude: [
|
|
897
1050
|
"**/node_modules/**",
|
|
@@ -939,7 +1092,7 @@ async function createViteConfig(options) {
|
|
|
939
1092
|
if (urlPath.startsWith("/__") || urlPath.startsWith("/@") || urlPath.startsWith("/node_modules") || urlPath.includes(".")) {
|
|
940
1093
|
return next();
|
|
941
1094
|
}
|
|
942
|
-
const indexPath =
|
|
1095
|
+
const indexPath = path9.join(srcRoot2, "theme/index.html");
|
|
943
1096
|
if (existsSync5(indexPath)) {
|
|
944
1097
|
server.transformIndexHtml(req.url, readFileSync4(indexPath, "utf-8")).then((html) => {
|
|
945
1098
|
res.setHeader("Content-Type", "text/html");
|
|
@@ -957,8 +1110,8 @@ async function createViteConfig(options) {
|
|
|
957
1110
|
resolveId(id) {
|
|
958
1111
|
if (id.startsWith("/_preview/")) {
|
|
959
1112
|
const relativePath = id.slice("/_preview/".length);
|
|
960
|
-
const previewsDir =
|
|
961
|
-
const resolved =
|
|
1113
|
+
const previewsDir = path9.join(rootDir, "previews");
|
|
1114
|
+
const resolved = path9.resolve(previewsDir, relativePath);
|
|
962
1115
|
if (resolved.startsWith(previewsDir)) {
|
|
963
1116
|
return resolved;
|
|
964
1117
|
}
|
|
@@ -968,7 +1121,7 @@ async function createViteConfig(options) {
|
|
|
968
1121
|
server.middlewares.use(async (req, res, next) => {
|
|
969
1122
|
const urlPath = req.url?.split("?")[0] || "";
|
|
970
1123
|
if (urlPath === "/_preview-runtime") {
|
|
971
|
-
const templatePath =
|
|
1124
|
+
const templatePath = path9.join(srcRoot2, "preview-runtime/template.html");
|
|
972
1125
|
if (existsSync5(templatePath)) {
|
|
973
1126
|
const html = readFileSync4(templatePath, "utf-8");
|
|
974
1127
|
res.setHeader("Content-Type", "text/html");
|
|
@@ -978,8 +1131,8 @@ async function createViteConfig(options) {
|
|
|
978
1131
|
}
|
|
979
1132
|
if (urlPath.startsWith("/_preview-config/")) {
|
|
980
1133
|
const previewName = decodeURIComponent(urlPath.slice("/_preview-config/".length));
|
|
981
|
-
const previewsDir =
|
|
982
|
-
const previewDir =
|
|
1134
|
+
const previewsDir = path9.join(rootDir, "previews");
|
|
1135
|
+
const previewDir = path9.resolve(previewsDir, previewName);
|
|
983
1136
|
if (!previewDir.startsWith(previewsDir)) {
|
|
984
1137
|
res.statusCode = 403;
|
|
985
1138
|
res.end("Forbidden");
|
|
@@ -1000,11 +1153,11 @@ async function createViteConfig(options) {
|
|
|
1000
1153
|
}
|
|
1001
1154
|
}
|
|
1002
1155
|
if (urlPath.startsWith("/_preview/")) {
|
|
1003
|
-
const isHtmlRequest = !
|
|
1156
|
+
const isHtmlRequest = !path9.extname(urlPath) || urlPath.endsWith("/");
|
|
1004
1157
|
if (isHtmlRequest) {
|
|
1005
1158
|
const previewName = decodeURIComponent(urlPath.slice("/_preview/".length).replace(/\/$/, ""));
|
|
1006
|
-
const previewsDir =
|
|
1007
|
-
const htmlPath =
|
|
1159
|
+
const previewsDir = path9.join(rootDir, "previews");
|
|
1160
|
+
const htmlPath = path9.resolve(previewsDir, previewName, "index.html");
|
|
1008
1161
|
if (!htmlPath.startsWith(previewsDir)) {
|
|
1009
1162
|
return next();
|
|
1010
1163
|
}
|
|
@@ -1031,15 +1184,15 @@ async function createViteConfig(options) {
|
|
|
1031
1184
|
],
|
|
1032
1185
|
resolve: {
|
|
1033
1186
|
alias: {
|
|
1034
|
-
"@prev/ui":
|
|
1035
|
-
"@prev/theme":
|
|
1036
|
-
react:
|
|
1037
|
-
"react-dom":
|
|
1038
|
-
"@tanstack/react-router":
|
|
1039
|
-
"@mdx-js/react":
|
|
1040
|
-
mermaid:
|
|
1041
|
-
dayjs:
|
|
1042
|
-
"@terrastruct/d2":
|
|
1187
|
+
"@prev/ui": path9.join(srcRoot2, "ui"),
|
|
1188
|
+
"@prev/theme": path9.join(srcRoot2, "theme"),
|
|
1189
|
+
react: path9.join(cliNodeModules, "react"),
|
|
1190
|
+
"react-dom": path9.join(cliNodeModules, "react-dom"),
|
|
1191
|
+
"@tanstack/react-router": path9.join(cliNodeModules, "@tanstack/react-router"),
|
|
1192
|
+
"@mdx-js/react": path9.join(cliNodeModules, "@mdx-js/react"),
|
|
1193
|
+
mermaid: path9.join(cliNodeModules, "mermaid"),
|
|
1194
|
+
dayjs: path9.join(cliNodeModules, "dayjs"),
|
|
1195
|
+
"@terrastruct/d2": path9.join(cliNodeModules, "@terrastruct/d2")
|
|
1043
1196
|
},
|
|
1044
1197
|
dedupe: [
|
|
1045
1198
|
"react",
|
|
@@ -1048,19 +1201,17 @@ async function createViteConfig(options) {
|
|
|
1048
1201
|
]
|
|
1049
1202
|
},
|
|
1050
1203
|
optimizeDeps: {
|
|
1051
|
-
entries: [],
|
|
1052
1204
|
noDiscovery: true,
|
|
1053
1205
|
include: [
|
|
1054
1206
|
"react",
|
|
1055
1207
|
"react-dom",
|
|
1056
1208
|
"react-dom/client",
|
|
1057
|
-
"@tanstack/react-router",
|
|
1058
1209
|
"react/jsx-runtime",
|
|
1059
1210
|
"react/jsx-dev-runtime",
|
|
1060
|
-
"@
|
|
1061
|
-
"
|
|
1062
|
-
"
|
|
1063
|
-
"@
|
|
1211
|
+
"@tanstack/react-router",
|
|
1212
|
+
"use-sync-external-store",
|
|
1213
|
+
"use-sync-external-store/shim/with-selector.js",
|
|
1214
|
+
"@mdx-js/react"
|
|
1064
1215
|
],
|
|
1065
1216
|
exclude: [
|
|
1066
1217
|
"virtual:prev-config",
|
|
@@ -1081,8 +1232,8 @@ async function createViteConfig(options) {
|
|
|
1081
1232
|
},
|
|
1082
1233
|
warmup: {
|
|
1083
1234
|
clientFiles: [
|
|
1084
|
-
|
|
1085
|
-
|
|
1235
|
+
path9.join(srcRoot2, "theme/entry.tsx"),
|
|
1236
|
+
path9.join(srcRoot2, "theme/styles.css")
|
|
1086
1237
|
]
|
|
1087
1238
|
}
|
|
1088
1239
|
},
|
|
@@ -1091,12 +1242,12 @@ async function createViteConfig(options) {
|
|
|
1091
1242
|
strictPort: false
|
|
1092
1243
|
},
|
|
1093
1244
|
build: {
|
|
1094
|
-
outDir:
|
|
1245
|
+
outDir: path9.join(rootDir, "dist"),
|
|
1095
1246
|
reportCompressedSize: false,
|
|
1096
1247
|
chunkSizeWarningLimit: 1e4,
|
|
1097
1248
|
rollupOptions: {
|
|
1098
1249
|
input: {
|
|
1099
|
-
main:
|
|
1250
|
+
main: path9.join(srcRoot2, "theme/index.html")
|
|
1100
1251
|
}
|
|
1101
1252
|
}
|
|
1102
1253
|
},
|
|
@@ -1141,7 +1292,7 @@ async function findAvailablePort(minPort, maxPort) {
|
|
|
1141
1292
|
// src/vite/start.ts
|
|
1142
1293
|
import { exec as exec2 } from "child_process";
|
|
1143
1294
|
import { existsSync as existsSync6, rmSync as rmSync2, copyFileSync } from "fs";
|
|
1144
|
-
import
|
|
1295
|
+
import path10 from "path";
|
|
1145
1296
|
function printWelcome(type) {
|
|
1146
1297
|
console.log();
|
|
1147
1298
|
console.log(" ✨ prev");
|
|
@@ -1174,8 +1325,8 @@ function openBrowser(url) {
|
|
|
1174
1325
|
console.log(` ↗ Opened ${url}`);
|
|
1175
1326
|
}
|
|
1176
1327
|
function clearCache(rootDir) {
|
|
1177
|
-
const viteCacheDir =
|
|
1178
|
-
const nodeModulesVite =
|
|
1328
|
+
const viteCacheDir = path10.join(rootDir, ".vite");
|
|
1329
|
+
const nodeModulesVite = path10.join(rootDir, "node_modules", ".vite");
|
|
1179
1330
|
let cleared = 0;
|
|
1180
1331
|
if (existsSync6(viteCacheDir)) {
|
|
1181
1332
|
rmSync2(viteCacheDir, { recursive: true });
|
|
@@ -1229,10 +1380,17 @@ async function startDev(rootDir, options = {}) {
|
|
|
1229
1380
|
rootDir,
|
|
1230
1381
|
mode: "development",
|
|
1231
1382
|
port,
|
|
1232
|
-
include: options.include
|
|
1383
|
+
include: options.include,
|
|
1384
|
+
debug: options.debug
|
|
1233
1385
|
});
|
|
1234
1386
|
const server = await createServer2(config);
|
|
1235
1387
|
await server.listen();
|
|
1388
|
+
const debugCollector = getDebugCollector();
|
|
1389
|
+
if (debugCollector) {
|
|
1390
|
+
debugCollector.startPhase("serverReady");
|
|
1391
|
+
const reportPath = debugCollector.writeReport();
|
|
1392
|
+
console.log(` \uD83D\uDCCA Debug trace written to: ${reportPath}`);
|
|
1393
|
+
}
|
|
1236
1394
|
const actualPort = server.config.server.port || port;
|
|
1237
1395
|
const url = `http://localhost:${actualPort}/`;
|
|
1238
1396
|
printWelcome("dev");
|
|
@@ -1281,12 +1439,19 @@ async function buildSite(rootDir, options = {}) {
|
|
|
1281
1439
|
rootDir,
|
|
1282
1440
|
mode: "production",
|
|
1283
1441
|
include: options.include,
|
|
1284
|
-
base: options.base
|
|
1442
|
+
base: options.base,
|
|
1443
|
+
debug: options.debug
|
|
1285
1444
|
});
|
|
1286
1445
|
await build2(config);
|
|
1287
|
-
const
|
|
1288
|
-
|
|
1289
|
-
|
|
1446
|
+
const debugCollector = getDebugCollector();
|
|
1447
|
+
if (debugCollector) {
|
|
1448
|
+
debugCollector.startPhase("buildComplete");
|
|
1449
|
+
const reportPath = debugCollector.writeReport();
|
|
1450
|
+
console.log(` \uD83D\uDCCA Debug trace written to: ${reportPath}`);
|
|
1451
|
+
}
|
|
1452
|
+
const distDir = path10.join(rootDir, "dist");
|
|
1453
|
+
const indexPath = path10.join(distDir, "index.html");
|
|
1454
|
+
const notFoundPath = path10.join(distDir, "404.html");
|
|
1290
1455
|
if (existsSync6(indexPath)) {
|
|
1291
1456
|
copyFileSync(indexPath, notFoundPath);
|
|
1292
1457
|
}
|
|
@@ -1301,9 +1466,16 @@ async function previewSite(rootDir, options = {}) {
|
|
|
1301
1466
|
rootDir,
|
|
1302
1467
|
mode: "production",
|
|
1303
1468
|
port,
|
|
1304
|
-
include: options.include
|
|
1469
|
+
include: options.include,
|
|
1470
|
+
debug: options.debug
|
|
1305
1471
|
});
|
|
1306
1472
|
const server = await preview(config);
|
|
1473
|
+
const debugCollector = getDebugCollector();
|
|
1474
|
+
if (debugCollector) {
|
|
1475
|
+
debugCollector.startPhase("previewReady");
|
|
1476
|
+
const reportPath = debugCollector.writeReport();
|
|
1477
|
+
console.log(` \uD83D\uDCCA Debug trace written to: ${reportPath}`);
|
|
1478
|
+
}
|
|
1307
1479
|
printWelcome("preview");
|
|
1308
1480
|
server.printUrls();
|
|
1309
1481
|
console.log();
|
|
@@ -1316,15 +1488,15 @@ async function previewSite(rootDir, options = {}) {
|
|
|
1316
1488
|
import yaml2 from "js-yaml";
|
|
1317
1489
|
function getVersion() {
|
|
1318
1490
|
try {
|
|
1319
|
-
let dir =
|
|
1491
|
+
let dir = path11.dirname(fileURLToPath3(import.meta.url));
|
|
1320
1492
|
for (let i = 0;i < 5; i++) {
|
|
1321
|
-
const pkgPath =
|
|
1493
|
+
const pkgPath = path11.join(dir, "package.json");
|
|
1322
1494
|
if (existsSync7(pkgPath)) {
|
|
1323
1495
|
const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
|
|
1324
1496
|
if (pkg.name === "prev-cli")
|
|
1325
1497
|
return pkg.version;
|
|
1326
1498
|
}
|
|
1327
|
-
dir =
|
|
1499
|
+
dir = path11.dirname(dir);
|
|
1328
1500
|
}
|
|
1329
1501
|
} catch {}
|
|
1330
1502
|
return "unknown";
|
|
@@ -1336,13 +1508,14 @@ var { values, positionals } = parseArgs({
|
|
|
1336
1508
|
days: { type: "string", short: "d" },
|
|
1337
1509
|
cwd: { type: "string", short: "c" },
|
|
1338
1510
|
base: { type: "string", short: "b" },
|
|
1511
|
+
debug: { type: "boolean" },
|
|
1339
1512
|
help: { type: "boolean", short: "h" },
|
|
1340
1513
|
version: { type: "boolean", short: "v" }
|
|
1341
1514
|
},
|
|
1342
1515
|
allowPositionals: true
|
|
1343
1516
|
});
|
|
1344
1517
|
var command = positionals[0] || "dev";
|
|
1345
|
-
var rootDir =
|
|
1518
|
+
var rootDir = path11.resolve(values.cwd || (command === "config" || command === "create" ? "." : positionals[1]) || ".");
|
|
1346
1519
|
function printHelp() {
|
|
1347
1520
|
console.log(`
|
|
1348
1521
|
prev - Zero-config documentation site generator
|
|
@@ -1367,6 +1540,7 @@ Options:
|
|
|
1367
1540
|
-p, --port <port> Specify port (dev/preview)
|
|
1368
1541
|
-b, --base <path> Base path for deployment (e.g., /repo-name/ for GitHub Pages)
|
|
1369
1542
|
-d, --days <days> Cache age threshold for clean (default: 30)
|
|
1543
|
+
--debug Write debug trace to .prev-debug/ for performance analysis
|
|
1370
1544
|
-h, --help Show this help message
|
|
1371
1545
|
-v, --version Show version number
|
|
1372
1546
|
|
|
@@ -1451,8 +1625,8 @@ async function clearViteCache(rootDir2) {
|
|
|
1451
1625
|
console.log(` ✓ Removed ${prevCacheDir}`);
|
|
1452
1626
|
}
|
|
1453
1627
|
} catch {}
|
|
1454
|
-
const viteCacheDir =
|
|
1455
|
-
const nodeModulesVite =
|
|
1628
|
+
const viteCacheDir = path11.join(rootDir2, ".vite");
|
|
1629
|
+
const nodeModulesVite = path11.join(rootDir2, "node_modules", ".vite");
|
|
1456
1630
|
if (existsSync7(viteCacheDir)) {
|
|
1457
1631
|
rmSync3(viteCacheDir, { recursive: true });
|
|
1458
1632
|
cleared++;
|
|
@@ -1504,7 +1678,7 @@ function handleConfig(rootDir2, subcommand) {
|
|
|
1504
1678
|
break;
|
|
1505
1679
|
}
|
|
1506
1680
|
case "init": {
|
|
1507
|
-
const targetPath =
|
|
1681
|
+
const targetPath = path11.join(rootDir2, ".prev.yaml");
|
|
1508
1682
|
if (configPath) {
|
|
1509
1683
|
console.log(`
|
|
1510
1684
|
Config already exists: ${configPath}
|
|
@@ -1540,7 +1714,7 @@ order: {}
|
|
|
1540
1714
|
# - "getting-started.md"
|
|
1541
1715
|
# - "guides/"
|
|
1542
1716
|
`;
|
|
1543
|
-
|
|
1717
|
+
writeFileSync5(targetPath, configContent, "utf-8");
|
|
1544
1718
|
console.log(`
|
|
1545
1719
|
✨ Created ${targetPath}
|
|
1546
1720
|
`);
|
|
@@ -1563,12 +1737,12 @@ Available subcommands: show, init, path`);
|
|
|
1563
1737
|
}
|
|
1564
1738
|
}
|
|
1565
1739
|
function createPreview(rootDir2, name) {
|
|
1566
|
-
const previewDir =
|
|
1740
|
+
const previewDir = path11.join(rootDir2, "previews", name);
|
|
1567
1741
|
if (existsSync7(previewDir)) {
|
|
1568
1742
|
console.error(`Preview "${name}" already exists at: ${previewDir}`);
|
|
1569
1743
|
process.exit(1);
|
|
1570
1744
|
}
|
|
1571
|
-
|
|
1745
|
+
mkdirSync3(previewDir, { recursive: true });
|
|
1572
1746
|
const appTsx = `import { useState } from 'react'
|
|
1573
1747
|
import './styles.css'
|
|
1574
1748
|
|
|
@@ -1689,8 +1863,8 @@ export default function App() {
|
|
|
1689
1863
|
.dark\\:text-white { color: #fff; }
|
|
1690
1864
|
}
|
|
1691
1865
|
`;
|
|
1692
|
-
|
|
1693
|
-
|
|
1866
|
+
writeFileSync5(path11.join(previewDir, "App.tsx"), appTsx);
|
|
1867
|
+
writeFileSync5(path11.join(previewDir, "styles.css"), stylesCss);
|
|
1694
1868
|
console.log(`
|
|
1695
1869
|
✨ Created preview: previews/${name}/
|
|
1696
1870
|
|
|
@@ -1722,13 +1896,13 @@ async function main() {
|
|
|
1722
1896
|
try {
|
|
1723
1897
|
switch (command) {
|
|
1724
1898
|
case "dev":
|
|
1725
|
-
await startDev(rootDir, { port, include });
|
|
1899
|
+
await startDev(rootDir, { port, include, debug: values.debug });
|
|
1726
1900
|
break;
|
|
1727
1901
|
case "build":
|
|
1728
|
-
await buildSite(rootDir, { include, base: values.base });
|
|
1902
|
+
await buildSite(rootDir, { include, base: values.base, debug: values.debug });
|
|
1729
1903
|
break;
|
|
1730
1904
|
case "preview":
|
|
1731
|
-
await previewSite(rootDir, { port, include });
|
|
1905
|
+
await previewSite(rootDir, { port, include, debug: values.debug });
|
|
1732
1906
|
break;
|
|
1733
1907
|
case "clean":
|
|
1734
1908
|
const removed = await cleanCache({ maxAgeDays: days });
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface FileEvent {
|
|
2
|
+
path: string;
|
|
3
|
+
event: 'resolve' | 'load' | 'transform';
|
|
4
|
+
ms: number;
|
|
5
|
+
phase: string;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
}
|
|
8
|
+
export interface PhaseInfo {
|
|
9
|
+
startMs: number;
|
|
10
|
+
endMs?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface DebugSummary {
|
|
13
|
+
totalFiles: number;
|
|
14
|
+
byDirectory: Record<string, number>;
|
|
15
|
+
byEvent: Record<string, number>;
|
|
16
|
+
slowest: Array<{
|
|
17
|
+
path: string;
|
|
18
|
+
totalMs: number;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
export interface DebugReport {
|
|
22
|
+
timestamp: string;
|
|
23
|
+
totalStartupMs: number;
|
|
24
|
+
phases: Record<string, PhaseInfo>;
|
|
25
|
+
files: FileEvent[];
|
|
26
|
+
summary: DebugSummary;
|
|
27
|
+
}
|
|
28
|
+
export declare class DebugCollector {
|
|
29
|
+
private startTime;
|
|
30
|
+
private files;
|
|
31
|
+
private phases;
|
|
32
|
+
private currentPhase;
|
|
33
|
+
private rootDir;
|
|
34
|
+
constructor(rootDir: string);
|
|
35
|
+
startPhase(name: string): void;
|
|
36
|
+
endPhase(name?: string): void;
|
|
37
|
+
trackFile(filePath: string, event: 'resolve' | 'load' | 'transform', startTime: number): void;
|
|
38
|
+
private generateSummary;
|
|
39
|
+
writeReport(): string;
|
|
40
|
+
}
|
|
41
|
+
export declare function createDebugCollector(rootDir: string): DebugCollector;
|
|
42
|
+
export declare function getDebugCollector(): DebugCollector | null;
|
package/dist/vite/config.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { InlineConfig } from 'vite';
|
|
2
|
+
import { getDebugCollector } from '../utils/debug';
|
|
3
|
+
export { getDebugCollector };
|
|
2
4
|
export interface ConfigOptions {
|
|
3
5
|
rootDir: string;
|
|
4
6
|
mode: 'development' | 'production';
|
|
5
7
|
port?: number;
|
|
6
8
|
include?: string[];
|
|
7
9
|
base?: string;
|
|
10
|
+
debug?: boolean;
|
|
8
11
|
}
|
|
9
12
|
export declare function createViteConfig(options: ConfigOptions): Promise<InlineConfig>;
|
package/dist/vite/start.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export interface DevOptions {
|
|
2
2
|
port?: number;
|
|
3
3
|
include?: string[];
|
|
4
|
+
debug?: boolean;
|
|
4
5
|
}
|
|
5
6
|
export interface BuildOptions {
|
|
6
7
|
include?: string[];
|
|
7
8
|
base?: string;
|
|
9
|
+
debug?: boolean;
|
|
8
10
|
}
|
|
9
11
|
export declare function startDev(rootDir: string, options?: DevOptions): Promise<import("vite").ViteDevServer>;
|
|
10
12
|
export declare function buildSite(rootDir: string, options?: BuildOptions): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prev-cli",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.6",
|
|
4
4
|
"description": "Transform MDX directories into beautiful documentation websites",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "bun build src/cli.ts --outdir dist --target node --packages external && tsc --emitDeclarationOnly",
|
|
38
38
|
"build:docs": "bun run build && bun ./dist/cli.js build",
|
|
39
|
+
"prepublishOnly": "bun run build",
|
|
39
40
|
"dev": "tsc --watch",
|
|
40
41
|
"test": "bun test src",
|
|
41
42
|
"test:integration": "bun run build && bun test test/integration.test.ts",
|