chore: remove rollup, always use webpack

These two issues have affected us, but go away without rollup:
- https://github.com/npm/cli/issues/4828
- https://github.com/rollup/rollup/issues/6168

We can just use webpack instead; it has never caused build/npm issues.
This migration was done using AI, by pasting error messages over and
over again until everything worked. Since we're not actively working on
terminal and phoenix (dependents of rollup) currently it doesn't make
sense to focus on doing this migration manually, and any errors not
observed in basic use can be remedied later.
This commit is contained in:
KernelDeimos
2025-11-07 17:01:08 -05:00
committed by Eric Dubé
parent 7e21aad986
commit 54310ad0ab
32 changed files with 560 additions and 775 deletions

509
package-lock.json generated
View File

@@ -28,7 +28,6 @@
"json-colorizer": "^3.0.1",
"open": "^10.1.0",
"parse-domain": "^8.2.2",
"rollup": "^4.52.4",
"simple-git": "^3.25.0",
"string-template": "^1.0.0",
"uuid": "^9.0.1"
@@ -5710,83 +5709,6 @@
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
"license": "BSD-3-Clause"
},
"node_modules/@rollup/plugin-node-resolve": {
"version": "15.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz",
"integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"@types/resolve": "1.20.2",
"deepmerge": "^4.2.2",
"is-module": "^1.0.0",
"resolve": "^1.22.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^2.78.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-replace": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.7.tgz",
"integrity": "sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"magic-string": "^0.30.3"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz",
"integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true,
"license": "MIT"
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.52.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz",
@@ -5794,6 +5716,7 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5807,6 +5730,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5820,6 +5744,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5833,6 +5758,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5846,6 +5772,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5859,6 +5786,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5872,6 +5800,7 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5885,6 +5814,7 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5898,6 +5828,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5911,6 +5842,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5924,6 +5856,7 @@
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5937,6 +5870,7 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5950,6 +5884,7 @@
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5963,6 +5898,7 @@
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5976,6 +5912,7 @@
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -5989,6 +5926,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6002,6 +5940,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6015,6 +5954,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6028,6 +5968,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6041,6 +5982,7 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6054,6 +5996,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6067,6 +6010,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6950,16 +6894,6 @@
"@types/send": "*"
}
},
"node_modules/@types/fs-extra": {
"version": "8.1.5",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz",
"integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/glob": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
@@ -7228,13 +7162,6 @@
"node": ">= 0.12"
}
},
"node_modules/@types/resolve": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/send": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.0.tgz",
@@ -9942,16 +9869,6 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"license": "MIT"
},
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/default-browser": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz",
@@ -11506,6 +11423,7 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -12688,13 +12606,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
"dev": true,
"license": "MIT"
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -12736,16 +12647,6 @@
"node": ">=0.10.0"
}
},
"node_modules/is-reference": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "*"
}
},
"node_modules/is-regexp": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-3.1.0.tgz",
@@ -16273,8 +16174,8 @@
"version": "4.52.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.4.tgz",
"integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@types/estree": "1.0.8"
},
@@ -16311,60 +16212,6 @@
"fsevents": "~2.3.2"
}
},
"node_modules/rollup-plugin-copy": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz",
"integrity": "sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/fs-extra": "^8.0.1",
"colorette": "^1.1.0",
"fs-extra": "^8.1.0",
"globby": "10.0.1",
"is-plain-object": "^3.0.0"
},
"engines": {
"node": ">=8.3"
}
},
"node_modules/rollup-plugin-copy/node_modules/colorette": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
"integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
"dev": true,
"license": "MIT"
},
"node_modules/rollup-plugin-copy/node_modules/globby": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz",
"integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/glob": "^7.1.1",
"array-union": "^2.1.0",
"dir-glob": "^3.0.1",
"fast-glob": "^3.0.3",
"glob": "^7.1.3",
"ignore": "^5.1.1",
"merge2": "^1.2.3",
"slash": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/rollup-plugin-copy/node_modules/is-plain-object": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz",
"integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/run-applescript": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz",
@@ -19588,106 +19435,8 @@
"version": "1.0.0",
"license": "AGPL-3.0-only",
"devDependencies": {
"@rollup/plugin-commonjs": "^24.1.0",
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-replace": "^5.0.2",
"rollup": "^3.21.4",
"rollup-plugin-copy": "^3.4.0"
}
},
"src/backend-core-0/node_modules/@rollup/plugin-commonjs": {
"version": "24.1.0",
"dev": true,
"license": "MIT",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"commondir": "^1.0.1",
"estree-walker": "^2.0.2",
"glob": "^8.0.3",
"is-reference": "1.2.1",
"magic-string": "^0.27.0"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^2.68.0||^3.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"src/backend-core-0/node_modules/brace-expansion": {
"version": "2.0.2",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"src/backend-core-0/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true,
"license": "MIT"
},
"src/backend-core-0/node_modules/glob": {
"version": "8.1.0",
"dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^5.0.1",
"once": "^1.3.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"src/backend-core-0/node_modules/magic-string": {
"version": "0.27.0",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.13"
},
"engines": {
"node": ">=12"
}
},
"src/backend-core-0/node_modules/minimatch": {
"version": "5.1.6",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
}
},
"src/backend-core-0/node_modules/rollup": {
"version": "3.29.5",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=14.18.0",
"npm": ">=8.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
"webpack": "^5.88.2",
"webpack-cli": "^5.1.1"
}
},
"src/backend/node_modules/@smithy/abort-controller": {
@@ -20305,41 +20054,15 @@
"sinon": "^17.0.1"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.1.0",
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-replace": "^5.0.2",
"copy-webpack-plugin": "^12.0.2",
"mocha": "^10.8.2",
"rollup": "^3.29.5",
"rollup-plugin-copy": "^3.4.0"
"webpack": "^5.88.2",
"webpack-cli": "^5.1.1"
},
"optionalDependencies": {
"node-pty": "^1.0.0"
}
},
"src/phoenix/node_modules/@rollup/plugin-commonjs": {
"version": "24.1.0",
"dev": true,
"license": "MIT",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"commondir": "^1.0.1",
"estree-walker": "^2.0.2",
"glob": "^8.0.3",
"is-reference": "1.2.1",
"magic-string": "^0.27.0"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^2.68.0||^3.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"src/phoenix/node_modules/@sinonjs/fake-timers": {
"version": "11.3.1",
"license": "BSD-3-Clause",
@@ -20347,77 +20070,6 @@
"@sinonjs/commons": "^3.0.1"
}
},
"src/phoenix/node_modules/brace-expansion": {
"version": "2.0.2",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"src/phoenix/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true,
"license": "MIT"
},
"src/phoenix/node_modules/glob": {
"version": "8.1.0",
"dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^5.0.1",
"once": "^1.3.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"src/phoenix/node_modules/magic-string": {
"version": "0.27.0",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.13"
},
"engines": {
"node": ">=12"
}
},
"src/phoenix/node_modules/minimatch": {
"version": "5.1.6",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
}
},
"src/phoenix/node_modules/rollup": {
"version": "3.29.5",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=14.18.0",
"npm": ">=8.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"src/phoenix/node_modules/sinon": {
"version": "17.0.1",
"license": "BSD-3-Clause",
@@ -20477,108 +20129,11 @@
"@xterm/xterm": "^5.5.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.1.0",
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-replace": "^5.0.2",
"copy-webpack-plugin": "^12.0.2",
"http-server": "^14.1.1",
"mocha": "^10.8.2",
"rollup": "^3.29.5",
"rollup-plugin-copy": "^3.4.0"
}
},
"src/terminal/node_modules/@rollup/plugin-commonjs": {
"version": "24.1.0",
"dev": true,
"license": "MIT",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"commondir": "^1.0.1",
"estree-walker": "^2.0.2",
"glob": "^8.0.3",
"is-reference": "1.2.1",
"magic-string": "^0.27.0"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^2.68.0||^3.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"src/terminal/node_modules/brace-expansion": {
"version": "2.0.2",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"src/terminal/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true,
"license": "MIT"
},
"src/terminal/node_modules/glob": {
"version": "8.1.0",
"dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^5.0.1",
"once": "^1.3.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"src/terminal/node_modules/magic-string": {
"version": "0.27.0",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.13"
},
"engines": {
"node": ">=12"
}
},
"src/terminal/node_modules/minimatch": {
"version": "5.1.6",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
}
},
"src/terminal/node_modules/rollup": {
"version": "3.29.5",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=14.18.0",
"npm": ">=8.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
"webpack": "^5.88.2",
"webpack-cli": "^5.1.1"
}
},
"src/useapi": {

View File

@@ -77,7 +77,6 @@
"json-colorizer": "^3.0.1",
"open": "^10.1.0",
"parse-domain": "^8.2.2",
"rollup": "^4.52.4",
"simple-git": "^3.25.0",
"string-template": "^1.0.0",
"uuid": "^9.0.1"
@@ -90,4 +89,4 @@
"engines": {
"node": ">=20.19.5"
}
}
}

