Multi-record list
This commit is contained in:
52
client.go
52
client.go
@@ -1,8 +1,3 @@
|
|||||||
// Copyright © 2020 Mike Berezin
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT license.
|
|
||||||
// Details in the LICENSE file.
|
|
||||||
|
|
||||||
package airtable
|
package airtable
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -20,22 +15,18 @@ const (
|
|||||||
defaultRateLimit = 4
|
defaultRateLimit = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client client for airtable api.
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Client *http.Client
|
Client *http.Client
|
||||||
BaseURL string
|
BaseURL string
|
||||||
APIKey string
|
apiKey string
|
||||||
rateLimiter <-chan time.Time
|
rateLimiter <-chan time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// New airtable client constructor
|
|
||||||
// your API KEY you can get on your account page
|
|
||||||
// https://airtable.com/account
|
|
||||||
func New(apiKey string) *Client {
|
func New(apiKey string) *Client {
|
||||||
c := &Client{
|
c := &Client{
|
||||||
Client: http.DefaultClient,
|
Client: http.DefaultClient,
|
||||||
APIKey: apiKey,
|
|
||||||
BaseURL: defaultBaseURL,
|
BaseURL: defaultBaseURL,
|
||||||
|
apiKey: apiKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
c.SetRateLimit(defaultRateLimit)
|
c.SetRateLimit(defaultRateLimit)
|
||||||
@@ -43,9 +34,6 @@ func New(apiKey string) *Client {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRateLimit rate limit setter for custom usage
|
|
||||||
// Airtable limit is 5 requests per second (we use 4)
|
|
||||||
// https://airtable.com/{yourDatabaseID}/api/docs#curl/ratelimits
|
|
||||||
func (at *Client) SetRateLimit(rateLimit int) {
|
func (at *Client) SetRateLimit(rateLimit int) {
|
||||||
at.rateLimiter = time.Tick(time.Second / time.Duration(rateLimit))
|
at.rateLimiter = time.Tick(time.Second / time.Duration(rateLimit))
|
||||||
}
|
}
|
||||||
@@ -108,7 +96,7 @@ func (at *Client) do(ctx context.Context, method, db, table, recordID string, pa
|
|||||||
req.URL.RawQuery = params.Encode()
|
req.URL.RawQuery = params.Encode()
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", at.APIKey))
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", at.apiKey))
|
||||||
|
|
||||||
resp, err := at.Client.Do(req)
|
resp, err := at.Client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -130,3 +118,37 @@ func (at *Client) do(ctx context.Context, method, db, table, recordID string, pa
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func listAll[T any](ctx context.Context, c *Client, db, table string, params url.Values, key string) ([]*T, error) {
|
||||||
|
ret := []*T{}
|
||||||
|
|
||||||
|
for {
|
||||||
|
resp := map[string]any{}
|
||||||
|
|
||||||
|
err := c.get(ctx, db, table, "", params, resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
off, found := resp["offset"]
|
||||||
|
if !found {
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
params.Set("offset", off.(string))
|
||||||
|
|
||||||
|
subresp, err := json.Marshal(resp[key])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
obj := []*T{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(subresp, obj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, obj...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
// Copyright © 2020 Mike Berezin
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT license.
|
|
||||||
// Details in the LICENSE file.
|
|
||||||
|
|
||||||
package airtable
|
package airtable
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ func (grc *GetRecordsConfig) InStringFormat(timeZone, userLocale string) *GetRec
|
|||||||
return grc
|
return grc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do send the prepared get records request.
|
func (grc *GetRecordsConfig) Do() ([]*Record, error) {
|
||||||
func (grc *GetRecordsConfig) Do() (*Records, error) {
|
|
||||||
return grc.table.GetRecordsWithParams(grc.params)
|
return grc.table.GetRecordsWithParams(grc.params)
|
||||||
}
|
}
|
||||||
|
|||||||
14
table.go
14
table.go
@@ -38,23 +38,17 @@ func (c *Client) GetTable(dbName, tableName string) *Table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRecordsWithParams get records with url values params
|
func (t *Table) GetRecordsWithParams(params url.Values) ([]*Record, error) {
|
||||||
// https://airtable.com/{yourDatabaseID}/api/docs#curl/table:{yourTableName}:list
|
|
||||||
func (t *Table) GetRecordsWithParams(params url.Values) (*Records, error) {
|
|
||||||
return t.GetRecordsWithParamsContext(context.Background(), params)
|
return t.GetRecordsWithParamsContext(context.Background(), params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRecordsWithParamsContext get records with url values params
|
func (t *Table) GetRecordsWithParamsContext(ctx context.Context, params url.Values) ([]*Record, error) {
|
||||||
// with custom context
|
records, err := listAll[Record](ctx, t.client, t.dbName, t.tableName, params, "records")
|
||||||
func (t *Table) GetRecordsWithParamsContext(ctx context.Context, params url.Values) (*Records, error) {
|
|
||||||
records := new(Records)
|
|
||||||
|
|
||||||
err := t.client.get(ctx, t.dbName, t.tableName, "", params, records)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, record := range records.Records {
|
for _, record := range records {
|
||||||
record.client = t.client
|
record.client = t.client
|
||||||
record.table = t
|
record.table = t
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user