.claude/skills/fosmvvm-fluent-datamodel-generator/SKILL.md
Generate Fluent DataModels for FOSMVVM server-side persistence. Scaffolds models, migrations, and tests for database-backed entities.
npx skillsauth add foscomputerservices/FOSUtilities fosmvvm-fluent-datamodel-generatorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate Fluent DataModels for server-side persistence following FOSMVVM architecture.
Dependency: This skill uses fosmvvm-fields-generator for the Fields layer (protocol, messages, YAML). Run that skill first for form-backed models.
This skill is specifically for Fluent persistence layer (typically in Vapor server apps).
STOP and ask the user if:
Check for Fluent indicators:
Package.swift imports fluent, fluent-postgres-driver, fluent-sqlite-driver, etc.@ID, @Field, @Parent, @Children, @Siblings property wrappersMigrations/ directory exists with Fluent migration patternsFluentKit or FluentIf Fluent isn't present, inform the user: "This skill generates Fluent DataModels for server-side persistence. Your project doesn't appear to use Fluent. How would you like to proceed?"
In FOSMVVM, the Model is the center - the source of truth that reads and writes flow through.
See FOSMVVMArchitecture.md | OpenClaw reference for full context.
┌─────────────────────────────────────┐
│ Fluent DataModel │
│ (implements Model + Fields) │
│ │
│ • All fields (system + user) │
│ • Relationships (@Parent, etc.) │
│ • Timestamps, audit fields │
│ • Persistence logic │
└──────────────┬──────────────────────┘
│
┌────────────────────┼────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ ViewModelFactory│ │ CreateRequest │ │ UpdateRequest │
│ (projector) │ │ RequestBody │ │ RequestBody │
│ │ │ │ │ │
│ → ViewModel │ │ → persists to │ │ → updates │
│ (projection) │ │ DataModel │ │ DataModel │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Fields protocol = Form input (user-editable subset)
DataModel = Complete entity (Fluent implementation)
Not all entities need Fields:
Each form-backed model requires files across multiple targets:
── fosmvvm-fields-generator ──────────────────────────────────
{ViewModelsTarget}/ (shared protocol layer)
FieldModels/
{Model}Fields.swift ← Protocol + Enum + Validation
{Model}FieldsMessages.swift ← Localization message struct
{ResourcesPath}/ (localization resources)
FieldModels/
{Model}FieldsMessages.yml ← YAML localization strings
── fosmvvm-fluent-datamodel-generator (this skill) ───────────
{WebServerTarget}/ (server implementation)
DataModels/
{Model}.swift ← Fluent model (implements protocol)
Migrations/
{Model}+Schema.swift ← Table creation migration
{Model}+Seed.swift ← Seed data migration
Tests/
{ViewModelsTarget}Tests/
FieldModels/
{Model}FieldsTests.swift ← Unit tests
database.swift ← Register migrations
Invocation: /fosmvvm-fluent-datamodel-generator
Prerequisites:
Workflow integration: This skill is used for server-side persistence with Fluent. For form-backed models, run fosmvvm-fields-generator first to create the Fields protocol. The skill references conversation context automatically—no file paths or Q&A needed.
This skill references conversation context to determine DataModel structure:
From conversation context, the skill identifies:
From requirements already in context:
Based on data source:
If form-backed model (Fields protocol exists):
If system-only model (no Fields):
Before generating, the skill validates:
Skill references information from:
See reference.md for complete file templates with all patterns.
import FluentKit
import FOSFoundation
import FOSMVVM
import FOSMVVMVapor
import Foundation
final class {Model}: DataModel, {Model}Fields, Hashable, @unchecked Sendable {
static let schema = "{models}" // snake_case plural
@ID(key: .id) var id: ModelIdType?
// Fields from protocol
@Field(key: "field_name") var fieldName: FieldType
// Validation messages
let {model}ValidationMessages: {Model}FieldsMessages
// Timestamps
@Timestamp(key: "created_at", on: .create) var createdAt: Date?
@Timestamp(key: "updated_at", on: .update) var updatedAt: Date?
// CRITICAL: Initialize validationMessages FIRST
init() {
self.{model}ValidationMessages = .init()
}
init(id: ModelIdType? = nil, fieldName: FieldType) {
self.{model}ValidationMessages = .init() // FIRST!
self.id = id
self.fieldName = fieldName
}
}
PRINCIPLE: Existential types (any Protocol) are a code smell. Always ask "Is there any other way?" before using them.
For required relationships, use associated types in the protocol:
public protocol IdeaFields: ValidatableModel, Codable, Sendable {
associatedtype User: UserFields
var createdBy: User { get set }
}
In the Fluent model, @Parent directly satisfies the protocol:
final class Idea: DataModel, IdeaFields, Hashable, @unchecked Sendable {
@Parent(key: "created_by") var createdBy: User
// No computed property needed - @Parent satisfies the associated type directly
}
In schema: .field("created_by", .uuid, .required, .references(User.schema, "id", onDelete: .cascade))
When to use each pattern:
associatedtype User: UserFields): Required relationshipsModelIdType? for optional FKsModelIdType: Optional FKs, external system references"{Model.schema}-initial""{Model.schema}-seed"guard count() == 0For PostgreSQL-specific features (tsvector, LTREE, etc.), use SQLKit:
import Fluent
import SQLKit // Required for raw SQL
// In prepare():
guard let sql = database as? any SQLDatabase else { return }
let schema = Model.schema
try await sql.raw(SQLQueryString("ALTER TABLE \(unsafeRaw: schema) ADD COLUMN search_vector tsvector")).run()
Key points:
SQLKit (not just Fluent)database as? any SQLDatabaseSQLQueryString with \(unsafeRaw:) for identifiers@Suite annotation with descriptive nameLocalizableTestCase@Test(arguments:)Test structs with associated types:
private struct TestIdea: IdeaFields {
typealias User = TestUser // Satisfy the associated type
var id: ModelIdType?
var createdBy: TestUser // Concrete type, not existential
}
private struct TestUser: UserFields {
var id: ModelIdType? = .init()
var firstName: String = "Test"
// ... other required fields with defaults
}
| Concept | Convention | Example |
|---------|------------|---------|
| Model class | PascalCase singular | User, Idea |
| Table name | snake_case plural | users, ideas |
| Field keys | snake_case | created_at, user_id |
| Enum cases | camelCase | searchLanguage, inProgress |
| Enum raw values | snake_case | "search_language", "in_progress" |
| Protocol | {Model}Fields | UserFields, IdeaFields |
| Messages struct | {Model}FieldsMessages | UserFieldsMessages |
| Swift Type | Fluent Type | Database |
|------------|-------------|----------|
| String | .string | VARCHAR/TEXT |
| Int | .int | INTEGER |
| Bool | .bool | BOOLEAN |
| Date | .datetime | TIMESTAMPTZ |
| UUID | .uuid | UUID |
| [UUID] | .array(of: .uuid) | UUID[] |
| Custom Enum | .string | VARCHAR (stored as raw value) |
| JSONB | .json | JSONB |
| Version | Date | Changes | |---------|------|---------| | 1.0 | 2025-12-23 | Initial skill based on SystemConfig pattern | | 1.1 | 2025-12-23 | Added relationship patterns (@Parent), initialization order, imports list | | 1.2 | 2025-12-23 | Associated types for relationships (not existentials), raw SQL patterns, test struct patterns | | 1.3 | 2025-12-24 | Factored out Fields layer to fields-generator skill | | 2.0 | 2025-12-26 | Renamed to fosmvvm-fluent-datamodel-generator, added Scope Guard, generalized from Kairos-specific to FOSMVVM patterns, added architecture context | | 2.1 | 2026-01-24 | Update to context-aware approach (remove file-parsing/Q&A). Skill references conversation context instead of asking questions or accepting file paths. |
development
Generate new Claude Code skills following the context-aware pattern. Scaffolds SKILL.md, reference docs, and frontmatter.
testing
Generate ViewModel tests with codable round-trip, versioning stability, and multi-locale translation verification.
data-ai
Generate FOSMVVM ViewModels for SwiftUI screens, pages, and components. Scaffolds RequestableViewModel, localization bindings, and stub factories.
testing
Generate UI tests for FOSMVVM SwiftUI views using XCTest and FOSTestingUI. Covers accessibility identifiers, ViewModelOperations, and test data transport.