import chalk from 'chalk'; import { extractSchema } from 'extract-pg-schema'; import fs from 'fs'; import path from 'path'; import { identity, indexBy, isEmpty, map } from 'ramda'; import rmfr from 'rmfr'; import Config, { Hook, nameIdentity, SchemaConfig } from './Config'; import defaultTypeMap from './defaultTypeMap'; import { logger } from './logger'; import processSchema from './processSchema'; const labelAsGenerated: Hook<unknown> = (lines) => [ '// @generated', "// Automatically generated. Don't change this file manually.", '', ...lines, ]; const addEmptyLineAtEnd: Hook<unknown> = (lines) => [...lines, '']; const defaultHooks = [labelAsGenerated, addEmptyLineAtEnd]; const processDatabase = async ({ connection, preDeleteModelFolder = false, customTypeMap = {}, modelHooks = [], modelNominator = nameIdentity, propertyNominator = (propertyName) => propertyName.indexOf(' ') !== -1 ? `'${propertyName}'` : propertyName, initializerNominator = (modelName) => `${modelName}Initializer`, idNominator = (modelName) => `${modelName}Id`, makeIdType = (innerType, modelName) => `${innerType} & { " __flavor"?: '${modelName}' };`, typeHooks = [], typeNominator = nameIdentity, fileNominator = identity, resolveViews = false, schemas, ...unknownProps }: Config) => { if (!isEmpty(unknownProps)) { logger.warn( `Unknown configuration properties: ${Object.keys(unknownProps).join( ', ' )}` ); } const typeMap = { ...defaultTypeMap, ...customTypeMap }; /** @type {import('./Config').Nominators} */ const nominators = { modelNominator, propertyNominator, initializerNominator, idNominator, typeNominator, fileNominator, }; const modelProcessChain = [...defaultHooks, ...modelHooks]; const typeProcessChain = [...defaultHooks, ...typeHooks]; if (typeof connection === 'string') { logger.log(`Connecting to ${chalk.greenBright(connection)}`); } else { logger.log( `Connecting to ${chalk.greenBright(connection.database)} on ${ connection.host }` ); } const schemaFolderMap = map( (s: SchemaConfig) => path.resolve(s.modelFolder), indexBy((s) => s.name, schemas) ) as Record<string, string>; for (const schemaConfig of schemas) { const schema = await extractSchema( schemaConfig.name, connection, schemaConfig.resolveViews !== undefined ? schemaConfig.resolveViews : resolveViews ); if (preDeleteModelFolder) { logger.log(` - Clearing old files in ${schemaConfig.modelFolder}`); await rmfr(schemaConfig.modelFolder, { glob: true }); } if (!fs.existsSync(schemaConfig.modelFolder)) { fs.mkdirSync(schemaConfig.modelFolder, { recursive: true }); } await processSchema( schemaConfig, schema, typeMap, nominators, modelProcessChain, typeProcessChain, schemaFolderMap, makeIdType ); } }; export default processDatabase;