1
0
Fork 0
forked from svrjs/svrjs

Compare commits

..

54 commits
main ... stable

Author SHA1 Message Date
317acff5d6 chore: release SVR.JS 4.1.0 2024-10-19 07:39:45 +02:00
f4fc6ba165 chore: release SVR.JS 4.0.2 2024-10-15 18:25:36 +02:00
3bf8ff799e chore: release SVR.JS 4.0.1 2024-09-25 15:51:40 +02:00
9e227bbec6 fix: fix bug with the extraction script 2024-09-20 07:47:15 +02:00
27c613f28e chore: release SVR.JS 4.0.0 2024-09-14 16:23:49 +02:00
215f1fae25 Update to SVR.JS 3.15.7 2024-08-26 08:36:01 +02:00
d44ee67e57 Update to SVR.JS 3.15.6 2024-08-07 06:23:42 +02:00
effc654f05 Update to SVR.JS 3.15.5 2024-06-13 15:26:46 +02:00
997b03c2a2 Update to SVR.JS 3.15.4 2024-05-30 21:09:00 +02:00
45d8b9bcd3 Update to SVR.JS 3.15.3 2024-05-21 17:28:47 +02:00
78e7c8c967 Update to SVR.JS 3.15.2 2024-05-20 17:42:16 +02:00
25280b310c Update to SVR.JS 3.15.1 2024-05-13 18:03:58 +02:00
73b062d306 Update to SVR.JS 3.15.0 2024-05-06 12:30:50 +02:00
2ae73966ec Update to SVR.JS 3.14.15 2024-04-29 20:12:49 +02:00
5e031fe997 Update to SVR.JS 3.14.14 2024-04-27 13:55:21 +02:00
1c6e707f58 Update to SVR.JS 3.14.13 2024-04-24 13:28:20 +02:00
4a1a59f15d Update to SVR.JS 3.14.12 2024-04-13 11:18:02 +02:00
67680fc97f Update to SVR.JS 3.14.11 2024-04-07 15:53:24 +02:00
40f100db94 Update to SVR.JS 3.14.10 2024-04-07 14:24:53 +02:00
7d144c95b6 Update to SVR.JS 3.14.9 2024-04-02 11:24:36 +02:00
3b25b33583 Update to SVR.JS 3.14.8 2024-03-29 11:08:18 +01:00
c70e078b26 Update to SVR.JS 3.14.7 2024-03-19 17:16:13 +01:00
3abc31e2aa Update to SVR.JS 3.14.6 2024-03-17 21:49:23 +01:00
0161b04e1f Update to SVR.JS 3.14.5 2024-03-09 16:37:18 +01:00
d7b0fc463e Update to SVR.JS 3.14.4 2024-03-03 21:20:09 +01:00
3d411c3be1 Update to SVR.JS 3.14.3 2024-02-11 21:37:26 +01:00
9c49df9d87 Update to SVR.JS 3.14.2 2024-02-07 00:57:09 +01:00
06712f35b5 Update to SVR.JS 3.14.1 2024-02-02 20:07:11 +01:00
91f2d3b50f Update to SVR.JS 3.14.0 2024-01-24 21:06:17 +01:00
688c850c50 Update to SVR.JS 3.13.1 2024-01-18 01:21:25 +01:00
26214c9eb8 Update to SVR.JS 3.13.0 2024-01-14 19:03:30 +01:00
4928ac1d2c Update to SVR.JS 3.12.3 2023-12-30 23:50:11 +01:00
27e62da887 Update to SVR.JS 3.12.2 2023-12-16 09:01:30 +01:00
d25f912c06 Update to SVR.JS 3.12.1 2023-12-12 23:28:00 +01:00
19f7345762 Update to SVR.JS 3.12.0 2023-12-07 09:58:43 +01:00
a63e1a893b Update to SVR.JS 3.11.0 2023-11-12 20:18:43 +01:00
a755e32bc7 Update to SVR.JS 3.10.3 2023-09-17 23:40:02 +02:00
c380c469ef Update to SVR.JS 3.10.2 2023-09-12 23:21:54 +02:00
faecaa8b8a Update to SVR.JS 3.10.1 2023-09-12 21:17:24 +02:00
ae3cf033be Update to SVR.JS 3.10.0 2023-09-11 23:23:54 +02:00
9fa9c047d1 Update to SVR.JS 3.9.6 2023-09-10 11:13:23 +02:00
faa043cb99 Update to SVR.JS 3.9.4 2023-09-08 20:20:40 +02:00
7587932250 Update to SVR.JS 3.9.3 2023-09-07 18:07:30 +02:00
9406ffda5f Update to SVR.JS 3.9.2 2023-09-06 20:23:53 +02:00
10ee128136 Update to SVR.JS 3.9.1 2023-09-05 00:13:52 +02:00
Dorian Niemiec
91d8d0df63 Update to SVR.JS 3.9.0 2023-09-03 22:51:02 +02:00
71b5727b6c Update to SVR.JS 3.8.1 2023-09-02 09:39:46 +02:00
c6960061b7 Update to SVR.JS 3.8.0 2023-09-01 11:53:00 +02:00
55262f73c5 Update to SVR.JS 3.7.5 2023-08-29 15:34:17 +02:00
750a312b2f Update to SVR.JS 3.7.4 2023-08-28 04:20:38 +02:00
e0f0cb69d8 Update to SVR.JS 3.7.3 2023-08-25 00:42:38 +02:00
d01064cc17 Update to SVR.JS 3.7.2 2023-08-21 19:44:25 +02:00
c9df74c745 Update to SVR.JS 3.7.1 2023-08-21 02:56:52 +02:00
46a256d31f Update to SVR.JS 3.7.0 2023-08-20 03:14:24 +02:00
18 changed files with 1360 additions and 1325 deletions

View file

