diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cb773a077743..0e826c1cb238 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -24,6 +24,7 @@ /dev-packages/node-core-integration-tests/ @getsentry/team-javascript-sdks-server /dev-packages/cloudflare-integration-tests/ @getsentry/team-javascript-sdks-server /dev-packages/bun-integration-tests/ @getsentry/team-javascript-sdks-server +/dev-packages/deno-integration-tests/ @getsentry/team-javascript-sdks-server # Framework integration packages /packages/angular/ @getsentry/team-javascript-sdks-framework diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 08c00304f15f..6a95233745f2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -172,6 +172,9 @@ jobs: changed_bun_integration: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry-internal/bun-integration-tests') }} + changed_deno_integration: + ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, + '@sentry-internal/deno-integration-tests') }} changed_browser_integration: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry-internal/browser-integration-tests') }} @@ -966,6 +969,36 @@ jobs: working-directory: dev-packages/bun-integration-tests run: yarn test + job_deno_integration_tests: + name: Deno Integration Tests + needs: [job_get_metadata, job_build] + if: needs.job_build.outputs.changed_deno_integration == 'true' || github.event_name != 'pull_request' + runs-on: ubuntu-24.04 + timeout-minutes: 15 + steps: + - name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) + uses: actions/checkout@v6 + with: + ref: ${{ env.HEAD_COMMIT }} + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version-file: 'package.json' + - name: Set up Deno + uses: denoland/setup-deno@v2.0.4 + with: + deno-version: 'v2.8.0' + - name: Restore caches + uses: ./.github/actions/restore-cache + with: + dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Build @sentry/deno + working-directory: packages/deno + run: yarn build + - name: Run integration tests + working-directory: dev-packages/deno-integration-tests + run: yarn test + job_build_tarballs: name: Build tarballs # We want to run this if: @@ -1266,6 +1299,7 @@ jobs: job_cloudflare_integration_tests, job_bundler_plugin_integration_tests, job_bun_integration_tests, + job_deno_integration_tests, job_browser_playwright_tests, job_browser_loader_tests, job_e2e_tests, diff --git a/.gitignore b/.gitignore index 8dcadcf57b91..722587ec72c0 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,7 @@ tmp.js packages/deno/build-types packages/deno/build-test packages/deno/lib.deno.d.ts +dev-packages/deno-integration-tests/lib.deno.d.ts deno.lock # gatsby diff --git a/dev-packages/deno-integration-tests/.oxlintrc.json b/dev-packages/deno-integration-tests/.oxlintrc.json new file mode 100644 index 000000000000..b3472f86b67a --- /dev/null +++ b/dev-packages/deno-integration-tests/.oxlintrc.json @@ -0,0 +1,25 @@ +{ + "$schema": "../../node_modules/oxlint/configuration_schema.json", + "extends": ["../.oxlintrc.json"], + "env": { + "node": true + }, + "overrides": [ + { + "files": ["suites/**/*.ts", "suites/**/*.mjs"], + "globals": { + "Deno": "readonly" + }, + "rules": { + "typescript/ban-ts-comment": [ + "error", + { + "ts-ignore": "allow-with-description", + "ts-expect-error": true + } + ], + "import/first": "off" + } + } + ] +} diff --git a/dev-packages/deno-integration-tests/package.json b/dev-packages/deno-integration-tests/package.json new file mode 100644 index 000000000000..a4430905f843 --- /dev/null +++ b/dev-packages/deno-integration-tests/package.json @@ -0,0 +1,26 @@ +{ + "name": "@sentry-internal/deno-integration-tests", + "version": "10.63.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "private": true, + "scripts": { + "deno-types": "node ./scripts/download-deno-types.mjs", + "install:deno": "node ./scripts/install-deno.mjs", + "lint": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --type-aware", + "lint:fix": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --fix --type-aware", + "test": "run-s install:deno deno-types test:unit", + "test:unit": "deno test --allow-net --allow-read --allow-run --allow-env --no-check" + }, + "dependencies": { + "@sentry/core": "10.63.0", + "@sentry/deno": "10.63.0", + "mysql": "^2.18.1", + "pg": "^8.22.0" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/dev-packages/deno-integration-tests/scripts/download-deno-types.mjs b/dev-packages/deno-integration-tests/scripts/download-deno-types.mjs new file mode 100644 index 000000000000..96cd724fbf99 --- /dev/null +++ b/dev-packages/deno-integration-tests/scripts/download-deno-types.mjs @@ -0,0 +1,7 @@ +import { existsSync, writeFileSync } from 'fs'; +import { download } from './download.mjs'; + +if (!existsSync('lib.deno.d.ts')) { + const code = await download('https://github.com/denoland/deno/releases/download/v2.8.0/lib.deno.d.ts'); + writeFileSync('lib.deno.d.ts', code); +} diff --git a/dev-packages/deno-integration-tests/scripts/download.mjs b/dev-packages/deno-integration-tests/scripts/download.mjs new file mode 100644 index 000000000000..4feefcfd3b90 --- /dev/null +++ b/dev-packages/deno-integration-tests/scripts/download.mjs @@ -0,0 +1,16 @@ +/** Download a url to a string */ +export async function download(url) { + try { + // `fetch` only rejects on network errors, so check the status explicitly — otherwise an error body + // (e.g. a 404 HTML page) would be treated as success and fed to `execSync`/written to disk. + const res = await fetch(url); + if (!res.ok) { + throw new Error(`HTTP ${res.status} ${res.statusText}`); + } + return await res.text(); + } catch (e) { + // eslint-disable-next-line no-console + console.error('Failed to download', url, e); + process.exit(1); + } +} diff --git a/dev-packages/deno-integration-tests/scripts/install-deno.mjs b/dev-packages/deno-integration-tests/scripts/install-deno.mjs new file mode 100644 index 000000000000..ad962778af88 --- /dev/null +++ b/dev-packages/deno-integration-tests/scripts/install-deno.mjs @@ -0,0 +1,26 @@ +import { execSync } from 'child_process'; + +import { download } from './download.mjs'; + +try { + execSync('deno --version', { stdio: 'inherit' }); +} catch { + // eslint-disable-next-line no-console + console.error('Deno is not installed. Installing...'); + if (process.platform === 'win32') { + // TODO + // eslint-disable-next-line no-console + console.error('Please install Deno manually: https://docs.deno.com/runtime/manual/getting_started/installation'); + process.exit(1); + } else { + const script = await download('https://deno.land/x/install/install.sh'); + + try { + execSync(script, { stdio: 'inherit' }); + } catch (e) { + // eslint-disable-next-line no-console + console.error('Failed to install Deno', e); + process.exit(1); + } + } +} diff --git a/packages/deno/test/orchestrion-mysql/scenario.mjs b/dev-packages/deno-integration-tests/suites/orchestrion-mysql/scenario.mjs similarity index 95% rename from packages/deno/test/orchestrion-mysql/scenario.mjs rename to dev-packages/deno-integration-tests/suites/orchestrion-mysql/scenario.mjs index d0adf6b1ae7a..19d9e7cf82fe 100644 --- a/packages/deno/test/orchestrion-mysql/scenario.mjs +++ b/dev-packages/deno-integration-tests/suites/orchestrion-mysql/scenario.mjs @@ -1,4 +1,4 @@ -// Spawned by orchestrion-mysql.test.ts via `deno run`. +// Spawned by test.ts via `deno run`. // // Importing `@sentry/deno/import` FIRST registers the orchestrion module hook, // so the subsequent `mysql` import is transformed to publish to the diff --git a/packages/deno/test/orchestrion-mysql.test.ts b/dev-packages/deno-integration-tests/suites/orchestrion-mysql/test.ts similarity index 95% rename from packages/deno/test/orchestrion-mysql.test.ts rename to dev-packages/deno-integration-tests/suites/orchestrion-mysql/test.ts index 0159d66baf79..0f1aef13b17c 100644 --- a/packages/deno/test/orchestrion-mysql.test.ts +++ b/dev-packages/deno-integration-tests/suites/orchestrion-mysql/test.ts @@ -2,11 +2,11 @@ import { tracingChannel } from 'node:diagnostics_channel'; import type { TransactionEvent } from '@sentry/core'; +import type { DenoClient } from '@sentry/deno'; +import { getCurrentScope, getGlobalScope, getIsolationScope, init, startSpan } from '@sentry/deno'; import { assert } from 'https://deno.land/std@0.212.0/assert/assert.ts'; import { assertEquals } from 'https://deno.land/std@0.212.0/assert/assert_equals.ts'; import { assertExists } from 'https://deno.land/std@0.212.0/assert/assert_exists.ts'; -import type { DenoClient } from '../build/esm/index.js'; -import { getCurrentScope, getGlobalScope, getIsolationScope, init, startSpan } from '../build/esm/index.js'; function resetGlobals(): void { getCurrentScope().clear(); @@ -65,10 +65,11 @@ Deno.test('denoMysqlIntegration: included in default integrations (Deno 2.8.0+)' // import inside the entry graph in Deno 2.8.0 through 2.8.2. // TODO: revisit a `--import` or `--preload` approach once Deno 2.8.3 ships. Deno.test('@sentry/deno/import: transforms mysql so it publishes the orchestrion channel', async () => { - const scenario = new URL('./orchestrion-mysql/scenario.mjs', import.meta.url); + const scenario = new URL('./scenario.mjs', import.meta.url); - // packages/deno — where node_modules resolves - const cwd = new URL('../', import.meta.url); + // The package root — where `node_modules` (and thus `@sentry/deno` / `mysql`) + // resolves for the spawned `deno run`. + const cwd = new URL('../../', import.meta.url); const command = new Deno.Command('deno', { args: ['run', '--allow-all', scenario.pathname], diff --git a/packages/deno/test/orchestrion-postgres/scenario.mjs b/dev-packages/deno-integration-tests/suites/orchestrion-postgres/scenario.mjs similarity index 95% rename from packages/deno/test/orchestrion-postgres/scenario.mjs rename to dev-packages/deno-integration-tests/suites/orchestrion-postgres/scenario.mjs index fa6aadbdbe31..8f2524ae3267 100644 --- a/packages/deno/test/orchestrion-postgres/scenario.mjs +++ b/dev-packages/deno-integration-tests/suites/orchestrion-postgres/scenario.mjs @@ -1,4 +1,4 @@ -// Spawned by orchestrion-postgres.test.ts via `deno run`. +// Spawned by test.ts via `deno run`. // // Importing `@sentry/deno/import` FIRST registers the orchestrion module hook, // so the subsequent `pg` import is transformed to publish to the diff --git a/packages/deno/test/orchestrion-postgres.test.ts b/dev-packages/deno-integration-tests/suites/orchestrion-postgres/test.ts similarity index 82% rename from packages/deno/test/orchestrion-postgres.test.ts rename to dev-packages/deno-integration-tests/suites/orchestrion-postgres/test.ts index f1ca62c16988..f2a7cf9f8940 100644 --- a/packages/deno/test/orchestrion-postgres.test.ts +++ b/dev-packages/deno-integration-tests/suites/orchestrion-postgres/test.ts @@ -2,11 +2,11 @@ import { tracingChannel } from 'node:diagnostics_channel'; import type { TransactionEvent } from '@sentry/core'; +import type { DenoClient } from '@sentry/deno'; +import { getCurrentScope, getGlobalScope, getIsolationScope, init, startSpan } from '@sentry/deno'; import { assert } from 'https://deno.land/std@0.212.0/assert/assert.ts'; import { assertEquals } from 'https://deno.land/std@0.212.0/assert/assert_equals.ts'; import { assertExists } from 'https://deno.land/std@0.212.0/assert/assert_exists.ts'; -import type { DenoClient } from '../build/esm/index.js'; -import { getCurrentScope, getGlobalScope, getIsolationScope, init, startSpan } from '../build/esm/index.js'; function resetGlobals(): void { getCurrentScope().clear(); @@ -15,7 +15,7 @@ function resetGlobals(): void { getGlobalScope().clear(); } -/** See `deno-redis.test.ts` same sink shape, deduped for clarity. */ +/** See deno-redis.test.ts — same sink shape, deduped for clarity. */ function transactionSink(): { beforeSendTransaction: (event: TransactionEvent) => null; waitFor: (predicate: (event: TransactionEvent) => boolean) => Promise; @@ -65,10 +65,11 @@ Deno.test('denoPostgresIntegration: included in default integrations (Deno 2.8.0 // import inside the entry graph in Deno 2.8.0 through 2.8.2. // TODO: revisit a `--import` or `--preload` approach once Deno 2.8.3 ships. Deno.test('@sentry/deno/import: transforms pg so it publishes the orchestrion channel', async () => { - const scenario = new URL('./orchestrion-postgres/scenario.mjs', import.meta.url); + const scenario = new URL('./scenario.mjs', import.meta.url); - // packages/deno, where node_modules resolves - const cwd = new URL('../', import.meta.url); + // The package root — where `node_modules` (and thus `@sentry/deno` / `pg`) + // resolves for the spawned `deno run`. + const cwd = new URL('../../', import.meta.url); const command = new Deno.Command('deno', { args: ['run', '--allow-all', scenario.pathname], @@ -94,13 +95,12 @@ Deno.test('@sentry/deno/import: transforms pg so it publishes the orchestrion ch assert(line.includes('"runtime":true'), `expected runtime marker, got: ${line}`); }); -// Exercises the SDK path e2e: `init()` wires `denoPostgresIntegration` -// (which installs the AsyncLocalStorage context strategy and subscribes to -// the channel), and we drive the `orchestrion:pg:query` channel manually, -// the same events the orchestrion transform publishes around -// `client.query()`, so no live database is needed. Asserting a nested `db` -// span proves the subscriber, the emitted attributes, AND the -// context-strategy wiring all work. +// Exercises the SDK path end-to-end: `init()` wires `denoPostgresIntegration` +// (which installs the AsyncLocalStorage context strategy and subscribes to the +// channel), and we drive the `orchestrion:pg:query` channel manually — the +// same events the orchestrion transform publishes around `client.query()` — +// so no live database is needed. Asserting a nested `db` span proves the +// subscriber, the emitted attributes, AND the context-strategy wiring all work. Deno.test('denoPostgresIntegration: orchestrion:pg:query channel produces a nested db span', async () => { resetGlobals(); const sink = transactionSink(); @@ -112,17 +112,17 @@ Deno.test('denoPostgresIntegration: orchestrion:pg:query channel produces a nest const channel = tracingChannel('orchestrion:pg:query'); - // The shared context object orchestrion reuses across the lifecycle events - // - // `arguments[0]` is the SQL; `self.connectionParameters` is pg's resolved - // connection config. + // The shared context object orchestrion reuses across the lifecycle events. + // `arguments[0]` is the SQL; `self.connectionParameters` is pg's resolved connection config. const ctx = { arguments: ['SELECT 1 AS solution'], self: { connectionParameters: { host: '127.0.0.1', port: 5432, database: 'mydb', user: 'root' } }, }; // Callback-success order published by orchestrion's transform: - // start -> end -> asyncStart -> asyncEnd (the span closes on asyncEnd). + // start → end → asyncStart → asyncEnd (the span closes on asyncEnd). + // `start`/`asyncStart` go through `runStores` (not bare `publish`), exactly as the transform's + // `wrapCallback` does — that's what activates the store the subscriber binds, so the span opens. startSpan({ name: 'parent', op: 'test' }, () => { channel.start.runStores(ctx, () => { channel.end.publish(ctx); diff --git a/dev-packages/deno-integration-tests/tsconfig.json b/dev-packages/deno-integration-tests/tsconfig.json new file mode 100644 index 000000000000..5906a14b8872 --- /dev/null +++ b/dev-packages/deno-integration-tests/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "include": ["suites/**/*"], + "compilerOptions": { + "lib": ["esnext"], + "target": "esnext" + } +} diff --git a/package.json b/package.json index 96afe5cc43f9..0ed1df51c77e 100644 --- a/package.json +++ b/package.json @@ -34,11 +34,11 @@ "dedupe-deps:check": "yarn-deduplicate yarn.lock --list --fail", "dedupe-deps:fix": "yarn-deduplicate yarn.lock", "postpublish": "nx run-many -t postpublish --parallel=1", - "test": "nx run-many -t test --exclude \"@sentry-internal/{browser-integration-tests,bun-integration-tests,e2e-tests,integration-shims,node-integration-tests,node-core-integration-tests,cloudflare-integration-tests,bundler-plugin-integration-tests}\"", + "test": "nx run-many -t test --exclude \"@sentry-internal/{browser-integration-tests,bun-integration-tests,deno-integration-tests,e2e-tests,integration-shims,node-integration-tests,node-core-integration-tests,cloudflare-integration-tests,bundler-plugin-integration-tests}\"", "test:scripts": "vitest run scripts/*.test.ts", - "test:unit": "nx run-many -t test:unit --exclude \"@sentry-internal/{browser-integration-tests,bun-integration-tests,e2e-tests,integration-shims,node-integration-tests,node-core-integration-tests,cloudflare-integration-tests,bundler-plugin-integration-tests}\"", + "test:unit": "nx run-many -t test:unit --exclude \"@sentry-internal/{browser-integration-tests,bun-integration-tests,deno-integration-tests,e2e-tests,integration-shims,node-integration-tests,node-core-integration-tests,cloudflare-integration-tests,bundler-plugin-integration-tests}\"", "test:update-snapshots": "nx run-many -t test:update-snapshots", - "test:pr": "nx affected -t test --exclude \"@sentry-internal/{browser-integration-tests,bun-integration-tests,e2e-tests,integration-shims,node-integration-tests,node-core-integration-tests,cloudflare-integration-tests,bundler-plugin-integration-tests}\"", + "test:pr": "nx affected -t test --exclude \"@sentry-internal/{browser-integration-tests,bun-integration-tests,deno-integration-tests,e2e-tests,integration-shims,node-integration-tests,node-core-integration-tests,cloudflare-integration-tests,bundler-plugin-integration-tests}\"", "test:pr:browser": "UNIT_TEST_ENV=browser ts-node ./scripts/ci-unit-tests.ts --affected", "test:pr:node": "UNIT_TEST_ENV=node ts-node ./scripts/ci-unit-tests.ts --affected", "test:ci:browser": "UNIT_TEST_ENV=browser ts-node ./scripts/ci-unit-tests.ts", @@ -105,6 +105,7 @@ "dev-packages/e2e-tests", "dev-packages/node-integration-tests", "dev-packages/bun-integration-tests", + "dev-packages/deno-integration-tests", "dev-packages/cloudflare-integration-tests", "dev-packages/node-core-integration-tests", "dev-packages/test-utils", diff --git a/packages/deno/package.json b/packages/deno/package.json index cd534645819f..a84b2e6cecb8 100644 --- a/packages/deno/package.json +++ b/packages/deno/package.json @@ -31,10 +31,6 @@ "@sentry/core": "10.63.0", "@sentry/server-utils": "10.63.0" }, - "devDependencies": { - "mysql": "^2.18.1", - "pg": "8.16.0" - }, "scripts": { "deno-types": "node ./scripts/download-deno-types.mjs", "build": "run-s build:transpile build:types", diff --git a/yarn.lock b/yarn.lock index 19432f5fdbea..4e94f640b6d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24031,7 +24031,7 @@ periscopic@^3.1.0: estree-walker "^3.0.0" is-reference "^3.0.0" -pg-cloudflare@^1.2.5, pg-cloudflare@^1.3.0: +pg-cloudflare@^1.2.5, pg-cloudflare@^1.3.0, pg-cloudflare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.4.0.tgz#4b4c20e6d8ae531d400730f4804571a8d62f1497" integrity sha512-Vo7z/6rrQYxpNRylp4Tlob2elzbh+N/MOQbxFVWCxS7oEx6jF53GTJFxK2WWpKuBRkmiin4Mt+xofFDjx09R0A== @@ -24041,7 +24041,7 @@ pg-connection-string@2.6.1: resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.1.tgz#78c23c21a35dd116f48e12e23c0965e8d9e2cbfb" integrity sha512-w6ZzNu6oMmIzEAYVw+RLK0+nqHPt8K3ZnknKi+g48Ak2pr3dtljJW3o+D/n2zzCG07Zoe9VOX3aiKpj+BN0pjg== -pg-connection-string@^2.12.0, pg-connection-string@^2.9.0: +pg-connection-string@^2.12.0, pg-connection-string@^2.14.0, pg-connection-string@^2.9.0: version "2.14.0" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.14.0.tgz#abc26ee4f37c56c0f3ae0fcf0b0653cc4e1c0fd9" integrity sha512-XwWDGcLRGCXAR8F/AM5bG7Q+A3Wm2s6QeEjlOKZLlH3UYcguiqCWKyWXVag5TLTIjR7oOJUY8kcADaZgWPyLeg== @@ -24051,12 +24051,12 @@ pg-int8@1.0.1: resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== -pg-pool@^3.10.0, pg-pool@^3.13.0: +pg-pool@^3.10.0, pg-pool@^3.13.0, pg-pool@^3.14.0: version "3.14.0" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.14.0.tgz#f35ae4eb846780cad71af24099b3edfa9781ad90" integrity sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw== -pg-protocol@*, pg-protocol@^1.10.0, pg-protocol@^1.13.0: +pg-protocol@*, pg-protocol@^1.10.0, pg-protocol@^1.13.0, pg-protocol@^1.15.0: version "1.15.0" resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.15.0.tgz#758f6c0679cc0bbf4938603b7597703f333180c0" integrity sha512-cq9sECI5s0+uPUXjbz8ioyPJni6RzsRib0US67i5IoTZKw8fNeYlVE7u8F4dG7vEJJtc5wdD1K189lCCUwqWTQ== @@ -24085,7 +24085,7 @@ pg@8.16.0: optionalDependencies: pg-cloudflare "^1.2.5" -pg@8.20.0, pg@^8.16.3: +pg@8.20.0: version "8.20.0" resolved "https://registry.yarnpkg.com/pg/-/pg-8.20.0.tgz#1a274de944cb329fd6dd77a6d371a005ba6b136d" integrity sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA== @@ -24098,6 +24098,19 @@ pg@8.20.0, pg@^8.16.3: optionalDependencies: pg-cloudflare "^1.3.0" +pg@^8.16.3, pg@^8.22.0: + version "8.22.0" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.22.0.tgz#55ca3975026180c6dced6eec3a20a844c2dc9237" + integrity sha512-8wih1vVIBMxoUM2oB4soJsD9tDnDpLv4OXBJ+EJzFsvycD+lfyIreC2gGHq78f8jbLLt+bvlPTFdFZfJkOuzAA== + dependencies: + pg-connection-string "^2.14.0" + pg-pool "^3.14.0" + pg-protocol "^1.15.0" + pg-types "2.2.0" + pgpass "1.0.5" + optionalDependencies: + pg-cloudflare "^1.4.0" + pgpass@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d"