Skip to content

Commit

Permalink
✨ feat: support server db with Postgres and drizzle ORM
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed May 29, 2024
1 parent 5eb43e8 commit 1d4de28
Show file tree
Hide file tree
Showing 55 changed files with 7,502 additions and 54 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Setup Testcontainers Cloud Client
uses: atomicjar/testcontainers-cloud-setup-action@v1
with:
token: ${{ secrets.TC_CLOUD_TOKEN }}

- name: Install bun
uses: oven-sh/setup-bun@v1
with:
bun-version: ${{ secrets.BUN_VERSION }}


- name: Install deps
run: bun i

Expand All @@ -20,6 +26,8 @@ jobs:

- name: Test and coverage
run: bun run test:coverage
env:
DATABASE_TEST_URL: ${{ secrets.DATABASE_TEST_URL }}

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
Expand Down
29 changes: 29 additions & 0 deletions drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as dotenv from 'dotenv';
import type { Config } from 'drizzle-kit';

// Read the .env file if it exists, or a file specified by the

// dotenv_config_path parameter that's passed to Node.js

dotenv.config();

let connectionString = process.env.DATABASE_URL;

if (process.env.NODE_ENV === 'test') {
console.log('current ENV:', process.env.NODE_ENV);
connectionString = process.env.DATABASE_TEST_URL;
}

if (!connectionString)
throw new Error('`DATABASE_URL` or `DATABASE_TEST_URL` not found in environment');

export default {
dbCredentials: {
url: connectionString,
},
dialect: 'postgresql',
out: './src/database/server/migrations',

schema: './src/database/server/schemas/lobechat.ts',
strict: true,
} satisfies Config;
3 changes: 3 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ const nextConfig = {
},
});

// https://github.com/pinojs/pino/issues/688#issuecomment-637763276
config.externals.push('pino-pretty');

