Skip to content

Commit

Permalink
chore: cleanup middleware implementation (#6969)
Browse files Browse the repository at this point in the history
Co-authored-by: Pierre-Antoine Mills <pierreantoine.urvoy@gmail.com>
Co-authored-by: Joël Galeran <Jolg42@users.noreply.github.com>
  • Loading branch information
3 people committed Jun 2, 2021
1 parent ed43150 commit dec79f5
Show file tree
Hide file tree
Showing 12 changed files with 509 additions and 422 deletions.
Expand Up @@ -36,7 +36,6 @@ Object {
string: true,
},
},
clientMethod: with_all_field_types.create,
dataPath: Array [],
model: with_all_field_types,
runInTransaction: false,
Expand Down Expand Up @@ -89,7 +88,6 @@ Object {
id: 2,
},
},
clientMethod: with_all_field_types.delete,
dataPath: Array [],
model: with_all_field_types,
runInTransaction: false,
Expand Down Expand Up @@ -133,7 +131,6 @@ Object {
string: true,
},
},
clientMethod: with_all_field_types.findMany,
dataPath: Array [],
model: with_all_field_types,
runInTransaction: false,
Expand Down Expand Up @@ -211,7 +208,6 @@ Object {
id: 1,
},
},
clientMethod: with_all_field_types.update,
dataPath: Array [],
model: with_all_field_types,
runInTransaction: false,
Expand Down
2 changes: 1 addition & 1 deletion src/packages/client/src/__tests__/batching.test.ts
@@ -1,4 +1,4 @@
import { PrismaClientFetcher } from '../runtime/getPrismaClient'
import { PrismaClientFetcher } from '../runtime/PrismaClientFetcher'
import { blog } from '../fixtures/blog'
import { getDMMF } from '../generation/getDMMF'
import { DMMFClass, makeDocument } from '../runtime'
Expand Down
Expand Up @@ -5,9 +5,9 @@ test('async-hooks', async () => {
const PrismaClient = await getTestClient()
const prisma = new PrismaClient()
let asyncId
prisma.$use((params, fetch) => {
prisma.$use((params, next) => {
asyncId = executionAsyncId()
return fetch(params)
return next(params)
})

await prisma.user.findMany()
Expand Down
Expand Up @@ -6,7 +6,7 @@ test('middlewares-manipulation', async () => {

let theParams
let firstCall = true
prisma.$use(async (params, fetch) => {
prisma.$use(async (params, next) => {
theParams = JSON.parse(JSON.stringify(params)) // clone
if (firstCall) {
params.args = {
Expand All @@ -16,12 +16,12 @@ test('middlewares-manipulation', async () => {
}
firstCall = false
}
const result = await fetch(params)
const result = await next(params)
return result
})

prisma.$use(async (params, fetch) => {
const result = await fetch(params)
prisma.$use(async (params, next) => {
const result = await next(params)
if (result.length > 0) {
result[0].name += '2' // make sure that we can change the result
}
Expand Down
Binary file not shown.
149 changes: 103 additions & 46 deletions src/packages/client/src/__tests__/integration/happy/middlewares/test.ts
@@ -1,64 +1,121 @@
import { getTestClient } from '../../../../utils/getTestClient'

test('middlewares', async () => {
const PrismaClient = await getTestClient()
const db = new PrismaClient()
describe('middleware', () => {
test('basic', async () => {
const PrismaClient = await getTestClient()

const allResults: any[] = []
const engineResults: any[] = []
const db = new PrismaClient()

const order: number[] = []
const allResults: any[] = []

db.$use(async (params, fetch) => {
order.push(1)
const result = await fetch(params)
order.push(4)
return result
})
db.$use(async (params, next) => {
const result = await next(params)
allResults.push(result)
return result
})

await db.user.findMany()
await db.post.findMany()

expect(allResults).toEqual([[], []])

db.$use(async (params, fetch) => {
order.push(2)
const result = await fetch(params)
order.push(3)
allResults.push(result)
return result
db.$disconnect()
})
test('order', async () => {
const PrismaClient = await getTestClient()
const db = new PrismaClient()
const order: number[] = []

db.$use(async (params, next) => {
order.push(1)
const result = await next(params)
order.push(4)
return result
})

db.$use(async (params, next) => {
order.push(2)
const result = await next(params)
order.push(3)
return result
})

db.$use('engine', async (params, fetch) => {
const result = await fetch(params)
engineResults.push(result)
return result
await db.user.findMany()
await db.post.findMany()

expect(order).toEqual([1, 2, 3, 4, 1, 2, 3, 4])

db.$disconnect()
})
test('engine middleware', async () => {
const PrismaClient = await getTestClient()
const db = new PrismaClient()

await db.user.findMany()
await db.post.findMany()
const engineResults: any[] = []

expect(order).toEqual([1, 2, 3, 4, 1, 2, 3, 4])
expect(allResults).toEqual([[], []])
expect(engineResults.map((r) => r.data)).toEqual([
{
data: {
findManyUser: [],
db.$use('engine', async (params, next) => {
const result = await next(params)
engineResults.push(result)
return result
})

await db.user.findMany()
await db.post.findMany()
expect(engineResults.map((r) => r.data)).toEqual([
{
data: {
findManyUser: [],
},
},
},
{
{
data: {
findManyPost: [],
},
},
])
expect(typeof engineResults[0].elapsed).toEqual('number')
expect(typeof engineResults[1].elapsed).toEqual('number')

db.$disconnect()
})
test('modify params', async () => {
const PrismaClient = await getTestClient()
const db = new PrismaClient()

const user = await db.user.create({
data: {
findManyPost: [],
email: 'test@test.com',
name: 'test',
},
},
])
expect(typeof engineResults[0].elapsed).toEqual('number')
expect(typeof engineResults[1].elapsed).toEqual('number')
})
db.$use(async (params, next) => {
if (params.action === 'findFirst' && params.model === 'User') {
params.args = { ...params.args, where: { name: 'test' } }
}
const result = await next(params)
return result
})

db.$disconnect()
})
const users = await db.user.findMany()
console.warn(users)
// The name should be overwritten by the middleware
const u = await db.user.findFirst({
where: {
name: 'fake',
},
})
expect(u.id).toBe(user.id)
await db.user.deleteMany()

test('middlewares unpack', async () => {
const PrismaClient = await getTestClient()
const db = new PrismaClient()
db.$use((params, next) => next(params))
const result = await db.user.count()
expect(typeof result).toBe('number')
db.$disconnect()
})
test('count unpack', async () => {
const PrismaClient = await getTestClient()
const db = new PrismaClient()
db.$use((params, next) => next(params))
const result = await db.user.count()
expect(typeof result).toBe('number')

db.$disconnect()
db.$disconnect()
})
})
2 changes: 2 additions & 0 deletions src/packages/client/src/generation/TSClient/helpers.ts
Expand Up @@ -87,6 +87,8 @@ export function getArgFieldJSDoc(
const comment = JSDocs[action]?.fields[fieldName](singular, plural)
return comment as string
}

return undefined
}

export function escapeJson(str: string): string {
Expand Down
59 changes: 59 additions & 0 deletions src/packages/client/src/runtime/MiddlewareHandler.ts
@@ -0,0 +1,59 @@
import { Action } from './getPrismaClient'
import { Document } from './query'

export type QueryMiddleware<T = unknown> = (
params: QueryMiddlewareParams,
next: (params: QueryMiddlewareParams) => Promise<T>,
) => Promise<T>

export type QueryMiddlewareParams = {
/** The model this is executed on */
model?: string
/** The action that is being handled */
action: Action
/** TODO what is this */
dataPath: string[]
/** TODO what is this */
runInTransaction: boolean
/** TODO what is this */
args: any // TODO remove any, does this make sense, what is args?
}

export type EngineMiddleware<T = unknown> = (
params: EngineMiddlewareParams,
next: (
params: EngineMiddlewareParams,
) => Promise<{ data: T; elapsed: number }>,
) => Promise<{ data: T; elapsed: number }>

export type EngineMiddlewareParams = {
document: Document
runInTransaction?: boolean
}

export type Namespace = 'all' | 'engine'

class MiddlewareHandler<M extends Function> {
private _middlewares: M[] = []

use(middleware: M) {
this._middlewares.push(middleware)
}

get(id: number): M | undefined {
return this._middlewares[id]
}

has(id: number) {
return !!this._middlewares[id]
}

length() {
return this._middlewares.length
}
}

export class Middlewares {
query = new MiddlewareHandler<QueryMiddleware>()
engine = new MiddlewareHandler<EngineMiddleware>()
}

0 comments on commit dec79f5

Please sign in to comment.