diff --git a/src/lib/generators.ts b/src/lib/generators.ts new file mode 100644 index 00000000..7a053b6f --- /dev/null +++ b/src/lib/generators.ts @@ -0,0 +1,118 @@ +import PostgresMeta from './PostgresMeta.js' +import { + PostgresColumn, + PostgresFunction, + PostgresMaterializedView, + PostgresRelationship, + PostgresSchema, + PostgresTable, + PostgresType, + PostgresView, +} from './types.js' +import { PostgresMetaResult } from './types.js' + +export type GeneratorMetadata = { + schemas: PostgresSchema[] + tables: Omit[] + views: Omit[] + materializedViews: Omit[] + columns: PostgresColumn[] + relationships: PostgresRelationship[] + functions: PostgresFunction[] + types: PostgresType[] +} + +export async function getGeneratorMetadata( + pgMeta: PostgresMeta, + filters: { includedSchemas?: string[]; excludedSchemas?: string[] } = { + includedSchemas: [], + excludedSchemas: [], + } +): Promise> { + const includedSchemas = filters.includedSchemas ?? [] + const excludedSchemas = filters.excludedSchemas ?? [] + + const { data: schemas, error: schemasError } = await pgMeta.schemas.list() + if (schemasError) { + return { data: null, error: schemasError } + } + + const { data: tables, error: tablesError } = await pgMeta.tables.list({ + includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined, + excludedSchemas, + includeColumns: false, + }) + if (tablesError) { + return { data: null, error: tablesError } + } + + const { data: views, error: viewsError } = await pgMeta.views.list({ + includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined, + excludedSchemas, + includeColumns: false, + }) + if (viewsError) { + return { data: null, error: viewsError } + } + + const { data: materializedViews, error: materializedViewsError } = + await pgMeta.materializedViews.list({ + includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined, + excludedSchemas, + includeColumns: false, + }) + if (materializedViewsError) { + return { data: null, error: materializedViewsError } + } + + const { data: columns, error: columnsError } = await pgMeta.columns.list({ + includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined, + excludedSchemas, + }) + if (columnsError) { + return { data: null, error: columnsError } + } + + const { data: relationships, error: relationshipsError } = await pgMeta.relationships.list() + if (relationshipsError) { + return { data: null, error: relationshipsError } + } + + const { data: functions, error: functionsError } = await pgMeta.functions.list({ + includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined, + excludedSchemas, + }) + if (functionsError) { + return { data: null, error: functionsError } + } + + const { data: types, error: typesError } = await pgMeta.types.list({ + includeArrayTypes: true, + includeSystemSchemas: true, + }) + if (typesError) { + return { data: null, error: typesError } + } + + await pgMeta.end() + + return { + data: { + schemas: schemas.filter( + ({ name }) => + !excludedSchemas.includes(name) && + (includedSchemas.length === 0 || includedSchemas.includes(name)) + ), + tables, + views, + materializedViews, + columns, + relationships, + functions: functions.filter( + ({ return_type }) => !['trigger', 'event_trigger'].includes(return_type) + ), + types, + }, + error: null, + } +} diff --git a/src/server/routes/generators/typescript.ts b/src/server/routes/generators/typescript.ts index 0e2f6b33..b7a75248 100644 --- a/src/server/routes/generators/typescript.ts +++ b/src/server/routes/generators/typescript.ts @@ -3,6 +3,7 @@ import { PostgresMeta } from '../../../lib/index.js' import { DEFAULT_POOL_CONFIG } from '../../constants.js' import { 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<{ @@ -21,97 +22,18 @@ export default async (fastify: FastifyInstance) => { const detectOneToOneRelationships = request.query.detect_one_to_one_relationships === 'true' const pgMeta: PostgresMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) - const { data: schemas, error: schemasError } = await pgMeta.schemas.list() - const { data: tables, error: tablesError } = await pgMeta.tables.list({ - includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined, + const { data: generatorMeta, error: generatorMetaError } = await getGeneratorMetadata(pgMeta, { + includedSchemas, excludedSchemas, - includeColumns: false, }) - const { data: views, error: viewsError } = await pgMeta.views.list({ - includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined, - excludedSchemas, - includeColumns: false, - }) - const { data: materializedViews, error: materializedViewsError } = - await pgMeta.materializedViews.list({ - includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined, - excludedSchemas, - includeColumns: false, - }) - const { data: columns, error: columnsError } = await pgMeta.columns.list({ - includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined, - excludedSchemas, - }) - const { data: relationships, error: relationshipsError } = await pgMeta.relationships.list() - const { data: functions, error: functionsError } = await pgMeta.functions.list({ - includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined, - excludedSchemas, - }) - const { data: types, error: typesError } = await pgMeta.types.list({ - includeArrayTypes: true, - includeSystemSchemas: true, - }) - await pgMeta.end() - - if (schemasError) { - request.log.error({ error: schemasError, request: extractRequestForLogging(request) }) - reply.code(500) - return { error: schemasError.message } - } - if (tablesError) { - request.log.error({ error: tablesError, request: extractRequestForLogging(request) }) - reply.code(500) - return { error: tablesError.message } - } - if (viewsError) { - request.log.error({ error: viewsError, request: extractRequestForLogging(request) }) - reply.code(500) - return { error: viewsError.message } - } - if (materializedViewsError) { - request.log.error({ - error: materializedViewsError, - request: extractRequestForLogging(request), - }) - reply.code(500) - return { error: materializedViewsError.message } - } - if (columnsError) { - request.log.error({ error: columnsError, request: extractRequestForLogging(request) }) - reply.code(500) - return { error: columnsError.message } - } - if (relationshipsError) { - request.log.error({ error: relationshipsError, request: extractRequestForLogging(request) }) - reply.code(500) - return { error: relationshipsError.message } - } - if (functionsError) { - request.log.error({ error: functionsError, request: extractRequestForLogging(request) }) - reply.code(500) - return { error: functionsError.message } - } - if (typesError) { - request.log.error({ error: typesError, request: extractRequestForLogging(request) }) + if (generatorMetaError) { + request.log.error({ error: generatorMetaError, request: extractRequestForLogging(request) }) reply.code(500) - return { error: typesError.message } + return { error: generatorMetaError.message } } return applyTypescriptTemplate({ - schemas: schemas.filter( - ({ name }) => - !excludedSchemas.includes(name) && - (includedSchemas.length === 0 || includedSchemas.includes(name)) - ), - tables, - views, - materializedViews, - columns, - relationships, - functions: functions.filter( - ({ return_type }) => !['trigger', 'event_trigger'].includes(return_type) - ), - types, + ...generatorMeta, detectOneToOneRelationships, }) }) diff --git a/src/server/templates/typescript.ts b/src/server/templates/typescript.ts index 56b118ed..c77fe43c 100644 --- a/src/server/templates/typescript.ts +++ b/src/server/templates/typescript.ts @@ -2,13 +2,10 @@ import prettier from 'prettier' import type { PostgresColumn, PostgresFunction, - PostgresMaterializedView, - PostgresRelationship, PostgresSchema, - PostgresTable, PostgresType, - PostgresView, } from '../../lib/index.js' +import type { GeneratorMetadata } from '../../lib/generators.js' export const apply = async ({ schemas, @@ -20,15 +17,7 @@ export const apply = async ({ functions, types, detectOneToOneRelationships, -}: { - schemas: PostgresSchema[] - tables: Omit[] - views: Omit[] - materializedViews: Omit[] - columns: PostgresColumn[] - relationships: PostgresRelationship[] - functions: PostgresFunction[] - types: PostgresType[] +}: GeneratorMetadata & { detectOneToOneRelationships: boolean }): Promise => { const columnsByTableId = Object.fromEntries(