Replace/UpsertReplace support
This commit is contained in:
10
base.go
10
base.go
@@ -6,9 +6,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Base struct {
|
type Base struct {
|
||||||
ID string `json:"id"`
|
ID *string `json:"id,omitempty"`
|
||||||
Name string `json:"name"`
|
Name *string `json:"name,omitempty"`
|
||||||
PermissionLevel string `json:"permissionLevel"`
|
PermissionLevel *string `json:"permissionLevel,omitempty"`
|
||||||
|
|
||||||
c *Client
|
c *Client
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ func (c *Client) GetBaseByName(ctx context.Context, name string) (*Base, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, base := range bases {
|
for _, base := range bases {
|
||||||
if base.Name == name {
|
if *base.Name == name {
|
||||||
return base, nil
|
return base, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,5 +36,5 @@ func (c *Client) GetBaseByName(ctx context.Context, name string) (*Base, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b Base) String() string {
|
func (b Base) String() string {
|
||||||
return b.Name
|
return *b.Name
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,3 +47,7 @@ func (c *Client) SetRateLimit(rateLimit int) {
|
|||||||
func (c *Client) waitForRateLimit() {
|
func (c *Client) waitForRateLimit() {
|
||||||
<-c.rateLimiter
|
<-c.rateLimiter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func P(s string) *string {
|
||||||
|
return &s
|
||||||
|
}
|
||||||
|
|||||||
4
http.go
4
http.go
@@ -5,6 +5,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
)
|
)
|
||||||
@@ -63,7 +64,8 @@ func do[T any](ctx context.Context, c *Client, method, path string, params url.V
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
||||||
return nil, fmt.Errorf("http error: %d %s", resp.StatusCode, http.StatusText(resp.StatusCode))
|
errBody, _ := io.ReadAll(resp.Body)
|
||||||
|
return nil, fmt.Errorf("http error: %d %s (%s)", resp.StatusCode, http.StatusText(resp.StatusCode), string(errBody))
|
||||||
}
|
}
|
||||||
|
|
||||||
dec := json.NewDecoder(resp.Body)
|
dec := json.NewDecoder(resp.Body)
|
||||||
|
|||||||
58
record.go
58
record.go
@@ -6,10 +6,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Record struct {
|
type Record struct {
|
||||||
ID string `json:"id,omitempty"`
|
ID *string `json:"id,omitempty"`
|
||||||
Fields map[string]any `json:"fields"`
|
Fields map[string]any `json:"fields"`
|
||||||
CreatedTime string `json:"createdTime,omitempty"`
|
CreatedTime *string `json:"createdTime,omitempty"`
|
||||||
Deleted bool `json:"deleted,omitempty"`
|
|
||||||
|
|
||||||
c *Client
|
c *Client
|
||||||
b *Base
|
b *Base
|
||||||
@@ -20,7 +19,7 @@ type ListRecordOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) ListRecords(ctx context.Context, opts *ListRecordOptions) ([]*Record, error) {
|
func (t *Table) ListRecords(ctx context.Context, opts *ListRecordOptions) ([]*Record, error) {
|
||||||
return listAll[Record](ctx, t.c, fmt.Sprintf("%s/%s", t.b.ID, t.ID), nil, "records", func(r *Record) error {
|
return listAll[Record](ctx, t.c, fmt.Sprintf("%s/%s", *t.b.ID, *t.ID), nil, "records", func(r *Record) error {
|
||||||
r.c = t.c
|
r.c = t.c
|
||||||
r.b = t.b
|
r.b = t.b
|
||||||
r.t = t
|
r.t = t
|
||||||
@@ -28,6 +27,53 @@ func (t *Table) ListRecords(ctx context.Context, opts *ListRecordOptions) ([]*Re
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Record) String() string {
|
type updateRecordsRequest struct {
|
||||||
return r.Fields[r.t.Fields[0].Name].(string)
|
PerformUpsert *performUpsertRequest `json:"performUpsert,omitempty"`
|
||||||
|
Records []*Record `json:"records"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type performUpsertRequest struct {
|
||||||
|
FieldsToMergeOn []string `json:"fieldsToMergeOn"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type updateRecordsResponse struct {
|
||||||
|
Records []*Record `json:"records"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Table) ReplaceRecords(ctx context.Context, records []*Record, matchFields []string) ([]*Record, error) {
|
||||||
|
ret := []*Record{}
|
||||||
|
|
||||||
|
req := &updateRecordsRequest{}
|
||||||
|
|
||||||
|
if len(matchFields) > 0 {
|
||||||
|
req.PerformUpsert = &performUpsertRequest{
|
||||||
|
FieldsToMergeOn: matchFields,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, chk := range chunk(records, 10) {
|
||||||
|
req.Records = chk
|
||||||
|
|
||||||
|
resp, err := put[updateRecordsResponse](ctx, t.c, fmt.Sprintf("%s/%s", *t.b.ID, *t.ID), req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rec := range resp.Records {
|
||||||
|
rec.c = t.c
|
||||||
|
rec.b = t.b
|
||||||
|
rec.t = t
|
||||||
|
ret = append(ret, rec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Record) String() string {
|
||||||
|
if r.ID == nil {
|
||||||
|
return fmt.Sprintf("(%s [nil])", r.Fields[*r.t.Fields[0].Name].(string))
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("(%s [%s])", r.Fields[*r.t.Fields[0].Name].(string), *r.ID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
table.go
26
table.go
@@ -6,10 +6,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Table struct {
|
type Table struct {
|
||||||
ID string `json:"id"`
|
ID *string `json:"id,omitempty"`
|
||||||
PrimaryFieldID string `json:"primaryFieldId"`
|
PrimaryFieldID *string `json:"primaryFieldId,omitempty"`
|
||||||
Name string `json:"name"`
|
Name *string `json:"name,omitempty"`
|
||||||
Description string `json:"description"`
|
Description *string `json:"description,omitempty"`
|
||||||
Fields []*Field `json:"fields"`
|
Fields []*Field `json:"fields"`
|
||||||
Views []*View `json:"views"`
|
Views []*View `json:"views"`
|
||||||
|
|
||||||
@@ -18,21 +18,21 @@ type Table struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Field struct {
|
type Field struct {
|
||||||
ID string `json:"id"`
|
ID *string `json:"id"`
|
||||||
Type string `json:"type"`
|
Type *string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name *string `json:"name"`
|
||||||
Description string `json:"description"`
|
Description *string `json:"description"`
|
||||||
Options map[string]any `json:"options"`
|
Options map[string]any `json:"options"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type View struct {
|
type View struct {
|
||||||
ID string `json:"id"`
|
ID *string `json:"id"`
|
||||||
Type string `json:"type"`
|
Type *string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name *string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Base) ListTables(ctx context.Context) ([]*Table, error) {
|
func (b *Base) ListTables(ctx context.Context) ([]*Table, error) {
|
||||||
return listAll[Table](ctx, b.c, fmt.Sprintf("meta/bases/%s/tables", b.ID), nil, "tables", func(t *Table) error {
|
return listAll[Table](ctx, b.c, fmt.Sprintf("meta/bases/%s/tables", *b.ID), nil, "tables", func(t *Table) error {
|
||||||
t.c = b.c
|
t.c = b.c
|
||||||
t.b = b
|
t.b = b
|
||||||
return nil
|
return nil
|
||||||
@@ -46,7 +46,7 @@ func (b *Base) GetTableByName(ctx context.Context, name string) (*Table, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, table := range tables {
|
for _, table := range tables {
|
||||||
if table.Name == name {
|
if *table.Name == name {
|
||||||
return table, nil
|
return table, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user