diff --git a/package.json b/package.json index ba1eea5..cd67399 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "dependencies": { "@prisma/generator-helper": "^2.29.1", "@prisma/sdk": "^2.29.1", + "morphism": "^1.12.3", "node-plop": "^0.26.2", "ramda": "^0.27.1" }, diff --git a/src/generator/properties.ts b/src/generator/properties.ts index f664c07..d81620a 100644 --- a/src/generator/properties.ts +++ b/src/generator/properties.ts @@ -7,3 +7,34 @@ export const PrismaTypeToSequelizeType: Record = { DateTime: 'DATE', Json: 'JSONB', }; + +export interface ModelProperties { + name: string; + dbName: string; + scalarFields: ScalarProperties[]; + belongsToFields: RelationProperties[]; + hasOneFields: RelationProperties[]; + hasManyFields: RelationProperties[]; + hasCreatedAt: boolean; + hasUpdatedAt: boolean; + hasDeletedAt: boolean; +} + +export interface RelationProperties { + as: string; + name: string; + targetKey: string; + foreignKey: string; +} + +export interface ScalarProperties { + isList: boolean; + hasDefaultValue: boolean; + default: any; + isId: boolean; + isUnique: boolean; + name: string; + type: string; + allowNull: boolean; + isAutoincrement: boolean; +} diff --git a/src/generator/transformDMMF.ts b/src/generator/transformDMMF.ts index beb9a9f..419c006 100644 --- a/src/generator/transformDMMF.ts +++ b/src/generator/transformDMMF.ts @@ -1,62 +1,82 @@ -import { indexBy, prop } from 'ramda'; +import { morphism, Schema } from 'morphism'; +import { compose, includes, indexBy, map, not, prop } from 'ramda'; -import { PrismaTypeToSequelizeType } from './properties'; +import { ModelProperties, PrismaTypeToSequelizeType, RelationProperties, ScalarProperties } 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); + const scalarMorphism = morphism>({ + isList: 'isList', + hasDefaultValue: 'hasDefaultValue', + default: 'default', + isId: 'isId', + isUnique: 'isUnique', + name: 'name', + type: (field: DMMF.Field) => + field.kind === 'scalar' + ? PrismaTypeToSequelizeType[field.type] + : `ENUM(${enumIndex[field.type].values + .map(prop('name')) + .map((n) => `'${n}'`) + .join(', ')})`, + allowNull: { path: 'isRequired', fn: not }, + isAutoincrement: (field: DMMF.Field) => + field.hasDefaultValue && typeof field.default === 'object' && field.default.name === 'autoincrement', + }); - return { - ...model, - scalarFields: model.fields + const relationMorphism = morphism>({ + as: 'name', + name: 'type', + targetKey: 'relationToFields[0]', + foreignKey: 'relationFromFields[0]', + }); + + const modelMorphism = morphism>({ + name: 'name', + dbName: 'dbName', + scalarFields: { + path: 'fields', + fn: (fields: DMMF.Field[]) => + 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 + .map(scalarMorphism), + }, + belongsToFields: { + path: 'fields', + fn: (fields: DMMF.Field[]) => + 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 + .map(relationMorphism), + }, + hasOneFields: { + path: 'fields', + fn: (fields: DMMF.Field[]) => + fields .filter((field) => field.kind === 'object') .filter((field) => !field.isList && !field.relationToFields?.length) - .map((field) => ({ - as: field.name, - name: field.type, - })), - hasManyFields: model.fields + .map(relationMorphism), + }, + hasManyFields: { + path: 'fields', + fn: (fields: DMMF.Field[]) => + 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'), - }; - }), - }; + .map(relationMorphism), + }, + hasCreatedAt: { path: 'fields', fn: compose(includes('createdAt'), map(prop('name'))) }, + hasUpdatedAt: { path: 'fields', fn: compose(includes('updatedAt'), map(prop('name'))) }, + hasDeletedAt: { path: 'fields', fn: compose(includes('deletedAt'), map(prop('name'))) }, + }); + + const transformMorphism = morphism>({ + models: { path: 'models', fn: modelMorphism }, + }); + + return transformMorphism(dmmf.datamodel); }