mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-05-03 02:04:54 +00:00
157 lines
4.7 KiB
Markdown
157 lines
4.7 KiB
Markdown
# Entity Prefixing for Package Database Operations
|
|
|
|
## Overview
|
|
|
|
To prevent entity name collisions between packages in the generated Prisma schema, MetaBuilder uses a standardized entity prefixing system. When schemas are generated from package YAML definitions, entity names are automatically prefixed.
|
|
|
|
## Prefix Format
|
|
|
|
| Component | Format | Example |
|
|
|-----------|--------|---------|
|
|
| Entity Name | `Pkg_{PascalPackage}_{EntityName}` | `Pkg_ForumForge_ForumPost` |
|
|
| Table Name | `{package_id}_{lowercaseentity}` | `forum_forge_forumpost` |
|
|
|
|
### Examples
|
|
|
|
| Package | Entity | Prefixed Entity | Table Mapping |
|
|
|---------|--------|-----------------|---------------|
|
|
| `forum_forge` | `ForumCategory` | `Pkg_ForumForge_ForumCategory` | `forum_forge_forumcategory` |
|
|
| `forum_forge` | `ForumThread` | `Pkg_ForumForge_ForumThread` | `forum_forge_forumthread` |
|
|
| `social_hub` | `SocialProfile` | `Pkg_SocialHub_SocialProfile` | `social_hub_socialprofile` |
|
|
| `github_tools` | `GitHubRepository` | `Pkg_GithubTools_GitHubRepository` | `github_tools_githubrepository` |
|
|
|
|
## TypeScript (Schema Generation)
|
|
|
|
The prefixing is handled automatically during schema generation by `tools/codegen/schema-registry.ts`:
|
|
|
|
```typescript
|
|
import { getPrefixedEntityName, entityToPrisma } from './schema-registry'
|
|
|
|
// Get prefixed name
|
|
const prefixed = getPrefixedEntityName('forum_forge', 'ForumPost')
|
|
// => 'Pkg_ForumForge_ForumPost'
|
|
|
|
// Generate Prisma model with prefix
|
|
const prismaModel = entityToPrisma(schemaEntity, 'forum_forge')
|
|
```
|
|
|
|
### CLI Commands
|
|
|
|
```bash
|
|
# Show prefixed entity names for a package
|
|
npx tsx tools/codegen/schema-cli.ts prefix forum_forge
|
|
|
|
# Preview generated Prisma models with prefixes
|
|
npx tsx tools/codegen/schema-cli.ts preview forum_forge
|
|
```
|
|
|
|
## Lua (Runtime Operations)
|
|
|
|
For Lua DB operations, use the shared prefix module:
|
|
|
|
### Simple Usage
|
|
|
|
```lua
|
|
local prefix = require('shared.db.prefix')
|
|
|
|
-- Package ID for entity prefixing
|
|
local PACKAGE_ID = 'forum_forge'
|
|
|
|
-- Helper function
|
|
local function entity(name)
|
|
return prefix.getPrefixedName(PACKAGE_ID, name)
|
|
end
|
|
|
|
-- Use in DBAL calls
|
|
function M.createPost(dbal, params)
|
|
return dbal:create(entity('ForumPost'), {
|
|
tenantId = params.tenantId,
|
|
content = params.content,
|
|
-- ...
|
|
})
|
|
end
|
|
|
|
function M.listPosts(dbal, threadId)
|
|
return dbal:list(entity('ForumPost'), {
|
|
where = { threadId = threadId },
|
|
})
|
|
end
|
|
```
|
|
|
|
### Wrapper-Based Usage
|
|
|
|
For simpler code, use the wrapper that auto-prefixes all entity names:
|
|
|
|
```lua
|
|
local prefix = require('shared.db.prefix')
|
|
|
|
-- Create a wrapped DBAL instance
|
|
local db = prefix.createPackageDb(dbal, 'forum_forge')
|
|
|
|
-- All calls automatically prefix entity names
|
|
function M.createPost(params)
|
|
return db:create('ForumPost', { -- Automatically becomes 'Pkg_ForumForge_ForumPost'
|
|
tenantId = params.tenantId,
|
|
content = params.content,
|
|
})
|
|
end
|
|
```
|
|
|
|
## Schema YAML Files
|
|
|
|
Schema YAML files in `packages/{name}/seed/schema/*.yaml` use **unprefixed** entity names. The prefixing is applied during generation:
|
|
|
|
```yaml
|
|
# packages/forum_forge/seed/schema/forum.yaml
|
|
entities:
|
|
ForumPost: # Unprefixed in YAML
|
|
fields:
|
|
id:
|
|
type: String
|
|
primaryKey: true
|
|
content:
|
|
type: String
|
|
threadId:
|
|
type: String
|
|
relations:
|
|
thread:
|
|
kind: belongsTo
|
|
target: ForumThread # Also unprefixed - same-package targets auto-resolve
|
|
foreignKey: threadId
|
|
```
|
|
|
|
When generated:
|
|
- Entity becomes `Pkg_ForumForge_ForumPost`
|
|
- Relation target becomes `Pkg_ForumForge_ForumThread`
|
|
- Table mapping is `@@map("forum_forge_forumpost")`
|
|
|
|
## Cross-Package Relations
|
|
|
|
For relations to entities in other packages, use the full prefixed name:
|
|
|
|
```yaml
|
|
# packages/social_hub/seed/schema/social.yaml
|
|
entities:
|
|
SocialProfile:
|
|
relations:
|
|
user:
|
|
kind: belongsTo
|
|
target: User # Core entity (no prefix)
|
|
foreignKey: userId
|
|
```
|
|
|
|
## Implementation Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| [tools/codegen/schema-registry.ts](../tools/codegen/schema-registry.ts) | TypeScript prefix functions |
|
|
| [tools/codegen/schema-cli.ts](../tools/codegen/schema-cli.ts) | CLI commands including `prefix` |
|
|
| [packages/shared/seed/scripts/db/prefix.lua](../packages/shared/seed/scripts/db/prefix.lua) | Lua prefix helper module |
|
|
|
|
## Benefits
|
|
|
|
1. **No Collisions**: Two packages can have entities named `Config` without conflict
|
|
2. **Clear Ownership**: Prefixed names immediately show which package owns an entity
|
|
3. **Database Isolation**: Table names are namespaced by package
|
|
4. **Simple Code**: Lua helper means package code uses simple names internally
|