Skip to content

Commit

Permalink
feat: support js code models generation
Browse files Browse the repository at this point in the history
  • Loading branch information
Victor Korzunin committed Sep 15, 2021
1 parent 059ce9c commit bb915d0
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 18 deletions.
42 changes: 42 additions & 0 deletions plop/js/index.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const { Sequelize } = require('sequelize');
const { tryLoadEnvs } = require('@prisma/sdk');
const { mergeDeepRight } = require('ramda');
const path = require('path');

const config = require('./config.json');
const models = require('./models');

const loadedEnv = tryLoadEnvs({
rootEnvPath: config.relativeEnvPaths.rootEnvPath && path.resolve(__dirname, config.relativeEnvPaths.rootEnvPath),
schemaEnvPath: config.relativeEnvPaths.schemaEnvPath && path.resolve(__dirname, config.relativeEnvPaths.schemaEnvPath),
});
const env = { ...(loadedEnv ? loadedEnv.parsed : {}), ...process.env };
const databaseUrl = config.datasource.url.fromEnvVar
? env[config.datasource.url.fromEnvVar]
: config.datasource.url.value;

module.exports.createSequelizeInstance = (options) => {
const withDefaults = mergeDeepRight({
define: {
freezeTableName: true,
},
});

const sequelize = new Sequelize(databaseUrl, withDefaults(options ?? {}));

// First initialize all models
Object.keys(models).forEach((model) => {
models[model].initialize?.(sequelize);
});

// Then apply associations
Object.keys(models).forEach((model) => {
models[model].associate?.(models);
models[model].hooks?.(models);
});

return {
sequelize,
models,
};
};
44 changes: 44 additions & 0 deletions plop/js/models/Model.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const { Model, DataTypes } = require('sequelize');

