Skip to content

Commit

Permalink
Merge pull request #2864 from tsedio/fix-prisma-circular-esm-ref
Browse files Browse the repository at this point in the history
fix(prisma): fix circular reference when column is optional
  • Loading branch information
Romakita authored Oct 17, 2024
2 parents 6d5cae8 + b02a9b7 commit 4c9a8c4
Show file tree
Hide file tree
Showing 15 changed files with 106 additions and 165 deletions.
1 change: 1 addition & 0 deletions packages/orm/prisma/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"generate:postgres:esm": "yarn build && cd test/postgres-esm && prisma -v && prisma generate",
"generate:mongo": "yarn build && cd test/mongo && prisma -v && prisma generate",
"generate:mongo:esm": "yarn build && cd test/mongo-esm && prisma -v && prisma generate",
"generate:circular:esm": "yarn build && cd test/circular-ref && prisma -v && prisma generate",
"test:ci": "vitest run --coverage.thresholds.autoUpdate=true"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,19 @@ describe("transformScalarToType()", () => {
});
// @ts-ignore
field.model.name = "User";
expect(transformScalarToType(field, ctx)).toEqual("UserModel | null");
expect(field.model.addImportDeclaration).not.toHaveBeenCalled();
expect(transformScalarToType(field, ctx)).toEqual("Relation<UserModel> | null");
expect(field.model.addImportDeclaration).toHaveBeenCalledWith("@tsed/core", "Relation", true);
});

