mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-27 15:24:56 +00:00
code: tools,schema,codegen (2 files)
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
* reject <id> - Reject a migration
|
||||
* generate - Generate Prisma fragment for approved migrations
|
||||
* status - Show overall migration status
|
||||
* prefix <pkg> <entity> - Show prefixed entity name
|
||||
*/
|
||||
|
||||
import * as path from 'path'
|
||||
@@ -25,6 +26,10 @@ import {
|
||||
loadPackageSchema,
|
||||
computeSchemaChecksum,
|
||||
entityToPrisma,
|
||||
getPrefixedEntityName,
|
||||
packageToPascalCase,
|
||||
extractPackageFromPrefix,
|
||||
extractEntityFromPrefix,
|
||||
type SchemaRegistry,
|
||||
} from './schema-registry'
|
||||
|
||||
@@ -63,12 +68,14 @@ Commands:
|
||||
${colors.green}reject${colors.reset} <id> Reject a migration
|
||||
${colors.green}generate${colors.reset} Generate Prisma fragment
|
||||
${colors.green}preview${colors.reset} <pkg> Preview Prisma output for package
|
||||
${colors.green}prefix${colors.reset} <pkg> [entity] Show prefixed entity name
|
||||
${colors.green}status${colors.reset} Show migration status
|
||||
|
||||
Examples:
|
||||
npx ts-node tools/codegen/schema-cli.ts scan
|
||||
npx ts-node tools/codegen/schema-cli.ts approve all
|
||||
npx ts-node tools/codegen/schema-cli.ts preview audit_log
|
||||
npx ts-node tools/codegen/schema-cli.ts prefix forum_forge Post
|
||||
`)
|
||||
}
|
||||
|
||||
@@ -258,6 +265,33 @@ const cmdStatus = (registry: SchemaRegistry): void => {
|
||||
}
|
||||
}
|
||||
|
||||
const cmdPrefix = (packageId: string, entityName?: string): void => {
|
||||
console.log(`\n${colors.cyan}Entity Prefix Info${colors.reset}\n`)
|
||||
console.log(`Package: ${packageId}`)
|
||||
console.log(`Pascal Case: ${packageToPascalCase(packageId)}`)
|
||||
console.log(`Prefix: Pkg_${packageToPascalCase(packageId)}_`)
|
||||
|
||||
if (entityName) {
|
||||
const prefixed = getPrefixedEntityName(packageId, entityName)
|
||||
console.log(`\n${colors.green}Entity:${colors.reset} ${entityName}`)
|
||||
console.log(`${colors.green}Prefixed:${colors.reset} ${prefixed}`)
|
||||
console.log(`${colors.green}Table:${colors.reset} ${packageId}_${entityName.toLowerCase()}`)
|
||||
} else {
|
||||
// Show all entities from package schema
|
||||
const pkgPath = path.join(PACKAGES_PATH, packageId)
|
||||
const schema = loadPackageSchema(pkgPath)
|
||||
if (schema && schema.entities) {
|
||||
console.log(`\n${colors.yellow}Entities in package:${colors.reset}`)
|
||||
for (const entity of schema.entities) {
|
||||
const prefixed = getPrefixedEntityName(packageId, entity.name)
|
||||
console.log(` ${entity.name} → ${prefixed}`)
|
||||
console.log(` ${colors.dim}Table: ${packageId}_${entity.name.toLowerCase()}${colors.reset}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log('')
|
||||
}
|
||||
|
||||
// Main
|
||||
const main = (): void => {
|
||||
const args = process.argv.slice(2)
|
||||
@@ -321,6 +355,14 @@ const main = (): void => {
|
||||
case 'status':
|
||||
cmdStatus(registry)
|
||||
break
|
||||
case 'prefix':
|
||||
if (!args[1]) {
|
||||
log.error('Package name required')
|
||||
log.info('Usage: prefix <package> [entity]')
|
||||
break
|
||||
}
|
||||
cmdPrefix(args[1], args[2])
|
||||
break
|
||||
default:
|
||||
log.error(`Unknown command: ${command}`)
|
||||
printUsage()
|
||||
|
||||
@@ -362,6 +362,7 @@ export const loadPackageSchema = (packagePath: string): PackageSchema | null =>
|
||||
|
||||
/**
|
||||
* Validate and queue schema changes for a package
|
||||
* Uses prefixed entity names to prevent cross-package collisions
|
||||
*/
|
||||
export const validateAndQueueSchema = (
|
||||
packageId: string,
|
||||
@@ -377,30 +378,28 @@ export const validateAndQueueSchema = (
|
||||
}
|
||||
|
||||
for (const entity of schema.entities) {
|
||||
// Use prefixed entity name to avoid collisions
|
||||
const prefixedName = getPrefixedEntityName(packageId, entity.name)
|
||||
const newChecksum = computeSchemaChecksum(entity)
|
||||
const existing = registry.entities[entity.name]
|
||||
const existing = registry.entities[prefixedName]
|
||||
|
||||
// Check for conflicts with other packages
|
||||
// Check for conflicts - with prefixes, only same package can conflict
|
||||
if (existing && existing.ownerPackage !== packageId) {
|
||||
if (existing.checksum !== newChecksum) {
|
||||
errors.push(
|
||||
`Entity "${entity.name}" owned by "${existing.ownerPackage}" has different schema. ` +
|
||||
`Current: ${existing.checksum}, Proposed: ${newChecksum}. ` +
|
||||
`Packages must use identical schema or coordinate versions.`
|
||||
)
|
||||
continue
|
||||
}
|
||||
// Same checksum = compatible, skip
|
||||
// This should be rare with prefixes, but check anyway
|
||||
errors.push(
|
||||
`Entity "${prefixedName}" owned by "${existing.ownerPackage}" conflicts. ` +
|
||||
`This is unexpected with prefixes - please report this bug.`
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
// New entity or updated schema
|
||||
if (!existing || existing.checksum !== newChecksum) {
|
||||
const prismaPreview = entityToPrisma(entity)
|
||||
const prismaPreview = entityToPrisma(entity, packageId)
|
||||
const item: MigrationQueueItem = {
|
||||
id: crypto.randomUUID(),
|
||||
packageId,
|
||||
entityName: entity.name,
|
||||
entityName: prefixedName, // Store prefixed name
|
||||
action: existing ? 'alter' : 'create',
|
||||
currentChecksum: existing?.checksum || null,
|
||||
newChecksum,
|
||||
|
||||
Reference in New Issue
Block a user