From a7ebb3e1afef712f0977c89293a294f7216f8339 Mon Sep 17 00:00:00 2001 From: nichwall Date: Sun, 23 Aug 2026 15:34:08 -0700 Subject: [PATCH 01/11] Add: typescript compile step and update packaging --- .github/workflows/integration-test.yml | 6 ++-- .gitignore | 1 + Dockerfile | 5 +-- build/linuxpackager | 3 +- package-lock.json | 34 ++++++++++++++++--- package.json | 31 +++++++++-------- readme.md | 2 +- scripts/buildServer.js | 46 ++++++++++++++++++++++++++ tsconfig.server.json | 20 +++++++++++ 9 files changed, 123 insertions(+), 25 deletions(-) create mode 100644 scripts/buildServer.js create mode 100644 tsconfig.server.json diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 18c1d2dae..bf754b071 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -37,11 +37,11 @@ jobs: working-directory: client run: npm run generate - - name: get server dependencies - run: npm ci --only=production + - name: get server dependencies and compile server + run: npm ci && npm run build:server && npm prune --omit=dev - name: build binary - run: pkg -t node20-linux-x64 -o audiobookshelf . + run: pkg -t node20-linux-x64 -o audiobookshelf dist-server/index.js - name: run audiobookshelf run: | diff --git a/.gitignore b/.gitignore index 12ebec1c2..9ca683854 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ /client/.nuxt/ /client/dist/ /dist/ +/dist-server/ /deploy/ /coverage/ /.nyc_output/ diff --git a/Dockerfile b/Dockerfile index 816bdd3c3..8bff3201b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,6 +26,7 @@ RUN apk add --no-cache --update \ WORKDIR /server COPY index.js package* /server +COPY /scripts /server/scripts COPY /server /server/server RUN case "$TARGETPLATFORM" in \ @@ -38,7 +39,7 @@ RUN case "$TARGETPLATFORM" in \ unzip /tmp/library.zip -d $NUSQLITE3_DIR && \ rm /tmp/library.zip -RUN npm ci --only=production +RUN npm ci && npm run build:server && npm prune --omit=dev ### STAGE 2: Create minimal runtime image ### FROM node:20-alpine @@ -70,4 +71,4 @@ ENV NUSQLITE3_DIR=${NUSQLITE3_DIR} ENV NUSQLITE3_PATH=${NUSQLITE3_PATH} ENTRYPOINT ["tini", "--"] -CMD ["node", "index.js"] +CMD ["node", "dist-server/index.js"] diff --git a/build/linuxpackager b/build/linuxpackager index 52a9beba9..d3fbb8508 100755 --- a/build/linuxpackager +++ b/build/linuxpackager @@ -17,6 +17,7 @@ echo "--------------------" cd client rm -rf node_modules npm ci --unsafe-perm=true --allow-root +npm run build:server npm run generate cd .. @@ -48,7 +49,7 @@ Description: $DESCRIPTION" echo "$controlfile" > dist/debian/DEBIAN/control; # Package debian -pkg -t node20-linux-x64 -o dist/debian/usr/share/audiobookshelf/audiobookshelf . +pkg -t node20-linux-x64 -o dist/debian/usr/share/audiobookshelf/audiobookshelf dist-server/index.js fakeroot dpkg-deb -Zxz --build dist/debian diff --git a/package-lock.json b/package-lock.json index 22d966447..abc221fa5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,11 +34,13 @@ "audiobookshelf": "index.js" }, "devDependencies": { + "@types/node": "^20.17.0", "chai": "^4.3.10", "mocha": "^10.2.0", "nodemon": "^2.0.20", "nyc": "^15.1.0", - "sinon": "^17.0.1" + "sinon": "^17.0.1", + "typescript": "^5.7.3" } }, "node_modules/@ampproject/remapping": { @@ -697,9 +699,13 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } }, "node_modules/@types/validator": { "version": "13.7.17", @@ -5263,6 +5269,20 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -5280,6 +5300,12 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, "node_modules/unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", diff --git a/package.json b/package.json index bbdb473e9..ef6516292 100644 --- a/package.json +++ b/package.json @@ -3,33 +3,34 @@ "version": "2.36.0", "buildNumber": 1, "description": "Self-hosted audiobook and podcast server", - "main": "index.js", + "main": "dist-server/index.js", "scripts": { - "dev": "nodemon --watch server index.js -- --dev", - "start": "node index.js", - "start-dev": "node index.js --prod-with-dev-env", + "build:server": "node scripts/buildServer.js", + "dev": "nodemon --watch server --watch index.js --ext js,ts --exec \"npm run build:server && node dist-server/index.js\" -- --dev", + "start": "node dist-server/index.js", + "start-dev": "node dist-server/index.js --prod-with-dev-env", "client": "cd client && npm ci && npm run generate", - "prod": "npm run client && npm ci && node index.js", - "build-win": "npm run client && pkg -t node20-win-x64 -o ./dist/win/audiobookshelf -C GZip .", - "build-win-no-compress": "npm run client && pkg -t node20-win-x64 -o ./dist/win/audiobookshelf .", + "prod": "npm run client && npm ci && npm run build:server && npm run start", + "build-win": "npm run client && npm run build:server && pkg -t node20-win-x64 -o ./dist/win/audiobookshelf -C GZip dist-server/index.js", + "build-win-no-compress": "npm run client && npm run build:server && pkg -t node20-win-x64 -o ./dist/win/audiobookshelf dist-server/index.js", "build-linux": "build/linuxpackager", "docker": "docker buildx build --platform linux/amd64,linux/arm64 --push . -t advplyr/audiobookshelf", "docker-amd64-local": "docker buildx build --platform linux/amd64 --load . -t advplyr/audiobookshelf-amd64-local", "docker-arm64-local": "docker buildx build --platform linux/arm64 --load . -t advplyr/audiobookshelf-arm64-local", "deploy-linux": "node deploy/linux", - "test": "mocha", - "coverage": "nyc mocha" + "test": "npm run build:server && mocha dist-server/test", + "coverage": "npm run build:server && nyc mocha dist-server/test" }, - "bin": "index.js", + "bin": "dist-server/index.js", "pkg": { "assets": [ "client/dist/**/*", "node_modules/sqlite3/lib/binding/**/*.node", - "server/migrations/*.js" + "dist-server/server/migrations/*.js" ], "scripts": [ - "index.js", - "server/**/*.js" + "dist-server/index.js", + "dist-server/server/**/*.js" ] }, "mocha": { @@ -60,11 +61,13 @@ "xml2js": "^0.5.0" }, "devDependencies": { + "@types/node": "^20.17.0", "chai": "^4.3.10", "mocha": "^10.2.0", "nodemon": "^2.0.20", "nyc": "^15.1.0", - "sinon": "^17.0.1" + "sinon": "^17.0.1", + "typescript": "^5.7.3" }, "allowScripts": { "sqlite3@5.1.7": true diff --git a/readme.md b/readme.md index 16a346c55..00ae8ea1f 100644 --- a/readme.md +++ b/readme.md @@ -183,7 +183,7 @@ cd .. After setting up your development environment, either using the dev container or using your own custom environment, the following commands will help you run the server and client. -To run the server, you can use the command `npm run dev`. This will use the client that was built when you ran `npm run generate` in the client directory or when you started the dev container. If you make changes to the server, you will need to restart the server. If you make changes to the client, you will need to run the command `(cd client; npm run generate)` and then restart the server. By default the client runs at `localhost:3333`, though the port can be configured in `dev.js`. +To run the server, you can use the command `npm run dev`. This will compile the server and use the client that was built when you ran `npm run generate` in the client directory or when you started the dev container. Server changes are compiled and restarted automatically. If you make changes to the client, you will need to run the command `(cd client; npm run generate)` and then restart the server. By default the client runs at `localhost:3333`, though the port can be configured in `dev.js`. You can also build a version of the client that supports live reloading. To do this, start the server, then run the command `(cd client; npm run dev)`. This will run a separate instance of the client at `localhost:3000` that will be automatically updated as you make changes to the client. diff --git a/scripts/buildServer.js b/scripts/buildServer.js new file mode 100644 index 000000000..a8213c4a3 --- /dev/null +++ b/scripts/buildServer.js @@ -0,0 +1,46 @@ +const fs = require('fs') +const path = require('path') +const { spawnSync } = require('child_process') + +const projectRoot = path.resolve(__dirname, '..') +const outputDirectory = path.join(projectRoot, 'dist-server') + +fs.rmSync(outputDirectory, { recursive: true, force: true }) +fs.mkdirSync(outputDirectory, { recursive: true }) +fs.copyFileSync(path.join(projectRoot, 'package.json'), path.join(outputDirectory, 'package.json')) +fs.copyFileSync(path.join(projectRoot, 'index.js'), path.join(outputDirectory, 'index.js')) + +const devConfigPath = path.join(projectRoot, 'dev.js') +if (fs.existsSync(devConfigPath)) { + fs.copyFileSync(devConfigPath, path.join(outputDirectory, 'dev.js')) +} + +fs.cpSync(path.join(projectRoot, 'server'), path.join(outputDirectory, 'server'), { + recursive: true, + force: true +}) + +const testDirectory = path.join(projectRoot, 'test') +if (fs.existsSync(testDirectory)) { + fs.cpSync(testDirectory, path.join(outputDirectory, 'test'), { + recursive: true, + force: true + }) +} + +function hasTypeScriptSource(directory) { + for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { + const entryPath = path.join(directory, entry.name) + if (entry.isDirectory() && hasTypeScriptSource(entryPath)) return true + if (entry.isFile() && entry.name.endsWith('.ts')) return true + } + return false +} + +if (hasTypeScriptSource(path.join(projectRoot, 'server'))) { + const result = spawnSync(process.execPath, [require.resolve('typescript/bin/tsc'), '--project', 'tsconfig.server.json'], { + cwd: projectRoot, + stdio: 'inherit' + }) + process.exit(result.status || 0) +} diff --git a/tsconfig.server.json b/tsconfig.server.json new file mode 100644 index 000000000..212a26240 --- /dev/null +++ b/tsconfig.server.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": ".", + "outDir": "dist-server", + "strict": true, + "skipLibCheck": true, + "noEmitOnError": true + }, + "include": [ + "server/**/*.ts" + ], + "exclude": [ + "node_modules", + "dist-server", + "client" + ] +} From ec2738cb0f38d1a65dded0bf4828a1d9af37407d Mon Sep 17 00:00:00 2001 From: nichwall Date: Sun, 23 Aug 2026 15:49:15 -0700 Subject: [PATCH 02/11] Fix: linux packager building client as typescript --- build/linuxpackager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/linuxpackager b/build/linuxpackager index d3fbb8508..d5b18346d 100755 --- a/build/linuxpackager +++ b/build/linuxpackager @@ -17,7 +17,6 @@ echo "--------------------" cd client rm -rf node_modules npm ci --unsafe-perm=true --allow-root -npm run build:server npm run generate cd .. @@ -26,6 +25,7 @@ echo "--------------------" rm -rf node_modules npm ci --unsafe-perm=true --allow-root +npm run build:server echo ">>> Packaging" echo "--------------------" From 0571747fab10bb2b65b09c2f453dfe816c4bf67d Mon Sep 17 00:00:00 2001 From: nichwall Date: Sun, 23 Aug 2026 16:02:39 -0700 Subject: [PATCH 03/11] Remove deprecated npm ci flags --- build/linuxpackager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/linuxpackager b/build/linuxpackager index d5b18346d..58bbb1b6f 100755 --- a/build/linuxpackager +++ b/build/linuxpackager @@ -16,7 +16,7 @@ echo "--------------------" cd client rm -rf node_modules -npm ci --unsafe-perm=true --allow-root +npm ci npm run generate cd .. @@ -24,7 +24,7 @@ echo ">>> Building Server" echo "--------------------" rm -rf node_modules -npm ci --unsafe-perm=true --allow-root +npm ci npm run build:server echo ">>> Packaging" From d6398e54dd2546b409a37377690e492d6510dd93 Mon Sep 17 00:00:00 2001 From: nichwall Date: Thu, 27 Aug 2026 21:40:09 -0700 Subject: [PATCH 04/11] Fix: docker build --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8bff3201b..63f7ee0b2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ RUN apk add --no-cache --update \ unzip WORKDIR /server -COPY index.js package* /server +COPY index.js package* tsconfig.server.json /server COPY /scripts /server/scripts COPY /server /server/server @@ -39,7 +39,7 @@ RUN case "$TARGETPLATFORM" in \ unzip /tmp/library.zip -d $NUSQLITE3_DIR && \ rm /tmp/library.zip -RUN npm ci && npm run build:server && npm prune --omit=dev +RUN npm ci --include=dev && npm run build:server && npm prune --omit=dev ### STAGE 2: Create minimal runtime image ### FROM node:20-alpine From 198b2c27b8de3379a2d72045e58f8e60a0ee3ff8 Mon Sep 17 00:00:00 2001 From: nichwall Date: Thu, 27 Aug 2026 22:46:04 -0700 Subject: [PATCH 05/11] Remove test files from docker image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 63f7ee0b2..3f53713b2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,7 +39,7 @@ RUN case "$TARGETPLATFORM" in \ unzip /tmp/library.zip -d $NUSQLITE3_DIR && \ rm /tmp/library.zip -RUN npm ci --include=dev && npm run build:server && npm prune --omit=dev +RUN npm ci --include=dev && npm run build:server && npm prune --omit=dev && rm -rf dist-server/test ### STAGE 2: Create minimal runtime image ### FROM node:20-alpine From 65c075283c8159a1f88a17218645e2cb9685dd99 Mon Sep 17 00:00:00 2001 From: nichwall Date: Thu, 27 Aug 2026 23:30:22 -0700 Subject: [PATCH 06/11] Fix appRoot directory --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index ce0195e95..63c863966 100644 --- a/index.js +++ b/index.js @@ -16,7 +16,7 @@ const Path = require('path') process.env.NODE_ENV = options.dev ? 'development' : process.env.NODE_ENV || 'production' const server = require('./server/Server') -global.appRoot = __dirname +global.appRoot = Path.basename(__dirname) === 'dist-server' ? Path.resolve(__dirname, '..') : __dirname const isDev = process.env.NODE_ENV !== 'production' if (isDev || options['prod-with-dev-env']) { From 2440fb37c4c15b793de59096f339b6503518bc5e Mon Sep 17 00:00:00 2001 From: nichwall Date: Thu, 27 Aug 2026 23:42:06 -0700 Subject: [PATCH 07/11] Ensure client is included in packaging after directory change --- .github/workflows/integration-test.yml | 2 +- build/linuxpackager | 2 +- package.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index bf754b071..f0c40a58d 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -41,7 +41,7 @@ jobs: run: npm ci && npm run build:server && npm prune --omit=dev - name: build binary - run: pkg -t node20-linux-x64 -o audiobookshelf dist-server/index.js + run: pkg --config package.json -t node20-linux-x64 -o audiobookshelf dist-server/index.js - name: run audiobookshelf run: | diff --git a/build/linuxpackager b/build/linuxpackager index 58bbb1b6f..ddd53476e 100755 --- a/build/linuxpackager +++ b/build/linuxpackager @@ -49,7 +49,7 @@ Description: $DESCRIPTION" echo "$controlfile" > dist/debian/DEBIAN/control; # Package debian -pkg -t node20-linux-x64 -o dist/debian/usr/share/audiobookshelf/audiobookshelf dist-server/index.js +pkg --config package.json -t node20-linux-x64 -o dist/debian/usr/share/audiobookshelf/audiobookshelf dist-server/index.js fakeroot dpkg-deb -Zxz --build dist/debian diff --git a/package.json b/package.json index ef6516292..52a451842 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "start-dev": "node dist-server/index.js --prod-with-dev-env", "client": "cd client && npm ci && npm run generate", "prod": "npm run client && npm ci && npm run build:server && npm run start", - "build-win": "npm run client && npm run build:server && pkg -t node20-win-x64 -o ./dist/win/audiobookshelf -C GZip dist-server/index.js", - "build-win-no-compress": "npm run client && npm run build:server && pkg -t node20-win-x64 -o ./dist/win/audiobookshelf dist-server/index.js", + "build-win": "npm run client && npm run build:server && pkg --config package.json -t node20-win-x64 -o ./dist/win/audiobookshelf -C GZip dist-server/index.js", + "build-win-no-compress": "npm run client && npm run build:server && pkg --config package.json -t node20-win-x64 -o ./dist/win/audiobookshelf dist-server/index.js", "build-linux": "build/linuxpackager", "docker": "docker buildx build --platform linux/amd64,linux/arm64 --push . -t advplyr/audiobookshelf", "docker-amd64-local": "docker buildx build --platform linux/amd64 --load . -t advplyr/audiobookshelf-amd64-local", From fbfb24c264a50bed3d58f82ec4f2f68e2cc4e1af Mon Sep 17 00:00:00 2001 From: nichwall Date: Thu, 27 Aug 2026 23:53:57 -0700 Subject: [PATCH 08/11] Fix: new packaging warnings --- .../readableStream/internal/streams/lazy_transform.js | 2 +- server/libs/watcher/types.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/lazy_transform.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/lazy_transform.js index 06073b0d1..afcb0c071 100644 --- a/server/libs/archiver/archiverUtils/readableStream/internal/streams/lazy_transform.js +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/lazy_transform.js @@ -7,7 +7,7 @@ const { ObjectDefineProperties, ObjectDefineProperty, ObjectSetPrototypeOf } = r const stream = require('../../stream') -const { getDefaultEncoding } = require('../crypto/util') +const getDefaultEncoding = () => 'buffer' module.exports = LazyTransform diff --git a/server/libs/watcher/types.js b/server/libs/watcher/types.js index 682b3f45f..cb0db20b6 100644 --- a/server/libs/watcher/types.js +++ b/server/libs/watcher/types.js @@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WatcherStats = exports.Stats = void 0; -const ripstat_1 = require("ripstat"); +const ripstat_1 = require("./ripstat"); Object.defineProperty(exports, "Stats", { enumerable: true, get: function () { return ripstat_1.Stats; } }); const watcher_stats_1 = __importDefault(require("./watcher_stats")); exports.WatcherStats = watcher_stats_1.default; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLFlBQVk7Ozs7OztBQUdaLHFDQUE4QjtBQWlGbUUsc0ZBakZ6RixlQUFLLE9BaUZ5RjtBQTlFdEcsb0VBQTJDO0FBOEUwSyx1QkE5RTlNLHVCQUFZLENBOEU4TSJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLFlBQVk7Ozs7OztBQUdaLHFDQUE4QjtBQWlGbUUsc0ZBakZ6RixlQUFLLE9BaUZ5RjtBQTlFdEcsb0VBQTJDO0FBOEUwSyx1QkE5RTlNLHVCQUFZLENBOEU4TSJ9 From b67cbffbf9839961e30b588bbd13edd5532f80f9 Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 17 Sep 2026 16:54:31 -0500 Subject: [PATCH 09/11] Update tsconfig to use allowJs to skip buildServer.js step --- index.js | 4 +--- package-lock.json | 2 +- package.json | 4 ++-- tsconfig.server.json | 18 +++++++++--------- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/index.js b/index.js index 63c863966..7c42e30ae 100644 --- a/index.js +++ b/index.js @@ -32,9 +32,7 @@ if (isDev || options['prod-with-dev-env']) { if (devEnv.BackupPath) process.env.BACKUP_PATH = devEnv.BackupPath if (devEnv.ReactClientPath) process.env.REACT_CLIENT_PATH = devEnv.ReactClientPath if (devEnv.AllowedDevOrigins) { - process.env.ALLOWED_DEV_ORIGINS = Array.isArray(devEnv.AllowedDevOrigins) - ? devEnv.AllowedDevOrigins.join(',') - : String(devEnv.AllowedDevOrigins) + process.env.ALLOWED_DEV_ORIGINS = Array.isArray(devEnv.AllowedDevOrigins) ? devEnv.AllowedDevOrigins.join(',') : String(devEnv.AllowedDevOrigins) } process.env.SOURCE = 'local' process.env.ROUTER_BASE_PATH = devEnv.RouterBasePath ?? '/audiobookshelf' diff --git a/package-lock.json b/package-lock.json index abc221fa5..88d03072a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "xml2js": "^0.5.0" }, "bin": { - "audiobookshelf": "index.js" + "audiobookshelf": "dist-server/index.js" }, "devDependencies": { "@types/node": "^20.17.0", diff --git a/package.json b/package.json index 52a451842..3b6b44d5f 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "description": "Self-hosted audiobook and podcast server", "main": "dist-server/index.js", "scripts": { - "build:server": "node scripts/buildServer.js", - "dev": "nodemon --watch server --watch index.js --ext js,ts --exec \"npm run build:server && node dist-server/index.js\" -- --dev", + "build:server": "tsc -p tsconfig.server.json", + "dev": "nodemon --watch server --watch index.js --watch test --watch dev.js --ext js,ts --exec \"npm run build:server && node dist-server/index.js\" -- --dev", "start": "node dist-server/index.js", "start-dev": "node dist-server/index.js --prod-with-dev-env", "client": "cd client && npm ci && npm run generate", diff --git a/tsconfig.server.json b/tsconfig.server.json index 212a26240..a3c6ce5c8 100644 --- a/tsconfig.server.json +++ b/tsconfig.server.json @@ -5,16 +5,16 @@ "moduleResolution": "node", "rootDir": ".", "outDir": "dist-server", + "allowJs": true, + "resolveJsonModule": true, + "esModuleInterop": true, "strict": true, "skipLibCheck": true, - "noEmitOnError": true + "noEmitOnError": true, + "incremental": true, + "tsBuildInfoFile": "dist-server/.tsbuildinfo", + "forceConsistentCasingInFileNames": true }, - "include": [ - "server/**/*.ts" - ], - "exclude": [ - "node_modules", - "dist-server", - "client" - ] + "include": ["index.js", "dev.js", "server/**/*.js", "server/**/*.ts", "test/**/*.js", "test/**/*.ts"], + "exclude": ["node_modules", "dist-server", "client", "**/*.d.ts"] } From 3c5d191c3319f8d8c5102d5e03f693773e316dc9 Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 17 Sep 2026 16:57:58 -0500 Subject: [PATCH 10/11] Fix MigrationManager undefined var --- test/server/managers/MigrationManager.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/server/managers/MigrationManager.test.js b/test/server/managers/MigrationManager.test.js index af2e9da8f..9ffd649ae 100644 --- a/test/server/managers/MigrationManager.test.js +++ b/test/server/managers/MigrationManager.test.js @@ -17,6 +17,7 @@ describe('MigrationManager', () => { let fsMoveStub let fsRemoveStub let fsEnsureDirStub + let fsPathExistsStub let processExitStub let configPath = '/path/to/config' From 99e2c454822383a1f88f030355e255c1f173b604 Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 17 Sep 2026 17:09:00 -0500 Subject: [PATCH 11/11] Remove buildServer and update docker and workflows --- .github/workflows/docker-build.yml | 2 ++ .github/workflows/integration-test.yml | 1 + Dockerfile | 3 +- scripts/buildServer.js | 46 -------------------------- 4 files changed, 4 insertions(+), 48 deletions(-) delete mode 100644 scripts/buildServer.js diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index fdb57fbc5..5ade98b91 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -19,6 +19,8 @@ on: - server/** - index.js - package.json + - tsconfig.server.json + - Dockerfile jobs: build: diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index f0c40a58d..beadc7f28 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -12,6 +12,7 @@ on: - test/** - index.js - package.json + - tsconfig.server.json jobs: build: diff --git a/Dockerfile b/Dockerfile index 3f53713b2..14005f25c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,6 @@ RUN apk add --no-cache --update \ WORKDIR /server COPY index.js package* tsconfig.server.json /server -COPY /scripts /server/scripts COPY /server /server/server RUN case "$TARGETPLATFORM" in \ @@ -39,7 +38,7 @@ RUN case "$TARGETPLATFORM" in \ unzip /tmp/library.zip -d $NUSQLITE3_DIR && \ rm /tmp/library.zip -RUN npm ci --include=dev && npm run build:server && npm prune --omit=dev && rm -rf dist-server/test +RUN npm ci --include=dev && npm run build:server && npm prune --omit=dev ### STAGE 2: Create minimal runtime image ### FROM node:20-alpine diff --git a/scripts/buildServer.js b/scripts/buildServer.js deleted file mode 100644 index a8213c4a3..000000000 --- a/scripts/buildServer.js +++ /dev/null @@ -1,46 +0,0 @@ -const fs = require('fs') -const path = require('path') -const { spawnSync } = require('child_process') - -const projectRoot = path.resolve(__dirname, '..') -const outputDirectory = path.join(projectRoot, 'dist-server') - -fs.rmSync(outputDirectory, { recursive: true, force: true }) -fs.mkdirSync(outputDirectory, { recursive: true }) -fs.copyFileSync(path.join(projectRoot, 'package.json'), path.join(outputDirectory, 'package.json')) -fs.copyFileSync(path.join(projectRoot, 'index.js'), path.join(outputDirectory, 'index.js')) - -const devConfigPath = path.join(projectRoot, 'dev.js') -if (fs.existsSync(devConfigPath)) { - fs.copyFileSync(devConfigPath, path.join(outputDirectory, 'dev.js')) -} - -fs.cpSync(path.join(projectRoot, 'server'), path.join(outputDirectory, 'server'), { - recursive: true, - force: true -}) - -const testDirectory = path.join(projectRoot, 'test') -if (fs.existsSync(testDirectory)) { - fs.cpSync(testDirectory, path.join(outputDirectory, 'test'), { - recursive: true, - force: true - }) -} - -function hasTypeScriptSource(directory) { - for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { - const entryPath = path.join(directory, entry.name) - if (entry.isDirectory() && hasTypeScriptSource(entryPath)) return true - if (entry.isFile() && entry.name.endsWith('.ts')) return true - } - return false -} - -if (hasTypeScriptSource(path.join(projectRoot, 'server'))) { - const result = spawnSync(process.execPath, [require.resolve('typescript/bin/tsc'), '--project', 'tsconfig.server.json'], { - cwd: projectRoot, - stdio: 'inherit' - }) - process.exit(result.status || 0) -}