return config;
},
};
Expand Down
21 changes: 19 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,18 @@
"sideEffects": false,
"scripts": {
"build": "next build",
"postbuild": "npm run build-sitemap",
"postbuild": "npm run build-sitemap && npm run build-migrate-db",
"build-migrate-db": "bun run db:migrate",
"build-sitemap": "next-sitemap --config next-sitemap.config.mjs",
"build:analyze": "ANALYZE=true next build",
"build:docker": "DOCKER=true next build && npm run build-sitemap",
"dev": "next dev -p 3010",
"db:generate": "drizzle-kit generate -- dotenv_config_path='.env'",
"db:migrate": "MIGRATION_DB=1 tsx scripts/migrateServerDB/index.ts",
"db:push": "drizzle-kit push -- dotenv_config_path='.env'",
"db:push-test": "NODE_ENV=test drizzle-kit push -- dotenv_config_path='.env'",
"db:studio": "drizzle-kit studio",
"db:z-pull": "drizzle-kit introspect -- dotenv_config_path='.env'",
"dev": "next dev -p 3011",
"dev:clerk-proxy": "ngrok http http://localhost:3011",
"docs:i18n": "lobe-i18n md && npm run workflow:docs && npm run lint:mdx",
"docs:seo": "lobe-seo && npm run workflow:mdx && npm run lint:mdx",
Expand All @@ -50,6 +57,7 @@
"stylelint": "stylelint \"src/**/*.{js,jsx,ts,tsx}\" --fix",
"test": "vitest",
"test:coverage": "vitest run --coverage",
"test:db": "vitest run src/database/server/**",
"test:update": "vitest -u",
"type-check": "tsc --noEmit",
"workflow:docs": "tsx scripts/docsWorkflow/index.ts",
Expand Down Expand Up @@ -101,6 +109,7 @@
"@lobehub/tts": "^1.24.1",
"@lobehub/ui": "^1.141.2",
"@microsoft/fetch-event-source": "^2.0.1",
"@neondatabase/serverless": "^0.9.3",
"@next/third-parties": "^14.2.3",
"@sentry/nextjs": "^7.116.0",
"@t3-oss/env-nextjs": "^0.10.1",
Expand All @@ -119,6 +128,8 @@
"debug": "^4.3.4",
"dexie": "^3.2.7",
"diff": "^5.2.0",
"drizzle-orm": "^0.30.10",
"drizzle-zod": "^0.5.1",
"fast-deep-equal": "^3.1.3",
"gpt-tokenizer": "^2.1.2",
"i18next": "^23.11.5",
Expand Down Expand Up @@ -163,6 +174,7 @@
"semver": "^7.6.2",
"sharp": "^0.33.4",
"superjson": "^2.2.1",
"svix": "^1.24.0",
"swr": "^2.2.5",
"systemjs": "^6.15.1",
"ts-md5": "^1.3.1",
Expand All @@ -171,6 +183,7 @@
"use-merge-value": "^1.2.0",
"utility-types": "^3.11.0",
"uuid": "^9.0.1",
"ws": "^8.17.0",
"y-protocols": "^1.0.6",
"y-webrtc": "^10.3.0",
"yaml": "^2.4.2",
Expand Down Expand Up @@ -207,12 +220,15 @@
"@types/systemjs": "^6.13.5",
"@types/ua-parser-js": "^0.7.39",
"@types/uuid": "^9.0.8",
"@types/ws": "^8.5.10",
"@umijs/lint": "^4.2.5",
"@vitest/coverage-v8": "~1.2.2",
"ajv-keywords": "^5.1.0",
"commitlint": "^19.3.0",
"consola": "^3.2.3",
"dotenv": "^16.4.5",
"dpdm": "^3.14.0",
"drizzle-kit": "^0.21.1",
"eslint": "^8.57.0",
"eslint-plugin-mdx": "^2.3.4",
"fake-indexeddb": "^6.0.0",
Expand All @@ -227,6 +243,7 @@
"node-fetch": "^3.3.2",
"node-gyp": "^10.1.0",
"p-map": "^7.0.2",
"pg": "^8.11.5",
"prettier": "^3.2.5",
"remark-cli": "^11.0.0",
"remark-parse": "^10.0.2",
Expand Down
30 changes: 30 additions & 0 deletions scripts/migrateServerDB/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as dotenv from 'dotenv';
import * as migrator from 'drizzle-orm/neon-serverless/migrator';
import { join } from 'node:path';

import { serverDB } from '../../src/database/server/core/db';

// Read the `.env` file if it exists, or a file specified by the
// dotenv_config_path parameter that's passed to Node.js
dotenv.config();

const runMigrations = async () => {
await migrator.migrate(serverDB, {
migrationsFolder: join(__dirname, '../../src/database/server/migrations'),
});
console.log('✅ database migration pass.');
// eslint-disable-next-line unicorn/no-process-exit
process.exit(0);
};

let connectionString = process.env.DATABASE_URL;

// only migrate database if the connection string is available
if (connectionString) {
// eslint-disable-next-line unicorn/prefer-top-level-await
runMigrations().catch((err) => {
console.error('❌ Database migrate failed:', err);
// eslint-disable-next-line unicorn/no-process-exit
process.exit(1);
});
}
73 changes: 73 additions & 0 deletions src/app/api/webhooks/clerk/__tests__/fixtures/createUser.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"backup_code_enabled": false,
"banned": false,
"create_organization_enabled": true,
"created_at": 1713709987911,
"delete_self_enabled": true,
"email_addresses": [
{
"created_at": 1713709977919,
"email_address": "arvinx@foxmail.com",
"id": "idn_2fPkD9X1lfzSn5lJVDGyochYq8k",
"linked_to": [],
"object": "email_address",
"reserved": false,
"updated_at": 1713709987951,
"verification": []
}
],
"external_accounts": [
{
"approved_scopes": "read:user user:email",
"avatar_url": "https://avatars.githubusercontent.com/u/28616219?v=4",
"created_at": 1713709542104,
"email_address": "arvinx@foxmail.com",
"first_name": "Arvin",
"id": "eac_2fPjKROeJ1bBs8Uxa6RFMxKogTB",
"identification_id": "idn_2fPjyV3sqtQJZUbEzdK2y23a1bq",
"image_url": "https://img.clerk.com/eyJ0eXBlIjoicHJveHkiLCJzcmMiOiJodHRwczovL2F2YXRhcnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3UvMjg2MTYyMTk/dj00IiwicyI6IkhCeHE5NmdlRk85ekRxMjJlR05EalUrbVFBbmVDZjRVQkpwNGYxcW5JajQifQ",
"label": null,
"last_name": "Xu",
"object": "external_account",
"provider": "oauth_github",
"provider_user_id": "28616219",
"public_metadata": {},
"updated_at": 1713709542104,
"username": "arvinxx",
"verification": {
"attempts": null,
"expire_at": 1713710140131,
"status": "verified",
"strategy": "oauth_github"
}
}
],
"external_id": null,
"first_name": "Arvin",
"has_image": true,
"id": "user_2fPkELglwI48WpZVwwdAxBKBPK6",
"image_url": "https://img.clerk.com/eyJ0eXBlIjoicHJveHkiLCJzcmMiOiJodHRwczovL2ltYWdlcy5jbGVyay5kZXYvb2F1dGhfZ2l0aHViL2ltZ18yZlBrRU1adVpwdlpvZFBHcVREdHJnTzJJM3cifQ",
"last_active_at": 1713709987902,
"last_name": "Xu",
"last_sign_in_at": null,
"locked": false,
"lockout_expires_in_seconds": null,
"object": "user",
"passkeys": [],
"password_enabled": false,
"phone_numbers": [],
"primary_email_address_id": "idn_2fPkD9X1lfzSn5lJVDGyochYq8k",
"primary_phone_number_id": null,
"primary_web3_wallet_id": null,
"private_metadata": {},
"profile_image_url": "https://images.clerk.dev/oauth_github/img_2fPkEMZuZpvZodPGqTDtrgO2I3w",
"public_metadata": {},
"saml_accounts": [],
"totp_enabled": false,
"two_factor_enabled": false,
"unsafe_metadata": {},
"updated_at": 1713709987972,
"username": "arvinxx",
"verification_attempts_remaining": 100,
"web3_wallets": []
}
Loading

0 comments on commit 1d4de28

Please sign in to comment.