diff --git a/package-lock.json b/package-lock.json index b4aaaa7..b2f64ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "svrjs-mod-starter", "version": "0.0.0", + "hasInstallScript": true, "devDependencies": { "@eslint/js": "^9.9.1", "esbuild": "^0.23.1", @@ -16,7 +17,8 @@ "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", - "prettier": "^3.3.3" + "prettier": "^3.3.3", + "zip": "^1.2.0" } }, "node_modules/@ampproject/remapping": { @@ -2085,6 +2087,25 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz", + "integrity": "sha512-Pj9L87dCdGcKlSqPVUjD+q96pbIx1zQQLb2CUiWURfjiBELv84YX+0nGnKmyT/9KkC7PQk7UN1w+Al8bBozaxQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bops": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/bops/-/bops-0.1.1.tgz", + "integrity": "sha512-Cx1zStcMp+YoFan8OgudNPMih82eJZE+27feki1WeyoFTR9Ye7AR1SUW3saE6QQvdS/g52aJ2IojBjWOiRiLbw==", + "dev": true, + "dependencies": { + "base64-js": "0.0.2", + "to-utf8": "0.0.1" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4809,6 +4830,12 @@ "node": ">=8.0" } }, + "node_modules/to-utf8": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", + "integrity": "sha512-zks18/TWT1iHO3v0vFp5qLKOG27m67ycq/Y7a7cTiRuUNlc4gf3HGnkRgMv0NyhnfTamtkYBJl+YeD1/j07gBQ==", + "dev": true + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -5055,6 +5082,15 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zip": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip/-/zip-1.2.0.tgz", + "integrity": "sha512-8B4Z9BXJKkI8BkHhKvQan4rwCzUENnj95YHFYrI7F1NbqKCIdW86kujctzEB+kJ6XapHPiAhiZ9xi5GbW5SPdw==", + "dev": true, + "dependencies": { + "bops": "~0.1.1" + } } } } diff --git a/package.json b/package.json index f8091e7..bd1c7a7 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "build": "node esbuild.config.js", "lint": "eslint --no-error-on-unmatched-pattern src/**/*.js src/*.js tests/**/*.test.js tests/**/*.js", "lint:fix": "npm run lint -- --fix", + "postinstall": "node svrjs.install.js", "test": "jest" }, "devDependencies": { @@ -17,6 +18,7 @@ "eslint-plugin-prettier": "^5.2.1", "globals": "^15.9.0", "jest": "^29.7.0", - "prettier": "^3.3.3" + "prettier": "^3.3.3", + "zip": "^1.2.0" } } diff --git a/svrjs.install.js b/svrjs.install.js new file mode 100644 index 0000000..7758857 --- /dev/null +++ b/svrjs.install.js @@ -0,0 +1,126 @@ +// Code in the SVR.JS installation script is derived from the "create-svrjs-server" command. + +const fs = require("fs"); +const https = require("https"); +const zip = require("zip"); +const zlib = require("zlib"); + +function downloadSVRJS(version) { + const normalizedVersion = version.toLowerCase().replace(/[^0-9a-z]+/g, "."); + let path = "/svr.js." + normalizedVersion + ".zip"; + if (normalizedVersion.indexOf("beta") != -1) + path = "/beta/svr.js." + normalizedVersion + ".zip"; + if (normalizedVersion.indexOf("nightly") != -1) + path = "/nightly/svr.js." + normalizedVersion + ".zip"; + https + .get( + { + hostname: "downloads.svrjs.org", + port: 443, + path: path, + method: "GET" + }, + (res) => { + let zipData = ""; + if (res.statusCode != 200) { + console.log( + "Server returned the " + + res.statusCode + + " HTTP status code while trying to download SVR.JS " + + version + ); + process.exit(1); + } + + res.on("data", (chunk) => { + zipData += chunk.toString("latin1"); + }); + + res.on("end", function () { + console.log("Downloaded the .zip file"); + zipData = Buffer.from(zipData, "latin1"); + const reader = zip.Reader(zipData); + const allFiles = reader.toObject(); + Object.keys(allFiles).forEach((filename) => { + var paths = filename.split("/"); + if ( + filename.match( + /^(?:[^/.]+\.compressed|(?:log(?:viewer|highlight)|svr(?:passwd|_new)?)\.js|node_modules(?:\/|$))/ + ) + ) { + for (var j = 0; j < paths.length - 1; j++) { + const dirname = JSON.parse(JSON.stringify(paths)) + .splice(0, j + 1) + .join("/"); + if (!fs.existsSync(__dirname + "/svrjs/" + dirname)) { + fs.mkdirSync(__dirname + "/svrjs/" + dirname); + } + } + fs.writeFileSync( + __dirname + "/svrjs/" + filename, + allFiles[filename] + ); + } + }); + fs.mkdirSync(__dirname + "/svrjs/mods"); + console.log("Deleting SVR.JS stub..."); + fs.unlinkSync(__dirname + "/svrjs/svr.js"); + // Modules aren't extracted in SVR.JS's 4.x stub, so no module extraction code here. + console.log("Decompressing SVR.JS..."); + const script = zlib.gunzipSync( + fs.readFileSync(__dirname + "/svrjs/svr.compressed") + ); + fs.unlinkSync(__dirname + "/svrjs/svr.compressed"); + fs.writeFileSync(__dirname + "/svrjs/svr.js", script); + console.log("SVR.JS is installed successfully."); + }); + } + ) + .on("error", function () { + console.log("Can't connect to the SVR.JS download server!"); + process.exit(1); + }); +} + +if (fs.existsSync(__dirname + "/svrjs")) { + console.log("SVR.JS is already installed."); +} else { + fs.mkdirSync(__dirname + "/svrjs"); + https + .get( + { + hostname: "downloads.svrjs.org", + port: 443, + path: "/latest.svrjs", + method: "GET" + }, + (res) => { + if (res.statusCode != 200) { + console.log( + "Server returned the " + res.statusCode + " HTTP status code" + ); + process.exit(1); + } + let data = ""; + res.on("data", (chunk) => { + data += chunk; + }); + res.on("end", () => { + const selectedVersion = data.trim(); + if (!selectedVersion) { + console.log( + "Can't obtain the latest version from downloads server" + ); + process.exit(1); + } else { + console.log("Selected SVR.JS " + selectedVersion); + downloadSVRJS(selectedVersion); + } + }); + } + ) + .on("error", function () { + console.log("Can't connect to the SVR.JS download server!"); + process.exit(1); + }); +}