Multi-record list

This commit is contained in:
Ian Gulliver
2024-06-22 15:33:14 -07:00
parent 8ea1e9731b
commit ea516a559f
4 changed files with 42 additions and 31 deletions

View File

@@ -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...)
}
}

View File

@@ -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

View File

@@ -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)
} }

View File

@@ -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
} }