From 4beb77c2dc8e7d50383cf63558e8f5003d6fe872 Mon Sep 17 00:00:00 2001 From: Victor Korzunin Date: Mon, 13 Sep 2021 23:05:08 +0200 Subject: [PATCH] refactor(transform): split code according to best practice --- .eslintrc.yml | 1 - package.json | 4 +- plop/models/Model.ts.hbs | 6 +- plop/plopfile.js | 2 +- prisma/schema.prisma | 2 +- prisma/sequelize/config.json | 2 +- src/{generator.ts => cli.ts} | 0 src/{mappers.ts => generator/properties.ts} | 0 src/generator/transformDMMF.ts | 62 +++++++++++++++++++++ src/index.ts | 59 ++------------------ tsconfig.json | 3 +- 11 files changed, 76 insertions(+), 65 deletions(-) rename src/{generator.ts => cli.ts} (100%) rename src/{mappers.ts => generator/properties.ts} (100%) create mode 100644 src/generator/transformDMMF.ts diff --git a/.eslintrc.yml b/.eslintrc.yml index 067787f..f8451e9 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -13,7 +13,6 @@ plugins: parserOptions: ecmaVersion: 9 sourceType: module - project: ./tsconfig.json extends: - eslint:recommended - plugin:@typescript-eslint/eslint-recommended diff --git a/package.json b/package.json index 47bc8ba..ba1eea5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "prisma-sequelize-generator", "version": "1.0.0-beta.3", - "main": "dist/generator.js", + "main": "dist/cli.js", "license": "MIT", "files": [ "dist", @@ -74,7 +74,7 @@ "prepare": "husky install" }, "bin": { - "prisma-sequelize-generator": "dist/generator.js" + "prisma-sequelize-generator": "dist/cli.js" }, "publishConfig": { "access": "public" diff --git a/plop/models/Model.ts.hbs b/plop/models/Model.ts.hbs index 248b22d..13a74b1 100644 --- a/plop/models/Model.ts.hbs +++ b/plop/models/Model.ts.hbs @@ -1,6 +1,6 @@ import { Sequelize, Model, DataTypes, ModelCtor } from 'sequelize'; -export class {{model.name}} extends Model { +export class {{name}} extends Model { static initialize(sequelize: Sequelize) { this.init( { @@ -17,8 +17,8 @@ export class {{model.name}} extends Model { }, { sequelize, - modelName: '{{model.name}}', - tableName: '{{#if model.dbName}}{{model.dbName}}{{else}}{{model.name}}{{/if}}', + modelName: '{{name}}', + tableName: '{{#if dbName}}{{dbName}}{{else}}{{name}}{{/if}}', timestamps: {{or (or hasCreatedAt hasUpdatedAt) hasDeletedAt}},{{#if (or (or hasCreatedAt hasUpdatedAt) hasDeletedAt)}}{{#if (eq hasCreatedAt false)}} createdAt: false,{{/if}}{{#if (eq hasUpdatedAt false)}} updatedAt: false,{{/if}}{{!-- {{#if (eq hasDeletedAt false)}} diff --git a/plop/plopfile.js b/plop/plopfile.js index 393b6d7..96171dd 100644 --- a/plop/plopfile.js +++ b/plop/plopfile.js @@ -53,7 +53,7 @@ module.exports = function (plop) { actions: () => [ { type: 'add', - path: 'models/{{model.name}}.ts', + path: 'models/{{name}}.ts', templateFile: path.join(__dirname, './models/Model.ts.hbs'), }, ], diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6b01e8c..78a3679 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,5 +1,5 @@ generator models { - provider = "node ./dist/generator.js" + provider = "node ./dist/cli.js" } datasource db { diff --git a/prisma/sequelize/config.json b/prisma/sequelize/config.json index e562033..d88f2fb 100644 --- a/prisma/sequelize/config.json +++ b/prisma/sequelize/config.json @@ -3,7 +3,7 @@ "name": "models", "provider": { "fromEnvVar": null, - "value": "node ./dist/generator.js" + "value": "node ./dist/cli.js" }, "output": { "value": "/Users/victor/Projects/_own/prisma-sequelize-generator/prisma/sequelize", diff --git a/src/generator.ts b/src/cli.ts similarity index 100% rename from src/generator.ts rename to src/cli.ts diff --git a/src/mappers.ts b/src/generator/properties.ts similarity index 100% rename from src/mappers.ts rename to src/generator/properties.ts diff --git a/src/generator/transformDMMF.ts b/src/generator/transformDMMF.ts new file mode 100644 index 0000000..beb9a9f --- /dev/null +++ b/src/generator/transformDMMF.ts @@ -0,0 +1,62 @@ +import { indexBy, prop } from 'ramda'; + +import { PrismaTypeToSequelizeType } from './properties'; + +import type { DMMF } from '@prisma/generator-helper'; + +export function transformDMMF(dmmf: DMMF.Document) { + const enumIndex = indexBy(prop('name'), dmmf.datamodel.enums ?? []); + + return { + models: dmmf.datamodel.models.map((model) => { + const attributes = model.fields.map((field) => field.name); + + return { + ...model, + scalarFields: model.fields + .filter((field) => ['scalar', 'enum'].includes(field.kind)) + .filter((field) => !['createdAt', 'updatedAt', 'deletedAt'].includes(field.name)) + .map((field) => ({ + ...field, + name: field.name, + type: + field.kind === 'scalar' + ? PrismaTypeToSequelizeType[field.type] + : `ENUM(${enumIndex[field.type].values + .map(prop('name')) + .map((n) => `'${n}'`) + .join(', ')})`, + allowNull: !field.isRequired, + isAutoincrement: + field.hasDefaultValue && typeof field.default === 'object' && field.default.name === 'autoincrement', + })), + belongsToFields: model.fields + .filter((field) => field.kind === 'object') + .filter((field) => !field.isList && field.relationToFields?.length) + .map((field) => ({ + as: field.name, + name: field.type, + targetKey: field.relationToFields![0], + foreignKey: field.relationFromFields[0], + })), + hasOneFields: model.fields + .filter((field) => field.kind === 'object') + .filter((field) => !field.isList && !field.relationToFields?.length) + .map((field) => ({ + as: field.name, + name: field.type, + })), + hasManyFields: model.fields + .filter((field) => field.kind === 'object') + .filter((field) => field.isList) + .map((field) => ({ + as: field.name, + name: field.type, + })), + hasCreatedAt: attributes.includes('createdAt'), + hasUpdatedAt: attributes.includes('updatedAt'), + hasDeletedAt: attributes.includes('deletedAt'), + }; + }), + }; +} diff --git a/src/index.ts b/src/index.ts index 4b0d900..70343b0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,9 @@ -import { indexBy, prop } from 'ramda'; import { generatorHandler } from '@prisma/generator-helper'; -import { parseEnvValue, getEnvPaths } from '@prisma/sdk'; +import { getEnvPaths, parseEnvValue } from '@prisma/sdk'; import nodePlop from 'node-plop'; import * as path from 'path'; -import { PrismaTypeToSequelizeType } from './mappers'; +import { transformDMMF } from './generator/transformDMMF'; // eslint-disable-next-line @typescript-eslint/no-var-requires // const pkg = require('../package.json'); @@ -52,63 +51,15 @@ generatorHandler({ // const relativeOutputDir = path.relative(process.cwd(), outputDir); // const slsRelativeOutputDir = path.relative(process.cwd(), outputDir).split(path.sep).slice(1).join(path.sep); - const enumIndex = indexBy(prop('name'), options.dmmf.datamodel.enums ?? []); + const { models } = transformDMMF(options.dmmf); await Promise.all([ utilsGenerator.runActions({}), indexGenerator.runActions({ - models: options.dmmf.datamodel.models, + models, config: JSON.stringify(config, null, 2), }), - ...options.dmmf.datamodel.models.map((model) => { - const attributes = model.fields.map((field) => field.name); - return modelGenerator.runActions({ - model, - scalarFields: model.fields - .filter((field) => ['scalar', 'enum'].includes(field.kind)) - .filter((field) => !['createdAt', 'updatedAt', 'deletedAt'].includes(field.name)) - .map((field) => ({ - ...field, - name: field.name, - type: - field.kind === 'scalar' - ? PrismaTypeToSequelizeType[field.type] - : `ENUM(${enumIndex[field.type].values - .map(prop('name')) - .map((n) => `'${n}'`) - .join(', ')})`, - allowNull: !field.isRequired, - isAutoincrement: - field.hasDefaultValue && typeof field.default === 'object' && field.default.name === 'autoincrement', - })), - belongsToFields: model.fields - .filter((field) => field.kind === 'object') - .filter((field) => !field.isList && field.relationToFields?.length) - .map((field) => ({ - as: field.name, - name: field.type, - targetKey: field.relationToFields![0], - foreignKey: field.relationFromFields[0], - })), - hasOneFields: model.fields - .filter((field) => field.kind === 'object') - .filter((field) => !field.isList && !field.relationToFields?.length) - .map((field) => ({ - as: field.name, - name: field.type, - })), - hasManyFields: model.fields - .filter((field) => field.kind === 'object') - .filter((field) => field.isList) - .map((field) => ({ - as: field.name, - name: field.type, - })), - hasCreatedAt: attributes.includes('createdAt'), - hasUpdatedAt: attributes.includes('updatedAt'), - hasDeletedAt: attributes.includes('deletedAt'), - }); - }), + ...models.map((model) => modelGenerator.runActions(model)), ]); } catch (e) { console.error('Error: unable to write files for Prisma Sequelize Generator'); diff --git a/tsconfig.json b/tsconfig.json index 2634f9a..86f542c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,8 +14,7 @@ "strictFunctionTypes": true }, "include": [ - "src/**/*.ts", - "tests/**/*.ts" + "src/**/*.ts" ], "exclude": [ "node_modules"