View File

@@ -4,7 +4,7 @@
"description": "The ugly name is intentional. We prefer to refactor incrementally which means we need a way to \"re-core\" the backend, and we may do this more than once simultaneously (hence it's `0` right now).",
"type": "module",
"scripts": {
"build": "rollup -c",
"build": "webpack",
"prepare": "npm run build",
"test": "echo \"Error: no test specified\" && exit 1"
},
@@ -15,11 +15,8 @@
}
},
"devDependencies": {
"rollup": "^3.21.4",
"rollup-plugin-copy": "^3.4.0",
"@rollup/plugin-commonjs": "^24.1.0",
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-replace": "^5.0.2"
"webpack": "^5.88.2",
"webpack-cli": "^5.1.1"
},
"keywords": [],
"author": "",

View File

@@ -1,27 +0,0 @@
import { defineConfig } from 'rollup';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
export default defineConfig([
// ESM build
{
input: 'src/exports.js',
output: {
dir: 'dist/esm',
format: 'es',
preserveModules: true
},
plugins: [nodeResolve()]
},
// CJS build
{
input: 'src/exports.js',
output: {
dir: 'dist/cjs',
format: 'cjs',
preserveModules: true,
entryFileNames: '[name].cjs',
},
plugins: [nodeResolve(), commonjs()]
}
]);

