校验 Prisma 客户端结构一致性
This commit is contained in:
parent
c664ac8723
commit
762b3ae69a
@ -5,7 +5,7 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "npm run storage:legacy-boundary && prisma generate && next build",
|
||||
"build": "npm run storage:legacy-boundary && prisma generate && npm run prisma:verify-client && next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"typecheck": "tsc --noEmit",
|
||||
@ -22,6 +22,7 @@
|
||||
"history:scan": "tsx scripts/scan-history-materials.ts",
|
||||
"history:import": "tsx scripts/import-history-materials.ts",
|
||||
"prisma:generate": "prisma generate",
|
||||
"prisma:verify-client": "node scripts/verify-prisma-client-schema.mjs",
|
||||
"prisma:push": "prisma db push",
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
|
||||
55
scripts/verify-prisma-client-schema.mjs
Normal file
55
scripts/verify-prisma-client-schema.mjs
Normal file
@ -0,0 +1,55 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { createRequire } from 'node:module'
|
||||
|
||||
const ROOT = process.cwd()
|
||||
const SOURCE_SCHEMA = path.join(ROOT, 'prisma', 'schema.prisma')
|
||||
const require = createRequire(import.meta.url)
|
||||
const clientPackage = require.resolve('@prisma/client/package.json')
|
||||
const GENERATED_SCHEMA = path.resolve(path.dirname(clientPackage), '..', '..', '.prisma', 'client', 'schema.prisma')
|
||||
|
||||
function readSchemaShape(schemaPath) {
|
||||
const source = fs.readFileSync(schemaPath, 'utf8')
|
||||
const shape = {}
|
||||
const declaration = /(?:^|\n)(model|enum)\s+(\w+)\s*\{([\s\S]*?)\n\}/g
|
||||
|
||||
for (const match of source.matchAll(declaration)) {
|
||||
const [, kind, name, body] = match
|
||||
const members = []
|
||||
|
||||
for (const rawLine of body.split(/\r?\n/)) {
|
||||
const line = rawLine.trim()
|
||||
if (!line || line.startsWith('//') || line.startsWith('@@')) continue
|
||||
const [memberName, memberType] = line.split(/\s+/)
|
||||
members.push(kind === 'model' ? `${memberName}:${memberType}` : memberName)
|
||||
}
|
||||
|
||||
shape[`${kind}:${name}`] = members.sort()
|
||||
}
|
||||
|
||||
return shape
|
||||
}
|
||||
|
||||
if (!fs.existsSync(GENERATED_SCHEMA)) {
|
||||
throw new Error(`Prisma Client schema is missing: ${GENERATED_SCHEMA}`)
|
||||
}
|
||||
|
||||
const sourceShape = readSchemaShape(SOURCE_SCHEMA)
|
||||
const generatedShape = readSchemaShape(GENERATED_SCHEMA)
|
||||
|
||||
if (JSON.stringify(sourceShape) !== JSON.stringify(generatedShape)) {
|
||||
const sourceKeys = new Set(Object.keys(sourceShape))
|
||||
const generatedKeys = new Set(Object.keys(generatedShape))
|
||||
const missingDeclarations = [...sourceKeys].filter((key) => !generatedKeys.has(key))
|
||||
const staleDeclarations = [...sourceKeys].filter((key) => (
|
||||
generatedKeys.has(key)
|
||||
&& JSON.stringify(sourceShape[key]) !== JSON.stringify(generatedShape[key])
|
||||
))
|
||||
throw new Error(
|
||||
`Prisma Client does not match prisma/schema.prisma; regenerate it before building. `
|
||||
+ `Missing declarations: ${missingDeclarations.join(', ') || 'none'}. `
|
||||
+ `Stale declarations: ${staleDeclarations.join(', ') || 'none'}.`,
|
||||
)
|
||||
}
|
||||
|
||||
console.log(`Prisma Client schema verified (${Object.keys(sourceShape).length} declarations)`)
|
||||
Loading…
x
Reference in New Issue
Block a user