commit cdfe2766168c3942aa8abbf906dbdf4f989badb7
parent 58cec8be9943c35f2a33e50d1d2fdb23ba1875d0
Author: mtmn <miro@haravara.org>
Date: Sat, 11 Apr 2026 15:14:48 +0200
chore: making builds work
Diffstat:
5 files changed, 107 insertions(+), 60 deletions(-)
diff --git a/Containerfile b/Containerfile
@@ -1,5 +1,5 @@
# docker.io/node:24-slim
-FROM docker.io/library/node@sha256:435f3537a088a01fd208bb629a4b69c28d85deb9a60af8a710cafc3befd6e3be as builder
+FROM docker.io/library/node@sha256:435f3537a088a01fd208bb629a4b69c28d85deb9a60af8a710cafc3befd6e3be AS builder
WORKDIR /app
@@ -8,36 +8,32 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
git \
libtinfo5 \
ca-certificates \
- python3 \
- make \
- g++ \
&& rm -rf /var/lib/apt/lists/*
COPY package.json package-lock.json ./
COPY spago.yaml spago.lock ./
COPY src ./src
+COPY assets ./assets
-RUN npm ci && \
+RUN npm ci --ignore-scripts && \
+ curl -fsSL https://npm.duckdb.org/duckdb/duckdb-v1.4.4-node-v137-linux-x64.tar.gz \
+ | tar -xz -C node_modules/duckdb/lib/binding --strip-components=1 && \
npx spago build --jobs 8 && \
npx esbuild output/Main/index.js --bundle --platform=node --format=esm --outfile=server.js --external:http --external:https --external:dotenv --external:url --external:duckdb --external:@aws-sdk/client-s3 && \
npx spago bundle --module Client --outfile client.js --platform browser
-# docker.io/node:25-slim
-FROM docker.io/library/node@sha256:435f3537a088a01fd208bb629a4b69c28d85deb9a60af8a710cafc3befd6e3be as builder
+FROM docker.io/library/node@sha256:435f3537a088a01fd208bb629a4b69c28d85deb9a60af8a710cafc3befd6e3be
WORKDIR /app
-RUN apt-get update && apt-get install -y --no-install-recommends \
- python3 \
- make \
- g++ \
- && rm -rf /var/lib/apt/lists/*
-
COPY package.json package-lock.json ./
-RUN npm ci --omit=dev
+RUN npm ci --omit=dev --ignore-scripts
+COPY --from=builder /app/node_modules/duckdb/lib/binding/duckdb.node \
+ ./node_modules/duckdb/lib/binding/duckdb.node
COPY --from=builder /app/server.js ./
COPY --from=builder /app/client.js ./
+COPY --from=builder /app/assets ./assets
RUN mkdir -p /app/data && chown -R node:node /app/data
diff --git a/flake.nix b/flake.nix
@@ -18,7 +18,69 @@
flake-utils.lib.eachDefaultSystem (
system: let
pkgs = nixpkgs.legacyPackages.${system};
- lib = pkgs.lib;
+
+ duckdbPrebuilt = pkgs.fetchurl {
+ url = "https://npm.duckdb.org/duckdb/duckdb-v1.4.4-node-v137-linux-x64.tar.gz";
+ hash = "sha256-Z91EJB81gRaZoLDjkw5lVVQ+jtGIvMV0tMJeOAY7Q3g=";
+ };
+
+ # Pinned registry + registry-index so the spago FOD is deterministic
+ spagoRegistry = pkgs.fetchFromGitHub {
+ owner = "purescript";
+ repo = "registry";
+ rev = "483aaf573663403afdabe20822ac88d565a65746";
+ hash = "sha256-pFVxQzt0+o1+nsCgk+VcprPSmEd8CH3Mkbk0vUy4x3g=";
+ };
+
+ spagoRegistryIndex = pkgs.fetchFromGitHub {
+ owner = "purescript";
+ repo = "registry-index";
+ rev = "77163eff5ea12e25d7391cf52fe5b9178145d843";
+ hash = "sha256-ez73ecGmzf5d7EkamNZ9KT8u7e4yR7jSvdiGu4bGAHs=";
+ };
+
+ # FOD: pre-fetch spago packages (needs network, but is now deterministic)
+ spagoDeps = pkgs.stdenv.mkDerivation {
+ name = "scorpus-spago-deps";
+
+ outputHashAlgo = "sha256";
+ outputHashMode = "recursive";
+ outputHash = "sha256-HCj4zn2E+UpeuMsmvvZe8d9nlkn1YF7vZ/j2I2Uoo20=";
+
+ nativeBuildInputs = with pkgs; [nodejs git cacert purescript];
+
+ dontUnpack = true;
+ dontFixup = true;
+
+ buildPhase = ''
+ export HOME=$TMPDIR
+ export SSL_CERT_FILE="${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
+ export NODE_EXTRA_CA_CERTS="${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
+
+ # Pre-populate registry so spago doesn't clone from GitHub
+ mkdir -p $HOME/.cache/spago-nodejs
+ cp -r ${spagoRegistry} $HOME/.cache/spago-nodejs/registry
+ cp -r ${spagoRegistryIndex} $HOME/.cache/spago-nodejs/registry-index
+ chmod -R u+w $HOME/.cache/spago-nodejs
+
+ cp ${self + "/package.json"} package.json
+ cp ${self + "/package-lock.json"} package-lock.json
+ cp ${self + "/spago.yaml"} spago.yaml
+ cp ${self + "/spago.lock"} spago.lock
+
+ npm ci --ignore-scripts
+ mkdir -p node_modules/.bin node_modules/purescript/bin
+ cp ${pkgs.purescript}/bin/purs node_modules/purescript/bin/purs
+ ln -sf ../purescript/bin/purs node_modules/.bin/purs
+ patchShebangs node_modules
+ npx spago install
+ '';
+
+ installPhase = ''
+ mkdir -p $out
+ cp -r .spago/p $out/packages
+ '';
+ };
scorpus = pkgs.buildNpmPackage {
pname = "scorpus";
@@ -26,42 +88,33 @@
src = self;
npmDepsHash = "sha256-L+9L3RY5CNLudmQL7EZwZO8x0kQ2MKCqSsn37ZIIKWE=";
+ npmRebuildFlags = ["--ignore-scripts"];
nativeBuildInputs = with pkgs; [
- purescript
- spago
- esbuild
makeWrapper
- python3
- pkg-config
nodejs
- # Native addon build dependencies
- gnumake
- stdenv.cc
- # DuckDB build dependencies
- duckdb
- # Remove duplicates
- ] ++ lib.optionals stdenv.isLinux [
- # Linux-specific build tools
- glibc
- # Other system dependencies that might be needed
+ git
+ purescript
];
buildPhase = ''
export HOME="$TMPDIR"
- # Node-gyp settings
- export npm_config_nodedir="${pkgs.nodejs}"
- export npm_config_python="${pkgs.python3}/bin/python"
- # C/C++ compiler settings
- export CC="${pkgs.stdenv.cc}/bin/cc"
- export CXX="${pkgs.stdenv.cc}/bin/c++"
- export LINK="${pkgs.stdenv.cc}/bin/cc"
- # Library paths
- export CFLAGS="-I${pkgs.duckdb}/include"
- export LDFLAGS="-L${pkgs.duckdb}/lib"
- # Enable multi-core building
- export npm_config_jobs="$NIX_BUILD_CORES"
-
+
+ # Place prebuilt duckdb native addon
+ mkdir -p node_modules/duckdb/lib/binding
+ tar -xf ${duckdbPrebuilt} -C node_modules/duckdb/lib/binding --strip-components=1
+
+ # Restore spago packages
+ mkdir -p .spago
+ cp -r ${spagoDeps}/packages .spago/p
+ chmod -R u+w .spago
+
+ # Provide pinned registry so spago finds package-sets
+ mkdir -p $HOME/.cache/spago-nodejs
+ cp -r ${spagoRegistry} $HOME/.cache/spago-nodejs/registry
+ cp -r ${spagoRegistryIndex} $HOME/.cache/spago-nodejs/registry-index
+ chmod -R u+w $HOME/.cache/spago-nodejs
+
npm run build
'';
@@ -96,11 +149,12 @@
"NODE_ENV=production"
];
};
- extraCommands = ''
- mkdir -p app/data
- chown -R 1000:1000 app
- chmod 700 app/data
+ fakeRootCommands = ''
+ mkdir -p /app/data
+ chown -R 1000:1000 /app
+ chmod 700 /app/data
'';
+ enableFakechroot = true;
};
devShells.default = pkgs.mkShell {
@@ -109,13 +163,7 @@
purescript
awscli2
duckdb
- spago
esbuild
- # Native addon build dependencies
- gnumake
- stdenv.cc
- python3
- pkg-config
];
};
}
diff --git a/justfile b/justfile
@@ -8,7 +8,7 @@ build:
nix build .
container:
- nix build .#oci
+ nix build .#container
load: container
podman load < result
diff --git a/package.json b/package.json
@@ -5,9 +5,9 @@
"main": "index.js",
"type": "module",
"scripts": {
- "build": "npx spago build && npx esbuild output/Main/index.js --bundle --platform=node --format=esm --outfile=server.js --external:http --external:https --external:dotenv --external:url --external:duckdb --external:@aws-sdk/client-s3 && npx spago bundle --module Client --outfile client.js --platform browser",
+ "build": "npx spago build && npx esbuild output/Main/index.js --bundle --platform=node --format=esm --footer:js='main();' --outfile=server.js --external:http --external:https --external:dotenv --external:url --external:duckdb --external:@aws-sdk/client-s3 && npx spago bundle --module Client --outfile client.js --platform browser",
"build-client": "npx spago bundle --module Client --outfile client.js --platform browser",
- "build-server": "npx esbuild output/Main/index.js --bundle --platform=node --format=esm --outfile=server.js --external:http --external:https --external:dotenv --external:url --external:duckdb --external:@aws-sdk/client-s3",
+ "build-server": "npx esbuild output/Main/index.js --bundle --platform=node --format=esm --footer:js='main();' --outfile=server.js --external:http --external:https --external:dotenv --external:url --external:duckdb --external:@aws-sdk/client-s3",
"test": "npx spago test",
"tidy": "purs-tidy format-in-place src/**/*.purs",
"serve": "node --no-deprecation server.js 2>&1 | tee server.log",
diff --git a/src/Main.purs b/src/Main.purs
@@ -614,9 +614,9 @@ serveNotFound res = do
void $ writeString w UTF8 "Not Found"
end w
-startServer :: Int -> Effect Unit
-startServer port = launchAff_ do
- conn <- connect "scorpus.db"
+startServer :: Int -> String -> Effect Unit
+startServer port dbFile = launchAff_ do
+ conn <- connect dbFile
initDb conn
void $ forkAff $ syncData conn
@@ -635,6 +635,9 @@ foreign import dotenvConfig :: Effect Unit
main :: Effect Unit
main = do
dotenvConfig
- startServer 8000
+ env <- getEnv
+ let port = fromMaybe 8000 (Object.lookup "PORT" env >>= fromString)
+ let dbFile = fromMaybe "scorpus.db" (Object.lookup "DATABASE_FILE" env)
+ startServer port dbFile
foreign import split :: String -> String -> Array String