diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 833f40e3..c57d889a 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -21,12 +21,10 @@ env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} CERTIFICATE_ARN: ${{ secrets.CERTIFICATE_ARN }} - DATABASE_URL: ${{ secrets.DATABASE_URL }} + DATABASE_URL: ${{ secrets.PROD_DB_URL }} jobs: deploy: - if: (!contains(github.event.pull_request.labels.*.name, 'no deploy')) - runs-on: ubuntu-latest environment: @@ -44,4 +42,4 @@ jobs: run: pnpm install --frozen-lockfile - name: Deploy ZotMeet to production - run: pnpm sst deploy --stage prod + run: pnpm migrate && pnpm sst deploy --stage prod diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml index 4ba0c361..095fbdc9 100644 --- a/.github/workflows/deploy-staging.yml +++ b/.github/workflows/deploy-staging.yml @@ -23,7 +23,7 @@ env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} CERTIFICATE_ARN: ${{ secrets.CERTIFICATE_ARN }} - DATABASE_URL: ${{ secrets.DATABASE_URL }} + DATABASE_URL: ${{ secrets.DEV_DB_URL }} PR_NUM: ${{ github.event.pull_request.number }} jobs: @@ -47,4 +47,4 @@ jobs: run: pnpm install --frozen-lockfile - name: Deploy ZotMeet to staging - run: pnpm sst deploy --stage staging-$PR_NUM + run: pnpm migrate && pnpm sst deploy --stage staging-$PR_NUM diff --git a/.github/workflows/destroy-staging.yml b/.github/workflows/destroy-staging.yml index b164c51f..cc3070b9 100644 --- a/.github/workflows/destroy-staging.yml +++ b/.github/workflows/destroy-staging.yml @@ -22,7 +22,7 @@ env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} CERTIFICATE_ARN: ${{ secrets.CERTIFICATE_ARN }} - DATABASE_URL: ${{ secrets.DATABASE_URL }} + DATABASE_URL: ${{ secrets.DEV_DB_URL }} PR_NUM: ${{ github.event.pull_request.number }} jobs: diff --git a/package.json b/package.json index d8960242..475ea1d5 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "generate": "drizzle-kit generate:pg --config=drizzle.config.ts", "postinstall": "husky install && pnpm generate && svelte-kit sync", "lint": "eslint --quiet --fix .", - "migrate": "pnpm dlx tsx src/lib/db/migrate.ts", + "migrate": "pnpm tsx src/lib/db/migrate.ts", + "migrate:dev": "pnpm dotenv -- pnpm tsx src/lib/db/migrate.ts", "preview": "vite preview", "sst:deploy": "sst deploy", "sst:dev": "sst dev", @@ -30,12 +31,15 @@ "@lucia-auth/adapter-drizzle": "^1.0.3", "arctic": "^1.2.1", "clsx": "^2.1.0", + "dotenv": "^16.4.5", + "dotenv-cli": "^7.4.1", "drizzle-orm": "0.29.4", "lucia": "^3.1.1", "pg": "^8.11.3", "postgres": "3.4.3", "svelty-picker": "^5.2.1", "tailwind-merge": "^2.2.1", + "tsx": "^4.7.2", "unplugin-icons": "^0.18.1" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c01e964e..b74439b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,12 @@ dependencies: clsx: specifier: ^2.1.0 version: 2.1.0 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 + dotenv-cli: + specifier: ^7.4.1 + version: 7.4.1 drizzle-orm: specifier: 0.29.4 version: 0.29.4(@aws-sdk/client-rds-data@3.533.0)(@types/pg@8.11.2)(kysely@0.25.0)(pg@8.11.3)(postgres@3.4.3)(react@18.2.0) @@ -35,6 +41,9 @@ dependencies: tailwind-merge: specifier: ^2.2.1 version: 2.2.1 + tsx: + specifier: ^4.7.2 + version: 4.7.2 unplugin-icons: specifier: ^0.18.1 version: 0.18.5 @@ -100,9 +109,6 @@ devDependencies: devmoji: specifier: 2.3.0 version: 2.3.0 - dotenv: - specifier: ^16.4.5 - version: 16.4.5 drizzle-kit: specifier: 0.20.17 version: 0.20.17 @@ -1664,6 +1670,7 @@ packages: /@babel/highlight@7.23.4: resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} engines: {node: '>=6.9.0'} + requiresBuild: true dependencies: '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 @@ -2030,7 +2037,6 @@ packages: cpu: [ppc64] os: [aix] requiresBuild: true - dev: true optional: true /@esbuild/android-arm64@0.18.13: @@ -2057,7 +2063,6 @@ packages: cpu: [arm64] os: [android] requiresBuild: true - dev: true optional: true /@esbuild/android-arm@0.18.13: @@ -2084,7 +2089,6 @@ packages: cpu: [arm] os: [android] requiresBuild: true - dev: true optional: true /@esbuild/android-x64@0.18.13: @@ -2111,7 +2115,6 @@ packages: cpu: [x64] os: [android] requiresBuild: true - dev: true optional: true /@esbuild/darwin-arm64@0.18.13: @@ -2138,7 +2141,6 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true - dev: true optional: true /@esbuild/darwin-x64@0.18.13: @@ -2165,7 +2167,6 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true - dev: true optional: true /@esbuild/freebsd-arm64@0.18.13: @@ -2192,7 +2193,6 @@ packages: cpu: [arm64] os: [freebsd] requiresBuild: true - dev: true optional: true /@esbuild/freebsd-x64@0.18.13: @@ -2219,7 +2219,6 @@ packages: cpu: [x64] os: [freebsd] requiresBuild: true - dev: true optional: true /@esbuild/linux-arm64@0.18.13: @@ -2246,7 +2245,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-arm@0.18.13: @@ -2273,7 +2271,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-ia32@0.18.13: @@ -2300,7 +2297,6 @@ packages: cpu: [ia32] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-loong64@0.18.13: @@ -2327,7 +2323,6 @@ packages: cpu: [loong64] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-mips64el@0.18.13: @@ -2354,7 +2349,6 @@ packages: cpu: [mips64el] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-ppc64@0.18.13: @@ -2381,7 +2375,6 @@ packages: cpu: [ppc64] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-riscv64@0.18.13: @@ -2408,7 +2401,6 @@ packages: cpu: [riscv64] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-s390x@0.18.13: @@ -2435,7 +2427,6 @@ packages: cpu: [s390x] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-x64@0.18.13: @@ -2462,7 +2453,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/netbsd-x64@0.18.13: @@ -2489,7 +2479,6 @@ packages: cpu: [x64] os: [netbsd] requiresBuild: true - dev: true optional: true /@esbuild/openbsd-x64@0.18.13: @@ -2516,7 +2505,6 @@ packages: cpu: [x64] os: [openbsd] requiresBuild: true - dev: true optional: true /@esbuild/sunos-x64@0.18.13: @@ -2543,7 +2531,6 @@ packages: cpu: [x64] os: [sunos] requiresBuild: true - dev: true optional: true /@esbuild/win32-arm64@0.18.13: @@ -2570,7 +2557,6 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true - dev: true optional: true /@esbuild/win32-ia32@0.18.13: @@ -2597,7 +2583,6 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true - dev: true optional: true /@esbuild/win32-x64@0.18.13: @@ -2624,7 +2609,6 @@ packages: cpu: [x64] os: [win32] requiresBuild: true - dev: true optional: true /@eslint-community/eslint-utils@4.4.0(eslint@8.54.0): @@ -5255,7 +5239,7 @@ packages: resolution: {integrity: sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==} dependencies: leven: 2.1.0 - minimist: 1.2.6 + minimist: 1.2.8 /commitizen@4.3.0(@types/node@20.10.0)(typescript@5.3.2): resolution: {integrity: sha512-H0iNtClNEhT0fotHvGV3E9tDejDeS04sN1veIebsKYGMuGscFaswRoYJKmT3eW85eIJAs0F28bG2+a/9wCOfPw==} @@ -5761,10 +5745,24 @@ packages: is-obj: 2.0.0 dev: true + /dotenv-cli@7.4.1: + resolution: {integrity: sha512-fE1aywjRrWGxV3miaiUr3d2zC/VAiuzEGghi+QzgIA9fEf/M5hLMaRSXb4IxbUAwGmaLi0IozdZddnVU96acag==} + hasBin: true + dependencies: + cross-spawn: 7.0.3 + dotenv: 16.4.5 + dotenv-expand: 10.0.0 + minimist: 1.2.8 + dev: false + + /dotenv-expand@10.0.0: + resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} + engines: {node: '>=12'} + dev: false + /dotenv@16.4.5: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} - dev: true /dreamopt@0.8.0: resolution: {integrity: sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==} @@ -5946,6 +5944,7 @@ packages: /error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + requiresBuild: true dependencies: is-arrayish: 0.2.1 dev: true @@ -6177,7 +6176,6 @@ packages: '@esbuild/win32-arm64': 0.19.12 '@esbuild/win32-ia32': 0.19.12 '@esbuild/win32-x64': 0.19.12 - dev: true /escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} @@ -6868,7 +6866,6 @@ packages: resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} dependencies: resolve-pkg-maps: 1.0.0 - dev: true /git-hooks-list@3.1.0: resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==} @@ -7359,6 +7356,7 @@ packages: /is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + requiresBuild: true dev: true /is-bigint@1.0.4: @@ -7682,6 +7680,7 @@ packages: /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + requiresBuild: true dev: true /json-schema-traverse@0.4.1: @@ -7690,6 +7689,7 @@ packages: /json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + requiresBuild: true dev: true /json-schema-typed@7.0.3: @@ -8232,6 +8232,7 @@ packages: /minimist@1.2.6: resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + dev: true /minimist@1.2.7: resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} @@ -8286,7 +8287,7 @@ packages: duplexify: 4.1.3 help-me: 3.0.0 inherits: 2.0.4 - minimist: 1.2.6 + minimist: 1.2.8 mqtt-packet: 6.10.0 pump: 3.0.0 readable-stream: 3.6.2 @@ -9163,6 +9164,7 @@ packages: /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + requiresBuild: true dev: true /pvtsutils@1.3.5: @@ -9334,6 +9336,7 @@ packages: /require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + requiresBuild: true dev: true /resolve-dir@1.0.1: @@ -9363,7 +9366,6 @@ packages: /resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - dev: true /resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} @@ -10390,6 +10392,17 @@ packages: /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + /tsx@4.7.2: + resolution: {integrity: sha512-BCNd4kz6fz12fyrgCTEdZHGJ9fWTGeUzXmQysh0RVocDY3h4frk05ZNCXSy4kIenF7y/QnrdiVpTsyNRn6vlAw==} + engines: {node: '>=18.0.0'} + hasBin: true + dependencies: + esbuild: 0.19.12 + get-tsconfig: 4.7.3 + optionalDependencies: + fsevents: 2.3.3 + dev: false + /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} diff --git a/src/lib/db/postgres.ts b/src/lib/db/postgres.ts index 8f0795cb..dbaedd3a 100644 --- a/src/lib/db/postgres.ts +++ b/src/lib/db/postgres.ts @@ -7,5 +7,7 @@ import { DATABASE_URL } from "$env/static/private"; * so you will have to use this instead of the Drizzle client. * * In all other cases, you should probably not use this unless you know what you are doing. + * + * TODO: Check if this is still necessary considering our Lucia version */ export const client = postgres(DATABASE_URL, { max: 1, ssl: "prefer" }); diff --git a/src/lib/db/schema.ts b/src/lib/db/schema.ts index d9578759..425ed520 100644 --- a/src/lib/db/schema.ts +++ b/src/lib/db/schema.ts @@ -2,7 +2,6 @@ import { relations } from "drizzle-orm"; import { text, uuid, - pgSchema, timestamp, index, smallint, @@ -11,21 +10,20 @@ import { pgEnum, boolean, json, + pgTable, } from "drizzle-orm/pg-core"; -export const zotMeet = pgSchema("zotmeet"); - export const attendanceEnum = pgEnum("attendance", ["accepted", "maybe", "declined"]); export const memberEnum = pgEnum("member_type", ["guest", "user"]); // Members encompasses anyone who uses ZotMeet, regardless of guest or user status. -export const members = zotMeet.table("members", { +export const members = pgTable("members", { id: text("id").primaryKey(), type: memberEnum("type").notNull().default("guest"), }); // Users encompasses Members who have created an account. -export const users = zotMeet.table("users", { +export const users = pgTable("users", { id: text("id") .primaryKey() .references(() => members.id, { onDelete: "cascade" }), @@ -37,7 +35,7 @@ export const users = zotMeet.table("users", { }); // Guests are Members who do not have an account and are bound to one specific meeting. -export const guests = zotMeet.table( +export const guests = pgTable( "guests", { id: text("id").unique().notNull(), @@ -49,7 +47,7 @@ export const guests = zotMeet.table( }), ); -export const meetings = zotMeet.table("meetings", { +export const meetings = pgTable("meetings", { id: uuid("id").defaultRandom().primaryKey(), title: text("title").notNull(), description: text("description"), @@ -61,7 +59,7 @@ export const meetings = zotMeet.table("meetings", { host_id: text("host_id").references(() => members.id), }); -export const meetingDates = zotMeet.table( +export const meetingDates = pgTable( "meeting_dates", { id: uuid("id").unique().defaultRandom(), @@ -73,7 +71,7 @@ export const meetingDates = zotMeet.table( }), ); -export const groups = zotMeet.table("groups", { +export const groups = pgTable("groups", { id: uuid("id").defaultRandom().primaryKey(), name: text("name").notNull(), description: text("description"), @@ -81,7 +79,7 @@ export const groups = zotMeet.table("groups", { created_by: text("user_id").references(() => users.id), }); -export const availabilities = zotMeet.table( +export const availabilities = pgTable( "availabilities", { day: date("day").notNull(), @@ -100,7 +98,7 @@ export const availabilities = zotMeet.table( ); // meeting_day -export const oauthAccountsTable = zotMeet.table( +export const oauthAccountsTable = pgTable( "oauth_accounts", { userId: text("user_id") @@ -117,7 +115,7 @@ export const oauthAccountsTable = zotMeet.table( }), ); -export const sessions = zotMeet.table( +export const sessions = pgTable( "sessions", { id: text("id").primaryKey(), @@ -135,7 +133,7 @@ export const sessions = zotMeet.table( }; }, ); -export const usersInGroup = zotMeet.table( +export const usersInGroup = pgTable( "users_in_group", { userId: text("user_id") @@ -150,7 +148,7 @@ export const usersInGroup = zotMeet.table( }), ); -export const membersInMeeting = zotMeet.table( +export const membersInMeeting = pgTable( "members_in_meeting", { memberId: text("member_id")