From 3590973a9836698c4c5b6f393f311027ecfe4fca Mon Sep 17 00:00:00 2001 From: KinjiKawaguchi Date: Sat, 4 Apr 2026 12:34:07 +0900 Subject: [PATCH 1/4] 3.0.0-rc.4 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 19aee33..2b9d202 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@shizuoka-its/core", - "version": "3.0.0-rc.3", + "version": "3.0.0-rc.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@shizuoka-its/core", - "version": "3.0.0-rc.3", + "version": "3.0.0-rc.4", "license": "ISC", "dependencies": { "drizzle-orm": "^0.45.1", diff --git a/package.json b/package.json index c7b43f2..f24fefb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@shizuoka-its/core", - "version": "3.0.0-rc.3", + "version": "3.0.0-rc.4", "description": "ITS core library", "keywords": [], "license": "ISC", From 63b9fbdb79a7f2b5114286947101071ab6c4dff7 Mon Sep 17 00:00:00 2001 From: KinjiKawaguchi Date: Sat, 4 Apr 2026 15:23:32 +0900 Subject: [PATCH 2/4] 3.0.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2b9d202..7e0fb81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@shizuoka-its/core", - "version": "3.0.0-rc.4", + "version": "3.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@shizuoka-its/core", - "version": "3.0.0-rc.4", + "version": "3.0.0", "license": "ISC", "dependencies": { "drizzle-orm": "^0.45.1", diff --git a/package.json b/package.json index f24fefb..63021f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@shizuoka-its/core", - "version": "3.0.0-rc.4", + "version": "3.0.0", "description": "ITS core library", "keywords": [], "license": "ISC", From 2c0af6d150905d8a70ab278ced3115eb91c38244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=82=8F=E3=81=8D=E3=82=93=28=E6=B2=B3=E5=8F=A3?= =?UTF-8?q?=E6=AC=A3=E4=BB=81=29?= <93261102+KinjiKawaguchi@users.noreply.github.com> Date: Sun, 5 Apr 2026 13:36:47 +0900 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20Supabase=20Transaction=20pool=20mode?= =?UTF-8?q?=20=E5=AF=BE=E5=BF=9C=E3=81=AE=E3=81=9F=E3=82=81=20DB=20?= =?UTF-8?q?=E3=83=89=E3=83=A9=E3=82=A4=E3=83=90=E3=82=92=20postgres-js=20?= =?UTF-8?q?=E3=81=AB=E5=88=87=E3=82=8A=E6=9B=BF=E3=81=88=20(#146)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary DB ドライバを `drizzle-orm/node-postgres` (`pg`) から Supabase 推奨の `drizzle-orm/postgres-js` (`postgres`) に切り替える。 ## Why ### 1. Transaction pool mode 対応 Supabase の Transaction pool mode(pgbouncer 経由、port 6543)は prepared statement をサポートしない。`postgres-js` の `prepare: false` オプションを明示することで、プーラー経由の接続で安全にクエリを実行できる。 ### 2. SSL 証明書検証の問題 最新の `pg` (v8.x 系の後期) は `sslmode=require` を `verify-full` のエイリアスとして扱うようになり、Supabase の証明書チェーンで `SELF_SIGNED_CERT_IN_CHAIN` エラーが発生するようになった。これにより its-discord から接続できなくなる問題が発生していた。 `postgres-js` はこの挙動に影響されず、プーラー URL でそのまま接続できる。 ### 3. Supabase 公式推奨 Supabase の Drizzle 接続ドキュメントでも `postgres-js` + `prepare: false` が推奨されている。 ## Changes - `drizzle-orm/node-postgres` → `drizzle-orm/postgres-js` - 依存パッケージ: `pg` / `@types/pg` を削除し `postgres` を追加 - `src/infrastructure/drizzle/client.ts` で `postgres(connectionString, { prepare: false })` を使用 ## Test plan - [x] `npm run build` が成功すること - [x] its-discord から `getMemberByDiscordId` が正常動作することを確認 - [ ] 既存のテストが通ること --- Open with Devin Co-authored-by: Claude Opus 4.6 (1M context) --- package-lock.json | 170 ++------------------------- package.json | 3 +- src/infrastructure/drizzle/client.ts | 18 +-- 3 files changed, 23 insertions(+), 168 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7e0fb81..8bcb48e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,12 +10,11 @@ "license": "ISC", "dependencies": { "drizzle-orm": "^0.45.1", - "pg": "^8.20.0", + "postgres": "^3.4.8", "uuid": "^13.0.0" }, "devDependencies": { "@types/node": "^25.5.0", - "@types/pg": "^8.20.0", "drizzle-kit": "^0.31.10", "typescript": "^6.0.2", "vite-plus": "^0.1.13" @@ -1693,24 +1692,12 @@ "version": "25.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~7.18.0" } }, - "node_modules/@types/pg": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.20.0.tgz", - "integrity": "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" - } - }, "node_modules/@voidzero-dev/vite-plus-darwin-arm64": { "version": "0.1.14", "resolved": "https://registry.npmjs.org/@voidzero-dev/vite-plus-darwin-arm64/-/vite-plus-darwin-arm64-0.1.14.tgz", @@ -2732,95 +2719,6 @@ "node": ">=8" } }, - "node_modules/pg": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.20.0.tgz", - "integrity": "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==", - "license": "MIT", - "dependencies": { - "pg-connection-string": "^2.12.0", - "pg-pool": "^3.13.0", - "pg-protocol": "^1.13.0", - "pg-types": "2.2.0", - "pgpass": "1.0.5" - }, - "engines": { - "node": ">= 16.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.3.0" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz", - "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==", - "license": "MIT", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.12.0.tgz", - "integrity": "sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ==", - "license": "MIT" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "license": "ISC", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-pool": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.13.0.tgz", - "integrity": "sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA==", - "license": "MIT", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.13.0.tgz", - "integrity": "sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==", - "license": "MIT" - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "license": "MIT", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "license": "MIT", - "dependencies": { - "split2": "^4.1.0" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -2893,43 +2791,17 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "license": "MIT", + "node_modules/postgres": { + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.8.tgz", + "integrity": "sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg==", + "license": "Unlicense", "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", - "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" + "node": ">=12" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" } }, "node_modules/resolve-pkg-maps": { @@ -3046,15 +2918,6 @@ "source-map": "^0.6.0" } }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, "node_modules/std-env": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", @@ -3163,7 +3026,7 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/uuid": { @@ -3426,15 +3289,6 @@ "optional": true } } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "license": "MIT", - "engines": { - "node": ">=0.4" - } } } } diff --git a/package.json b/package.json index 63021f7..abba0a9 100644 --- a/package.json +++ b/package.json @@ -53,12 +53,11 @@ }, "dependencies": { "drizzle-orm": "^0.45.1", - "pg": "^8.20.0", + "postgres": "^3.4.8", "uuid": "^13.0.0" }, "devDependencies": { "@types/node": "^25.5.0", - "@types/pg": "^8.20.0", "drizzle-kit": "^0.31.10", "typescript": "^6.0.2", "vite-plus": "^0.1.13" diff --git a/src/infrastructure/drizzle/client.ts b/src/infrastructure/drizzle/client.ts index 12ecc0b..14fa1e5 100644 --- a/src/infrastructure/drizzle/client.ts +++ b/src/infrastructure/drizzle/client.ts @@ -1,22 +1,24 @@ -import { drizzle } from "drizzle-orm/node-postgres"; -import { Pool } from "pg"; +/// +import { drizzle } from "drizzle-orm/postgres-js"; +import postgres, { type Sql } from "postgres"; import * as schema from "./schema"; -let pool: Pool | null = null; +let client: Sql | null = null; -function getPool(): Pool { - if (!pool) { +function getClient(): Sql { + if (!client) { const connectionString = process.env.DATABASE_URL; if (!connectionString) { throw new Error("DATABASE_URL environment variable is not set"); } - pool = new Pool({ connectionString }); + // Supabase の Transaction pool mode は prepared statement をサポートしないため無効化 + client = postgres(connectionString, { prepare: false }); } - return pool; + return client; } export function getDb() { - return drizzle(getPool(), { schema }); + return drizzle(getClient(), { schema }); } export type DrizzleDb = ReturnType; From 12103bbed60bbac083444e6e33b1858c2ca3efa8 Mon Sep 17 00:00:00 2001 From: KinjiKawaguchi Date: Sun, 5 Apr 2026 13:37:07 +0900 Subject: [PATCH 4/4] 3.0.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8bcb48e..cbc49a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@shizuoka-its/core", - "version": "3.0.0", + "version": "3.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@shizuoka-its/core", - "version": "3.0.0", + "version": "3.0.1", "license": "ISC", "dependencies": { "drizzle-orm": "^0.45.1", diff --git a/package.json b/package.json index abba0a9..1a54c83 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@shizuoka-its/core", - "version": "3.0.0", + "version": "3.0.1", "description": "ITS core library", "keywords": [], "license": "ISC",