@ -8,10 +8,10 @@
It's free as in freedom, scalable, secure, and configurable. It's free as in freedom, scalable, secure, and configurable.
</p> </p>
<p align="center"> <p align="center">
<a href="https://svrjs.org/docs" target="_blank"><img alt="Static Badge" src="https://img.shields.io/badge/Documentation-green"></a> <a href="https://svrjs.org/docs/tentative" target="_blank"><img alt="Static Badge" src="https://img.shields.io/badge/Documentation-green"></a>
<a href="https://svrjs.org" target="_blank"><img alt="Website" src="https://img.shields.io/website?url=https%3A%2F%2Fsvrjs.org"></a> <a href="https://svrjs.org" target="_blank"><img alt="Website" src="https://img.shields.io/website?url=https%3A%2F%2Fsvrjs.org"></a>
<a href="https://hub.docker.com/r/svrjs/svrjs" target="_blank"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/svrjs/svrjs"></a> <a href="https://hub.docker.com/r/svrjs/svrjs" target="_blank"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/svrjs/svrjs"></a>
<a href="https://github.com/svr-js/svrjs" target="_blank"><img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/svr-js/svrjs"></a> <a href="https://github.com/svr-js/svrjs/tree/next" target="_blank"><img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/svr-js/svrjs"></a>
<a href="https://x.com/SVR_JS" target="_blank"><img alt="X (formerly Twitter) Follow" src="https://img.shields.io/twitter/follow/SVR_JS"></a> <a href="https://x.com/SVR_JS" target="_blank"><img alt="X (formerly Twitter) Follow" src="https://img.shields.io/twitter/follow/SVR_JS"></a>
<a href="https://mastodon.social/@svrjs" target="_blank"><img alt="Mastodon Follow" src="https://img.shields.io/mastodon/follow/111643338718098121"></a> <a href="https://mastodon.social/@svrjs" target="_blank"><img alt="Mastodon Follow" src="https://img.shields.io/mastodon/follow/111643338718098121"></a>
</p> </p>
@ -87,7 +87,7 @@ After running the command, you will get bundled SVR.JS script, around with built
To install SVR.JS you just built from the source code, you can install it via SVR.JS installer for GNU/Linux or manually. To install SVR.JS you just built from the source code, you can install it via SVR.JS installer for GNU/Linux or manually.
If you want to install SVR.JS manually, you can read the [server documentation](https://svrjs.org/docs). If you want to install SVR.JS manually, you can read the [server documentation](https://svrjs.org/docs/tentative).
If you want to install via SVR.JS installer for GNU/Linux, run this command: If you want to install via SVR.JS installer for GNU/Linux, run this command:
```bash ```bash
@ -102,7 +102,7 @@ After installation, SVR.JS should be listening at http://localhost.
## SVR.JS documentation ## SVR.JS documentation
You can read the [SVR.JS documentation](https://svrjs.org/docs) to get information on how to use SVR.JS. You can read the [SVR.JS documentation](https://svrjs.org/docs/tentative) to get information on how to use SVR.JS.
## npm scripts ## npm scripts

View file

@ -59,6 +59,5 @@
"disableTrailingSlashRedirects": false, "disableTrailingSlashRedirects": false,
"environmentVariables": {}, "environmentVariables": {},
"allowDoubleSlashes": false, "allowDoubleSlashes": false,
"optOutOfStatisticsServer": false, "optOutOfStatisticsServer": false
"disableConfigurationSaving": false
} }

View file