module.exports.{{modelName}} = class extends Model {
static initialize(sequelize) {
this.init(
{
{{#each scalarFields}}
{{fieldName}}: {
type: {{#if isList}}DataTypes.ARRAY(DataTypes.{{type}}){{else}}DataTypes.{{{type}}}{{/if}},{{#if (eq allowNull false)}}
allowNull: {{allowNull}},{{/if}}{{#if (and hasDefaultValue (eq isAutoincrement false))}}
defaultValue: '{{default}}',{{/if}}{{#if isId}}
primaryKey: {{isId}},{{/if}}{{#if isAutoincrement}}
autoIncrement: {{isAutoincrement}},{{/if}}{{#if isUnique}}
unique: {{isUnique}},{{/if}}
},
{{/each}}
},
{
sequelize,
modelName: '{{modelName}}',
tableName: '{{#if dbName}}{{dbName}}{{else}}{{modelName}}{{/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)}}
deletedAt: false,{{/if}} --}}{{#if hasDeletedAt}}
paranoid: true,{{/if}}{{/if}}
}
);
}

{{#if (or belongsToFields (or hasManyFields hasOneFields))}}
static associate(models) {
{{#each belongsToFields}}
this.belongsTo(models.{{name}}, { as: '{{as}}', targetKey: '{{targetKey}}', foreignKey: '{{foreignKey}}' });
{{/each}}
{{#each hasManyFields}}
this.hasMany(models.{{name}}, { as: '{{as}}' });
{{/each}}
{{#each hasOneFields}}
this.hasOne(models.{{name}}, { as: '{{as}}' });
{{/each}}
}
{{/if}}
}
9 changes: 9 additions & 0 deletions plop/js/models/index.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{{#each models}}
const { {{modelName}} } = require('./{{modelName}}');
{{/each}}

module.exports = {
{{#each models}}
{{modelName}},
{{/each}}
};
24 changes: 12 additions & 12 deletions plop/plopfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,28 @@ module.exports = function (plop) {
actions: () => [
{
type: 'add',
path: 'utils/find.ts',
templateFile: path.join(__dirname, './utils/find.ts.hbs'),
path: 'utils/find.{{outputFormat}}',
templateFile: path.join(__dirname, './{{outputFormat}}/utils/find.hbs'),
},
{
type: 'add',
path: 'utils/index.ts',
templateFile: path.join(__dirname, './utils/index.ts.hbs'),
path: 'utils/index.{{outputFormat}}',
templateFile: path.join(__dirname, './{{outputFormat}}/utils/index.hbs'),
},
],
});

plop.setGenerator('index.ts', {
plop.setGenerator('index', {
actions: () => [
{
type: 'add',
path: 'models/index.ts',
templateFile: path.join(__dirname, './models/index.ts.hbs'),
path: 'models/index.{{outputFormat}}',
templateFile: path.join(__dirname, './{{outputFormat}}/models/index.hbs'),
},
{
type: 'add',
path: 'index.ts',
templateFile: path.join(__dirname, './index.ts.hbs'),
path: 'index.{{outputFormat}}',
templateFile: path.join(__dirname, './{{outputFormat}}/index.hbs'),
},
{
type: 'add',
Expand All @@ -49,12 +49,12 @@ module.exports = function (plop) {
],
});

plop.setGenerator('Model.ts', {
plop.setGenerator('Model', {
actions: () => [
{
type: 'add',
path: 'models/{{modelName}}.ts',
templateFile: path.join(__dirname, './models/Model.ts.hbs'),
path: 'models/{{modelName}}.{{outputFormat}}',
templateFile: path.join(__dirname, './{{outputFormat}}/models/Model.hbs'),
},
],
});
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
generator models {
provider = "node ./dist/cli.js"
provider = "node ./dist/cli.js"
outputFormat = "typescript"
}

datasource db {
Expand Down
4 changes: 3 additions & 1 deletion prisma/sequelize/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"value": "/Users/victor/Projects/_own/prisma-sequelize-generator/prisma/sequelize",
"fromEnvVar": "null"
},
"config": {},
"config": {
"outputFormat": "typescript"
},
"binaryTargets": [],
"previewFeatures": []
},
Expand Down
26 changes: 22 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,23 @@ import { generatorHandler } from '@prisma/generator-helper';
import { getEnvPaths, parseEnvValue } from '@prisma/sdk';
import nodePlop from 'node-plop';
import * as path from 'path';
import { mergeRight, prop } from 'ramda';

import { transformDMMF } from './generator/transformDMMF';

// eslint-disable-next-line @typescript-eslint/no-var-requires
// const pkg = require('../package.json');

const formatAliases = {
javascript: 'js',
typescript: 'ts',
js: 'js',
ts: 'ts',
};
const withDefaults = mergeRight({
outputFormat: formatAliases.js,
});

generatorHandler({
onManifest() {
return {
Expand All @@ -20,6 +31,13 @@ generatorHandler({
throw new Error('No output was specified for Prisma Sequelize Generator');
}

const generatorConfig = withDefaults(options.generator.config);

if (!Object.keys(formatAliases).includes(generatorConfig.outputFormat)) {
throw new Error(`Incorrect output format was specified. Allowed formats are: ${Object.keys(formatAliases)}`);
}
const outputFormat = prop(generatorConfig.outputFormat as keyof typeof formatAliases, formatAliases);

const outputDir =
// This ensures previous version of prisma are still supported
typeof options.generator.output === 'string'
Expand All @@ -29,8 +47,8 @@ generatorHandler({
try {
const plop = nodePlop(path.join(__dirname, '../plop/plopfile.js'), { destBasePath: outputDir, force: true });
// const utilsGenerator = plop.getGenerator('utils');
const indexGenerator = plop.getGenerator('index.ts');
const modelGenerator = plop.getGenerator('Model.ts');
const indexGenerator = plop.getGenerator('index');
const modelGenerator = plop.getGenerator('Model');

const schemaDir = options.schemaPath ? path.dirname(options.schemaPath) : process.cwd();
const schemaPath = path.join(schemaDir, 'prisma.schema');
Expand All @@ -55,8 +73,8 @@ generatorHandler({

await Promise.all([
// utilsGenerator.runActions({}),
indexGenerator.runActions({ models, config: JSON.stringify(config, null, 2) }),
...models.map((model) => modelGenerator.runActions(model)),
indexGenerator.runActions({ models, config: JSON.stringify(config, null, 2), outputFormat }),
...models.map((model) => modelGenerator.runActions({ ...model, outputFormat })),
]);
} catch (e) {
console.error('Error: unable to write files for Prisma Sequelize Generator');
Expand Down

0 comments on commit bb915d0

Please sign in to comment.