diff --git a/.env.example b/.env.example index e9a4195..1e91e78 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,6 @@ PORT=5000 NODE_ENV=development -STELLAR_NETWORK=testnet # testnet | mainnet (default: testnet) +STELLAR_NETWORK=testnet JWT_SECRET=your_jwt_secret -DATABASE_URL=postgresql://user:password@localhost:5432/learnault \ No newline at end of file +# Database Configuration +DATABASE_URL="postgresql://username:password@localhost:5432/learnault_db?schema=public" \ No newline at end of file diff --git a/README.md b/README.md index b5ddc57..1e38e66 100644 --- a/README.md +++ b/README.md @@ -67,10 +67,16 @@ pnpm install # Set up environment variables cp .env.example .env +# Set up database +pnpm db:migrate +pnpm db:seed + # Run development environment pnpm dev ``` +For detailed database setup instructions, see [Prisma Setup Guide](./prisma/SETUP.md) + ### Development Workflow ```bash diff --git a/package.json b/package.json index 4b3dadc..8bb687d 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "description": "Decentralized learn-to-earn platform on Stellar", + "type": "module", "keywords": [ "stellar", "education", @@ -25,19 +26,23 @@ "test": "vitest", "test:watch": "vitest", "test:coverage": "vitest run --coverage", - "test:ci": "vitest run" + "test:ci": "vitest run", + "db:migrate": "prisma migrate dev", + "db:seed": "tsx prisma/seed.ts", + "db:studio": "prisma studio" }, "dependencies": { - "@prisma/client": "^7.4.1", + "@prisma/adapter-pg": "^7.4.2", + "@prisma/client": "^7.4.2", "@stellar/stellar-sdk": "^14.6.1", - "bcrypt": "^5.1.1", + "bcryptjs": "^3.0.3", "cors": "^2.8.6", "dotenv": "^16.6.1", "express": "^5.2.1", "helmet": "^8.1.0", "jsonwebtoken": "^9.0.2", "morgan": "^1.10.1", - "pg": "^8.11.3", + "pg": "^8.20.0", "winston": "^3.19.0" }, "devDependencies": { @@ -49,11 +54,12 @@ "@types/jsonwebtoken": "^9.0.5", "@types/morgan": "^1.9.10", "@types/node": "^22.19.13", + "@types/pg": "^8.18.0", "@types/supertest": "^7.2.0", "@vitest/coverage-v8": "4.0.18", "eslint": "^10.0.2", "nodemon": "^3.1.14", - "prisma": "^7.4.1", + "prisma": "^7.4.2", "supertest": "^7.2.2", "ts-node": "^10.9.2", "tsx": "^4.7.0", @@ -62,6 +68,9 @@ "vitest": "^4.0.18" }, "packageManager": "pnpm@10.0.0", + "prisma": { + "seed": "tsx prisma/seed.ts" + }, "engines": { "node": ">=20.0.0", "pnpm": ">=10.0.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e06cbad..a18b7e1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,15 +8,18 @@ importers: .: dependencies: + '@prisma/adapter-pg': + specifier: ^7.4.2 + version: 7.4.2 '@prisma/client': - specifier: ^7.4.1 + specifier: ^7.4.2 version: 7.4.2(prisma@7.4.2(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3) '@stellar/stellar-sdk': specifier: ^14.6.1 version: 14.6.1 - bcrypt: - specifier: ^5.1.1 - version: 5.1.1 + bcryptjs: + specifier: ^3.0.3 + version: 3.0.3 cors: specifier: ^2.8.6 version: 2.8.6 @@ -36,7 +39,7 @@ importers: specifier: ^1.10.1 version: 1.10.1 pg: - specifier: ^8.11.3 + specifier: ^8.20.0 version: 8.20.0 winston: specifier: ^3.19.0 @@ -66,6 +69,9 @@ importers: '@types/node': specifier: ^22.19.13 version: 22.19.15 + '@types/pg': + specifier: ^8.18.0 + version: 8.18.0 '@types/supertest': specifier: ^7.2.0 version: 7.2.0 @@ -79,7 +85,7 @@ importers: specifier: ^3.1.14 version: 3.1.14 prisma: - specifier: ^7.4.1 + specifier: ^7.4.2 version: 7.4.2(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) supertest: specifier: ^7.2.2 @@ -402,10 +408,6 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@mapbox/node-pre-gyp@1.0.11': - resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} - hasBin: true - '@mrleebo/prisma-ast@0.13.1': resolution: {integrity: sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw==} engines: {node: '>=16'} @@ -421,6 +423,9 @@ packages: '@paralleldrive/cuid2@2.3.1': resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} + '@prisma/adapter-pg@7.4.2': + resolution: {integrity: sha512-oUo2Zhe9Tf6YwVL8kLPuOLTK1Z2pwi/Ua77t2PuGyBan2w7shRKqHvYK+3XXmRH9RWhPJ4SMtHZKpNo6Ax/4bQ==} + '@prisma/client-runtime-utils@7.4.2': resolution: {integrity: sha512-cID+rzOEb38VyMsx5LwJMEY4NGIrWCNpKu/0ImbeooQ2Px7TI+kOt7cm0NelxUzF2V41UVVXAmYjANZQtCu1/Q==} @@ -448,6 +453,9 @@ packages: '@prisma/dev@0.20.0': resolution: {integrity: sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ==} + '@prisma/driver-adapter-utils@7.4.2': + resolution: {integrity: sha512-REdjFpT/ye9KdDs+CXAXPIbMQkVLhne9G5Pe97sNY4Ovx4r2DAbWM9hOFvvB1Oq8H8bOCdu0Ri3AoGALquQqVw==} + '@prisma/engines-version@7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919': resolution: {integrity: sha512-5FIKY3KoYQlBuZC2yc16EXfVRQ8HY+fLqgxkYfWCtKhRb3ajCRzP/rPeoSx11+NueJDANdh4hjY36mdmrTcGSg==} @@ -691,6 +699,9 @@ packages: '@types/node@22.19.15': resolution: {integrity: sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==} + '@types/pg@8.18.0': + resolution: {integrity: sha512-gT+oueVQkqnj6ajGJXblFR4iavIXWsGAFCk3dP4Kki5+a9R4NMt0JARdk6s8cUKcfUoqP5dAtDSLU8xYUTFV+Q==} + '@types/qs@6.15.0': resolution: {integrity: sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==} @@ -818,9 +829,6 @@ packages: '@vitest/utils@4.0.18': resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} - abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - accepts@2.0.0: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} @@ -839,29 +847,13 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - aproba@2.1.0: - resolution: {integrity: sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==} - - are-we-there-yet@2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} - deprecated: This package is no longer supported. - arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -892,9 +884,6 @@ packages: axios@1.13.6: resolution: {integrity: sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==} - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - balanced-match@4.0.4: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} @@ -910,9 +899,9 @@ packages: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} - bcrypt@5.1.1: - resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==} - engines: {node: '>= 10.0.0'} + bcryptjs@3.0.3: + resolution: {integrity: sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==} + hasBin: true bignumber.js@9.3.1: resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} @@ -925,9 +914,6 @@ packages: resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} engines: {node: '>=18'} - brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - brace-expansion@5.0.4: resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} engines: {node: 18 || 20 || >=22} @@ -987,10 +973,6 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} - chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} @@ -1009,10 +991,6 @@ packages: resolution: {integrity: sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==} engines: {node: '>=18'} - color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - color@5.0.3: resolution: {integrity: sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==} engines: {node: '>=18'} @@ -1028,9 +1006,6 @@ packages: component-emitter@1.3.1: resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - confbox@0.2.4: resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} @@ -1038,9 +1013,6 @@ packages: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} - console-control-strings@1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - content-disposition@1.0.1: resolution: {integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==} engines: {node: '>=18'} @@ -1112,9 +1084,6 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} @@ -1130,10 +1099,6 @@ packages: destr@2.0.5: resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -1161,9 +1126,6 @@ packages: effect@3.18.4: resolution: {integrity: sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==} - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - empathic@2.0.0: resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} engines: {node: '>=14'} @@ -1371,13 +1333,6 @@ packages: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} - fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1386,11 +1341,6 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - gauge@3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} - deprecated: This package is no longer supported. - generate-function@2.3.1: resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==} @@ -1423,10 +1373,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -1459,9 +1405,6 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -1484,10 +1427,6 @@ packages: http-status-codes@2.3.0: resolution: {integrity: sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==} - https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - iconv-lite@0.7.2: resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} @@ -1510,10 +1449,6 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -1533,10 +1468,6 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -1669,10 +1600,6 @@ packages: magicast@0.5.2: resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} - make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} @@ -1847,26 +1774,6 @@ packages: resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} - minimatch@3.1.5: - resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} - - minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - - minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - - minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - - mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - morgan@1.10.1: resolution: {integrity: sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==} engines: {node: '>= 0.8.0'} @@ -1897,39 +1804,18 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} - node-addon-api@5.1.0: - resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} - node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - nodemon@3.1.14: resolution: {integrity: sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==} engines: {node: '>=10'} hasBin: true - nopt@5.0.0: - resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} - engines: {node: '>=6'} - hasBin: true - normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - npmlog@5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - deprecated: This package is no longer supported. - nypm@0.6.5: resolution: {integrity: sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==} engines: {node: '>=18'} @@ -1987,10 +1873,6 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2064,6 +1946,10 @@ packages: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} + postgres-array@3.0.4: + resolution: {integrity: sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==} + engines: {node: '>=12'} + postgres-bytea@1.0.1: resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==} engines: {node: '>=0.10.0'} @@ -2169,11 +2055,6 @@ packages: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - rollup@4.59.0: resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -2199,10 +2080,6 @@ packages: scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - semver@7.7.4: resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} engines: {node: '>=10'} @@ -2219,9 +2096,6 @@ packages: resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} engines: {node: '>= 18'} - set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -2297,17 +2171,9 @@ packages: std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - superagent@10.3.0: resolution: {integrity: sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==} engines: {node: '>=14.18.0'} @@ -2324,11 +2190,6 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - text-hex@1.0.0: resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} @@ -2366,9 +2227,6 @@ packages: resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} hasBin: true - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - triple-beam@1.4.1: resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} engines: {node: '>= 14.0.0'} @@ -2542,12 +2400,6 @@ packages: jsdom: optional: true - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - which-typed-array@1.1.20: resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} engines: {node: '>= 0.4'} @@ -2562,9 +2414,6 @@ packages: engines: {node: '>=8'} hasBin: true - wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - winston-transport@4.9.0: resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} engines: {node: '>= 12.0.0'} @@ -2584,9 +2433,6 @@ packages: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} @@ -2819,21 +2665,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@mapbox/node-pre-gyp@1.0.11': - dependencies: - detect-libc: 2.1.2 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.7.4 - tar: 6.2.1 - transitivePeerDependencies: - - encoding - - supports-color - '@mrleebo/prisma-ast@0.13.1': dependencies: chevrotain: 10.5.0 @@ -2849,6 +2680,14 @@ snapshots: dependencies: '@noble/hashes': 1.8.0 + '@prisma/adapter-pg@7.4.2': + dependencies: + '@prisma/driver-adapter-utils': 7.4.2 + pg: 8.20.0 + postgres-array: 3.0.4 + transitivePeerDependencies: + - pg-native + '@prisma/client-runtime-utils@7.4.2': {} '@prisma/client@7.4.2(prisma@7.4.2(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3)': @@ -2893,6 +2732,10 @@ snapshots: transitivePeerDependencies: - typescript + '@prisma/driver-adapter-utils@7.4.2': + dependencies: + '@prisma/debug': 7.4.2 + '@prisma/engines-version@7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919': {} '@prisma/engines@7.4.2': @@ -3114,6 +2957,12 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/pg@8.18.0': + dependencies: + '@types/node': 22.19.15 + pg-protocol: 1.13.0 + pg-types: 2.2.0 + '@types/qs@6.15.0': {} '@types/range-parser@1.2.7': {} @@ -3297,8 +3146,6 @@ snapshots: '@vitest/pretty-format': 4.0.18 tinyrainbow: 3.0.3 - abbrev@1.1.1: {} - accepts@2.0.0: dependencies: mime-types: 3.0.2 @@ -3314,12 +3161,6 @@ snapshots: acorn@8.16.0: {} - agent-base@6.0.2: - dependencies: - debug: 4.4.3(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - ajv@6.14.0: dependencies: fast-deep-equal: 3.1.3 @@ -3327,20 +3168,11 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ansi-regex@5.0.1: {} - anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - aproba@2.1.0: {} - - are-we-there-yet@2.0.0: - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - arg@4.1.3: {} asap@2.0.6: {} @@ -3371,8 +3203,6 @@ snapshots: transitivePeerDependencies: - debug - balanced-match@1.0.2: {} - balanced-match@4.0.4: {} base32.js@0.1.0: {} @@ -3383,13 +3213,7 @@ snapshots: dependencies: safe-buffer: 5.1.2 - bcrypt@5.1.1: - dependencies: - '@mapbox/node-pre-gyp': 1.0.11 - node-addon-api: 5.1.0 - transitivePeerDependencies: - - encoding - - supports-color + bcryptjs@3.0.3: {} bignumber.js@9.3.1: {} @@ -3409,11 +3233,6 @@ snapshots: transitivePeerDependencies: - supports-color - brace-expansion@1.1.12: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - brace-expansion@5.0.4: dependencies: balanced-match: 4.0.4 @@ -3494,8 +3313,6 @@ snapshots: dependencies: readdirp: 4.1.2 - chownr@2.0.0: {} - citty@0.1.6: dependencies: consola: 3.4.2 @@ -3512,8 +3329,6 @@ snapshots: dependencies: color-name: 2.1.0 - color-support@1.1.3: {} - color@5.0.3: dependencies: color-convert: 3.1.3 @@ -3527,14 +3342,10 @@ snapshots: component-emitter@1.3.1: {} - concat-map@0.0.1: {} - confbox@0.2.4: {} consola@3.4.2: {} - console-control-strings@1.1.0: {} - content-disposition@1.0.1: {} content-type@1.0.5: {} @@ -3588,8 +3399,6 @@ snapshots: delayed-stream@1.0.0: {} - delegates@1.0.0: {} - denque@2.1.0: {} depd@2.0.0: {} @@ -3598,8 +3407,6 @@ snapshots: destr@2.0.5: {} - detect-libc@2.1.2: {} - devlop@1.1.0: dependencies: dequal: 2.0.3 @@ -3630,8 +3437,6 @@ snapshots: '@standard-schema/spec': 1.1.0 fast-check: 3.23.2 - emoji-regex@8.0.0: {} - empathic@2.0.0: {} enabled@2.0.0: {} @@ -3891,29 +3696,11 @@ snapshots: fresh@2.0.0: {} - fs-minipass@2.1.0: - dependencies: - minipass: 3.3.6 - - fs.realpath@1.0.0: {} - fsevents@2.3.3: optional: true function-bind@1.1.2: {} - gauge@3.0.2: - dependencies: - aproba: 2.1.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - generate-function@2.3.1: dependencies: is-property: 1.0.2 @@ -3961,15 +3748,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.5 - once: 1.4.0 - path-is-absolute: 1.0.1 - gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -3992,8 +3770,6 @@ snapshots: dependencies: has-symbols: 1.1.0 - has-unicode@2.0.1: {} - hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -4014,13 +3790,6 @@ snapshots: http-status-codes@2.3.0: {} - https-proxy-agent@5.0.1: - dependencies: - agent-base: 6.0.2 - debug: 4.4.3(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - iconv-lite@0.7.2: dependencies: safer-buffer: 2.1.2 @@ -4035,11 +3804,6 @@ snapshots: imurmurhash@0.1.4: {} - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - inherits@2.0.4: {} ipaddr.js@1.9.1: {} @@ -4052,8 +3816,6 @@ snapshots: is-extglob@2.1.1: {} - is-fullwidth-code-point@3.0.0: {} - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -4181,10 +3943,6 @@ snapshots: '@babel/types': 7.29.0 source-map-js: 1.2.1 - make-dir@3.1.0: - dependencies: - semver: 6.3.1 - make-dir@4.0.0: dependencies: semver: 7.7.4 @@ -4530,23 +4288,6 @@ snapshots: dependencies: brace-expansion: 5.0.4 - minimatch@3.1.5: - dependencies: - brace-expansion: 1.1.12 - - minipass@3.3.6: - dependencies: - yallist: 4.0.0 - - minipass@5.0.0: {} - - minizlib@2.1.2: - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - - mkdirp@1.0.4: {} - morgan@1.10.1: dependencies: basic-auth: 2.0.1 @@ -4583,14 +4324,8 @@ snapshots: negotiator@1.0.0: {} - node-addon-api@5.1.0: {} - node-fetch-native@1.6.7: {} - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - nodemon@3.1.14: dependencies: chokidar: 3.6.0 @@ -4604,19 +4339,8 @@ snapshots: touch: 3.1.1 undefsafe: 2.0.5 - nopt@5.0.0: - dependencies: - abbrev: 1.1.1 - normalize-path@3.0.0: {} - npmlog@5.0.1: - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - nypm@0.6.5: dependencies: citty: 0.2.1 @@ -4670,8 +4394,6 @@ snapshots: path-exists@4.0.0: {} - path-is-absolute@1.0.1: {} - path-key@3.1.1: {} path-to-regexp@8.3.0: {} @@ -4737,6 +4459,8 @@ snapshots: postgres-array@2.0.0: {} + postgres-array@3.0.4: {} + postgres-bytea@1.0.1: {} postgres-date@1.0.7: {} @@ -4833,10 +4557,6 @@ snapshots: retry@0.12.0: {} - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - rollup@4.59.0: dependencies: '@types/estree': 1.0.8 @@ -4888,8 +4608,6 @@ snapshots: scheduler@0.27.0: {} - semver@6.3.1: {} - semver@7.7.4: {} send@1.2.1: @@ -4919,8 +4637,6 @@ snapshots: transitivePeerDependencies: - supports-color - set-blocking@2.0.0: {} - set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -4996,20 +4712,10 @@ snapshots: std-env@3.10.0: {} - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - superagent@10.3.0: dependencies: component-emitter: 1.3.1 @@ -5040,15 +4746,6 @@ snapshots: dependencies: has-flag: 4.0.0 - tar@6.2.1: - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - text-hex@1.0.0: {} tinybench@2.9.0: {} @@ -5078,8 +4775,6 @@ snapshots: touch@3.1.1: {} - tr46@0.0.3: {} - triple-beam@1.4.1: {} ts-api-utils@2.4.0(typescript@5.9.3): @@ -5232,13 +4927,6 @@ snapshots: - tsx - yaml - webidl-conversions@3.0.1: {} - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - which-typed-array@1.1.20: dependencies: available-typed-arrays: 1.0.7 @@ -5258,10 +4946,6 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 - wide-align@1.1.5: - dependencies: - string-width: 4.2.3 - winston-transport@4.9.0: dependencies: logform: 2.7.0 @@ -5288,8 +4972,6 @@ snapshots: xtend@4.0.2: {} - yallist@4.0.0: {} - yn@3.1.1: {} yocto-queue@0.1.0: {} diff --git a/prisma.config.ts b/prisma.config.ts new file mode 100644 index 0000000..4ddab3a --- /dev/null +++ b/prisma.config.ts @@ -0,0 +1,12 @@ +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) \ No newline at end of file diff --git a/prisma/SETUP.md b/prisma/SETUP.md new file mode 100644 index 0000000..85f7f23 --- /dev/null +++ b/prisma/SETUP.md @@ -0,0 +1,202 @@ +# Prisma Setup Guide + +This directory contains the Prisma ORM configuration for the Learnault API. + +## Quick Start + +### 1. Install Dependencies + +Make sure all dependencies are installed: + +```bash +pnpm install +``` + +### 2. Configure Database + +Copy `.env.example` to `.env` and update the `DATABASE_URL` with your PostgreSQL connection string: + +```bash +cp .env.example .env +``` + +Example for local PostgreSQL: +```env +DATABASE_URL="postgresql://postgres:postgres@localhost:5432/learnault_dev?schema=public" +``` + +### 3. Run Migrations + +Create the database schema by running the initial migration: + +```bash +pnpm db:migrate +``` + +This will: +- Create all tables based on the schema defined in `schema.prisma` +- Store migration history in the `_prisma_migrations` table +- Generate the Prisma Client + +### 4. Seed the Database (Optional) + +Populate the database with mock data for development: + +```bash +pnpm db:seed +``` + +This will create: +- 2 test users +- 4 sample modules with different difficulties +- 3 module completions +- 2 credentials +- 3 transactions +- 1 webhook endpoint + +### 5. Verify Setup + +Open Prisma Studio to view and manage your data: + +```bash +pnpm db:studio +``` + +## Database Schema + +### Models + +#### User +- Email and wallet address are unique +- Relates to completions, credentials, and transactions +- Password is stored as bcrypt hash + +#### Module +- Contains course/learning content +- Has difficulty (easy, medium, hard) +- Associates reward amount +- Relates to completions and credentials + +#### Completion +- Links users to completed modules +- Stores completion score +- Unique constraint on userId + moduleId pair + +#### Credential +- NFT/on-chain credential issued upon module completion +- Stores on-chain ID if already issued +- Unique constraint on userId + moduleId pair + +#### Transaction +- Records all reward/transfer transactions +- Status tracking: pending, completed, failed +- Types: reward, refund, transfer + +#### WebhookEndpoint & WebhookDelivery +- For event webhook delivery +- Supports retry logic with configurable attempts + +## Useful Commands + +```bash +# Run migrations in development mode (interactive) +pnpm db:migrate + +# Create a new migration without running it +pnpm db:migrate -- --skip-apply + +# Reset database (caution: deletes all data) +prisma migrate reset + +# View database in Prisma Studio UI +pnpm db:studio + +# Generate Prisma Client +prisma generate + +# Seed database with mock data +pnpm db:seed + +# Format schema.prisma +prisma format +``` + +## Environment Configuration + +### Development +```env +DATABASE_URL="postgresql://postgres:postgres@localhost:5432/learnault_dev?schema=public" +NODE_ENV=development +``` + +### Production +```env +DATABASE_URL="postgresql://user:password@host:5432/learnault_prod?schema=public&sslmode=require" +NODE_ENV=production +``` + +## Setting Up PostgreSQL Locally + +### Using Docker + +```bash +docker run --name learnault-postgres \ + -e POSTGRES_USER=postgres \ + -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_DB=learnault_dev \ + -p 5432:5432 \ + -d postgres:15 +``` + +### Using Homebrew (macOS) + +```bash +brew install postgresql +brew services start postgresql +psql -U postgres -c "CREATE DATABASE learnault_dev;" +``` + +### Using APT (Ubuntu/Debian) + +```bash +sudo apt-get install postgresql postgresql-contrib +sudo -u postgres psql -c "CREATE DATABASE learnault_dev;" +``` + +## Testing the Connection + +After setup, test the connection from the Node.js application: + +```typescript +import { PrismaClient } from "@prisma/client"; + +const prisma = new PrismaClient(); + +async function main() { + const users = await prisma.user.findMany(); + console.log("Users:", users); +} + +main() + .catch(console.error) + .finally(() => prisma.$disconnect()); +``` + +## Troubleshooting + +### "Can't reach database server" +- Verify PostgreSQL is running +- Check DATABASE_URL format +- Ensure correct host, port, credentials + +### "Schema validation failed" +- Run `prisma migrate reset` to reset database +- Check for any migration files and review them + +### "Prisma Client not found" +- Run `pnpm install` to install dependencies +- Run `pnpm db:migrate` to regenerate Prisma Client + +### Import errors in seed.ts +- Ensure dependencies are installed: `pnpm install` +- Check that TypeScript and ts-node are in devDependencies diff --git a/prisma/migrations/20260307143903_init/migration.sql b/prisma/migrations/20260307143903_init/migration.sql new file mode 100644 index 0000000..b23aade --- /dev/null +++ b/prisma/migrations/20260307143903_init/migration.sql @@ -0,0 +1,128 @@ +-- CreateTable +CREATE TABLE "User" ( + "id" TEXT NOT NULL, + "email" TEXT NOT NULL, + "name" TEXT NOT NULL, + "walletAddress" TEXT, + "passwordHash" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Module" ( + "id" TEXT NOT NULL, + "title" TEXT NOT NULL, + "description" TEXT NOT NULL, + "category" TEXT NOT NULL, + "difficulty" TEXT NOT NULL, + "reward" DOUBLE PRECISION NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Module_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Completion" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "moduleId" TEXT NOT NULL, + "score" DOUBLE PRECISION NOT NULL, + "completedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Completion_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Credential" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "moduleId" TEXT NOT NULL, + "onChainId" TEXT, + "issuedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Credential_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Transaction" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "amount" DOUBLE PRECISION NOT NULL, + "type" TEXT NOT NULL, + "status" TEXT NOT NULL DEFAULT 'pending', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Transaction_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "WebhookEndpoint" ( + "id" TEXT NOT NULL, + "url" TEXT NOT NULL, + "secret" TEXT, + "description" TEXT, + "isActive" BOOLEAN NOT NULL DEFAULT true, + "events" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "WebhookEndpoint_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "WebhookDelivery" ( + "id" TEXT NOT NULL, + "endpointId" TEXT NOT NULL, + "eventType" TEXT NOT NULL, + "payload" TEXT NOT NULL, + "status" TEXT NOT NULL DEFAULT 'pending', + "statusCode" INTEGER, + "responseBody" TEXT, + "error" TEXT, + "attemptCount" INTEGER NOT NULL DEFAULT 0, + "maxAttempts" INTEGER NOT NULL DEFAULT 5, + "nextAttemptAt" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP, + "lastAttemptAt" TIMESTAMP(3), + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "WebhookDelivery_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_walletAddress_key" ON "User"("walletAddress"); + +-- CreateIndex +CREATE UNIQUE INDEX "Completion_userId_moduleId_key" ON "Completion"("userId", "moduleId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Credential_userId_moduleId_key" ON "Credential"("userId", "moduleId"); + +-- AddForeignKey +ALTER TABLE "Completion" ADD CONSTRAINT "Completion_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Completion" ADD CONSTRAINT "Completion_moduleId_fkey" FOREIGN KEY ("moduleId") REFERENCES "Module"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Credential" ADD CONSTRAINT "Credential_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Credential" ADD CONSTRAINT "Credential_moduleId_fkey" FOREIGN KEY ("moduleId") REFERENCES "Module"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Transaction" ADD CONSTRAINT "Transaction_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "WebhookDelivery" ADD CONSTRAINT "WebhookDelivery_endpointId_fkey" FOREIGN KEY ("endpointId") REFERENCES "WebhookEndpoint"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..044d57c --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b8085d0..9ddd7d2 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -3,8 +3,72 @@ generator client { } datasource db { - provider = "sqlite" - url = env("DATABASE_URL") + provider = "postgresql" +} + +model User { + id String @id @default(uuid()) + email String @unique + name String + walletAddress String? @unique + passwordHash String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + completions Completion[] + credentials Credential[] + transactions Transaction[] +} + +model Module { + id String @id @default(uuid()) + title String + description String + category String + difficulty String // easy, medium, hard + reward Float + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + completions Completion[] + credentials Credential[] +} + +model Completion { + id String @id @default(uuid()) + userId String + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + moduleId String + module Module @relation(fields: [moduleId], references: [id], onDelete: Cascade) + score Float + completedAt DateTime @default(now()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@unique([userId, moduleId]) +} + +model Credential { + id String @id @default(uuid()) + userId String + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + moduleId String + module Module @relation(fields: [moduleId], references: [id], onDelete: Cascade) + onChainId String? + issuedAt DateTime @default(now()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@unique([userId, moduleId]) +} + +model Transaction { + id String @id @default(uuid()) + userId String + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + amount Float + type String // reward, refund, transfer + status String @default("pending") // pending, completed, failed + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model WebhookEndpoint { @@ -22,7 +86,7 @@ model WebhookEndpoint { model WebhookDelivery { id String @id @default(uuid()) endpointId String - endpoint WebhookEndpoint @relation(fields: [endpointId], references: [id]) + endpoint WebhookEndpoint @relation(fields: [endpointId], references: [id], onDelete: Cascade) eventType String payload String // JSON string status String @default("pending") // pending, success, failed diff --git a/prisma/seed.ts b/prisma/seed.ts new file mode 100644 index 0000000..d6dacbf --- /dev/null +++ b/prisma/seed.ts @@ -0,0 +1,189 @@ + +import 'dotenv/config' +import { PrismaClient } from '@prisma/client' +import { PrismaPg } from '@prisma/adapter-pg' +import { Pool } from 'pg' +import { hash } from 'bcryptjs' + +const pool = new Pool({ connectionString: process.env.DATABASE_URL }) +const adapter = new PrismaPg(pool) +const prisma = new PrismaClient({ adapter }) + +async function main() { + console.log('🌱 Starting database seed...') + + // Clear existing data + await prisma.transaction.deleteMany() + await prisma.credential.deleteMany() + await prisma.completion.deleteMany() + await prisma.webhookDelivery.deleteMany() + await prisma.webhookEndpoint.deleteMany() + await prisma.module.deleteMany() + await prisma.user.deleteMany() + + // Create test users + const user1 = await prisma.user.create({ + data: { + email: 'alice@example.com', + name: 'Alice Johnson', + walletAddress: 'GBUQWP3BOUZX34ULNQG23RQ6F4BFSRJ4HBSNF63YLIXLQ5EDLF274Y6C', + passwordHash: await hash('password123', 10), + }, + }) + + const user2 = await prisma.user.create({ + data: { + email: 'bob@example.com', + name: 'Bob Smith', + walletAddress: 'GB7YLLICSMNYWJ46NWYCBTGXD54FPPWFY3YQYBFJFTQ6B2N3WHAL5V4K', + passwordHash: await hash('password456', 10), + }, + }) + + console.log(`✅ Created ${2} users`) + + // Create modules + const modules = await Promise.all([ + prisma.module.create({ + data: { + title: 'Introduction to Stellar', + description: 'Learn the basics of Stellar blockchain', + category: 'Blockchain', + difficulty: 'easy', + reward: 10, + }, + }), + prisma.module.create({ + data: { + title: 'Smart Contracts with Soroban', + description: 'Build smart contracts on Stellar using Soroban', + category: 'Blockchain', + difficulty: 'hard', + reward: 50, + }, + }), + prisma.module.create({ + data: { + title: 'Stellar wallet integration', + description: 'Integrate Stellar wallets into your applications', + category: 'Integration', + difficulty: 'medium', + reward: 25, + }, + }), + prisma.module.create({ + data: { + title: 'JavaScript fundamentals', + description: 'Master JavaScript basics for blockchain development', + category: 'Programming', + difficulty: 'easy', + reward: 15, + }, + }), + ]) + + console.log(`✅ Created ${modules.length} modules`) + + // Create completions + const completions = await Promise.all([ + prisma.completion.create({ + data: { + userId: user1.id, + moduleId: modules[0].id, + score: 95, + }, + }), + prisma.completion.create({ + data: { + userId: user1.id, + moduleId: modules[2].id, + score: 87, + }, + }), + prisma.completion.create({ + data: { + userId: user2.id, + moduleId: modules[0].id, + score: 92, + }, + }), + ]) + + console.log(`✅ Created ${completions.length} completions`) + + // Create credentials + const credentials = await Promise.all([ + prisma.credential.create({ + data: { + userId: user1.id, + moduleId: modules[0].id, + onChainId: 'cred_abc123def456', + issuedAt: new Date(), + }, + }), + prisma.credential.create({ + data: { + userId: user1.id, + moduleId: modules[2].id, + onChainId: 'cred_xyz789uvw012', + issuedAt: new Date(), + }, + }), + ]) + + console.log(`✅ Created ${credentials.length} credentials`) + + // Create transactions + const transactions = await Promise.all([ + prisma.transaction.create({ + data: { + userId: user1.id, + amount: 20, + type: 'reward', + status: 'completed', + }, + }), + prisma.transaction.create({ + data: { + userId: user2.id, + amount: 10, + type: 'reward', + status: 'completed', + }, + }), + prisma.transaction.create({ + data: { + userId: user1.id, + amount: 5, + type: 'transfer', + status: 'pending', + }, + }), + ]) + + console.log(`✅ Created ${transactions.length} transactions`) + + // Create webhook endpoint + const webhook = await prisma.webhookEndpoint.create({ + data: { + url: 'https://example.com/webhook', + secret: 'webhook_secret_key', + description: 'Test webhook endpoint', + isActive: true, + events: 'module.completed,reward.issued', + }, + }) + + console.log('✅ Created webhook endpoint') + + console.log('🎉 Database seed completed successfully!') +} + +main() + .catch((e) => { + console.error('❌ Seed failed:', e) + process.exit(1) + }) + .finally(async () => { + await prisma.$disconnect() + }) diff --git a/src/app.ts b/src/app.ts index a357aa1..f79b234 100644 --- a/src/app.ts +++ b/src/app.ts @@ -9,7 +9,7 @@ import { errorHandler, notFoundHandler } from './middleware/error.middleware' dotenv.config() -const app = express() +const app: express.Application = express() app.use(express.json()) app.use(cors()) diff --git a/src/routes/index.ts b/src/routes/index.ts index 5b98443..3e57f60 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -1,7 +1,7 @@ -import { Router } from 'express' +import express, { Router } from 'express' import userRoutes from './v1/users.routes' -const router = Router() +const router: express.Router = Router() router.get('/', (req, res) => { res.json({ message: 'API is running' }) diff --git a/src/routes/v1/users.routes.ts b/src/routes/v1/users.routes.ts index 6738c6d..690f289 100644 --- a/src/routes/v1/users.routes.ts +++ b/src/routes/v1/users.routes.ts @@ -1,9 +1,9 @@ -import { Router } from 'express' +import express, { Router } from 'express' import { UserController } from '../../controllers/user.controller' import { authenticate } from '../../middleware/auth.middleware' import { validateProfileUpdate, validatePasswordChange, validateWalletAddress } from '../../middleware/validation.middleware' -const router = Router() +const router: express.Router = Router() const userController = new UserController() router.get('/me', authenticate, userController.getCurrentUser.bind(userController)) diff --git a/temp-prisma/prisma/schema.prisma b/temp-prisma/prisma/schema.prisma index abba8da..65e5f3d 100644 --- a/temp-prisma/prisma/schema.prisma +++ b/temp-prisma/prisma/schema.prisma @@ -1,11 +1,8 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - generator client { provider = "prisma-client" output = "../src/generated/prisma" } datasource db { - provider = "sqlite" + provider = "post" } diff --git a/tsconfig.json b/tsconfig.json index b8b37d6..49edeca 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { - "target": "ES2020", - "module": "commonjs", + "target": "es2023", + "module": "esnext", "lib": ["ES2020"], "rootDir": "./src", "outDir": "./dist", @@ -13,10 +13,11 @@ "declaration": true, "declarationMap": true, "sourceMap": true, - "moduleResolution": "node", + "moduleResolution": "bundler", "allowSyntheticDefaultImports": true, "experimentalDecorators": true, - "emitDecoratorMetadata": true + "emitDecoratorMetadata": true, + // "ignoreDeprecations": "6.0" }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "tests"]