/
datamodel.go
166 lines (124 loc) · 4.06 KB
/
datamodel.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package cmd
import (
"github.com/spf13/cobra"
"github.com/hofstadter-io/hof/cmd/hof/cmd/datamodel"
"github.com/hofstadter-io/hof/cmd/hof/flags"
"github.com/hofstadter-io/hof/cmd/hof/ga"
)
var datamodelLong = `Data models are values or objects used in many hof processes and modules.
The "datamodel" command helps you manage them and track their change history.
At their core, they represent the models that make up your application.
The intention is to define a data model for your entire application once,
then use this source of truth to generate code from database to server to client.
Hof's schema for datamodels is minimal and flexible, allowing you to define the
shape based on your application. You can have multiple datamodels as well.
You can also control and where and how history should be tracked. This history
is included during code generation so that database migrations and functions
for converting between versions can be created.
# Examples Datamodels
-- config.cue --
package datamodel
import (
"github.com/hofstadter-io/hof/schema/dm"
"github.com/hofstadter-io/hof/schema/dm/fields"
)
// Track an entire oject
Config: dm.Object & {
host: fields.String & { Default: "8080" }
database: {
host: fields.String
port: fields.String
dbconn: fields.String
}
}
-- database.cue --
package datamodel
import (
"github.com/hofstadter-io/hof/schema/dm/sql"
"github.com/hofstadter-io/hof/schema/dm/fields"
)
// Traditional database model which maps onto tables & columns
Datamodel: sql.Datamodel & {
// implied through definition, duplicated here for example clarity
$hof: metadata: {
id: "datamodel-abc123"
name: "MyDatamodel"
}
Models: {
User: {
Fields: {
ID: fields.UUID
CreatedAt: fields.Datetime
UpdatedAt: fields.Datetime
DeletedAt: fields.Datetime
email: fields.Email
username: fields.String
password: fields.Password
verified: fields.Bool
active: fields.Bool
persona: fields.Enum & {
Vals: ["guest", "user", "admin", "owner"]
Default: "user"
}
}
}
}
}
# Example Usage (dm is short for datamodel)
$ hof dm list (print known data models)
NAME TYPE VERSION STATUS ID
Config object - ok Config
MyDatamodel datamodel - ok datamodel-abc123
$ hof dm tree (print the structure of the datamodels)
$ hof dm diff (prints a tree based diff of the datamodel)
$ hof dm checkpoint -m "a message about this checkpoint"
$ hof dm log (prints the log of changes from latest to oldest)
You can also use the -d & -e flags to subselect datamodels and nested values
# Learn more:
- https://docs.hofstadter.io/getting-started/data-layer/
- https://docs.hofstadter.io/data-modeling/`
func init() {
DatamodelCmd.PersistentFlags().StringSliceVarP(&(flags.DatamodelPflags.Datamodels), "datamodel", "d", nil, "specify one or more datamodels to operate on")
DatamodelCmd.PersistentFlags().StringSliceVarP(&(flags.DatamodelPflags.Expression), "expr", "e", nil, "CUE paths to select outputs, depending on the command")
}
var DatamodelCmd = &cobra.Command{
Use: "datamodel",
Aliases: []string{
"dm",
},
Short: "manage, diff, and migrate your data models",
Long: datamodelLong,
}
func init() {
extra := func(cmd *cobra.Command) bool {
return false
}
ohelp := DatamodelCmd.HelpFunc()
ousage := DatamodelCmd.UsageFunc()
help := func(cmd *cobra.Command, args []string) {
ga.SendCommandPath(cmd.CommandPath() + " help")
if extra(cmd) {
return
}
ohelp(cmd, args)
}
usage := func(cmd *cobra.Command) error {
if extra(cmd) {
return nil
}
return ousage(cmd)
}
thelp := func(cmd *cobra.Command, args []string) {
help(cmd, args)
}
tusage := func(cmd *cobra.Command) error {
return usage(cmd)
}
DatamodelCmd.SetHelpFunc(thelp)
DatamodelCmd.SetUsageFunc(tusage)
DatamodelCmd.AddCommand(cmddatamodel.CheckpointCmd)
DatamodelCmd.AddCommand(cmddatamodel.DiffCmd)
DatamodelCmd.AddCommand(cmddatamodel.TreeCmd)
DatamodelCmd.AddCommand(cmddatamodel.ListCmd)
DatamodelCmd.AddCommand(cmddatamodel.LogCmd)
}