diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4112daf7..17850281 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -448,6 +448,12 @@ importers: '@goodgo/types': specifier: workspace:* version: link:../../packages/types + '@neondatabase/serverless': + specifier: ^1.0.2 + version: 1.0.2 + '@prisma/adapter-neon': + specifier: ^7.2.0 + version: 7.2.0 '@prisma/client': specifier: ^7.2.0 version: 7.2.0(prisma@7.2.0)(typescript@5.9.3) @@ -532,7 +538,7 @@ importers: version: 29.7.0(@types/node@25.0.3)(ts-node@10.9.2) prisma: specifier: ^7.2.0 - version: 7.2.0(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3)(typescript@5.9.3) + version: 7.2.0(@types/react@18.3.27)(react-dom@18.3.1)(react@18.3.1)(typescript@5.9.3) supertest: specifier: ^7.0.0 version: 7.2.2 @@ -566,6 +572,12 @@ importers: '@goodgo/types': specifier: workspace:* version: link:../../packages/types + '@neondatabase/serverless': + specifier: ^1.0.2 + version: 1.0.2 + '@prisma/adapter-neon': + specifier: ^7.2.0 + version: 7.2.0 '@prisma/client': specifier: ^7.2.0 version: 7.2.0(prisma@7.2.0)(typescript@5.9.3) @@ -740,7 +752,7 @@ importers: version: 29.7.0(@types/node@25.0.3)(ts-node@10.9.2) prisma: specifier: ^7.2.0 - version: 7.2.0(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3)(typescript@5.9.3) + version: 7.2.0(@types/react@18.3.27)(react-dom@18.3.1)(react@18.3.1)(typescript@5.9.3) supertest: specifier: ^7.0.0 version: 7.2.2 @@ -2097,6 +2109,14 @@ packages: resolution: {integrity: sha512-klcSooChXXOzIm+SE5IISIAn3bYzYfPjbX7D7HoqZL84oAfgREeSg5vSIaSFH+DaGzzvImTyWe1OyrJ67vik4A==} dev: true + /@neondatabase/serverless@1.0.2: + resolution: {integrity: sha512-I5sbpSIAHiB+b6UttofhrN/UJXII+4tZPAq1qugzwCwLIL8EZLV7F/JyHUrEIiGgQpEXzpnjlJ+zwcEhheGvCw==} + engines: {node: '>=19.0.0'} + dependencies: + '@types/node': 22.19.3 + '@types/pg': 8.15.6 + dev: false + /@next/env@14.2.35: resolution: {integrity: sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==} @@ -3469,6 +3489,14 @@ packages: resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} dev: true + /@prisma/adapter-neon@7.2.0: + resolution: {integrity: sha512-XLTCQ0mDdaOqzBO99jyMOWBofJ5iqsvgWYB7lW+2ZEXvY6888tkeKfpo2VwdKhu1Cj/q4IqHd15eFQzPwbpjJQ==} + dependencies: + '@neondatabase/serverless': 1.0.2 + '@prisma/driver-adapter-utils': 7.2.0 + postgres-array: 3.0.4 + dev: false + /@prisma/client-runtime-utils@7.2.0: resolution: {integrity: sha512-dn7oB53v0tqkB0wBdMuTNFNPdEbfICEUe82Tn9FoKAhJCUkDH+fmyEp0ClciGh+9Hp2Tuu2K52kth2MTLstvmA==} dev: false @@ -3487,7 +3515,7 @@ packages: optional: true dependencies: '@prisma/client-runtime-utils': 7.2.0 - prisma: 7.2.0(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3)(typescript@5.9.3) + prisma: 7.2.0(@types/react@18.3.27)(react-dom@18.3.1)(react@18.3.1)(typescript@5.9.3) typescript: 5.9.3 dev: false @@ -3530,6 +3558,12 @@ packages: transitivePeerDependencies: - typescript + /@prisma/driver-adapter-utils@7.2.0: + resolution: {integrity: sha512-gzrUcbI9VmHS24Uf+0+7DNzdIw7keglJsD5m/MHxQOU68OhGVzlphQRobLiDMn8CHNA2XN8uugwKjudVtnfMVQ==} + dependencies: + '@prisma/debug': 7.2.0 + dev: false + /@prisma/engines-version@7.2.0-4.0c8ef2ce45c83248ab3df073180d5eda9e8be7a3: resolution: {integrity: sha512-KezsjCZDsbjNR7SzIiVlUsn9PnLePI7r5uxABlwL+xoerurZTfgQVbIjvjF2sVr3Uc0ZcsnREw3F84HvbggGdA==} @@ -3562,16 +3596,16 @@ packages: /@prisma/query-plan-executor@6.18.0: resolution: {integrity: sha512-jZ8cfzFgL0jReE1R10gT8JLHtQxjWYLiQ//wHmVYZ2rVkFHoh0DT8IXsxcKcFlfKN7ak7k6j0XMNn2xVNyr5cA==} - /@prisma/studio-core@0.9.0(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + /@prisma/studio-core@0.9.0(@types/react@18.3.27)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-xA2zoR/ADu/NCSQuriBKTh6Ps4XjU0bErkEcgMfnSGh346K1VI7iWKnoq1l2DoxUqiddPHIEWwtxJ6xCHG6W7g==} peerDependencies: '@types/react': ^18.0.0 || ^19.0.0 react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 dependencies: - '@types/react': 19.2.7 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) + '@types/react': 18.3.27 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) /@protobufjs/aspromise@1.1.2: resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -7003,6 +7037,12 @@ packages: node-cache: 5.1.2 dev: true + /@types/node@22.19.3: + resolution: {integrity: sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==} + dependencies: + undici-types: 6.21.0 + dev: false + /@types/node@25.0.3: resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==} dependencies: @@ -7108,11 +7148,6 @@ packages: '@types/prop-types': 15.7.15 csstype: 3.2.3 - /@types/react@19.2.7: - resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==} - dependencies: - csstype: 3.2.3 - /@types/resolve@1.20.6: resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} dev: true @@ -12447,6 +12482,11 @@ packages: engines: {node: '>=4'} dev: false + /postgres-array@3.0.4: + resolution: {integrity: sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==} + engines: {node: '>=12'} + dev: false + /postgres-bytea@1.0.1: resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==} engines: {node: '>=0.10.0'} @@ -12495,7 +12535,7 @@ packages: react-is: 18.3.1 dev: true - /prisma@7.2.0(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3)(typescript@5.9.3): + /prisma@7.2.0(@types/react@18.3.27)(react-dom@18.3.1)(react@18.3.1)(typescript@5.9.3): resolution: {integrity: sha512-jSdHWgWOgFF24+nRyyNRVBIgGDQEsMEF8KPHvhBBg3jWyR9fUAK0Nq9ThUmiGlNgq2FA7vSk/ZoCvefod+a8qg==} engines: {node: ^20.19 || ^22.12 || >=24.0} hasBin: true @@ -12512,7 +12552,7 @@ packages: '@prisma/config': 7.2.0 '@prisma/dev': 0.17.0(typescript@5.9.3) '@prisma/engines': 7.2.0 - '@prisma/studio-core': 0.9.0(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@prisma/studio-core': 0.9.0(@types/react@18.3.27)(react-dom@18.3.1)(react@18.3.1) mysql2: 3.15.3 postgres: 3.4.7 typescript: 5.9.3 @@ -12796,14 +12836,6 @@ packages: react: 18.3.1 scheduler: 0.23.2 - /react-dom@19.2.3(react@19.2.3): - resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} - peerDependencies: - react: ^19.2.3 - dependencies: - react: 19.2.3 - scheduler: 0.27.0 - /react-hook-form@7.70.0(react@18.3.1): resolution: {integrity: sha512-COOMajS4FI3Wuwrs3GPpi/Jeef/5W1DRR84Yl5/ShlT3dKVFUfoGiEZ/QE6Uw8P4T2/CLJdcTVYKvWBMQTEpvw==} engines: {node: '>=18.0.0'} @@ -12941,10 +12973,6 @@ packages: dependencies: loose-envify: 1.4.0 - /react@19.2.3: - resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} - engines: {node: '>=0.10.0'} - /readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -13233,9 +13261,6 @@ packages: dependencies: loose-envify: 1.4.0 - /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 @@ -14183,6 +14208,10 @@ packages: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 + /undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + dev: false + /undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} diff --git a/services/_template/package.json b/services/_template/package.json index 25a88fe9..039f64df 100644 --- a/services/_template/package.json +++ b/services/_template/package.json @@ -25,6 +25,8 @@ "@goodgo/logger": "workspace:*", "@goodgo/tracing": "workspace:*", "@goodgo/types": "workspace:*", + "@neondatabase/serverless": "^1.0.2", + "@prisma/adapter-neon": "^7.2.0", "@prisma/client": "^7.2.0", "cors": "^2.8.5", "dotenv": "^17.2.3", diff --git a/services/_template/prisma/prisma.config.ts b/services/_template/prisma/prisma.config.ts new file mode 100644 index 00000000..2b9bb3dc --- /dev/null +++ b/services/_template/prisma/prisma.config.ts @@ -0,0 +1,28 @@ +// Prisma 7 Configuration File +// https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/introduction/configuration + +import { PrismaClient } from '@prisma/client'; +import { neonConfig } from '@neondatabase/serverless'; +import { Pool } from '@neondatabase/serverless'; +import { PrismaNeon } from '@prisma/adapter-neon'; + +// EN: Get database URL from environment +// VI: Lấy database URL từ environment +const databaseUrl = process.env.DATABASE_URL; + +if (!databaseUrl) { + throw new Error('DATABASE_URL environment variable is required'); +} + +// EN: Configure Neon connection pool +// VI: Cấu hình connection pool cho Neon +neonConfig.webSocketConstructor = globalThis.WebSocket; + +const pool = new Pool({ connectionString: databaseUrl }); +const adapter = new PrismaNeon(pool); + +// EN: Export configured Prisma Client +// VI: Export Prisma Client đã cấu hình +export const prisma = new PrismaClient({ adapter }); + +export default prisma; diff --git a/services/_template/prisma/schema.prisma b/services/_template/prisma/schema.prisma index 3a7f8e4f..fec080ea 100644 --- a/services/_template/prisma/schema.prisma +++ b/services/_template/prisma/schema.prisma @@ -7,9 +7,9 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } + // EN: Feature model - represents a configurable feature in the system // VI: Model Feature - đại diện cho một tính năng có thể cấu hình trong hệ thống model Feature { diff --git a/services/iam-service/package.json b/services/iam-service/package.json index 9759d449..b4229899 100644 --- a/services/iam-service/package.json +++ b/services/iam-service/package.json @@ -27,6 +27,8 @@ "@goodgo/logger": "workspace:*", "@goodgo/tracing": "workspace:*", "@goodgo/types": "workspace:*", + "@neondatabase/serverless": "^1.0.2", + "@prisma/adapter-neon": "^7.2.0", "@prisma/client": "^7.2.0", "@simplewebauthn/server": "^9.0.0", "@types/dompurify": "^3.2.0", diff --git a/services/iam-service/prisma/prisma.config.ts b/services/iam-service/prisma/prisma.config.ts new file mode 100644 index 00000000..2b9bb3dc --- /dev/null +++ b/services/iam-service/prisma/prisma.config.ts @@ -0,0 +1,28 @@ +// Prisma 7 Configuration File +// https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/introduction/configuration + +import { PrismaClient } from '@prisma/client'; +import { neonConfig } from '@neondatabase/serverless'; +import { Pool } from '@neondatabase/serverless'; +import { PrismaNeon } from '@prisma/adapter-neon'; + +// EN: Get database URL from environment +// VI: Lấy database URL từ environment +const databaseUrl = process.env.DATABASE_URL; + +if (!databaseUrl) { + throw new Error('DATABASE_URL environment variable is required'); +} + +// EN: Configure Neon connection pool +// VI: Cấu hình connection pool cho Neon +neonConfig.webSocketConstructor = globalThis.WebSocket; + +const pool = new Pool({ connectionString: databaseUrl }); +const adapter = new PrismaNeon(pool); + +// EN: Export configured Prisma Client +// VI: Export Prisma Client đã cấu hình +export const prisma = new PrismaClient({ adapter }); + +export default prisma; diff --git a/services/iam-service/prisma/schema.prisma b/services/iam-service/prisma/schema.prisma index 81540e5c..c2e0520f 100644 --- a/services/iam-service/prisma/schema.prisma +++ b/services/iam-service/prisma/schema.prisma @@ -8,9 +8,9 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } + // EN: User model - Core user entity // VI: Model User - Entity người dùng cốt lõi model User {