From 1bf15e5ce02485bd1e370d1037e191c3b5551e88 Mon Sep 17 00:00:00 2001 From: Mathias Date: Mon, 23 May 2022 17:41:49 +0200 Subject: [PATCH 01/11] Fixed Client.Call; added CreateStringAttribute --- client.go | 96 +++++++++++++++++++++++++++++----------------- database.go | 108 +++++++++++++++++++++++++++++++++------------------- main.go | 4 +- users.go | 33 +++++++--------- utils.go | 4 ++ 5 files changed, 152 insertions(+), 93 deletions(-) diff --git a/client.go b/client.go index 36fb2f2..f8a809f 100644 --- a/client.go +++ b/client.go @@ -2,9 +2,8 @@ package appwrite import ( "encoding/json" - "io/ioutil" + "io/ioutil" "net/http" - "net/url" "strings" ) @@ -61,57 +60,86 @@ func (clt *Client) Call(method string, path string, headers map[string]interface } urlPath := clt.endpoint + path - isGet := strings.ToUpper(method) == "GET" - var reqBody *strings.Reader - if !isGet { - frm := url.Values{} + var http_req *http.Request + var reqBody []byte + switch strings.ToUpper(method) { + case "GET": + + http_req, _ = http.NewRequest(strings.ToUpper(method), urlPath, strings.NewReader(string(reqBody))) + q := http_req.URL.Query() for key, val := range params { - frm.Add(key, ToString(val)) + q.Add(key, ToString(val)) } - reqBody = strings.NewReader(frm.Encode()) - } + http_req.URL.RawQuery = q.Encode() - // Create and modify HTTP request before sending - req, err := http.NewRequest(method, urlPath, reqBody) - if err != nil { - return nil, err + default: + reqBody, _ = json.Marshal(params) + http_req, _ = http.NewRequest(strings.ToUpper(method), urlPath, strings.NewReader(string(reqBody))) } - // Set Client headers + // set general headers for key, val := range clt.headers { - req.Header.Set(key, ToString(val)) + http_req.Header.Set(key, val) } - // Set Custom headers + // set specific headers for key, val := range headers { - req.Header.Set(key, ToString(val)) + http_req.Header.Set(key, ToString(val)) } - if isGet { - q := req.URL.Query() - for key, val := range params { - q.Add(key, ToString(val)) - } - req.URL.RawQuery = q.Encode() - } - - // Make request - response, err := clt.client.Do(req) + // submit the request + resp, err := clt.client.Do(http_req) if err != nil { return nil, err } + defer resp.Body.Close() - // Handle response - defer response.Body.Close() - - responseData, err := ioutil.ReadAll(response.Body) + // read the response data + respData, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } + var jsonResp map[string]interface{} + json.Unmarshal(respData, &jsonResp) + return jsonResp, nil - var jsonResponse map[string]interface{} - json.Unmarshal(responseData, &jsonResponse) + /* + urlPath := clt.endpoint + path + isGet := strings.ToUpper(method) == "GET" - return jsonResponse, nil + var _reqBody []byte + if !isGet { + jsonOb, _ := json.Marshal(params) + _reqBody = (jsonOb) + + } + fmt.Println(string(_reqBody)) + reqBody := strings.NewReader(string(_reqBody)) + + // Create and modify HTTP request before sending + req, err := http.NewRequest(method, urlPath, reqBody) + if err != nil { + return nil, err + } + + // Set Client headers + for key, val := range clt.headers { + req.Header.Set(key, val) + } + + // Set Custom headers + for key, val := range headers { + req.Header.Set(key, ToString(val)) + } + + if isGet { + q := req.URL.Query() + for key, val := range params { + q.Add(key, ToString(val)) + } + req.URL.RawQuery = q.Encode() + } + */ + // Make request } diff --git a/database.go b/database.go index 7e5f686..b0238c4 100644 --- a/database.go +++ b/database.go @@ -9,12 +9,12 @@ type Database struct { client Client } -func NewDatabase(clt Client) Database { - service := Database{ +func NewDatabase(clt Client) Database { + service := Database{ client: clt, } - return service + return service } // ListCollections get a list of all the user collections. You can use the @@ -25,27 +25,36 @@ func (srv *Database) ListCollections(Search string, Limit int, Offset int, Order path := "/database/collections" params := map[string]interface{}{ - "search": Search, - "limit": Limit, - "offset": Offset, + "search": Search, + "limit": Limit, + "offset": Offset, "orderType": OrderType, } - return srv.client.Call("GET", path, nil, params) + header := map[string]interface{}{ + "content-type": "application/json", + } + + return srv.client.Call("GET", path, header, params) } // CreateCollection create a new Collection. -func (srv *Database) CreateCollection(Name string, Read []interface{}, Write []interface{}, Rules []interface{}) (map[string]interface{}, error) { +func (srv *Database) CreateCollection(CollectionId string, Name string, Permission string, Read []string, Write []string) (map[string]interface{}, error) { path := "/database/collections" params := map[string]interface{}{ - "name": Name, - "read": Read, - "write": Write, - "rules": Rules, + "collectionId": CollectionId, + "name": Name, + "read": Read, + "write": Write, + "permission": Permission, } - return srv.client.Call("POST", path, nil, params) + header := map[string]interface{}{ + "content-type": "application/json", + } + + return srv.client.Call("POST", path, header, params) } // GetCollection get collection by its unique ID. This endpoint response @@ -54,8 +63,7 @@ func (srv *Database) GetCollection(CollectionId string) (map[string]interface{}, r := strings.NewReplacer("{collectionId}", CollectionId) path := r.Replace("/database/collections/{collectionId}") - params := map[string]interface{}{ - } + params := map[string]interface{}{} return srv.client.Call("GET", path, nil, params) } @@ -66,8 +74,8 @@ func (srv *Database) UpdateCollection(CollectionId string, Name string, Read []i path := r.Replace("/database/collections/{collectionId}") params := map[string]interface{}{ - "name": Name, - "read": Read, + "name": Name, + "read": Read, "write": Write, "rules": Rules, } @@ -81,8 +89,7 @@ func (srv *Database) DeleteCollection(CollectionId string) (map[string]interface r := strings.NewReplacer("{collectionId}", CollectionId) path := r.Replace("/database/collections/{collectionId}") - params := map[string]interface{}{ - } + params := map[string]interface{}{} return srv.client.Call("DELETE", path, nil, params) } @@ -96,31 +103,31 @@ func (srv *Database) ListDocuments(CollectionId string, Filters []interface{}, O path := r.Replace("/database/collections/{collectionId}/documents") params := map[string]interface{}{ - "filters": Filters, - "offset": Offset, - "limit": Limit, + "filters": Filters, + "offset": Offset, + "limit": Limit, "order-field": OrderField, - "order-type": OrderType, - "order-cast": OrderCast, - "search": Search, - "first": First, - "last": Last, + "order-type": OrderType, + "order-cast": OrderCast, + "search": Search, + "first": First, + "last": Last, } return srv.client.Call("GET", path, nil, params) } // CreateDocument create a new Document. -func (srv *Database) CreateDocument(CollectionId string, Data object, Read []interface{}, Write []interface{}, ParentDocument string, ParentProperty string, ParentPropertyType string) (map[string]interface{}, error) { +func (srv *Database) CreateDocument(CollectionId string, Data interface{}, Read []interface{}, Write []interface{}, ParentDocument string, ParentProperty string, ParentPropertyType string) (map[string]interface{}, error) { r := strings.NewReplacer("{collectionId}", CollectionId) path := r.Replace("/database/collections/{collectionId}/documents") params := map[string]interface{}{ - "data": Data, - "read": Read, - "write": Write, - "parentDocument": ParentDocument, - "parentProperty": ParentProperty, + "data": Data, + "read": Read, + "write": Write, + "parentDocument": ParentDocument, + "parentProperty": ParentProperty, "parentPropertyType": ParentPropertyType, } @@ -133,20 +140,19 @@ func (srv *Database) GetDocument(CollectionId string, DocumentId string) (map[st r := strings.NewReplacer("{collectionId}", CollectionId, "{documentId}", DocumentId) path := r.Replace("/database/collections/{collectionId}/documents/{documentId}") - params := map[string]interface{}{ - } + params := map[string]interface{}{} return srv.client.Call("GET", path, nil, params) } // UpdateDocument -func (srv *Database) UpdateDocument(CollectionId string, DocumentId string, Data object, Read []interface{}, Write []interface{}) (map[string]interface{}, error) { +func (srv *Database) UpdateDocument(CollectionId string, DocumentId string, Data interface{}, Read []interface{}, Write []interface{}) (map[string]interface{}, error) { r := strings.NewReplacer("{collectionId}", CollectionId, "{documentId}", DocumentId) path := r.Replace("/database/collections/{collectionId}/documents/{documentId}") params := map[string]interface{}{ - "data": Data, - "read": Read, + "data": Data, + "read": Read, "write": Write, } @@ -160,8 +166,32 @@ func (srv *Database) DeleteDocument(CollectionId string, DocumentId string) (map r := strings.NewReplacer("{collectionId}", CollectionId, "{documentId}", DocumentId) path := r.Replace("/database/collections/{collectionId}/documents/{documentId}") + params := map[string]interface{}{} + + return srv.client.Call("DELETE", path, nil, params) +} + +func (srv *Database) CreateStringAttribute(CollectionId string, key string, size int, required bool, xdefault interface{}, isArray bool) (map[string]interface{}, error) { + Type := "string" + + path := "/database/collections/{collectionId}/attributes/{type}" + r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) + path = r.Replace(path) + params := map[string]interface{}{ + "key": key, + "required": required, + "size": size, + "array": isArray, } - return srv.client.Call("DELETE", path, nil, params) + if xdefault != nil { + params["default"] = xdefault + } + + headers := map[string]interface{}{ + "content-type": "application/json", + } + return srv.client.Call("POST", path, headers, params) + } diff --git a/main.go b/main.go index 13df7fc..1c415fb 100644 --- a/main.go +++ b/main.go @@ -2,5 +2,7 @@ package appwrite // NewClient initializes a new Appwrite client func NewClient() Client { - return Client{} + clt := Client{} + clt.headers = make(map[string]string) + return clt } diff --git a/users.go b/users.go index dc1b6be..4d148c6 100644 --- a/users.go +++ b/users.go @@ -9,12 +9,12 @@ type Users struct { client Client } -func NewUsers(clt Client) Users { - service := Users{ +func NewUsers(clt Client) Users { + service := Users{ client: clt, } - return service + return service } // List get a list of all the project users. You can use the query params to @@ -23,9 +23,9 @@ func (srv *Users) List(Search string, Limit int, Offset int, OrderType string) ( path := "/users" params := map[string]interface{}{ - "search": Search, - "limit": Limit, - "offset": Offset, + "search": Search, + "limit": Limit, + "offset": Offset, "orderType": OrderType, } @@ -37,9 +37,9 @@ func (srv *Users) Create(Email string, Password string, Name string) (map[string path := "/users" params := map[string]interface{}{ - "email": Email, + "email": Email, "password": Password, - "name": Name, + "name": Name, } return srv.client.Call("POST", path, nil, params) @@ -50,8 +50,7 @@ func (srv *Users) Get(UserId string) (map[string]interface{}, error) { r := strings.NewReplacer("{userId}", UserId) path := r.Replace("/users/{userId}") - params := map[string]interface{}{ - } + params := map[string]interface{}{} return srv.client.Call("GET", path, nil, params) } @@ -61,8 +60,7 @@ func (srv *Users) GetLogs(UserId string) (map[string]interface{}, error) { r := strings.NewReplacer("{userId}", UserId) path := r.Replace("/users/{userId}/logs") - params := map[string]interface{}{ - } + params := map[string]interface{}{} return srv.client.Call("GET", path, nil, params) } @@ -72,15 +70,14 @@ func (srv *Users) GetPrefs(UserId string) (map[string]interface{}, error) { r := strings.NewReplacer("{userId}", UserId) path := r.Replace("/users/{userId}/prefs") - params := map[string]interface{}{ - } + params := map[string]interface{}{} return srv.client.Call("GET", path, nil, params) } // UpdatePrefs update user preferences by its unique ID. You can pass only the // specific settings you wish to update. -func (srv *Users) UpdatePrefs(UserId string, Prefs object) (map[string]interface{}, error) { +func (srv *Users) UpdatePrefs(UserId string, Prefs []interface{}) (map[string]interface{}, error) { r := strings.NewReplacer("{userId}", UserId) path := r.Replace("/users/{userId}/prefs") @@ -96,8 +93,7 @@ func (srv *Users) GetSessions(UserId string) (map[string]interface{}, error) { r := strings.NewReplacer("{userId}", UserId) path := r.Replace("/users/{userId}/sessions") - params := map[string]interface{}{ - } + params := map[string]interface{}{} return srv.client.Call("GET", path, nil, params) } @@ -107,8 +103,7 @@ func (srv *Users) DeleteSessions(UserId string) (map[string]interface{}, error) r := strings.NewReplacer("{userId}", UserId) path := r.Replace("/users/{userId}/sessions") - params := map[string]interface{}{ - } + params := map[string]interface{}{} return srv.client.Call("DELETE", path, nil, params) } diff --git a/utils.go b/utils.go index ca36149..5e952b2 100644 --- a/utils.go +++ b/utils.go @@ -4,6 +4,7 @@ import ( "fmt" "reflect" "strconv" + "strings" ) // ToString changes arg to string @@ -28,6 +29,9 @@ func ToString(arg interface{}) string { return strconv.FormatFloat(v, 'f', -1, 64) case fmt.Stringer: return v.String() + case []string: + joined_string := strings.Join(v, `","`) + return "[" + joined_string + "]" case reflect.Value: return ToString(v.Interface()) default: From c5a97efc5b5823fe83093faad2bc45096e123ef2 Mon Sep 17 00:00:00 2001 From: Mathias Date: Mon, 23 May 2022 17:53:50 +0200 Subject: [PATCH 02/11] removed commented out code --- client.go | 52 ++++++---------------------------------------------- 1 file changed, 6 insertions(+), 46 deletions(-) diff --git a/client.go b/client.go index f8a809f..369f439 100644 --- a/client.go +++ b/client.go @@ -59,31 +59,30 @@ func (clt *Client) Call(method string, path string, headers map[string]interface // Allow self signed requests } + isGet := strings.ToUpper(method) == "GET" + urlPath := clt.endpoint + path var http_req *http.Request var reqBody []byte - switch strings.ToUpper(method) { - case "GET": - + if isGet { http_req, _ = http.NewRequest(strings.ToUpper(method), urlPath, strings.NewReader(string(reqBody))) q := http_req.URL.Query() for key, val := range params { q.Add(key, ToString(val)) } http_req.URL.RawQuery = q.Encode() - - default: + } else { reqBody, _ = json.Marshal(params) http_req, _ = http.NewRequest(strings.ToUpper(method), urlPath, strings.NewReader(string(reqBody))) } - // set general headers + // set client headers for key, val := range clt.headers { http_req.Header.Set(key, val) } - // set specific headers + // set custom headers for key, val := range headers { http_req.Header.Set(key, ToString(val)) } @@ -103,43 +102,4 @@ func (clt *Client) Call(method string, path string, headers map[string]interface var jsonResp map[string]interface{} json.Unmarshal(respData, &jsonResp) return jsonResp, nil - - /* - urlPath := clt.endpoint + path - isGet := strings.ToUpper(method) == "GET" - - var _reqBody []byte - if !isGet { - jsonOb, _ := json.Marshal(params) - _reqBody = (jsonOb) - - } - fmt.Println(string(_reqBody)) - reqBody := strings.NewReader(string(_reqBody)) - - // Create and modify HTTP request before sending - req, err := http.NewRequest(method, urlPath, reqBody) - if err != nil { - return nil, err - } - - // Set Client headers - for key, val := range clt.headers { - req.Header.Set(key, val) - } - - // Set Custom headers - for key, val := range headers { - req.Header.Set(key, ToString(val)) - } - - if isGet { - q := req.URL.Query() - for key, val := range params { - q.Add(key, ToString(val)) - } - req.URL.RawQuery = q.Encode() - } - */ - // Make request } From 0625db090adb404441d65bd3b74451522c0b4a13 Mon Sep 17 00:00:00 2001 From: Mathias Date: Mon, 23 May 2022 18:56:20 +0200 Subject: [PATCH 03/11] CreateEmailAttribute & fix xdefault on CreateStringAttribute --- database.go | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/database.go b/database.go index b0238c4..dd26465 100644 --- a/database.go +++ b/database.go @@ -171,9 +171,8 @@ func (srv *Database) DeleteDocument(CollectionId string, DocumentId string) (map return srv.client.Call("DELETE", path, nil, params) } -func (srv *Database) CreateStringAttribute(CollectionId string, key string, size int, required bool, xdefault interface{}, isArray bool) (map[string]interface{}, error) { +func (srv *Database) CreateStringAttribute(CollectionId string, key string, size int, required bool, xdefault string, isArray bool) (map[string]interface{}, error) { Type := "string" - path := "/database/collections/{collectionId}/attributes/{type}" r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) path = r.Replace(path) @@ -184,10 +183,31 @@ func (srv *Database) CreateStringAttribute(CollectionId string, key string, size "size": size, "array": isArray, } + if xdefault != "" { + params["default"] = xdefault + } + headers := map[string]interface{}{ + "content-type": "application/json", + } + return srv.client.Call("POST", path, headers, params) +} - if xdefault != nil { +func (srv *Database) CreateEmailAttribute(CollectionId string, key string, required bool, xdefault string, isArray bool) (map[string]interface{}, error) { + Type := "email" + path := "/database/collections/{collectionId}/attributes/{type}" + r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) + path = r.Replace(path) + + params := map[string]interface{}{ + "key": key, + "required": required, + } + if xdefault != "" { params["default"] = xdefault } + if isArray { + params["array"] = isArray + } headers := map[string]interface{}{ "content-type": "application/json", From 519900baf21fe6b980d62a50ad1f1679d6363755 Mon Sep 17 00:00:00 2001 From: Mathias Date: Mon, 23 May 2022 19:24:35 +0200 Subject: [PATCH 04/11] CreateEnumAttribute & Xdefault type for default values in the CreateAttribute --- database.go | 40 ++++++++++++++++++++++++++++++++++------ utils.go | 17 +++++++++++++++++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/database.go b/database.go index dd26465..56b27c3 100644 --- a/database.go +++ b/database.go @@ -1,6 +1,7 @@ package appwrite import ( + "fmt" "strings" ) @@ -171,7 +172,7 @@ func (srv *Database) DeleteDocument(CollectionId string, DocumentId string) (map return srv.client.Call("DELETE", path, nil, params) } -func (srv *Database) CreateStringAttribute(CollectionId string, key string, size int, required bool, xdefault string, isArray bool) (map[string]interface{}, error) { +func (srv *Database) CreateStringAttribute(CollectionId string, key string, size int, required bool, xdefault Xdefault, isArray bool) (map[string]interface{}, error) { Type := "string" path := "/database/collections/{collectionId}/attributes/{type}" r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) @@ -183,8 +184,8 @@ func (srv *Database) CreateStringAttribute(CollectionId string, key string, size "size": size, "array": isArray, } - if xdefault != "" { - params["default"] = xdefault + if xdefault.Specified { + params["default"] = xdefault.Value } headers := map[string]interface{}{ "content-type": "application/json", @@ -192,7 +193,7 @@ func (srv *Database) CreateStringAttribute(CollectionId string, key string, size return srv.client.Call("POST", path, headers, params) } -func (srv *Database) CreateEmailAttribute(CollectionId string, key string, required bool, xdefault string, isArray bool) (map[string]interface{}, error) { +func (srv *Database) CreateEmailAttribute(CollectionId string, key string, required bool, xdefault Xdefault, isArray bool) (map[string]interface{}, error) { Type := "email" path := "/database/collections/{collectionId}/attributes/{type}" r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) @@ -202,8 +203,8 @@ func (srv *Database) CreateEmailAttribute(CollectionId string, key string, requi "key": key, "required": required, } - if xdefault != "" { - params["default"] = xdefault + if xdefault.Specified { + params["default"] = xdefault.Value } if isArray { params["array"] = isArray @@ -213,5 +214,32 @@ func (srv *Database) CreateEmailAttribute(CollectionId string, key string, requi "content-type": "application/json", } return srv.client.Call("POST", path, headers, params) +} + +func (srv *Database) CreateEnumAttribute(CollectionId string, key string, elements []string, required bool, xdefault Xdefault, isArray bool) (map[string]interface{}, error) { + Type := "enum" + path := "/database/collections/{collectionId}/attributes/{type}" + r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) + path = r.Replace(path) + params := map[string]interface{}{ + "key": key, + "required": required, + "elements": elements, + } + if xdefault.Specified { + if contains(elements, xdefault.Value) { + params["default"] = xdefault + } else if xdefault.Value != "" { + fmt.Println("❌ The default value is not contained in the array of elementes") + return nil, nil + } + } + if isArray { + params["array"] = isArray + } + headers := map[string]interface{}{ + "content-type": "application/json", + } + return srv.client.Call("POST", path, headers, params) } diff --git a/utils.go b/utils.go index 5e952b2..a3edc35 100644 --- a/utils.go +++ b/utils.go @@ -38,3 +38,20 @@ func ToString(arg interface{}) string { return "" } } + +// returns if an element is contained in an array s +func contains[T comparable](s []T, element T) bool { + var result bool = false + for _, el := range s { + if el == element { + result = true + break + } + } + return result +} + +type Xdefault struct { + Value string + Specified bool +} From 302bb58d4ff84c79cbde784e2f1e1d8f201e128f Mon Sep 17 00:00:00 2001 From: Mathias Date: Mon, 23 May 2022 19:35:03 +0200 Subject: [PATCH 05/11] IP & Url --- database.go | 52 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/database.go b/database.go index 56b27c3..0da7eed 100644 --- a/database.go +++ b/database.go @@ -206,9 +206,7 @@ func (srv *Database) CreateEmailAttribute(CollectionId string, key string, requi if xdefault.Specified { params["default"] = xdefault.Value } - if isArray { - params["array"] = isArray - } + params["array"] = isArray headers := map[string]interface{}{ "content-type": "application/json", @@ -229,15 +227,55 @@ func (srv *Database) CreateEnumAttribute(CollectionId string, key string, elemen } if xdefault.Specified { if contains(elements, xdefault.Value) { - params["default"] = xdefault - } else if xdefault.Value != "" { + params["default"] = xdefault.Value + } else { fmt.Println("❌ The default value is not contained in the array of elementes") return nil, nil } } - if isArray { - params["array"] = isArray + params["array"] = isArray + + headers := map[string]interface{}{ + "content-type": "application/json", + } + return srv.client.Call("POST", path, headers, params) +} + +func (srv *Database) CreateIpAttribute(CollectionId string, key string, required bool, xdefault Xdefault, isArray bool) (map[string]interface{}, error) { + Type := "ip" + path := "/database/collections/{collectionId}/attributes/{type}" + r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) + path = r.Replace(path) + + params := map[string]interface{}{ + "key": key, + "required": required, + } + if xdefault.Specified { + params["default"] = xdefault.Value + } + params["array"] = isArray + headers := map[string]interface{}{ + "content-type": "application/json", + } + return srv.client.Call("POST", path, headers, params) +} + +// Url Layout url://something +func (srv *Database) CreateUrlAttribute(CollectionId string, key string, required bool, xdefault Xdefault, isArray bool) (map[string]interface{}, error) { + Type := "url" + path := "/database/collections/{collectionId}/attributes/{type}" + r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) + path = r.Replace(path) + + params := map[string]interface{}{ + "key": key, + "required": required, + } + if xdefault.Specified { + params["default"] = xdefault.Value } + params["array"] = isArray headers := map[string]interface{}{ "content-type": "application/json", } From 3fb8c9d80d5d8dd5acac6b40d584b166b37e1b61 Mon Sep 17 00:00:00 2001 From: Mathias Date: Tue, 24 May 2022 00:14:21 +0200 Subject: [PATCH 06/11] Created CreateAttributeFunctions --- database.go | 100 ++++++++++++++++++++++++++++++++++++++++++++++------ utils.go | 4 +-- 2 files changed, 91 insertions(+), 13 deletions(-) diff --git a/database.go b/database.go index 0da7eed..de71965 100644 --- a/database.go +++ b/database.go @@ -2,6 +2,8 @@ package appwrite import ( "fmt" + "reflect" + "regexp" "strings" ) @@ -172,7 +174,7 @@ func (srv *Database) DeleteDocument(CollectionId string, DocumentId string) (map return srv.client.Call("DELETE", path, nil, params) } -func (srv *Database) CreateStringAttribute(CollectionId string, key string, size int, required bool, xdefault Xdefault, isArray bool) (map[string]interface{}, error) { +func (srv *Database) CreateStringAttribute(CollectionId string, key string, size int, required bool, xdefault Optional[string], isArray Optional[bool]) (map[string]interface{}, error) { Type := "string" path := "/database/collections/{collectionId}/attributes/{type}" r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) @@ -182,18 +184,21 @@ func (srv *Database) CreateStringAttribute(CollectionId string, key string, size "key": key, "required": required, "size": size, - "array": isArray, } + // optionals if xdefault.Specified { params["default"] = xdefault.Value } + if isArray.Specified { + params["array"] = isArray.Value + } headers := map[string]interface{}{ "content-type": "application/json", } return srv.client.Call("POST", path, headers, params) } -func (srv *Database) CreateEmailAttribute(CollectionId string, key string, required bool, xdefault Xdefault, isArray bool) (map[string]interface{}, error) { +func (srv *Database) CreateEmailAttribute(CollectionId string, key string, required bool, xdefault Optional[string], isArray Optional[bool]) (map[string]interface{}, error) { Type := "email" path := "/database/collections/{collectionId}/attributes/{type}" r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) @@ -203,10 +208,13 @@ func (srv *Database) CreateEmailAttribute(CollectionId string, key string, requi "key": key, "required": required, } + // optionals if xdefault.Specified { params["default"] = xdefault.Value } - params["array"] = isArray + if isArray.Specified { + params["arrray"] = isArray.Value + } headers := map[string]interface{}{ "content-type": "application/json", @@ -214,7 +222,7 @@ func (srv *Database) CreateEmailAttribute(CollectionId string, key string, requi return srv.client.Call("POST", path, headers, params) } -func (srv *Database) CreateEnumAttribute(CollectionId string, key string, elements []string, required bool, xdefault Xdefault, isArray bool) (map[string]interface{}, error) { +func (srv *Database) CreateEnumAttribute(CollectionId string, key string, elements []string, required bool, xdefault, isArray Optional[string]) (map[string]interface{}, error) { Type := "enum" path := "/database/collections/{collectionId}/attributes/{type}" r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) @@ -225,6 +233,7 @@ func (srv *Database) CreateEnumAttribute(CollectionId string, key string, elemen "required": required, "elements": elements, } + // optionals if xdefault.Specified { if contains(elements, xdefault.Value) { params["default"] = xdefault.Value @@ -233,15 +242,16 @@ func (srv *Database) CreateEnumAttribute(CollectionId string, key string, elemen return nil, nil } } - params["array"] = isArray - + if isArray.Specified { + params["array"] = isArray.Value + } headers := map[string]interface{}{ "content-type": "application/json", } return srv.client.Call("POST", path, headers, params) } -func (srv *Database) CreateIpAttribute(CollectionId string, key string, required bool, xdefault Xdefault, isArray bool) (map[string]interface{}, error) { +func (srv *Database) CreateIpAttribute(CollectionId string, key string, required bool, xdefault, isArray Optional[bool]) (map[string]interface{}, error) { Type := "ip" path := "/database/collections/{collectionId}/attributes/{type}" r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) @@ -254,7 +264,9 @@ func (srv *Database) CreateIpAttribute(CollectionId string, key string, required if xdefault.Specified { params["default"] = xdefault.Value } - params["array"] = isArray + if isArray.Specified { + params["array"] = isArray + } headers := map[string]interface{}{ "content-type": "application/json", } @@ -262,7 +274,7 @@ func (srv *Database) CreateIpAttribute(CollectionId string, key string, required } // Url Layout url://something -func (srv *Database) CreateUrlAttribute(CollectionId string, key string, required bool, xdefault Xdefault, isArray bool) (map[string]interface{}, error) { +func (srv *Database) CreateUrlAttribute(CollectionId string, key string, required bool, xdefault Optional[string], isArray Optional[bool]) (map[string]interface{}, error) { Type := "url" path := "/database/collections/{collectionId}/attributes/{type}" r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) @@ -272,12 +284,78 @@ func (srv *Database) CreateUrlAttribute(CollectionId string, key string, require "key": key, "required": required, } + // optionals if xdefault.Specified { params["default"] = xdefault.Value } - params["array"] = isArray + if isArray.Specified { + params["array"] = isArray.Value + } headers := map[string]interface{}{ "content-type": "application/json", } return srv.client.Call("POST", path, headers, params) } + +func (srv *Database) CreateIntegerAttribute(CollectionId string, key string, required bool, min, max, xdefault Optional[int], isArray Optional[bool]) (map[string]interface{}, error) { + return createNumAttribute(srv, CollectionId, key, required, isArray, min, max, xdefault) +} + +func (srv *Database) CreateFloatAttribute(CollectionId string, key string, required bool, min, max, xdefault Optional[float64], isArray Optional[bool]) (map[string]interface{}, error) { + return createNumAttribute(srv, CollectionId, key, required, isArray, min, max, xdefault) +} + +func createNumAttribute[T any](srv *Database, CollectionId string, key string, required bool, isArray Optional[bool], min, max, xdefault Optional[T]) (map[string]interface{}, error) { + reg, _ := regexp.Compile(`\D+`) + Type := reg.FindString(reflect.TypeOf(min.Value).String()) + if Type == "int" { + Type = "integer" + } + path := "/database/collections/{collectionId}/attributes/{type}" + r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) + path = r.Replace(path) + params := map[string]interface{}{ + "key": key, + "required": required, + } + // optionals + if min.Specified { + params["min"] = min.Value + } + if max.Specified { + params["max"] = max.Value + } + if xdefault.Specified { + params["default"] = xdefault.Value + } + if isArray.Specified { + params["array"] = isArray.Value + } + headers := map[string]interface{}{ + "content-type": "application/json", + } + return srv.client.Call("POST", path, headers, params) +} + +func (srv *Database) CreateBooleanAttribute(CollectionId string, key string, required bool, isArray, xdefault Optional[bool]) (map[string]interface{}, error) { + Type := "boolean" + path := "/database/collections/{collectionId}/attributes/{type}" + r := strings.NewReplacer("{collectionId}", CollectionId, "{type}", Type) + path = r.Replace(path) + + params := map[string]interface{}{ + "key": key, + "required": required, + } + if xdefault.Specified { + params["default"] = xdefault.Value + } + if isArray.Specified { + params["array"] = isArray + } + headers := map[string]interface{}{ + "content-type": "application/json", + } + return srv.client.Call("POST", path, headers, params) + +} diff --git a/utils.go b/utils.go index a3edc35..ffb7c96 100644 --- a/utils.go +++ b/utils.go @@ -51,7 +51,7 @@ func contains[T comparable](s []T, element T) bool { return result } -type Xdefault struct { - Value string +type Optional[T any] struct { + Value T Specified bool } From 80f648bab61a1c4a009487433fdb444832d97c3e Mon Sep 17 00:00:00 2001 From: Mathias Date: Tue, 24 May 2022 00:26:14 +0200 Subject: [PATCH 07/11] fix optional isArray not being set to its value --- database.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database.go b/database.go index de71965..77d634e 100644 --- a/database.go +++ b/database.go @@ -265,7 +265,7 @@ func (srv *Database) CreateIpAttribute(CollectionId string, key string, required params["default"] = xdefault.Value } if isArray.Specified { - params["array"] = isArray + params["array"] = isArray.Value } headers := map[string]interface{}{ "content-type": "application/json", @@ -351,7 +351,7 @@ func (srv *Database) CreateBooleanAttribute(CollectionId string, key string, req params["default"] = xdefault.Value } if isArray.Specified { - params["array"] = isArray + params["array"] = isArray.Value } headers := map[string]interface{}{ "content-type": "application/json", From 5e3f5f9cb409312249092cdd48eb08413e8e17bf Mon Sep 17 00:00:00 2001 From: Mathias Date: Tue, 24 May 2022 00:36:22 +0200 Subject: [PATCH 08/11] updated docs for createCollection --- docs/examples/Database/create-collection.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/docs/examples/Database/create-collection.md b/docs/examples/Database/create-collection.md index 947ce79..5335ac2 100644 --- a/docs/examples/Database/create-collection.md +++ b/docs/examples/Database/create-collection.md @@ -8,18 +8,12 @@ import ( func main() { var client := appwrite.Client{} + client.setEndpoint("url") // url to your appwrite instance client.SetProject("5df5acd0d48c2") // Your project ID client.SetKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key - var service := appwrite.Database{ - client: &client - } - - var response, error := service.CreateCollection("[NAME]", [], [], []) - - if error != nil { - panic(error) - } - + appwrite_db := appwrite.NewDatabase(client) + + response, error :=appwrite_db.CreateCollection("unique()", "Collection_name", "document", []string{"role:all"}, []string{"role:all"}) fmt.Println(response) } \ No newline at end of file From 3f4a198a49cbdb771ac3ab3d487b50c24c738609 Mon Sep 17 00:00:00 2001 From: Mathias Date: Tue, 24 May 2022 08:23:15 +0200 Subject: [PATCH 09/11] shameful mistake corrected -> efficientyle find if an element T is contained in a slice with elements of type T --- utils.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/utils.go b/utils.go index ffb7c96..e6c12f3 100644 --- a/utils.go +++ b/utils.go @@ -41,14 +41,12 @@ func ToString(arg interface{}) string { // returns if an element is contained in an array s func contains[T comparable](s []T, element T) bool { - var result bool = false for _, el := range s { if el == element { - result = true - break + return true } } - return result + return false } type Optional[T any] struct { From 5bac76c4dd16e79db809f82bfe61fad16706d466 Mon Sep 17 00:00:00 2001 From: Mathias Date: Tue, 24 May 2022 08:25:18 +0200 Subject: [PATCH 10/11] added warning message in ToString --- utils.go | 1 + 1 file changed, 1 insertion(+) diff --git a/utils.go b/utils.go index e6c12f3..4d7fc8f 100644 --- a/utils.go +++ b/utils.go @@ -35,6 +35,7 @@ func ToString(arg interface{}) string { case reflect.Value: return ToString(v.Interface()) default: + fmt.Println("⚠️ : Warning in utils ToString method: argument type is unknown returning empty string") return "" } } From 6fe7003616e18990255d0af34f6a5f6c6ba07a9e Mon Sep 17 00:00:00 2001 From: Mathias Date: Tue, 24 May 2022 08:34:39 +0200 Subject: [PATCH 11/11] docs for create-attributes, created the intro and the CreateStringAttribute --- docs/examples/Database/create-attribute.md | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 docs/examples/Database/create-attribute.md diff --git a/docs/examples/Database/create-attribute.md b/docs/examples/Database/create-attribute.md new file mode 100644 index 0000000..3f44ed7 --- /dev/null +++ b/docs/examples/Database/create-attribute.md @@ -0,0 +1,24 @@ +Usage of CreateAttribute methods + +Attributes that are available: +- string +- Enum +- Email +- Ip +- Url +- Integer +- Float +- Boolean + +Note: for the optional parameters, there is new type created (since GO doesn't have optional or default arguments). The Optional type is defined as a struct with fields: + +- Value -> this contains the value +- Specified -> wether or not it is specified (defaults to false) + +Optional[T]{} -> replace T with the desired type (string, int, ...) +empty optional = will see as "optional value not set" + +Example Use of the CreateAttribute functions: + +CreateStringAttribute("unique()", "StringName", 15, false, Optional[string]{Value: "MyDefaultString",Specified: false}, Optional[bool]{}) +This wil create a String attribute with name "StringName" that is max. 15 characters long and has default value "MyDefaultString". Since the isArray is an empty Optional[bool], the isArray bool will be false -> this is not an array