github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/istructsmem/internal/descr/example_test.go (about) 1 /* 2 * Copyright (c) 2021-present Sigma-Soft, Ltd. 3 * @author: Nikolay Nikitin 4 */ 5 6 package descr_test 7 8 import ( 9 "encoding/json" 10 "fmt" 11 12 "github.com/stretchr/testify/mock" 13 "github.com/voedger/voedger/pkg/appdef" 14 "github.com/voedger/voedger/pkg/istructs" 15 "github.com/voedger/voedger/pkg/istructsmem/internal/descr" 16 ) 17 18 func Example() { 19 appDef := func() appdef.IAppDef { 20 adb := appdef.New() 21 adb.AddPackage("test", "test/path") 22 23 numName := appdef.NewQName("test", "number") 24 strName := appdef.NewQName("test", "string") 25 26 sysRecords := appdef.NewQName("sys", "records") 27 sysViews := appdef.NewQName("sys", "views") 28 29 docName, recName := appdef.NewQName("test", "doc"), appdef.NewQName("test", "rec") 30 31 n := adb.AddData(numName, appdef.DataKind_int64, appdef.NullQName, appdef.MinIncl(1)) 32 n.SetComment("natural (positive) integer") 33 34 s := adb.AddData(strName, appdef.DataKind_string, appdef.NullQName) 35 s.AddConstraints(appdef.MinLen(1), appdef.MaxLen(100), appdef.Pattern(`^\w+$`, "only word characters allowed")) 36 37 doc := adb.AddCDoc(docName) 38 doc.SetSingleton() 39 doc. 40 AddField("f1", appdef.DataKind_int64, true). 41 SetFieldComment("f1", "field comment"). 42 AddField("f2", appdef.DataKind_string, false, appdef.MinLen(4), appdef.MaxLen(4), appdef.Pattern(`^\w+$`)). 43 AddDataField("numField", numName, false). 44 AddRefField("mainChild", false, recName) 45 doc.AddContainer("rec", recName, 0, 100, "container comment") 46 doc.AddUnique(appdef.UniqueQName(docName, "unique1"), []appdef.FieldName{"f1", "f2"}) 47 doc.SetComment(`comment 1`, `comment 2`) 48 49 rec := adb.AddCRecord(recName) 50 rec. 51 AddField("f1", appdef.DataKind_int64, true). 52 AddField("f2", appdef.DataKind_string, false). 53 AddField("phone", appdef.DataKind_string, true, appdef.MinLen(1), appdef.MaxLen(25)). 54 SetFieldVerify("phone", appdef.VerificationKind_Any...) 55 rec. 56 SetUniqueField("phone"). 57 AddUnique(appdef.UniqueQName(recName, "uniq1"), []appdef.FieldName{"f1"}) 58 59 viewName := appdef.NewQName("test", "view") 60 view := adb.AddView(viewName) 61 view.Key().PartKey(). 62 AddField("pk_1", appdef.DataKind_int64) 63 view.Key().ClustCols(). 64 AddField("cc_1", appdef.DataKind_string, appdef.MaxLen(100)) 65 view.Value(). 66 AddDataField("vv_code", strName, true). 67 AddRefField("vv_1", true, docName) 68 69 objName := appdef.NewQName("test", "obj") 70 obj := adb.AddObject(objName) 71 obj.AddField("f1", appdef.DataKind_string, true) 72 73 cmdName := appdef.NewQName("test", "cmd") 74 adb.AddCommand(cmdName). 75 SetUnloggedParam(objName). 76 SetParam(objName). 77 SetEngine(appdef.ExtensionEngineKind_WASM) 78 79 queryName := appdef.NewQName("test", "query") 80 adb.AddQuery(queryName). 81 SetParam(objName). 82 SetResult(appdef.QNameANY) 83 84 prj := adb.AddProjector(appdef.NewQName("test", "projector")) 85 prj. 86 SetWantErrors(). 87 SetEngine(appdef.ExtensionEngineKind_WASM) 88 prj.Events(). 89 Add(recName, appdef.ProjectorEventKind_AnyChanges...).SetComment(recName, "run projector every time when «test.rec» is changed"). 90 Add(cmdName).SetComment(cmdName, "run projector every time when «test.cmd» command is executed"). 91 Add(objName).SetComment(objName, "run projector every time when any command with «test.obj» argument is executed") 92 prj.States(). 93 Add(sysRecords, docName, recName).SetComment(sysRecords, "needs to read «test.doc» and «test.rec» from «sys.records» storage") 94 prj.Intents(). 95 Add(sysViews, viewName).SetComment(sysViews, "needs to update «test.view» from «sys.views» storage") 96 97 reader := adb.AddRole(appdef.NewQName("test", "reader")) 98 reader.SetComment("read-only role") 99 reader.Grant( 100 []appdef.PrivilegeKind{appdef.PrivilegeKind_Select}, 101 []appdef.QName{docName, recName}, []appdef.FieldName{"f1", "f2"}, 102 "allow reader to select some fields from test.doc and test.rec") 103 reader.Grant( 104 []appdef.PrivilegeKind{appdef.PrivilegeKind_Select}, 105 []appdef.QName{viewName}, nil, 106 "allow reader to select all fields from test.view") 107 reader.GrantAll([]appdef.QName{queryName}, "allow reader to execute test.query") 108 109 writer := adb.AddRole(appdef.NewQName("test", "writer")) 110 writer.SetComment("read-write role") 111 writer.GrantAll([]appdef.QName{docName, recName, viewName}, "allow writer to do anything with test.doc, test.rec and test.view") 112 writer.Revoke( 113 []appdef.PrivilegeKind{appdef.PrivilegeKind_Update}, 114 []appdef.QName{docName}, 115 "disable writer to update test.doc") 116 writer.GrantAll([]appdef.QName{cmdName, queryName}, "allow writer to execute all test functions") 117 118 app, err := adb.Build() 119 if err != nil { 120 panic(err) 121 } 122 123 return app 124 }() 125 126 res := &mockResources{} 127 res. 128 On("Resources", mock.AnythingOfType("func(appdef.QName)")).Run(func(args mock.Arguments) {}) 129 130 appStr := &mockedAppStructs{} 131 appStr. 132 On("AppQName").Return(istructs.AppQName_test1_app1). 133 On("AppDef").Return(appDef). 134 On("Resources").Return(res) 135 136 appLimits := map[appdef.QName]map[istructs.RateLimitKind]istructs.RateLimit{} 137 138 app := descr.Provide(appStr, appLimits) 139 140 json, err := json.MarshalIndent(app, "", " ") 141 142 fmt.Println("error:", err) 143 fmt.Println(string(json)) 144 145 //os.WriteFile("C://temp//provide_test.json", json, 0644) 146 147 // Output: 148 // error: <nil> 149 // { 150 // "Name": "test1/app1", 151 // "Packages": { 152 // "test": { 153 // "Path": "test/path", 154 // "DataTypes": { 155 // "test.number": { 156 // "Comment": "natural (positive) integer", 157 // "Ancestor": "sys.int64", 158 // "Constraints": { 159 // "MinIncl": 1 160 // } 161 // }, 162 // "test.string": { 163 // "Ancestor": "sys.string", 164 // "Constraints": { 165 // "MaxLen": 100, 166 // "MinLen": 1, 167 // "Pattern": "^\\w+$" 168 // } 169 // } 170 // }, 171 // "Structures": { 172 // "test.doc": { 173 // "Comment": "comment 1\ncomment 2", 174 // "Kind": "CDoc", 175 // "Fields": [ 176 // { 177 // "Name": "sys.QName", 178 // "Data": "sys.QName", 179 // "Required": true 180 // }, 181 // { 182 // "Name": "sys.ID", 183 // "Data": "sys.RecordID", 184 // "Required": true 185 // }, 186 // { 187 // "Name": "sys.IsActive", 188 // "Data": "sys.bool" 189 // }, 190 // { 191 // "Comment": "field comment", 192 // "Name": "f1", 193 // "Data": "sys.int64", 194 // "Required": true 195 // }, 196 // { 197 // "Name": "f2", 198 // "DataType": { 199 // "Ancestor": "sys.string", 200 // "Constraints": { 201 // "MaxLen": 4, 202 // "MinLen": 4, 203 // "Pattern": "^\\w+$" 204 // } 205 // } 206 // }, 207 // { 208 // "Name": "numField", 209 // "Data": "test.number" 210 // }, 211 // { 212 // "Name": "mainChild", 213 // "Data": "sys.RecordID", 214 // "Refs": [ 215 // "test.rec" 216 // ] 217 // } 218 // ], 219 // "Containers": [ 220 // { 221 // "Comment": "container comment", 222 // "Name": "rec", 223 // "Type": "test.rec", 224 // "MinOccurs": 0, 225 // "MaxOccurs": 100 226 // } 227 // ], 228 // "Uniques": { 229 // "test.doc$uniques$unique1": { 230 // "Fields": [ 231 // "f1", 232 // "f2" 233 // ] 234 // } 235 // }, 236 // "Singleton": true 237 // }, 238 // "test.obj": { 239 // "Kind": "Object", 240 // "Fields": [ 241 // { 242 // "Name": "sys.QName", 243 // "Data": "sys.QName", 244 // "Required": true 245 // }, 246 // { 247 // "Name": "sys.Container", 248 // "Data": "sys.string" 249 // }, 250 // { 251 // "Name": "f1", 252 // "Data": "sys.string", 253 // "Required": true 254 // } 255 // ] 256 // }, 257 // "test.rec": { 258 // "Kind": "CRecord", 259 // "Fields": [ 260 // { 261 // "Name": "sys.QName", 262 // "Data": "sys.QName", 263 // "Required": true 264 // }, 265 // { 266 // "Name": "sys.ID", 267 // "Data": "sys.RecordID", 268 // "Required": true 269 // }, 270 // { 271 // "Name": "sys.ParentID", 272 // "Data": "sys.RecordID", 273 // "Required": true 274 // }, 275 // { 276 // "Name": "sys.Container", 277 // "Data": "sys.string", 278 // "Required": true 279 // }, 280 // { 281 // "Name": "sys.IsActive", 282 // "Data": "sys.bool" 283 // }, 284 // { 285 // "Name": "f1", 286 // "Data": "sys.int64", 287 // "Required": true 288 // }, 289 // { 290 // "Name": "f2", 291 // "Data": "sys.string" 292 // }, 293 // { 294 // "Name": "phone", 295 // "DataType": { 296 // "Ancestor": "sys.string", 297 // "Constraints": { 298 // "MaxLen": 25, 299 // "MinLen": 1 300 // } 301 // }, 302 // "Required": true, 303 // "Verifiable": true 304 // } 305 // ], 306 // "Uniques": { 307 // "test.rec$uniques$uniq1": { 308 // "Fields": [ 309 // "f1" 310 // ] 311 // } 312 // }, 313 // "UniqueField": "phone" 314 // } 315 // }, 316 // "Views": { 317 // "test.view": { 318 // "Key": { 319 // "Partition": [ 320 // { 321 // "Name": "pk_1", 322 // "Data": "sys.int64", 323 // "Required": true 324 // } 325 // ], 326 // "ClustCols": [ 327 // { 328 // "Name": "cc_1", 329 // "DataType": { 330 // "Ancestor": "sys.string", 331 // "Constraints": { 332 // "MaxLen": 100 333 // } 334 // } 335 // } 336 // ] 337 // }, 338 // "Value": [ 339 // { 340 // "Name": "sys.QName", 341 // "Data": "sys.QName", 342 // "Required": true 343 // }, 344 // { 345 // "Name": "vv_code", 346 // "Data": "test.string", 347 // "Required": true 348 // }, 349 // { 350 // "Name": "vv_1", 351 // "Data": "sys.RecordID", 352 // "Required": true, 353 // "Refs": [ 354 // "test.doc" 355 // ] 356 // } 357 // ] 358 // } 359 // }, 360 // "Extensions": { 361 // "Commands": { 362 // "test.cmd": { 363 // "Name": "cmd", 364 // "Engine": "WASM", 365 // "Arg": "test.obj", 366 // "UnloggedArg": "test.obj" 367 // } 368 // }, 369 // "Queries": { 370 // "test.query": { 371 // "Name": "query", 372 // "Engine": "BuiltIn", 373 // "Arg": "test.obj", 374 // "Result": "sys.ANY" 375 // } 376 // }, 377 // "Projectors": { 378 // "test.projector": { 379 // "Name": "projector", 380 // "Engine": "WASM", 381 // "Events": { 382 // "test.cmd": { 383 // "Comment": "run projector every time when «test.cmd» command is executed", 384 // "Kind": [ 385 // "Execute" 386 // ] 387 // }, 388 // "test.obj": { 389 // "Comment": "run projector every time when any command with «test.obj» argument is executed", 390 // "Kind": [ 391 // "ExecuteWithParam" 392 // ] 393 // }, 394 // "test.rec": { 395 // "Comment": "run projector every time when «test.rec» is changed", 396 // "Kind": [ 397 // "Insert", 398 // "Update", 399 // "Activate", 400 // "Deactivate" 401 // ] 402 // } 403 // }, 404 // "WantErrors": true, 405 // "States": { 406 // "sys.records": [ 407 // "test.doc", 408 // "test.rec" 409 // ] 410 // }, 411 // "Intents": { 412 // "sys.views": [ 413 // "test.view" 414 // ] 415 // } 416 // } 417 // } 418 // }, 419 // "Roles": { 420 // "test.reader": { 421 // "Comment": "read-only role", 422 // "Privileges": [ 423 // { 424 // "Comment": "allow reader to select some fields from test.doc and test.rec", 425 // "Access": "grant", 426 // "Kinds": [ 427 // "Select" 428 // ], 429 // "On": [ 430 // "test.doc", 431 // "test.rec" 432 // ], 433 // "Fields": [ 434 // "f1", 435 // "f2" 436 // ] 437 // }, 438 // { 439 // "Comment": "allow reader to select all fields from test.view", 440 // "Access": "grant", 441 // "Kinds": [ 442 // "Select" 443 // ], 444 // "On": [ 445 // "test.view" 446 // ] 447 // }, 448 // { 449 // "Comment": "allow reader to execute test.query", 450 // "Access": "grant", 451 // "Kinds": [ 452 // "Execute" 453 // ], 454 // "On": [ 455 // "test.query" 456 // ] 457 // } 458 // ] 459 // }, 460 // "test.writer": { 461 // "Comment": "read-write role", 462 // "Privileges": [ 463 // { 464 // "Comment": "allow writer to do anything with test.doc, test.rec and test.view", 465 // "Access": "grant", 466 // "Kinds": [ 467 // "Insert", 468 // "Update", 469 // "Select" 470 // ], 471 // "On": [ 472 // "test.doc", 473 // "test.rec", 474 // "test.view" 475 // ] 476 // }, 477 // { 478 // "Comment": "disable writer to update test.doc", 479 // "Access": "revoke", 480 // "Kinds": [ 481 // "Update" 482 // ], 483 // "On": [ 484 // "test.doc" 485 // ] 486 // }, 487 // { 488 // "Comment": "allow writer to execute all test functions", 489 // "Access": "grant", 490 // "Kinds": [ 491 // "Execute" 492 // ], 493 // "On": [ 494 // "test.cmd", 495 // "test.query" 496 // ] 497 // } 498 // ] 499 // } 500 // } 501 // } 502 // } 503 // } 504 } 505 506 type mockedAppStructs struct { 507 istructs.IAppStructs 508 mock.Mock 509 } 510 511 func (s *mockedAppStructs) AppDef() appdef.IAppDef { 512 return s.Called().Get(0).(appdef.IAppDef) 513 } 514 515 func (s *mockedAppStructs) AppQName() istructs.AppQName { 516 return s.Called().Get(0).(istructs.AppQName) 517 } 518 519 func (s *mockedAppStructs) Resources() istructs.IResources { 520 return s.Called().Get(0).(istructs.IResources) 521 } 522 523 type mockResources struct { 524 istructs.IResources 525 mock.Mock 526 } 527 528 func (r *mockResources) Resources(cb func(appdef.QName)) { 529 r.Called(cb) 530 }