@ -4,36 +4,15 @@ const fs = require("fs");
const zlib = require("zlib"); const zlib = require("zlib");
const ejs = require("ejs"); const ejs = require("ejs");
const archiver = require("archiver"); const archiver = require("archiver");
const chokidar = require("chokidar"); const dependencies =
const svrjsInfo = JSON.parse(fs.readFileSync(__dirname + "/svrjs.json"));
const { version } = svrjsInfo;
const isDev = process.env.NODE_ENV == "development";
// Create the dist directory if it doesn't exist
if (!fs.existsSync(__dirname + "/dist")) fs.mkdirSync(__dirname + "/dist");
if (!fs.existsSync(__dirname + "/dist/log"))
fs.mkdirSync(__dirname + "/dist/log");
if (!fs.existsSync(__dirname + "/dist/mods"))
fs.mkdirSync(__dirname + "/dist/mods");
if (!fs.existsSync(__dirname + "/dist/temp"))
fs.mkdirSync(__dirname + "/dist/temp");
// Create the out directory if it doesn't exist and if not building for development
if (!isDev && !fs.existsSync(__dirname + "/out")) fs.mkdirSync(__dirname + "/out");
function generateAssets() {
// Variables from "svrjs.json" file
const svrjsInfo = JSON.parse(fs.readFileSync(__dirname + "/svrjs.json"));
const { name, version, documentationURL, changes } = svrjsInfo;
// Dependency-related variables
const dependencies =
JSON.parse(fs.readFileSync(__dirname + "/package.json")).dependencies || {}; JSON.parse(fs.readFileSync(__dirname + "/package.json")).dependencies || {};
const requiredDependencyList = Object.keys(dependencies); const requiredDependencyList = Object.keys(dependencies);
let dependencyList = Object.keys(dependencies); let dependencyList = Object.keys(dependencies);
const svrjsInfo = JSON.parse(fs.readFileSync(__dirname + "/svrjs.json"));
const { name, version, documentationURL, changes } = svrjsInfo;
// Function to find and add all dependencies into the dependencyList array. // Function to find and add all dependencies into the dependencyList array.
const findAllDependencies = (curList) => { function findAllDependencies(curList) {
// If no curList parameter is specified, use dependencyList. // If no curList parameter is specified, use dependencyList.
if (!curList) curList = dependencyList; if (!curList) curList = dependencyList;
curList.forEach((dependency) => { curList.forEach((dependency) => {
@ -60,42 +39,42 @@ function generateAssets() {
// Call findAllDependencies for the dependency list. // Call findAllDependencies for the dependency list.
findAllDependencies(noDupNewDepList); findAllDependencies(noDupNewDepList);
}); });
}; }
// Get list of all dependencies // Get list of all dependencies
findAllDependencies(); findAllDependencies();
dependencyList = dependencyList.sort(); dependencyList = dependencyList.sort();
// Create and populate an object, where whenever the dependencies are required are listed. // Create and populate an object, where whenever the dependencies are required are listed.
let dependenciesAreRequired = {}; let dependenciesAreRequired = {};
dependencyList.forEach((dependency) => { dependencyList.forEach((dependency) => {
dependenciesAreRequired[dependency] = false; dependenciesAreRequired[dependency] = false;
}); });
requiredDependencyList.forEach((dependency) => { requiredDependencyList.forEach((dependency) => {
dependenciesAreRequired[dependency] = true; dependenciesAreRequired[dependency] = true;
}); });
// Create the template functions using EJS // Create the template functions using EJS
const layoutTemplate = ejs.compile( const layoutTemplate = ejs.compile(
fs.readFileSync(__dirname + "/templates/layout.ejs").toString() fs.readFileSync(__dirname + "/templates/layout.ejs").toString()
); );
const testsTemplate = ejs.compile( const testsTemplate = ejs.compile(
fs.readFileSync(__dirname + "/templates/tests.ejs").toString() fs.readFileSync(__dirname + "/templates/tests.ejs").toString()
); );
const indexTemplate = ejs.compile( const indexTemplate = ejs.compile(
fs.readFileSync(__dirname + "/templates/index.ejs").toString() fs.readFileSync(__dirname + "/templates/index.ejs").toString()
); );
const licensesTemplate = ejs.compile( const licensesTemplate = ejs.compile(
fs.readFileSync(__dirname + "/templates/licenses.ejs").toString() fs.readFileSync(__dirname + "/templates/licenses.ejs").toString()
); );
const licenseElementTemplate = ejs.compile( const licenseElementTemplate = ejs.compile(
fs.readFileSync(__dirname + "/templates/licenseElement.ejs").toString() fs.readFileSync(__dirname + "/templates/licenseElement.ejs").toString()
); );
let licenseElements = ""; let licenseElements = "";
// Generate the licenses list in HTML // Generate the licenses list in HTML
dependencyList.forEach((dependency) => { dependencyList.forEach((dependency) => {
const packageJSON = JSON.parse( const packageJSON = JSON.parse(
fs fs
.readFileSync( .readFileSync(
@ -114,27 +93,27 @@ function generateAssets() {
author: packageJSON.author ? packageJSON.author.name : packageJSON.author, author: packageJSON.author ? packageJSON.author.name : packageJSON.author,
required: dependenciesAreRequired[dependency] required: dependenciesAreRequired[dependency]
}); });
}); });
// Generate pages // Generate pages
const licensesPage = layoutTemplate({ const licensesPage = layoutTemplate({
title: name + " " + version + " Licenses", title: name + " " + version + " Licenses",
content: licensesTemplate({ content: licensesTemplate({
name: name, name: name,
version: version, version: version,
licenses: licenseElements licenses: licenseElements
}) })
}); });
const testsPage = layoutTemplate({ const testsPage = layoutTemplate({
title: name + " " + version + " Tests", title: name + " " + version + " Tests",
content: testsTemplate({ content: testsTemplate({
name: name, name: name,
version: version version: version
}) })
}); });
const indexPage = layoutTemplate({ const indexPage = layoutTemplate({
title: name + " " + version, title: name + " " + version,
content: indexTemplate({ content: indexTemplate({
name: name, name: name,
@ -142,57 +121,45 @@ function generateAssets() {
documentationURL: documentationURL, documentationURL: documentationURL,
changes: changes changes: changes
}) })
}); });
// Create the generated assets directory if it doesn't exist // Remove the generated assets directory if exists, and create a new one.
if (!fs.existsSync(__dirname + "/generatedAssets")) if (fs.existsSync(__dirname + "/generatedAssets")) {
fs.mkdirSync(__dirname + "/generatedAssets"); if (fs.rmSync) fs.rmSync(__dirname + "/generatedAssets", { recursive: true });
else fs.rmdirSync(__dirname + "/generatedAssets", { recursive: true });
}
fs.mkdirSync(__dirname + "/generatedAssets");
// Create a licenses directory // Remove the dist directory if exists, and create a new one.
if (!fs.existsSync(__dirname + "/generatedAssets/licenses")) if (fs.existsSync(__dirname + "/dist")) {
fs.mkdirSync(__dirname + "/generatedAssets/licenses"); if (fs.rmSync) fs.rmSync(__dirname + "/dist", { recursive: true });
else fs.rmdirSync(__dirname + "/dist", { recursive: true });
}
fs.mkdirSync(__dirname + "/dist");
fs.mkdirSync(__dirname + "/dist/log");
fs.mkdirSync(__dirname + "/dist/mods");
fs.mkdirSync(__dirname + "/dist/temp");
// Write to HTML files // Remove the out directory if exists, and create a new one.
fs.writeFileSync(__dirname + "/generatedAssets/index.html", indexPage); if (fs.existsSync(__dirname + "/out")) {
fs.writeFileSync(__dirname + "/generatedAssets/tests.html", testsPage); if (fs.rmSync) fs.rmSync(__dirname + "/out", { recursive: true });
fs.writeFileSync( else fs.rmdirSync(__dirname + "/out", { recursive: true });
}
fs.mkdirSync(__dirname + "/out");
// Create a licenses directory
fs.mkdirSync(__dirname + "/generatedAssets/licenses");
// Write to HTML files
fs.writeFileSync(__dirname + "/generatedAssets/index.html", indexPage);
fs.writeFileSync(__dirname + "/generatedAssets/tests.html", testsPage);
fs.writeFileSync(
__dirname + "/generatedAssets/licenses/index.html", __dirname + "/generatedAssets/licenses/index.html",
licensesPage licensesPage
); );
}
if (!isDev) { // Bundle the source and copy the assets using esbuild and esbuild-plugin-copy
// Generate assets esbuild
generateAssets();
} else {
// Generate assets with watching
const watcher = chokidar.watch([
__dirname + "/templates",
__dirname + "/package.json",
__dirname + "/svrjs.json"
]);
watcher.on("change", () => {
try {
generateAssets();
} catch (err) {
console.error("There is a problem when regenerating assets!");
console.error("Stack:");
console.error(err.stack);
}
}).on("ready", () => {
try {
generateAssets();
} catch (err) {
console.error("There is a problem when regenerating assets!");
console.error("Stack:");
console.error(err.stack);
}
});
}
if (!isDev) {
// Bundle the source and copy the assets using esbuild and esbuild-plugin-copy
esbuild
.build({ .build({
entryPoints: ["src/index.js"], entryPoints: ["src/index.js"],
bundle: true, bundle: true,
@ -247,9 +214,7 @@ if (!isDev) {
"svr.js." + "svr.js." +
version.toLowerCase().replace(/[^0-9a-z]+/g, ".") + version.toLowerCase().replace(/[^0-9a-z]+/g, ".") +
".zip"; ".zip";
const output = fs.createWriteStream( const output = fs.createWriteStream(__dirname + "/out/" + archiveName);
__dirname + "/out/" + archiveName
);
const archive = archiver("zip", { const archive = archiver("zip", {
zlib: { level: 9 } zlib: { level: 9 }
}); });
@ -284,82 +249,3 @@ if (!isDev) {
.catch((err) => { .catch((err) => {
throw err; throw err;
}); });
} else {
// Bundle the source and copy the assets using esbuild and esbuild-plugin-copy with watching
esbuild
.context({
entryPoints: ["src/index.js"],
bundle: true,
outfile: "dist/svr.js",
platform: "node",
target: "es2017",
plugins: [
esbuildCopyPlugin.copy({
resolveFrom: __dirname,
assets: {
from: ["./assets/**/*"],
to: ["./dist"]
},
globbyOptions: {
dot: true
},
watch: {}
}),
esbuildCopyPlugin.copy({
resolveFrom: __dirname,
assets: {
from: ["./generatedAssets/**/*"],
to: ["./dist"]
},
watch: {}
})
]
})
.then((ctx) => {
ctx
.watch()
.then(() => {
const utilFilesAndDirectories = fs.existsSync(
__dirname + "/src/extraScripts"
)
? fs.readdirSync(__dirname + "/src/extraScripts")
: [];
const utilFiles = [];
utilFilesAndDirectories.forEach((entry) => {
if (fs.statSync(__dirname + "/src/extraScripts/" + entry).isFile())
utilFiles.push(entry);
});
// Transpile utilities using esbuild
esbuild
.context({
entryPoints: utilFiles.map(
(filename) => "src/extraScripts/" + filename
),
bundle: true,
outdir: "dist",
platform: "node",
target: "es2017"
})
.then((ctx) => {
ctx
.watch()
.then(() => {
console.log("Watching for changes in SVR.JS source code...");
})
.catch((err) => {
throw err;
});
})
.catch((err) => {
throw err;
});
})
.catch((err) => {
throw err;
});
})
.catch((err) => {
throw err;
});
}

View file

@ -1,6 +0,0 @@
{
"watch": [
"dist/svr.js",
"dist/config.json"
]
}

1731
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -3,10 +3,9 @@
"version": "0.0.0", "version": "0.0.0",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "npm run clean && NODE_ENV=production node esbuild.config.js", "build": "node esbuild.config.js",
"cz": "cz", "cz": "cz",
"clean": "rimraf dist && rimraf out && rimraf generatedAssets", "dev": "npm run build && npm run start",
"dev": "npm run clean && concurrently \"NODE_ENV=development node esbuild.config.js\" \"wait-on dist/svr.js && nodemon dist/svr.js --stdout-notty --no-save-config\"",
"lint": "eslint --no-error-on-unmatched-pattern src/**/*.js src/*.js tests/**/*.test.js tests/**/*.js tests/*.test.js tests/*.js", "lint": "eslint --no-error-on-unmatched-pattern src/**/*.js src/*.js tests/**/*.test.js tests/**/*.js tests/*.test.js tests/*.js",
"lint:fix": "npm run lint -- --fix", "lint:fix": "npm run lint -- --fix",
"prepare": "husky", "prepare": "husky",
@ -21,9 +20,7 @@
"@commitlint/config-conventional": "^19.4.1", "@commitlint/config-conventional": "^19.4.1",
"@eslint/js": "^9.9.0", "@eslint/js": "^9.9.0",
"archiver": "^7.0.1", "archiver": "^7.0.1",
"chokidar": "^4.0.1",
"commitizen": "^4.3.0", "commitizen": "^4.3.0",
"concurrently": "^9.1.0",
"cz-conventional-changelog": "^3.3.0", "cz-conventional-changelog": "^3.3.0",
"ejs": "^3.1.10", "ejs": "^3.1.10",
"esbuild": "^0.23.1", "esbuild": "^0.23.1",
@ -37,10 +34,7 @@
"jest": "^29.7.0", "jest": "^29.7.0",
"lint-staged": "^15.2.10", "lint-staged": "^15.2.10",
"node-mocks-http": "^1.15.1", "node-mocks-http": "^1.15.1",
"nodemon": "^3.1.7", "prettier": "^3.3.3"
"prettier": "^3.3.3",
"rimraf": "^5.0.10",
"wait-on": "^8.0.1"
}, },
"dependencies": { "dependencies": {
"formidable": "^2.1.2", "formidable": "^2.1.2",

View file

@ -12,9 +12,6 @@ let serverconsole = {};
function clientErrorHandler(err, socket) { function clientErrorHandler(err, socket) {
const config = deepClone(process.serverConfig); const config = deepClone(process.serverConfig);
// Determine the webroot from the current working directory if it is not configured
if (config.wwwroot === undefined) config.wwwroot = process.cwd();
config.generateServerString = () => config.generateServerString = () =>
generateServerString(config.exposeServerVersion); generateServerString(config.exposeServerVersion);
@ -185,14 +182,14 @@ function clientErrorHandler(err, socket) {
fs.access(config.page404, fs.constants.F_OK, (err) => { fs.access(config.page404, fs.constants.F_OK, (err) => {
if (err) { if (err) {
fs.access( fs.access(
config.wwwroot + "/." + errorCode.toString(), "." + errorCode.toString(),
fs.constants.F_OK, fs.constants.F_OK,
(err) => { (err) => {
try { try {
if (err) { if (err) {
callback(errorCode.toString() + ".html"); callback(errorCode.toString() + ".html");
} else { } else {
callback(config.wwwroot + "/." + errorCode.toString()); callback("." + errorCode.toString());
} }
} catch (err2) { } catch (err2) {
callServerError(500, err2); callServerError(500, err2);
@ -208,21 +205,17 @@ function clientErrorHandler(err, socket) {
} }
}); });
} else { } else {
fs.access( fs.access("." + errorCode.toString(), fs.constants.F_OK, (err) => {
config.wwwroot + "/." + errorCode.toString(),
fs.constants.F_OK,
(err) => {
try { try {
if (err) { if (err) {
callback(errorCode.toString() + ".html"); callback(errorCode.toString() + ".html");
} else { } else {
callback(config.wwwroot + "/." + errorCode.toString()); callback("." + errorCode.toString());
} }
} catch (err2) { } catch (err2) {
callServerError(500, err2); callServerError(500, err2);
} }
} });
);
} }
} }
}; };
@ -464,15 +457,15 @@ function clientErrorHandler(err, socket) {
} sent invalid request.` } sent invalid request.`
); );
try { try {
head = fs.existsSync(`${config.wwwroot}/.head`) head = fs.existsSync("./.head")
? fs.readFileSync(`${config.wwwroot}/.head`).toString() ? fs.readFileSync("./.head").toString()
: fs.existsSync(`${config.wwwroot}/head.html`) : fs.existsSync("./head.html")
? fs.readFileSync(`${config.wwwroot}/head.html`).toString() ? fs.readFileSync("./head.html").toString()
: ""; // header : ""; // header
foot = fs.existsSync(`${config.wwwroot}/.foot`) foot = fs.existsSync("./.foot")
? fs.readFileSync(`${config.wwwroot}/.foot`).toString() ? fs.readFileSync("./.foot").toString()
: fs.existsSync(`${config.wwwroot}/foot.html`) : fs.existsSync("./foot.html")
? fs.readFileSync(`${config.wwwroot}/foot.html`).toString() ? fs.readFileSync("./foot.html").toString()
: ""; // footer : ""; // footer
if ( if (

View file

@ -32,9 +32,6 @@ function proxyHandler(req, socket, head) {
// SVR.JS configuration object (modified) // SVR.JS configuration object (modified)
const config = deepClone(process.serverConfig); const config = deepClone(process.serverConfig);
// Determine the webroot from the current working directory if it is not configured
if (config.wwwroot === undefined) config.wwwroot = process.cwd();
config.generateServerString = () => config.generateServerString = () =>
generateServerString(config.exposeServerVersion); generateServerString(config.exposeServerVersion);

View file

@ -37,9 +37,6 @@ function requestHandler(req, res) {
config.generateServerString = () => config.generateServerString = () =>
generateServerString(config.exposeServerVersion); generateServerString(config.exposeServerVersion);
// Determine the webroot from the current working directory if it is not configured
if (config.wwwroot === undefined) config.wwwroot = process.cwd();
// getCustomHeaders() in SVR.JS 3.x // getCustomHeaders() in SVR.JS 3.x
config.getCustomHeaders = () => { config.getCustomHeaders = () => {
let ph = Object.assign({}, config.customHeaders); let ph = Object.assign({}, config.customHeaders);
@ -348,14 +345,14 @@ function requestHandler(req, res) {
fs.access(config.page404, fs.constants.F_OK, (err) => { fs.access(config.page404, fs.constants.F_OK, (err) => {
if (err) { if (err) {
fs.access( fs.access(
config.wwwroot + "/." + errorCode.toString(), "." + errorCode.toString(),
fs.constants.F_OK, fs.constants.F_OK,
(err) => { (err) => {
try { try {
if (err) { if (err) {
callback(errorCode.toString() + ".html"); callback(errorCode.toString() + ".html");
} else { } else {
callback(config.wwwroot + "/." + errorCode.toString()); callback("." + errorCode.toString());
} }
} catch (err2) { } catch (err2) {
res.error(500, err2); res.error(500, err2);
@ -371,21 +368,17 @@ function requestHandler(req, res) {
} }
}); });
} else { } else {
fs.access( fs.access("." + errorCode.toString(), fs.constants.F_OK, (err) => {
config.wwwroot + "/." + errorCode.toString(),
fs.constants.F_OK,
(err) => {
try { try {
if (err) { if (err) {
callback(errorCode.toString() + ".html"); callback(errorCode.toString() + ".html");
} else { } else {
callback(config.wwwroot + "/." + errorCode.toString()); callback("." + errorCode.toString());
} }
} catch (err2) { } catch (err2) {
res.error(500, err2); res.error(500, err2);
} }
} });
);
} }
} }
}; };
@ -640,15 +633,15 @@ function requestHandler(req, res) {
}; };
try { try {
res.head = fs.existsSync(`${config.wwwroot}/.head`) res.head = fs.existsSync("./.head")
? fs.readFileSync(`${config.wwwroot}/.head`).toString() ? fs.readFileSync("./.head").toString()
: fs.existsSync(`${config.wwwroot}/head.html`) : fs.existsSync("./head.html")
? fs.readFileSync(`${config.wwwroot}/head.html`).toString() ? fs.readFileSync("./head.html").toString()
: ""; // header : ""; // header
res.foot = fs.existsSync(`${config.wwwroot}/.foot`) res.foot = fs.existsSync("./.foot")
? fs.readFileSync(`${config.wwwroot}/.foot`).toString() ? fs.readFileSync("./.foot").toString()
: fs.existsSync(`${config.wwwroot}/foot.html`) : fs.existsSync("./foot.html")
? fs.readFileSync(`${config.wwwroot}/foot.html`).toString() ? fs.readFileSync("./foot.html").toString()
: ""; // footer : ""; // footer
} catch (err) { } catch (err) {
res.error(500, err); res.error(500, err);

View file

@ -117,7 +117,7 @@ if (process.versions) process.versions.svrjs = version; // Inject SVR.JS into pr
function printUsage() { function printUsage() {
console.log(`${name} usage:`); console.log(`${name} usage:`);
console.log( console.log(
"node svr.js [-h] [--help] [-?] [/h] [/?] [--secure] [--reset] [--clean] [--disable-mods] [--single-threaded] [--stdout-notty] [--no-save-config] [-v] [--version]" "node svr.js [-h] [--help] [-?] [/h] [/?] [--secure] [--reset] [--clean] [--disable-mods] [--single-threaded] [-v] [--version]"
); );
console.log("-h -? /h /? --help -- Displays help"); console.log("-h -? /h /? --help -- Displays help");
console.log("--clean -- Cleans up files created by " + name); console.log("--clean -- Cleans up files created by " + name);
@ -127,18 +127,12 @@ function printUsage() {
console.log("--secure -- Runs HTTPS server"); console.log("--secure -- Runs HTTPS server");
console.log("--disable-mods -- Disables mods (safe mode)"); console.log("--disable-mods -- Disables mods (safe mode)");
console.log("--single-threaded -- Run single-threaded"); console.log("--single-threaded -- Run single-threaded");
console.log(
"--stdout-notty -- Enable stdout even when stdout is not a TTY. May decrease the performace"
);
console.log("--no-save-config -- Don't save configuration file");
console.log("-v --version -- Display server version"); console.log("-v --version -- Display server version");
} }
let exiting = false; let exiting = false;
let forceSecure = false; let forceSecure = false;
let disableMods = false; let disableMods = false;
let stdoutNoTTY = false;
let noSaveConfig = false;
// Handle command line arguments // Handle command line arguments
const args = process.argv; const args = process.argv;
@ -190,10 +184,6 @@ for (
disableMods = true; disableMods = true;
} else if (args[i] == "--single-threaded") { } else if (args[i] == "--single-threaded") {
process.singleThreaded = true; process.singleThreaded = true;
} else if (args[i] == "--stdout-notty") {
stdoutNoTTY = true;
} else if (args[i] == "--no-save-config") {
noSaveConfig = true;
} else { } else {
console.log(`Unrecognized argument: ${args[i]}`); console.log(`Unrecognized argument: ${args[i]}`);
printUsage(); printUsage();
@ -339,11 +329,6 @@ if (process.serverConfig.allowPostfixDoubleSlashes === undefined)
process.serverConfig.allowPostfixDoubleSlashes = false; process.serverConfig.allowPostfixDoubleSlashes = false;
if (process.serverConfig.optOutOfStatisticsServer === undefined) if (process.serverConfig.optOutOfStatisticsServer === undefined)
process.serverConfig.optOutOfStatisticsServer = false; process.serverConfig.optOutOfStatisticsServer = false;
if (process.serverConfig.disableConfigurationSaving === undefined)
process.serverConfig.disableConfigurationSaving = false;
// Don't save configuration if disableConfigurationSaving option is set to true
if (process.serverConfig.disableConfigurationSaving) noSaveConfig = true;
// Compatiblity for very old SVR.JS mods // Compatiblity for very old SVR.JS mods
process.serverConfig.version = version; process.serverConfig.version = version;
@ -400,7 +385,7 @@ try {
// Failed to get inspector URL // Failed to get inspector URL
} }
if (!stdoutNoTTY && !process.stdout.isTTY && !inspectorURL) { if (!process.stdout.isTTY && !inspectorURL) {
// When stdout is not a terminal and not attached to an Node.JS inspector, disable it to improve performance of SVR.JS // When stdout is not a terminal and not attached to an Node.JS inspector, disable it to improve performance of SVR.JS
console.log = () => {}; console.log = () => {};
process.stdout.write = () => {}; process.stdout.write = () => {};
@ -812,11 +797,7 @@ if (!disableMods) {
} }
// Determine path of server-side script file // Determine path of server-side script file
let SSJSPath = `${ let SSJSPath = "./serverSideScript.js";
process.serverConfig.wwwroot != undefined
? process.serverConfig.wwwroot
: process.dirname
}/serverSideScript.js`;
if (!process.serverConfig.useWebRootServerSideScript) if (!process.serverConfig.useWebRootServerSideScript)
SSJSPath = process.dirname + "/serverSideScript.js"; SSJSPath = process.dirname + "/serverSideScript.js";
@ -1705,8 +1686,6 @@ function saveConfig() {
configJSONobj.allowDoubleSlashes = false; configJSONobj.allowDoubleSlashes = false;
if (configJSONobj.optOutOfStatisticsServer === undefined) if (configJSONobj.optOutOfStatisticsServer === undefined)
configJSONobj.optOutOfStatisticsServer = false; configJSONobj.optOutOfStatisticsServer = false;
if (configJSONobj.disableConfigurationSaving === undefined)
configJSONobj.disableConfigurationSaving = false;
fs.writeFileSync( fs.writeFileSync(
process.dirname + "/config.json", process.dirname + "/config.json",
@ -1999,7 +1978,6 @@ function start(init) {
let workersToFork = 1; let workersToFork = 1;
if (cluster.isPrimary === undefined) { if (cluster.isPrimary === undefined) {
if (!noSaveConfig) {
setInterval(() => { setInterval(() => {
try { try {
saveConfig(); saveConfig();
@ -2008,9 +1986,7 @@ function start(init) {
throw new Error(err); throw new Error(err);
} }
}, 300000); }, 300000);
}
} else if (cluster.isPrimary) { } else if (cluster.isPrimary) {
if (!noSaveConfig) {
setInterval(() => { setInterval(() => {
let allWorkers = Object.keys(cluster.workers); let allWorkers = Object.keys(cluster.workers);
let goodWorkers = []; let goodWorkers = [];
@ -2066,7 +2042,6 @@ function start(init) {
}); });
}, 300000); }, 300000);
} }
}
if (!cluster.isPrimary && cluster.isPrimary !== undefined) { if (!cluster.isPrimary && cluster.isPrimary !== undefined) {
process.on("message", (line) => { process.on("message", (line) => {
@ -2454,7 +2429,7 @@ if (cluster.isPrimary || cluster.isPrimary === undefined) {
process.on("exit", (code) => { process.on("exit", (code) => {
try { try {
if (!configJSONRErr && !configJSONPErr && !noSaveConfig) { if (!configJSONRErr && !configJSONPErr) {
saveConfig(); saveConfig();
} }
} catch (err) { } catch (err) {

View file

@ -8,12 +8,8 @@ const {
} = require("../utils/forbiddenPaths.js"); } = require("../utils/forbiddenPaths.js");
const svrjsInfo = require("../../svrjs.json"); const svrjsInfo = require("../../svrjs.json");
const { name } = svrjsInfo; const { name } = svrjsInfo;
const wwwroot =
process.serverConfig && process.serverConfig.wwwroot !== undefined
? process.serverConfig.wwwroot
: ".";
forbiddenPaths.config = getInitializePath(`${wwwroot}/config.json`); forbiddenPaths.config = getInitializePath("./config.json");
forbiddenPaths.certificates = []; forbiddenPaths.certificates = [];
if (process.serverConfig.secure) { if (process.serverConfig.secure) {
forbiddenPaths.certificates.push( forbiddenPaths.certificates.push(
@ -30,8 +26,7 @@ if (process.serverConfig.secure) {
}); });
} }
forbiddenPaths.svrjs = getInitializePath( forbiddenPaths.svrjs = getInitializePath(
wwwroot + "./" +
"/" +
(process.dirname[process.dirname.length - 1] != "/" (process.dirname[process.dirname.length - 1] != "/"
? process.filename.replace(process.dirname + "/", "") ? process.filename.replace(process.dirname + "/", "")
: process.filename.replace(process.dirname, "")) : process.filename.replace(process.dirname, ""))
@ -41,18 +36,16 @@ if (process.serverConfig.useWebRootServerSideScript) {
forbiddenPaths.serverSideScripts.push("/serverSideScript.js"); forbiddenPaths.serverSideScripts.push("/serverSideScript.js");
} else { } else {
forbiddenPaths.serverSideScripts.push( forbiddenPaths.serverSideScripts.push(
getInitializePath(`${wwwroot}/serverSideScript.js`) getInitializePath("./serverSideScript.js")
); );
} }
forbiddenPaths.serverSideScriptDirectories = []; forbiddenPaths.serverSideScriptDirectories = [];
forbiddenPaths.serverSideScriptDirectories.push( forbiddenPaths.serverSideScriptDirectories.push(
getInitializePath(`${wwwroot}/node_modules`) getInitializePath("./node_modules")
); );
forbiddenPaths.serverSideScriptDirectories.push( forbiddenPaths.serverSideScriptDirectories.push(getInitializePath("./mods"));
getInitializePath(wwwroot + "/mods") forbiddenPaths.temp = getInitializePath("./temp");
); forbiddenPaths.log = getInitializePath("./log");
forbiddenPaths.temp = getInitializePath(`${wwwroot}/temp`);
forbiddenPaths.log = getInitializePath(`${wwwroot}/log`);
module.exports = (req, res, logFacilities, config, next) => { module.exports = (req, res, logFacilities, config, next) => {
let decodedHrefWithoutDuplicateSlashes = ""; let decodedHrefWithoutDuplicateSlashes = "";

View file

@ -9,9 +9,7 @@ module.exports = (req, res, logFacilities, config, next) => {
req.originalParsedURL.pathname[req.originalParsedURL.pathname.length - 1] != req.originalParsedURL.pathname[req.originalParsedURL.pathname.length - 1] !=
"/" "/"
) { ) {
fs.stat( fs.stat("." + decodeURIComponent(req.parsedURL.pathname), (err, stats) => {
config.wwwroot + decodeURIComponent(req.parsedURL.pathname),
(err, stats) => {
if (err || !stats.isDirectory()) { if (err || !stats.isDirectory()) {
try { try {
next(); next();
@ -26,8 +24,7 @@ module.exports = (req, res, logFacilities, config, next) => {
(req.parsedURL.hash ? req.parsedURL.hash : "") (req.parsedURL.hash ? req.parsedURL.hash : "")
); );
} }
} });
);
} else { } else {
next(); next();
} }

View file

@ -28,7 +28,7 @@ module.exports = (req, res, logFacilities, config, next) => {
!_fileState !_fileState
) { ) {
fs.stat( fs.stat(
config.wwwroot + decodeURIComponent(req.parsedURL.pathname), "." + decodeURIComponent(req.parsedURL.pathname),
(err, stats) => { (err, stats) => {
let _fileState = 3; let _fileState = 3;
if (err) { if (err) {

View file

@ -86,7 +86,7 @@ module.exports = (req, res, logFacilities, config, next) => {
res.error(400); res.error(400);
return; return;
} }
let readFrom = config.wwwroot + dHref; let readFrom = "." + dHref;
let dirImagesMissing = false; let dirImagesMissing = false;
fs.stat(readFrom, (err, stats) => { fs.stat(readFrom, (err, stats) => {
if (err) { if (err) {
@ -502,16 +502,13 @@ module.exports = (req, res, logFacilities, config, next) => {
const getCustomDirListingHeader = (callback) => { const getCustomDirListingHeader = (callback) => {
fs.readFile( fs.readFile(
(config.wwwroot + dHref + "/.dirhead").replace(/\/+/g, "/"), ("." + dHref + "/.dirhead").replace(/\/+/g, "/"),
(err, data) => { (err, data) => {
if (err) { if (err) {
if (err.code == "ENOENT" || err.code == "EISDIR") { if (err.code == "ENOENT" || err.code == "EISDIR") {
if (os.platform != "win32" || href != "/") { if (os.platform != "win32" || href != "/") {
fs.readFile( fs.readFile(
(config.wwwroot + dHref + "/HEAD.html").replace( ("." + dHref + "/HEAD.html").replace(/\/+/g, "/"),
/\/+/g,
"/"
),
(err, data) => { (err, data) => {
if (err) { if (err) {
if (err.code == "ENOENT" || err.code == "EISDIR") { if (err.code == "ENOENT" || err.code == "EISDIR") {
@ -541,16 +538,13 @@ module.exports = (req, res, logFacilities, config, next) => {
const getCustomDirListingFooter = (callback) => { const getCustomDirListingFooter = (callback) => {
fs.readFile( fs.readFile(
(config.wwwroot + dHref + "/.dirfoot").replace(/\/+/g, "/"), ("." + dHref + "/.dirfoot").replace(/\/+/g, "/"),
(err, data) => { (err, data) => {
if (err) { if (err) {
if (err.code == "ENOENT" || err.code == "EISDIR") { if (err.code == "ENOENT" || err.code == "EISDIR") {
if (os.platform != "win32" || href != "/") { if (os.platform != "win32" || href != "/") {
fs.readFile( fs.readFile(
(config.wwwroot + dHref + "/FOOT.html").replace( ("." + dHref + "/FOOT.html").replace(/\/+/g, "/"),
/\/+/g,
"/"
),
(err, data) => { (err, data) => {
if (err) { if (err) {
if (err.code == "ENOENT" || err.code == "EISDIR") { if (err.code == "ENOENT" || err.code == "EISDIR") {
@ -652,7 +646,7 @@ module.exports = (req, res, logFacilities, config, next) => {
if ( if (
fs.existsSync( fs.existsSync(
config.wwwroot + "." +
decodeURIComponent(href) + decodeURIComponent(href) +
"/.maindesc".replace(/\/+/g, "/") "/.maindesc".replace(/\/+/g, "/")
) )
@ -660,7 +654,7 @@ module.exports = (req, res, logFacilities, config, next) => {
htmlFoot = htmlFoot =
"</table><hr/>" + "</table><hr/>" +
fs.readFileSync( fs.readFileSync(
config.wwwroot + "." +
decodeURIComponent(href) + decodeURIComponent(href) +
"/.maindesc".replace(/\/+/g, "/") "/.maindesc".replace(/\/+/g, "/")
) + ) +

View file

@ -1,9 +1,9 @@
{ {
"version": "Nightly-GitNext", "version": "4.1.0",
"name": "SVR.JS", "name": "SVR.JS",
"documentationURL": "https://svrjs.org/docs", "documentationURL": "https://svrjs.org/docs",
"statisticsServerCollectEndpoint": "https://statistics.svrjs.org/collect.svr", "statisticsServerCollectEndpoint": "https://statistics.svrjs.org/collect.svr",
"changes": [ "changes": [
"INSERT CHANGES THERE" "Added experimental support for Deno 2."
] ]
} }

View file

@ -73,8 +73,7 @@
"disableTrailingSlashRedirects": false, "disableTrailingSlashRedirects": false,
"environmentVariables": {}, "environmentVariables": {},
"allowDoubleSlashes": false, "allowDoubleSlashes": false,
"optOutOfStatisticsServer": false, "optOutOfStatisticsServer": false
"disableConfigurationSaving": false
}</pre> }</pre>
</code> </code>
<p>Changes:</p> <p>Changes:</p>

View file

@ -1,8 +1,8 @@
const middleware = require("../../src/utils/ipBlockList.js"); const middleware = require("../../src/utils/ipBlockList.js");
const cluster = require("../../src/utils/clusterShim.js"); const cluster = require("../../src/utils/clusterBunShim.js");
jest.mock("../../src/utils/ipBlockList.js"); jest.mock("../../src/utils/ipBlockList.js");
jest.mock("../../src/utils/clusterShim.js"); jest.mock("../../src/utils/clusterBunShim.js");
const ipBlockListAdd = jest.fn(); const ipBlockListAdd = jest.fn();
const ipBlockListCheck = jest.fn(); const ipBlockListCheck = jest.fn();

View file

@ -2,13 +2,13 @@ const sha256 = require("../../src/utils/sha256.js");
const ipMatch = require("../../src/utils/ipMatch.js"); const ipMatch = require("../../src/utils/ipMatch.js");
const matchHostname = require("../../src/utils/matchHostname.js"); const matchHostname = require("../../src/utils/matchHostname.js");
const ipBlockList = require("../../src/utils/ipBlockList.js"); const ipBlockList = require("../../src/utils/ipBlockList.js");
const cluster = require("../../src/utils/clusterShim.js"); const cluster = require("../../src/utils/clusterBunShim.js");
jest.mock("../../src/utils/sha256.js"); jest.mock("../../src/utils/sha256.js");
jest.mock("../../src/utils/ipMatch.js"); jest.mock("../../src/utils/ipMatch.js");
jest.mock("../../src/utils/matchHostname.js"); jest.mock("../../src/utils/matchHostname.js");
jest.mock("../../src/utils/ipBlockList.js"); jest.mock("../../src/utils/ipBlockList.js");
jest.mock("../../src/utils/clusterShim.js"); jest.mock("../../src/utils/clusterBunShim.js");
let mockScryptHash = "mocked-scrypt-hash"; let mockScryptHash = "mocked-scrypt-hash";
let mockPbkdf2Hash = "mocked-pbkdf2-hash"; let mockPbkdf2Hash = "mocked-pbkdf2-hash";