diff --git a/package-lock.json b/package-lock.json index 921e6f4b..752051a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7836,6 +7836,51 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tinypool": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", @@ -8130,15 +8175,18 @@ } }, "node_modules/vite": { - "version": "6.2.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.6.tgz", - "integrity": "sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw==", + "version": "6.3.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.4.tgz", + "integrity": "sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", "postcss": "^8.5.3", - "rollup": "^4.30.1" + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" @@ -8224,6 +8272,34 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/vitest": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", diff --git a/src/server/routes/column-privileges.ts b/src/server/routes/column-privileges.ts index ddde2c57..d1b1f194 100644 --- a/src/server/routes/column-privileges.ts +++ b/src/server/routes/column-privileges.ts @@ -6,7 +6,7 @@ import { postgresColumnPrivilegesRevokeSchema, postgresColumnPrivilegesSchema, } from '../../lib/types.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging, translateErrorToResponseCode } from '../utils.js' const route: FastifyPluginAsyncTypebox = async (fastify) => { @@ -16,6 +16,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), querystring: Type.Object({ include_system_schemas: Type.Optional(Type.Boolean()), @@ -34,14 +35,14 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const includeSystemSchemas = request.query.include_system_schemas const includedSchemas = request.query.included_schemas?.split(',') const excludedSchemas = request.query.excluded_schemas?.split(',') const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.columnPrivileges.list({ includeSystemSchemas, includedSchemas, @@ -66,6 +67,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), body: Type.Array(postgresColumnPrivilegesGrantSchema), response: { @@ -77,9 +79,9 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.columnPrivileges.grant(request.body) await pgMeta.end() if (error) { @@ -98,6 +100,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), body: Type.Array(postgresColumnPrivilegesRevokeSchema), response: { @@ -112,9 +115,9 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.columnPrivileges.revoke(request.body) await pgMeta.end() if (error) { diff --git a/src/server/routes/columns.ts b/src/server/routes/columns.ts index 54a7ba2a..21e12364 100644 --- a/src/server/routes/columns.ts +++ b/src/server/routes/columns.ts @@ -1,6 +1,5 @@ import { PostgresMeta } from '../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' -import { extractRequestForLogging } from '../utils.js' +import { createConnectionConfig, extractRequestForLogging } from '../utils.js' import { Type } from '@sinclair/typebox' import { postgresColumnCreateSchema, @@ -16,6 +15,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), querystring: Type.Object({ include_system_schemas: Type.Optional(Type.Boolean()), @@ -33,14 +33,14 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg const includeSystemSchemas = request.query.include_system_schemas const includedSchemas = request.query.included_schemas?.split(',') const excludedSchemas = request.query.excluded_schemas?.split(',') const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.columns.list({ includeSystemSchemas, includedSchemas, @@ -65,6 +65,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ tableId: Type.String(), @@ -86,13 +87,13 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { async (request, reply) => { if (request.params.ordinalPosition === '') { const { - headers: { pg: connectionString }, query: { limit, offset }, params: { tableId }, } = request const includeSystemSchemas = request.query.include_system_schemas - const pgMeta: PostgresMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta: PostgresMeta = new PostgresMeta(config) const { data, error } = await pgMeta.columns.list({ tableId: Number(tableId), includeSystemSchemas, @@ -109,12 +110,12 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { return data[0] } else if (/^\.\d+$/.test(request.params.ordinalPosition)) { const { - headers: { pg: connectionString }, params: { tableId, ordinalPosition: ordinalPositionWithDot }, } = request const ordinalPosition = ordinalPositionWithDot.slice(1) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.columns.retrieve({ id: `${tableId}.${ordinalPosition}`, }) @@ -139,6 +140,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), body: postgresColumnCreateSchema, response: { @@ -150,9 +152,8 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg - - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.columns.create(request.body) await pgMeta.end() if (error) { @@ -172,6 +173,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.String(), @@ -186,9 +188,8 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg - - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.columns.update(request.params.id, request.body) await pgMeta.end() if (error) { @@ -208,6 +209,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.String(), @@ -224,10 +226,10 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg const cascade = request.query.cascade === 'true' - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.columns.remove(request.params.id, { cascade }) await pgMeta.end() if (error) { diff --git a/src/server/routes/config.ts b/src/server/routes/config.ts index f24e9628..a2faf9db 100644 --- a/src/server/routes/config.ts +++ b/src/server/routes/config.ts @@ -1,21 +1,21 @@ import { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' export default async (fastify: FastifyInstance) => { fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Querystring: { limit?: number offset?: number } }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.config.list({ limit, offset }) await pgMeta.end() if (error) { @@ -28,11 +28,11 @@ export default async (fastify: FastifyInstance) => { }) fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } }>('/version', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.version.retrieve() await pgMeta.end() if (error) { diff --git a/src/server/routes/extensions.ts b/src/server/routes/extensions.ts index 71c9308a..b202c251 100644 --- a/src/server/routes/extensions.ts +++ b/src/server/routes/extensions.ts @@ -1,21 +1,21 @@ import { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' export default async (fastify: FastifyInstance) => { fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Querystring: { limit?: number offset?: number } }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.extensions.list({ limit, offset }) await pgMeta.end() if (error) { @@ -28,14 +28,14 @@ export default async (fastify: FastifyInstance) => { }) fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { name: string } }>('/:name', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.extensions.retrieve({ name: request.params.name }) await pgMeta.end() if (error) { @@ -48,12 +48,12 @@ export default async (fastify: FastifyInstance) => { }) fastify.post<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Body: any }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.extensions.create(request.body as any) await pgMeta.end() if (error) { @@ -66,15 +66,15 @@ export default async (fastify: FastifyInstance) => { }) fastify.patch<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { name: string } Body: any }>('/:name', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.extensions.update(request.params.name, request.body as any) await pgMeta.end() if (error) { @@ -88,7 +88,7 @@ export default async (fastify: FastifyInstance) => { }) fastify.delete<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { name: string } @@ -96,10 +96,10 @@ export default async (fastify: FastifyInstance) => { cascade?: string } }>('/:name', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const cascade = request.query.cascade === 'true' - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.extensions.remove(request.params.name, { cascade }) await pgMeta.end() if (error) { diff --git a/src/server/routes/foreign-tables.ts b/src/server/routes/foreign-tables.ts index 931295b4..4de924f6 100644 --- a/src/server/routes/foreign-tables.ts +++ b/src/server/routes/foreign-tables.ts @@ -2,7 +2,7 @@ import { FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox' import { Type } from '@sinclair/typebox' import { PostgresMeta } from '../../lib/index.js' import { postgresForeignTableSchema } from '../../lib/types.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' const route: FastifyPluginAsyncTypebox = async (fastify) => { @@ -12,6 +12,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), querystring: Type.Object({ limit: Type.Optional(Type.Integer()), @@ -27,12 +28,12 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const limit = request.query.limit const offset = request.query.offset const includeColumns = request.query.include_columns - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.foreignTables.list({ limit, offset, includeColumns }) await pgMeta.end() if (error) { @@ -51,6 +52,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.Integer(), @@ -64,10 +66,10 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = request.params.id - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.foreignTables.retrieve({ id }) await pgMeta.end() if (error) { diff --git a/src/server/routes/functions.ts b/src/server/routes/functions.ts index 2e494be3..51fd5737 100644 --- a/src/server/routes/functions.ts +++ b/src/server/routes/functions.ts @@ -1,11 +1,11 @@ import { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' export default async (fastify: FastifyInstance) => { fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Querystring: { include_system_schemas?: string // Note: this only supports comma separated values (e.g., ".../functions?included_schemas=public,core") @@ -15,14 +15,14 @@ export default async (fastify: FastifyInstance) => { offset?: number } }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const includeSystemSchemas = request.query.include_system_schemas === 'true' const includedSchemas = request.query.included_schemas?.split(',') const excludedSchemas = request.query.excluded_schemas?.split(',') const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.functions.list({ includeSystemSchemas, includedSchemas, @@ -41,15 +41,15 @@ export default async (fastify: FastifyInstance) => { }) fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.functions.retrieve({ id }) await pgMeta.end() if (error) { @@ -62,12 +62,12 @@ export default async (fastify: FastifyInstance) => { }) fastify.post<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Body: any }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.functions.create(request.body as any) await pgMeta.end() if (error) { @@ -79,16 +79,16 @@ export default async (fastify: FastifyInstance) => { }) fastify.patch<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } Body: any }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.functions.update(id, request.body as any) await pgMeta.end() if (error) { @@ -101,15 +101,15 @@ export default async (fastify: FastifyInstance) => { }) fastify.delete<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.functions.remove(id) await pgMeta.end() if (error) { diff --git a/src/server/routes/generators/go.ts b/src/server/routes/generators/go.ts index aaf1bb07..fa85fa46 100644 --- a/src/server/routes/generators/go.ts +++ b/src/server/routes/generators/go.ts @@ -1,25 +1,24 @@ import type { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../../constants.js' -import { extractRequestForLogging } from '../../utils.js' +import { createConnectionConfig, extractRequestForLogging } from '../../utils.js' import { apply as applyGoTemplate } from '../../templates/go.js' import { getGeneratorMetadata } from '../../../lib/generators.js' export default async (fastify: FastifyInstance) => { fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Querystring: { excluded_schemas?: string included_schemas?: string } }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const excludedSchemas = request.query.excluded_schemas?.split(',').map((schema) => schema.trim()) ?? [] const includedSchemas = request.query.included_schemas?.split(',').map((schema) => schema.trim()) ?? [] - const pgMeta: PostgresMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta: PostgresMeta = new PostgresMeta(config) const { data: generatorMeta, error: generatorMetaError } = await getGeneratorMetadata(pgMeta, { includedSchemas, excludedSchemas, diff --git a/src/server/routes/generators/swift.ts b/src/server/routes/generators/swift.ts index 2c802fe2..e02839fb 100644 --- a/src/server/routes/generators/swift.ts +++ b/src/server/routes/generators/swift.ts @@ -1,27 +1,26 @@ import type { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../../constants.js' -import { extractRequestForLogging } from '../../utils.js' +import { createConnectionConfig, extractRequestForLogging } from '../../utils.js' import { apply as applySwiftTemplate, AccessControl } from '../../templates/swift.js' import { getGeneratorMetadata } from '../../../lib/generators.js' export default async (fastify: FastifyInstance) => { fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Querystring: { excluded_schemas?: string included_schemas?: string access_control?: AccessControl } }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const excludedSchemas = request.query.excluded_schemas?.split(',').map((schema) => schema.trim()) ?? [] const includedSchemas = request.query.included_schemas?.split(',').map((schema) => schema.trim()) ?? [] const accessControl = request.query.access_control ?? 'internal' - const pgMeta: PostgresMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta: PostgresMeta = new PostgresMeta(config) const { data: generatorMeta, error: generatorMetaError } = await getGeneratorMetadata(pgMeta, { includedSchemas, excludedSchemas, diff --git a/src/server/routes/generators/typescript.ts b/src/server/routes/generators/typescript.ts index b7a75248..3e615b32 100644 --- a/src/server/routes/generators/typescript.ts +++ b/src/server/routes/generators/typescript.ts @@ -1,27 +1,26 @@ import type { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../../constants.js' -import { extractRequestForLogging } from '../../utils.js' +import { createConnectionConfig, extractRequestForLogging } from '../../utils.js' import { apply as applyTypescriptTemplate } from '../../templates/typescript.js' import { getGeneratorMetadata } from '../../../lib/generators.js' export default async (fastify: FastifyInstance) => { fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Querystring: { excluded_schemas?: string included_schemas?: string detect_one_to_one_relationships?: string } }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const excludedSchemas = request.query.excluded_schemas?.split(',').map((schema) => schema.trim()) ?? [] const includedSchemas = request.query.included_schemas?.split(',').map((schema) => schema.trim()) ?? [] const detectOneToOneRelationships = request.query.detect_one_to_one_relationships === 'true' - const pgMeta: PostgresMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta: PostgresMeta = new PostgresMeta(config) const { data: generatorMeta, error: generatorMetaError } = await getGeneratorMetadata(pgMeta, { includedSchemas, excludedSchemas, diff --git a/src/server/routes/indexes.ts b/src/server/routes/indexes.ts index 69e88ef6..b024ea09 100644 --- a/src/server/routes/indexes.ts +++ b/src/server/routes/indexes.ts @@ -1,11 +1,10 @@ import { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' -import { extractRequestForLogging } from '../utils.js' +import { createConnectionConfig, extractRequestForLogging } from '../utils.js' export default async (fastify: FastifyInstance) => { fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Querystring: { include_system_schemas?: string // Note: this only supports comma separated values (e.g., ".../functions?included_schemas=public,core") @@ -15,14 +14,14 @@ export default async (fastify: FastifyInstance) => { offset?: number } }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const includeSystemSchemas = request.query.include_system_schemas === 'true' const includedSchemas = request.query.included_schemas?.split(',') const excludedSchemas = request.query.excluded_schemas?.split(',') const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.indexes.list({ includeSystemSchemas, includedSchemas, @@ -41,15 +40,15 @@ export default async (fastify: FastifyInstance) => { }) fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.indexes.retrieve({ id }) await pgMeta.end() if (error) { diff --git a/src/server/routes/materialized-views.ts b/src/server/routes/materialized-views.ts index 48c2fee7..9a5a0b4f 100644 --- a/src/server/routes/materialized-views.ts +++ b/src/server/routes/materialized-views.ts @@ -2,7 +2,7 @@ import { FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox' import { Type } from '@sinclair/typebox' import { PostgresMeta } from '../../lib/index.js' import { postgresMaterializedViewSchema } from '../../lib/types.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' const route: FastifyPluginAsyncTypebox = async (fastify) => { @@ -12,6 +12,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), querystring: Type.Object({ included_schemas: Type.Optional(Type.String()), @@ -29,14 +30,14 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const includedSchemas = request.query.included_schemas?.split(',') const excludedSchemas = request.query.excluded_schemas?.split(',') const limit = request.query.limit const offset = request.query.offset const includeColumns = request.query.include_columns - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.materializedViews.list({ includedSchemas, excludedSchemas, @@ -61,6 +62,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.Integer(), @@ -74,10 +76,10 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = request.params.id - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.materializedViews.retrieve({ id }) await pgMeta.end() if (error) { diff --git a/src/server/routes/policies.ts b/src/server/routes/policies.ts index bb369a53..4e951ad3 100644 --- a/src/server/routes/policies.ts +++ b/src/server/routes/policies.ts @@ -1,11 +1,11 @@ import { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' export default async (fastify: FastifyInstance) => { fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Querystring: { include_system_schemas?: string // Note: this only supports comma separated values (e.g., ".../policies?included_schemas=public,core") @@ -15,14 +15,14 @@ export default async (fastify: FastifyInstance) => { offset?: number } }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const includeSystemSchemas = request.query.include_system_schemas === 'true' const includedSchemas = request.query.included_schemas?.split(',') const excludedSchemas = request.query.excluded_schemas?.split(',') const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.policies.list({ includeSystemSchemas, includedSchemas, @@ -41,15 +41,15 @@ export default async (fastify: FastifyInstance) => { }) fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.policies.retrieve({ id }) await pgMeta.end() if (error) { @@ -62,12 +62,12 @@ export default async (fastify: FastifyInstance) => { }) fastify.post<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Body: any }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.policies.create(request.body as any) await pgMeta.end() if (error) { @@ -80,16 +80,16 @@ export default async (fastify: FastifyInstance) => { }) fastify.patch<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } Body: any }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.policies.update(id, request.body as any) await pgMeta.end() if (error) { @@ -103,15 +103,15 @@ export default async (fastify: FastifyInstance) => { }) fastify.delete<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.policies.remove(id) await pgMeta.end() if (error) { diff --git a/src/server/routes/publications.ts b/src/server/routes/publications.ts index 4aa63796..68cf45b2 100644 --- a/src/server/routes/publications.ts +++ b/src/server/routes/publications.ts @@ -1,21 +1,21 @@ import { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' export default async (fastify: FastifyInstance) => { fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Querystring: { limit?: number offset?: number } }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.publications.list({ limit, offset }) await pgMeta.end() if (error) { @@ -28,15 +28,15 @@ export default async (fastify: FastifyInstance) => { }) fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.publications.retrieve({ id }) await pgMeta.end() if (error) { @@ -49,12 +49,12 @@ export default async (fastify: FastifyInstance) => { }) fastify.post<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Body: any }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.publications.create(request.body as any) await pgMeta.end() if (error) { @@ -67,16 +67,16 @@ export default async (fastify: FastifyInstance) => { }) fastify.patch<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } Body: any }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.publications.update(id, request.body as any) await pgMeta.end() if (error) { @@ -90,15 +90,15 @@ export default async (fastify: FastifyInstance) => { }) fastify.delete<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.publications.remove(id) await pgMeta.end() if (error) { diff --git a/src/server/routes/query.ts b/src/server/routes/query.ts index 6fa775c7..21788ce8 100644 --- a/src/server/routes/query.ts +++ b/src/server/routes/query.ts @@ -1,8 +1,11 @@ import { FastifyInstance, FastifyRequest } from 'fastify' import { PostgresMeta } from '../../lib/index.js' import * as Parser from '../../lib/Parser.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' -import { extractRequestForLogging, translateErrorToResponseCode } from '../utils.js' +import { + createConnectionConfig, + extractRequestForLogging, + translateErrorToResponseCode, +} from '../utils.js' const errorOnEmptyQuery = (request: FastifyRequest) => { if (!(request.body as any).query) { @@ -12,15 +15,14 @@ const errorOnEmptyQuery = (request: FastifyRequest) => { export default async (fastify: FastifyInstance) => { fastify.post<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Body: { query: string } }>('/', async (request, reply) => { errorOnEmptyQuery(request) - const connectionString = request.headers.pg - - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.query(request.body.query, false) await pgMeta.end() if (error) { @@ -33,7 +35,7 @@ export default async (fastify: FastifyInstance) => { }) fastify.post<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Body: { query: string } @@ -51,7 +53,7 @@ export default async (fastify: FastifyInstance) => { }) fastify.post<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Body: { query: string } @@ -69,7 +71,7 @@ export default async (fastify: FastifyInstance) => { }) fastify.post<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Body: { ast: object } diff --git a/src/server/routes/roles.ts b/src/server/routes/roles.ts index f9d125db..a8809be2 100644 --- a/src/server/routes/roles.ts +++ b/src/server/routes/roles.ts @@ -1,6 +1,6 @@ import { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' import { PostgresRoleCreate, @@ -24,6 +24,7 @@ export default async (fastify: FastifyInstance) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), querystring: Type.Object({ include_system_schemas: Type.Optional(Type.String()), @@ -39,12 +40,12 @@ export default async (fastify: FastifyInstance) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const includeDefaultRoles = request.query.include_default_roles === 'true' const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.roles.list({ includeDefaultRoles, limit, @@ -72,6 +73,7 @@ export default async (fastify: FastifyInstance) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.RegExp(/\d+/), @@ -85,10 +87,10 @@ export default async (fastify: FastifyInstance) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.roles.retrieve({ id }) await pgMeta.end() if (error) { @@ -110,6 +112,7 @@ export default async (fastify: FastifyInstance) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), body: postgresRoleCreateSchema, response: { @@ -121,9 +124,9 @@ export default async (fastify: FastifyInstance) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.roles.create(request.body) await pgMeta.end() if (error) { @@ -148,6 +151,7 @@ export default async (fastify: FastifyInstance) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.RegExp(/\d+/), @@ -165,10 +169,10 @@ export default async (fastify: FastifyInstance) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.roles.update(id, request.body) await pgMeta.end() if (error) { @@ -193,6 +197,7 @@ export default async (fastify: FastifyInstance) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.RegExp(/\d+/), @@ -212,10 +217,10 @@ export default async (fastify: FastifyInstance) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.roles.remove(id) await pgMeta.end() if (error) { diff --git a/src/server/routes/schemas.ts b/src/server/routes/schemas.ts index 16cd70e5..a65d104a 100644 --- a/src/server/routes/schemas.ts +++ b/src/server/routes/schemas.ts @@ -6,7 +6,7 @@ import { postgresSchemaCreateSchema, postgresSchemaUpdateSchema, } from '../../lib/types.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' const route: FastifyPluginAsyncTypebox = async (fastify) => { @@ -16,6 +16,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), querystring: Type.Object({ include_system_schemas: Type.Optional(Type.Boolean()), @@ -31,12 +32,12 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const includeSystemSchemas = request.query.include_system_schemas const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.schemas.list({ includeSystemSchemas, limit, offset }) await pgMeta.end() if (error) { @@ -55,6 +56,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.Integer(), @@ -68,10 +70,10 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = request.params.id - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.schemas.retrieve({ id }) await pgMeta.end() if (error) { @@ -90,6 +92,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), body: postgresSchemaCreateSchema, response: { @@ -101,9 +104,9 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.schemas.create(request.body) await pgMeta.end() if (error) { @@ -122,6 +125,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.Integer(), @@ -139,10 +143,10 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = request.params.id - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.schemas.update(id, request.body) await pgMeta.end() if (error) { @@ -162,6 +166,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.Integer(), @@ -181,11 +186,11 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = request.params.id const cascade = request.query.cascade - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.schemas.remove(id, { cascade }) await pgMeta.end() if (error) { diff --git a/src/server/routes/table-privileges.ts b/src/server/routes/table-privileges.ts index 31d7b2b7..615d6efa 100644 --- a/src/server/routes/table-privileges.ts +++ b/src/server/routes/table-privileges.ts @@ -6,7 +6,7 @@ import { postgresTablePrivilegesRevokeSchema, postgresTablePrivilegesSchema, } from '../../lib/types.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging, translateErrorToResponseCode } from '../utils.js' const route: FastifyPluginAsyncTypebox = async (fastify) => { @@ -16,6 +16,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), querystring: Type.Object({ include_system_schemas: Type.Optional(Type.Boolean()), @@ -34,14 +35,14 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const includeSystemSchemas = request.query.include_system_schemas const includedSchemas = request.query.included_schemas?.split(',') const excludedSchemas = request.query.excluded_schemas?.split(',') const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.tablePrivileges.list({ includeSystemSchemas, includedSchemas, @@ -66,6 +67,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), body: Type.Array(postgresTablePrivilegesGrantSchema), response: { @@ -77,9 +79,9 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.tablePrivileges.grant(request.body) await pgMeta.end() if (error) { @@ -98,6 +100,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), body: Type.Array(postgresTablePrivilegesRevokeSchema), response: { @@ -112,9 +115,9 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.tablePrivileges.revoke(request.body) await pgMeta.end() if (error) { diff --git a/src/server/routes/tables.ts b/src/server/routes/tables.ts index 2efd3d05..ff5cb2c9 100644 --- a/src/server/routes/tables.ts +++ b/src/server/routes/tables.ts @@ -6,8 +6,11 @@ import { postgresTableSchema, postgresTableUpdateSchema, } from '../../lib/types.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' -import { extractRequestForLogging, translateErrorToResponseCode } from '../utils.js' +import { + createConnectionConfig, + extractRequestForLogging, + translateErrorToResponseCode, +} from '../utils.js' const route: FastifyPluginAsyncTypebox = async (fastify) => { fastify.get( @@ -16,6 +19,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), querystring: Type.Object({ include_system_schemas: Type.Optional(Type.Boolean()), @@ -35,7 +39,6 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg const includeSystemSchemas = request.query.include_system_schemas const includedSchemas = request.query.included_schemas?.split(',') const excludedSchemas = request.query.excluded_schemas?.split(',') @@ -43,7 +46,8 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { const offset = request.query.offset const includeColumns = request.query.include_columns - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.tables.list({ includeSystemSchemas, includedSchemas, @@ -69,6 +73,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.Integer(), @@ -82,10 +87,10 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg const id = request.params.id - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.tables.retrieve({ id }) await pgMeta.end() if (error) { @@ -104,6 +109,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), body: postgresTableCreateSchema, response: { @@ -115,9 +121,8 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg - - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.tables.create(request.body) await pgMeta.end() if (error) { @@ -136,6 +141,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.Integer(), @@ -153,10 +159,10 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg const id = request.params.id - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.tables.update(id, request.body) await pgMeta.end() if (error) { @@ -176,6 +182,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.Integer(), @@ -195,11 +202,11 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg const id = request.params.id const cascade = request.query.cascade - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const config = createConnectionConfig(request) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.tables.remove(id, { cascade }) await pgMeta.end() if (error) { diff --git a/src/server/routes/triggers.ts b/src/server/routes/triggers.ts index 138b6061..3eb2212a 100644 --- a/src/server/routes/triggers.ts +++ b/src/server/routes/triggers.ts @@ -1,11 +1,11 @@ import { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' export default async (fastify: FastifyInstance) => { fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Querystring: { include_system_schemas?: string // Note: this only supports comma separated values (e.g., ".../columns?included_schemas=public,core") @@ -15,14 +15,14 @@ export default async (fastify: FastifyInstance) => { offset?: number } }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const includeSystemSchemas = request.query.include_system_schemas === 'true' const includedSchemas = request.query.included_schemas?.split(',') const excludedSchemas = request.query.excluded_schemas?.split(',') const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.triggers.list({ includeSystemSchemas, includedSchemas, @@ -41,15 +41,15 @@ export default async (fastify: FastifyInstance) => { }) fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.triggers.retrieve({ id }) await pgMeta.end() if (error) { @@ -62,12 +62,12 @@ export default async (fastify: FastifyInstance) => { }) fastify.post<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Body: any }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.triggers.create(request.body as any) await pgMeta.end() if (error) { @@ -80,16 +80,16 @@ export default async (fastify: FastifyInstance) => { }) fastify.patch<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } Body: any }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.triggers.update(id, request.body as any) await pgMeta.end() if (error) { @@ -103,7 +103,7 @@ export default async (fastify: FastifyInstance) => { }) fastify.delete<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Params: { id: string } @@ -111,11 +111,11 @@ export default async (fastify: FastifyInstance) => { cascade?: string } }>('/:id(\\d+)', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = Number(request.params.id) const cascade = request.query.cascade === 'true' - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.triggers.remove(id, { cascade }) await pgMeta.end() if (error) { diff --git a/src/server/routes/types.ts b/src/server/routes/types.ts index 168f39ac..c4e0dfbd 100644 --- a/src/server/routes/types.ts +++ b/src/server/routes/types.ts @@ -1,11 +1,11 @@ import { FastifyInstance } from 'fastify' import { PostgresMeta } from '../../lib/index.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' export default async (fastify: FastifyInstance) => { fastify.get<{ - Headers: { pg: string } + Headers: { pg: string; 'x-pg-application-name'?: string } Querystring: { include_array_types?: string include_system_schemas?: string @@ -16,7 +16,7 @@ export default async (fastify: FastifyInstance) => { offset?: number } }>('/', async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const includeArrayTypes = request.query.include_array_types === 'true' const includeSystemSchemas = request.query.include_system_schemas === 'true' const includedSchemas = request.query.included_schemas?.split(',') @@ -24,7 +24,7 @@ export default async (fastify: FastifyInstance) => { const limit = request.query.limit const offset = request.query.offset - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.types.list({ includeArrayTypes, includeSystemSchemas, diff --git a/src/server/routes/views.ts b/src/server/routes/views.ts index f8794f36..119088e3 100644 --- a/src/server/routes/views.ts +++ b/src/server/routes/views.ts @@ -2,7 +2,7 @@ import { FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox' import { Type } from '@sinclair/typebox' import { PostgresMeta } from '../../lib/index.js' import { postgresViewSchema } from '../../lib/types.js' -import { DEFAULT_POOL_CONFIG } from '../constants.js' +import { createConnectionConfig } from '../utils.js' import { extractRequestForLogging } from '../utils.js' const route: FastifyPluginAsyncTypebox = async (fastify) => { @@ -12,6 +12,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), querystring: Type.Object({ include_system_schemas: Type.Optional(Type.Boolean()), @@ -31,7 +32,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const includeSystemSchemas = request.query.include_system_schemas const includedSchemas = request.query.included_schemas?.split(',') const excludedSchemas = request.query.excluded_schemas?.split(',') @@ -39,7 +40,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { const offset = request.query.offset const includeColumns = request.query.include_columns - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.views.list({ includeSystemSchemas, includedSchemas, @@ -65,6 +66,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { schema: { headers: Type.Object({ pg: Type.String(), + 'x-pg-application-name': Type.Optional(Type.String()), }), params: Type.Object({ id: Type.Integer(), @@ -78,10 +80,10 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => { }, }, async (request, reply) => { - const connectionString = request.headers.pg + const config = createConnectionConfig(request) const id = request.params.id - const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) + const pgMeta = new PostgresMeta(config) const { data, error } = await pgMeta.views.retrieve({ id }) await pgMeta.end() if (error) { diff --git a/src/server/utils.ts b/src/server/utils.ts index cc8de839..ebb8ec90 100644 --- a/src/server/utils.ts +++ b/src/server/utils.ts @@ -1,5 +1,7 @@ import pgcs from 'pg-connection-string' import { FastifyRequest } from 'fastify' +import { DEFAULT_POOL_CONFIG } from './constants.js' +import { PoolConfig } from '../lib/types.js' export const extractRequestForLogging = (request: FastifyRequest) => { let pg: string = 'unknown' @@ -21,6 +23,18 @@ export const extractRequestForLogging = (request: FastifyRequest) => { } } +export function createConnectionConfig(request: FastifyRequest): PoolConfig { + const connectionString = request.headers.pg as string + const config = { ...DEFAULT_POOL_CONFIG, connectionString } + + // Override application_name if custom one provided in header + if (request.headers['x-pg-application-name']) { + config.application_name = request.headers['x-pg-application-name'] as string + } + + return config +} + export function translateErrorToResponseCode( error: { message: string }, defaultResponseCode = 400 diff --git a/test/server/query.ts b/test/server/query.ts index 25c4c262..2b4bc2ba 100644 --- a/test/server/query.ts +++ b/test/server/query.ts @@ -730,3 +730,24 @@ test('error with internalQuery property', async () => { } `) }) + +test('custom application_name', async () => { + const res = await app.inject({ + method: 'POST', + path: '/query', + headers: { + 'x-pg-application-name': 'test', + }, + payload: { + query: 'SHOW application_name;', + }, + }) + + expect(res.json()).toMatchInlineSnapshot(` + [ + { + "application_name": "test", + }, + ] + `) +})