build: 🏗️ Make Nix build great again

This commit is contained in:
Jesse Wierzbinski 2025-04-14 16:51:00 +02:00
parent 1679585c4c
commit 5a4ce29206
No known key found for this signature in database
13 changed files with 6773 additions and 194 deletions

4
app.ts
View file

@ -27,7 +27,7 @@ import { routes } from "./routes.ts";
import type { ApiRouteExports, HonoEnv } from "./types/api.ts"; import type { ApiRouteExports, HonoEnv } from "./types/api.ts";
// Extends Zod with OpenAPI schema generation // Extends Zod with OpenAPI schema generation
import "zod-openapi/extend"; import "zod-openapi/extend";
import { cwd } from "node:process"; import { cwdFromEntrypoint } from "@/lib.ts";
export const appFactory = async (): Promise<Hono<HonoEnv>> => { export const appFactory = async (): Promise<Hono<HonoEnv>> => {
await configureLoggers(); await configureLoggers();
@ -122,7 +122,7 @@ export const appFactory = async (): Promise<Hono<HonoEnv>> => {
const loader = new PluginLoader(); const loader = new PluginLoader();
const plugins = await loader.loadPlugins( const plugins = await loader.loadPlugins(
join(cwd(), "plugins"), join(cwdFromEntrypoint(), "plugins"),
config.plugins?.autoload ?? true, config.plugins?.autoload ?? true,
config.plugins?.overrides.enabled, config.plugins?.overrides.enabled,
config.plugins?.overrides.disabled, config.plugins?.overrides.disabled,

View file

@ -47,15 +47,15 @@ await $`mkdir -p dist/node_modules`;
// Copy Sharp to dist // Copy Sharp to dist
await $`mkdir -p dist/node_modules/@img`; await $`mkdir -p dist/node_modules/@img`;
await $`cp -r node_modules/@img/sharp-libvips-linuxmusl-* dist/node_modules/@img`; await $`cp -rL node_modules/@img/sharp-libvips-linux* dist/node_modules/@img`;
await $`cp -r node_modules/@img/sharp-linuxmusl-* dist/node_modules/@img`; await $`cp -rL node_modules/@img/sharp-linux* dist/node_modules/@img`;
// Copy acorn to dist // Copy acorn to dist
await $`cp -r node_modules/acorn dist/node_modules/acorn`; await $`cp -rL node_modules/acorn dist/node_modules/acorn`;
// Copy bull-board to dist // Copy bull-board to dist
await $`mkdir -p dist/node_modules/@bull-board`; await $`mkdir -p dist/node_modules/@bull-board`;
await $`cp -r node_modules/@bull-board/ui dist/node_modules/@bull-board/ui`; await $`cp -rL node_modules/@bull-board/ui dist/node_modules/@bull-board/ui`;
// Copy the Bee Movie script from pages // Copy the Bee Movie script from pages
await $`cp beemovie.txt dist/beemovie.txt`; await $`cp beemovie.txt dist/beemovie.txt`;

View file

@ -1,4 +1,3 @@
import { cwd } from "node:process";
import { type BunFile, env, file } from "bun"; import { type BunFile, env, file } from "bun";
import ISO6391 from "iso-639-1"; import ISO6391 from "iso-639-1";
import { types as mimeTypes } from "mime-types"; import { types as mimeTypes } from "mime-types";
@ -6,6 +5,7 @@ import { generateVAPIDKeys } from "web-push";
import { z } from "zod"; import { z } from "zod";
import { ZodError } from "zod"; import { ZodError } from "zod";
import { fromZodError } from "zod-validation-error"; import { fromZodError } from "zod-validation-error";
import { cwdFromEntrypoint } from "@/lib.ts";
import { ProxiableUrl } from "~/classes/media/url.ts"; import { ProxiableUrl } from "~/classes/media/url.ts";
import { RolePermission } from "~/packages/client/schemas/permissions.ts"; import { RolePermission } from "~/packages/client/schemas/permissions.ts";
@ -402,7 +402,9 @@ export const ConfigSchema = z
}), }),
frontend: z.strictObject({ frontend: z.strictObject({
enabled: z.boolean().default(true), enabled: z.boolean().default(true),
path: z.string().default(env.VERSIA_FRONTEND_PATH || cwd()), path: z
.string()
.default(env.VERSIA_FRONTEND_PATH || cwdFromEntrypoint()),
routes: z.strictObject({ routes: z.strictObject({
home: urlPath.default("/"), home: urlPath.default("/"),
login: urlPath.default("/oauth/authorize"), login: urlPath.default("/oauth/authorize"),

View file

@ -1,29 +1,15 @@
{ {
"nodes": { "nodes": {
"flake-compat": {
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"revCount": 57,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"
}
},
"flake-utils": { "flake-utils": {
"inputs": { "inputs": {
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1710146030, "lastModified": 1731533236,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -34,11 +20,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1724395761, "lastModified": 1744536153,
"narHash": "sha256-zRkDV/nbrnp3Y8oCADf5ETl1sDrdmAW6/bBVJ8EbIdQ=", "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "ae815cee91b417be55d43781eb4b73ae1ecc396c", "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -50,7 +36,6 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
} }

View file

@ -3,55 +3,30 @@
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz";
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
}; };
nixConfig = { outputs = {
extra-substituters = [ self,
"https://cache.kyouma.net" nixpkgs,
]; flake-utils,
extra-trusted-public-keys = [ ...
"cache.kyouma.net:Frjwu4q1rnwE/MnSTmX9yx86GNA/z3p/oElGvucLiZg=" }:
]; {
}; overlays.default = final: prev: {
versia-server = final.callPackage ./nix/package.nix {};
outputs = { self, nixpkgs, flake-utils, ... }: {
hydraJobs = {
inherit (self) packages;
};
overlays.default = final: prev: {
versiajs = final.callPackage ./nix/package.nix {};
};
} //
flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" ] (system: let
pkgs = import nixpkgs {
inherit system;
overlays = [ self.overlays.default ];
};
in {
packages = {
inherit (pkgs) versiajs;
default = self.packages.${system}.versiajs;
};
apps.update-modules = {
type = "app";
program = ./nix/update.sh;
};
}) //
flake-utils.lib.eachDefaultSystem (system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells = {
default = pkgs.mkShell {
buildInputs = with pkgs; [
bun
nodejs
nodePackages.typescript
nodePackages.typescript-language-server
nix-ld
];
}; };
}; }
}); // flake-utils.lib.eachSystem ["x86_64-linux" "aarch64-linux"] (system: let
pkgs = import nixpkgs {
inherit system;
overlays = [self.overlays.default];
};
in {
packages = {
inherit (pkgs) versia-server;
default = self.packages.${system}.versia-server;
};
});
} }

View file

@ -1,9 +1,11 @@
diff --git a/build.ts b/build.ts diff --git a/build.ts b/build.ts
index 3b3ebe9..9531121 100644 index a4ad17b2..516b55bf 100644
--- a/build.ts --- a/build.ts
+++ b/build.ts +++ b/build.ts
@@ -1,10 +1,10 @@ @@ -1,12 +1,12 @@
import { readdir } from "node:fs/promises";
import { $ } from "bun"; import { $ } from "bun";
import { build } from "bun";
-import ora from "ora"; -import ora from "ora";
+// import ora from "ora"; +// import ora from "ora";
import { routes } from "~/routes"; import { routes } from "~/routes";
@ -11,23 +13,22 @@ index 3b3ebe9..9531121 100644
-const buildSpinner = ora("Building").start(); -const buildSpinner = ora("Building").start();
+// const buildSpinner = ora("Building").start(); +// const buildSpinner = ora("Building").start();
-await $`rm -rf dist && mkdir dist`; await $`rm -rf dist && mkdir dist`;
+// await $`rm -rf dist && mkdir dist`;
await Bun.build({ // Get all directories under the plugins/ directory
entrypoints: [ const pluginDirs = await readdir("plugins", { withFileTypes: true });
@@ -25,7 +25,7 @@ await Bun.build({ @@ -31,7 +31,7 @@ await build({
} external: ["acorn", "@bull-board/ui"],
}); });
-buildSpinner.text = "Transforming"; -buildSpinner.text = "Transforming";
+// buildSpinner.text = "Transforming"; +// buildSpinner.text = "Transforming";
// Copy Drizzle migrations to dist // Fix Bun incorrectly transforming aliased imports
await $`cp -r drizzle dist/drizzle`; await $`sed -i 's/var serveStatic = (options) => {/var serveStaticBase = (options) => {/g' dist/*.js`;
@@ -49,4 +49,4 @@ await $`cp package.json dist/package.json`; @@ -63,4 +63,4 @@ await $`cp beemovie.txt dist/beemovie.txt`;
// Copy cli/theme.json // Copy package.json
await $`cp cli/theme.json dist/cli/theme.json`; await $`cp package.json dist/package.json`;
-buildSpinner.stop(); -buildSpinner.stop();
+// buildSpinner.stop(); +// buildSpinner.stop();

View file

@ -1,97 +1,88 @@
{ {
lib, lib,
stdenv, stdenv,
pnpm,
bun, bun,
callPackage, nodejs,
modulesSrc ? callPackage ./source.nix {}, vips,
nodePackages_latest, makeWrapper,
makeBinaryWrapper, }: let
}: packageJson = builtins.fromJSON (builtins.readFile ../package.json);
in
stdenv.mkDerivation (finalAttrs: {
pname = packageJson.name;
version = packageJson.version;
assert lib.assertMsg ( src = ../.;
with builtins; hashFile "sha256" ../bun.lockb == hashFile "sha256" "${modulesSrc.src}/bun.lockb" patches = [./fix-build-spinner.patch];
) "bun.lockb has changed. Please run 'nix run .#apps.x86_64-linux.update-modules'";
stdenv.mkDerivation (finalAttrs: { # Fixes the build script mv usage
pname = "versiajs"; pnpmInstallFlags = ["--shamefully-hoist"];
version = "0.7.0";
src = ../.; pnpmDeps = pnpm.fetchDeps {
inherit (finalAttrs) pname version src pnpmInstallFlags;
hash = "sha256-As7RBxTWgk8HlWr4/xn2j3rqf3N7r0VvFGMbMHjyCKA=";
};
versiajsModules = stdenv.mkDerivation (modulesAttrs: { nativeBuildInputs = [
pname = "${finalAttrs.pname}-modules"; pnpm
pnpm.configHook
bun
nodejs
makeWrapper
];
inherit (finalAttrs) version; buildInputs = [
vips
src = modulesSrc.src; ];
nativeBuildInputs = with nodePackages_latest; [ bun nodejs typescript ];
dontConfigure = true;
buildPhase = '' buildPhase = ''
bun install --production --no-progress --ignore-scripts --frozen-lockfile runHook preBuild
bun run build
runHook postBuild
''; '';
installPhase = '' installPhase = let
mkdir -p $out/node_modules libPath = lib.makeLibraryPath [
cp -r node_modules $out vips
stdenv.cc.cc.lib
];
binPath = lib.makeBinPath [
bun
];
in ''
runHook preInstall
mkdir -p $out
cp -r dist $out/${finalAttrs.pname}
makeWrapper ${lib.getExe bun} $out/bin/${finalAttrs.pname} \
--add-flags "run $out/${finalAttrs.pname}/index.js" \
--set NODE_PATH $out/${finalAttrs.pname}/node_modules \
--prefix PATH : ${binPath} \
--prefix LD_LIBRARY_PATH : ${libPath}
runHook postInstall
''; '';
dontFixup = true; meta = with lib; {
description = packageJson.description;
outputHash = modulesSrc.outputHash.${stdenv.system}; homepage = packageJson.homepage;
outputHashMode = "recursive"; license = licenses.agpl3Only;
}); maintainers = [
{
nativeBuildInputs = [ bun ]; name = "CPlusPatch";
email = "contact@cpluspatch.com";
buildInputs = [ bun nodePackages_latest.nodejs makeBinaryWrapper ]; github = "CPlusPatch";
githubId = 42910258;
patches = [ ./fix-build-spinner.patch ]; matrix = "@jesse:cpluspatch.dev";
}
configurePhase = '' ];
runHook preConfigure platforms = ["x86_64-linux" "aarch64-linux"];
mainProgram = finalAttrs.pname;
cp -r ${finalAttrs.versiajsModules}/node_modules . };
})
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
bun run build
runHook postBuild
'';
installPhase = ''
runHook preInstall
cp -r dist/ $out
mkdir -p $out/bin
makeBinaryWrapper ${bun}/bin/bun $out/bin/versiajs \
--prefix PATH : ${lib.makeBinPath [ bun ]} \
--set NODE_ENV "production" \
--add-flags "run --prefer-offline --no-install --cwd $out $out/index.js"
makeBinaryWrapper ${bun}/bin/bun $out/bin/versiajs-cli \
--prefix PATH : ${lib.makeBinPath [ bun ]} \
--add-flags "run --prefer-offline --no-install --cwd $out $out/cli/index.js"
runHook postInstall
'';
passthru.updateScript = ./update.sh;
meta = {
description = "A new federated server written with TypeScript and Bun ";
homepage = "https://versia.pub";
license = with lib.licenses; [ agpl3Plus ];
maintainers = with lib.maintainers; [ snaki ];
platforms = [ "x86_64-linux" "aarch64-linux" ];
};
})

View file

@ -1,13 +0,0 @@
{
lib,
fetchFromGitHub,
}: {
outputHash.x86_64-linux = lib.fakeHash;
outputHash.aarch64-linux = lib.fakeHash;
src = fetchFromGitHub {
owner = "versia-pub";
repo = "server";
rev = "fbb845f7f8ee97e51ff57edba3817224341d3078";
hash = "sha256-pc5t6z/AE+NPZEzXxTlzT76jq5PF7Mvjh94A0NCBDh8=";
};
}

View file

@ -3,7 +3,8 @@
"module": "index.ts", "module": "index.ts",
"type": "module", "type": "module",
"version": "0.8.0-alpha", "version": "0.8.0-alpha",
"description": "A project to build a federated social network", "description": "Powerful, configurable and modular federated server using the Versia Protocol.",
"homepage": "https://versia.pub",
"author": { "author": {
"email": "contact@cpluspatch.com", "email": "contact@cpluspatch.com",
"name": "Jesse Wierzbinski", "name": "Jesse Wierzbinski",

6615
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load diff

12
pnpm-workspace.yaml Normal file
View file

@ -0,0 +1,12 @@
packages:
- packages/*
onlyBuiltDependencies:
- esbuild
- msgpackr-extract
- sharp
patchedDependencies:
giget@2.0.0: patches/giget@2.0.0.patch
shamefullyHoist: true

View file

@ -1,15 +1,18 @@
import { join } from "node:path"; import { join } from "node:path";
import { cwd } from "node:process";
import { FileSystemRouter } from "bun"; import { FileSystemRouter } from "bun";
import { cwdFromEntrypoint } from "@/lib.ts";
// Returns the route filesystem path when given a URL // Returns the route filesystem path when given a URL
export const routeMatcher = new FileSystemRouter({ export const routeMatcher = new FileSystemRouter({
style: "nextjs", style: "nextjs",
dir: `${cwd()}/api`, dir: `${cwdFromEntrypoint()}/api`,
fileExtensions: [".ts", ".js"], fileExtensions: [".ts", ".js"],
}); });
export const routes = Object.fromEntries( export const routes = Object.fromEntries(
Object.entries(routeMatcher.routes) Object.entries(routeMatcher.routes)
.filter(([route]) => !route.endsWith(".test")) .filter(([route]) => !route.endsWith(".test"))
.map(([route, path]) => [route, path.replace(join(cwd()), ".")]), .map(([route, path]) => [
route,
path.replace(join(cwdFromEntrypoint()), "."),
]),
) as Record<string, string>; ) as Record<string, string>;

View file

@ -1,3 +1,6 @@
import { dirname } from "node:path";
import { main } from "bun";
type ElementWithId = { id: string }; type ElementWithId = { id: string };
export const mergeAndDeduplicate = <T extends ElementWithId>( export const mergeAndDeduplicate = <T extends ElementWithId>(
@ -9,3 +12,7 @@ export const mergeAndDeduplicate = <T extends ElementWithId>(
(element, index, self) => (element, index, self) =>
index === self.findIndex((t) => t.id === element.id), index === self.findIndex((t) => t.id === element.id),
); );
export const cwdFromEntrypoint = (): string => {
return dirname(main);
};