From 8c924ed54f3e9d414ff6287be2c0eed1f16edf43 Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 2 Oct 2025 12:19:51 -0700 Subject: [PATCH] Migrate postgres --- ...e-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa | 2 +- ...5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc | 12 +- flake.nix | 1 - hindki/.env.example | 17 +- hindki/.gitignore | 6 + hindki/Dockerfile | 3 +- hindki/astro.config.mjs | 33 +- hindki/drizzle.config.ts | 5 +- hindki/drizzle/0000_bouncy_demogoblin.sql | 43 +++ hindki/drizzle/0000_charming_screwball.sql | 42 --- hindki/drizzle/0001_shallow_sasquatch.sql | 13 - hindki/drizzle/meta/0000_snapshot.json | 163 +++++----- hindki/drizzle/meta/0001_snapshot.json | 292 ------------------ hindki/drizzle/meta/_journal.json | 15 +- hindki/package-lock.json | 63 +++- hindki/package.json | 7 +- hindki/scripts/migrate-sqlite-to-postgres.ts | 109 +++++++ hindki/src/lib/db/index.ts | 16 +- hindki/src/lib/db/schema.ts | 34 +- package-lock.json | 164 ++++++++++ package.json | 7 + 21 files changed, 548 insertions(+), 499 deletions(-) create mode 100644 hindki/drizzle/0000_bouncy_demogoblin.sql delete mode 100644 hindki/drizzle/0000_charming_screwball.sql delete mode 100644 hindki/drizzle/0001_shallow_sasquatch.sql delete mode 100644 hindki/drizzle/meta/0001_snapshot.json create mode 100644 hindki/scripts/migrate-sqlite-to-postgres.ts create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa b/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa index a6aafbe..8b1a608 120000 --- a/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa +++ b/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa @@ -1 +1 @@ -/nix/store/gsxc3lz58zr7pdvvlihz39pqhidnh7aq-nix-shell-env \ No newline at end of file +/nix/store/2l63479bllklr4bzi4vscn7ndj6lg614-nix-shell-env \ No newline at end of file diff --git a/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc b/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc index 45f832d..0eb7027 100644 --- a/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc +++ b/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc @@ -15,7 +15,7 @@ export CONFIG_SHELL CXX='g++' export CXX HOSTTYPE='x86_64' -HOST_PATH='/nix/store/ddx7976jyll30xjbasghv9jailswprcp-bash-interactive-5.3p3/bin:/nix/store/q1zaii9cirbfpmwr7d86hpppql3kjcpf-git-2.51.0/bin:/nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev/bin:/nix/store/r4557ald6zn4dzmvgh8na9vwnwzgrjgc-nodejs-22.19.0/bin:/nix/store/967gn7p1p47ic924r2fx4rgbfp49fhsy-pnpm-10.15.1/bin:/nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/bin:/nix/store/jq2kbdw6ljv9i47jz23pm072cfyxwpfj-postgresql-17.6/bin:/nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/bin:/nix/store/1p5n2mzy33ayzc1scdnz82h53d192knh-claude-code-1.0.117/bin:/nix/store/gmwaym3dwkrb9987z8xg4njl2kmm2dvc-sqlite-3.50.2-bin/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l964krgbp613d5jxga2vy5qdssj7zfzj-findutils-4.10.0/bin:/nix/store/s2fvny566vls74p4qm9v3fdqd741fh3f-diffutils-3.12/bin:/nix/store/pmhkmqy0vxk47r6ndh0azybhf6gs6k25-gnused-4.9/bin:/nix/store/vlckk0vnmawq9wwh7ndkrwxlpv4h29yh-gnugrep-3.12/bin:/nix/store/03nvbw411p097h6yxjghc33rbcrjfb9d-gawk-5.3.2/bin:/nix/store/8av8pfs7bnyc6hqj764ns4z1fnr9bva1-gnutar-1.35/bin:/nix/store/8gsxxh82rf957ffbsk0q9670nhvl5lia-gzip-1.14/bin:/nix/store/6yjb3zdj448rm8qsmpiq3f67kvj5683a-bzip2-1.0.8-bin/bin:/nix/store/aqdvlkh0jdwkc22hh5vr9sl6qlw5ha74-gnumake-4.4.1/bin:/nix/store/q7sqwn7i6w2b67adw0bmix29pxg85x3w-bash-5.3p3/bin:/nix/store/856i1ajaci3kmmp15rifacfz3jvn5l3q-patch-2.8/bin:/nix/store/y9kgzp85ykrhd7l691w4djx121qygy68-xz-5.8.1-bin/bin:/nix/store/v40ijzz8p2fpk9ihjck3a1ncqaqfmn3c-file-5.45/bin' +HOST_PATH='/nix/store/ddx7976jyll30xjbasghv9jailswprcp-bash-interactive-5.3p3/bin:/nix/store/q1zaii9cirbfpmwr7d86hpppql3kjcpf-git-2.51.0/bin:/nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev/bin:/nix/store/r4557ald6zn4dzmvgh8na9vwnwzgrjgc-nodejs-22.19.0/bin:/nix/store/967gn7p1p47ic924r2fx4rgbfp49fhsy-pnpm-10.15.1/bin:/nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/bin:/nix/store/jq2kbdw6ljv9i47jz23pm072cfyxwpfj-postgresql-17.6/bin:/nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/bin:/nix/store/1p5n2mzy33ayzc1scdnz82h53d192knh-claude-code-1.0.117/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l964krgbp613d5jxga2vy5qdssj7zfzj-findutils-4.10.0/bin:/nix/store/s2fvny566vls74p4qm9v3fdqd741fh3f-diffutils-3.12/bin:/nix/store/pmhkmqy0vxk47r6ndh0azybhf6gs6k25-gnused-4.9/bin:/nix/store/vlckk0vnmawq9wwh7ndkrwxlpv4h29yh-gnugrep-3.12/bin:/nix/store/03nvbw411p097h6yxjghc33rbcrjfb9d-gawk-5.3.2/bin:/nix/store/8av8pfs7bnyc6hqj764ns4z1fnr9bva1-gnutar-1.35/bin:/nix/store/8gsxxh82rf957ffbsk0q9670nhvl5lia-gzip-1.14/bin:/nix/store/6yjb3zdj448rm8qsmpiq3f67kvj5683a-bzip2-1.0.8-bin/bin:/nix/store/aqdvlkh0jdwkc22hh5vr9sl6qlw5ha74-gnumake-4.4.1/bin:/nix/store/q7sqwn7i6w2b67adw0bmix29pxg85x3w-bash-5.3p3/bin:/nix/store/856i1ajaci3kmmp15rifacfz3jvn5l3q-patch-2.8/bin:/nix/store/y9kgzp85ykrhd7l691w4djx121qygy68-xz-5.8.1-bin/bin:/nix/store/v40ijzz8p2fpk9ihjck3a1ncqaqfmn3c-file-5.45/bin' export HOST_PATH IFS=' ' @@ -37,13 +37,13 @@ NIX_CC='/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0' export NIX_CC NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu='1' export NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu -NIX_CFLAGS_COMPILE=' -frandom-seed=gsxc3lz58z -isystem /nix/store/7zwa3r9agcyzf21d0792fvhrsl6gajiy-bash-interactive-5.3p3-dev/include -isystem /nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev/include -isystem /nix/store/r4557ald6zn4dzmvgh8na9vwnwzgrjgc-nodejs-22.19.0/include -isystem /nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/include -isystem /nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/include -isystem /nix/store/w3ibvzff0yrpg8abrl8n2fxn0d9fpfpc-sqlite-3.50.2-dev/include -isystem /nix/store/7zwa3r9agcyzf21d0792fvhrsl6gajiy-bash-interactive-5.3p3-dev/include -isystem /nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev/include -isystem /nix/store/r4557ald6zn4dzmvgh8na9vwnwzgrjgc-nodejs-22.19.0/include -isystem /nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/include -isystem /nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/include -isystem /nix/store/w3ibvzff0yrpg8abrl8n2fxn0d9fpfpc-sqlite-3.50.2-dev/include' +NIX_CFLAGS_COMPILE=' -frandom-seed=2l63479bll -isystem /nix/store/7zwa3r9agcyzf21d0792fvhrsl6gajiy-bash-interactive-5.3p3-dev/include -isystem /nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev/include -isystem /nix/store/r4557ald6zn4dzmvgh8na9vwnwzgrjgc-nodejs-22.19.0/include -isystem /nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/include -isystem /nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/include -isystem /nix/store/7zwa3r9agcyzf21d0792fvhrsl6gajiy-bash-interactive-5.3p3-dev/include -isystem /nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev/include -isystem /nix/store/r4557ald6zn4dzmvgh8na9vwnwzgrjgc-nodejs-22.19.0/include -isystem /nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/include -isystem /nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/include' export NIX_CFLAGS_COMPILE NIX_ENFORCE_NO_NATIVE='1' export NIX_ENFORCE_NO_NATIVE NIX_HARDENING_ENABLE='bindnow format fortify fortify3 pic relro stackclashprotection stackprotector strictoverflow zerocallusedregs' export NIX_HARDENING_ENABLE -NIX_LDFLAGS='-rpath /home/ryan/Documents/Code/hindki/outputs/out/lib -L/nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/lib -L/nix/store/msjxcqa4x2f52dyq10rbrbw6k0m0hi90-postgresql-17.6-lib/lib -L/nix/store/jq2kbdw6ljv9i47jz23pm072cfyxwpfj-postgresql-17.6/lib -L/nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/lib -L/nix/store/8bsyjdxv61ha88hjrpgl6nyfjxfqnphx-sqlite-3.50.2/lib -L/nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/lib -L/nix/store/msjxcqa4x2f52dyq10rbrbw6k0m0hi90-postgresql-17.6-lib/lib -L/nix/store/jq2kbdw6ljv9i47jz23pm072cfyxwpfj-postgresql-17.6/lib -L/nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/lib -L/nix/store/8bsyjdxv61ha88hjrpgl6nyfjxfqnphx-sqlite-3.50.2/lib' +NIX_LDFLAGS='-rpath /home/ryan/Documents/Code/hindki/outputs/out/lib -L/nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/lib -L/nix/store/msjxcqa4x2f52dyq10rbrbw6k0m0hi90-postgresql-17.6-lib/lib -L/nix/store/jq2kbdw6ljv9i47jz23pm072cfyxwpfj-postgresql-17.6/lib -L/nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/lib -L/nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/lib -L/nix/store/msjxcqa4x2f52dyq10rbrbw6k0m0hi90-postgresql-17.6-lib/lib -L/nix/store/jq2kbdw6ljv9i47jz23pm072cfyxwpfj-postgresql-17.6/lib -L/nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/lib' export NIX_LDFLAGS NIX_NO_SELF_RPATH='1' NIX_STORE='/nix/store' @@ -60,7 +60,7 @@ OLDPWD='' export OLDPWD OPTERR='1' OSTYPE='linux-gnu' -PATH='/nix/store/gx2l0rnp3qcnysdddkg9dqnh2mz6w08k-patchelf-0.15.2/bin:/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0/bin:/nix/store/82kmz7r96navanrc2fgckh2bamiqrgsw-gcc-14.3.0/bin:/nix/store/4jxivbjpr86wmsziqlf7iljlwjlxz8bh-glibc-2.40-66-bin/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l19cddv64i52rhcwahif8sgyrd3mhiqb-binutils-wrapper-2.44/bin:/nix/store/c43ry7z24x3jhnjlj4gpay8a4g2p3x1h-binutils-2.44/bin:/nix/store/ddx7976jyll30xjbasghv9jailswprcp-bash-interactive-5.3p3/bin:/nix/store/q1zaii9cirbfpmwr7d86hpppql3kjcpf-git-2.51.0/bin:/nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev/bin:/nix/store/r4557ald6zn4dzmvgh8na9vwnwzgrjgc-nodejs-22.19.0/bin:/nix/store/967gn7p1p47ic924r2fx4rgbfp49fhsy-pnpm-10.15.1/bin:/nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/bin:/nix/store/jq2kbdw6ljv9i47jz23pm072cfyxwpfj-postgresql-17.6/bin:/nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/bin:/nix/store/1p5n2mzy33ayzc1scdnz82h53d192knh-claude-code-1.0.117/bin:/nix/store/gmwaym3dwkrb9987z8xg4njl2kmm2dvc-sqlite-3.50.2-bin/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l964krgbp613d5jxga2vy5qdssj7zfzj-findutils-4.10.0/bin:/nix/store/s2fvny566vls74p4qm9v3fdqd741fh3f-diffutils-3.12/bin:/nix/store/pmhkmqy0vxk47r6ndh0azybhf6gs6k25-gnused-4.9/bin:/nix/store/vlckk0vnmawq9wwh7ndkrwxlpv4h29yh-gnugrep-3.12/bin:/nix/store/03nvbw411p097h6yxjghc33rbcrjfb9d-gawk-5.3.2/bin:/nix/store/8av8pfs7bnyc6hqj764ns4z1fnr9bva1-gnutar-1.35/bin:/nix/store/8gsxxh82rf957ffbsk0q9670nhvl5lia-gzip-1.14/bin:/nix/store/6yjb3zdj448rm8qsmpiq3f67kvj5683a-bzip2-1.0.8-bin/bin:/nix/store/aqdvlkh0jdwkc22hh5vr9sl6qlw5ha74-gnumake-4.4.1/bin:/nix/store/q7sqwn7i6w2b67adw0bmix29pxg85x3w-bash-5.3p3/bin:/nix/store/856i1ajaci3kmmp15rifacfz3jvn5l3q-patch-2.8/bin:/nix/store/y9kgzp85ykrhd7l691w4djx121qygy68-xz-5.8.1-bin/bin:/nix/store/v40ijzz8p2fpk9ihjck3a1ncqaqfmn3c-file-5.45/bin' +PATH='/nix/store/gx2l0rnp3qcnysdddkg9dqnh2mz6w08k-patchelf-0.15.2/bin:/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0/bin:/nix/store/82kmz7r96navanrc2fgckh2bamiqrgsw-gcc-14.3.0/bin:/nix/store/4jxivbjpr86wmsziqlf7iljlwjlxz8bh-glibc-2.40-66-bin/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l19cddv64i52rhcwahif8sgyrd3mhiqb-binutils-wrapper-2.44/bin:/nix/store/c43ry7z24x3jhnjlj4gpay8a4g2p3x1h-binutils-2.44/bin:/nix/store/ddx7976jyll30xjbasghv9jailswprcp-bash-interactive-5.3p3/bin:/nix/store/q1zaii9cirbfpmwr7d86hpppql3kjcpf-git-2.51.0/bin:/nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev/bin:/nix/store/r4557ald6zn4dzmvgh8na9vwnwzgrjgc-nodejs-22.19.0/bin:/nix/store/967gn7p1p47ic924r2fx4rgbfp49fhsy-pnpm-10.15.1/bin:/nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev/bin:/nix/store/jq2kbdw6ljv9i47jz23pm072cfyxwpfj-postgresql-17.6/bin:/nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0/bin:/nix/store/1p5n2mzy33ayzc1scdnz82h53d192knh-claude-code-1.0.117/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l964krgbp613d5jxga2vy5qdssj7zfzj-findutils-4.10.0/bin:/nix/store/s2fvny566vls74p4qm9v3fdqd741fh3f-diffutils-3.12/bin:/nix/store/pmhkmqy0vxk47r6ndh0azybhf6gs6k25-gnused-4.9/bin:/nix/store/vlckk0vnmawq9wwh7ndkrwxlpv4h29yh-gnugrep-3.12/bin:/nix/store/03nvbw411p097h6yxjghc33rbcrjfb9d-gawk-5.3.2/bin:/nix/store/8av8pfs7bnyc6hqj764ns4z1fnr9bva1-gnutar-1.35/bin:/nix/store/8gsxxh82rf957ffbsk0q9670nhvl5lia-gzip-1.14/bin:/nix/store/6yjb3zdj448rm8qsmpiq3f67kvj5683a-bzip2-1.0.8-bin/bin:/nix/store/aqdvlkh0jdwkc22hh5vr9sl6qlw5ha74-gnumake-4.4.1/bin:/nix/store/q7sqwn7i6w2b67adw0bmix29pxg85x3w-bash-5.3p3/bin:/nix/store/856i1ajaci3kmmp15rifacfz3jvn5l3q-patch-2.8/bin:/nix/store/y9kgzp85ykrhd7l691w4djx121qygy68-xz-5.8.1-bin/bin:/nix/store/v40ijzz8p2fpk9ihjck3a1ncqaqfmn3c-file-5.45/bin' export PATH PS4='+ ' RANLIB='ranlib' @@ -82,7 +82,7 @@ export XDG_DATA_DIRS __structuredAttrs='' export __structuredAttrs _substituteStream_has_warned_replace_deprecation='false' -buildInputs='/nix/store/7zwa3r9agcyzf21d0792fvhrsl6gajiy-bash-interactive-5.3p3-dev /nix/store/008h0z2m22alg2v8kcdcw4v0f7c39lmm-glibc-locales-2.40-66 /nix/store/q1zaii9cirbfpmwr7d86hpppql3kjcpf-git-2.51.0 /nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev /nix/store/967gn7p1p47ic924r2fx4rgbfp49fhsy-pnpm-10.15.1 /nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev /nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0 /nix/store/1p5n2mzy33ayzc1scdnz82h53d192knh-claude-code-1.0.117 /nix/store/w3ibvzff0yrpg8abrl8n2fxn0d9fpfpc-sqlite-3.50.2-dev' +buildInputs='/nix/store/7zwa3r9agcyzf21d0792fvhrsl6gajiy-bash-interactive-5.3p3-dev /nix/store/008h0z2m22alg2v8kcdcw4v0f7c39lmm-glibc-locales-2.40-66 /nix/store/q1zaii9cirbfpmwr7d86hpppql3kjcpf-git-2.51.0 /nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev /nix/store/967gn7p1p47ic924r2fx4rgbfp49fhsy-pnpm-10.15.1 /nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev /nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0 /nix/store/1p5n2mzy33ayzc1scdnz82h53d192knh-claude-code-1.0.117' export buildInputs buildPhase='{ echo "------------------------------------------------------------"; echo " WARNING: the existence of this path is not guaranteed."; @@ -161,7 +161,7 @@ declare -a pkgsBuildBuild=() declare -a pkgsBuildHost=('/nix/store/gx2l0rnp3qcnysdddkg9dqnh2mz6w08k-patchelf-0.15.2' '/nix/store/jwjq0fjgn7d00kswhaw2m8hbgws5vbi4-update-autotools-gnu-config-scripts-hook' '/nix/store/0y5xmdb7qfvimjwbq7ibg1xdgkgjwqng-no-broken-symlinks.sh' '/nix/store/cv1d7p48379km6a85h4zp6kr86brh32q-audit-tmpdir.sh' '/nix/store/85clx3b0xkdf58jn161iy80y5223ilbi-compress-man-pages.sh' '/nix/store/wgrbkkaldkrlrni33ccvm3b6vbxzb656-make-symlinks-relative.sh' '/nix/store/5yzw0vhkyszf2d179m0qfkgxmp5wjjx4-move-docs.sh' '/nix/store/fyaryjvghbkpfnsyw97hb3lyb37s1pd6-move-lib64.sh' '/nix/store/kd4xwxjpjxi71jkm6ka0np72if9rm3y0-move-sbin.sh' '/nix/store/pag6l61paj1dc9sv15l7bm5c17xn5kyk-move-systemd-user-units.sh' '/nix/store/cmzya9irvxzlkh7lfy6i82gbp0saxqj3-multiple-outputs.sh' '/nix/store/x8c40nfigps493a07sdr2pm5s9j1cdc0-patch-shebangs.sh' '/nix/store/cickvswrvann041nqxb0rxilc46svw1n-prune-libtool-files.sh' '/nix/store/xyff06pkhki3qy1ls77w10s0v79c9il0-reproducible-builds.sh' '/nix/store/z7k98578dfzi6l3hsvbivzm7hfqlk0zc-set-source-date-epoch-to-latest.sh' '/nix/store/pilsssjjdxvdphlg2h19p0bfx5q0jzkn-strip.sh' '/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0' '/nix/store/l19cddv64i52rhcwahif8sgyrd3mhiqb-binutils-wrapper-2.44' ) declare -a pkgsBuildTarget=() declare -a pkgsHostHost=() -declare -a pkgsHostTarget=('/nix/store/7zwa3r9agcyzf21d0792fvhrsl6gajiy-bash-interactive-5.3p3-dev' '/nix/store/ddx7976jyll30xjbasghv9jailswprcp-bash-interactive-5.3p3' '/nix/store/008h0z2m22alg2v8kcdcw4v0f7c39lmm-glibc-locales-2.40-66' '/nix/store/q1zaii9cirbfpmwr7d86hpppql3kjcpf-git-2.51.0' '/nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev' '/nix/store/r4557ald6zn4dzmvgh8na9vwnwzgrjgc-nodejs-22.19.0' '/nix/store/967gn7p1p47ic924r2fx4rgbfp49fhsy-pnpm-10.15.1' '/nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev' '/nix/store/msjxcqa4x2f52dyq10rbrbw6k0m0hi90-postgresql-17.6-lib' '/nix/store/jq2kbdw6ljv9i47jz23pm072cfyxwpfj-postgresql-17.6' '/nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0' '/nix/store/1p5n2mzy33ayzc1scdnz82h53d192knh-claude-code-1.0.117' '/nix/store/w3ibvzff0yrpg8abrl8n2fxn0d9fpfpc-sqlite-3.50.2-dev' '/nix/store/gmwaym3dwkrb9987z8xg4njl2kmm2dvc-sqlite-3.50.2-bin' '/nix/store/8bsyjdxv61ha88hjrpgl6nyfjxfqnphx-sqlite-3.50.2' ) +declare -a pkgsHostTarget=('/nix/store/7zwa3r9agcyzf21d0792fvhrsl6gajiy-bash-interactive-5.3p3-dev' '/nix/store/ddx7976jyll30xjbasghv9jailswprcp-bash-interactive-5.3p3' '/nix/store/008h0z2m22alg2v8kcdcw4v0f7c39lmm-glibc-locales-2.40-66' '/nix/store/q1zaii9cirbfpmwr7d86hpppql3kjcpf-git-2.51.0' '/nix/store/a99hiwhamgzds70gxkfnb4cm8i926356-nodejs-22.19.0-dev' '/nix/store/r4557ald6zn4dzmvgh8na9vwnwzgrjgc-nodejs-22.19.0' '/nix/store/967gn7p1p47ic924r2fx4rgbfp49fhsy-pnpm-10.15.1' '/nix/store/l8m7mbvqxdi9bd5apl8s49kjpnzrcv6c-postgresql-17.6-dev' '/nix/store/msjxcqa4x2f52dyq10rbrbw6k0m0hi90-postgresql-17.6-lib' '/nix/store/jq2kbdw6ljv9i47jz23pm072cfyxwpfj-postgresql-17.6' '/nix/store/ks5kxqrg113jkv9bsvhgpavrq1z1ks4g-inotify-tools-4.23.9.0' '/nix/store/1p5n2mzy33ayzc1scdnz82h53d192knh-claude-code-1.0.117' ) declare -a pkgsTargetTarget=() declare -a postFixupHooks=('noBrokenSymlinksInAllOutputs' '_makeSymlinksRelativeInAllOutputs' '_multioutPropagateDev' ) declare -a postUnpackHooks=('_updateSourceDateEpochFromSourceRoot' ) diff --git a/flake.nix b/flake.nix index cac5cda..39b5d17 100644 --- a/flake.nix +++ b/flake.nix @@ -27,7 +27,6 @@ postgresql inotify-tools claude-code - sqlite ]; }; } diff --git a/hindki/.env.example b/hindki/.env.example index 96dfaf0..3a23da6 100644 --- a/hindki/.env.example +++ b/hindki/.env.example @@ -1,14 +1,3 @@ -# Storage configuration for vocabulary updates -# Options: filesystem (default), git - -# For local development (default) -VOCAB_STORAGE_TYPE=filesystem - -# For Gitea/GitHub storage in production -# VOCAB_STORAGE_TYPE=git -# GIT_API_URL=https://gitea.example.com # Your Gitea instance URL (omit for GitHub) -# GIT_OWNER=your-username -# GIT_REPO=hindki -# GIT_PATH=src/vocab_list.yaml -# GIT_BRANCH=main -# GIT_TOKEN=your-personal-access-token \ No newline at end of file +# Database connection string +# Format: postgresql://username:password@host:port/database +DATABASE_URL=postgresql://hindki:your_password@localhost:5432/hindki diff --git a/hindki/.gitignore b/hindki/.gitignore index 5d77e79..18a4726 100644 --- a/hindki/.gitignore +++ b/hindki/.gitignore @@ -23,3 +23,9 @@ data.db-wal # build output dist/ .astro/ + +# direnv and nix +.direnv/ +.envrc +result +result-* diff --git a/hindki/Dockerfile b/hindki/Dockerfile index edc5606..ca1d520 100644 --- a/hindki/Dockerfile +++ b/hindki/Dockerfile @@ -12,6 +12,7 @@ ENV HOST=0.0.0.0 ENV PORT=4321 EXPOSE 4321 -# Database will be mounted as a volume at runtime +# DATABASE_URL will be provided as an environment variable at runtime +# Set in Coolify or via docker run -e DATABASE_URL=... CMD node ./dist/server/entry.mjs diff --git a/hindki/astro.config.mjs b/hindki/astro.config.mjs index c0c76e5..b89c48d 100644 --- a/hindki/astro.config.mjs +++ b/hindki/astro.config.mjs @@ -3,14 +3,35 @@ import { defineConfig } from "astro/config"; import starlight from "@astrojs/starlight"; import react from "@astrojs/react"; import node from "@astrojs/node"; -import Database from 'better-sqlite3'; -import { drizzle } from 'drizzle-orm/better-sqlite3'; -import { tags } from './src/lib/db/schema.ts'; +import { drizzle } from "drizzle-orm/postgres-js"; +import postgres from "postgres"; +import { tags } from "./src/lib/db/schema.ts"; +import "dotenv/config"; // Load tags from database for sidebar -const sqlite = new Database('./data.db'); -const db = drizzle(sqlite); -const tagsList = db.select().from(tags).all(); +// Explicitly type tagsList as an array of objects with a 'name' property +/** @type {{ name: string }[]} */ +let tagsList = []; +try { + const connectionString = process.env.DATABASE_URL || ""; + if (connectionString) { + const client = postgres(connectionString); + const db = drizzle(client, { schema: { tags } }); + tagsList = await db.select().from(tags); + await client.end(); + } else { + console.warn( + "⚠️ DATABASE_URL not found - sidebar will not include vocabulary tags", + ); + } +} catch (error) { + const errorMessage = + typeof error === "object" && error !== null && "message" in error + ? error.message + : String(error); + console.warn("⚠️ Could not load tags from database:", errorMessage); + console.warn(" Sidebar will not include vocabulary tags"); +} const vocabList = [ { diff --git a/hindki/drizzle.config.ts b/hindki/drizzle.config.ts index 39646d9..1c4ae2d 100644 --- a/hindki/drizzle.config.ts +++ b/hindki/drizzle.config.ts @@ -1,10 +1,11 @@ import { defineConfig } from 'drizzle-kit'; +import 'dotenv/config'; export default defineConfig({ schema: './src/lib/db/schema.ts', out: './drizzle', - dialect: 'sqlite', + dialect: 'postgresql', dbCredentials: { - url: './data.db', + url: process.env.DATABASE_URL!, }, }); diff --git a/hindki/drizzle/0000_bouncy_demogoblin.sql b/hindki/drizzle/0000_bouncy_demogoblin.sql new file mode 100644 index 0000000..b326f87 --- /dev/null +++ b/hindki/drizzle/0000_bouncy_demogoblin.sql @@ -0,0 +1,43 @@ +CREATE TABLE "examples" ( + "id" serial PRIMARY KEY NOT NULL, + "word_id" serial NOT NULL, + "hindi" text NOT NULL, + "english" text NOT NULL, + "note" text +); +--> statement-breakpoint +CREATE TABLE "see_also" ( + "id" serial PRIMARY KEY NOT NULL, + "word_id" serial NOT NULL, + "reference" text NOT NULL, + "note" text +); +--> statement-breakpoint +CREATE TABLE "tags" ( + "id" serial PRIMARY KEY NOT NULL, + "name" text NOT NULL, + "description" text, + CONSTRAINT "tags_name_unique" UNIQUE("name") +); +--> statement-breakpoint +CREATE TABLE "word_tags" ( + "id" serial PRIMARY KEY NOT NULL, + "word_id" serial NOT NULL, + "tag_id" serial NOT NULL +); +--> statement-breakpoint +CREATE TABLE "words" ( + "id" serial PRIMARY KEY NOT NULL, + "hindi" text NOT NULL, + "english" text NOT NULL, + "type" text, + "gender" text, + "note" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +ALTER TABLE "examples" ADD CONSTRAINT "examples_word_id_words_id_fk" FOREIGN KEY ("word_id") REFERENCES "public"."words"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "see_also" ADD CONSTRAINT "see_also_word_id_words_id_fk" FOREIGN KEY ("word_id") REFERENCES "public"."words"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "word_tags" ADD CONSTRAINT "word_tags_word_id_words_id_fk" FOREIGN KEY ("word_id") REFERENCES "public"."words"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "word_tags" ADD CONSTRAINT "word_tags_tag_id_tags_id_fk" FOREIGN KEY ("tag_id") REFERENCES "public"."tags"("id") ON DELETE no action ON UPDATE no action; \ No newline at end of file diff --git a/hindki/drizzle/0000_charming_screwball.sql b/hindki/drizzle/0000_charming_screwball.sql deleted file mode 100644 index d3caaf4..0000000 --- a/hindki/drizzle/0000_charming_screwball.sql +++ /dev/null @@ -1,42 +0,0 @@ -CREATE TABLE `examples` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `word_id` integer NOT NULL, - `hindi` text NOT NULL, - `english` text NOT NULL, - `note` text, - FOREIGN KEY (`word_id`) REFERENCES `words`(`id`) ON UPDATE no action ON DELETE cascade -); ---> statement-breakpoint -CREATE TABLE `see_also` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `word_id` integer NOT NULL, - `reference` text, - `note` text, - FOREIGN KEY (`word_id`) REFERENCES `words`(`id`) ON UPDATE no action ON DELETE cascade -); ---> statement-breakpoint -CREATE TABLE `tags` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `name` text NOT NULL, - `description` text -); ---> statement-breakpoint -CREATE UNIQUE INDEX `tags_name_unique` ON `tags` (`name`);--> statement-breakpoint -CREATE TABLE `word_tags` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `word_id` integer NOT NULL, - `tag_id` integer NOT NULL, - FOREIGN KEY (`word_id`) REFERENCES `words`(`id`) ON UPDATE no action ON DELETE cascade, - FOREIGN KEY (`tag_id`) REFERENCES `tags`(`id`) ON UPDATE no action ON DELETE no action -); ---> statement-breakpoint -CREATE TABLE `words` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `hindi` text NOT NULL, - `english` text NOT NULL, - `type` text, - `gender` text, - `note` text, - `created_at` integer NOT NULL, - `updated_at` integer NOT NULL -); diff --git a/hindki/drizzle/0001_shallow_sasquatch.sql b/hindki/drizzle/0001_shallow_sasquatch.sql deleted file mode 100644 index d81d4eb..0000000 --- a/hindki/drizzle/0001_shallow_sasquatch.sql +++ /dev/null @@ -1,13 +0,0 @@ -PRAGMA foreign_keys=OFF;--> statement-breakpoint -CREATE TABLE `__new_see_also` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `word_id` integer NOT NULL, - `reference` text NOT NULL, - `note` text, - FOREIGN KEY (`word_id`) REFERENCES `words`(`id`) ON UPDATE no action ON DELETE cascade -); ---> statement-breakpoint -INSERT INTO `__new_see_also`("id", "word_id", "reference", "note") SELECT "id", "word_id", "reference", "note" FROM `see_also`;--> statement-breakpoint -DROP TABLE `see_also`;--> statement-breakpoint -ALTER TABLE `__new_see_also` RENAME TO `see_also`;--> statement-breakpoint -PRAGMA foreign_keys=ON; \ No newline at end of file diff --git a/hindki/drizzle/meta/0000_snapshot.json b/hindki/drizzle/meta/0000_snapshot.json index 7f5c662..5a67b62 100644 --- a/hindki/drizzle/meta/0000_snapshot.json +++ b/hindki/drizzle/meta/0000_snapshot.json @@ -1,46 +1,42 @@ { - "version": "6", - "dialect": "sqlite", - "id": "0c4cf3cf-109c-455f-9adb-40293d6825f0", + "id": "e5ed4824-2e96-4821-84c9-c33bd5d1cda8", "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", "tables": { - "examples": { + "public.examples": { "name": "examples", + "schema": "", "columns": { "id": { "name": "id", - "type": "integer", + "type": "serial", "primaryKey": true, - "notNull": true, - "autoincrement": true + "notNull": true }, "word_id": { "name": "word_id", - "type": "integer", + "type": "serial", "primaryKey": false, - "notNull": true, - "autoincrement": false + "notNull": true }, "hindi": { "name": "hindi", "type": "text", "primaryKey": false, - "notNull": true, - "autoincrement": false + "notNull": true }, "english": { "name": "english", "type": "text", "primaryKey": false, - "notNull": true, - "autoincrement": false + "notNull": true }, "note": { "name": "note", "type": "text", "primaryKey": false, - "notNull": false, - "autoincrement": false + "notNull": false } }, "indexes": {}, @@ -61,38 +57,37 @@ }, "compositePrimaryKeys": {}, "uniqueConstraints": {}, - "checkConstraints": {} + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false }, - "see_also": { + "public.see_also": { "name": "see_also", + "schema": "", "columns": { "id": { "name": "id", - "type": "integer", + "type": "serial", "primaryKey": true, - "notNull": true, - "autoincrement": true + "notNull": true }, "word_id": { "name": "word_id", - "type": "integer", + "type": "serial", "primaryKey": false, - "notNull": true, - "autoincrement": false + "notNull": true }, "reference": { "name": "reference", "type": "text", "primaryKey": false, - "notNull": false, - "autoincrement": false + "notNull": true }, "note": { "name": "note", "type": "text", "primaryKey": false, - "notNull": false, - "autoincrement": false + "notNull": false } }, "indexes": {}, @@ -113,70 +108,70 @@ }, "compositePrimaryKeys": {}, "uniqueConstraints": {}, - "checkConstraints": {} + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false }, - "tags": { + "public.tags": { "name": "tags", + "schema": "", "columns": { "id": { "name": "id", - "type": "integer", + "type": "serial", "primaryKey": true, - "notNull": true, - "autoincrement": true + "notNull": true }, "name": { "name": "name", "type": "text", "primaryKey": false, - "notNull": true, - "autoincrement": false + "notNull": true }, "description": { "name": "description", "type": "text", "primaryKey": false, - "notNull": false, - "autoincrement": false - } - }, - "indexes": { - "tags_name_unique": { - "name": "tags_name_unique", - "columns": [ - "name" - ], - "isUnique": true + "notNull": false } }, + "indexes": {}, "foreignKeys": {}, "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} + "uniqueConstraints": { + "tags_name_unique": { + "name": "tags_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false }, - "word_tags": { + "public.word_tags": { "name": "word_tags", + "schema": "", "columns": { "id": { "name": "id", - "type": "integer", + "type": "serial", "primaryKey": true, - "notNull": true, - "autoincrement": true + "notNull": true }, "word_id": { "name": "word_id", - "type": "integer", + "type": "serial", "primaryKey": false, - "notNull": true, - "autoincrement": false + "notNull": true }, "tag_id": { "name": "tag_id", - "type": "integer", + "type": "serial", "primaryKey": false, - "notNull": true, - "autoincrement": false + "notNull": true } }, "indexes": {}, @@ -210,83 +205,83 @@ }, "compositePrimaryKeys": {}, "uniqueConstraints": {}, - "checkConstraints": {} + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false }, - "words": { + "public.words": { "name": "words", + "schema": "", "columns": { "id": { "name": "id", - "type": "integer", + "type": "serial", "primaryKey": true, - "notNull": true, - "autoincrement": true + "notNull": true }, "hindi": { "name": "hindi", "type": "text", "primaryKey": false, - "notNull": true, - "autoincrement": false + "notNull": true }, "english": { "name": "english", "type": "text", "primaryKey": false, - "notNull": true, - "autoincrement": false + "notNull": true }, "type": { "name": "type", "type": "text", "primaryKey": false, - "notNull": false, - "autoincrement": false + "notNull": false }, "gender": { "name": "gender", "type": "text", "primaryKey": false, - "notNull": false, - "autoincrement": false + "notNull": false }, "note": { "name": "note", "type": "text", "primaryKey": false, - "notNull": false, - "autoincrement": false + "notNull": false }, "created_at": { "name": "created_at", - "type": "integer", + "type": "timestamp", "primaryKey": false, "notNull": true, - "autoincrement": false + "default": "now()" }, "updated_at": { "name": "updated_at", - "type": "integer", + "type": "timestamp", "primaryKey": false, "notNull": true, - "autoincrement": false + "default": "now()" } }, "indexes": {}, "foreignKeys": {}, "compositePrimaryKeys": {}, "uniqueConstraints": {}, - "checkConstraints": {} + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false } }, - "views": {}, "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, "_meta": { + "columns": {}, "schemas": {}, - "tables": {}, - "columns": {} - }, - "internal": { - "indexes": {} + "tables": {} } } \ No newline at end of file diff --git a/hindki/drizzle/meta/0001_snapshot.json b/hindki/drizzle/meta/0001_snapshot.json deleted file mode 100644 index 367f83c..0000000 --- a/hindki/drizzle/meta/0001_snapshot.json +++ /dev/null @@ -1,292 +0,0 @@ -{ - "version": "6", - "dialect": "sqlite", - "id": "e2f4339d-0cbb-4dd5-ba04-427b0f25625c", - "prevId": "0c4cf3cf-109c-455f-9adb-40293d6825f0", - "tables": { - "examples": { - "name": "examples", - "columns": { - "id": { - "name": "id", - "type": "integer", - "primaryKey": true, - "notNull": true, - "autoincrement": true - }, - "word_id": { - "name": "word_id", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "hindi": { - "name": "hindi", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "english": { - "name": "english", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "note": { - "name": "note", - "type": "text", - "primaryKey": false, - "notNull": false, - "autoincrement": false - } - }, - "indexes": {}, - "foreignKeys": { - "examples_word_id_words_id_fk": { - "name": "examples_word_id_words_id_fk", - "tableFrom": "examples", - "tableTo": "words", - "columnsFrom": [ - "word_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "see_also": { - "name": "see_also", - "columns": { - "id": { - "name": "id", - "type": "integer", - "primaryKey": true, - "notNull": true, - "autoincrement": true - }, - "word_id": { - "name": "word_id", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "reference": { - "name": "reference", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "note": { - "name": "note", - "type": "text", - "primaryKey": false, - "notNull": false, - "autoincrement": false - } - }, - "indexes": {}, - "foreignKeys": { - "see_also_word_id_words_id_fk": { - "name": "see_also_word_id_words_id_fk", - "tableFrom": "see_also", - "tableTo": "words", - "columnsFrom": [ - "word_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "tags": { - "name": "tags", - "columns": { - "id": { - "name": "id", - "type": "integer", - "primaryKey": true, - "notNull": true, - "autoincrement": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false, - "autoincrement": false - } - }, - "indexes": { - "tags_name_unique": { - "name": "tags_name_unique", - "columns": [ - "name" - ], - "isUnique": true - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "word_tags": { - "name": "word_tags", - "columns": { - "id": { - "name": "id", - "type": "integer", - "primaryKey": true, - "notNull": true, - "autoincrement": true - }, - "word_id": { - "name": "word_id", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "tag_id": { - "name": "tag_id", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - } - }, - "indexes": {}, - "foreignKeys": { - "word_tags_word_id_words_id_fk": { - "name": "word_tags_word_id_words_id_fk", - "tableFrom": "word_tags", - "tableTo": "words", - "columnsFrom": [ - "word_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "word_tags_tag_id_tags_id_fk": { - "name": "word_tags_tag_id_tags_id_fk", - "tableFrom": "word_tags", - "tableTo": "tags", - "columnsFrom": [ - "tag_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "words": { - "name": "words", - "columns": { - "id": { - "name": "id", - "type": "integer", - "primaryKey": true, - "notNull": true, - "autoincrement": true - }, - "hindi": { - "name": "hindi", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "english": { - "name": "english", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": false, - "autoincrement": false - }, - "gender": { - "name": "gender", - "type": "text", - "primaryKey": false, - "notNull": false, - "autoincrement": false - }, - "note": { - "name": "note", - "type": "text", - "primaryKey": false, - "notNull": false, - "autoincrement": false - }, - "created_at": { - "name": "created_at", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "updated_at": { - "name": "updated_at", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - } - }, - "views": {}, - "enums": {}, - "_meta": { - "schemas": {}, - "tables": {}, - "columns": {} - }, - "internal": { - "indexes": {} - } -} \ No newline at end of file diff --git a/hindki/drizzle/meta/_journal.json b/hindki/drizzle/meta/_journal.json index 4242cb1..1bf8767 100644 --- a/hindki/drizzle/meta/_journal.json +++ b/hindki/drizzle/meta/_journal.json @@ -1,19 +1,12 @@ { "version": "7", - "dialect": "sqlite", + "dialect": "postgresql", "entries": [ { "idx": 0, - "version": "6", - "when": 1759426695406, - "tag": "0000_charming_screwball", - "breakpoints": true - }, - { - "idx": 1, - "version": "6", - "when": 1759430283642, - "tag": "0001_shallow_sasquatch", + "version": "7", + "when": 1759431829568, + "tag": "0000_bouncy_demogoblin", "breakpoints": true } ] diff --git a/hindki/package-lock.json b/hindki/package-lock.json index 15baf12..2eb36ae 100644 --- a/hindki/package-lock.json +++ b/hindki/package-lock.json @@ -14,16 +14,18 @@ "@types/markdown-it": "^14.1.2", "astro": "^5.6.1", "astro-code-editor": "^0.1.1", - "better-sqlite3": "^12.4.1", + "dotenv": "^17.2.3", "drizzle-orm": "^0.44.6", "markdown-it": "^14.1.0", "markdown-it-mark": "^4.0.0", "monaco-yaml": "^5.4.0", + "postgres": "^3.4.7", "sharp": "^0.34.2", "yaml": "^2.8.1" }, "devDependencies": { "@types/better-sqlite3": "^7.6.13", + "better-sqlite3": "^12.4.1", "drizzle-kit": "^0.31.5", "prettier": "^3.6.2", "prettier-plugin-astro": "^0.14.1", @@ -3056,6 +3058,7 @@ "version": "12.4.1", "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.4.1.tgz", "integrity": "sha512-3yVdyZhklTiNrtg+4WqHpJpFDd+WHTg2oM7UcR80GqL05AOV0xEJzc6qNvFYoEtE+hRp1n9MpN6/+4yhlGkDXQ==", + "devOptional": true, "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -3070,6 +3073,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "devOptional": true, "license": "MIT", "dependencies": { "file-uri-to-path": "1.0.0" @@ -3079,6 +3083,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "devOptional": true, "license": "MIT", "dependencies": { "buffer": "^5.5.0", @@ -3180,6 +3185,7 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "devOptional": true, "funding": [ { "type": "github", @@ -3320,6 +3326,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "devOptional": true, "license": "ISC" }, "node_modules/ci-info": { @@ -3514,6 +3521,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "devOptional": true, "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" @@ -3529,6 +3537,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=4.0.0" @@ -3638,6 +3647,18 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "license": "MIT" }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/drizzle-kit": { "version": "0.31.5", "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.31.5.tgz", @@ -3819,6 +3840,7 @@ "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "devOptional": true, "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -4065,6 +4087,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "devOptional": true, "license": "(MIT OR WTFPL)", "engines": { "node": ">=6" @@ -4115,6 +4138,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "devOptional": true, "license": "MIT" }, "node_modules/flattie": { @@ -4166,6 +4190,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "devOptional": true, "license": "MIT" }, "node_modules/fsevents": { @@ -4220,6 +4245,7 @@ "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "devOptional": true, "license": "MIT" }, "node_modules/github-slugger": { @@ -4704,6 +4730,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "devOptional": true, "funding": [ { "type": "github", @@ -4740,6 +4767,7 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "devOptional": true, "license": "ISC" }, "node_modules/inline-style-parser": { @@ -6125,6 +6153,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=10" @@ -6137,6 +6166,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "devOptional": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6146,6 +6176,7 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "devOptional": true, "license": "MIT" }, "node_modules/monaco-editor": { @@ -6267,6 +6298,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "devOptional": true, "license": "MIT" }, "node_modules/neotraverse": { @@ -6295,6 +6327,7 @@ "version": "3.77.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.77.0.tgz", "integrity": "sha512-DSmt0OEcLoK4i3NuscSbGjOf3bqiDEutejqENSplMSFA/gmB8mkED9G4pKWnPl7MDU4rSHebKPHeitpDfyH0cQ==", + "devOptional": true, "license": "MIT", "dependencies": { "semver": "^7.3.5" @@ -6307,6 +6340,7 @@ "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -6407,6 +6441,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "devOptional": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -6658,10 +6693,24 @@ "node": ">=4" } }, + "node_modules/postgres": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz", + "integrity": "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==", + "license": "Unlicense", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + } + }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "devOptional": true, "license": "MIT", "dependencies": { "detect-libc": "^2.0.0", @@ -6759,6 +6808,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "devOptional": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -6793,6 +6843,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "devOptional": true, "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", @@ -6840,6 +6891,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "devOptional": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -7293,6 +7345,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "devOptional": true, "funding": [ { "type": "github", @@ -7449,6 +7502,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "devOptional": true, "funding": [ { "type": "github", @@ -7469,6 +7523,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "devOptional": true, "funding": [ { "type": "github", @@ -7601,6 +7656,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "devOptional": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" @@ -7656,6 +7712,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7693,6 +7750,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "devOptional": true, "license": "MIT", "dependencies": { "chownr": "^1.1.1", @@ -7705,6 +7763,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "devOptional": true, "license": "MIT", "dependencies": { "bl": "^4.0.3", @@ -7830,6 +7889,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "devOptional": true, "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" @@ -8461,6 +8521,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "devOptional": true, "license": "ISC" }, "node_modules/xxhash-wasm": { diff --git a/hindki/package.json b/hindki/package.json index 89ac571..1eec62b 100644 --- a/hindki/package.json +++ b/hindki/package.json @@ -8,7 +8,8 @@ "build": "astro build", "preview": "astro preview", "astro": "astro", - "migrate": "tsx scripts/migrate-yaml-to-db.ts" + "migrate": "tsx scripts/migrate-yaml-to-db.ts", + "migrate:postgres": "tsx scripts/migrate-sqlite-to-postgres.ts" }, "dependencies": { "@astrojs/node": "^9.4.4", @@ -17,16 +18,18 @@ "@types/markdown-it": "^14.1.2", "astro": "^5.6.1", "astro-code-editor": "^0.1.1", - "better-sqlite3": "^12.4.1", + "dotenv": "^17.2.3", "drizzle-orm": "^0.44.6", "markdown-it": "^14.1.0", "markdown-it-mark": "^4.0.0", "monaco-yaml": "^5.4.0", + "postgres": "^3.4.7", "sharp": "^0.34.2", "yaml": "^2.8.1" }, "devDependencies": { "@types/better-sqlite3": "^7.6.13", + "better-sqlite3": "^12.4.1", "drizzle-kit": "^0.31.5", "prettier": "^3.6.2", "prettier-plugin-astro": "^0.14.1", diff --git a/hindki/scripts/migrate-sqlite-to-postgres.ts b/hindki/scripts/migrate-sqlite-to-postgres.ts new file mode 100644 index 0000000..45d57ba --- /dev/null +++ b/hindki/scripts/migrate-sqlite-to-postgres.ts @@ -0,0 +1,109 @@ +import Database from 'better-sqlite3'; +import { drizzle as sqliteDrizzle } from 'drizzle-orm/better-sqlite3'; +import { drizzle as postgresDrizzle } from 'drizzle-orm/postgres-js'; +import postgres from 'postgres'; +import { words, examples, tags, wordTags, seeAlso } from '../src/lib/db/schema'; +import 'dotenv/config'; + +const connectionString = process.env.DATABASE_URL || ''; + +if (!connectionString) { + console.error('DATABASE_URL environment variable is required'); + process.exit(1); +} + +async function migrate() { + console.log('Starting SQLite to PostgreSQL migration...\n'); + + // Connect to SQLite + const sqlite = new Database('./data.db'); + const sqliteDb = sqliteDrizzle(sqlite); + + // Connect to PostgreSQL + const pgClient = postgres(connectionString); + const pgDb = postgresDrizzle(pgClient, { schema: { words, examples, tags, wordTags, seeAlso } }); + + try { + // Migrate tags first + console.log('Migrating tags...'); + const sqliteTags = sqlite.prepare('SELECT * FROM tags').all() as any[]; + + for (const tag of sqliteTags) { + await pgDb.insert(tags).values({ + name: tag.name, + description: tag.description, + }); + } + console.log(`✅ Migrated ${sqliteTags.length} tags\n`); + + // Get tag ID mapping (SQLite ID -> PostgreSQL ID) + const pgTags = await pgDb.select().from(tags); + const tagIdMap = new Map(); + for (let i = 0; i < sqliteTags.length; i++) { + const sqliteTag = sqliteTags[i]; + const pgTag = pgTags.find(t => t.name === sqliteTag.name); + if (pgTag) { + tagIdMap.set(sqliteTag.id, pgTag.id); + } + } + + // Migrate words + console.log('Migrating words...'); + const sqliteWords = sqlite.prepare('SELECT * FROM words').all() as any[]; + + for (const word of sqliteWords) { + const [insertedWord] = await pgDb.insert(words).values({ + hindi: word.hindi, + english: word.english, + type: word.type, + gender: word.gender, + note: word.note, + }).returning(); + + // Migrate word_tags associations + const wordTagsData = sqlite.prepare('SELECT * FROM word_tags WHERE word_id = ?').all(word.id) as any[]; + for (const wt of wordTagsData) { + const newTagId = tagIdMap.get(wt.tag_id); + if (newTagId) { + await pgDb.insert(wordTags).values({ + wordId: insertedWord.id, + tagId: newTagId, + }); + } + } + + // Migrate examples + const examplesData = sqlite.prepare('SELECT * FROM examples WHERE word_id = ?').all(word.id) as any[]; + for (const example of examplesData) { + await pgDb.insert(examples).values({ + wordId: insertedWord.id, + hindi: example.hindi, + english: example.english, + note: example.note, + }); + } + + // Migrate see_also + const seeAlsoData = sqlite.prepare('SELECT * FROM see_also WHERE word_id = ?').all(word.id) as any[]; + for (const sa of seeAlsoData) { + await pgDb.insert(seeAlso).values({ + wordId: insertedWord.id, + reference: sa.reference, + note: sa.note, + }); + } + } + console.log(`✅ Migrated ${sqliteWords.length} words with all relations\n`); + + console.log('Migration complete! 🎉'); + + } catch (error) { + console.error('Migration failed:', error); + process.exit(1); + } finally { + sqlite.close(); + await pgClient.end(); + } +} + +migrate(); diff --git a/hindki/src/lib/db/index.ts b/hindki/src/lib/db/index.ts index 285c606..04233f5 100644 --- a/hindki/src/lib/db/index.ts +++ b/hindki/src/lib/db/index.ts @@ -1,8 +1,12 @@ -import Database from 'better-sqlite3'; -import { drizzle } from 'drizzle-orm/better-sqlite3'; +import { drizzle } from 'drizzle-orm/postgres-js'; +import postgres from 'postgres'; import * as schema from './schema'; -import path from 'path'; -const dbPath = path.join(process.cwd(), 'data.db'); -const sqlite = new Database(dbPath); -export const db = drizzle(sqlite, { schema }); +const connectionString = process.env.DATABASE_URL || ''; + +if (!connectionString) { + throw new Error('DATABASE_URL environment variable is required'); +} + +const client = postgres(connectionString); +export const db = drizzle(client, { schema }); diff --git a/hindki/src/lib/db/schema.ts b/hindki/src/lib/db/schema.ts index a8feab2..4e725ef 100644 --- a/hindki/src/lib/db/schema.ts +++ b/hindki/src/lib/db/schema.ts @@ -1,40 +1,40 @@ -import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'; +import { pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core'; import { relations } from 'drizzle-orm'; -export const words = sqliteTable('words', { - id: integer('id').primaryKey({ autoIncrement: true }), +export const words = pgTable('words', { + id: serial('id').primaryKey(), hindi: text('hindi').notNull(), english: text('english').notNull(), type: text('type'), // noun, verb, adjective, etc. gender: text('gender'), // m, f, or null note: text('note'), - createdAt: integer('created_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()), - updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()), + createdAt: timestamp('created_at').notNull().defaultNow(), + updatedAt: timestamp('updated_at').notNull().defaultNow(), }); -export const examples = sqliteTable('examples', { - id: integer('id').primaryKey({ autoIncrement: true }), - wordId: integer('word_id').notNull().references(() => words.id, { onDelete: 'cascade' }), +export const examples = pgTable('examples', { + id: serial('id').primaryKey(), + wordId: serial('word_id').notNull().references(() => words.id, { onDelete: 'cascade' }), hindi: text('hindi').notNull(), english: text('english').notNull(), note: text('note'), }); -export const tags = sqliteTable('tags', { - id: integer('id').primaryKey({ autoIncrement: true }), +export const tags = pgTable('tags', { + id: serial('id').primaryKey(), name: text('name').notNull().unique(), description: text('description'), }); -export const wordTags = sqliteTable('word_tags', { - id: integer('id').primaryKey({ autoIncrement: true }), - wordId: integer('word_id').notNull().references(() => words.id, { onDelete: 'cascade' }), - tagId: integer('tag_id').notNull().references(() => tags.id), +export const wordTags = pgTable('word_tags', { + id: serial('id').primaryKey(), + wordId: serial('word_id').notNull().references(() => words.id, { onDelete: 'cascade' }), + tagId: serial('tag_id').notNull().references(() => tags.id), }); -export const seeAlso = sqliteTable('see_also', { - id: integer('id').primaryKey({ autoIncrement: true }), - wordId: integer('word_id').notNull().references(() => words.id, { onDelete: 'cascade' }), +export const seeAlso = pgTable('see_also', { + id: serial('id').primaryKey(), + wordId: serial('word_id').notNull().references(() => words.id, { onDelete: 'cascade' }), reference: text('reference').notNull(), // Link text like "[चीज़](#चीज़)" or "[Reflexive verbs](/grammar/reflexive-verbs)" note: text('note'), // Optional additional context }); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9090c4c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,164 @@ +{ + "name": "hindki", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "dotenv": "^17.2.3", + "drizzle-orm": "^0.44.6", + "postgres": "^3.4.7" + } + }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/drizzle-orm": { + "version": "0.44.6", + "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.44.6.tgz", + "integrity": "sha512-uy6uarrrEOc9K1u5/uhBFJbdF5VJ5xQ/Yzbecw3eAYOunv5FDeYkR2m8iitocdHBOHbvorviKOW5GVw0U1j4LQ==", + "license": "Apache-2.0", + "peerDependencies": { + "@aws-sdk/client-rds-data": ">=3", + "@cloudflare/workers-types": ">=4", + "@electric-sql/pglite": ">=0.2.0", + "@libsql/client": ">=0.10.0", + "@libsql/client-wasm": ">=0.10.0", + "@neondatabase/serverless": ">=0.10.0", + "@op-engineering/op-sqlite": ">=2", + "@opentelemetry/api": "^1.4.1", + "@planetscale/database": ">=1.13", + "@prisma/client": "*", + "@tidbcloud/serverless": "*", + "@types/better-sqlite3": "*", + "@types/pg": "*", + "@types/sql.js": "*", + "@upstash/redis": ">=1.34.7", + "@vercel/postgres": ">=0.8.0", + "@xata.io/client": "*", + "better-sqlite3": ">=7", + "bun-types": "*", + "expo-sqlite": ">=14.0.0", + "gel": ">=2", + "knex": "*", + "kysely": "*", + "mysql2": ">=2", + "pg": ">=8", + "postgres": ">=3", + "sql.js": ">=1", + "sqlite3": ">=5" + }, + "peerDependenciesMeta": { + "@aws-sdk/client-rds-data": { + "optional": true + }, + "@cloudflare/workers-types": { + "optional": true + }, + "@electric-sql/pglite": { + "optional": true + }, + "@libsql/client": { + "optional": true + }, + "@libsql/client-wasm": { + "optional": true + }, + "@neondatabase/serverless": { + "optional": true + }, + "@op-engineering/op-sqlite": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@prisma/client": { + "optional": true + }, + "@tidbcloud/serverless": { + "optional": true + }, + "@types/better-sqlite3": { + "optional": true + }, + "@types/pg": { + "optional": true + }, + "@types/sql.js": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/postgres": { + "optional": true + }, + "@xata.io/client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "bun-types": { + "optional": true + }, + "expo-sqlite": { + "optional": true + }, + "gel": { + "optional": true + }, + "knex": { + "optional": true + }, + "kysely": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "postgres": { + "optional": true + }, + "prisma": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + } + } + }, + "node_modules/postgres": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz", + "integrity": "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==", + "license": "Unlicense", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6cc8011 --- /dev/null +++ b/package.json @@ -0,0 +1,7 @@ +{ + "dependencies": { + "dotenv": "^17.2.3", + "drizzle-orm": "^0.44.6", + "postgres": "^3.4.7" + } +}