Schemas
The hof supplied datamodel schemas
schema/dm
schema/dm
package dm
import (
"github.com/hofstadter-io/hof/schema"
)
// This is a complete Value tracked as one
// useful for schemas, config, and NoSQL
Object: {
schema.Hof// needed for reFerences
#hof: datamodel: root: true
TrackHistory
// all fields will be tracked
}
// This is like object, but supports cue values
// (todo, should support full lattice)
Value: {
Object
#hof: datamodel: cue: true
}
// This is a general datamodel useful in many applications
// It can be expanded and enriched to cover more
// Useful for SQL, APIs, forms, and similar
Datamodel: {
schema.DHof // needed for references
#hof: datamodel: root: true
}
// Schema for a snapshot, can include anything else
Snapshot: {
Timestamp: string | *""
}
// convenience type for embedding history
History: [...Snapshot]
TrackHistory: {
#hof: datamodel: history: true // needed for CUE compat
"Snapshot": Snapshot
"History": History
}
schema/dm/fields
schema/dm/fields.Common
package fields
DataTypes: ID |
UUID |
CUID |
Bool |
String |
Int |
Float |
Enum |
Password |
Email
ID: UUID & {Default: "" | *"uuid_generate_v4()"}
Field: {
Name: string
Plural: string | *"\(Name)s"
Type: string
Reln?: string
}
UUID: Field & {
Type: "uuid"
Nullable: bool | *false
Unique: bool | *true
Default?: string
Validation: {
Format: "uuid"
}
}
CUID: Field & {
Type: "cuid"
Nullable: bool | *false
Unique: bool | *true
}
Bool: Field & {
Type: "bool"
Default: string | *"false"
Nullable: bool | *false
}
String: Field & {
Type: "string"
Length: int | *64
Unique: bool | *false
Nullable: bool | *false
Default?: string
Validation: {
Max: int | *Length
}
}
Int: Field & {
Type: "int"
Nullable: bool | *false
Default?: int
}
Float: Field & {
Type: "float"
Nullable: bool | *false
Default?: float
}
Enum: Field & {
Type: "string"
Vals: [...string]
Nullable: bool | *false
Default?: string
}
Password: String & {
Bcrypt: true
}
Email: String & {
Validation: {
Format: "email"
}
Unique: true
}
Date: Field & {
Type: "date"
}
Time: Field & {
Type: "time"
}
Datetime: Field & {
Type: "datetime"
}
schema/dm/sql
schema/dm/sql.Datamodel
package sql
import (
"github.com/hofstadter-io/hof/schema"
"github.com/hofstadter-io/hof/schema/dm"
)
Datamodel: {
#hof: datamodel: root: true
schema.Hof
dm.TrackHistory
// these are the models for the application
// they can map onto database tables and apis
Models: {
#hof: datamodel: node: true
#hof: datamodel: ordered: true
[N=string]: Model & {Name: N, #hof: metadata: name: N}
}
// OrderedModels: [...Model] will be
// inject here for order stability
}
Model: M={
schema.Hof
dm.TrackHistory
// for easy access
Name: M.#hof.metadata.name
Plural: string | *"\(Name)s"
// These are the fields of a model
// they can map onto database columnts and form fields
Fields: {
#hof: datamodel: node: true
#hof: datamodel: ordered: true
[N=string]: Field & {Name: N, #hof: metadata: name: N}
}
// OrderedFields: [...Fields] will be
// inject here for order stability
// if we want Relations as a separate value
// we can process the fields to extract them
}
Field: {
// schema.Hof
// TODO, decide if these should be the default
// #hof: datamodel: history: true // needed for CUE compat
// History: dm.History
Name: string
Type: string
// relation type, open to be flexible
Relation?: {
"Name": string | *Name
Type: "has-one" | "has-many" | "belongs-to" | "many-to-many"
Other: string // technically a cue path, but as a string
}
// what about {val, *val, []val, []*val}
// we probably don't care about pointer here
// that is a language detail (code gen target)
// we can enrich this for various types
// in our app or other reusable datamodels
}
schema/dm/sql.Fields
package sql
import (
"github.com/hofstadter-io/hof/schema/dm/fields"
)
CommonFields: {
ID: fields.UUID & {Default: string | *"uuid_generate_v4()"}
CreatedAt: fields.Datetime
UpdatedAt: fields.Datetime
}
SoftDelete: {
DeletedAt: fields.Datetime
}
PrimaryKey: fields.UUID & {
Default: string | *"uuid_generate_v4()"
SQL: PrimaryKey: true
}
Varchar: F=fields.String & {
SQL: Type: "character varying(\(F.Length))"
}
schema/dm/enrichers
Examples for language type enrichments
schema/dm/enrichers.Go
package go
import "github.com/hofstadter-io/hof/schema/dm"
FieldEnricher: {
field: dm.Field
output: field
output: GoType: [
if field.Type == "uuid" {"uuid.UUID"},
if field.Type == "datetime" {"time.Time"},
if field.Type == "float" {"float64"},
field.Type,
][0]
}
schema/dm/enrichers.Py
package py
import "github.com/hofstadter-io/hof/schema/dm"
FieldEnricher: {
field: dm.Field
output: field
output: PyType: [
if field.Type == "uuid" {"uuid.UUID"},
if field.Type == "date" {"datetime.date"},
if field.Type == "time" {"datetime.time"},
if field.Type == "datetime" {"datetime.datetime"},
if field.Type == "string" {"str"},
field.Type,
][0]
}