@bodheesh/create-bodhi-node-app
Version:
Create a production-ready Node.js REST API with zero configuration
115 lines (97 loc) • 3.43 kB
text/typescript
import { Umzug, SequelizeStorage } from 'umzug';
import { Sequelize } from 'sequelize';
import fs from 'fs';
import path from 'path';
export const generateMigrations = async (schema: any, outputDir: string, dbConfig: any) => {
const migrationDir = path.join(outputDir, 'migrations');
if (!fs.existsSync(migrationDir)) {
fs.mkdirSync(migrationDir, { recursive: true });
}
const timestamp = new Date().toISOString().replace(/[^0-9]/g, '').slice(0, -3);
const migrationPath = path.join(migrationDir, `${timestamp}-create-tables.js`);
const migrationContent = generateMigrationContent(schema);
fs.writeFileSync(migrationPath, migrationContent);
// Generate sequelize configuration
const configPath = path.join(outputDir, 'config');
if (!fs.existsSync(configPath)) {
fs.mkdirSync(configPath, { recursive: true });
}
const dbConfigContent = generateDBConfig(dbConfig);
fs.writeFileSync(path.join(configPath, 'database.js'), dbConfigContent);
};
const generateMigrationContent = (schema: any) => {
let upQueries = [];
let downQueries = [];
for (const [modelName, properties] of Object.entries(schema)) {
const tableName = modelName.toLowerCase() + 's';
const columns = Object.entries(properties).map(([field, rules]: [string, any]) => {
return generateColumnDefinition(field, rules);
}).join(',\n ');
upQueries.push(`
await queryInterface.createTable('${tableName}', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
${columns},
createdAt: {
type: Sequelize.DATE,
allowNull: false
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false
}
});`);
downQueries.push(`await queryInterface.dropTable('${tableName}');`);
}
return `'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
${upQueries.join('\n')}
},
down: async (queryInterface, Sequelize) => {
${downQueries.join('\n')}
}
};`;
};
const generateColumnDefinition = (field: string, rules: any) => {
const type = rules.type === 'string' ? 'STRING' :
rules.type === 'number' ? 'INTEGER' :
rules.type === 'boolean' ? 'BOOLEAN' :
rules.type === 'date' ? 'DATE' : 'STRING';
return `${field}: {
type: Sequelize.${type},
allowNull: ${!rules.required},
${rules.unique ? 'unique: true,' : ''}
${rules.defaultValue ? `defaultValue: ${JSON.stringify(rules.defaultValue)},` : ''}
}`;
};
const generateDBConfig = (config: any) => {
return `module.exports = {
development: {
username: process.env.DB_USERNAME || '${config.username}',
password: process.env.DB_PASSWORD || '${config.password}',
database: process.env.DB_NAME || '${config.database}',
host: process.env.DB_HOST || '${config.host}',
dialect: '${config.dialect}',
logging: false
},
test: {
username: process.env.TEST_DB_USERNAME,
password: process.env.TEST_DB_PASSWORD,
database: process.env.TEST_DB_NAME,
host: process.env.TEST_DB_HOST,
dialect: '${config.dialect}',
logging: false
},
production: {
username: process.env.PROD_DB_USERNAME,
password: process.env.PROD_DB_PASSWORD,
database: process.env.PROD_DB_NAME,
host: process.env.PROD_DB_HOST,
dialect: '${config.dialect}',
logging: false
}
};`;