Skip to content

Commit

Permalink
fix(client): Allow to use Metric as a model name
Browse files Browse the repository at this point in the history
Problem: even though built-in `Metric` type is placed in
a different namespace, type conflict still occurs: `Delegate` classes
are in the same namespace and can't refer to non-namespaced name.

Implements a tiny part of [namespace overhaul proposal](https://www.notion.so/prismaio/Fix-type-name-clashes-in-TS-Client-9e9bbdee13f94a818ece060e55465267): introduces `$Models` namespace.

Ref #12469
  • Loading branch information
SevInf committed Jun 13, 2023
1 parent 4a3536d commit 800dff2
Show file tree
Hide file tree
Showing 10 changed files with 1,317 additions and 1,198 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/client/src/generation/TSClient/Generatable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export interface Generatable {
toTS(edge?: boolean): string | Promise<string>
toBrowserJS?(): string | Promise<string>
toTSWithoutNamespace?(): string | Promise<string>
toTSInModelNamespace?(): string | Promise<string>
}

export function JS(gen: Generatable, edge = false): string | Promise<string> {
Expand Down
18 changes: 14 additions & 4 deletions packages/client/src/generation/TSClient/Model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export type ${getAggregateGetName(model.name)}<T extends ${getAggregateArgsName(
: GetScalarType<T[P], ${aggregateName}[P]>
}`
}
public toTSWithoutNamespace(): string {
public toTSInModelNamespace(): string {
const { model } = this
const docLines = model.documentation ?? ''
const modelLine = `Model ${model.name}\n`
Expand Down Expand Up @@ -315,6 +315,16 @@ export type ${getAggregateGetName(model.name)}<T extends ${getAggregateArgsName(

return `${ts.stringify(payloadExport)}\n\n${ts.stringify(modelTypeExport)}`
}

toTSWithoutNamespace() {
return ts.stringify(
ts.moduleExport(ts.typeDeclaration(this.model.name, ts.namedType(`$Model.${this.model.name}`))),
{
indentLevel: 1,
},
)
}

public toTS(): string {
const { model } = this
const isComposite = this.dmmf.typeMap[model.name]
Expand Down Expand Up @@ -344,9 +354,9 @@ ${ts.stringify(buildScalarSelectType({ modelName: this.model.name, fields: this.
})}
${includeType}
type ${model.name}GetPayload<S extends boolean | null | undefined | ${getArgName(model.name)}> = $Types.GetResult<${
model.name
}Payload, S>
type ${model.name}GetPayload<S extends boolean | null | undefined | ${getArgName(
model.name,
)}> = $Types.GetResult<$Model.${model.name}Payload, S>
${isComposite ? '' : new ModelDelegate(this.outputType, this.dmmf, this.generator).toTS()}
Expand Down
6 changes: 3 additions & 3 deletions packages/client/src/generation/TSClient/PrismaClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function clientExtensionsResultDefinition(this: PrismaClientClass) {
return `${lowerCase(modelName)}?: {
[K in keyof R_${modelName}_Needs]: {
needs: R_${modelName}_Needs[K]
compute: (data: $Types.GetResult<${modelName}Payload<ExtArgs>, { select: R_${modelName}_Needs[K] }, 'findUniqueOrThrow'>) => unknown
compute: (data: $Types.GetResult<$Model.${modelName}Payload<ExtArgs>, { select: R_${modelName}_Needs[K] }, 'findUniqueOrThrow'>) => unknown
}
}`
}
Expand Down Expand Up @@ -86,8 +86,8 @@ function clientTypeMapModelsDefinition(this: PrismaClientClass) {
return `${acc}
${action}: {
args: Prisma.${getModelArgName(modelName, action)}<ExtArgs>,
result: $Utils.OptionalFlat<${modelName}>
payload: ${modelName}Payload<ExtArgs>
result: $Utils.OptionalFlat<$Model.${modelName}>
payload: $Model.${modelName}Payload<ExtArgs>
}`
}, '')}
}`
Expand Down
4 changes: 4 additions & 0 deletions packages/client/src/generation/TSClient/TSClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ ${buildNFTAnnotations(dataProxy, engineType, platforms, relativeOutdir)}
${commonCode.tsWithoutNamespace()}
declare namespace $Model {
${modelAndTypes.map((m) => m.toTSInModelNamespace()).join('\n')}
}
${modelAndTypes.map((m) => m.toTSWithoutNamespace()).join('\n')}
${
modelEnums && modelEnums.length > 0
Expand Down
12 changes: 6 additions & 6 deletions packages/client/src/generation/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,34 +247,34 @@ export function getReturnType({
const promiseOpen = renderPromise ? 'Prisma.PrismaPromise<' : ''
const promiseClose = renderPromise ? '>' : ''

return `${promiseOpen}$Types.GetResult<${name}Payload<ExtArgs>, T, '${actionName}', never>${
return `${promiseOpen}$Types.GetResult<$Model.${name}Payload<ExtArgs>, T, '${actionName}', never>${
isChaining ? '| Null' : ''
}${promiseClose}`
}

if (actionName === 'findFirstOrThrow' || actionName === 'findUniqueOrThrow') {
return `Prisma__${name}Client<${getType(
`$Types.GetResult<${name}Payload<ExtArgs>, T, '${actionName}', never>`,
`$Types.GetResult<$Model.${name}Payload<ExtArgs>, T, '${actionName}', never>`,
isList,
)}, never, ExtArgs>`
}
if (actionName === 'findFirst' || actionName === 'findUnique') {
if (isField) {
return `Prisma__${name}Client<${getType(
`$Types.GetResult<${name}Payload<ExtArgs>, T, '${actionName}', never>`,
`$Types.GetResult<$Model.${name}Payload<ExtArgs>, T, '${actionName}', never>`,
isList,
)} | Null, never, ExtArgs>`
}
return `HasReject<GlobalRejectSettings, LocalRejectSettings, '${actionName}', '${name}'> extends True ? Prisma__${name}Client<${getType(
`$Types.GetResult<${name}Payload<ExtArgs>, T, '${actionName}', never>`,
`$Types.GetResult<$Model.${name}Payload<ExtArgs>, T, '${actionName}', never>`,
isList,
)}, never, ExtArgs> : Prisma__${name}Client<${getType(
`$Types.GetResult<${name}Payload<ExtArgs>, T, '${actionName}', never>`,
`$Types.GetResult<$Model.${name}Payload<ExtArgs>, T, '${actionName}', never>`,
isList,
)} | null, null, ExtArgs>`
}
return `Prisma__${name}Client<${getType(
`$Types.GetResult<${name}Payload<ExtArgs>, T, '${actionName}', never>`,
`$Types.GetResult<$Model.${name}Payload<ExtArgs>, T, '${actionName}', never>`,
isList,
)}, never, ExtArgs>`
}
Expand Down
24 changes: 24 additions & 0 deletions packages/client/tests/functional/naming-conflict/metric/_matrix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { defineMatrix } from '../../_utils/defineMatrix'

export default defineMatrix(() => [
[
{
provider: 'sqlite',
},
{
provider: 'postgresql',
},
{
provider: 'mysql',
},
{
provider: 'mongodb',
},
{
provider: 'cockroachdb',
},
{
provider: 'sqlserver',
},
],
])
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { idForProvider } from '../../../_utils/idForProvider'
import testMatrix from '../_matrix'

export default testMatrix.setupSchema(({ provider }) => {
return /* Prisma */ `
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "${provider}"
url = env("DATABASE_URI_${provider}")
}
model Metric {
id ${idForProvider(provider)}
name String
value Int
}
`
})
24 changes: 24 additions & 0 deletions packages/client/tests/functional/naming-conflict/metric/tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import testMatrix from './_matrix'
// @ts-ignore
import type { PrismaClient } from './node_modules/@prisma/client'

declare let prisma: PrismaClient

testMatrix.setupTestSuite(() => {
test('allows to use Metric name for a model', async () => {
await prisma.metric.create({
data: {
name: 'signups',
value: 9000,
},
})

const metric = await prisma.metric.findFirst()

expect(metric).toEqual({
id: expect.any(String),
name: 'signups',
value: 9000,
})
})
})

0 comments on commit 800dff2

Please sign in to comment.