diff --git a/internal-packages/database/prisma/schema.prisma b/internal-packages/database/prisma/schema.prisma index 8ea3ea2fc3a..545b0259539 100644 --- a/internal-packages/database/prisma/schema.prisma +++ b/internal-packages/database/prisma/schema.prisma @@ -8,7 +8,7 @@ generator client { provider = "prisma-client-js" output = "../generated/prisma" binaryTargets = ["native", "debian-openssl-1.1.x"] - previewFeatures = ["metrics"] + previewFeatures = ["metrics", "driverAdapters"] } model User { diff --git a/internal-packages/run-ops-database/prisma/schema.prisma b/internal-packages/run-ops-database/prisma/schema.prisma index 4750efa392c..0a6c10dd034 100644 --- a/internal-packages/run-ops-database/prisma/schema.prisma +++ b/internal-packages/run-ops-database/prisma/schema.prisma @@ -7,7 +7,7 @@ generator client { provider = "prisma-client-js" output = "../generated/run-ops" binaryTargets = ["native", "debian-openssl-1.1.x"] - previewFeatures = ["metrics"] + previewFeatures = ["metrics", "driverAdapters"] } // ───────────────────────────────────────────────────────────────────────────── diff --git a/internal-packages/testcontainers/package.json b/internal-packages/testcontainers/package.json index 291c1314c18..b8d8d150a5d 100644 --- a/internal-packages/testcontainers/package.json +++ b/internal-packages/testcontainers/package.json @@ -20,9 +20,16 @@ }, "devDependencies": { "@internal/run-ops-database": "workspace:*", + "@opentelemetry/instrumentation": "0.218.0", + "@opentelemetry/sdk-trace-base": "2.7.1", + "@opentelemetry/sdk-trace-node": "2.7.1", + "@prisma/adapter-pg": "6.14.0", + "@prisma/instrumentation": "6.14.0", "@testcontainers/postgresql": "^11.14.0", + "@types/pg": "^8.11.10", "@testcontainers/redis": "^11.14.0", "@trigger.dev/core": "workspace:*", + "pg": "8.15.6", "std-env": "^3.9.0", "testcontainers": "^11.14.0", "tinyexec": "^0.3.0" diff --git a/internal-packages/testcontainers/src/adapterGolden.test.ts b/internal-packages/testcontainers/src/adapterGolden.test.ts new file mode 100644 index 00000000000..fbd59617234 --- /dev/null +++ b/internal-packages/testcontainers/src/adapterGolden.test.ts @@ -0,0 +1,255 @@ +import { writeFileSync } from "node:fs"; +import { Prisma } from "@trigger.dev/database"; +import { expect } from "vitest"; +import { postgresTest } from "./index"; +import { + createAdapterClient, + createClientPair, + createRustClient, + describe, + runShape, + type ShapeCase, + type ShapeResult, +} from "./adapterGolden"; + +function safeWrite(path: string, contents: string) { + try { + writeFileSync(path, contents); + } catch { + void 0; + } +} + +const shapes: ShapeCase[] = [ + { + id: 1, + name: "text[] param with explicit cast (= ANY(${ids}::text[]))", + callSite: "PostgresRunStore.ts L2159-2161 (documented binding workaround)", + upstream: "#24338", + setup: async (c) => { + await c.$executeRawUnsafe(`CREATE TABLE g1 (id text)`); + await c.$executeRawUnsafe(`INSERT INTO g1 (id) VALUES ('a'),('b'),('c')`); + }, + run: (c) => { + const ids = ["a", "c"]; + return c.$queryRaw`SELECT id FROM g1 WHERE id = ANY(${ids}::text[]) ORDER BY id`; + }, + }, + { + id: 2, + name: "array results (array_agg + text[] column)", + callSite: "text[] columns / array_agg readers", + upstream: "#27823", + setup: async (c) => { + await c.$executeRawUnsafe(`CREATE TABLE g2 (id text, tags text[])`); + await c.$executeRawUnsafe(`INSERT INTO g2 (id, tags) VALUES ('x', ARRAY['a','b'])`); + }, + run: (c) => c.$queryRaw`SELECT tags, array_agg(id ORDER BY id) AS ids FROM g2 GROUP BY tags`, + }, + { + id: 3, + name: "bigint from COUNT(*)", + callSite: "PostgresRunStore.ts:2162,2171; DeploymentListPresenter.server.ts:322,168", + upstream: "#23926", + setup: async (c) => { + await c.$executeRawUnsafe(`CREATE TABLE g3 (id int)`); + await c.$executeRawUnsafe(`INSERT INTO g3 (id) VALUES (1),(2),(3)`); + }, + run: (c) => c.$queryRaw`SELECT COUNT(*) AS c FROM g3`, + }, + { + id: 4, + name: "bigint ns timestamp (keyset pagination)", + callSite: "taskEventStore.server.ts L339-386", + run: (c) => c.$queryRaw`SELECT 1723058400000000000::int8 AS t`, + }, + { + id: 5, + name: "NUMERIC -> Prisma.Decimal", + callSite: "QueueListPresenter.server.ts:383", + setup: async (c) => { + await c.$executeRawUnsafe(`CREATE TABLE g5 (n numeric(30,4))`); + await c.$executeRawUnsafe(`INSERT INTO g5 (n) VALUES ('12345.6789')`); + }, + run: (c) => c.$queryRaw`SELECT n FROM g5`, + }, + { + id: 6, + name: "enum cast (CAST('LOG'::text AS enum))", + callSite: "taskEventStore.server.ts:196,224,274,303,327", + setup: async (c) => { + await c.$executeRawUnsafe(`CREATE TYPE g6_kind AS ENUM ('LOG','SPAN')`); + }, + run: (c) => c.$queryRaw`SELECT CAST('LOG'::text AS g6_kind) AS kind`, + }, + { + id: 7, + name: "jsonb with cast parameters (to_jsonb(${v}::text/::int))", + callSite: "dashboardPreferences.server.ts:145,175", + upstream: "#24338", + run: (c) => { + const theme = "dark"; + const contrast = 1; + return c.$queryRaw` + SELECT jsonb_set( + jsonb_set('{}'::jsonb, '{theme}', to_jsonb(${theme}::text)), + '{contrast}', to_jsonb(${contrast}::int) + ) AS prefs`; + }, + }, + { + id: 8, + name: "timestamptz round-trip (Date param)", + callSite: "Date -> timestamptz writers", + upstream: "#28629", + run: (c) => { + const d = new Date("2026-08-07T12:34:56.789Z"); + return c.$queryRaw`SELECT ${d}::timestamptz AS ts`; + }, + }, + { + id: 9, + name: "IN with varying arity", + callSite: "boundedIn() (TRI-4480)", + upstream: "#21803", + setup: async (c) => { + await c.$executeRawUnsafe(`CREATE TABLE g9 (id text)`); + await c.$executeRawUnsafe(`INSERT INTO g9 (id) VALUES ('a'),('b'),('c'),('d')`); + }, + run: async (c) => { + const one = await c.$queryRaw`SELECT id FROM g9 WHERE id IN (${"a"}) ORDER BY id`; + const three = + await c.$queryRaw`SELECT id FROM g9 WHERE id IN (${"a"},${"c"},${"d"}) ORDER BY id`; + return { arity1: one, arity3: three }; + }, + }, + { + id: 11, + name: "nulls, empty result set, zero-row RETURNING", + callSite: "classic divergence points", + setup: async (c) => { + await c.$executeRawUnsafe(`CREATE TABLE g11 (id text)`); + await c.$executeRawUnsafe(`INSERT INTO g11 (id) VALUES ('a')`); + }, + run: async (c) => { + const nulls = await c.$queryRaw`SELECT NULL::text AS a, NULL::int AS b`; + const empty = await c.$queryRaw`SELECT id FROM g11 WHERE 1=0`; + const returning = await c.$queryRaw`UPDATE g11 SET id = id WHERE 1=0 RETURNING id`; + return { nulls, empty, returning }; + }, + }, +]; + +function renderTable(results: ShapeResult[]): string { + const rows = results.map((r) => { + const status = r.identical ? "IDENTICAL" : r.adapterErrored ? "ADAPTER ERROR" : "DIVERGES"; + return [ + `### Shape ${r.id}: ${r.name}`, + `- call site: ${r.callSite}${r.upstream ? ` (upstream ${r.upstream})` : ""}`, + `- result: **${status}**`, + `- rust: \`${r.rust}\``, + `- adapter: \`${r.adapter}\``, + "", + ].join("\n"); + }); + const pass = results.filter((r) => r.identical).length; + return [`## Golden matrix: ${pass}/${results.length} identical`, "", ...rows].join("\n"); +} + +postgresTest( + "Deliverable B — raw-result equivalence matrix", + async ({ postgresContainer }) => { + const pair = await createClientPair(postgresContainer.getConnectionUri()); + const results: ShapeResult[] = []; + + try { + for (const shape of shapes) { + const result = await runShape(pair, shape); + results.push(result); + const tag = result.identical ? "OK " : result.adapterErrored ? "ERR " : "DIFF"; + console.log(`[TRI-13039][B] ${tag} shape ${result.id}: ${result.name}`); + if (!result.identical) { + console.log(` rust: ${result.rust}`); + console.log(` adapter: ${result.adapter}`); + } + } + } finally { + await pair.disconnect(); + } + + const md = renderTable(results); + console.log("\n" + md); + safeWrite("/Users/eric/code/triggerdotdev/isolated/adapter-pg-spike-work/golden-matrix.md", md); + + for (const r of results) { + expect(r.rust, `shape ${r.id} (${r.name}) must be byte-identical`).toBe(r.adapter); + } + }, + 180000 +); + +postgresTest( + "Deliverable B shape 10 — unqualified SQL relying on search_path / {schema} (#28128)", + async ({ postgresContainer }) => { + const baseUri = postgresContainer.getConnectionUri(); + + const admin = createRustClient(baseUri); + await admin.$executeRawUnsafe(`CREATE SCHEMA s1`); + await admin.$executeRawUnsafe(`CREATE TABLE s1.t (id text)`); + await admin.$executeRawUnsafe(`INSERT INTO s1.t (id) VALUES ('inschema')`); + await admin.$executeRawUnsafe(`CREATE TABLE public.pt (id text)`); + await admin.$executeRawUnsafe(`INSERT INTO public.pt (id) VALUES ('inpublic')`); + await admin.$disconnect(); + + const capture = async (fn: () => Promise) => { + try { + return { ok: true as const, desc: describe(await fn()) }; + } catch (err: any) { + return { + ok: false as const, + desc: `${err?.code}: ${String(err?.message).split("\n").pop()}`, + }; + } + }; + + const nonPublicAdapter = createAdapterClient(baseUri, "s1"); + const publicAdapter = createAdapterClient(baseUri, "public"); + try { + const nonPublic = await capture(() => + nonPublicAdapter.$queryRaw(Prisma.sql([`SELECT id FROM t ORDER BY id`])) + ); + const publicSchema = await capture(() => + publicAdapter.$queryRaw(Prisma.sql([`SELECT id FROM pt ORDER BY id`])) + ); + + console.log(`[TRI-13039][B] shape 10 adapter {schema:s1} unqualified: ${nonPublic.desc}`); + console.log( + `[TRI-13039][B] shape 10 adapter {schema:public} unqualified: ${publicSchema.desc}` + ); + safeWrite( + "/Users/eric/code/triggerdotdev/isolated/adapter-pg-spike-work/golden-shape10.md", + [ + "## Shape 10: unqualified SQL relying on search_path (#28128)", + "", + "The adapter's `{schema}` option does NOT set a session search_path for raw SQL.", + `- {schema:s1} + unqualified \`t\` (non-public): ${nonPublic.ok ? "OK" : "FAILS"} -> \`${nonPublic.desc}\``, + `- {schema:public} + unqualified \`pt\` (public): ${publicSchema.ok ? "OK" : "FAILS"} -> \`${publicSchema.desc}\``, + "", + "Prod impact: both DATABASE_URL and RUN_OPS_DATABASE_URL use ?schema=public, so unqualified", + "raw SQL resolves fine under the adapter. Only a non-public schema would break.", + ].join("\n") + ); + + expect(nonPublic.ok, "non-public schema breaks unqualified raw SQL (confirms #28128)").toBe( + false + ); + expect(publicSchema.ok, "public schema resolves unqualified raw SQL under the adapter").toBe( + true + ); + expect(publicSchema.desc).toBe(`[{id: "inpublic"}]`); + } finally { + await Promise.allSettled([nonPublicAdapter.$disconnect(), publicAdapter.$disconnect()]); + } + }, + 180000 +); diff --git a/internal-packages/testcontainers/src/adapterGolden.ts b/internal-packages/testcontainers/src/adapterGolden.ts new file mode 100644 index 00000000000..aa5ff1269fc --- /dev/null +++ b/internal-packages/testcontainers/src/adapterGolden.ts @@ -0,0 +1,99 @@ +import { PrismaClient, Prisma } from "@trigger.dev/database"; +import { PrismaPg } from "@prisma/adapter-pg"; + +export type ClientPair = { + rust: PrismaClient; + adapter: PrismaClient; + disconnect: () => Promise; +}; + +export function createRustClient(url: string): PrismaClient { + return new PrismaClient({ datasources: { db: { url } } }); +} + +export function createAdapterClient(url: string, schema?: string): PrismaClient { + const adapter = new PrismaPg({ connectionString: url }, schema ? { schema } : undefined); + return new PrismaClient({ adapter } as unknown as ConstructorParameters[0]); +} + +export async function createClientPair(url: string): Promise { + const rust = createRustClient(url); + const adapter = createAdapterClient(url); + return { + rust, + adapter, + disconnect: async () => { + await Promise.allSettled([rust.$disconnect(), adapter.$disconnect()]); + }, + }; +} + +export function describe(value: unknown): string { + if (value === null) return "null"; + if (value === undefined) return "undefined"; + if (typeof value === "bigint") return `bigint(${value.toString()})`; + if (Prisma.Decimal.isDecimal(value)) return `Decimal(${(value as Prisma.Decimal).toString()})`; + if (value instanceof Date) return `Date(${value.toISOString()})`; + if (Buffer.isBuffer(value)) return `Buffer(${value.toString("hex")})`; + if (Array.isArray(value)) return `[${value.map(describe).join(", ")}]`; + if (typeof value === "object") { + const entries = Object.entries(value as Record) + .map(([k, v]) => `${k}: ${describe(v)}`) + .join(", "); + return `{${entries}}`; + } + if (typeof value === "string") return `"${value}"`; + return `${typeof value}(${String(value)})`; +} + +export function deepEqual(a: unknown, b: unknown): boolean { + return describe(a) === describe(b); +} + +export type ShapeCase = { + id: number; + name: string; + callSite: string; + upstream?: string; + setup?: (rust: PrismaClient) => Promise; + run: (client: PrismaClient) => Promise; +}; + +export type ShapeResult = { + id: number; + name: string; + callSite: string; + upstream?: string; + rust: string; + adapter: string; + identical: boolean; + adapterErrored: boolean; +}; + +async function capture(fn: () => Promise): Promise<{ desc: string; errored: boolean }> { + try { + const value = await fn(); + return { desc: describe(value), errored: false }; + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + return { desc: `ERROR: ${message.split("\n")[0]}`, errored: true }; + } +} + +export async function runShape(pair: ClientPair, shape: ShapeCase): Promise { + if (shape.setup) { + await shape.setup(pair.rust); + } + const rust = await capture(() => shape.run(pair.rust)); + const adapter = await capture(() => shape.run(pair.adapter)); + return { + id: shape.id, + name: shape.name, + callSite: shape.callSite, + upstream: shape.upstream, + rust: rust.desc, + adapter: adapter.desc, + identical: rust.desc === adapter.desc, + adapterErrored: adapter.errored, + }; +} diff --git a/internal-packages/testcontainers/src/adapterTracing.test.ts b/internal-packages/testcontainers/src/adapterTracing.test.ts new file mode 100644 index 00000000000..c683f51082a --- /dev/null +++ b/internal-packages/testcontainers/src/adapterTracing.test.ts @@ -0,0 +1,70 @@ +import { registerInstrumentations } from "@opentelemetry/instrumentation"; +import { + InMemorySpanExporter, + SimpleSpanProcessor, + type ReadableSpan, +} from "@opentelemetry/sdk-trace-base"; +import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node"; +import { PrismaInstrumentation } from "@prisma/instrumentation"; +import { expect } from "vitest"; +import { postgresTest } from "./index"; +import { createAdapterClient, createRustClient } from "./adapterGolden"; + +const exporter = new InMemorySpanExporter(); +const provider = new NodeTracerProvider({ spanProcessors: [new SimpleSpanProcessor(exporter)] }); +provider.register(); +registerInstrumentations({ + tracerProvider: provider, + instrumentations: [new PrismaInstrumentation()], +}); + +async function collectSpanNames(query: () => Promise): Promise { + exporter.reset(); + await query(); + await provider.forceFlush(); + return exporter + .getFinishedSpans() + .map((s: ReadableSpan) => s.name) + .sort(); +} + +postgresTest( + "Deliverable A — engine spans survive the adapter", + async ({ postgresContainer }) => { + const url = postgresContainer.getConnectionUri(); + const rust = createRustClient(url); + const adapter = createAdapterClient(url); + + try { + const rustSpans = await collectSpanNames( + () => rust.$queryRaw`SELECT 1 AS one, 'x'::text AS label` + ); + const adapterSpans = await collectSpanNames( + () => adapter.$queryRaw`SELECT 1 AS one, 'x'::text AS label` + ); + + const unique = (xs: string[]) => Array.from(new Set(xs)).sort(); + + console.log("[TRI-13039][A] rust engine span names: ", unique(rustSpans)); + console.log("[TRI-13039][A] adapter span names: ", unique(adapterSpans)); + console.log( + "[TRI-13039][A] prisma:engine:connection present under adapter:", + adapterSpans.includes("prisma:engine:connection") + ); + + expect(rustSpans, "baseline: rust engine emits engine spans").toContain( + "prisma:engine:db_query" + ); + + expect(adapterSpans, "GATE: client operation span present under adapter").toContain( + "prisma:client:operation" + ); + expect(adapterSpans, "GATE: engine db_query span present under adapter").toContain( + "prisma:engine:db_query" + ); + } finally { + await Promise.allSettled([rust.$disconnect(), adapter.$disconnect()]); + } + }, + 120000 +); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f7532695b4e..8ba63003f5c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1436,6 +1436,21 @@ importers: '@internal/run-ops-database': specifier: workspace:* version: link:../run-ops-database + '@opentelemetry/instrumentation': + specifier: 0.218.0 + version: 0.218.0(@opentelemetry/api@1.9.1)(supports-color@10.0.0) + '@opentelemetry/sdk-trace-base': + specifier: 2.7.1 + version: 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-node': + specifier: 2.7.1 + version: 2.7.1(@opentelemetry/api@1.9.1) + '@prisma/adapter-pg': + specifier: 6.14.0 + version: 6.14.0 + '@prisma/instrumentation': + specifier: 6.14.0 + version: 6.14.0(@opentelemetry/api@1.9.1) '@testcontainers/postgresql': specifier: ^11.14.0 version: 11.14.0 @@ -1445,6 +1460,12 @@ importers: '@trigger.dev/core': specifier: workspace:* version: link:../../packages/core + '@types/pg': + specifier: ^8.11.10 + version: 8.11.14 + pg: + specifier: 8.15.6 + version: 8.15.6 std-env: specifier: ^3.9.0 version: 3.9.0 @@ -5679,6 +5700,9 @@ packages: '@posthog/types@1.376.4': resolution: {integrity: sha512-EoDEvA925lf6yxPpbP4wozlXgu4b9WEqxZlFBUDd4k2akP5R/RWyHpvQT8aYyfY6BtSLn8TnVwxPQOM4b90isA==} + '@prisma/adapter-pg@6.14.0': + resolution: {integrity: sha512-heUCNPZ3f2Iv/JId280HCoN7NECWkYckC3K1cOKpTRRjiJv0mN0w99V91vBq7aHHTtlOVpfDPQbUMNAjMegIWg==} + '@prisma/client@6.14.0': resolution: {integrity: sha512-8E/Nk3eL5g7RQIg/LUj1ICyDmhD053STjxrPxUtCRybs2s/2sOEcx9NpITuAOPn07HEpWBfhAVe1T/HYWXUPOw==} engines: {node: '>=18.18'} @@ -5700,6 +5724,9 @@ packages: '@prisma/debug@6.14.0': resolution: {integrity: sha512-j4Lf+y+5QIJgQD4sJWSbkOD7geKx9CakaLp/TyTy/UDu9Wo0awvWCBH/BAxTHUaCpIl9USA5VS/KJhDqKJSwug==} + '@prisma/driver-adapter-utils@6.14.0': + resolution: {integrity: sha512-On9vTNiJ7J/O1kVqedLtfdhhrfRYprkUOhxjlmmWEv12WNdG6v5x4PsrfZXdBtZqRZaqK1i1TigO6IdtYh8z+A==} + '@prisma/engines-version@6.14.0-25.717184b7b35ea05dfa71a3236b7af656013e1e49': resolution: {integrity: sha512-EgN9ODJpiX45yvwcngoStp3uQPJ3l+AEVoQ6dMMO2QvmwIlnxfApzKmJQExzdo7/hqQANrz5txHJdGYHzOnGHA==} @@ -13324,9 +13351,6 @@ packages: pg-protocol@1.10.3: resolution: {integrity: sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==} - pg-protocol@1.9.5: - resolution: {integrity: sha512-DYTWtWpfd5FOro3UnAfwvhD8jh59r2ig8bPtc9H8Ds7MscE/9NYruUQWFAOuraRl29jwcT2kyMFQ3MxeaVjUhg==} - pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} @@ -16209,7 +16233,7 @@ snapshots: cjs-module-lexer: 1.4.3 fflate: 0.8.3 lru-cache: 11.2.4 - semver: 7.8.1 + semver: 7.8.5 typescript: 5.6.1-rc validate-npm-package-name: 5.0.0 @@ -19428,7 +19452,7 @@ snapshots: '@npmcli/fs@3.1.0': dependencies: - semver: 7.8.1 + semver: 7.8.5 '@npmcli/git@4.1.0': dependencies: @@ -19438,7 +19462,7 @@ snapshots: proc-log: 3.0.0 promise-inflight: 1.0.1 promise-retry: 2.0.1 - semver: 7.8.1 + semver: 7.8.5 which: 3.0.1 transitivePeerDependencies: - bluebird @@ -19817,7 +19841,7 @@ snapshots: '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.28.0 forwarded-parse: 2.1.2 - semver: 7.8.1 + semver: 7.8.5 transitivePeerDependencies: - supports-color @@ -19960,7 +19984,7 @@ snapshots: '@types/shimmer': 1.2.0 import-in-the-middle: 1.15.0 require-in-the-middle: 7.5.2 - semver: 7.8.1 + semver: 7.8.5 shimmer: 1.2.1 transitivePeerDependencies: - supports-color @@ -20315,6 +20339,14 @@ snapshots: '@posthog/types@1.376.4': {} + '@prisma/adapter-pg@6.14.0': + dependencies: + '@prisma/driver-adapter-utils': 6.14.0 + pg: 8.15.6 + postgres-array: 3.0.4 + transitivePeerDependencies: + - pg-native + '@prisma/client@6.14.0(prisma@6.14.0(magicast@0.3.5)(typescript@7.0.2))(typescript@7.0.2)': optionalDependencies: prisma: 6.14.0(magicast@0.3.5)(typescript@7.0.2) @@ -20340,6 +20372,10 @@ snapshots: '@prisma/debug@6.14.0': {} + '@prisma/driver-adapter-utils@6.14.0': + dependencies: + '@prisma/debug': 6.14.0 + '@prisma/engines-version@6.14.0-25.717184b7b35ea05dfa71a3236b7af656013e1e49': {} '@prisma/engines@6.14.0': @@ -23169,7 +23205,7 @@ snapshots: '@types/pg@8.11.14': dependencies: '@types/node': 24.13.3 - pg-protocol: 1.9.5 + pg-protocol: 1.10.3 pg-types: 4.0.2 '@types/pg@8.6.1': @@ -24273,7 +24309,7 @@ snapshots: builtins@5.0.1: dependencies: - semver: 7.8.1 + semver: 7.8.5 bundle-name@4.1.0: dependencies: @@ -24641,7 +24677,7 @@ snapshots: dot-prop: 10.1.0 env-paths: 3.0.0 json-schema-typed: 8.0.2 - semver: 7.8.1 + semver: 7.8.5 uint8array-extras: 1.5.0 confbox@0.1.8: {} @@ -25339,7 +25375,7 @@ snapshots: '@one-ini/wasm': 0.1.1 commander: 10.0.1 minimatch: 9.0.1 - semver: 7.8.1 + semver: 7.8.5 ee-first@1.1.1: {} @@ -27324,7 +27360,7 @@ snapshots: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.8.1 + semver: 7.8.5 junk@4.0.1: {} @@ -27600,7 +27636,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.8.1 + semver: 7.8.5 map-obj@1.0.1: {} @@ -28661,7 +28697,7 @@ snapshots: dependencies: hosted-git-info: 6.1.1 is-core-module: 2.14.0 - semver: 7.8.1 + semver: 7.8.5 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} @@ -28674,7 +28710,7 @@ snapshots: npm-install-checks@6.2.0: dependencies: - semver: 7.8.1 + semver: 7.8.5 npm-normalize-package-bin@3.0.1: {} @@ -28682,7 +28718,7 @@ snapshots: dependencies: hosted-git-info: 6.1.1 proc-log: 3.0.0 - semver: 7.8.1 + semver: 7.8.5 validate-npm-package-name: 5.0.0 npm-pick-manifest@8.0.2: @@ -28690,7 +28726,7 @@ snapshots: npm-install-checks: 6.2.0 npm-normalize-package-bin: 3.0.1 npm-package-arg: 10.1.0 - semver: 7.8.1 + semver: 7.8.5 npm-run-all@4.1.5: dependencies: @@ -29209,8 +29245,6 @@ snapshots: pg-protocol@1.10.3: {} - pg-protocol@1.9.5: {} - pg-types@2.2.0: dependencies: pg-int8: 1.0.1