diff --git a/README.md b/README.md index 54e9e50..eda1117 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,31 @@ The deployment process: ## šŸ”§ Development +### Rolldown Version Testing + +The repository includes a tool for testing different rolldown-vite versions: + +```bash +# List available versions +pnpm rolldown:list + +# Switch to a specific version (by index) +pnpm rolldown:use 2 + +# Switch to a specific version (by version string) +pnpm rolldown:use 7.1.2 + +# Use experimental versions from pkg.pr.new +pnpm rolldown:use pkg.pr.new/rolldown-rs/vite@1234 +``` + +The tool automatically: +- Updates the package.json with the new version +- Installs dependencies +- Rebuilds the application + +See [`tool/README.md`](tool/README.md) for detailed usage instructions. + ### Adding New Metrics 1. Add your data to the respective data arrays in `apps/dashboard/src/App.tsx` diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index 8a587f4..75284d5 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -19,6 +19,6 @@ "@types/react": "^19.1.10", "@types/react-dom": "^19.1.7", "typescript": "~5.8.3", - "rolldown-vite": "^7.1.3" + "rolldown-vite": "7.1.4" } } diff --git a/package.json b/package.json index b52a53f..128ae83 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,10 @@ "lint": "oxlint .", "test": "pnpm -r test", "clean": "pnpm -r clean", - "build-deploy": "pnpm lint && pnpm build" + "build-deploy": "pnpm lint && pnpm build", + "rolldown:list": "node tool/override-rolldown.js --list", + "rolldown:use": "node tool/override-rolldown.js", + "rolldown:stats": "node tool/override-rolldown.js --stats" }, "keywords": ["dashboard", "charts", "metrics", "frontend"], "author": "", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9539a7f..9e065dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,8 +40,8 @@ importers: specifier: ^19.1.7 version: 19.1.7(@types/react@19.1.11) rolldown-vite: - specifier: ^7.1.3 - version: 7.1.4(@types/node@20.19.11)(esbuild@0.25.9) + specifier: 7.1.4 + version: 7.1.4(@types/node@20.19.11) typescript: specifier: ~5.8.3 version: 5.8.3 @@ -61,162 +61,6 @@ packages: '@emnapi/wasi-threads@1.0.4': resolution: {integrity: sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==} - '@esbuild/aix-ppc64@0.25.9': - resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.25.9': - resolution: {integrity: sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.25.9': - resolution: {integrity: sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.25.9': - resolution: {integrity: sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.25.9': - resolution: {integrity: sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.25.9': - resolution: {integrity: sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.25.9': - resolution: {integrity: sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.25.9': - resolution: {integrity: sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.25.9': - resolution: {integrity: sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.25.9': - resolution: {integrity: sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.25.9': - resolution: {integrity: sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.25.9': - resolution: {integrity: sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.25.9': - resolution: {integrity: sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.25.9': - resolution: {integrity: sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.25.9': - resolution: {integrity: sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.25.9': - resolution: {integrity: sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.25.9': - resolution: {integrity: sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.25.9': - resolution: {integrity: sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.25.9': - resolution: {integrity: sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.25.9': - resolution: {integrity: sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.25.9': - resolution: {integrity: sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.25.9': - resolution: {integrity: sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.25.9': - resolution: {integrity: sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.25.9': - resolution: {integrity: sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.25.9': - resolution: {integrity: sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.25.9': - resolution: {integrity: sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@napi-rs/wasm-runtime@1.0.3': resolution: {integrity: sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q==} @@ -476,11 +320,6 @@ packages: dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} - esbuild@0.25.9: - resolution: {integrity: sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==} - engines: {node: '>=18'} - hasBin: true - eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} @@ -746,84 +585,6 @@ snapshots: tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.25.9': - optional: true - - '@esbuild/android-arm64@0.25.9': - optional: true - - '@esbuild/android-arm@0.25.9': - optional: true - - '@esbuild/android-x64@0.25.9': - optional: true - - '@esbuild/darwin-arm64@0.25.9': - optional: true - - '@esbuild/darwin-x64@0.25.9': - optional: true - - '@esbuild/freebsd-arm64@0.25.9': - optional: true - - '@esbuild/freebsd-x64@0.25.9': - optional: true - - '@esbuild/linux-arm64@0.25.9': - optional: true - - '@esbuild/linux-arm@0.25.9': - optional: true - - '@esbuild/linux-ia32@0.25.9': - optional: true - - '@esbuild/linux-loong64@0.25.9': - optional: true - - '@esbuild/linux-mips64el@0.25.9': - optional: true - - '@esbuild/linux-ppc64@0.25.9': - optional: true - - '@esbuild/linux-riscv64@0.25.9': - optional: true - - '@esbuild/linux-s390x@0.25.9': - optional: true - - '@esbuild/linux-x64@0.25.9': - optional: true - - '@esbuild/netbsd-arm64@0.25.9': - optional: true - - '@esbuild/netbsd-x64@0.25.9': - optional: true - - '@esbuild/openbsd-arm64@0.25.9': - optional: true - - '@esbuild/openbsd-x64@0.25.9': - optional: true - - '@esbuild/openharmony-arm64@0.25.9': - optional: true - - '@esbuild/sunos-x64@0.25.9': - optional: true - - '@esbuild/win32-arm64@0.25.9': - optional: true - - '@esbuild/win32-ia32@0.25.9': - optional: true - - '@esbuild/win32-x64@0.25.9': - optional: true - '@napi-rs/wasm-runtime@1.0.3': dependencies: '@emnapi/core': 1.4.5 @@ -1017,36 +778,6 @@ snapshots: '@babel/runtime': 7.28.3 csstype: 3.1.3 - esbuild@0.25.9: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.9 - '@esbuild/android-arm': 0.25.9 - '@esbuild/android-arm64': 0.25.9 - '@esbuild/android-x64': 0.25.9 - '@esbuild/darwin-arm64': 0.25.9 - '@esbuild/darwin-x64': 0.25.9 - '@esbuild/freebsd-arm64': 0.25.9 - '@esbuild/freebsd-x64': 0.25.9 - '@esbuild/linux-arm': 0.25.9 - '@esbuild/linux-arm64': 0.25.9 - '@esbuild/linux-ia32': 0.25.9 - '@esbuild/linux-loong64': 0.25.9 - '@esbuild/linux-mips64el': 0.25.9 - '@esbuild/linux-ppc64': 0.25.9 - '@esbuild/linux-riscv64': 0.25.9 - '@esbuild/linux-s390x': 0.25.9 - '@esbuild/linux-x64': 0.25.9 - '@esbuild/netbsd-arm64': 0.25.9 - '@esbuild/netbsd-x64': 0.25.9 - '@esbuild/openbsd-arm64': 0.25.9 - '@esbuild/openbsd-x64': 0.25.9 - '@esbuild/openharmony-arm64': 0.25.9 - '@esbuild/sunos-x64': 0.25.9 - '@esbuild/win32-arm64': 0.25.9 - '@esbuild/win32-ia32': 0.25.9 - '@esbuild/win32-x64': 0.25.9 - optional: true - eventemitter3@4.0.7: {} fast-equals@5.2.2: {} @@ -1204,7 +935,7 @@ snapshots: tiny-invariant: 1.3.3 victory-vendor: 36.9.2 - rolldown-vite@7.1.4(@types/node@20.19.11)(esbuild@0.25.9): + rolldown-vite@7.1.4(@types/node@20.19.11): dependencies: fdir: 6.5.0(picomatch@4.0.3) lightningcss: 1.30.1 @@ -1214,7 +945,6 @@ snapshots: tinyglobby: 0.2.14 optionalDependencies: '@types/node': 20.19.11 - esbuild: 0.25.9 fsevents: 2.3.3 rolldown@1.0.0-beta.33: diff --git a/rolldown-version-stats.json b/rolldown-version-stats.json new file mode 100644 index 0000000..f720a2f --- /dev/null +++ b/rolldown-version-stats.json @@ -0,0 +1,147 @@ +[ + { + "version": "7.1.0", + "timestamp": "2025-08-25T04:10:30.355Z", + "files": [ + { + "path": "assets/index-DD-rq4eS.css", + "size": 2812, + "type": "css" + }, + { + "path": "assets/index-xJMNECRy.js", + "size": 564642, + "type": "js" + }, + { + "path": "index.html", + "size": 506, + "type": "html" + }, + { + "path": "vite.svg", + "size": 1497, + "type": "other" + } + ], + "totalSize": 569457, + "totalGzipSize": 0, + "buildTime": 1741 + }, + { + "version": "7.1.1", + "timestamp": "2025-08-25T04:10:33.181Z", + "files": [ + { + "path": "assets/index-DD-rq4eS.css", + "size": 2812, + "type": "css" + }, + { + "path": "assets/index-xMD4_U6M.js", + "size": 564629, + "type": "js" + }, + { + "path": "index.html", + "size": 506, + "type": "html" + }, + { + "path": "vite.svg", + "size": 1497, + "type": "other" + } + ], + "totalSize": 569444, + "totalGzipSize": 0, + "buildTime": 1511 + }, + { + "version": "7.1.2", + "timestamp": "2025-08-25T04:10:36.031Z", + "files": [ + { + "path": "assets/index-DD-rq4eS.css", + "size": 2812, + "type": "css" + }, + { + "path": "assets/index-xMD4_U6M.js", + "size": 564629, + "type": "js" + }, + { + "path": "index.html", + "size": 506, + "type": "html" + }, + { + "path": "vite.svg", + "size": 1497, + "type": "other" + } + ], + "totalSize": 569444, + "totalGzipSize": 0, + "buildTime": 1464 + }, + { + "version": "7.1.3", + "timestamp": "2025-08-25T04:11:10.423Z", + "files": [ + { + "path": "assets/index-C_guGHi2.js", + "size": 563794, + "type": "js" + }, + { + "path": "assets/index-DD-rq4eS.css", + "size": 2812, + "type": "css" + }, + { + "path": "index.html", + "size": 506, + "type": "html" + }, + { + "path": "vite.svg", + "size": 1497, + "type": "other" + } + ], + "totalSize": 568609, + "totalGzipSize": 0, + "buildTime": 1634 + }, + { + "version": "7.1.4", + "timestamp": "2025-08-25T04:11:13.184Z", + "files": [ + { + "path": "assets/index-C_guGHi2.js", + "size": 563794, + "type": "js" + }, + { + "path": "assets/index-DD-rq4eS.css", + "size": 2812, + "type": "css" + }, + { + "path": "index.html", + "size": 506, + "type": "html" + }, + { + "path": "vite.svg", + "size": 1497, + "type": "other" + } + ], + "totalSize": 568609, + "totalGzipSize": 0, + "buildTime": 1467 + } +] \ No newline at end of file diff --git a/tool/README.md b/tool/README.md new file mode 100644 index 0000000..0afac2c --- /dev/null +++ b/tool/README.md @@ -0,0 +1,145 @@ +# Rolldown Version Override Tool + +This tool allows you to easily test the vibe-dashboard with different rolldown-vite versions. + +## Features + +- 🟢 **Stable Versions**: Test with the last 5 stable versions from npm +- šŸš€ **Future Versions**: Test with experimental versions from pkg.pr.new (when available) +- šŸ”„ **Automatic Rebuild**: Automatically installs dependencies and rebuilds the app +- šŸ“‹ **Easy Selection**: Use version numbers or indices for quick switching +- šŸ“Š **Comprehensive Analysis**: Collect build statistics across all versions + +## Usage + +### List Available Versions + +```bash +# From root directory +pnpm rolldown:list + +# Or directly with node +node tool/override-rolldown.js --list +``` + +### Switch to a Version by Index + +```bash +# Use the 2nd version in the list (7.1.3) +pnpm rolldown:use 2 + +# Or directly with node +node tool/override-rolldown.js 2 +``` + +### Switch to a Specific Version + +```bash +# Use a specific version +pnpm rolldown:use 7.1.2 + +# Or directly with node +node tool/override-rolldown.js 7.1.2 +``` + +### Collect Statistics for All Versions + +```bash +# Analyze all available versions and collect build statistics +pnpm rolldown:stats + +# Or directly with node +node tool/override-rolldown.js --stats +``` + +This command will: +- Test all available rolldown versions (stable + experimental) +- Build the application with each version +- Collect file statistics from the dist directory +- Save comprehensive data to `rolldown-version-stats.json` + +### Get Help + +```bash +node tool/override-rolldown.js --help +``` + +## Available Versions + +The tool currently supports: + +### Stable Versions (from npm) +- 7.1.4 (latest) +- 7.1.3 +- 7.1.2 +- 7.1.1 +- 7.1.0 + +### Future Versions (from pkg.pr.new) +Future versions will be added as they become available through pkg.pr.new for testing experimental features. + +## What It Does + +1. **Updates package.json**: Modifies `apps/dashboard/package.json` to use the specified rolldown-vite version +2. **Installs dependencies**: Runs `pnpm install` to update the lockfile +3. **Rebuilds the app**: Runs `pnpm build` to ensure everything works with the new version +4. **Collects stats** (with --stats): Analyzes build output, file sizes, and build times + +## Stats Collection Output + +The `--stats` command generates a JSON file with the following structure: + +```json +[ + { + "version": "7.1.4", + "timestamp": "2025-08-24T15:23:00.139Z", + "files": [ + { + "path": "assets/index-C_guGHi2.js", + "size": 563794, + "type": "js" + }, + { + "path": "assets/index-DD-rq4eS.css", + "size": 2812, + "type": "css" + } + ], + "totalSize": 568609, + "totalGzipSize": 0, + "buildTime": 3342 + } +] +``` + +## Example Workflow + +```bash +# Check current setup +pnpm build + +# List available versions +pnpm rolldown:list + +# Test with an older version +pnpm rolldown:use 7.1.1 + +# Verify the build still works +pnpm dev + +# Switch back to latest +pnpm rolldown:use 7.1.4 + +# Collect comprehensive statistics for all versions +pnpm rolldown:stats +``` + +## Notes + +- The tool modifies `apps/dashboard/package.json` directly +- Always commit your changes before using this tool if you want to preserve the current version +- The tool automatically runs `pnpm install` and `pnpm build` after version changes +- Build failures will be reported if the new version has compatibility issues +- Stats collection automatically restores the original package.json after analysis +- The `rolldown-version-stats.json` file is gitignored to prevent accidental commits \ No newline at end of file diff --git a/tool/override-rolldown.js b/tool/override-rolldown.js new file mode 100755 index 0000000..19c2224 --- /dev/null +++ b/tool/override-rolldown.js @@ -0,0 +1,494 @@ +#!/usr/bin/env node + +/** + * Rolldown Version Override Tool + * + * This tool allows testing the vibe-dashboard with different rolldown-vite versions: + * - Last 5 stable versions from npm + * - Future/experimental versions from pkg.pr.new + */ + +const { execSync } = require('child_process'); +const { readFileSync, writeFileSync, readdirSync, statSync, existsSync } = require('fs'); +const { join } = require('path'); +const https = require('https'); + +const DASHBOARD_PACKAGE_PATH = join(process.cwd(), 'apps/dashboard/package.json'); +const DIST_PATH = join(process.cwd(), 'apps/dashboard/dist'); +const STATS_OUTPUT_PATH = join(process.cwd(), 'rolldown-version-stats.json'); + +/** + * Fetch the last 5 stable versions from npm registry + */ +async function fetchStableVersions() { + return new Promise((resolve, reject) => { + const url = 'https://registry.npmjs.org/rolldown-vite'; + + https.get(url, (res) => { + let data = ''; + res.on('data', (chunk) => data += chunk); + res.on('end', () => { + try { + const packageInfo = JSON.parse(data); + let versions = Object.keys(packageInfo.versions) + .filter(v => !v.includes('-')) // Filter out pre-release versions + .sort((a, b) => { + // Sort by publication date (most recent last) + const dateA = new Date(packageInfo.time[a]); + const dateB = new Date(packageInfo.time[b]); + return dateA - dateB; + }); + versions = versions.slice(versions.length - 5, versions.length); + + resolve(versions); + } catch (error) { + reject(new Error(`Failed to parse npm registry response: ${error.message}`)); + } + }); + }).on('error', (error) => { + reject(new Error(`Failed to fetch from npm registry: ${error.message}`)); + }); + }); +} + +/** + * Fetch future versions from pkg.pr.new API using authoredDate filtering + * Currently commented out due to issues with future versions + */ +/* +async function fetchFutureVersions(lastNpmVersionDate) { + return new Promise((resolve, reject) => { + const url = 'https://pkg.pr.new/api/repo/commits?owner=rolldown&repo=rolldown'; + + https.get(url, (res) => { + let data = ''; + res.on('data', (chunk) => data += chunk); + res.on('end', () => { + try { + const response = JSON.parse(data); + + // Extract commits from the nested structure + const commits = response.target?.history?.nodes || []; + + const futureCommits = commits + .filter(commit => { + const commitDate = new Date(commit.authoredDate); + return commitDate > lastNpmVersionDate; + }) + .sort((a, b) => { + // Sort by authored date (most recent first) + const dateA = new Date(a.authoredDate); + const dateB = new Date(b.authoredDate); + return dateB - dateA; + }) + .map(commit => `pkg.pr.new/rolldown@${commit.abbreviatedOid}`); + + resolve(futureCommits); + } catch (error) { + reject(new Error(`Failed to parse pkg.pr.new API response: ${error.message}`)); + } + }); + }).on('error', (error) => { + reject(new Error(`Failed to fetch from pkg.pr.new API: ${error.message}`)); + }); + }); +} +*/ + +/** + * Get the publication date of the latest npm version + * Currently commented out as it's only used with future versions + */ +/* +async function getLatestNpmVersionDate() { + return new Promise((resolve, reject) => { + const url = 'https://registry.npmjs.org/rolldown-vite'; + + https.get(url, (res) => { + let data = ''; + res.on('data', (chunk) => data += chunk); + res.on('end', () => { + try { + const packageInfo = JSON.parse(data); + const latestVersion = packageInfo['dist-tags'].latest; + const publishDate = new Date(packageInfo.time[latestVersion]); + + resolve(publishDate); + } catch (error) { + reject(new Error(`Failed to get latest npm version date: ${error.message}`)); + } + }); + }).on('error', (error) => { + reject(new Error(`Failed to fetch npm version date: ${error.message}`)); + }); + }); +} +*/ + +function getCurrentVersion() { + try { + const packageJson = JSON.parse(readFileSync(DASHBOARD_PACKAGE_PATH, 'utf8')); + return packageJson.devDependencies['rolldown-vite']; + } catch (error) { + console.error('Error reading package.json:', error.message); + process.exit(1); + } +} + +function isPkgPrNewUrl(version) { + return version.includes('pkg.pr.new') || version.startsWith('https://pkg.pr.new'); +} + +function updateRolldownVersion(version) { + try { + console.log(`šŸ“¦ Updating rolldown-vite to version: ${version}`); + + // Read current package.json + const packageJson = JSON.parse(readFileSync(DASHBOARD_PACKAGE_PATH, 'utf8')); + + // Update rolldown-vite version + packageJson.devDependencies['rolldown-vite'] = version; + + // Write back to package.json + writeFileSync(DASHBOARD_PACKAGE_PATH, JSON.stringify(packageJson, null, 2) + '\n'); + + if (isPkgPrNewUrl(version)) { + console.log('šŸš€ Using experimental version from pkg.pr.new'); + } + console.log('āœ… Package.json updated successfully'); + return true; + } catch (error) { + console.error('āŒ Error updating package.json:', error.message); + return false; + } +} + +function installDependencies() { + try { + console.log('šŸ“„ Installing dependencies...'); + execSync('pnpm install --no-frozen-lockfile', { + stdio: 'inherit', + cwd: process.cwd() + }); + console.log('āœ… Dependencies installed successfully'); + return true; + } catch (error) { + console.error('āŒ Error installing dependencies:', error.message); + return false; + } +} + +function buildApp() { + try { + console.log('šŸ”Ø Building application...'); + const startTime = Date.now(); + execSync('pnpm build', { + stdio: 'inherit', + cwd: process.cwd() + }); + const buildTime = Date.now() - startTime; + console.log(`āœ… Build completed successfully in ${buildTime}ms`); + return { success: true, buildTime }; + } catch (error) { + console.error('āŒ Build failed:', error.message); + return { success: false, buildTime: null }; + } +} + +/** + * Collect file statistics from the dist directory + */ +function collectDistStats(version, buildTime = null) { + const stats = { + version, + timestamp: new Date().toISOString(), + files: [], + totalSize: 0, + totalGzipSize: 0, + buildTime + }; + + if (!existsSync(DIST_PATH)) { + console.warn(`āš ļø Dist directory not found for version ${version}`); + return stats; + } + + try { + // Get all files recursively + function getFilesRecursively(dir, baseDir = '') { + const files = []; + const items = readdirSync(dir); + + for (const item of items) { + const fullPath = join(dir, item); + const relativePath = join(baseDir, item); + const stat = statSync(fullPath); + + if (stat.isDirectory()) { + files.push(...getFilesRecursively(fullPath, relativePath)); + } else { + files.push({ + path: relativePath, + size: stat.size, + type: item.endsWith('.js') ? 'js' : + item.endsWith('.css') ? 'css' : + item.endsWith('.html') ? 'html' : 'other' + }); + } + } + return files; + } + + stats.files = getFilesRecursively(DIST_PATH); + stats.totalSize = stats.files.reduce((total, file) => total + file.size, 0); + + console.log(`šŸ“Š Collected stats for ${stats.files.length} files (${(stats.totalSize / 1024).toFixed(2)} KB total)`); + + } catch (error) { + console.warn(`āš ļø Error collecting stats for version ${version}:`, error.message); + } + + return stats; +} + +async function listVersions() { + console.log('šŸ“‹ Fetching available rolldown-vite versions...\n'); + + try { + // Fetch stable versions from npm + console.log('šŸ” Fetching stable versions from npm...'); + const stableVersions = await fetchStableVersions(); + + // Get latest npm version date for filtering future versions + // console.log('šŸ“… Getting latest npm version date...'); + // const latestNpmDate = await getLatestNpmVersionDate(); + + // Fetch future versions from pkg.pr.new + // console.log('šŸš€ Fetching future versions from pkg.pr.new...'); + // const futureVersions = await fetchFutureVersions(latestNpmDate); + const futureVersions = []; // Commented out future versions functionality + + console.log('\n🟢 Stable versions (last 5 from npm):'); + stableVersions.forEach((version, index) => { + const current = getCurrentVersion() === `^${version}` || getCurrentVersion() === version; + console.log(` ${index + 1}. ${version} ${current ? '(current)' : ''}`); + }); + + // Commenting out future versions display + // if (futureVersions.length > 0) { + // console.log('\nšŸš€ Future versions (from pkg.pr.new):'); + // futureVersions.forEach((version, index) => { + // console.log(` ${stableVersions.length + index + 1}. ${version}`); + // }); + // } else { + // console.log('\nšŸš€ Future versions (from pkg.pr.new):'); + // console.log(' No future versions found (all commits are older than latest npm version).'); + // } + + console.log('\nšŸ’” Usage: node override-rolldown.js '); + console.log('Example: node override-rolldown.js 2 # Use second stable version'); + console.log('Example: node override-rolldown.js 7.1.2 # Use specific version'); + console.log('Example: node override-rolldown.js pkg.pr.new/rolldown-rs/rolldown@1234567 # Use pkg.pr.new URL'); + + return { stableVersions, futureVersions }; + } catch (error) { + console.error('āŒ Error fetching versions:', error.message); + console.log('\nšŸ”„ Falling back to manual version entry...'); + console.log('šŸ’” Usage: node override-rolldown.js '); + console.log('Example: node override-rolldown.js 7.1.2'); + console.log('Example: node override-rolldown.js pkg.pr.new/rolldown-rs/rolldown@1234567'); + return { stableVersions: [], futureVersions: [] }; + } +} + +/** + * Collect statistics for all available rolldown versions + */ +async function collectAllVersionStats() { + console.log('šŸš€ Starting comprehensive rolldown version analysis...\n'); + + const allStats = []; + let successCount = 0; + let failureCount = 0; + + try { + // Fetch all available versions + console.log('šŸ” Fetching all available versions...'); + const stableVersions = await fetchStableVersions(); + // const latestNpmDate = await getLatestNpmVersionDate(); + // const futureVersions = await fetchFutureVersions(latestNpmDate); + const allVersions = [...stableVersions]; + + console.log(`šŸ“¦ Found ${allVersions.length} versions to analyze:`); + console.log(` - ${stableVersions.length} stable versions`); + // console.log(` - ${futureVersions.length} future versions\n`); + + // Store original package.json for restoration + const originalPackageJson = readFileSync(DASHBOARD_PACKAGE_PATH, 'utf8'); + + for (let i = 0; i < allVersions.length; i++) { + const version = allVersions[i]; + const versionNumber = i + 1; + + console.log(`\n==================== VERSION ${versionNumber}/${allVersions.length} ====================`); + console.log(`šŸŽÆ Testing version: ${version}`); + + try { + // Update version + if (!updateRolldownVersion(version)) { + console.error(`āŒ Failed to update package.json for version ${version}`); + failureCount++; + continue; + } + + // Install dependencies + if (!installDependencies()) { + console.error(`āŒ Failed to install dependencies for version ${version}`); + failureCount++; + continue; + } + + // Build app + const buildResult = buildApp(); + if (!buildResult.success) { + console.error(`āŒ Build failed for version ${version}`); + failureCount++; + continue; + } + + // Collect stats + const stats = collectDistStats(version, buildResult.buildTime); + allStats.push(stats); + successCount++; + + console.log(`āœ… Successfully analyzed version ${version}`); + + } catch (error) { + console.error(`āŒ Unexpected error analyzing version ${version}:`, error.message); + failureCount++; + } + } + + // Restore original package.json + console.log('\nšŸ”„ Restoring original package.json...'); + writeFileSync(DASHBOARD_PACKAGE_PATH, originalPackageJson); + + // Save results + console.log(`\nšŸ’¾ Saving results to ${STATS_OUTPUT_PATH}...`); + writeFileSync(STATS_OUTPUT_PATH, JSON.stringify(allStats, null, 2)); + + console.log('\n==================== ANALYSIS COMPLETE ===================='); + console.log(`šŸ“Š Analysis Summary:`); + console.log(` - Total versions analyzed: ${allVersions.length}`); + console.log(` - Successful builds: ${successCount}`); + console.log(` - Failed builds: ${failureCount}`); + console.log(` - Results saved to: ${STATS_OUTPUT_PATH}`); + + if (allStats.length > 0) { + const avgBuildTime = allStats + .filter(s => s.buildTime) + .reduce((sum, s) => sum + s.buildTime, 0) / allStats.filter(s => s.buildTime).length; + const avgTotalSize = allStats.reduce((sum, s) => sum + s.totalSize, 0) / allStats.length; + + console.log(`\nšŸ“ˆ Quick Stats:`); + console.log(` - Average build time: ${Math.round(avgBuildTime)}ms`); + console.log(` - Average bundle size: ${(avgTotalSize / 1024).toFixed(2)} KB`); + } + + } catch (error) { + console.error('āŒ Fatal error during analysis:', error.message); + process.exit(1); + } +} + +async function main() { + const args = process.argv.slice(2); + + if (args.length === 0 || args[0] === '--list' || args[0] === '-l') { + await listVersions(); + return; + } + + if (args[0] === '--collect-stats' || args[0] === '--stats') { + await collectAllVersionStats(); + return; + } + + const input = args[0]; + let targetVersion; + + // Check if input is a number (index) + if (/^\d+$/.test(input)) { + console.log('šŸ” Fetching version lists for index lookup...'); + + try { + const stableVersions = await fetchStableVersions(); + // const latestNpmDate = await getLatestNpmVersionDate(); + // const futureVersions = await fetchFutureVersions(latestNpmDate); + const futureVersions = []; // Commented out future versions functionality + + const index = parseInt(input, 10) - 1; + const allVersions = [...stableVersions, ...futureVersions]; + + if (index >= 0 && index < allVersions.length) { + targetVersion = allVersions[index]; + } else { + console.error(`āŒ Invalid version index. Use 1-${allVersions.length}`); + await listVersions(); + process.exit(1); + } + } catch (error) { + console.error(`āŒ Error fetching versions for index lookup: ${error.message}`); + console.log('šŸ’” Please use a specific version string instead of an index.'); + process.exit(1); + } + } else { + // Assume it's a version string + targetVersion = input; + } + + console.log(`šŸŽÆ Target version: ${targetVersion}`); + console.log(`šŸ“ Current version: ${getCurrentVersion()}\n`); + + // Update version + if (!updateRolldownVersion(targetVersion)) { + process.exit(1); + } + + // Install dependencies + if (!installDependencies()) { + process.exit(1); + } + + // Build app + const buildResult = buildApp(); + if (!buildResult.success) { + process.exit(1); + } + + console.log('\nšŸŽ‰ Successfully updated rolldown-vite and rebuilt the application!'); + console.log(`šŸ“Š Dashboard is ready with rolldown-vite ${targetVersion}`); +} + +// Handle command line arguments +if (process.argv.includes('--help') || process.argv.includes('-h')) { + console.log('Rolldown Version Override Tool\n'); + console.log('Usage:'); + console.log(' node override-rolldown.js --list List available versions'); + console.log(' node override-rolldown.js --stats Collect stats for all versions'); + console.log(' node override-rolldown.js Use version by index (1-5)'); + console.log(' node override-rolldown.js Use specific version'); + console.log(' node override-rolldown.js Use pkg.pr.new URL'); + console.log('\nExamples:'); + console.log(' node override-rolldown.js --list'); + console.log(' node override-rolldown.js --stats'); + console.log(' node override-rolldown.js 2'); + console.log(' node override-rolldown.js 7.1.2'); + console.log(' node override-rolldown.js pkg.pr.new/rolldown-rs/vite@1234'); + process.exit(0); +} + +main().catch(error => { + console.error('āŒ Unexpected error:', error.message); + process.exit(1); +});