mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2026-03-13 22:12:54 +03:00
fix(nix): enable sandboxed builds with bun2nix (#199)
* fix(nix): enable sandboxed builds with bun2nix The Nix package was broken on Linux because `bun install` requires network access, which is blocked by Nix sandboxing (enabled by default on Linux). This switches to bun2nix for dependency management: - Add bun2nix flake input to pre-fetch all npm dependencies - Generate bun.nix lockfile for reproducible dependency resolution - Copy bun cache to writable location during build to avoid EACCES errors from bunx writing to the read-only Nix store - Add nanoid as an explicit dependency (was imported directly but only available as a transitive dep, which breaks with isolated linker) - Update CI workflow to perform a full sandboxed build - Add bun2nix to devShell for easy lockfile regeneration Closes #197 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(nix): create writable workdir for database access The app uses process.cwd()/data for the database path, but when running from the Nix store the cwd is read-only. Create a writable working directory with symlinks to app files and a real data directory. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
12
.github/workflows/nix-build.yml
vendored
12
.github/workflows/nix-build.yml
vendored
@@ -33,13 +33,5 @@ jobs:
|
|||||||
- name: Show flake info
|
- name: Show flake info
|
||||||
run: nix flake show
|
run: nix flake show
|
||||||
|
|
||||||
- name: Evaluate package
|
- name: Build package
|
||||||
run: |
|
run: nix build --print-build-logs
|
||||||
# Evaluate the derivation without building (validates the Nix expression)
|
|
||||||
nix eval .#packages.$(nix eval --impure --expr 'builtins.currentSystem').default.name
|
|
||||||
echo "Flake evaluation successful"
|
|
||||||
|
|
||||||
# Note: Full build requires network access for bun install.
|
|
||||||
# Nix sandboxed builds block network access.
|
|
||||||
# To build locally: nix build --option sandbox false
|
|
||||||
# Or use: nix develop && bun install && bun run build
|
|
||||||
|
|||||||
133
bun.lock
133
bun.lock
@@ -5,74 +5,75 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "gitea-mirror",
|
"name": "gitea-mirror",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/check": "latest",
|
"@astrojs/check": "^0.9.6",
|
||||||
"@astrojs/mdx": "latest",
|
"@astrojs/mdx": "4.3.13",
|
||||||
"@astrojs/node": "latest",
|
"@astrojs/node": "9.5.4",
|
||||||
"@astrojs/react": "latest",
|
"@astrojs/react": "^4.4.2",
|
||||||
"@better-auth/sso": "latest",
|
"@better-auth/sso": "1.4.19",
|
||||||
"@octokit/plugin-throttling": "latest",
|
"@octokit/plugin-throttling": "^11.0.3",
|
||||||
"@octokit/rest": "latest",
|
"@octokit/rest": "^22.0.1",
|
||||||
"@radix-ui/react-accordion": "latest",
|
"@radix-ui/react-accordion": "^1.2.12",
|
||||||
"@radix-ui/react-avatar": "latest",
|
"@radix-ui/react-avatar": "^1.1.11",
|
||||||
"@radix-ui/react-checkbox": "latest",
|
"@radix-ui/react-checkbox": "^1.3.3",
|
||||||
"@radix-ui/react-collapsible": "latest",
|
"@radix-ui/react-collapsible": "^1.1.12",
|
||||||
"@radix-ui/react-dialog": "latest",
|
"@radix-ui/react-dialog": "^1.1.15",
|
||||||
"@radix-ui/react-dropdown-menu": "latest",
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
||||||
"@radix-ui/react-hover-card": "latest",
|
"@radix-ui/react-hover-card": "^1.1.15",
|
||||||
"@radix-ui/react-label": "latest",
|
"@radix-ui/react-label": "^2.1.8",
|
||||||
"@radix-ui/react-popover": "latest",
|
"@radix-ui/react-popover": "^1.1.15",
|
||||||
"@radix-ui/react-progress": "latest",
|
"@radix-ui/react-progress": "^1.1.8",
|
||||||
"@radix-ui/react-radio-group": "latest",
|
"@radix-ui/react-radio-group": "^1.3.8",
|
||||||
"@radix-ui/react-scroll-area": "latest",
|
"@radix-ui/react-scroll-area": "^1.2.10",
|
||||||
"@radix-ui/react-select": "latest",
|
"@radix-ui/react-select": "^2.2.6",
|
||||||
"@radix-ui/react-separator": "latest",
|
"@radix-ui/react-separator": "^1.1.8",
|
||||||
"@radix-ui/react-slot": "latest",
|
"@radix-ui/react-slot": "^1.2.4",
|
||||||
"@radix-ui/react-switch": "latest",
|
"@radix-ui/react-switch": "^1.2.6",
|
||||||
"@radix-ui/react-tabs": "latest",
|
"@radix-ui/react-tabs": "^1.1.13",
|
||||||
"@radix-ui/react-tooltip": "latest",
|
"@radix-ui/react-tooltip": "^1.2.8",
|
||||||
"@tailwindcss/vite": "latest",
|
"@tailwindcss/vite": "^4.2.1",
|
||||||
"@tanstack/react-virtual": "latest",
|
"@tanstack/react-virtual": "^3.13.19",
|
||||||
"@types/canvas-confetti": "latest",
|
"@types/canvas-confetti": "^1.9.0",
|
||||||
"@types/react": "latest",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "latest",
|
"@types/react-dom": "^19.2.3",
|
||||||
"astro": "latest",
|
"astro": "^5.17.3",
|
||||||
"bcryptjs": "latest",
|
"bcryptjs": "^3.0.3",
|
||||||
"better-auth": "latest",
|
"better-auth": "1.4.19",
|
||||||
"buffer": "latest",
|
"buffer": "^6.0.3",
|
||||||
"canvas-confetti": "latest",
|
"canvas-confetti": "^1.9.4",
|
||||||
"class-variance-authority": "latest",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "latest",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "latest",
|
"cmdk": "^1.1.1",
|
||||||
"dotenv": "latest",
|
"dotenv": "^17.3.1",
|
||||||
"drizzle-orm": "latest",
|
"drizzle-orm": "^0.45.1",
|
||||||
"fuse.js": "latest",
|
"fuse.js": "^7.1.0",
|
||||||
"jsonwebtoken": "latest",
|
"jsonwebtoken": "^9.0.3",
|
||||||
"lucide-react": "latest",
|
"lucide-react": "^0.575.0",
|
||||||
"next-themes": "latest",
|
"nanoid": "^3.3.11",
|
||||||
"react": "latest",
|
"next-themes": "^0.4.6",
|
||||||
"react-dom": "latest",
|
"react": "^19.2.4",
|
||||||
"react-icons": "latest",
|
"react-dom": "^19.2.4",
|
||||||
"sonner": "latest",
|
"react-icons": "^5.5.0",
|
||||||
"tailwind-merge": "latest",
|
"sonner": "^2.0.7",
|
||||||
"tailwindcss": "latest",
|
"tailwind-merge": "^3.5.0",
|
||||||
"tw-animate-css": "latest",
|
"tailwindcss": "^4.2.1",
|
||||||
"typescript": "latest",
|
"tw-animate-css": "^1.4.0",
|
||||||
"uuid": "latest",
|
"typescript": "^5.9.3",
|
||||||
"vaul": "latest",
|
"uuid": "^13.0.0",
|
||||||
"zod": "latest",
|
"vaul": "^1.1.2",
|
||||||
|
"zod": "^4.3.6",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@testing-library/jest-dom": "latest",
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
"@testing-library/react": "latest",
|
"@testing-library/react": "^16.3.2",
|
||||||
"@types/bcryptjs": "latest",
|
"@types/bcryptjs": "^3.0.0",
|
||||||
"@types/bun": "latest",
|
"@types/bun": "^1.3.9",
|
||||||
"@types/jsonwebtoken": "latest",
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
"@types/uuid": "latest",
|
"@types/uuid": "^11.0.0",
|
||||||
"@vitejs/plugin-react": "latest",
|
"@vitejs/plugin-react": "^5.1.4",
|
||||||
"drizzle-kit": "latest",
|
"drizzle-kit": "^0.31.9",
|
||||||
"jsdom": "latest",
|
"jsdom": "^28.1.0",
|
||||||
"tsx": "latest",
|
"tsx": "^4.21.0",
|
||||||
"vitest": "latest",
|
"vitest": "^4.0.18",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
111
flake.lock
generated
111
flake.lock
generated
@@ -1,8 +1,50 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"bun2nix": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-parts": "flake-parts",
|
||||||
|
"import-tree": "import-tree",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": "systems",
|
||||||
|
"treefmt-nix": "treefmt-nix"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1770895533,
|
||||||
|
"narHash": "sha256-v3QaK9ugy9bN9RXDnjw0i2OifKmz2NnKM82agtqm/UY=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "bun2nix",
|
||||||
|
"rev": "c843f477b15f51151f8c6bcc886954699440a6e1",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "bun2nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1769996383,
|
||||||
|
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems"
|
"systems": "systems_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1731533236,
|
"lastModified": 1731533236,
|
||||||
@@ -18,6 +60,21 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"import-tree": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1763762820,
|
||||||
|
"narHash": "sha256-ZvYKbFib3AEwiNMLsejb/CWs/OL/srFQ8AogkebEPF0=",
|
||||||
|
"owner": "vic",
|
||||||
|
"repo": "import-tree",
|
||||||
|
"rev": "3c23749d8013ec6daa1d7255057590e9ca726646",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "vic",
|
||||||
|
"repo": "import-tree",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1761672384,
|
"lastModified": 1761672384,
|
||||||
@@ -34,8 +91,24 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs-lib": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1769909678,
|
||||||
|
"narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"rev": "72716169fe93074c333e8d0173151350670b824c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"bun2nix": "bun2nix",
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
}
|
}
|
||||||
@@ -54,6 +127,42 @@
|
|||||||
"repo": "default",
|
"repo": "default",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"treefmt-nix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"bun2nix",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1770228511,
|
||||||
|
"narHash": "sha256-wQ6NJSuFqAEmIg2VMnLdCnUc0b7vslUohqqGGD+Fyxk=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"rev": "337a4fe074be1042a35086f15481d763b8ddc0e7",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|||||||
76
flake.nix
76
flake.nix
@@ -1,18 +1,32 @@
|
|||||||
{
|
{
|
||||||
description = "Gitea Mirror - Self-hosted GitHub to Gitea mirroring service";
|
description = "Gitea Mirror - Self-hosted GitHub to Gitea mirroring service";
|
||||||
|
|
||||||
|
nixConfig = {
|
||||||
|
extra-substituters = [
|
||||||
|
"https://nix-community.cachix.org"
|
||||||
|
];
|
||||||
|
extra-trusted-public-keys = [
|
||||||
|
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
bun2nix = {
|
||||||
|
url = "github:nix-community/bun2nix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, flake-utils }:
|
outputs = { self, nixpkgs, flake-utils, bun2nix }:
|
||||||
let
|
let
|
||||||
forEachSystem = flake-utils.lib.eachDefaultSystem;
|
forEachSystem = flake-utils.lib.eachDefaultSystem;
|
||||||
in
|
in
|
||||||
(forEachSystem (system:
|
(forEachSystem (system:
|
||||||
let
|
let
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
b2n = bun2nix.packages.${system}.default;
|
||||||
|
|
||||||
# Build the application
|
# Build the application
|
||||||
gitea-mirror = pkgs.stdenv.mkDerivation {
|
gitea-mirror = pkgs.stdenv.mkDerivation {
|
||||||
@@ -21,8 +35,9 @@
|
|||||||
|
|
||||||
src = ./.;
|
src = ./.;
|
||||||
|
|
||||||
nativeBuildInputs = with pkgs; [
|
nativeBuildInputs = [
|
||||||
bun
|
pkgs.bun
|
||||||
|
b2n.hook
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
@@ -30,21 +45,40 @@
|
|||||||
openssl
|
openssl
|
||||||
];
|
];
|
||||||
|
|
||||||
configurePhase = ''
|
bunDeps = b2n.fetchBunDeps {
|
||||||
export HOME=$TMPDIR
|
bunNix = ./bun.nix;
|
||||||
export BUN_INSTALL=$TMPDIR/.bun
|
};
|
||||||
export PATH=$BUN_INSTALL/bin:$PATH
|
|
||||||
'';
|
# Let the bun2nix hook handle dependency installation via the
|
||||||
|
# pre-fetched cache, but skip its default build/check/install
|
||||||
|
# phases since we have custom ones.
|
||||||
|
dontUseBunBuild = true;
|
||||||
|
dontUseBunCheck = true;
|
||||||
|
dontUseBunInstall = true;
|
||||||
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
# Install dependencies
|
runHook preBuild
|
||||||
bun install --frozen-lockfile --no-progress
|
export HOME=$TMPDIR
|
||||||
|
|
||||||
# Build the application
|
# The bun2nix cache is in the read-only Nix store, but bunx/astro
|
||||||
|
# may try to write to it at build time. Copy the cache to a
|
||||||
|
# writable location.
|
||||||
|
if [ -n "$BUN_INSTALL_CACHE_DIR" ] && [ -d "$BUN_INSTALL_CACHE_DIR" ]; then
|
||||||
|
WRITABLE_CACHE="$TMPDIR/bun-cache"
|
||||||
|
cp -rL "$BUN_INSTALL_CACHE_DIR" "$WRITABLE_CACHE" 2>/dev/null || true
|
||||||
|
chmod -R u+w "$WRITABLE_CACHE" 2>/dev/null || true
|
||||||
|
export BUN_INSTALL_CACHE_DIR="$WRITABLE_CACHE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the Astro application
|
||||||
bun run build
|
bun run build
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
'';
|
'';
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
mkdir -p $out/lib/gitea-mirror
|
mkdir -p $out/lib/gitea-mirror
|
||||||
mkdir -p $out/bin
|
mkdir -p $out/bin
|
||||||
|
|
||||||
@@ -82,7 +116,18 @@ export MIRROR_PULL_REQUEST_CONCURRENCY=''${MIRROR_PULL_REQUEST_CONCURRENCY:-5}
|
|||||||
# Create data directory
|
# Create data directory
|
||||||
mkdir -p "$DATA_DIR"
|
mkdir -p "$DATA_DIR"
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
cd "$SCRIPT_DIR/../lib/gitea-mirror"
|
APP_DIR="$SCRIPT_DIR/../lib/gitea-mirror"
|
||||||
|
|
||||||
|
# The app uses process.cwd()/data for the database, but the Nix store
|
||||||
|
# is read-only. Create a writable working directory with symlinks to
|
||||||
|
# the app files and a real data directory.
|
||||||
|
WORK_DIR="$DATA_DIR/.workdir"
|
||||||
|
mkdir -p "$WORK_DIR"
|
||||||
|
for item in dist node_modules scripts src drizzle package.json tsconfig.json; do
|
||||||
|
ln -sfn "$APP_DIR/$item" "$WORK_DIR/$item"
|
||||||
|
done
|
||||||
|
ln -sfn "$DATA_DIR" "$WORK_DIR/data"
|
||||||
|
cd "$WORK_DIR"
|
||||||
|
|
||||||
# === AUTO-GENERATE SECRETS ===
|
# === AUTO-GENERATE SECRETS ===
|
||||||
BETTER_AUTH_SECRET_FILE="$DATA_DIR/.better_auth_secret"
|
BETTER_AUTH_SECRET_FILE="$DATA_DIR/.better_auth_secret"
|
||||||
@@ -185,6 +230,8 @@ cd "$SCRIPT_DIR/../lib/gitea-mirror"
|
|||||||
exec ${pkgs.bun}/bin/bun scripts/manage-db.ts "$@"
|
exec ${pkgs.bun}/bin/bun scripts/manage-db.ts "$@"
|
||||||
EOF
|
EOF
|
||||||
chmod +x $out/bin/gitea-mirror-db
|
chmod +x $out/bin/gitea-mirror-db
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = with pkgs.lib; {
|
meta = with pkgs.lib; {
|
||||||
@@ -209,6 +256,7 @@ EOF
|
|||||||
bun
|
bun
|
||||||
sqlite
|
sqlite
|
||||||
openssl
|
openssl
|
||||||
|
b2n
|
||||||
];
|
];
|
||||||
|
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
@@ -219,6 +267,10 @@ EOF
|
|||||||
echo " bun run dev # Start development server"
|
echo " bun run dev # Start development server"
|
||||||
echo " bun run build # Build for production"
|
echo " bun run build # Build for production"
|
||||||
echo ""
|
echo ""
|
||||||
|
echo "Nix packaging:"
|
||||||
|
echo " bun2nix -o bun.nix # Regenerate bun.nix after dependency changes"
|
||||||
|
echo " nix build # Build the package"
|
||||||
|
echo ""
|
||||||
echo "Database:"
|
echo "Database:"
|
||||||
echo " bun run manage-db init # Initialize database"
|
echo " bun run manage-db init # Initialize database"
|
||||||
echo " bun run db:studio # Open Drizzle Studio"
|
echo " bun run db:studio # Open Drizzle Studio"
|
||||||
|
|||||||
@@ -75,8 +75,8 @@
|
|||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"astro": "^5.17.3",
|
"astro": "^5.17.3",
|
||||||
"bcryptjs": "^3.0.3",
|
"bcryptjs": "^3.0.3",
|
||||||
"buffer": "^6.0.3",
|
|
||||||
"better-auth": "1.4.19",
|
"better-auth": "1.4.19",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
"canvas-confetti": "^1.9.4",
|
"canvas-confetti": "^1.9.4",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
@@ -86,6 +86,7 @@
|
|||||||
"fuse.js": "^7.1.0",
|
"fuse.js": "^7.1.0",
|
||||||
"jsonwebtoken": "^9.0.3",
|
"jsonwebtoken": "^9.0.3",
|
||||||
"lucide-react": "^0.575.0",
|
"lucide-react": "^0.575.0",
|
||||||
|
"nanoid": "^3.3.11",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^19.2.4",
|
"react-dom": "^19.2.4",
|
||||||
|
|||||||
Reference in New Issue
Block a user