@amberjs/cli
Version:
Amber.js command line interface
324 lines (257 loc) • 11.1 kB
JavaScript
/* eslint-disable prefer-destructuring */
const transform = require('graphql-to-json-schema');
const fs = require('fs');
const inflection = require('inflection');
const exec = require('child_process').execSync;
const Sequelize = require('sequelize');
const {
getModelData, convertToStringModel, generateSchema, generateResolvers, deleteFolderRecursive,
} = require('./utils');
const { firstToUpper } = require('../../utils/string-manipulation');
const createRepository = require('./templates/repositoryTemplate');
const CreateService = require('./templates/serviceTemplate');
const createDomain = require('./templates/domainTemplate');
const createModels = (modelData) => {
// convert modelData to model strings
const models = convertToStringModel(modelData);
const path = `${process.env.PWD}/src/infra/database/models`; // '/Users/JoshMante/Projects/brewery/graphql-resolver/src/infra/database/models';
// write updated models
Object.keys(models).forEach((key) => {
const modelString = models[key];
const fileName = `${inflection.pluralize(key).toLowerCase()}.js`;
fs.writeFileSync(`${path}/${fileName}`, modelString);
console.log(`Model ${fileName} created!`);
});
};
const createDomains = () => {
const config = require(`${process.cwd()}/config/index.js`);
const sequelize = new Sequelize(config.db);
const path = `${process.env.PWD}/src/domain`;
fs
.readdirSync(`${process.env.PWD}/src/infra/database/models`)
.filter((file) => (file.indexOf('.') !== 0) && (file !== 'index.js') && (file.slice(-3) === '.js'))
.forEach((file) => {
const model = sequelize.import(`${process.env.PWD}/src/infra/database/models/${file}`);
const domain = createDomain(model);
const fileName = `${inflection.singularize(firstToUpper(file.split('.')[0]))}.js`;
fs.writeFileSync(`${path}/${fileName}`, domain);
console.log(`Domain ${fileName} created!`);
});
};
const createRepositories = () => {
const models = [];
const path = `${process.env.PWD}/src/infra/repositories`;
fs
.readdirSync(`${process.env.PWD}/src/infra/database/models`)
.filter((file) => (file.indexOf('.') !== 0) && (file !== 'index.js') && (file.slice(-3) === '.js'))
.forEach((file) => {
models.push({
plural: file.split('.')[0],
singular: inflection.singularize(file.split('.')[0]),
});
});
models.forEach((model) => {
const repository = createRepository(model);
const fileName = `${firstToUpper(model.singular)}Repository.js`;
fs.writeFileSync(`${path}/${fileName}`, repository);
console.log(`Repository ${fileName} created!`);
});
};
const createSchemas = (modelData) => {
// convert modelData to string gql schema
const schemas = generateSchema(modelData);
const path = `${process.env.PWD}/src/interfaces/graphql/typeDefs`;
Object.keys(schemas).forEach((key) => {
const schemaString = schemas[key];
const fileName = `${inflection.singularize(key).toLowerCase()}.js`;
fs.writeFileSync(`${path}/${fileName}`, schemaString);
console.log(`Schema ${fileName} created!`);
});
};
const createServices = (modelData) => {
const indexFile = {};
// create service directory and operations
Object.keys(modelData).forEach((modelName) => {
if (modelData[modelName].type === 'model') {
const service = inflection.singularize(modelName).toLowerCase();
const path = `${process.env.PWD}/src/app/${service}`;
if (!fs.existsSync(path)) {
fs.mkdirSync(path);
fs.chmodSync(path, '0775');
}
const operationTemplate = new CreateService(service);
const templateList = operationTemplate.list();
const templateCreate = operationTemplate.create();
const templateShow = operationTemplate.show();
const templateUpdate = operationTemplate.update();
const templateDelete = operationTemplate.delete();
fs.writeFileSync(`${path}/List${firstToUpper(service)}.js`, templateList);
fs.writeFileSync(`${path}/Create${firstToUpper(service)}.js`, templateCreate);
fs.writeFileSync(`${path}/Show${firstToUpper(service)}.js`, templateShow);
fs.writeFileSync(`${path}/Update${firstToUpper(service)}.js`, templateUpdate);
fs.writeFileSync(`${path}/Delete${firstToUpper(service)}.js`, templateDelete);
console.log(`Service ${service} created!`);
indexFile[service] = 'module.exports = {\n';
indexFile[service] += ` list${firstToUpper(inflection.pluralize(service))} : require('./List${firstToUpper(service)}'),\n`;
indexFile[service] += ` create${firstToUpper(service)} : require('./Create${firstToUpper(service)}'),\n`;
indexFile[service] += ` show${firstToUpper(service)} : require('./Show${firstToUpper(service)}'),\n`;
indexFile[service] += ` update${firstToUpper(service)} : require('./Update${firstToUpper(service)}'),\n`;
indexFile[service] += ` delete${firstToUpper(service)} : require('./Delete${firstToUpper(service)}'),\n`;
}
});
// create index files , register operations to container
let containerFile = fs.readFileSync(`${process.env.PWD}/src/container.js`, 'utf8');
Object.keys(indexFile).forEach((service) => {
// create index file
indexFile[service] += '};';
const lowerSingular = inflection.singularize(service).toLowerCase();
fs.writeFileSync(`${process.env.PWD}/src/app/${lowerSingular}/index.js`, indexFile[service]);
// register operation on container
const requireOperation = `const ${lowerSingular}Operations = require('./app/${lowerSingular}');`;
const registerOperation = `container.registerClass(${lowerSingular}Operations);`;
if (containerFile.includes(requireOperation) === false) {
containerFile = `${requireOperation}\n${containerFile}`;
}
if (containerFile.includes(registerOperation) === false) {
containerFile = `${containerFile + registerOperation}\n`;
}
});
fs.writeFileSync(`${process.env.PWD}/src/container.js`, containerFile);
};
const createResolvers = (modelData) => {
const resolvers = generateResolvers(modelData);
const path = `${process.env.PWD}/src/interfaces/graphql/resolvers`;
if (!fs.existsSync(path)) {
fs.mkdirSync(path);
fs.chmodSync(path, '0775');
}
Object.keys(resolvers).forEach((key) => {
const resolverString = resolvers[key];
const fileName = `${inflection.singularize(key).toLowerCase()}.js`;
fs.writeFileSync(`${path}/${fileName}`, resolverString);
console.log(`Resolver ${fileName} created!`);
});
};
const deleteFiles = () => {
/* DELETE MODELS */
const modelsPath = `${process.env.PWD}/src/infra/database/models`;
if (!fs.existsSync(modelsPath)) {
fs.mkdirSync(modelsPath);
fs.chmodSync(modelsPath, '0775');
}
fs
.readdirSync(modelsPath)
.filter((file) => (file.indexOf('.') !== 0) && (file !== 'index.js') && (file.slice(-3) === '.js'))
.forEach((file) => {
fs.unlinkSync(`${modelsPath}/${file}`, (err) => {
if (err) throw err;
});
});
/* DELETE DOMAINS */
const domainsPath = `${process.env.PWD}/src/domain`;
if (!fs.existsSync(domainsPath)) {
fs.mkdirSync(domainsPath);
fs.chmodSync(domainsPath, '0775');
}
fs
.readdirSync(domainsPath)
.filter((file) => (file.indexOf('.') !== 0) && (file !== 'index.js') && (file.slice(-3) === '.js'))
.forEach((file) => {
fs.unlinkSync(`${domainsPath}/${file}`, (err) => {
if (err) throw err;
});
});
/* DELETE REPOSITORIES */
const repositoriesPath = `${process.env.PWD}/src/infra/repositories`;
if (!fs.existsSync(repositoriesPath)) {
fs.mkdirSync(repositoriesPath);
fs.chmodSync(repositoriesPath, '0775');
}
fs
.readdirSync(repositoriesPath)
.filter((file) => (file.indexOf('.') !== 0) && (file !== 'index.js') && (file !== 'BaseRepository.js') && (file.slice(-3) === '.js'))
.forEach((file) => {
fs.unlinkSync(`${repositoriesPath}/${file}`, (err) => {
if (err) throw err;
});
});
/* DELETE SCHEMAS */
const schemaPath = `${process.env.PWD}/src/interfaces/graphql/typeDefs`;
if (!fs.existsSync(schemaPath)) {
fs.mkdirSync(schemaPath);
fs.chmodSync(schemaPath, '0775');
}
fs
.readdirSync(schemaPath)
.filter((file) => (file.indexOf('.') !== 0) && (file !== 'FilterTypes.js') && (file.slice(-3) === '.js'))
.forEach((file) => {
fs.unlinkSync(`${schemaPath}/${file}`, (err) => {
if (err) throw err;
});
});
/* DELETE SERVICES */
const servicesPath = `${process.env.PWD}/src/app`;
fs
.readdirSync(servicesPath)
.filter((file) => (file.indexOf('.') !== 0) && (file !== 'Application.js') && (file !== 'Operation.js'))
.forEach((file) => {
deleteFolderRecursive(`${servicesPath}/${file}`);
});
let containerFile = fs.readFileSync(`${process.env.PWD}/src/container.js`, 'utf8');
containerFile = containerFile.split('/* Require Operations END */')[1];
containerFile = `/* Require Operations END */${containerFile}`;
containerFile = containerFile.split('/* Operations BEGIN */')[0];
containerFile += '/* Operations BEGIN */\n';
fs.writeFileSync(`${process.env.PWD}/src/container.js`, containerFile);
/* DELETE RESOLVERS */
const resolversPath = `${process.env.PWD}/src/interfaces/graphql/resolvers`;
if (!fs.existsSync(resolversPath)) {
fs.mkdirSync(resolversPath);
fs.chmodSync(resolversPath, '0775');
}
fs
.readdirSync(resolversPath)
.forEach((file) => {
fs.unlinkSync(`${resolversPath}/${file}`, (err) => {
if (err) throw err;
});
});
};
const graphql = () => {
// Get resolver SDL Data
const schemaPath = `${process.env.PWD}/src/interfaces/graphql/resolver.graphql`;
if (!fs.existsSync(schemaPath)) {
throw new Error('resolver SDL doesnt exist');
}
// convert SDL into json schema
const schemaJson = transform(fs.readFileSync(schemaPath, 'utf8'));
// convert json schema into simplified json for sequelize
console.log('Parsing SDL...');
const modelData = getModelData(schemaJson.definitions);
// clean up old generated files
deleteFiles();
// create sequelize models
console.log('Creating Models...');
createModels(modelData);
// create domains
console.log('Creating Domains...');
createDomains();
// create migration out of model and run migration
console.log('Creating migrations...');
console.log('Running Migrations...');
exec('NODE_PATH=. node ./node_modules/sequelize-auto-migrations/bin/makemigration.js -x');
// exec('NODE_PATH=. node ./node_modules/sequelize-auto-migrations/bin/runmigration.js');
// generate repositories
console.log('Creating repositories...');
createRepositories();
// generate schema
console.log('Creating graphQL schema...');
createSchemas(modelData);
// generate service operations
console.log('Creating Services...');
createServices(modelData);
// generate resolvers
console.log('Creating resolvers...');
createResolvers(modelData);
};
module.exports = graphql;