View File

@@ -1 +1 @@
export * as validation from './pdim/validation';
export * as validation from './pdim/validation.js';

View File

@@ -0,0 +1,54 @@
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// ESM build
const esmConfig = {
mode: 'production',
entry: './src/exports.js',
experiments: {
outputModule: true,
},
output: {
path: path.resolve(__dirname, 'dist/esm'),
filename: 'exports.js',
module: true,
library: {
type: 'module',
},
},
optimization: {
minimize: false,
},
resolve: {
extensions: ['.js', '.mjs'],
fullySpecified: false,
},
target: 'node',
};
// CJS build
const cjsConfig = {
mode: 'production',
entry: './src/exports.js',
output: {
path: path.resolve(__dirname, 'dist/cjs'),
filename: 'exports.cjs',
library: {
type: 'commonjs2',
},
},
optimization: {
minimize: false,
},
resolve: {
extensions: ['.js', '.mjs'],
fullySpecified: false,
},
target: 'node',
};
export default [esmConfig, cjsConfig];

View File

@@ -21,7 +21,6 @@ const BaseService = require("../../services/BaseService");
const path_ = require('node:path');
const fs = require('node:fs');
const rollupModule = require("rollup");
class ProxyLogger {
constructor (log) {
@@ -70,9 +69,8 @@ class DevWatcherService extends BaseService {
async ['__on_ready.webserver'] () {
const svc_process = this.services.get('process');
let { root, commands, webpack, rollup } = this.args;
let { root, commands, webpack } = this.args;
if ( ! webpack ) webpack = [];
if ( ! rollup ) rollup = [];
let promises = [];
for ( const entry of commands ) {
@@ -86,10 +84,6 @@ class DevWatcherService extends BaseService {
const p = this.start_a_webpack_watcher_(entry);
promises.push(p);
}
for ( const entry of rollup ) {
const p = this.start_a_rollup_watcher_(entry);
promises.push(p);
}
await Promise.all(promises);
// It's difficult to tell when webpack is "done" its first
@@ -152,8 +146,37 @@ class DevWatcherService extends BaseService {
if ( entry.env ) {
oldEnv = process.env;
const newEnv = Object.create(process.env);
let global_config = null;
try {
const svc_config = this.services.get('config');
global_config = svc_config ? svc_config.get('global_config') : null;
} catch (e) {
// Config service not available yet, will use null
}
for ( const k in entry.env ) {
newEnv[k] = entry.env[k];
const envValue = entry.env[k];
// If it's a function, call it with the config, otherwise use the value directly
if ( typeof envValue === 'function' ) {
try {
const result = envValue({ global_config: global_config });
// Only set the env var if we got a non-empty result
// This allows the webpack config to use its fallback values
if ( result ) {
newEnv[k] = result;
}
} catch (e) {
// If config is not available yet, don't set the env var
// This allows the webpack config to use its fallback values from config files
// Only log if it's not a null/undefined access error (which is expected)
if ( !e.message.includes('Cannot read properties of null') &&
!e.message.includes('Cannot read properties of undefined') ) {
this.log.warn(`Could not evaluate env function for ${k}: ${e.message}`);
}
}
} else {
newEnv[k] = envValue;
}
}
process.env = newEnv; // Yep, it totally lets us do this
}
@@ -185,10 +208,13 @@ class DevWatcherService extends BaseService {
hideSuccess = true;
}
if (err || stats.hasErrors()) {
this.log.error(`error information: ${entry.directory} using Webpack`, {
err,
stats,
});
// Extract error information without serializing the entire stats object
const errorInfo = {
err: err ? err.message : null,
errors: stats.compilation?.errors?.map(e => e.message) || [],
warnings: stats.compilation?.warnings?.map(w => w.message) || [],
};
this.log.error(`error information: ${entry.directory} using Webpack`, errorInfo);
this.log.error(`❌ failed to update ${entry.directory} using Webpack`);
} else {
// Normally success messages aren't important, but sometimes it takes
@@ -200,83 +226,6 @@ class DevWatcherService extends BaseService {
}
});
}
async start_a_rollup_watcher_ (entry) {
const possibleConfigNames = [
['rollup.config.js', 'package.json'],
['rollup.config.cjs', 'commonjs'],
['rollup.config.mjs', 'module'],
];
const {
configjsPath: rollupConfigPath,
moduleType,
} = await this.get_configjs({
directory: entry.directory,
configIsFor: 'rollup', // for error message
possibleConfigNames,
});
const updateRollupPaths = (config, newBase) => {
const onoutput = o => ({ ...o, file: o.file ? path_.join(newBase, o.file) : o.file });
return {
...config,
input: path_.join(newBase, config.input),
output: Array.isArray(config.output)
? config.output.map(onoutput)
: onoutput(config.output),
};
};
let oldEnv;
if ( entry.env ) {
oldEnv = process.env;
const newEnv = Object.create(process.env);
for ( const k in entry.env ) {
newEnv[k] = entry.env[k];
}
process.env = newEnv; // Yep, it totally lets us do this
}
let rollupConfig = moduleType === 'module'
? (await import(rollupConfigPath)).default
: require(rollupConfigPath);
if ( oldEnv ) process.env = oldEnv;
rollupConfig = updateRollupPaths(
rollupConfig,
path_.join(this.args.root, entry.directory),
);
// rollupConfig.watch = true; // I mean why can't it just...
const watcher = rollupModule.watch(rollupConfig);
let errorAfterLastEnd = false;
let firstEvent = true;
watcher.on('event', (event) => {
if ( event.code === 'END' ) {
let hideSuccess = false;
if ( firstEvent ) {
firstEvent = false;
hideSuccess = true;
}
if ( errorAfterLastEnd ) {
errorAfterLastEnd = false;
return;
}
if ( ! hideSuccess ) {
this.log.info(`✅ updated ${entry.directory} using Rollup`);
}
} else if ( event.code === 'ERROR' ) {
this.log.error(`error information: ${entry.directory} using Rollup`, {
event,
});
this.log.error(`❌ failed to update ${entry.directory} using Rollup`);
errorAfterLastEnd = true;
}
});
}
};
module.exports = DevWatcherService;

View File

@@ -51,23 +51,21 @@ class SelfHostedModule extends AdvancedBase {
{
services.registerService('__dev-watcher', DevWatcherService, {
root: path_.resolve(__dirname, RELATIVE_PATH),
rollup: [
webpack: [
{
name: 'phoenix',
directory: 'src/phoenix',
env: {
PUTER_JS_URL: ({ global_config: config }) => config.origin + '/sdk/puter.dev.js',
PUTER_JS_URL: ({ global_config: config }) => config?.origin ? config.origin + '/puter.js/v2' : '',
},
},
{
name: 'terminal',
directory: 'src/terminal',
env: {
PUTER_JS_URL: ({ global_config: config }) => config.origin + '/sdk/puter.dev.js',
PUTER_JS_URL: ({ global_config: config }) => config?.origin ? config.origin + '/puter.js/v2' : '',
},
},
],
webpack: [
{
name: 'puter.js',
directory: 'src/puter-js',
@@ -76,8 +74,8 @@ class SelfHostedModule extends AdvancedBase {
config.devtool = 'source-map';
},
env: {
PUTER_ORIGIN: ({ global_config: config }) => config.origin,
PUTER_API_ORIGIN: ({ global_config: config }) => config.api_base_url,
PUTER_ORIGIN: ({ global_config: config }) => config?.origin || '',
PUTER_API_ORIGIN: ({ global_config: config }) => config?.api_base_url || '',
},
},
{

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
@@ -10,8 +11,20 @@
<script src="bundle.js"></script>
<script>
document.addEventListener('DOMContentLoaded', async () => {
// Wait for the SDK to load (with timeout)
let attempts = 0;
const maxAttempts = 100; // 5 seconds max
while (typeof puter === 'undefined' && attempts < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, 50));
attempts++;
}
if (typeof puter === 'undefined') {
console.error('Puter SDK failed to load');
return;
}
main_shell();
});
</script>
</head>
</html>
</html>

View File

@@ -19,5 +19,5 @@
globalThis.__CONFIG__ = {
"origin": "https://puter.local:8080",
"shell.href": "https://puter.local:8081",
"sdk_url": "http://puter.localhost:4100/sdk/puter.js",
"sdk_url": "http://puter.localhost:4100/puter.js/v2",
};

View File

@@ -10,12 +10,10 @@
"license": "AGPL-3.0-only",
"type": "module",
"devDependencies": {
"@rollup/plugin-commonjs": "^24.1.0",
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-replace": "^5.0.2",
"copy-webpack-plugin": "^12.0.2",
"mocha": "^10.8.2",
"rollup": "^3.29.5",
"rollup-plugin-copy": "^3.4.0"
"webpack": "^5.88.2",
"webpack-cli": "^5.1.1"
},
"dependencies": {
"@pkgjs/parseargs": "^0.11.0",
@@ -36,4 +34,4 @@
"packages/strataparse",
"packages/contextlink"
]
}
}

View File

@@ -1,55 +0,0 @@
/*
* Copyright (C) 2024-present Puter Technologies Inc.
*
* This file is part of Puter.
*
* Puter is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { nodeResolve } from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs';
import copy from 'rollup-plugin-copy';
import process from 'node:process';
import path from 'node:path';
const configFile = process.env.CONFIG_FILE ?? 'config/dev.js';
await import(`./${configFile}`);
export default {
input: "src/main_puter.js",
output: {
file: "dist/bundle.js",
format: "iife",
strict: false,
},
plugins: [
nodeResolve({
rootDir: path.join(process.cwd(), '..'),
}),
commonjs(),
copy({
targets: [
{
src: 'assets/index.html',
dest: 'dist',
transform: (contents, name) => {
return contents.toString().replace('__SDK_URL__',
process.env.PUTER_JS_URL ?? globalThis.__CONFIG__.sdk_url);
}
},
{ src: 'assets/shell.html', dest: 'dist' },
{ src: configFile, dest: 'dist', rename: 'config.js' }
]
}),
]
}

View File

@@ -7,8 +7,8 @@
command: 'npx http-server -p 8080',
},
{
name: 'shell.rollup',
command: 'npx rollup -c rollup.config.js --watch',
name: 'shell.webpack',
command: 'npx webpack --watch',
pwd: '.'
},
],

View File

@@ -0,0 +1,3 @@
// Browser stub for node:child_process - not used in browser builds
export default {};

View File

@@ -0,0 +1,3 @@
// Browser stub for node-pty - not used in browser builds
export default {};

View File

@@ -0,0 +1,3 @@
// Browser stub for node:path - not used in browser builds
export default {};

View File

@@ -0,0 +1,3 @@
// Browser stub for node:process - not used in browser builds
export default {};

View File

@@ -0,0 +1,3 @@
// Browser stub for node:stream - not used in browser builds
export default {};

View File

@@ -16,28 +16,28 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import builtins from './coreutils/__exports__.js';
import ReadlineLib from "../ansi-shell/readline/readline.js";
import builtins from './coreutils/__exports__.js';
// TODO: auto-gen argument parser registry from files
import { libs } from '@heyputer/putility';
import { BetterReader } from 'dev-pty';
import { ANSIShell } from "../ansi-shell/ANSIShell.js";
import SimpleArgParser from "../ansi-shell/arg-parsers/simple-parser.js";
import ErrorsDecorator from "../ansi-shell/decorators/errors.js";
import { ANSIShell } from "../ansi-shell/ANSIShell.js";
import { libs } from '@heyputer/putility';
const { Context } = libs.context;
import { SHELL_VERSIONS } from "../meta/versions.js";
import { PuterShellParser } from "../ansi-shell/parsing/PuterShellParser.js";
import { BuiltinCommandProvider } from "./providers/BuiltinCommandProvider.js";
import { CreateChatHistoryPlugin } from './plugins/ChatHistoryPlugin.js';
import { Pipe } from '../ansi-shell/pipeline/Pipe.js';
import { Coupler } from '../ansi-shell/pipeline/Coupler.js';
import { BetterReader } from 'dev-pty';
import { MultiWriter } from '../ansi-shell/ioutil/MultiWriter.js';
import { PuterShellParser } from "../ansi-shell/parsing/PuterShellParser.js";
import { Coupler } from '../ansi-shell/pipeline/Coupler.js';
import { Pipe } from '../ansi-shell/pipeline/Pipe.js';
import { SHELL_VERSIONS } from "../meta/versions.js";
import { CreateChatHistoryPlugin } from './plugins/ChatHistoryPlugin.js';
import { BuiltinCommandProvider } from "./providers/BuiltinCommandProvider.js";
import { CompositeCommandProvider } from './providers/CompositeCommandProvider.js';
import { ScriptCommandProvider } from './providers/ScriptCommandProvider.js';
import { PuterAppCommandProvider } from './providers/PuterAppCommandProvider.js';
import { EmuCommandProvider } from './providers/EmuCommandProvider.js';
import { PDECommandProvider } from './providers/PDECommandProvider.js';
import { PuterAppCommandProvider } from './providers/PuterAppCommandProvider.js';
import { ScriptCommandProvider } from './providers/ScriptCommandProvider.js';
const { Context } = libs.context;
const argparser_registry = {
[SimpleArgParser.name]: SimpleArgParser
@@ -78,7 +78,7 @@ export const launchPuterShell = async (ctx) => {
}
// PathCommandProvider is only compatible with node.js for now
// HACK: The import path is split to fool rollup into not including it.
// HACK: The import path is split to fool webpack into not including it.
const { PathCommandProvider } = (ctx.platform.name === 'node')
? await import('./providers/' + 'PathCommandProvider.js')
: { PathCommandProvider: null };

View File

@@ -4,7 +4,7 @@ if [ $(basename "$(pwd)") != "phoenix" ]; then
fi
export CONFIG_FILE='config/release.js'
npx rollup -c rollup.config.js
npx webpack
if [ -d ./release ]; then
rm -rf ./release/*

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2024-present Puter Technologies Inc.
*
* This file is part of Puter.
*
* Puter is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import fs from 'node:fs';
import path from 'node:path';
class ResolveExtensionsPlugin {
apply(compiler) {
compiler.hooks.normalModuleFactory.tap('ResolveExtensionsPlugin', (nmf) => {
nmf.hooks.beforeResolve.tap('ResolveExtensionsPlugin', (data) => {
if (!data) return;
// Skip if already has an extension
if (data.request.match(/\.(js|mjs|json|ts|tsx|css|html)$/)) {
return;
}
const context = data.context || compiler.options.context || process.cwd();
let requestPath;
// Handle relative imports (starting with ./ or ../)
if (data.request.startsWith('.')) {
requestPath = path.resolve(context, data.request);
}
// Handle package subpath imports (like @heyputer/putility/src/libs/promise)
// Only add .js if there's a subpath (more than just the package name)
else if (data.request.includes('/') && !data.request.startsWith('/') && !data.request.startsWith('.')) {
const parts = data.request.split('/');
// If there are more than 2 parts (e.g., @scope/pkg/path/to/file), it's a subpath
// Scoped packages like @heyputer/putility have 2 parts for the name
if (data.request.startsWith('@')) {
// Scoped package: @scope/pkg/path -> needs 3+ parts for subpath
if (parts.length > 2) {
data.request = data.request + '.js';
return;
}
} else {
// Non-scoped package: pkg/path -> needs 2+ parts for subpath
if (parts.length > 1) {
data.request = data.request + '.js';
return;
}
}
return; // Top-level package import, don't modify
} else {
return; // Not a relative or package subpath import
}
// Check if .js file exists (for relative imports)
const jsPath = requestPath + '.js';
if (fs.existsSync(jsPath)) {
data.request = data.request + '.js';
return;
}
// Check if it's a directory with index.js
if (fs.existsSync(requestPath) && fs.statSync(requestPath).isDirectory()) {
const indexPath = path.join(requestPath, 'index.js');
if (fs.existsSync(indexPath)) {
data.request = data.request + '/index.js';
}
}
});
});
}
}
export default ResolveExtensionsPlugin;

View File

@@ -0,0 +1,96 @@
/*
* Copyright (C) 2024-present Puter Technologies Inc.
*
* This file is part of Puter.
*
* Puter is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import CopyWebpackPlugin from 'copy-webpack-plugin';
import fs from 'node:fs';
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import webpack from 'webpack';
import ResolveExtensionsPlugin from './webpack-resolve-extensions-plugin.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const configFile = process.env.CONFIG_FILE ?? 'config/dev.js';
const configPath = path.resolve(__dirname, configFile);
// Read and evaluate config file manually to avoid webpack processing it
const configContent = fs.readFileSync(configPath, 'utf-8');
// Create a safe context to evaluate the config
const configContext = { globalThis: { __CONFIG__: {} } };
// Evaluate the config file in a controlled way
eval(configContent.replace(/globalThis\.__CONFIG__/g, 'configContext.globalThis.__CONFIG__'));
// Capture config values at build time
const sdkUrl = process.env.PUTER_JS_URL ??
(configContext.globalThis.__CONFIG__?.sdk_url ?? '');
export default {
mode: 'development',
entry: './src/main_puter.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
iife: true,
},
resolve: {
modules: [path.resolve(__dirname, '..'), 'node_modules'],
extensions: ['.js', '.mjs', '.json'],
},
plugins: [
new ResolveExtensionsPlugin(),
// Replace Node.js built-ins with empty modules for browser builds
new webpack.NormalModuleReplacementPlugin(
/^node:path$/,
path.resolve(__dirname, 'src/platform/browser/node-stubs/path.js')
),
new webpack.NormalModuleReplacementPlugin(
/^node:child_process$/,
path.resolve(__dirname, 'src/platform/browser/node-stubs/child_process.js')
),
new webpack.NormalModuleReplacementPlugin(
/^node:stream$/,
path.resolve(__dirname, 'src/platform/browser/node-stubs/stream.js')
),
new webpack.NormalModuleReplacementPlugin(
/^node:process$/,
path.resolve(__dirname, 'src/platform/browser/node-stubs/process.js')
),
new webpack.NormalModuleReplacementPlugin(
/^node-pty$/,
path.resolve(__dirname, 'src/platform/browser/node-stubs/node-pty.js')
),
new CopyWebpackPlugin({
patterns: [
{
from: 'assets/index.html',
to: 'index.html',
transform: (content) => {
return content.toString().replace('__SDK_URL__', sdkUrl);
},
},
{
from: configFile,
to: 'config.js',
},
],
}),
],
};

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
@@ -13,10 +14,23 @@
<script src="bundle.js"></script>
<script>
document.addEventListener('DOMContentLoaded', async () => {
// Wait for the SDK to load (with timeout)
let attempts = 0;
const maxAttempts = 100; // 5 seconds max
while (typeof puter === 'undefined' && attempts < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, 50));
attempts++;
}
if (typeof puter === 'undefined') {
console.error('Puter SDK failed to load');
return;
}
main_term();
});
</script>
</head>
<body>
</body>
</html>
</html>

View File

@@ -18,5 +18,5 @@
*/
globalThis.__CONFIG__ = {
"origin": "http://127.0.0.1:8082",
"sdk_url": "http://puter.localhost:4100/sdk/puter.js",
"sdk_url": "http://puter.localhost:4100/puter.js/v2",
};

View File

@@ -10,17 +10,15 @@
"license": "AGPL-3.0-only",
"type": "module",
"devDependencies": {
"@rollup/plugin-commonjs": "^24.1.0",
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-replace": "^5.0.2",
"copy-webpack-plugin": "^12.0.2",
"http-server": "^14.1.1",
"mocha": "^10.8.2",
"rollup": "^3.29.5",
"rollup-plugin-copy": "^3.4.0"
"webpack": "^5.88.2",
"webpack-cli": "^5.1.1"
},
"dependencies": {
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-image": "^0.8.0",
"@xterm/xterm": "^5.5.0"
}
}
}

View File

@@ -1,64 +0,0 @@
/*
* Copyright (C) 2024-present Puter Technologies Inc.
*
* This file is part of Puter.
*
* Puter is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { nodeResolve } from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs';
import copy from 'rollup-plugin-copy';
import process from 'node:process';
import path from 'node:path';
const configFile = process.env.CONFIG_FILE ?? 'config/dev.js';
await import(`./${configFile}`);
export default {
input: "src/main.js",
output: {
file: "dist/bundle.js",
format: "iife"
},
plugins: [
nodeResolve({
rootDir: path.join(process.cwd(), '..'),
}),
commonjs(),
copy({
targets: [
{
src: 'assets/index.html',
dest: 'dist',
transform: (contents, name) => {
return contents.toString().replace('__SDK_URL__',
process.env.PUTER_JS_URL ?? globalThis.__CONFIG__.sdk_url);
}
},
{ src: 'assets/shell.html', dest: 'dist' },
{ src: 'assets/normalize.css', dest: 'dist' },
{ src: 'assets/style.css', dest: 'dist' },
// We add this manually because there's no way to be sure
// _which_ node_modules directory is the correct one, since
// support for workspaces is under-documented and people may
// be using package managers other than npm.
{ src: 'assets/xterm.css', dest: 'dist' },
// { src: 'node_modules/xterm/css/xterm.css', dest: 'dist' },
{ src: configFile, dest: 'dist', rename: 'config.js' }
]
}),
]
}

View File

@@ -6,9 +6,9 @@
command: 'npx http-server -p 8082',
},
{
name: 'term.rollup',
name: 'term.webpack',
pwd: '.',
command: 'npx rollup -c rollup.config.js --watch',
command: 'npx webpack --watch',
},
]
}

View File

@@ -6,9 +6,9 @@
command: 'npx http-server -p 8082 -S -C "{cert}" -K "{key}"',
},
{
name: 'term.rollup',
name: 'term.webpack',
pwd: '.',
command: 'npx rollup -c rollup.config.js --watch',
command: 'npx webpack --watch',
},
]
}

View File

@@ -2,22 +2,22 @@
init: [
{
pwd: '.',
command: 'npx rollup -c rollup.config.js'
command: 'npx webpack'
},
{
pwd: '../phoenix',
command: 'npx rollup -c rollup.config.js'
command: 'npx webpack'
},
],
services: [
{
name: 'term.rollup',
name: 'term.webpack',
pwd: '.',
command: 'npx rollup -c rollup.config.js --watch',
command: 'npx webpack --watch',
},
{
name: 'shell.rollup',
command: 'npx rollup -c rollup.config.js --watch',
name: 'shell.webpack',
command: 'npx webpack --watch',
pwd: '../phoenix'
},
{

View File

@@ -11,13 +11,13 @@
command: 'npx http-server -p 8080 -S -C "{cert}" -K "{key}"',
},
{
name: 'term.rollup',
command: 'npx rollup -c rollup.config.js --watch',
name: 'term.webpack',
command: 'npx webpack --watch',
pwd: '.'
},
{
name: 'ansi.rollup',
command: 'npx rollup -c rollup.config.js --watch',
name: 'ansi.webpack',
command: 'npx webpack --watch',
pwd: '../phoenix'
},
]

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2024-present Puter Technologies Inc.
*
* This file is part of Puter.
*
* Puter is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import fs from 'node:fs';
import path from 'node:path';
class ResolveExtensionsPlugin {
apply(compiler) {
compiler.hooks.normalModuleFactory.tap('ResolveExtensionsPlugin', (nmf) => {
nmf.hooks.beforeResolve.tap('ResolveExtensionsPlugin', (data) => {
if (!data) return;
// Skip if already has an extension
if (data.request.match(/\.(js|mjs|json|ts|tsx|css|html)$/)) {
return;
}
const context = data.context || compiler.options.context || process.cwd();
let requestPath;
// Handle relative imports (starting with ./ or ../)
if (data.request.startsWith('.')) {
requestPath = path.resolve(context, data.request);
}
// Handle package subpath imports (like @heyputer/putility/src/libs/promise)
// Only add .js if there's a subpath (more than just the package name)
else if (data.request.includes('/') && !data.request.startsWith('/') && !data.request.startsWith('.')) {
const parts = data.request.split('/');
// If there are more than 2 parts (e.g., @scope/pkg/path/to/file), it's a subpath
// Scoped packages like @heyputer/putility have 2 parts for the name
if (data.request.startsWith('@')) {
// Scoped package: @scope/pkg/path -> needs 3+ parts for subpath
if (parts.length > 2) {
data.request = data.request + '.js';
return;
}
} else {
// Non-scoped package: pkg/path -> needs 2+ parts for subpath
if (parts.length > 1) {
data.request = data.request + '.js';
return;
}
}
return; // Top-level package import, don't modify
} else {
return; // Not a relative or package subpath import
}
// Check if .js file exists (for relative imports)
const jsPath = requestPath + '.js';
if (fs.existsSync(jsPath)) {
data.request = data.request + '.js';
return;
}
// Check if it's a directory with index.js
if (fs.existsSync(requestPath) && fs.statSync(requestPath).isDirectory()) {
const indexPath = path.join(requestPath, 'index.js');
if (fs.existsSync(indexPath)) {
data.request = data.request + '/index.js';
}
}
});
});
}
}
export default ResolveExtensionsPlugin;

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2024-present Puter Technologies Inc.
*
* This file is part of Puter.
*
* Puter is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import CopyWebpackPlugin from 'copy-webpack-plugin';
import fs from 'node:fs';
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import ResolveExtensionsPlugin from './webpack-resolve-extensions-plugin.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const configFile = process.env.CONFIG_FILE ?? 'config/dev.js';
const configPath = path.resolve(__dirname, configFile);
// Read and evaluate config file manually to avoid webpack processing it
const configContent = fs.readFileSync(configPath, 'utf-8');
// Create a safe context to evaluate the config
const configContext = { globalThis: { __CONFIG__: {} } };
// Evaluate the config file in a controlled way
eval(configContent.replace(/globalThis\.__CONFIG__/g, 'configContext.globalThis.__CONFIG__'));
// Capture config values at build time
const sdkUrl = process.env.PUTER_JS_URL ??
(configContext.globalThis.__CONFIG__?.sdk_url ?? '');
export default {
mode: 'development',
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
iife: true,
},
resolve: {
modules: [path.resolve(__dirname, '..'), 'node_modules'],
extensions: ['.js', '.mjs', '.json'],
},
plugins: [
new ResolveExtensionsPlugin(),
new CopyWebpackPlugin({
patterns: [
{
from: 'assets/index.html',
to: 'index.html',
transform: (content) => {
return content.toString().replace('__SDK_URL__', sdkUrl);
},
},
{ from: 'assets/normalize.css', to: 'normalize.css' },
{ from: 'assets/style.css', to: 'style.css' },
{ from: 'assets/xterm.css', to: 'xterm.css' },
{
from: configFile,
to: 'config.js',
},
],
}),
],
};