Repository: amp-labs/connectors (go)

Issue:
Add Airtable connector

Pull request description:
feat: Add Airtable Connector
Closes #154
## Checklist
- [x] Ran Linter
- [x] Catalog tests passing
- [x] Created PR from non-main branch 

## Catalog variables
None

## Notes
Auth flow uses PKCE, it is a mandatory requirement.

## Testing 
### GET 
<img width="1144" alt="Screenshot 2024-04-03 at 12 08 22" src="https://github.com/amp-labs/connectors/assets/52887226/3de3d36f-3ae1-4e9b-97ec-10fecd39397f">


### POST
<img width="1146" alt="Screenshot 2024-04-03 at 12 19 19" src="https://github.com/amp-labs/connectors/assets/52887226/b048560f-d9c9-4437-8423-61ce5a10258f">


### PUT
<img width="1156" alt="Screenshot 2024-04-03 at 12 23 36" src="https://github.com/amp-labs/connectors/assets/52887226/e2ce94af-57bf-4291-8d56-5a61b4b07a00">

### DELETE
<img width="1151" alt="Screenshot 2024-04-03 at 13 02 33" src="https://github.com/amp-labs/connectors/assets/52887226/59c519ba-65e7-4069-be3a-148cdb07a52d">


## Pagination
Requesting a list of records
<img width="1147" alt="Screenshot 2024-04-03 at 12 38 13" src="https://github.com/amp-labs/connectors/assets/52887226/4f995ef1-3539-4eae-8379-9b61ae30d001">

The response has `offset` indicating there is a next page, using it to get the next page values
<img width="1153" alt="Screenshot 2024-04-03 at 12 39 06" src="https://github.com/amp-labs/connectors/assets/52887226/927156d7-31f6-4cc5-afc8-a188600d0853">



Patch:
diff --git a/providers/catalog.go b/providers/catalog.go
index 48ee3f9f..819ef715 100644
--- a/providers/catalog.go
+++ b/providers/catalog.go
@@ -38,6 +38,7 @@ const (
 	ZendeskSupport                      Provider = "zendeskSupport"
 	ZendeskChat                         Provider = "zendeskChat"
 	WordPress                           Provider = "wordPress"
+	Airtable                            Provider = "airtable"
 )
 
 // ================================================================================
@@ -859,4 +860,32 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			Write:     false,
 		},
 	},
+
+	// Airtable Support Configuration
+	Airtable: {
+		AuthType: Oauth2,
+		BaseURL:  "https://api.airtable.com",
+		OauthOpts: OauthOpts{
+			GrantType:                 PKCE,
+			AuthURL:                   "https://airtable.com/oauth2/v1/authorize",
+			TokenURL:                  "https://airtable.com/oauth2/v1/token",
+			ExplicitScopesRequired:    true,
+			ExplicitWorkspaceRequired: false,
+			TokenMetadataFields: TokenMetadataFields{
+				ScopesField: "scope",
+			},
+		},
+		Support: Support{
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
+			Proxy:     false,
+			Read:      false,
+			Subscribe: false,
+			Write:     false,
+		},
+	},
 }


Test patch:
diff --git a/providers/catalog_test.go b/providers/catalog_test.go
index 9f0d6dc7..f57b8121 100644
--- a/providers/catalog_test.go
+++ b/providers/catalog_test.go
@@ -979,6 +979,37 @@ var testCases = []struct { // nolint
 		},
 		expectedErr: nil,
 	},
+	{
+		provider:    Airtable,
+		description: "Valid Airtable provider config with no substitutions",
+		expected: &ProviderInfo{
+			AuthType: Oauth2,
+			OauthOpts: OauthOpts{
+				GrantType:                 PKCE,
+				AuthURL:                   "https://airtable.com/oauth2/v1/authorize",
+				TokenURL:                  "https://airtable.com/oauth2/v1/token",
+				ExplicitScopesRequired:    true,
+				ExplicitWorkspaceRequired: false,
+				TokenMetadataFields: TokenMetadataFields{
+					ScopesField: "scope",
+				},
+			},
+			Support: Support{
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
+				Proxy:     false,
+				Read:      false,
+				Subscribe: false,
+				Write:     false,
+			},
+			BaseURL: "https://api.airtable.com",
+		},
+		expectedErr: nil,
+	},
 }
 
 func TestReadInfo(t *testing.T) { // nolint