Describe the bug
Two problems in the code @tsed/prisma generates, seen with Prisma 7 (prisma-client generator) and an API bundled with esbuild:
1. Bytes fields are typed Buffer, which is not assignable to the type the Prisma client declares.
The Prisma 7 client types a Bytes field as Uint8Array<ArrayBuffer>. The generated model declares it as Buffer, so type-checking the generated models fails:
models/UserMfaPasskeyModel.ts:25:3 - error TS2416: Property 'publicKey' in type 'UserMfaPasskeyModel' is not assignable to the same property in base type '{ uuid: string; userId: string; createdAt: Date; updatedAt: Date; nickname: string; lastUsedAt: Date | null; credentialId: string; publicKey: Uint8Array<ArrayBuffer>; signCount: number; transports: string[]; aaguid: string | null; }'.
Type 'Buffer<ArrayBufferLike>' is not assignable to type 'Uint8Array<ArrayBuffer>'.
Types of property 'buffer' are incompatible.
Type 'ArrayBufferLike' is not assignable to type 'ArrayBuffer'.
Type 'SharedArrayBuffer' is not assignable to type 'ArrayBuffer'.
The mapping is hardcoded in lib/esm/generator/domain/ScalarTsTypes.js ([PrismaScalars.Bytes]: "Buffer"), and documentation attributes (/// @TsED.…) can add decorators but cannot change the property type, so there is no way around it from the schema.
2. The generated .ts code depends on decorator metadata for DI tokens and collection types.
PrismaService and every repository use @Inject() without a token (generatePrismaService.js, generateRepositories.js).
- List fields use
@CollectionOf(() => Model) without a collection type (transformFieldToDecorators.js).
Both fall back to design:type. A toolchain that does not emit decorator metadata (esbuild, which bundles our API) produces a server that fails at boot with:
Given token is undefined. Could mean a circular dependency problem. Try to use @Inject(() => Token) to solve it.
and, once the injections are given explicit tokens, list fields are mapped as plain objects instead of arrays.
Setting emitTranspiledCode = "true" on the generator works around both points: the output is compiled by ts-morph with emitDecoratorMetadata: true, and the Buffer type ends up in a .d.ts that skipLibCheck skips. Point 1 is still wrong there, only hidden.
To Reproduce
- Declare a model with a
Bytes field and a one-to-many relation, with the prisma-client generator and the Ts.ED generator writing TypeScript (no emitTranspiledCode).
- Run
prisma generate.
- Type-check the generated models: error from point 1.
- Bundle an app that injects a generated repository with esbuild and bootstrap it: error from point 2.
Expected behavior
Bytes generated as Uint8Array<ArrayBuffer>, matching the Prisma client.
- The generated code names its tokens and collection types explicitly, so it works without decorator metadata:
@Inject(PrismaService) in repositories and @Inject(Logger) in PrismaService;
@CollectionOf(() => Model, "Array") on list fields.
Code snippets
// schema.prisma
generator client {
provider = "prisma-client"
output = "./generated/prisma"
}
generator tsed {
provider = "tsed-prisma"
output = "./generated/tsed"
}
// Generated today (generated/tsed/models/UserMfaPasskeyModel.ts)
@Property(Buffer)
@Required()
publicKey: Buffer;
// Generated today (generated/tsed/repositories/AccountsRepository.ts)
@Inject()
protected prisma: PrismaService;
// Generated today (generated/tsed/models/AccountModel.ts)
@CollectionOf(() => LinkedChannelModel)
@Required()
linkedChannels: LinkedChannelModel[];
OS
Linux
Node version
Node v24.21.0
Library version
@tsed/prisma 8.40.1 (all @tsed/* framework packages 8.40.1), prisma / @prisma/client 7.10.0, TypeScript 6.0.3
Additional context
We currently run with emitTranspiledCode = "true". The changes above would make the default TypeScript output work with bundlers that do not emit decorator metadata, and make it type-check against the Prisma 7 client.
Describe the bug
Two problems in the code
@tsed/prismagenerates, seen with Prisma 7 (prisma-clientgenerator) and an API bundled with esbuild:1.
Bytesfields are typedBuffer, which is not assignable to the type the Prisma client declares.The Prisma 7 client types a
Bytesfield asUint8Array<ArrayBuffer>. The generated model declares it asBuffer, so type-checking the generated models fails:The mapping is hardcoded in
lib/esm/generator/domain/ScalarTsTypes.js([PrismaScalars.Bytes]: "Buffer"), and documentation attributes (/// @TsED.…) can add decorators but cannot change the property type, so there is no way around it from the schema.2. The generated
.tscode depends on decorator metadata for DI tokens and collection types.PrismaServiceand every repository use@Inject()without a token (generatePrismaService.js,generateRepositories.js).@CollectionOf(() => Model)without a collection type (transformFieldToDecorators.js).Both fall back to
design:type. A toolchain that does not emit decorator metadata (esbuild, which bundles our API) produces a server that fails at boot with:and, once the injections are given explicit tokens, list fields are mapped as plain objects instead of arrays.
Setting
emitTranspiledCode = "true"on the generator works around both points: the output is compiled by ts-morph withemitDecoratorMetadata: true, and theBuffertype ends up in a.d.tsthatskipLibCheckskips. Point 1 is still wrong there, only hidden.To Reproduce
Bytesfield and a one-to-many relation, with theprisma-clientgenerator and the Ts.ED generator writing TypeScript (noemitTranspiledCode).prisma generate.Expected behavior
Bytesgenerated asUint8Array<ArrayBuffer>, matching the Prisma client.@Inject(PrismaService)in repositories and@Inject(Logger)inPrismaService;@CollectionOf(() => Model, "Array")on list fields.Code snippets
OS
Linux
Node version
Node v24.21.0
Library version
@tsed/prisma 8.40.1 (all @tsed/* framework packages 8.40.1), prisma / @prisma/client 7.10.0, TypeScript 6.0.3
Additional context
We currently run with
emitTranspiledCode = "true". The changes above would make the default TypeScript output work with bundlers that do not emit decorator metadata, and make it type-check against the Prisma 7 client.