diff --git a/client.go b/client.go index aceb3b6..85ea2e8 100644 --- a/client.go +++ b/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 import ( @@ -20,22 +15,18 @@ const ( defaultRateLimit = 4 ) -// Client client for airtable api. type Client struct { Client *http.Client BaseURL string - APIKey string + apiKey string 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 { c := &Client{ Client: http.DefaultClient, - APIKey: apiKey, BaseURL: defaultBaseURL, + apiKey: apiKey, } c.SetRateLimit(defaultRateLimit) @@ -43,9 +34,6 @@ func New(apiKey string) *Client { 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) { 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.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) if err != nil { @@ -130,3 +118,37 @@ func (at *Client) do(ctx context.Context, method, db, table, recordID string, pa 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...) + } +} diff --git a/field-converter.go b/field-converter.go index 20b80ab..f2af9bc 100644 --- a/field-converter.go +++ b/field-converter.go @@ -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 diff --git a/get-records.go b/get-records.go index b0bc7e6..ddfc459 100644 --- a/get-records.go +++ b/get-records.go @@ -101,7 +101,6 @@ func (grc *GetRecordsConfig) InStringFormat(timeZone, userLocale string) *GetRec return grc } -// Do send the prepared get records request. -func (grc *GetRecordsConfig) Do() (*Records, error) { +func (grc *GetRecordsConfig) Do() ([]*Record, error) { return grc.table.GetRecordsWithParams(grc.params) } diff --git a/table.go b/table.go index 08a8092..7445a37 100644 --- a/table.go +++ b/table.go @@ -38,23 +38,17 @@ func (c *Client) GetTable(dbName, tableName string) *Table { } } -// GetRecordsWithParams get records with url values params -// https://airtable.com/{yourDatabaseID}/api/docs#curl/table:{yourTableName}:list -func (t *Table) GetRecordsWithParams(params url.Values) (*Records, error) { +func (t *Table) GetRecordsWithParams(params url.Values) ([]*Record, error) { return t.GetRecordsWithParamsContext(context.Background(), params) } -// GetRecordsWithParamsContext get records with url values params -// with custom context -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) +func (t *Table) GetRecordsWithParamsContext(ctx context.Context, params url.Values) ([]*Record, error) { + records, err := listAll[Record](ctx, t.client, t.dbName, t.tableName, params, "records") if err != nil { return nil, err } - for _, record := range records.Records { + for _, record := range records { record.client = t.client record.table = t }