diff --git a/pkgs/by-name/ho/hoarder/helpers/hoarder-cli b/pkgs/by-name/ho/hoarder/helpers/hoarder-cli new file mode 100755 index 000000000000..0a957eacaad9 --- /dev/null +++ b/pkgs/by-name/ho/hoarder/helpers/hoarder-cli @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -eu -o pipefail +HOARDER_LIB_PATH= +NODEJS= +exec "$NODEJS/bin/node" "$HOARDER_LIB_PATH/apps/cli/dist/index.mjs" "$@" diff --git a/pkgs/by-name/ho/hoarder/helpers/migrate b/pkgs/by-name/ho/hoarder/helpers/migrate new file mode 100755 index 000000000000..e11a50542340 --- /dev/null +++ b/pkgs/by-name/ho/hoarder/helpers/migrate @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -eu -o pipefail +HOARDER_LIB_PATH= +RELEASE= +NODE_ENV=production + +[[ -d "$DATA_DIR" ]] # Ensure DATA_DIR is defined and exists + +export RELEASE NODE_ENV +exec "$HOARDER_LIB_PATH/node_modules/.bin/tsx" "$HOARDER_LIB_PATH/packages/db/migrate.ts" "$@" diff --git a/pkgs/by-name/ho/hoarder/helpers/start-web b/pkgs/by-name/ho/hoarder/helpers/start-web new file mode 100755 index 000000000000..93c920f07a55 --- /dev/null +++ b/pkgs/by-name/ho/hoarder/helpers/start-web @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -eu -o pipefail +HOARDER_LIB_PATH= +RELEASE= +NODEJS= +NODE_ENV=production + +[[ -d "$DATA_DIR" ]] # Ensure DATA_DIR is defined and exists + +export RELEASE NODE_ENV +exec "$NODEJS/bin/node" "$HOARDER_LIB_PATH/apps/web/.next/standalone/apps/web/server.js" diff --git a/pkgs/by-name/ho/hoarder/helpers/start-workers b/pkgs/by-name/ho/hoarder/helpers/start-workers new file mode 100755 index 000000000000..5af794341bb5 --- /dev/null +++ b/pkgs/by-name/ho/hoarder/helpers/start-workers @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -eu -o pipefail +HOARDER_LIB_PATH= +RELEASE= +NODE_ENV=production +NODE_PATH="$HOARDER_LIB_PATH/apps/workers" + +[[ -d "$DATA_DIR" ]] # Ensure DATA_DIR is defined and exists + +export RELEASE NODE_ENV NODE_PATH +exec "$HOARDER_LIB_PATH/node_modules/.bin/tsx" "$HOARDER_LIB_PATH/apps/workers/index.ts" diff --git a/pkgs/by-name/ho/hoarder/package.nix b/pkgs/by-name/ho/hoarder/package.nix new file mode 100644 index 000000000000..9635eceec1e2 --- /dev/null +++ b/pkgs/by-name/ho/hoarder/package.nix @@ -0,0 +1,143 @@ +{ + lib, + stdenv, + fetchFromGitHub, + nodejs, + node-gyp, + inter, + python3, + srcOnly, + removeReferencesTo, + pnpm_9, +}: +let + pnpm = pnpm_9; +in +stdenv.mkDerivation (finalAttrs: { + pname = "hoarder"; + version = "0.21.0"; + + src = fetchFromGitHub { + owner = "hoarder-app"; + repo = "hoarder"; + tag = "v${finalAttrs.version}"; + hash = "sha256-3xgpiqq+BV0a/OlcQiGDt59fYNF+zP0+HPeBCRiZj48="; + }; + + patches = [ + ./patches/use-local-font.patch + ./patches/fix-migrations-path.patch + ./patches/dont-lock-pnpm-version.patch + ]; + postPatch = '' + ln -s ${inter}/share/fonts/truetype ./apps/landing/app/fonts + ln -s ${inter}/share/fonts/truetype ./apps/web/app/fonts + ''; + + nativeBuildInputs = [ + python3 + nodejs + node-gyp + pnpm.configHook + ]; + pnpmDeps = pnpm.fetchDeps { + inherit (finalAttrs) pname version; + + # We need to pass the patched source code, so pnpm sees the patched version + src = stdenv.mkDerivation { + name = "${finalAttrs.pname}-patched-source"; + phases = [ + "unpackPhase" + "patchPhase" + "installPhase" + ]; + src = finalAttrs.src; + patches = finalAttrs.patches; + installPhase = "cp -pr --reflink=auto -- . $out"; + }; + + hash = "sha256-U2wrjBhklP7c8S3QQoUtOPTYyJr7MBOwm0R/76FjhqE="; + }; + buildPhase = '' + runHook preBuild + + # Based on matrix-appservice-discord + pushd node_modules/better-sqlite3 + npm run build-release --offline "--nodedir=${srcOnly nodejs}" + find build -type f -exec ${removeReferencesTo}/bin/remove-references-to -t "${srcOnly nodejs}" {} \; + popd + + export CI=true + + echo "Compiling apps/web..." + pushd apps/web + pnpm run build + popd + + echo "Building apps/cli" + pushd apps/cli + pnpm run build + popd + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/share/doc/hoarder + cp README.md LICENSE $out/share/doc/hoarder + + # Copy necessary files into lib/hoarder while keeping the directory structure + LIB_TO_COPY="node_modules apps/web/.next/standalone apps/cli/dist apps/workers packages/db packages/shared packages/trpc" + HOARDER_LIB_PATH="$out/lib/hoarder" + for DIR in $LIB_TO_COPY; do + mkdir -p "$HOARDER_LIB_PATH/$DIR" + cp -a $DIR/{.,}* "$HOARDER_LIB_PATH/$DIR" + chmod -R u+w "$HOARDER_LIB_PATH/$DIR" + done + + # NextJS requires static files are copied in a specific way + # https://nextjs.org/docs/pages/api-reference/config/next-config-js/output#automatically-copying-traced-files + cp -r ./apps/web/public "$HOARDER_LIB_PATH/apps/web/.next/standalone/apps/web/" + cp -r ./apps/web/.next/static "$HOARDER_LIB_PATH/apps/web/.next/standalone/apps/web/.next/" + + # Copy and patch helper scripts + for HELPER_SCRIPT in ${./helpers}/*; do + HELPER_SCRIPT_NAME="$(basename "$HELPER_SCRIPT")" + cp "$HELPER_SCRIPT" "$HOARDER_LIB_PATH/" + substituteInPlace "$HOARDER_LIB_PATH/$HELPER_SCRIPT_NAME" \ + --replace-warn "HOARDER_LIB_PATH=" "HOARDER_LIB_PATH=$HOARDER_LIB_PATH" \ + --replace-warn "RELEASE=" "RELEASE=${finalAttrs.version}" \ + --replace-warn "NODEJS=" "NODEJS=${nodejs}" + chmod +x "$HOARDER_LIB_PATH/$HELPER_SCRIPT_NAME" + patchShebangs "$HOARDER_LIB_PATH/$HELPER_SCRIPT_NAME" + done + + # The cli should be in bin/ + mkdir -p $out/bin + mv "$HOARDER_LIB_PATH/hoarder-cli" $out/bin/ + + runHook postInstall + ''; + + fixupPhase = '' + runHook preFixup + + # Remove large dependencies that are not necessary during runtime + rm -rf $out/lib/hoarder/node_modules/{@next,next,@swc,react-native,monaco-editor,faker,@typescript-eslint,@microsoft,@typescript-eslint,pdfjs-dist} + + # Remove broken symlinks + find $out -type l ! -exec test -e {} \; -delete + + runHook postFixup + ''; + + meta = { + homepage = "https://github.com/hoarder-app/hoarder"; + description = "Self-hostable bookmark-everything app with a touch of AI for the data hoarders out there"; + license = lib.licenses.agpl3Only; + maintainers = [ lib.maintainers.three ]; + platforms = lib.platforms.linux; + }; +}) diff --git a/pkgs/by-name/ho/hoarder/patches/dont-lock-pnpm-version.patch b/pkgs/by-name/ho/hoarder/patches/dont-lock-pnpm-version.patch new file mode 100644 index 000000000000..5f56dff81d35 --- /dev/null +++ b/pkgs/by-name/ho/hoarder/patches/dont-lock-pnpm-version.patch @@ -0,0 +1,24 @@ +The Hoarder project uses a very specific version of pnpm (9.0.0-alpha.8) and +will fail to build with other pnpm versions. Instead of adding this pnpm +version to nixpkgs, we override this requirement and use the latest v9 release. + +--- +--- a/package.json ++++ b/package.json +@@ -33,7 +33,7 @@ + "turbo": "^2.1.2" + }, + "prettier": "@hoarder/prettier-config", +- "packageManager": "pnpm@9.0.0-alpha.8+sha256.a433a59569b00389a951352956faf25d1fdf43b568213fbde591c36274d4bc30", ++ "packageManager": "pnpm", + "pnpm": { + "patchedDependencies": { + "xcode@3.0.1": "patches/xcode@3.0.1.patch" +--- a/pnpm-lock.yaml ++++ b/pnpm-lock.yaml +@@ -1,4 +1,4 @@ +-lockfileVersion: '7.0' ++lockfileVersion: '9.0' + + settings: + autoInstallPeers: true diff --git a/pkgs/by-name/ho/hoarder/patches/fix-migrations-path.patch b/pkgs/by-name/ho/hoarder/patches/fix-migrations-path.patch new file mode 100644 index 000000000000..dfc49380b64d --- /dev/null +++ b/pkgs/by-name/ho/hoarder/patches/fix-migrations-path.patch @@ -0,0 +1,15 @@ +Without this change the migrations script will fail if the working directory +isn't the same directory this file is located in. To improve usability we +specify the migrations folder relative to __dirname, which doesn't depend on the +working directory. + +--- +--- a/packages/db/migrate.ts ++++ b/packages/db/migrate.ts +@@ -1,4 +1,5 @@ + import { db } from "./drizzle"; + import { migrate } from "drizzle-orm/better-sqlite3/migrator"; ++import path from "path"; + +-migrate(db, { migrationsFolder: "./drizzle" }); ++migrate(db, { migrationsFolder: path.join(__dirname, "./drizzle") }); diff --git a/pkgs/by-name/ho/hoarder/patches/use-local-font.patch b/pkgs/by-name/ho/hoarder/patches/use-local-font.patch new file mode 100644 index 000000000000..e1092cba3ac7 --- /dev/null +++ b/pkgs/by-name/ho/hoarder/patches/use-local-font.patch @@ -0,0 +1,47 @@ +Prevents NextJS from attempting to download fonts during build. The fonts +directory will be created in the derivation script. + +See similar patches: + pkgs/by-name/cr/crabfit-frontend/01-localfont.patch + pkgs/by-name/al/alcom/use-local-fonts.patch + pkgs/by-name/ne/nextjs-ollama-llm-ui/0002-use-local-google-fonts.patch + +--- +--- a/apps/landing/app/layout.tsx ++++ b/apps/landing/app/layout.tsx +@@ -1,11 +1,14 @@ + import type { Metadata } from "next"; +-import { Inter } from "next/font/google"; ++import localFont from 'next/font/local'; + + import "@hoarder/tailwind-config/globals.css"; + + import React from "react"; + +-const inter = Inter({ subsets: ["latin"] }); ++const inter = localFont({ ++ subsets: ["latin"], ++ src: "./fonts/InterVariable.ttf", ++}); + + export const metadata: Metadata = { + title: "Hoarder", +--- a/apps/web/app/layout.tsx ++++ b/apps/web/app/layout.tsx +@@ -1,5 +1,5 @@ + import type { Metadata } from "next"; +-import { Inter } from "next/font/google"; ++import localFont from 'next/font/local'; + + import "@hoarder/tailwind-config/globals.css"; + +@@ -13,7 +13,8 @@ + + import { clientConfig } from "@hoarder/shared/config"; + +-const inter = Inter({ ++const inter = localFont({ ++ src: "./fonts/InterVariable.ttf", + subsets: ["latin"], + fallback: ["sans-serif"], + });