it("should transform User to User", () => {
it("should transform Role to User", () => {
const ctx = createContextFixture();
const field = createDmmfFieldFixture({
kind: "object",
type: "Role"
});
// @ts-ignore
field.model.name = "User";
expect(transformScalarToType(field, ctx)).toEqual("RoleModel | null");
expect(transformScalarToType(field, ctx)).toEqual("Relation<RoleModel> | null");
expect(field.model.addImportDeclaration).toHaveBeenCalledWith("./RoleModel", "RoleModel");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ export function transformScalarToType(field: DmmfField, ctx: TransformContext):
TSType += "[]";
}

if (!isList && hasCircularRef && ["inputObjectTypes", "enumTypes"].includes(location)) {
hasCircularRef && !isList && field.model.addImportDeclaration("@tsed/core", "Relation", true);
TSType = `Relation<${TSType}>`;
}

if (!isRequired) {
if (model.isInputType) {
TSType += " | undefined";
Expand All @@ -41,10 +46,7 @@ export function transformScalarToType(field: DmmfField, ctx: TransformContext):
TSType += " | null";
}

if (isRequired && !isList && !isNullable && hasCircularRef && ["inputObjectTypes", "enumTypes"].includes(location)) {
hasCircularRef && !isList && field.model.addImportDeclaration("@tsed/core", "Relation", true);
TSType = `Relation<${TSType}>`;
}


return TSType;
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ exports[`generateModels > should generate models (post) 1`] = `
"import { Post } from "../client/index";
import { Integer, Required, Property, Allow } from "@tsed/schema";
import { UserModel } from "./UserModel";
import type { Relation } from "@tsed/core";
export class PostModel implements Post {
@Property(Number)
Expand All @@ -30,7 +31,7 @@ export class PostModel implements Post {
@Property(() => UserModel)
@Allow(null)
user: UserModel | null;
user: Relation<UserModel> | null;
@Property(Number)
@Integer()
Expand All @@ -44,6 +45,7 @@ export class PostModel implements Post {
exports[`generateModels > should generate models (user) 1`] = `
"import { User } from "../client/index";
import { Integer, Required, Property, Groups, Format, Email, Description, Allow, Enum, CollectionOf } from "@tsed/schema";
import type { Relation } from "@tsed/core";
import { Role } from "../enums/index";
import { PostModel } from "./PostModel";
Expand Down Expand Up @@ -84,121 +86,11 @@ export class UserModel implements User {
@Property(() => UserModel)
@Allow(null)
successor: UserModel | null;
successor: Relation<UserModel> | null;
@Property(() => UserModel)
@Allow(null)
predecessor: UserModel | null;
@Required()
@Enum(Role)
role: Role;
@CollectionOf(() => PostModel)
@Required()
posts: PostModel[];
@CollectionOf(String)
@Required()
keywords: string[];
@Property(Object)
@Required()
biography: any;
}
"
`;

exports[`generateModels should generate models (info) 1`] = `
"import { Info } from \\"../client/index\\";
import { Required, Property } from \\"@tsed/schema\\";
export class InfoModel implements Info {
@Property(String)
@Required()
firstName: string;
@Property(String)
@Required()
lastName: string;
}
"
`;

exports[`generateModels should generate models (post) 1`] = `
"import { Post } from \\"../client/index\\";
import { Integer, Required, Property, Allow } from \\"@tsed/schema\\";
import { UserModel } from \\"./UserModel\\";
export class PostModel implements Post {
@Property(Number)
@Integer()
@Required()
id: number;
@Property(() => UserModel)
@Allow(null)
user: UserModel | null;
@Property(Number)
@Integer()
@Allow(null)
userId: number | null;
}
"
`;

exports[`generateModels should generate models (user) 1`] = `
"import { User } from \\"../client/index\\";
import { Integer, Required, Property, Groups, Format, Email, Description, Allow, Enum, CollectionOf } from \\"@tsed/schema\\";
import { Role } from \\"../enums/index\\";
import { PostModel } from \\"./PostModel\\";
export class UserModel implements User {
@Property(Number)
@Integer()
@Required()
@Groups(\\"!creation\\")
id: number;
@Property(Date)
@Format(\\"date-time\\")
@Required()
createdAt: Date;
@Property(String)
@Required()
@Email()
@Description(\\"User email. This email must be unique!\\")
email: string;
@Property(Number)
@Allow(null)
weight: number | null;
@Property(Boolean)
@Allow(null)
is18: boolean | null;
@Property(String)
@Allow(null)
name: string | null;
@Property(Number)
@Integer()
@Allow(null)
successorId: number | null;
@Property(() => UserModel)
@Allow(null)
successor: UserModel | null;
@Property(() => UserModel)
@Allow(null)
predecessor: UserModel | null;
predecessor: Relation<UserModel> | null;
@Required()
@Enum(Role)
Expand Down
10 changes: 10 additions & 0 deletions packages/orm/prisma/test/circular-ref/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@tsed/prisma-test",
"type": "commonjs",
"devDependencies": {
"prisma": "^4.0.0"
},
"dependencies": {
"@prisma/client": "^4.0.0"
}
}
32 changes: 32 additions & 0 deletions packages/orm/prisma/test/circular-ref/prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "windows", "debian-openssl-1.1.x"]
output = "../prisma/generated/client"
}

generator tsed {
provider = "node ../../lib/cjs/generator.js"
output = "../prisma/generated/tsed"
emitDMMF = true
}

model Conversation {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
assignmentId String? @map("assignment_id") @db.Uuid
assignment Assignment? @relation(fields: [assignmentId], references: [id], onDelete: NoAction, onUpdate: NoAction)
@@map("conversation")
}

model Assignment {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
conversations Conversation[]
@@map("assignment")
}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export {Role} from "./Role";
export { Role } from "./Role";
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Prisma} from "../client/index";
import { Prisma } from "../client/index";

declare global {
namespace TsED {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {Post} from "../client/index";
import {Integer, Required, Property, Allow} from "@tsed/schema";
import {UserModel} from "./UserModel";
import { Post } from "../client/index";
import { Integer, Required, Property, Allow } from "@tsed/schema";
import { UserModel } from "./UserModel";
import type { Relation } from "@tsed/core";

export class PostModel implements Post {
@Property(Number)
Expand All @@ -10,10 +11,11 @@ export class PostModel implements Post {

@Property(() => UserModel)
@Allow(null)
user: UserModel | null;
user: Relation<UserModel> | null;

@Property(Number)
@Integer()
@Allow(null)
userId: number | null;
}

Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {User} from "../client/index";
import {Integer, Required, Property, Groups, Format, Email, Description, Allow, Enum, CollectionOf} from "@tsed/schema";
import {Role} from "../enums/index";
import {PostModel} from "./PostModel";
import { User } from "../client/index";
import { Integer, Required, Property, Groups, Format, Email, Description, Allow, Enum, CollectionOf } from "@tsed/schema";
import type { Relation } from "@tsed/core";
import { Role } from "../enums/index";
import { PostModel } from "./PostModel";

export class UserModel implements User {
@Property(Number)
Expand Down Expand Up @@ -40,11 +41,11 @@ export class UserModel implements User {

@Property(() => UserModel)
@Allow(null)
successor: UserModel | null;
successor: Relation<UserModel> | null;

@Property(() => UserModel)
@Allow(null)
predecessor: UserModel | null;
predecessor: Relation<UserModel> | null;

@Required()
@Enum(Role)
Expand All @@ -62,3 +63,4 @@ export class UserModel implements User {
@Required()
biography: any;
}

Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export {PostModel} from "./PostModel";
export {UserModel} from "./UserModel";
export { PostModel } from "./PostModel";
export { UserModel } from "./UserModel";
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import {isArray} from "@tsed/core";
import {deserialize} from "@tsed/json-mapper";
import {Injectable, Inject} from "@tsed/di";
import {PrismaService} from "../services/PrismaService";
import {Prisma, Post} from "../client/index";
import {PostModel} from "../models/index";
import { isArray } from "@tsed/core";
import { deserialize } from "@tsed/json-mapper";
import { Injectable, Inject } from "@tsed/di";
import { PrismaService } from "../services/PrismaService";
import { Prisma, Post } from "../client/index";
import { PostModel } from "../models/index";

@Injectable()
export class PostsRepository {
@Inject()
protected prisma: PrismaService;

get collection() {
return this.prisma.post;
return this.prisma.post
}

get groupBy() {
return this.collection.groupBy.bind(this.collection);
return this.collection.groupBy.bind(this.collection)
}

protected deserialize<T>(obj: null | Post | Post[]): T {
return deserialize<T>(obj, {type: PostModel, collectionType: isArray(obj) ? Array : undefined});
return deserialize<T>(obj, { type: PostModel, collectionType: isArray(obj) ? Array : undefined })
}

async findUnique(args: Prisma.PostFindUniqueArgs): Promise<PostModel | null> {
Expand Down Expand Up @@ -58,14 +58,14 @@ export class PostsRepository {
}

deleteMany(args: Prisma.PostDeleteManyArgs) {
return this.collection.deleteMany(args);
return this.collection.deleteMany(args)
}

updateMany(args: Prisma.PostUpdateManyArgs) {
return this.collection.updateMany(args);
return this.collection.updateMany(args)
}

aggregate(args: Prisma.PostAggregateArgs) {
return this.collection.aggregate(args);
return this.collection.aggregate(args)
}
}
Loading

0 comments on commit 4c9a8c4

Please sign in to comment.