Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for computed fields in prisma plugin? #2808

Open
shivanshtalwar0 opened this issue Aug 31, 2024 · 8 comments
Open

Support for computed fields in prisma plugin? #2808

shivanshtalwar0 opened this issue Aug 31, 2024 · 8 comments
Assignees

Comments

@shivanshtalwar0
Copy link

Is your feature request related to a problem? Please describe.

currently it seems computed fields are not supported in tsed/prisma out of the box

Describe the solution you'd like

according to https://www.prisma.io/docs/orm/prisma-client/queries/computed-fields i believe it should be straightforward to add the support

Describe alternatives you've considered

No response

Additional context

No response

Acceptance criteria

No response

@Romakita
Copy link
Collaborator

Romakita commented Sep 1, 2024

I don’t see how we can reflect that with the generator. Tsed use the schema to generate field and computed fields is declared outside of the schema.

see you

@shivanshtalwar0
Copy link
Author

shivanshtalwar0 commented Sep 1, 2024

currently i do this

	async $onReady(): Promise<any> {
		this.extend<VideoCallModel>("videoCall", {
			duration: {
				needs: { acceptedAt: true, endedAt: true },
				compute(item) {
					if (item.acceptedAt && item.endedAt) {
						return (item.endedAt.getTime() - item.acceptedAt.getTime())/1000
					}
					return null
				},
			},
		})
	}
@Service()
export class BaseService<T> implements OnInit {
	private prismaService: PrismaService

	extend<T>(model: string, computedFields: Record<string, {
		needs: Partial<Record<keyof T, boolean>>
		compute: (model: T) => any
	}>) {
		const data = this.prismaService.$extends({
			result: {
				[model]: computedFields as any
			}
		})
		this.repositoryContainer = data[model]
	}

}

maybe some other solution that we can build on top of it?

@Romakita
Copy link
Collaborator

Hello @shivanshtalwar0

I have no idea to simplify that. Excepted through a configuration.

@Configuration({

   prisma: {
      extends: {
         "videoCall": {
	      duration: {
				needs: { acceptedAt: true, endedAt: true },
				compute(item) {
					if (item.acceptedAt && item.endedAt) {
						return (item.endedAt.getTime() - item.acceptedAt.getTime())/1000
					}
					return null
				},
               },
          }
      }
   }
}

or using DI container:

import {extends} from "@tsed/prisma";

// maybe instead videoCall we can give VideoCallModel and retrieve the collection name

extends("videoCall", {
	      duration: {
				needs: { acceptedAt: true, endedAt: true },
				compute(item) {
					if (item.acceptedAt && item.endedAt) {
						return (item.endedAt.getTime() - item.acceptedAt.getTime())/1000
					}
					return null
				},
               },
          }
})

but VideoCallModel.duration be generated by typescript so type checking won't works. Prisma schema is the source of truth and there is no way to generate computed properties from schema. So adding this will only create problems if the typings are not correct.

@shivanshtalwar0
Copy link
Author

Thanks for getting back to this issue, yeah if there will be no types on prisma model on typescript it defeats the whole point of typescript (doing "any" forcefully to read properties from model) but with my implementation typing works but it isn't a standard solution but again it will not have support for any of tsed model decorators so i guess i will have to do the ugly way only
Therefore you can close it or wait until you think you get any eureka moment ^^

@shivanshtalwar0
Copy link
Author

On second thoughts how about if we can solve it using special service like i did with support for tsed decorators for model? Lmk what u think

@Romakita
Copy link
Collaborator

On second thoughts how about if we can solve it using special service like i did with support for tsed decorators for model? Lmk what u think

I don't see what you mean. Please write a short (hypothetical) code you have in mind.

@shivanshtalwar0
Copy link
Author

See the current implementation that i shared above something like that but somehow make it generic so users wanting to have computed field support should strictly resort to this service for a specific model needs be it fetching data updating data in database for example a service like
PrismaComputedService which users can inject into controllers ot elsewhere and define computed fields programmatically for any model having single instance of this service like i did since with my implementation typing works fine

@shivanshtalwar
Copy link

something like this not sure how easy or hard it is

import {PrismaComputedService} from '@prisma/core'
@Controller()
class MyComputedTester implements OnReady{
async $OnReady(){
this.pcs.extend<VideoCallModel>("videoCall", {
			duration: {
				needs: { acceptedAt: true, endedAt: true },
				compute(item) {
					if (item.acceptedAt && item.endedAt) {
						return (item.endedAt.getTime() - item.acceptedAt.getTime())/1000
					}
					return null
				},
			},
		})
}
@Inject()
pcs:PrismaComputedService

@Get()
getAll(){
return this.pcs.VideoCallRepository.find()
}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants