From be324407e372c05902c3c84ee6470010f41c75a2 Mon Sep 17 00:00:00 2001 From: Eric Cabrel TIOGO Date: Sun, 1 Sep 2024 23:45:37 +0200 Subject: [PATCH] chore(database): move from planetsacle to rds sniff (#105) * chore(database): move from planetsacle to rds sniff * fix: doppler install * fix: migration diff step * fix: migration diff step n tests * fix: migration diff step n tests * fix: migration diff step n tests * fix: migration diff step n tests * fix: migration diff step n tests * fix: migration diff step n tests * fix: migration diff step n tests * fix: migration diff step n tests * fix: migration diff step n tests * fix: migration diff step n tests * fix: migration diff step n tests * fix: migration diff step n tests * fix: migration diff step n tests --- .github/workflows/migration-db-check.yml | 126 ++++++++---------- .github/workflows/migration-db-deploy.yml | 83 ++---------- README.md | 4 +- _infra/credentials/database_prod.tf | 1 + apps/backend/.env.example | 2 +- apps/backend/README.md | 4 +- apps/backend/package.json | 2 +- apps/backend/src/utils/tests/helpers.ts | 2 + packages/domain/.env.template | 2 +- packages/domain/README.md | 44 ++---- packages/domain/package.json | 13 +- .../migration.sql | 17 +++ packages/domain/prisma/schema.prisma | 9 +- .../services/folders/folder.service.test.ts | 2 - .../services/sessions/session.service.test.ts | 18 +-- packages/domain/tests/database.mjs | 11 +- yarn.lock | 88 ++++++------ 17 files changed, 168 insertions(+), 260 deletions(-) create mode 100644 packages/domain/prisma/migrations/20240901144144_enable_foreign_keys/migration.sql diff --git a/.github/workflows/migration-db-check.yml b/.github/workflows/migration-db-check.yml index abe7d1b2..501b8b03 100644 --- a/.github/workflows/migration-db-check.yml +++ b/.github/workflows/migration-db-check.yml @@ -6,93 +6,75 @@ on: paths: - 'packages/domain/prisma/migrations/**' -env: - PLANETSCALE_SERVICE_TOKEN_ID: ${{ secrets.PLANETSCALE_SERVICE_TOKEN_ID }} - PLANETSCALE_SERVICE_TOKEN: ${{ secrets.PLANETSCALE_SERVICE_TOKEN }} - jobs: migration-detail: runs-on: ubuntu-latest + env: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: db + MYSQL_PORT: 3306 + DATABASE_URL: mysql://root:root@127.0.0.1:3306/db steps: - uses: actions/checkout@v4 - - name: Setup pscale - uses: planetscale/setup-pscale-action@v1 - - - name: Set database branch name - run: echo "PSCALE_BRANCH_NAME=$(echo ${{ github.head_ref }} | tr -cd '[:alnum:]-'| tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV - - - name: Create deploy request on development branch - run: | - DEPLOY_REQUEST_STATE=$(pscale deploy-request show ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.PSCALE_BRANCH_NAME }} --org ${{ secrets.PLANETSCALE_ORG_NAME }} -f json | jq -r '.state') - - echo "Deploy request State: $DEPLOY_REQUEST_STATE" - - if [ "$DEPLOY_REQUEST_STATE" = "open" ]; then - echo "Deploy request exists: skipping creation" - else - echo "Deploy request does not exist : creating..." - pscale deploy-request create ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.PSCALE_BRANCH_NAME }} \ - --org ${{ secrets.PLANETSCALE_ORG_NAME }} \ - --into dev \ - --notes "Apply changes to the dev branch" - fi + - name: Start MySQL server + run: sudo systemctl start mysql.service - - name: Get deploy request number - run: | - DEPLOY_REQUEST_NUMBER=$(pscale deploy-request show ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.PSCALE_BRANCH_NAME }} --org ${{ secrets.PLANETSCALE_ORG_NAME }} -f json | jq -r '.number') - echo "DEPLOY_REQUEST_NUMBER=$DEPLOY_REQUEST_NUMBER" >> $GITHUB_ENV + - name: Install dependencies + uses: ./.github/actions/install-dependencies - - name: Check deployment state - continue-on-error: false - run: | - for i in {1..10}; do - DEPLOYMENT_STATE=$(pscale deploy-request show ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.DEPLOY_REQUEST_NUMBER }} --org ${{ secrets.PLANETSCALE_ORG_NAME }} --format json | jq -r '.deployment_state') - echo "Deployment State: $DEPLOYMENT_STATE" + - name: Run migrations + run: yarn workspace @snipcode/domain db:migrate - if [ "$DEPLOYMENT_STATE" = "ready" ]; then - echo "Deployment state is ready. Continuing." - echo "DEPLOY_REQUEST_OPENED=true" >> $GITHUB_ENV - break - fi + - name: Install Doppler CLI + uses: dopplerhq/cli-action@v3 - echo "Deployment state is not ready. Waiting 2 seconds before checking again." - sleep 2 - done + - name: Retrieve and export the production database URL + run: echo "PROD_DATABASE_URL=$(doppler secrets get CONNECTION_STRING --plain)" >> $GITHUB_ENV + env: + DOPPLER_TOKEN: ${{ secrets.DOPPLER_DATABASE_TOKEN }} - name: Collect the migration diff continue-on-error: false - if: ${{ env.DEPLOY_REQUEST_OPENED }} + working-directory: packages/domain run: | - DEPLOY_DATA=$(pscale api organizations/${{ secrets.PLANETSCALE_ORG_NAME }}/databases/${{ secrets.PLANETSCALE_DATABASE_NAME }}/deploy-requests/${{ env.DEPLOY_REQUEST_NUMBER }}/deployment --org planetscale) - CAN_DROP_DATA=$(echo "$DEPLOY_DATA" | jq -r '.deploy_operations[] | select(.can_drop_data == true) | .can_drop_data') - - echo "Deploy request opened: https://app.planetscale.com/${{ secrets.PLANETSCALE_ORG_NAME }}/${{ secrets.PLANETSCALE_DATABASE_NAME }}/deploy-requests/${{ env.DEPLOY_REQUEST_NUMBER }}" >> migration-message.txt + set -e + echo "### Database Migration Detected" > migration-message.txt + echo "The following migration will be applied to the production database:" >> migration-message.txt echo "" >> migration-message.txt - - if [ "$CAN_DROP_DATA" = "true" ]; then - echo ":rotating_light: You are dropping a column. Before running the migration make sure to do the following:" >> migration-message.txt - echo "" >> migration-message.txt - - echo "1. [ ] Deploy app changes to ensure the column is no longer being used." >> migration-message.txt - echo "2. [ ] Once you've verified it's no used, run the deploy request." >> migration-message.txt - echo "" >> migration-message.txt - else - echo "When adding to the schema, the Deploy Request must be run **before** the code is deployed." >> migration-message.txt - echo "Please ensure your schema changes are compatible with the application code currently running in production." >> migration-message.txt - echo "" >> migration-message.txt - - echo "1. [ ] Successfully run the Deploy Request" >> migration-message.txt - echo "2. [ ] Deploy this PR" >> migration-message.txt - echo "" >> migration-message.txt - fi - - echo "\`\`\`diff" >> migration-message.txt - pscale deploy-request diff ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.DEPLOY_REQUEST_NUMBER }} --org ${{ secrets.PLANETSCALE_ORG_NAME }} -f json | jq -r '.[].raw' >> migration-message.txt + echo "\`\`\`sql" >> migration-message.txt + yarn prisma migrate diff --from-url "$PROD_DATABASE_URL" --to-url "$DATABASE_URL" --script >> migration-message.txt echo "\`\`\`" >> migration-message.txt + echo "" >> migration-message.txt + echo "" >> migration-message.txt + echo "Please ensure your schema changes are compatible with the application code currently running in production." >> migration-message.txt - - name: Comment pull request with the migration diff - uses: thollander/actions-comment-pull-request@v2 - if: ${{ env.DEPLOY_REQUEST_OPENED }} + - name: Create or update the pull request with the migration diff + uses: actions/github-script@v6 + id: plan-comment with: - filePath: migration-message.txt + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('fs'); + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + const botComment = comments.find(comment => { + return comment.user.type === 'Bot' && comment.body.includes('Database Migration Detected') + }); + const output = fs.readFileSync('packages/domain/migration-message.txt', 'utf8'); + if (botComment) { + github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + }); + } + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: output + }); diff --git a/.github/workflows/migration-db-deploy.yml b/.github/workflows/migration-db-deploy.yml index 73c008ec..0db00eb4 100644 --- a/.github/workflows/migration-db-deploy.yml +++ b/.github/workflows/migration-db-deploy.yml @@ -6,85 +6,22 @@ on: paths: - 'packages/domain/prisma/migrations/**' -env: - PLANETSCALE_SERVICE_TOKEN_ID: ${{ secrets.PLANETSCALE_SERVICE_TOKEN_ID }} - PLANETSCALE_SERVICE_TOKEN: ${{ secrets.PLANETSCALE_SERVICE_TOKEN }} - jobs: apply-migration: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Setup pscale - uses: planetscale/setup-pscale-action@v1 - - - name: Get the deploy request number and branch name in development branch - run: | - DEPLOYER_REQUEST_LIST=$(pscale deploy-request list ${{ secrets.PLANETSCALE_DATABASE_NAME }} --org ${{ secrets.PLANETSCALE_ORG_NAME }} -f json) - DEV_DEPLOY_REQUEST_NUMBER=$(echo "$DEPLOYER_REQUEST_LIST" | jq -r '.[] | select(.into_branch == "dev" and .state == "open") | .number') - PSCALE_BRANCH_NAME=$(echo "$DEPLOYER_REQUEST_LIST" | jq -r '.[] | select(.into_branch == "dev" and .state == "open") | .branch') - - if [ -z "$DEV_DEPLOY_REQUEST_NUMBER" ]; then - echo "No open deploy request found in the development branch." - exit 1 - fi - echo "DEV_DEPLOY_REQUEST_NUMBER=$DEV_DEPLOY_REQUEST_NUMBER" >> $GITHUB_ENV - echo "PSCALE_BRANCH_NAME=$PSCALE_BRANCH_NAME" >> $GITHUB_ENV - - - name: Check deployment state - continue-on-error: false - run: | - for i in {1..10}; do - DEPLOYMENT_STATE=$(pscale deploy-request show ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.DEV_DEPLOY_REQUEST_NUMBER }} --org ${{ secrets.PLANETSCALE_ORG_NAME }} -f json | jq -r '.deployment_state') - echo "Deployment State: $DEPLOYMENT_STATE" - - if [ "$DEPLOYMENT_STATE" = "ready" ]; then - echo "Deployment state is ready. Continuing." - echo "DEPLOY_REQUEST_OPENED=true" >> $GITHUB_ENV - break - fi - - echo "Deployment state is not ready. Waiting 2 seconds before checking again." - sleep 2 - done - - - name: Deploy schema migration in the development branch - continue-on-error: false - run: | - pscale deploy-request deploy ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.DEV_DEPLOY_REQUEST_NUMBER }} --org ${{ secrets.PLANETSCALE_ORG_NAME }} --wait - pscale deploy-request skip-revert ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.DEV_DEPLOY_REQUEST_NUMBER }} --org ${{ secrets.PLANETSCALE_ORG_NAME }} - - - name: Deploy schema migration in the production branch - if: ${{ success() }} - continue-on-error: false - run: | - pscale deploy-request create ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.PSCALE_BRANCH_NAME }} \ - --org ${{ secrets.PLANETSCALE_ORG_NAME }} \ - --into main \ - --notes "Apply changes to the production branch" - - PROD_DEPLOY_REQUEST_NUMBER=$(pscale deploy-request show ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.PSCALE_BRANCH_NAME }} --org ${{ secrets.PLANETSCALE_ORG_NAME }} -f json | jq -r '.number') - - for i in {1..10}; do - DEPLOYMENT_STATE=$(pscale deploy-request show ${{ secrets.PLANETSCALE_DATABASE_NAME }} $PROD_DEPLOY_REQUEST_NUMBER --org ${{ secrets.PLANETSCALE_ORG_NAME }} -f json | jq -r '.deployment_state') - echo "Deployment State: $DEPLOYMENT_STATE" - - if [ "$DEPLOYMENT_STATE" = "ready" ]; then - echo "Deployment state is ready. Continuing." - break - fi + - name: Install dependencies + uses: ./.github/actions/install-dependencies - echo "Deployment state is not ready. Waiting 2 seconds before checking again." - sleep 2 - done + - name: Install Doppler CLI + run: curl -Ls https://cli.doppler.com/install.sh | sh - pscale deploy-request deploy ${{ secrets.PLANETSCALE_DATABASE_NAME }} $PROD_DEPLOY_REQUEST_NUMBER --org ${{ secrets.PLANETSCALE_ORG_NAME }} --wait + - name: Retrieve and export the database URL + run: echo "DATABASE_URL=$(doppler secrets get CONNECTION_STRING --plain)" >> $GITHUB_ENV + env: + DOPPLER_TOKEN: ${{ secrets.DOPPLER_DATABASE_TOKEN }} - - name: Delete the database branch - if: ${{ success() }} - run: | - PROD_DEPLOY_REQUEST_NUMBER=$(pscale deploy-request show ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.PSCALE_BRANCH_NAME }} --org ${{ secrets.PLANETSCALE_ORG_NAME }} -f json | jq -r '.number') - pscale deploy-request skip-revert ${{ secrets.PLANETSCALE_DATABASE_NAME }} $PROD_DEPLOY_REQUEST_NUMBER --org ${{ secrets.PLANETSCALE_ORG_NAME }} - pscale branch delete ${{ secrets.PLANETSCALE_DATABASE_NAME }} ${{ env.PSCALE_BRANCH_NAME }} --org ${{ secrets.PLANETSCALE_ORG_NAME }} --force - echo "The branch \"${{ env.PSCALE_BRANCH_NAME }}\" has been successfully." + - name: Deploy schema migration to the production database + run: yarn workspace @snipcode/domain db:deploy diff --git a/README.md b/README.md index e8f2b7b1..9d2fcada 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Snipcode is an open-source code-sharing platform that makes it easy to create co * [Node.js](https://nodejs.org/en/) * [TypeScript](https://www.typescriptlang.org/) * [GraphQL](https://graphql.org/) -* [MySQL 8 with PlanetScale](https://planetscale.com/) +* [MySQL 8.0](https://dev.mysql.com/doc/refman/8.0/en/) * [Prisma](https://www.prisma.io/) * [Tailwind CSS](https://tailwindcss.com/) * [AWS](https://aws.amazon.com) @@ -29,11 +29,9 @@ snipcode │ ├─ backend │ ├─ web ├─ packages -│ ├─ database │ ├─ embed │ ├─ domain │ ├─ front -│ ├─ logger │ ├─ utils package.json tsconfig.base.json diff --git a/_infra/credentials/database_prod.tf b/_infra/credentials/database_prod.tf index c4b797f9..ce850308 100644 --- a/_infra/credentials/database_prod.tf +++ b/_infra/credentials/database_prod.tf @@ -24,6 +24,7 @@ variable "database_prod_secrets_map" { "ADMIN_PASSWORD" = "", "DATABASE_NAME" = "", "PORT" = "3306" + "CONNECTION_STRING" = "" } } diff --git a/apps/backend/.env.example b/apps/backend/.env.example index 26e4eac1..8797b8af 100644 --- a/apps/backend/.env.example +++ b/apps/backend/.env.example @@ -3,7 +3,7 @@ APP_VERSION=1.0.0 HOST=http://localhost PORT=7501 INTROSPECTION_ENABLED=true -DATABASE_URL="mysql://root:@127.0.0.1:3311/snipcode" +DATABASE_URL=mysql://root:secret@127.0.0.1:3311/snipcode ADMIN_PASSWORD=nwHSvXuQxjey43Bp CONVERTKIT_API_KEY=convertKitApiKey CONVERTKIT_FORM_ID=formId diff --git a/apps/backend/README.md b/apps/backend/README.md index be03994b..5372fc9a 100644 --- a/apps/backend/README.md +++ b/apps/backend/README.md @@ -1,4 +1,4 @@ -# Snipcode Core +# Snipcode Backend This is the backend of Snipcode, containing the business logics related to . @@ -15,7 +15,7 @@ Make sure you have these tools installed before running the project * NPM or Yarn * Docker * AWS CLI v2 -* MySQL 8 on PlanetScale +* MySQL 8.0 ## Packages dependencies We use Yarn workspace to create packages we can share with other applications. diff --git a/apps/backend/package.json b/apps/backend/package.json index 846ca903..ae72b905 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -28,7 +28,7 @@ "@nestjs/graphql": "12.1.1", "@nestjs/platform-express": "10.3.9", "@nestjs/serve-static": "4.0.2", - "@prisma/client": "5.14.0", + "@prisma/client": "5.19.0", "@sentry/node": "8.11.0", "@snipcode/domain": "workspace:*", "@snipcode/embed": "workspace:*", diff --git a/apps/backend/src/utils/tests/helpers.ts b/apps/backend/src/utils/tests/helpers.ts index ad825962..ca845f0a 100644 --- a/apps/backend/src/utils/tests/helpers.ts +++ b/apps/backend/src/utils/tests/helpers.ts @@ -47,7 +47,9 @@ export class TestHelper { await prismaService.snippet.deleteMany(); // Recursive relationship between folders makes it hard to delete all folders using folder.deleteMany() + await prismaService.$executeRaw`SET FOREIGN_KEY_CHECKS=0;`; await prismaService.$executeRaw`TRUNCATE TABLE folders;`; + await prismaService.$executeRaw`SET FOREIGN_KEY_CHECKS=1;`; await prismaService.session.deleteMany(); diff --git a/packages/domain/.env.template b/packages/domain/.env.template index 777655a4..ae1692f0 100644 --- a/packages/domain/.env.template +++ b/packages/domain/.env.template @@ -1,2 +1,2 @@ -DATABASE_URL=mysql://root:@127.0.0.1:3311/core-db +DATABASE_URL=mysql://root:secret@127.0.0.1:3311/snipcode SHADOW_DATABASE_URL=mysql://root:secret@127.0.0.1:3312/snipcode diff --git a/packages/domain/README.md b/packages/domain/README.md index d574784c..d7cebb27 100644 --- a/packages/domain/README.md +++ b/packages/domain/README.md @@ -11,7 +11,6 @@ Make sure you have this tools installed before running the project * Node.js 20+ * Yarn 4 * Docker -* [The PlanetScale CLI](https://planetscale.com/cli) ## Set up the project Delete the existing folders output from build commands @@ -29,42 +28,23 @@ Create the .env file from the template. This file is useful for test executions, cp .env.template .env ``` -Create git branch for your feature; there is no convention for the branch name. +### Start the local database and run the migrations ```shell -git checkout -b your-feature-name -``` - -### Connect to the local database locally -This project uses PlanetScale as the database.
-To connect to the database locally, you must authenticate first (Ask the credentials to [@tericcabrel](https://github.com/tericcabrel)).
-Once authenticated from the terminal, execute the commands below to create a database branch for your feature and create local tunnel to it. -```shell -yarn db:branch:dev -yarn db:branch:connect -``` -Open a second terminal and run the command below to start the shadow database; -this is only necessary to run generate or execute database migrations with prisma schema -```shell -yarn db:shadow +yarn db:local +yarn db:migrate ``` -The shadow database runs on Docker, you can stop it when you don't need it +### Generate Prisma types and seed the database with default data ```shell -yarn db:shadow:stop +yarn db:generate +yarn db:seed ``` -### Connect to the development database -The development database is used to beta test features. Execute the command below to connect to it +To stop the local database run the command below: ```shell -yarn db:dev:connect +yarn db:local:stop ``` -### Run the database migration, generate Prisma types and seed the database with default data -```shell -yarn db:generate -yarn db:migrate -yarn db:seed -``` ### Generate a database migration To create a database migration that generate the SQL file, run the command below: @@ -78,13 +58,7 @@ yarn db:migrate --name - Open Prisma Studio to browse your database: `db:view` - Lint the Prisma schema file: `db:format` -### Create a deployment request -To publish the database schema changes in production, you must create a deployment request. Run the command below to do that -```shell -yarn db:deploy:create -``` - -Build the package to generate types declaration required to provide autocompletion while using the functions in the core or Lambda functions +Build the package to generate types declaration required to provide autocompletion while using the functions in the backend application ```bash yarn build ``` diff --git a/packages/domain/package.json b/packages/domain/package.json index 3f4787a9..a7a673de 100644 --- a/packages/domain/package.json +++ b/packages/domain/package.json @@ -12,14 +12,11 @@ "clean": "rm -rf .turbo dist coverage", "lint": "eslint --fix", "env": "dotenv -e .env.local", - "db:branch:create": "pscale branch create core-db $(git rev-parse --abbrev-ref HEAD)", - "db:branch:connect": "pscale connect core-db $(git rev-parse --abbrev-ref HEAD) --port 3311", - "db:dev:connect": "pscale connect core-db dev --port 3311", - "db:shadow": "docker run -d --rm -e MYSQL_ROOT_PASSWORD=secret -e MYSQL_DATABASE=snipcode --name snipcode-shadow-db -p 3312:3306 mysql:8.0.34", - "db:shadow:stop": "docker kill snipcode-shadow-db && docker container prune -f", - "db:deploy:create": "pscale deploy-request create core-db dev", + "db:local": "docker run -d --rm -e MYSQL_ROOT_PASSWORD=secret -e MYSQL_DATABASE=snipcode --name snipcode-local-db -p 3311:3306 mysql:8.0.39", + "db:local:stop": "docker kill snipcode-local-db && docker container prune -f", "db:generate": "yarn env -- prisma generate", "db:migrate": "yarn env -- prisma migrate dev", + "db:deploy": "yarn env -- prisma migrate deploy", "db:reset": "yarn env -- prisma migrate reset --skip-seed --force", "db:reset:seed": "yarn env -- prisma migrate reset", "db:view": "yarn env -- prisma studio", @@ -31,7 +28,7 @@ }, "dependencies": { "@bugsnag/cuid": "3.1.1", - "@prisma/client": "5.14.0", + "@prisma/client": "5.19.0", "@snipcode/utils": "workspace:*", "axios": "1.7.2", "bcryptjs": "2.4.3", @@ -45,7 +42,7 @@ "dotenv-cli": "7.4.2", "mysql2": "3.10.1", "nock": "13.5.4", - "prisma": "5.14.0", + "prisma": "5.19.0", "zx": "8.1.3" } } diff --git a/packages/domain/prisma/migrations/20240901144144_enable_foreign_keys/migration.sql b/packages/domain/prisma/migrations/20240901144144_enable_foreign_keys/migration.sql new file mode 100644 index 00000000..aab4be7d --- /dev/null +++ b/packages/domain/prisma/migrations/20240901144144_enable_foreign_keys/migration.sql @@ -0,0 +1,17 @@ +-- AddForeignKey +ALTER TABLE `users` ADD CONSTRAINT `users_role_id_fkey` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `folders` ADD CONSTRAINT `folders_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `folders` ADD CONSTRAINT `folders_parent_id_fkey` FOREIGN KEY (`parent_id`) REFERENCES `folders`(`id`) ON DELETE RESTRICT ON UPDATE NO ACTION; + +-- AddForeignKey +ALTER TABLE `snippets` ADD CONSTRAINT `snippets_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `snippets` ADD CONSTRAINT `snippets_folder_id_fkey` FOREIGN KEY (`folder_id`) REFERENCES `folders`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `sessions` ADD CONSTRAINT `sessions_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/packages/domain/prisma/schema.prisma b/packages/domain/prisma/schema.prisma index eb6c10ba..0e13c312 100644 --- a/packages/domain/prisma/schema.prisma +++ b/packages/domain/prisma/schema.prisma @@ -5,10 +5,9 @@ generator client { } datasource db { - provider = "mysql" - url = env("DATABASE_URL") - shadowDatabaseUrl = env("SHADOW_DATABASE_URL") - relationMode = "prisma" + provider = "mysql" + url = env("DATABASE_URL") + relationMode = "foreignKeys" } enum RoleName { @@ -80,7 +79,7 @@ model Folder { createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) - parent Folder? @relation(name: "parent_folder", fields: [parentId], references: [id], onDelete: NoAction, onUpdate: NoAction) + parent Folder? @relation(name: "parent_folder", fields: [parentId], references: [id], onDelete: Restrict, onUpdate: NoAction) subFolders Folder[] @relation("parent_folder") snippets Snippet[] diff --git a/packages/domain/src/services/folders/folder.service.test.ts b/packages/domain/src/services/folders/folder.service.test.ts index fb3706d9..5c738468 100644 --- a/packages/domain/src/services/folders/folder.service.test.ts +++ b/packages/domain/src/services/folders/folder.service.test.ts @@ -16,8 +16,6 @@ describe('Test Folder service', () => { let testHelper: TestHelper; beforeAll(async () => { - console.log('Environment Variables:', process.env); - const module: TestingModule = await Test.createTestingModule({ imports: [ DomainModule.forRootAsync({ diff --git a/packages/domain/src/services/sessions/session.service.test.ts b/packages/domain/src/services/sessions/session.service.test.ts index 24a3ca00..558b2811 100644 --- a/packages/domain/src/services/sessions/session.service.test.ts +++ b/packages/domain/src/services/sessions/session.service.test.ts @@ -35,8 +35,8 @@ describe('Test Session Service', function () { }); test('Create a session', async () => { - const userId = TestHelper.generateTestId(); - const input = TestHelper.createTestSessionInput(userId); + const user = await testHelper.createTestUser({}); + const input = TestHelper.createTestSessionInput(user.id); const sessionCreated = await sessionService.create(input); @@ -46,8 +46,8 @@ describe('Test Session Service', function () { }); test('Retrieve a session by the token attached to it', async () => { - const userId = TestHelper.generateTestId(); - const session = await testHelper.createTestSession({ userId }); + const user = await testHelper.createTestUser({}); + const session = await testHelper.createTestSession({ userId: user.id }); const sessionFound = await sessionService.findByToken(session.token); @@ -57,15 +57,15 @@ describe('Test Session Service', function () { }); test('Delete all sessions of a user', async () => { - const userId = TestHelper.generateTestId(); + const user = await testHelper.createTestUser({}); const sessionsCreated = await Promise.all([ - testHelper.createTestSession({ userId }), - testHelper.createTestSession({ userId }), - testHelper.createTestSession({ userId }), + testHelper.createTestSession({ userId: user.id }), + testHelper.createTestSession({ userId: user.id }), + testHelper.createTestSession({ userId: user.id }), ]); - await sessionService.deleteUserSessions(userId); + await sessionService.deleteUserSessions(user.id); const userSessions = await Promise.all(sessionsCreated.map(({ token }) => sessionService.findByToken(token))); diff --git a/packages/domain/tests/database.mjs b/packages/domain/tests/database.mjs index 05388704..80a76b73 100755 --- a/packages/domain/tests/database.mjs +++ b/packages/domain/tests/database.mjs @@ -1,7 +1,7 @@ #!/usr/bin/env zx -import { $, sleep } from 'zx'; import mysql from 'mysql2/promise'; +import { $, sleep } from 'zx'; const CONTAINER_NAME = 'snipcode-test-db'; const MYSQL_HOST = '127.0.0.1'; @@ -16,11 +16,11 @@ const waitForMysql = async () => { while (true) { try { const connection = await mysql.createConnection({ + database: MYSQL_DATABASE, host: MYSQL_HOST, + password: MYSQL_PASSWORD, port: MYSQL_PORT, user: MYSQL_USER, - password: MYSQL_PASSWORD, - database: MYSQL_DATABASE, }); await connection.end(); @@ -31,14 +31,14 @@ const waitForMysql = async () => { await sleep(1000); } } -} +}; try { await $`docker ps | grep ${CONTAINER_NAME}`; } catch (error) { console.log('Database container not found, creating...'); - await $`docker run -d --rm --name ${CONTAINER_NAME} -e MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD} -e MYSQL_DATABASE=${MYSQL_DATABASE} -p ${MYSQL_PORT}:3306 mysql:8.0.34`; + await $`docker run -d --rm --name ${CONTAINER_NAME} -e MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD} -e MYSQL_DATABASE=${MYSQL_DATABASE} -p ${MYSQL_PORT}:3306 mysql:8.0.39`; await waitForMysql(); @@ -48,4 +48,3 @@ try { await $`yarn prisma migrate dev`; } - diff --git a/yarn.lock b/yarn.lock index b1687cd3..f64b05a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4587,61 +4587,61 @@ __metadata: languageName: node linkType: hard -"@prisma/client@npm:5.14.0": - version: 5.14.0 - resolution: "@prisma/client@npm:5.14.0" +"@prisma/client@npm:5.19.0": + version: 5.19.0 + resolution: "@prisma/client@npm:5.19.0" peerDependencies: prisma: "*" peerDependenciesMeta: prisma: optional: true - checksum: 10/7023b1423fd0083ec14fa5e50fa2507a40c3981a0c412143e9b2ebd9f88b137e5aecc0533bf8406c1122c75071a78bbaee8b37db826ab3a4b689ad1f004dddfe + checksum: 10/e8795d2d3058b747f87d0b1b4dd1d19a33dab8daddef514d893a0cc5ba27f217e17f4e61955c80bb22ef4a6bc417075ae29b879f1eb742ba6025c2ff35c8fedf languageName: node linkType: hard -"@prisma/debug@npm:5.14.0": - version: 5.14.0 - resolution: "@prisma/debug@npm:5.14.0" - checksum: 10/d1afd73075a4753b49cce8b1dfc8c2a20d88624d2570abd4baf24a1353e24dad3c0b55db7b4055c70e76545c6f172dfd0a54d58d2dc827a93b1bde04c2f3b5aa +"@prisma/debug@npm:5.19.0": + version: 5.19.0 + resolution: "@prisma/debug@npm:5.19.0" + checksum: 10/8195ada224956374469094251b8bcec12573914c4afa258c038813ef323491952abc09fccf24a04df1d332133ea65920bd9a7d5c53ddbdc27977177edec123c2 languageName: node linkType: hard -"@prisma/engines-version@npm:5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48": - version: 5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48 - resolution: "@prisma/engines-version@npm:5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48" - checksum: 10/88dece13c407aff3177970b761bd332a06abda9d0d0a8e5a628f8580ee52ac3ff1a06f52cdf7876e6b9823f2bf2b8e8d34890fa2eb237e98a59c1dc5ae73f9bf +"@prisma/engines-version@npm:5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f": + version: 5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f + resolution: "@prisma/engines-version@npm:5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f" + checksum: 10/445fca7effb81aea2afee25bc59ffa639d832a406de84950b61859dd37f90045b026e904dd9ed81bb093aff652837bdbc1f97cd172ad2bdee4108161cc6e14bc languageName: node linkType: hard -"@prisma/engines@npm:5.14.0": - version: 5.14.0 - resolution: "@prisma/engines@npm:5.14.0" +"@prisma/engines@npm:5.19.0": + version: 5.19.0 + resolution: "@prisma/engines@npm:5.19.0" dependencies: - "@prisma/debug": "npm:5.14.0" - "@prisma/engines-version": "npm:5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48" - "@prisma/fetch-engine": "npm:5.14.0" - "@prisma/get-platform": "npm:5.14.0" - checksum: 10/d9677a3a6c53c6f96644f3fccb5903e7234758edc38e8d9632a5282ab9e979e6e8c8b892f8a920937e8ae6da5535a9a35cc66b9c5ecbe83375e738f0e49ac699 + "@prisma/debug": "npm:5.19.0" + "@prisma/engines-version": "npm:5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f" + "@prisma/fetch-engine": "npm:5.19.0" + "@prisma/get-platform": "npm:5.19.0" + checksum: 10/12ac027624700bcf24497aa0c4e1376bd29094fd21ed9e67ada904b5bd53b18d9b690f090a4d5a38a49bd4a2dbbb37a9057a6b27166cb5c4f56a0ad2d517d03b languageName: node linkType: hard -"@prisma/fetch-engine@npm:5.14.0": - version: 5.14.0 - resolution: "@prisma/fetch-engine@npm:5.14.0" +"@prisma/fetch-engine@npm:5.19.0": + version: 5.19.0 + resolution: "@prisma/fetch-engine@npm:5.19.0" dependencies: - "@prisma/debug": "npm:5.14.0" - "@prisma/engines-version": "npm:5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48" - "@prisma/get-platform": "npm:5.14.0" - checksum: 10/81af34764e42771c5377e6d1d4b6ff9642ac59b56bcbea5ba8cd7a415dfbc0c030490e8ad84bc73bc4685d3adc2dcd2a524e79c5fa4a9d7ef9eabd6b1def99b1 + "@prisma/debug": "npm:5.19.0" + "@prisma/engines-version": "npm:5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f" + "@prisma/get-platform": "npm:5.19.0" + checksum: 10/83232142e408daa06c18a8d2a7a5d42530da8b3672420562b7bff8e6847825ed64a3dcf7a433651e2d7ad22a1602cbaa9028148eb669fdbab5a06352938b1b3a languageName: node linkType: hard -"@prisma/get-platform@npm:5.14.0": - version: 5.14.0 - resolution: "@prisma/get-platform@npm:5.14.0" +"@prisma/get-platform@npm:5.19.0": + version: 5.19.0 + resolution: "@prisma/get-platform@npm:5.19.0" dependencies: - "@prisma/debug": "npm:5.14.0" - checksum: 10/b0b0db492916466d42dd5e6460e8c7f0f8a11f4eb14ad7e89c4e011c7d53c37a3ca44563f4cca8a3af7e7501ae96f15eb454524c0069e1eb9f15f8ba5b1824fc + "@prisma/debug": "npm:5.19.0" + checksum: 10/085ea26bbb29fdd963771ab7a382786e2fa099d0e20a055cdf338d67831524f82451a268e9e86b558673865d3dc89b61267370904824dfa3f71169a7aa271a53 languageName: node linkType: hard @@ -5417,7 +5417,7 @@ __metadata: "@nestjs/serve-static": "npm:4.0.2" "@nestjs/testing": "npm:10.3.9" "@ngneat/falso": "npm:7.2.0" - "@prisma/client": "npm:5.14.0" + "@prisma/client": "npm:5.19.0" "@sentry/node": "npm:8.11.0" "@snipcode/domain": "workspace:*" "@snipcode/embed": "workspace:*" @@ -5446,7 +5446,7 @@ __metadata: "@nestjs/common": "npm:10.3.9" "@nestjs/testing": "npm:10.3.9" "@ngneat/falso": "npm:7.2.0" - "@prisma/client": "npm:5.14.0" + "@prisma/client": "npm:5.19.0" "@snipcode/utils": "workspace:*" "@types/bcryptjs": "npm:2.4.6" axios: "npm:1.7.2" @@ -5454,7 +5454,7 @@ __metadata: dotenv-cli: "npm:7.4.2" mysql2: "npm:3.10.1" nock: "npm:13.5.4" - prisma: "npm:5.14.0" + prisma: "npm:5.19.0" unique-username-generator: "npm:1.3.0" zx: "npm:8.1.3" languageName: unknown @@ -10836,7 +10836,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": +"fsevents@npm:2.3.3, fsevents@npm:^2.3.2, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": version: 2.3.3 resolution: "fsevents@npm:2.3.3" dependencies: @@ -10846,7 +10846,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": +"fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin, fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" dependencies: @@ -15460,14 +15460,18 @@ __metadata: languageName: node linkType: hard -"prisma@npm:5.14.0": - version: 5.14.0 - resolution: "prisma@npm:5.14.0" +"prisma@npm:5.19.0": + version: 5.19.0 + resolution: "prisma@npm:5.19.0" dependencies: - "@prisma/engines": "npm:5.14.0" + "@prisma/engines": "npm:5.19.0" + fsevents: "npm:2.3.3" + dependenciesMeta: + fsevents: + optional: true bin: prisma: build/index.js - checksum: 10/90184937495e1366923d5a4c55626072556472ea6aa76f31ce85cc4f1be0875d978a3311c2a872e28861790cf20a182a1c3925b311ed645d2a11d241bc8c2574 + checksum: 10/17b2a83d174c12724954bc4cd8df3fe087201cc31bb064fc669b286412261a851d1b9144baa044f167c550446d3c20aea86fcac61655fbb4316113555ea8ed05 languageName: node linkType: hard