From 864bbe7e12e4e8c34ef6676e5ec2ddacbdb05db8 Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Mon, 21 Aug 2023 12:58:18 +0300 Subject: [PATCH] added SchemaField.Presentable field --- apis/collection_test.go | 87 +-------------------------- daos/record_table_sync.go | 49 --------------- forms/collection_upsert.go | 22 ------- forms/collection_upsert_test.go | 21 +------ models/schema/schema_field.go | 7 ++- models/schema/schema_field_test.go | 74 +++++++++++------------ models/schema/schema_test.go | 14 ++--- plugins/migratecmd/migratecmd_test.go | 8 +++ 8 files changed, 61 insertions(+), 221 deletions(-) diff --git a/apis/collection_test.go b/apis/collection_test.go index 7b15df7d..936f29be 100644 --- a/apis/collection_test.go +++ b/apis/collection_test.go @@ -12,7 +12,6 @@ import ( "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/models" - "github.com/pocketbase/pocketbase/models/schema" "github.com/pocketbase/pocketbase/tests" "github.com/pocketbase/pocketbase/tools/list" ) @@ -401,7 +400,7 @@ func TestCollectionCreate(t *testing.T) { `"name":"new"`, `"type":"base"`, `"system":false`, - `"schema":[{"system":false,"id":"12345789","name":"test","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}]`, + `"schema":[{"system":false,"id":"12345789","name":"test","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}]`, `"options":{}`, }, ExpectedEvents: map[string]int{ @@ -425,7 +424,7 @@ func TestCollectionCreate(t *testing.T) { `"name":"new"`, `"type":"auth"`, `"system":false`, - `"schema":[{"system":false,"id":"12345789","name":"test","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}]`, + `"schema":[{"system":false,"id":"12345789","name":"test","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}]`, `"options":{"allowEmailAuth":false,"allowOAuth2Auth":false,"allowUsernameAuth":false,"exceptEmailDomains":null,"manageRule":null,"minPasswordLength":0,"onlyEmailDomains":null,"requireEmail":false}`, }, ExpectedEvents: map[string]int{ @@ -960,88 +959,6 @@ func TestCollectionUpdate(t *testing.T) { }, }, - // rel field change displayFields propagation - // ----------------------------------------------------------- - { - Name: "renaming a display field should also update the referenced displayFields value", - Method: http.MethodPatch, - Url: "/api/collections/demo3", - Body: strings.NewReader(`{ - "schema":[ - { - "id": "w5z2x0nq", - "type": "text", - "name": "title_change" - } - ] - }`), - RequestHeaders: map[string]string{ - "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8", - }, - ExpectedStatus: 200, - ExpectedContent: []string{ - `"name":"title_change"`, - }, - ExpectedEvents: map[string]int{ - "OnModelBeforeUpdate": 2, - "OnModelAfterUpdate": 2, - "OnCollectionBeforeUpdateRequest": 1, - "OnCollectionAfterUpdateRequest": 1, - }, - AfterTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) { - collection, err := app.Dao().FindCollectionByNameOrId("demo4") - if err != nil { - t.Fatal(err) - } - - relField := collection.Schema.GetFieldByName("rel_many_no_cascade_required") - options := relField.Options.(*schema.RelationOptions) - expectedDisplayFields := []string{"title_change", "id"} - if len(list.SubtractSlice(options.DisplayFields, expectedDisplayFields)) != 0 { - t.Fatalf("Expected displayFields %v, got %v", expectedDisplayFields, options.DisplayFields) - } - }, - }, - { - Name: "deleting a display field should also update the referenced displayFields value", - Method: http.MethodPatch, - Url: "/api/collections/demo3", - Body: strings.NewReader(`{ - "schema":[ - { - "type": "text", - "name": "new_field" - } - ] - }`), - RequestHeaders: map[string]string{ - "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8", - }, - ExpectedStatus: 200, - ExpectedContent: []string{ - `"name":"new_field"`, - }, - ExpectedEvents: map[string]int{ - "OnModelBeforeUpdate": 2, - "OnModelAfterUpdate": 2, - "OnCollectionBeforeUpdateRequest": 1, - "OnCollectionAfterUpdateRequest": 1, - }, - AfterTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) { - collection, err := app.Dao().FindCollectionByNameOrId("demo4") - if err != nil { - t.Fatal(err) - } - - relField := collection.Schema.GetFieldByName("rel_many_no_cascade_required") - options := relField.Options.(*schema.RelationOptions) - expectedDisplayFields := []string{"id"} - if len(list.SubtractSlice(options.DisplayFields, expectedDisplayFields)) != 0 { - t.Fatalf("Expected displayFields %v, got %v", expectedDisplayFields, options.DisplayFields) - } - }, - }, - // view // ----------------------------------------------------------- { diff --git a/daos/record_table_sync.go b/daos/record_table_sync.go index 04512f01..c853fa24 100644 --- a/daos/record_table_sync.go +++ b/daos/record_table_sync.go @@ -10,7 +10,6 @@ import ( "github.com/pocketbase/pocketbase/models" "github.com/pocketbase/pocketbase/models/schema" "github.com/pocketbase/pocketbase/tools/dbutils" - "github.com/pocketbase/pocketbase/tools/list" "github.com/pocketbase/pocketbase/tools/security" ) @@ -159,10 +158,6 @@ func (dao *Dao) SyncRecordTableSchema(newCollection *models.Collection, oldColle return err } - if err := txDao.syncRelationDisplayFieldsChanges(newCollection, renamedFieldNames, deletedFieldNames); err != nil { - return err - } - return txDao.createCollectionIndexes(newCollection) }) } @@ -294,50 +289,6 @@ func (dao *Dao) normalizeSingleVsMultipleFieldChanges(newCollection, oldCollecti }) } -func (dao *Dao) syncRelationDisplayFieldsChanges(collection *models.Collection, renamedFieldNames map[string]string, deletedFieldNames []string) error { - if len(renamedFieldNames) == 0 && len(deletedFieldNames) == 0 { - return nil // nothing to sync - } - - refs, err := dao.FindCollectionReferences(collection) - if err != nil { - return err - } - - for refCollection, refFields := range refs { - for _, refField := range refFields { - options, _ := refField.Options.(*schema.RelationOptions) - if options == nil { - continue - } - - // remove deleted (if any) - newDisplayFields := list.SubtractSlice(options.DisplayFields, deletedFieldNames) - - for old, new := range renamedFieldNames { - for i, name := range newDisplayFields { - if name == old { - newDisplayFields[i] = new - } - } - } - - // has changes - if len(list.SubtractSlice(options.DisplayFields, newDisplayFields)) > 0 { - options.DisplayFields = newDisplayFields - - // direct collection save to prevent self-referencing - // recursion and unnecessary records table sync checks - if err := dao.Save(refCollection); err != nil { - return err - } - } - } - } - - return nil -} - func (dao *Dao) dropCollectionIndex(collection *models.Collection) error { if collection.IsView() { return nil // views don't have indexes diff --git a/forms/collection_upsert.go b/forms/collection_upsert.go index ca1db1fc..27bc8bfa 100644 --- a/forms/collection_upsert.go +++ b/forms/collection_upsert.go @@ -229,14 +229,6 @@ func (form *CollectionUpsert) ensureNoFieldsTypeChange(value any) error { func (form *CollectionUpsert) checkRelationFields(value any) error { v, _ := value.(schema.Schema) - systemDisplayFields := schema.BaseModelFieldNames() - systemDisplayFields = append(systemDisplayFields, - schema.FieldNameUsername, - schema.FieldNameEmail, - schema.FieldNameEmailVisibility, - schema.FieldNameVerified, - ) - for i, field := range v.Fields() { if field.Type != schema.FieldTypeRelation { continue @@ -294,20 +286,6 @@ func (form *CollectionUpsert) checkRelationFields(value any) error { }}, } } - - // validate displayFields (if any) - for _, name := range options.DisplayFields { - if relCollection.Schema.GetFieldByName(name) == nil && !list.ExistInSlice(name, systemDisplayFields) { - return validation.Errors{fmt.Sprint(i): validation.Errors{ - "options": validation.Errors{ - "displayFields": validation.NewError( - "validation_field_invalid_relation_displayFields", - fmt.Sprintf("%q does not exist in the related %q collection.", name, relCollection.Name), - ), - }}, - } - } - } } return nil diff --git a/forms/collection_upsert_test.go b/forms/collection_upsert_test.go index 305c21b7..e9f6a9ae 100644 --- a/forms/collection_upsert_test.go +++ b/forms/collection_upsert_test.go @@ -171,25 +171,6 @@ func TestCollectionUpsertValidateAndSubmit(t *testing.T) { }`, []string{"schema"}, }, - { - "create failure - missing relation display field", - "", - `{ - "name": "test_new", - "type": "base", - "schema": [ - { - "name":"test", - "type":"relation", - "options":{ - "collectionId":"wsmn24bux7wo113", - "displayFields":["text", "missing"] - } - } - ] - }`, - []string{"schema"}, - }, { "create failure - check auth options validators", "", @@ -605,7 +586,7 @@ func TestCollectionUpsertValidateAndSubmit(t *testing.T) { } if form.Name != collection.Name { - t.Errorf("Expected Name %q, got %q", collection.Name, form.Name) + t.Fatalf("Expected Name %q, got %q", collection.Name, form.Name) } if form.Type != collection.Type { diff --git a/models/schema/schema_field.go b/models/schema/schema_field.go index bcc7b940..47318331 100644 --- a/models/schema/schema_field.go +++ b/models/schema/schema_field.go @@ -132,6 +132,10 @@ type SchemaField struct { Type string `form:"type" json:"type"` Required bool `form:"required" json:"required"` + // Presentable indicates whether the field is suitable for + // visualization purposes (eg. in the Admin UI relation views). + Presentable bool `form:"presentable" json:"presentable"` + // Deprecated: This field is no-op and will be removed in future versions. // Please use the collection.Indexes field to define a unique constraint. Unique bool `form:"unique" json:"unique"` @@ -645,7 +649,8 @@ type RelationOptions struct { // If nil no limits are applied. MaxSelect *int `form:"maxSelect" json:"maxSelect"` - // DisplayFields is optional slice of collection field names used for UI purposes. + // Deprecated: This field is no-op and will be removed in future versions. + // Instead use the individula SchemaField.Presentable option for each field in the relation collection. DisplayFields []string `form:"displayFields" json:"displayFields"` } diff --git a/models/schema/schema_field_test.go b/models/schema/schema_field_test.go index 12c48ce7..eb8a67b5 100644 --- a/models/schema/schema_field_test.go +++ b/models/schema/schema_field_test.go @@ -129,19 +129,19 @@ func TestSchemaFieldColDefinition(t *testing.T) { func TestSchemaFieldString(t *testing.T) { f := schema.SchemaField{ - Id: "abc", - Name: "test", - Type: schema.FieldTypeText, - Required: true, - Unique: false, - System: true, + Id: "abc", + Name: "test", + Type: schema.FieldTypeText, + Required: true, + Presentable: true, + System: true, Options: &schema.TextOptions{ Pattern: "test", }, } result := f.String() - expected := `{"system":true,"id":"abc","name":"test","type":"text","required":true,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}` + expected := `{"system":true,"id":"abc","name":"test","type":"text","required":true,"presentable":true,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}` if result != expected { t.Errorf("Expected \n%v, got \n%v", expected, result) @@ -156,19 +156,19 @@ func TestSchemaFieldMarshalJSON(t *testing.T) { // empty { schema.SchemaField{}, - `{"system":false,"id":"","name":"","type":"","required":false,"unique":false,"options":null}`, + `{"system":false,"id":"","name":"","type":"","required":false,"presentable":false,"unique":false,"options":null}`, }, // without defined options { schema.SchemaField{ - Id: "abc", - Name: "test", - Type: schema.FieldTypeText, - Required: true, - Unique: false, - System: true, + Id: "abc", + Name: "test", + Type: schema.FieldTypeText, + Required: true, + Presentable: true, + System: true, }, - `{"system":true,"id":"abc","name":"test","type":"text","required":true,"unique":false,"options":{"min":null,"max":null,"pattern":""}}`, + `{"system":true,"id":"abc","name":"test","type":"text","required":true,"presentable":true,"unique":false,"options":{"min":null,"max":null,"pattern":""}}`, }, // with defined options { @@ -182,7 +182,7 @@ func TestSchemaFieldMarshalJSON(t *testing.T) { Pattern: "test", }, }, - `{"system":true,"id":"","name":"test","type":"text","required":true,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}`, + `{"system":true,"id":"","name":"test","type":"text","required":true,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}`, }, } @@ -207,32 +207,32 @@ func TestSchemaFieldUnmarshalJSON(t *testing.T) { { nil, true, - `{"system":false,"id":"","name":"","type":"","required":false,"unique":false,"options":null}`, + `{"system":false,"id":"","name":"","type":"","required":false,"presentable":false,"unique":false,"options":null}`, }, { []byte{}, true, - `{"system":false,"id":"","name":"","type":"","required":false,"unique":false,"options":null}`, + `{"system":false,"id":"","name":"","type":"","required":false,"presentable":false,"unique":false,"options":null}`, }, { []byte(`{"system": true}`), true, - `{"system":true,"id":"","name":"","type":"","required":false,"unique":false,"options":null}`, + `{"system":true,"id":"","name":"","type":"","required":false,"presentable":false,"unique":false,"options":null}`, }, { []byte(`{"invalid"`), true, - `{"system":false,"id":"","name":"","type":"","required":false,"unique":false,"options":null}`, + `{"system":false,"id":"","name":"","type":"","required":false,"presentable":false,"unique":false,"options":null}`, }, { []byte(`{"type":"text","system":true}`), false, - `{"system":true,"id":"","name":"","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}`, + `{"system":true,"id":"","name":"","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}`, }, { []byte(`{"type":"text","options":{"pattern":"test"}}`), false, - `{"system":false,"id":"","name":"","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}`, + `{"system":false,"id":"","name":"","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}`, }, } @@ -470,72 +470,72 @@ func TestSchemaFieldInitOptions(t *testing.T) { { schema.SchemaField{}, true, - `{"system":false,"id":"","name":"","type":"","required":false,"unique":false,"options":null}`, + `{"system":false,"id":"","name":"","type":"","required":false,"presentable":false,"unique":false,"options":null}`, }, { schema.SchemaField{Type: "unknown"}, true, - `{"system":false,"id":"","name":"","type":"unknown","required":false,"unique":false,"options":null}`, + `{"system":false,"id":"","name":"","type":"unknown","required":false,"presentable":false,"unique":false,"options":null}`, }, { schema.SchemaField{Type: schema.FieldTypeText}, false, - `{"system":false,"id":"","name":"","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}`, + `{"system":false,"id":"","name":"","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}`, }, { schema.SchemaField{Type: schema.FieldTypeNumber}, false, - `{"system":false,"id":"","name":"","type":"number","required":false,"unique":false,"options":{"min":null,"max":null}}`, + `{"system":false,"id":"","name":"","type":"number","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null}}`, }, { schema.SchemaField{Type: schema.FieldTypeBool}, false, - `{"system":false,"id":"","name":"","type":"bool","required":false,"unique":false,"options":{}}`, + `{"system":false,"id":"","name":"","type":"bool","required":false,"presentable":false,"unique":false,"options":{}}`, }, { schema.SchemaField{Type: schema.FieldTypeEmail}, false, - `{"system":false,"id":"","name":"","type":"email","required":false,"unique":false,"options":{"exceptDomains":null,"onlyDomains":null}}`, + `{"system":false,"id":"","name":"","type":"email","required":false,"presentable":false,"unique":false,"options":{"exceptDomains":null,"onlyDomains":null}}`, }, { schema.SchemaField{Type: schema.FieldTypeUrl}, false, - `{"system":false,"id":"","name":"","type":"url","required":false,"unique":false,"options":{"exceptDomains":null,"onlyDomains":null}}`, + `{"system":false,"id":"","name":"","type":"url","required":false,"presentable":false,"unique":false,"options":{"exceptDomains":null,"onlyDomains":null}}`, }, { schema.SchemaField{Type: schema.FieldTypeEditor}, false, - `{"system":false,"id":"","name":"","type":"editor","required":false,"unique":false,"options":{}}`, + `{"system":false,"id":"","name":"","type":"editor","required":false,"presentable":false,"unique":false,"options":{}}`, }, { schema.SchemaField{Type: schema.FieldTypeDate}, false, - `{"system":false,"id":"","name":"","type":"date","required":false,"unique":false,"options":{"min":"","max":""}}`, + `{"system":false,"id":"","name":"","type":"date","required":false,"presentable":false,"unique":false,"options":{"min":"","max":""}}`, }, { schema.SchemaField{Type: schema.FieldTypeSelect}, false, - `{"system":false,"id":"","name":"","type":"select","required":false,"unique":false,"options":{"maxSelect":0,"values":null}}`, + `{"system":false,"id":"","name":"","type":"select","required":false,"presentable":false,"unique":false,"options":{"maxSelect":0,"values":null}}`, }, { schema.SchemaField{Type: schema.FieldTypeJson}, false, - `{"system":false,"id":"","name":"","type":"json","required":false,"unique":false,"options":{}}`, + `{"system":false,"id":"","name":"","type":"json","required":false,"presentable":false,"unique":false,"options":{}}`, }, { schema.SchemaField{Type: schema.FieldTypeFile}, false, - `{"system":false,"id":"","name":"","type":"file","required":false,"unique":false,"options":{"maxSelect":0,"maxSize":0,"mimeTypes":null,"thumbs":null,"protected":false}}`, + `{"system":false,"id":"","name":"","type":"file","required":false,"presentable":false,"unique":false,"options":{"maxSelect":0,"maxSize":0,"mimeTypes":null,"thumbs":null,"protected":false}}`, }, { schema.SchemaField{Type: schema.FieldTypeRelation}, false, - `{"system":false,"id":"","name":"","type":"relation","required":false,"unique":false,"options":{"collectionId":"","cascadeDelete":false,"minSelect":null,"maxSelect":null,"displayFields":null}}`, + `{"system":false,"id":"","name":"","type":"relation","required":false,"presentable":false,"unique":false,"options":{"collectionId":"","cascadeDelete":false,"minSelect":null,"maxSelect":null,"displayFields":null}}`, }, { schema.SchemaField{Type: schema.FieldTypeUser}, false, - `{"system":false,"id":"","name":"","type":"user","required":false,"unique":false,"options":{"maxSelect":0,"cascadeDelete":false}}`, + `{"system":false,"id":"","name":"","type":"user","required":false,"presentable":false,"unique":false,"options":{"maxSelect":0,"cascadeDelete":false}}`, }, { schema.SchemaField{ @@ -543,7 +543,7 @@ func TestSchemaFieldInitOptions(t *testing.T) { Options: &schema.TextOptions{Pattern: "test"}, }, false, - `{"system":false,"id":"","name":"","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}`, + `{"system":false,"id":"","name":"","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}`, }, } diff --git a/models/schema/schema_test.go b/models/schema/schema_test.go index 7642a79a..7ff4afac 100644 --- a/models/schema/schema_test.go +++ b/models/schema/schema_test.go @@ -286,7 +286,7 @@ func TestSchemaMarshalJSON(t *testing.T) { t.Fatal(err) } - expected := `[{"system":false,"id":"f1id","name":"test1","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}},{"system":false,"id":"f2id","name":"test2","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}]` + expected := `[{"system":false,"id":"f1id","name":"test1","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}},{"system":false,"id":"f2id","name":"test2","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}]` if string(result) != expected { t.Fatalf("Expected %s, got %s", expected, string(result)) @@ -354,7 +354,7 @@ func TestSchemaValue(t *testing.T) { if err != nil { t.Fatal(err) } - expected := `[{"system":false,"id":"f1id","name":"test1","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}]` + expected := `[{"system":false,"id":"f1id","name":"test1","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}]` if v2 != expected { t.Fatalf("Expected %v, got %v", expected, v2) @@ -377,21 +377,21 @@ func TestSchemaScan(t *testing.T) { {`[{}]`, true, `[]`}, // unknown field type { - `[{"system":false,"id":"123","name":"test1","type":"unknown","required":false,"unique":false}]`, + `[{"system":false,"id":"123","name":"test1","type":"unknown","required":false,"presentable":false,"unique":false}]`, true, `[]`, }, // without options { - `[{"system":false,"id":"123","name":"test1","type":"text","required":false,"unique":false}]`, + `[{"system":false,"id":"123","name":"test1","type":"text","required":false,"presentable":false,"unique":false}]`, false, - `[{"system":false,"id":"123","name":"test1","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}]`, + `[{"system":false,"id":"123","name":"test1","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}}]`, }, // with options { - `[{"system":false,"id":"123","name":"test1","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}]`, + `[{"system":false,"id":"123","name":"test1","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}]`, false, - `[{"system":false,"id":"123","name":"test1","type":"text","required":false,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}]`, + `[{"system":false,"id":"123","name":"test1","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":"test"}}]`, }, } diff --git a/plugins/migratecmd/migratecmd_test.go b/plugins/migratecmd/migratecmd_test.go index d397fd4f..870becc5 100644 --- a/plugins/migratecmd/migratecmd_test.go +++ b/plugins/migratecmd/migratecmd_test.go @@ -398,6 +398,7 @@ migrate((db) => { "name": "f4_name", "type": "text", "required": false, + "presentable": false, "unique": false, "options": { "min": null, @@ -413,6 +414,7 @@ migrate((db) => { "name": "f2_name_new", "type": "number", "required": false, + "presentable": false, "unique": true, "options": { "min": 10, @@ -450,6 +452,7 @@ migrate((db) => { "name": "f3_name", "type": "bool", "required": false, + "presentable": false, "unique": false, "options": {} })) @@ -464,6 +467,7 @@ migrate((db) => { "name": "f2_name", "type": "number", "required": false, + "presentable": false, "unique": true, "options": { "min": 10, @@ -526,6 +530,7 @@ func init() { "name": "f4_name", "type": "text", "required": false, + "presentable": false, "unique": false, "options": { "min": null, @@ -543,6 +548,7 @@ func init() { "name": "f2_name_new", "type": "number", "required": false, + "presentable": false, "unique": true, "options": { "min": 10, @@ -593,6 +599,7 @@ func init() { "name": "f3_name", "type": "bool", "required": false, + "presentable": false, "unique": false, "options": {} }` + "`" + `), del_f3_name) @@ -609,6 +616,7 @@ func init() { "name": "f2_name", "type": "number", "required": false, + "presentable": false, "unique": true, "options": { "min": 10,