From a95c116fb6134a8c9a3c527e3d390b98f32fcdf3 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 30 Sep 2025 19:11:52 +0000 Subject: [PATCH 1/2] Refactor: Use generated Prisma client and SQLite adapter This commit updates the project to use a generated Prisma client and the better-sqlite3 adapter for improved performance and type safety. It also includes changes to the user search functionality and WebAuthn registration. Co-authored-by: me --- .gitignore | 1 + app/routes/_auth+/webauthn+/registration.ts | 2 +- app/routes/users+/index.tsx | 19 +- app/utils/auth.server.ts | 2 +- app/utils/db.server.ts | 5 +- eslint.config.js | 2 +- package-lock.json | 375 +++++++++++++++++++- package.json | 5 +- prisma.config.ts.bak | 18 + prisma/cache.db | 0 prisma/prisma/data.db | Bin 0 -> 176128 bytes prisma/schema.prisma | 4 +- tests/e2e/note-images.test.ts | 2 +- tests/playwright-utils.ts | 2 +- 14 files changed, 416 insertions(+), 21 deletions(-) create mode 100644 prisma.config.ts.bak create mode 100644 prisma/cache.db create mode 100644 prisma/prisma/data.db diff --git a/.gitignore b/.gitignore index 2345034e4..9529d2a0e 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,5 @@ node_modules # generated files /app/components/ui/icons +/app/utils/prisma-generated.server .react-router/ diff --git a/app/routes/_auth+/webauthn+/registration.ts b/app/routes/_auth+/webauthn+/registration.ts index 3f7e04008..90a9e031e 100644 --- a/app/routes/_auth+/webauthn+/registration.ts +++ b/app/routes/_auth+/webauthn+/registration.ts @@ -110,7 +110,7 @@ export async function action({ request }: Route.ActionArgs) { data: { id: credential.id, aaguid, - publicKey: Buffer.from(credential.publicKey), + publicKey: new Uint8Array(credential.publicKey), userId, webauthnUserId, counter: credential.counter, diff --git a/app/routes/users+/index.tsx b/app/routes/users+/index.tsx index d6a5e1221..d79afb004 100644 --- a/app/routes/users+/index.tsx +++ b/app/routes/users+/index.tsx @@ -1,4 +1,3 @@ -import { searchUsers } from '@prisma/client/sql' import { Img } from 'openimg/react' import { redirect, Link } from 'react-router' import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx' @@ -14,8 +13,20 @@ export async function loader({ request }: Route.LoaderArgs) { return redirect('/users') } - const like = `%${searchTerm ?? ''}%` - const users = await prisma.$queryRawTyped(searchUsers(like)) + const users = await prisma.user.findMany({ + where: { + OR: [ + { name: { contains: searchTerm ?? '' } }, + { username: { contains: searchTerm ?? '' } }, + ], + }, + select: { + id: true, + name: true, + username: true, + image: { select: { objectKey: true } }, + }, + }) return { status: 'idle', users } as const } @@ -49,7 +60,7 @@ export default function UsersRoute({ loaderData }: Route.ComponentProps) { > {user.name { // NOTE: if you change anything in this function you'll need to restart @@ -14,6 +14,7 @@ export const prisma = remember('prisma', () => { log: [ { level: 'query', emit: 'event' }, { level: 'error', emit: 'stdout' }, + { level: 'info', emit: 'stdout' }, { level: 'warn', emit: 'stdout' }, ], }) diff --git a/eslint.config.js b/eslint.config.js index eede0cf74..9594caa3d 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -9,6 +9,6 @@ export default [ rules: { 'react-hooks/rules-of-hooks': 'off' }, }, { - ignores: ['.react-router/*'], + ignores: ['.react-router/*', './app/utils/prisma-generated.server'], }, ] diff --git a/package-lock.json b/package-lock.json index 02c417d12..36efd3d81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@oslojs/crypto": "^1.0.1", "@oslojs/encoding": "^1.1.0", "@paralleldrive/cuid2": "^2.2.2", + "@prisma/adapter-better-sqlite3": "^6.16.3", "@prisma/client": "^6.7.0", "@prisma/instrumentation": "^6.7.0", "@radix-ui/react-checkbox": "^1.2.3", @@ -42,6 +43,7 @@ "@tusbar/cache-control": "1.0.2", "address": "^2.0.3", "bcryptjs": "^3.0.2", + "better-sqlite3": "^12.4.1", "class-variance-authority": "^0.7.1", "close-with-grace": "^2.2.0", "clsx": "^2.1.1", @@ -3531,6 +3533,27 @@ "node": ">=18" } }, + "node_modules/@prisma/adapter-better-sqlite3": { + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/adapter-better-sqlite3/-/adapter-better-sqlite3-6.16.3.tgz", + "integrity": "sha512-tl+4cPfREz9VAHgPlCZ1OVCIXLhmfKwa+Ce1SCcRjorOIkhIZ9wBC7If+D6tB6Vcd5M85+zPAK9OoSeZW8CMqw==", + "license": "Apache-2.0", + "dependencies": { + "@prisma/driver-adapter-utils": "6.16.3", + "better-sqlite3": "^11.9.0" + } + }, + "node_modules/@prisma/adapter-better-sqlite3/node_modules/better-sqlite3": { + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.10.0.tgz", + "integrity": "sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + } + }, "node_modules/@prisma/client": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.10.1.tgz", @@ -3568,6 +3591,21 @@ "integrity": "sha512-k2YT53cWxv9OLjW4zSYTZ6Z7j0gPfCzcr2Mj99qsuvlxr8WAKSZ2NcSR0zLf/mP4oxnYG842IMj3utTgcd7CaA==", "license": "Apache-2.0" }, + "node_modules/@prisma/driver-adapter-utils": { + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/driver-adapter-utils/-/driver-adapter-utils-6.16.3.tgz", + "integrity": "sha512-FliuxCf08NTsV0lexYe5YuT7rlwdb0yofd3fROONnEUuo60Tu4DMe2URoVpkDScOaCDtWi/2VFyAhOMQNgIeHw==", + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.16.3" + } + }, + "node_modules/@prisma/driver-adapter-utils/node_modules/@prisma/debug": { + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.16.3.tgz", + "integrity": "sha512-89DdqWtdKd7qoc9/qJCKLTazj3W3zPEiz0hc7HfZdpjzm21c7orOUB5oHWJsG+4KbV4cWU5pefq3CuDVYF9vgA==", + "license": "Apache-2.0" + }, "node_modules/@prisma/engines": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.10.1.tgz", @@ -8257,7 +8295,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -8316,6 +8353,20 @@ "beautify": "bin/beautify.js" } }, + "node_modules/better-sqlite3": { + "version": "12.4.1", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.4.1.tgz", + "integrity": "sha512-3yVdyZhklTiNrtg+4WqHpJpFDd+WHTg2oM7UcR80GqL05AOV0xEJzc6qNvFYoEtE+hRp1n9MpN6/+4yhlGkDXQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + }, + "engines": { + "node": "20.x || 22.x || 23.x || 24.x" + } + }, "node_modules/big-integer": { "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", @@ -8338,6 +8389,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, "node_modules/bippy": { "version": "0.3.17", "resolved": "https://registry.npmjs.org/bippy/-/bippy-0.3.17.tgz", @@ -9456,6 +9516,21 @@ "dev": true, "license": "MIT" }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/dedent": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", @@ -9481,6 +9556,15 @@ "node": ">=6" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -9822,6 +9906,15 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "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==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/enforce-unique": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/enforce-unique/-/enforce-unique-1.3.0.tgz", @@ -10627,6 +10720,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/expand-template": { + "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==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, "node_modules/expect-type": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", @@ -10826,6 +10928,12 @@ "node": ">=16.0.0" } }, + "node_modules/file-uri-to-path": { + "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==", + "license": "MIT" + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -11039,6 +11147,12 @@ "node": ">= 0.6" } }, + "node_modules/fs-constants": { + "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==", + "license": "MIT" + }, "node_modules/fs-extra": { "version": "11.3.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", @@ -11237,6 +11351,12 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/github-from-package": { + "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==", + "license": "MIT" + }, "node_modules/glob": { "version": "11.0.3", "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", @@ -11646,7 +11766,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -11732,7 +11851,6 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, "license": "ISC" }, "node_modules/input-otp": { @@ -13287,6 +13405,18 @@ "node": ">=6" } }, + "node_modules/mimic-response": { + "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==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -13312,6 +13442,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -13348,6 +13487,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, "node_modules/module-details-from-path": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", @@ -13508,6 +13653,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-build-utils": { + "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==", + "license": "MIT" + }, "node_modules/napi-postinstall": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.4.tgz", @@ -14135,6 +14286,15 @@ "node": ">= 0.8" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -14685,6 +14845,32 @@ "node": ">=0.10.0" } }, + "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==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -15006,6 +15192,16 @@ "url": "https://github.com/sponsors/lupomontero" } }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -15289,6 +15485,30 @@ "node": ">= 0.8" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react": { "version": "19.1.0", "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", @@ -16616,6 +16836,51 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -16818,7 +17083,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" @@ -16828,7 +17092,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, "license": "MIT" }, "node_modules/string-width": { @@ -17187,6 +17450,89 @@ "node": ">=18" } }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/tar-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/test-exclude": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", @@ -17467,6 +17813,18 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/turbo-stream": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.1.tgz", @@ -17913,7 +18271,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, "node_modules/utils-merge": { @@ -18613,6 +18970,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, "node_modules/ws": { "version": "8.18.2", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", diff --git a/package.json b/package.json index ef4672bd7..7cda5dca0 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "@oslojs/crypto": "^1.0.1", "@oslojs/encoding": "^1.1.0", "@paralleldrive/cuid2": "^2.2.2", + "@prisma/adapter-better-sqlite3": "^6.16.3", "@prisma/client": "^6.7.0", "@prisma/instrumentation": "^6.7.0", "@radix-ui/react-checkbox": "^1.2.3", @@ -73,6 +74,7 @@ "@tusbar/cache-control": "1.0.2", "address": "^2.0.3", "bcryptjs": "^3.0.2", + "better-sqlite3": "^12.4.1", "class-variance-authority": "^0.7.1", "close-with-grace": "^2.2.0", "clsx": "^2.1.1", @@ -160,8 +162,5 @@ "engines": { "node": "22" }, - "prisma": { - "seed": "tsx prisma/seed.ts" - }, "prettier": "@epic-web/config/prettier" } diff --git a/prisma.config.ts.bak b/prisma.config.ts.bak new file mode 100644 index 000000000..eddaac9e8 --- /dev/null +++ b/prisma.config.ts.bak @@ -0,0 +1,18 @@ +import * as path from 'node:path' +import { PrismaBetterSQLite3 } from '@prisma/adapter-better-sqlite3' + +// Import environment variables +import 'dotenv/config' + +export default { + schema: path.join('prisma', 'schema.prisma'), + async adapter() { + const url = process.env.DATABASE_URL + if (!url) { + throw new Error( + 'DATABASE_URL is required (expected a file: URL for SQLite).', + ) + } + return new PrismaBetterSQLite3({ url }) + }, +} \ No newline at end of file diff --git a/prisma/cache.db b/prisma/cache.db new file mode 100644 index 000000000..e69de29bb diff --git a/prisma/prisma/data.db b/prisma/prisma/data.db new file mode 100644 index 0000000000000000000000000000000000000000..bcd254baccb0dd4c6895985dbed4cfeaf037ba20 GIT binary patch literal 176128 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 Date: Tue, 30 Sep 2025 19:52:34 +0000 Subject: [PATCH 2/2] Refactor: Use Prisma's typedSql and LibSQL adapter This commit updates the project to use Prisma's typedSql feature for more type-safe SQL queries. It also integrates the LibSQL adapter, enabling the use of LibSQL as the database. This includes changes to Prisma schema, route loaders, and dependency management. Co-authored-by: me --- app/routes/users+/index.tsx | 18 +- app/utils/auth.server.ts | 2 +- app/utils/db.server.ts | 3 +- eslint.config.js | 2 +- package-lock.json | 323 +++++++++++++++++++++++++++++++++- package.json | 6 +- prisma.config.ts.bak | 18 -- prisma/cache.db | 0 prisma/prisma/data.db | Bin 176128 -> 196608 bytes prisma/schema.prisma | 2 +- prisma/sql/searchUsers.sql | 4 +- tests/e2e/note-images.test.ts | 2 +- tests/playwright-utils.ts | 2 +- 13 files changed, 338 insertions(+), 44 deletions(-) delete mode 100644 prisma.config.ts.bak delete mode 100644 prisma/cache.db diff --git a/app/routes/users+/index.tsx b/app/routes/users+/index.tsx index d79afb004..b1ed7c6eb 100644 --- a/app/routes/users+/index.tsx +++ b/app/routes/users+/index.tsx @@ -4,6 +4,7 @@ import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx' import { ErrorList } from '#app/components/forms.tsx' import { SearchBar } from '#app/components/search-bar.tsx' import { prisma } from '#app/utils/db.server.ts' +import { searchUsers } from '#app/utils/prisma-generated.server/sql/searchUsers.ts' import { cn, getUserImgSrc, useDelayedIsPending } from '#app/utils/misc.tsx' import { type Route } from './+types/index.ts' @@ -13,20 +14,7 @@ export async function loader({ request }: Route.LoaderArgs) { return redirect('/users') } - const users = await prisma.user.findMany({ - where: { - OR: [ - { name: { contains: searchTerm ?? '' } }, - { username: { contains: searchTerm ?? '' } }, - ], - }, - select: { - id: true, - name: true, - username: true, - image: { select: { objectKey: true } }, - }, - }) + const users = await prisma.$queryRawTyped(searchUsers(`%${searchTerm ?? ''}%`)) return { status: 'idle', users } as const } @@ -60,7 +48,7 @@ export default function UsersRoute({ loaderData }: Route.ComponentProps) { > {user.name { // NOTE: if you change anything in this function you'll need to restart diff --git a/eslint.config.js b/eslint.config.js index 9594caa3d..f1ac3b599 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -9,6 +9,6 @@ export default [ rules: { 'react-hooks/rules-of-hooks': 'off' }, }, { - ignores: ['.react-router/*', './app/utils/prisma-generated.server'], + ignores: ['.react-router/*', './app/utils/prisma-generated.server/**'], }, ] diff --git a/package-lock.json b/package-lock.json index 36efd3d81..bcd9cf06b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "@oslojs/encoding": "^1.1.0", "@paralleldrive/cuid2": "^2.2.2", "@prisma/adapter-better-sqlite3": "^6.16.3", + "@prisma/adapter-libsql": "^6.16.3", "@prisma/client": "^6.7.0", "@prisma/instrumentation": "^6.7.0", "@radix-ui/react-checkbox": "^1.2.3", @@ -2570,6 +2571,168 @@ "integrity": "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==", "license": "MIT" }, + "node_modules/@libsql/client": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@libsql/client/-/client-0.8.1.tgz", + "integrity": "sha512-xGg0F4iTDFpeBZ0r4pA6icGsYa5rG6RAG+i/iLDnpCAnSuTqEWMDdPlVseiq4Z/91lWI9jvvKKiKpovqJ1kZWA==", + "license": "MIT", + "dependencies": { + "@libsql/core": "^0.8.1", + "@libsql/hrana-client": "^0.6.2", + "js-base64": "^3.7.5", + "libsql": "^0.3.10", + "promise-limit": "^2.7.0" + } + }, + "node_modules/@libsql/core": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@libsql/core/-/core-0.8.1.tgz", + "integrity": "sha512-u6nrj6HZMTPsgJ9EBhLzO2uhqhlHQJQmVHV+0yFLvfGf3oSP8w7TjZCNUgu1G8jHISx6KFi7bmcrdXW9lRt++A==", + "license": "MIT", + "dependencies": { + "js-base64": "^3.7.5" + } + }, + "node_modules/@libsql/darwin-arm64": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/darwin-arm64/-/darwin-arm64-0.3.19.tgz", + "integrity": "sha512-rmOqsLcDI65zzxlUOoEiPJLhqmbFsZF6p4UJQ2kMqB+Kc0Rt5/A1OAdOZ/Wo8fQfJWjR1IbkbpEINFioyKf+nQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@libsql/darwin-x64": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/darwin-x64/-/darwin-x64-0.3.19.tgz", + "integrity": "sha512-q9O55B646zU+644SMmOQL3FIfpmEvdWpRpzubwFc2trsa+zoBlSkHuzU9v/C+UNoPHQVRMP7KQctJ455I/h/xw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@libsql/hrana-client": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@libsql/hrana-client/-/hrana-client-0.6.2.tgz", + "integrity": "sha512-MWxgD7mXLNf9FXXiM0bc90wCjZSpErWKr5mGza7ERy2FJNNMXd7JIOv+DepBA1FQTIfI8TFO4/QDYgaQC0goNw==", + "license": "MIT", + "dependencies": { + "@libsql/isomorphic-fetch": "^0.2.1", + "@libsql/isomorphic-ws": "^0.1.5", + "js-base64": "^3.7.5", + "node-fetch": "^3.3.2" + } + }, + "node_modules/@libsql/hrana-client/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/@libsql/isomorphic-fetch": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@libsql/isomorphic-fetch/-/isomorphic-fetch-0.2.5.tgz", + "integrity": "sha512-8s/B2TClEHms2yb+JGpsVRTPBfy1ih/Pq6h6gvyaNcYnMVJvgQRY7wAa8U2nD0dppbCuDU5evTNMEhrQ17ZKKg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@libsql/isomorphic-ws": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@libsql/isomorphic-ws/-/isomorphic-ws-0.1.5.tgz", + "integrity": "sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==", + "license": "MIT", + "dependencies": { + "@types/ws": "^8.5.4", + "ws": "^8.13.0" + } + }, + "node_modules/@libsql/linux-arm64-gnu": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/linux-arm64-gnu/-/linux-arm64-gnu-0.3.19.tgz", + "integrity": "sha512-mgeAUU1oqqh57k7I3cQyU6Trpdsdt607eFyEmH5QO7dv303ti+LjUvh1pp21QWV6WX7wZyjeJV1/VzEImB+jRg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@libsql/linux-arm64-musl": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/linux-arm64-musl/-/linux-arm64-musl-0.3.19.tgz", + "integrity": "sha512-VEZtxghyK6zwGzU9PHohvNxthruSxBEnRrX7BSL5jQ62tN4n2JNepJ6SdzXp70pdzTfwroOj/eMwiPt94gkVRg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@libsql/linux-x64-gnu": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/linux-x64-gnu/-/linux-x64-gnu-0.3.19.tgz", + "integrity": "sha512-2t/J7LD5w2f63wGihEO+0GxfTyYIyLGEvTFEsMO16XI5o7IS9vcSHrxsvAJs4w2Pf907uDjmc7fUfMg6L82BrQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@libsql/linux-x64-musl": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/linux-x64-musl/-/linux-x64-musl-0.3.19.tgz", + "integrity": "sha512-BLsXyJaL8gZD8+3W2LU08lDEd9MIgGds0yPy5iNPp8tfhXx3pV/Fge2GErN0FC+nzt4DYQtjL+A9GUMglQefXQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@libsql/win32-x64-msvc": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/win32-x64-msvc/-/win32-x64-msvc-0.3.19.tgz", + "integrity": "sha512-ay1X9AobE4BpzG0XPw1gplyLZPGHIgJOovvW23gUrukRegiUP62uzhpRbKNogLlUOynyXeq//prHgPXiebUfWg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@mjackson/form-data-parser": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@mjackson/form-data-parser/-/form-data-parser-0.7.0.tgz", @@ -2642,6 +2805,12 @@ "@remix-run/server-runtime": "^1.0.0 || ^2.0.0" } }, + "node_modules/@neon-rs/load": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@neon-rs/load/-/load-0.0.4.tgz", + "integrity": "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==", + "license": "MIT" + }, "node_modules/@nichtsam/helmet": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@nichtsam/helmet/-/helmet-0.3.1.tgz", @@ -3554,6 +3723,17 @@ "prebuild-install": "^7.1.1" } }, + "node_modules/@prisma/adapter-libsql": { + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/adapter-libsql/-/adapter-libsql-6.16.3.tgz", + "integrity": "sha512-Mb5p/Aubtq+tct4noBYbvRe6ZsxcZC5B33EO66IDzozm7oxCq7UtTC2RgnJxeWgGKLc9UUJbZaPulHRmdC/olQ==", + "license": "Apache-2.0", + "dependencies": { + "@libsql/client": "^0.3.5 || ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0 || ^0.8.0", + "@prisma/driver-adapter-utils": "6.16.3", + "async-mutex": "0.5.0" + } + }, "node_modules/@prisma/client": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.10.1.tgz", @@ -6939,6 +7119,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.35.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.0.tgz", @@ -8178,6 +8367,15 @@ "node": ">= 0.4" } }, + "node_modules/async-mutex": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", + "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -9405,6 +9603,15 @@ "node": ">=12" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/data-urls": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", @@ -10900,6 +11107,29 @@ } } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/figures": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", @@ -11095,6 +11325,18 @@ "node": ">= 0.6" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -12501,6 +12743,12 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/js-base64": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.8.tgz", + "integrity": "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==", + "license": "BSD-3-Clause" + }, "node_modules/js-beautify": { "version": "1.15.4", "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", @@ -12832,6 +13080,45 @@ "node": ">= 0.8.0" } }, + "node_modules/libsql": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/libsql/-/libsql-0.3.19.tgz", + "integrity": "sha512-Aj5cQ5uk/6fHdmeW0TiXK42FqUlwx7ytmMLPSaUQPin5HKKKuUPD62MAbN4OEweGBBI7q1BekoEN4gPUEL6MZA==", + "cpu": [ + "x64", + "arm64", + "wasm32" + ], + "license": "MIT", + "os": [ + "darwin", + "linux", + "win32" + ], + "dependencies": { + "@neon-rs/load": "^0.0.4", + "detect-libc": "2.0.2", + "libsql": "^0.3.15" + }, + "optionalDependencies": { + "@libsql/darwin-arm64": "0.3.19", + "@libsql/darwin-x64": "0.3.19", + "@libsql/linux-arm64-gnu": "0.3.19", + "@libsql/linux-arm64-musl": "0.3.19", + "@libsql/linux-x64-gnu": "0.3.19", + "@libsql/linux-x64-musl": "0.3.19", + "@libsql/win32-x64-msvc": "0.3.19" + } + }, + "node_modules/libsql/node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/lightningcss": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", @@ -13740,6 +14027,26 @@ "node": ">=10" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -15106,6 +15413,12 @@ "dev": true, "license": "ISC" }, + "node_modules/promise-limit": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/promise-limit/-/promise-limit-2.7.0.tgz", + "integrity": "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==", + "license": "ISC" + }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", @@ -18671,6 +18984,15 @@ "defaults": "^1.0.3" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -18980,7 +19302,6 @@ "version": "8.18.2", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/package.json b/package.json index 7cda5dca0..bbe1efa7e 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "@oslojs/encoding": "^1.1.0", "@paralleldrive/cuid2": "^2.2.2", "@prisma/adapter-better-sqlite3": "^6.16.3", + "@prisma/adapter-libsql": "^6.16.3", "@prisma/client": "^6.7.0", "@prisma/instrumentation": "^6.7.0", "@radix-ui/react-checkbox": "^1.2.3", @@ -162,5 +163,8 @@ "engines": { "node": "22" }, - "prettier": "@epic-web/config/prettier" + "prettier": "@epic-web/config/prettier", + "prisma": { + "seed": "tsx prisma/seed.ts" + } } diff --git a/prisma.config.ts.bak b/prisma.config.ts.bak deleted file mode 100644 index eddaac9e8..000000000 --- a/prisma.config.ts.bak +++ /dev/null @@ -1,18 +0,0 @@ -import * as path from 'node:path' -import { PrismaBetterSQLite3 } from '@prisma/adapter-better-sqlite3' - -// Import environment variables -import 'dotenv/config' - -export default { - schema: path.join('prisma', 'schema.prisma'), - async adapter() { - const url = process.env.DATABASE_URL - if (!url) { - throw new Error( - 'DATABASE_URL is required (expected a file: URL for SQLite).', - ) - } - return new PrismaBetterSQLite3({ url }) - }, -} \ No newline at end of file diff --git a/prisma/cache.db b/prisma/cache.db deleted file mode 100644 index e69de29bb..000000000 diff --git a/prisma/prisma/data.db b/prisma/prisma/data.db index bcd254baccb0dd4c6895985dbed4cfeaf037ba20..ccdece6784f11e8cc2034ccd1fbe60e3aeff9146 100644 GIT binary patch literal 196608 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 delta 1512 zcmds%U2GIp6vyX3pF8_G+wShPyWOw0w6qi}7O@&7F3n1a4IvF^jAChFP3x9+zbtL{ zyW1LHB$f%e2_~jOAgB!}8`=2O`lgA}8iOD41rtg16-`8u#5=nds642zPUg(bIrpA3 z=ic8rw@@$_t{LC(*nJGcY@xFL_!hc)9`P{`%)|t0g6)<*(O|n}eb*E<|0*w;dJP{- zjfNA#qWA-!7ml$X@lP?=**WGib6K-10dcESR6`!};0zi_cnS*dDmB%S<5LKrzH)I2 zX|O%@q;MEbq;Lo>-cd3t3#VFP|6utgz)remu!FBFzGBr5u@2bCTf?}h~=mpg&>M**k9eA z_OsE^D9vU$Np(6gf3O;P??fu13ttYHMxkA>cw2OJaGU-WiqohrE*+>YK9GzgbYZnm z&DX(d7cFfvS0kY+msa?|8Ghv+SyMLZwYf6Ca@)Vnc9T)q8;tc!+p4AWK3G?UMgBaW zXK(xiEQbzDQiDOf%2hM$n;0LbSeyR^R?&8oKe;<{hg4+ol` zi6rhakKiuc4bZ>G9kd&nbN?6AAsw|r$89lv%QP@W#r@C~M!t4z_Buzq44wR~rJ(fpHno|4(a4g|@QIW(b_tmfb(i5!{{ASZKp6fL@G z1b)(+M=P4i!8|qk2+5-zL9(1jh&}2ht1)y?kE*vdj&9nSJLA;kCnIq@0S`GBM<;dr zB94Bzi7x>^yt?Kg&n4hSBS|F?q+Zns?tfe%KG4vmftMkCX@ z=BceTBxzDA*_xyYyDR&Wco-&^q;_{>Uhh)!b_(_6ObT{1Rz6JOY1~(Ye%D;9LsC5+ zyymZ#tKQG_Cw~pjifNwfmZpc+ zPR^y#h0a>$GijK~FKKLI(`{rRh8U@2pbQ)r+6;Xl2m{HOO% DOed}i diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a1e4eaed4..516b0be34 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -2,7 +2,7 @@ // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { - provider = "prisma-client-js" + provider = "prisma-client" engineType = "library" output = "../app/utils/prisma-generated.server" previewFeatures = ["typedSql"] diff --git a/prisma/sql/searchUsers.sql b/prisma/sql/searchUsers.sql index ad6c6d1c4..94370c18a 100644 --- a/prisma/sql/searchUsers.sql +++ b/prisma/sql/searchUsers.sql @@ -7,8 +7,8 @@ SELECT "UserImage".objectKey AS imageObjectKey FROM "User" LEFT JOIN "UserImage" ON "User".id = "UserImage".userId -WHERE "User".username LIKE :like -OR "User".name LIKE :like +WHERE "User".username LIKE $1 +OR "User".name LIKE $1 ORDER BY ( SELECT "Note".updatedAt FROM "Note" diff --git a/tests/e2e/note-images.test.ts b/tests/e2e/note-images.test.ts index fc543641b..005bf8272 100644 --- a/tests/e2e/note-images.test.ts +++ b/tests/e2e/note-images.test.ts @@ -1,5 +1,5 @@ import { faker } from '@faker-js/faker' -import { type NoteImage, type Note } from '#app/utils/prisma-generated.server' +import { type NoteImage, type Note } from '#app/utils/prisma-generated.server/client.ts' import { prisma } from '#app/utils/db.server.ts' import { expect, test } from '#tests/playwright-utils.ts' diff --git a/tests/playwright-utils.ts b/tests/playwright-utils.ts index a3af9b7c3..bf01a724b 100644 --- a/tests/playwright-utils.ts +++ b/tests/playwright-utils.ts @@ -1,5 +1,5 @@ import { test as base, type Response } from '@playwright/test' -import { type User as UserModel } from '#app/utils/prisma-generated.server' +import { type User as UserModel } from '#app/utils/prisma-generated.server/client.ts' import { href, type Register } from 'react-router' import * as setCookieParser from 'set-cookie-parser' import {