diff --git a/src/generators/src/infra/database/repositories/repositories.js b/src/generators/src/infra/database/repositories/repositories.js index 9a806a5..d5bde5b 100644 --- a/src/generators/src/infra/database/repositories/repositories.js +++ b/src/generators/src/infra/database/repositories/repositories.js @@ -3,29 +3,55 @@ const camelCase = require('lodash.camelcase') const fs = require('fs') const path = require('path') +const types = {String , Boolean, Number, undefined, Symbol, Object, Null: null} + +function generateForeignKeysField(schema) { + const idFieldsNames = {} + Object.values(schema).map(field => { + if (types[field.type.name]) return + + const { schema, name } = field.type.prototype.meta + + Object.values(schema).map(idFields => { + if(idFields.options.isId) + idFieldsNames[`${camelCase(name)}_${idFields.name}`] = idFields.type.name + }) + }) + return idFieldsNames +} + async function generateRepositories(generate, filesystem, db, command) { const requires = {} - const herbarium = requireHerbarium(command, filesystem.cwd()) const entities = herbarium.entities.all for (const entity of Array.from(entities.values())) { - const { name } = entity.entity.prototype.meta + const { name, schema } = entity.entity.prototype.meta const lowCCName = camelCase(name) const repositoryPath = path.normalize(`${filesystem.cwd()}/src/infra/data/repositories/${lowCCName}Repository.js`) + let foreignKeysFields + const primaryKeyFields = [] + Object.values(schema).filter(idFields => { + if(idFields.options.isId) + primaryKeyFields.push(idFields.name) + }) requires[`${lowCCName}Repository`] = `await new (require('./${lowCCName}Repository.js'))(conn)` if (fs.existsSync(repositoryPath)) continue + if (db !== 'mongo') foreignKeysFields = generateForeignKeysField(schema) + await generate({ template: `infra/data/repository/${db}/repository.ejs`, target: repositoryPath, props: { name: { pascalCase: name, - camelCase: lowCCName + camelCase: lowCCName, }, + primaryKeyFields, + foreignKeysFields, table: `${lowCCName}s` } }) diff --git a/src/templates/infra/data/repository/mysql/repository.ejs b/src/templates/infra/data/repository/mysql/repository.ejs index 370c46f..e8ecb62 100644 --- a/src/templates/infra/data/repository/mysql/repository.ejs +++ b/src/templates/infra/data/repository/mysql/repository.ejs @@ -8,7 +8,9 @@ class <%- props.name.pascalCase %>Repository extends Repository { super({ entity: <%- props.name.pascalCase %>, table: "<%- props.table %>", - knex: connection + ids: [<% for (const [index, value] of Object.entries(props.primaryKeyFields)) { %><%if(index != 0) { %>, <% } %>'<%= value %>'<% } %>], + knex: connection<%if(Object.values(props.foreignKeysFields).length) {%>, + foreignKeys: [{ <% Object.entries(props.foreignKeysFields).forEach(([key, value], index) => {%><%if(index != 0) { %>, <% } %><%= key %>: <%= value %><% }) %> }]<% }%> }) } } diff --git a/src/templates/infra/data/repository/postgres/repository.ejs b/src/templates/infra/data/repository/postgres/repository.ejs index 370c46f..e8ecb62 100644 --- a/src/templates/infra/data/repository/postgres/repository.ejs +++ b/src/templates/infra/data/repository/postgres/repository.ejs @@ -8,7 +8,9 @@ class <%- props.name.pascalCase %>Repository extends Repository { super({ entity: <%- props.name.pascalCase %>, table: "<%- props.table %>", - knex: connection + ids: [<% for (const [index, value] of Object.entries(props.primaryKeyFields)) { %><%if(index != 0) { %>, <% } %>'<%= value %>'<% } %>], + knex: connection<%if(Object.values(props.foreignKeysFields).length) {%>, + foreignKeys: [{ <% Object.entries(props.foreignKeysFields).forEach(([key, value], index) => {%><%if(index != 0) { %>, <% } %><%= key %>: <%= value %><% }) %> }]<% }%> }) } } diff --git a/src/templates/infra/data/repository/sqlserver/repository.ejs b/src/templates/infra/data/repository/sqlserver/repository.ejs index 370c46f..e8ecb62 100644 --- a/src/templates/infra/data/repository/sqlserver/repository.ejs +++ b/src/templates/infra/data/repository/sqlserver/repository.ejs @@ -8,7 +8,9 @@ class <%- props.name.pascalCase %>Repository extends Repository { super({ entity: <%- props.name.pascalCase %>, table: "<%- props.table %>", - knex: connection + ids: [<% for (const [index, value] of Object.entries(props.primaryKeyFields)) { %><%if(index != 0) { %>, <% } %>'<%= value %>'<% } %>], + knex: connection<%if(Object.values(props.foreignKeysFields).length) {%>, + foreignKeys: [{ <% Object.entries(props.foreignKeysFields).forEach(([key, value], index) => {%><%if(index != 0) { %>, <% } %><%= key %>: <%= value %><% }) %> }]<% }%> }) } } diff --git a/src/tests/repositories.test.js b/src/tests/repositories.test.js new file mode 100644 index 0000000..74836b4 --- /dev/null +++ b/src/tests/repositories.test.js @@ -0,0 +1,49 @@ +/* globals describe, it, afterEach */ + +const { system } = require('gluegun') +const { expect } = require('chai') +const fs = require('fs') +const path = require('path') + +const projectName = 'herbs-test-runner' + +const generateProject = () => system.run(`herbs new --name ${projectName} --description "testing the herbs CLI" --author herbs --license MIT --graphql --rest no --database postgres --npmInstall yes`) +const callHerbsCli = () => system.run(`herbs`) + +const herbsUpdate = () => system.run(`cd ${projectName} && herbs update`) + +describe('When I generate a complete project that uses postgres', () => { + afterEach(async () => { + fs.rmSync(path.resolve(process.cwd(), `${projectName}`), { recursive: true }) + }) + + it('Should I create a new repository with foreign key', async () => { + await generateProject() + await callHerbsCli() + const customerEntity = + ` + const { entity, id, field } = require('@herbsjs/herbs') + const { herbarium } = require('@herbsjs/herbarium') + const User = require('./user') + + const Customer = + entity('Customer', { + id: id(String), + description: field(String), + user: field(User) + }) + + module.exports = + herbarium.entities + .add(Customer, 'Customer') + .entity + ` + + const dir = `${path.resolve(process.cwd(), `${projectName}/src/domain/entities/customer.js`)}` + fs.writeFileSync(dir, customerEntity) + expect(fs.existsSync(dir)).to.be.true + await herbsUpdate() + expect(fs.existsSync(path.resolve(process.cwd(), `${projectName}/src/infra/data/repositories/customerRepository.js`))).to.be.true + }) +}) + diff --git a/src/tests/shell.test.js b/src/tests/shell.test.js index 7beb296..040fed4 100644 --- a/src/tests/shell.test.js +++ b/src/tests/shell.test.js @@ -6,7 +6,6 @@ const path = require('path') const fs = require('fs') const { expect } = require('chai') const projectName = 'herbs-test-runner' -const { exec } = require('node:child_process') const linknpm = () => system.run(`cd bin && npm link --force`) const generateProject = () => system.run(`herbs new --name ${projectName} --description "testing the herbs CLI" --author herbs --license MIT --graphql --rest --database mongo --npmInstall yes`)