mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
docs: schema,migrations,scripts (2 files)
This commit is contained in:
90
deployment/scripts/apply-schema-migrations.sh
Normal file
90
deployment/scripts/apply-schema-migrations.sh
Normal file
@@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
# Docker entrypoint hook for schema migrations
|
||||
# Called during container startup to apply approved migrations
|
||||
|
||||
set -e
|
||||
|
||||
REGISTRY_FILE="/app/prisma/schema-registry.json"
|
||||
GENERATED_PRISMA="/app/prisma/generated-from-packages.prisma"
|
||||
|
||||
echo "🔍 Checking for pending schema migrations..."
|
||||
|
||||
# Check if registry exists
|
||||
if [ ! -f "$REGISTRY_FILE" ]; then
|
||||
echo "✓ No schema registry found - skipping"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check for approved migrations
|
||||
APPROVED_COUNT=$(cat "$REGISTRY_FILE" | python3 -c "
|
||||
import json, sys
|
||||
data = json.load(sys.stdin)
|
||||
count = sum(1 for m in data.get('migrationQueue', []) if m['status'] == 'approved')
|
||||
print(count)
|
||||
")
|
||||
|
||||
if [ "$APPROVED_COUNT" -eq 0 ]; then
|
||||
echo "✓ No approved migrations pending"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "⚠️ Found $APPROVED_COUNT approved migration(s) to apply"
|
||||
|
||||
# Generate Prisma schema fragment
|
||||
echo "📝 Generating Prisma schema..."
|
||||
npx ts-node /app/tools/codegen/schema-cli.ts generate
|
||||
|
||||
# Check if generated file exists
|
||||
if [ ! -f "$GENERATED_PRISMA" ]; then
|
||||
echo "❌ Failed to generate Prisma schema"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📋 Generated schema fragment:"
|
||||
cat "$GENERATED_PRISMA"
|
||||
|
||||
# Apply migrations
|
||||
echo ""
|
||||
echo "🚀 Running Prisma migrate..."
|
||||
npx prisma migrate dev --name "package-schema-$(date +%Y%m%d%H%M%S)" --skip-generate
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✓ Migrations applied successfully"
|
||||
|
||||
# Mark migrations as applied in registry
|
||||
python3 -c "
|
||||
import json
|
||||
|
||||
with open('$REGISTRY_FILE', 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
import time
|
||||
for m in data.get('migrationQueue', []):
|
||||
if m['status'] == 'approved':
|
||||
m['status'] = 'applied'
|
||||
m['appliedAt'] = int(time.time() * 1000)
|
||||
# Update entity registry
|
||||
data['entities'][m['entityName']] = {
|
||||
'checksum': m['newChecksum'],
|
||||
'version': '1.0',
|
||||
'ownerPackage': m['packageId'],
|
||||
'prismaModel': m['prismaPreview'],
|
||||
'appliedAt': m['appliedAt']
|
||||
}
|
||||
|
||||
with open('$REGISTRY_FILE', 'w') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
|
||||
print('✓ Registry updated')
|
||||
"
|
||||
|
||||
# Regenerate Prisma client
|
||||
echo "🔧 Regenerating Prisma client..."
|
||||
npx prisma generate
|
||||
|
||||
echo ""
|
||||
echo "✅ Schema migrations complete!"
|
||||
else
|
||||
echo "❌ Migration failed!"
|
||||
exit 1
|
||||
fi
|
||||
153
docs/packages/schema-migrations.md
Normal file
153
docs/packages/schema-migrations.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Package Schema Migration System
|
||||
|
||||
## Overview
|
||||
|
||||
Packages can define their own database schemas in `seed/schema/entities.yaml`. The system:
|
||||
|
||||
1. **Validates** schemas across packages to prevent conflicts
|
||||
2. **Queues** changes for admin approval
|
||||
3. **Generates** Prisma schema fragments
|
||||
4. **Applies** migrations on container restart
|
||||
|
||||
## Flow
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
||||
│ Package with │────▶│ npm run │────▶│ Admin reviews │
|
||||
│ schema/ │ │ schema:scan │ │ pending queue │
|
||||
│ entities.yaml │ │ │ │ │
|
||||
└─────────────────┘ └──────────────────┘ └────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
||||
│ Prisma migrate │◀────│ Container │◀────│ Admin approves │
|
||||
│ applied │ │ restart │ │ migrations │
|
||||
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## Package Schema Format
|
||||
|
||||
Create `packages/{name}/seed/schema/entities.yaml`:
|
||||
|
||||
```yaml
|
||||
entities:
|
||||
- name: MyEntity
|
||||
version: "1.0"
|
||||
description: "Description of entity"
|
||||
|
||||
fields:
|
||||
id:
|
||||
type: cuid
|
||||
primary: true
|
||||
generated: true
|
||||
|
||||
tenantId:
|
||||
type: string
|
||||
required: true
|
||||
index: true
|
||||
|
||||
name:
|
||||
type: string
|
||||
required: true
|
||||
maxLength: 100
|
||||
|
||||
data:
|
||||
type: string
|
||||
nullable: true
|
||||
description: "JSON: additional data"
|
||||
|
||||
createdAt:
|
||||
type: bigint
|
||||
required: true
|
||||
|
||||
indexes:
|
||||
- fields: [tenantId, name]
|
||||
unique: true
|
||||
|
||||
relations:
|
||||
- name: tenant
|
||||
type: belongsTo
|
||||
entity: Tenant
|
||||
field: tenantId
|
||||
onDelete: Cascade
|
||||
|
||||
acl:
|
||||
create: [user]
|
||||
read: [public]
|
||||
update: [self, admin]
|
||||
delete: [admin]
|
||||
```
|
||||
|
||||
## Field Types
|
||||
|
||||
| Type | Prisma | Notes |
|
||||
|------|--------|-------|
|
||||
| `string` | `String` | Text fields |
|
||||
| `int` | `Int` | 32-bit integer |
|
||||
| `bigint` | `BigInt` | 64-bit integer (timestamps) |
|
||||
| `float` | `Float` | Decimal numbers |
|
||||
| `boolean` | `Boolean` | True/false |
|
||||
| `cuid` | `String` | CUID identifier |
|
||||
| `uuid` | `String` | UUID identifier |
|
||||
| `json` | `Json` | JSON data |
|
||||
|
||||
## CLI Commands
|
||||
|
||||
```bash
|
||||
# Scan all packages for schema changes
|
||||
npm run schema:scan
|
||||
|
||||
# List pending migrations
|
||||
npm run schema:list
|
||||
|
||||
# Approve migrations
|
||||
npm run schema:approve all
|
||||
npm run schema:approve <migration-id>
|
||||
|
||||
# Generate Prisma fragment
|
||||
npm run schema:generate
|
||||
|
||||
# Preview package schema as Prisma
|
||||
npm run schema:preview audit_log
|
||||
|
||||
# Check status
|
||||
npm run schema:status
|
||||
```
|
||||
|
||||
## Checksum Validation
|
||||
|
||||
The system computes checksums from schema structure (not descriptions). If two packages define the same entity:
|
||||
|
||||
- **Same checksum**: Compatible, no conflict
|
||||
- **Different checksum**: Error - packages must coordinate
|
||||
|
||||
## Metadata.json Integration
|
||||
|
||||
Add schema export to `metadata.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"packageId": "my_package",
|
||||
"schema": {
|
||||
"entities": ["MyEntity", "MyOtherEntity"],
|
||||
"path": "schema/entities.yaml"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Docker Integration
|
||||
|
||||
The container startup script (`apply-schema-migrations.sh`) automatically:
|
||||
|
||||
1. Checks for approved migrations
|
||||
2. Generates Prisma schema fragment
|
||||
3. Runs `prisma migrate dev`
|
||||
4. Updates registry to mark as applied
|
||||
5. Regenerates Prisma client
|
||||
|
||||
## Security
|
||||
|
||||
- Only **admin** can approve migrations
|
||||
- Schema changes require container restart
|
||||
- Checksums prevent unauthorized modifications
|
||||
- ACL rules define entity-level permissions
|
||||
Reference in New Issue
Block a user