Repository: amp-labs/connectors
Pull request #194 (2024-04-09 08:56:31)

chore: Minor fix & remove google cal


Patch:
diff --git a/basic/client.go b/connector/client.go
similarity index 65%
rename from basic/client.go
rename to connector/client.go
index 4bab3a3a..6aaee506 100644
--- a/basic/client.go
+++ b/connector/client.go
@@ -1,9 +1,13 @@
-package basic
+package connector
 
 import (
 	"github.com/amp-labs/connectors/common"
 )
 
+func (c *Connector) JSONHTTPClient() *common.JSONHTTPClient {
+	return c.Client
+}
+
 func (c *Connector) HTTPClient() *common.HTTPClient {
 	return c.Client.HTTPClient
 }
diff --git a/basic/connector.go b/connector/connector.go
similarity index 90%
rename from basic/connector.go
rename to connector/connector.go
index fd70bbf6..31a181ca 100644
--- a/basic/connector.go
+++ b/connector/connector.go
@@ -1,18 +1,16 @@
-package basic
+package connector
 
 import (
 	"github.com/amp-labs/connectors/common"
 	"github.com/amp-labs/connectors/providers"
 )
 
-// Connector is a Basic connector.
 type Connector struct {
 	ProviderInfo *providers.ProviderInfo
 	Client       *common.JSONHTTPClient
 	provider     providers.Provider
 }
 
-// NewConnector returns a new Basic connector.
 func NewConnector(
 	provider providers.Provider,
 	opts ...Option,
@@ -30,7 +28,7 @@ func NewConnector(
 	}()
 
 	// Set up basic params
-	params := &basicParams{}
+	params := &connectorParams{}
 	params.provider = provider
 
 	// Apply options & verify
diff --git a/basic/errors.go b/connector/errors.go
similarity index 91%
rename from basic/errors.go
rename to connector/errors.go
index b14c12ae..411efe71 100644
--- a/basic/errors.go
+++ b/connector/errors.go
@@ -1,4 +1,4 @@
-package basic
+package connector
 
 import (
 	"net/http"
diff --git a/basic/params.go b/connector/params.go
similarity index 87%
rename from basic/params.go
rename to connector/params.go
index c0b9ac1e..94a31209 100644
--- a/basic/params.go
+++ b/connector/params.go
@@ -1,4 +1,4 @@
-package basic
+package connector
 
 import (
 	"context"
@@ -18,15 +18,15 @@ var (
 	ErrMissingProvider = errors.New("missing provider")
 )
 
-type Option func(*basicParams)
+type Option func(*connectorParams)
 
-type basicParams struct {
+type connectorParams struct {
 	provider      providers.Provider
 	client        *common.JSONHTTPClient
 	substitutions map[string]string
 }
 
-func (p *basicParams) prepare() (*basicParams, error) {
+func (p *connectorParams) prepare() (*connectorParams, error) {
 	if p.provider == "" {
 		return nil, ErrMissingProvider
 	}
@@ -42,7 +42,7 @@ func (p *basicParams) prepare() (*basicParams, error) {
 // reading from providers.yaml. If the provider values are not set, the connector
 // will use error out.
 func WithCatalogSubstitutions(substitutions map[string]string) Option {
-	return func(params *basicParams) {
+	return func(params *connectorParams) {
 		params.substitutions = substitutions
 	}
 }
@@ -51,7 +51,7 @@ func WithCatalogSubstitutions(substitutions map[string]string) Option {
 func WithClient(ctx context.Context, client *http.Client, config *oauth2.Config, token *oauth2.Token,
 	opts ...common.OAuthOption,
 ) Option {
-	return func(params *basicParams) {
+	return func(params *connectorParams) {
 		options := []common.OAuthOption{
 			common.WithClient(client),
 			common.WithOAuthConfig(config),
@@ -69,7 +69,7 @@ func WithClient(ctx context.Context, client *http.Client, config *oauth2.Config,
 
 // WithAuthenticatedClient sets the http client to use for the connector. Its usage is optional.
 func WithAuthenticatedClient(client common.AuthenticatedHTTPClient) Option {
-	return func(params *basicParams) {
+	return func(params *connectorParams) {
 		params.client = &common.JSONHTTPClient{
 			HTTPClient: &common.HTTPClient{
 				Client:       client,
diff --git a/basic/provider.go b/connector/provider.go
similarity index 87%
rename from basic/provider.go
rename to connector/provider.go
index 6f33a72d..f32e5eb4 100644
--- a/basic/provider.go
+++ b/connector/provider.go
@@ -1,4 +1,4 @@
-package basic
+package connector
 
 import (
 	"github.com/amp-labs/connectors/providers"
diff --git a/basic/string.go b/connector/string.go
similarity index 81%
rename from basic/string.go
rename to connector/string.go
index e38aad4e..d1c56325 100644
--- a/basic/string.go
+++ b/connector/string.go
@@ -1,4 +1,4 @@
-package basic
+package connector
 
 func (c *Connector) String() string {
 	return c.Provider() + ".Connector"
diff --git a/connectors.go b/connectors.go
index c730df24..6d9d4631 100644
--- a/connectors.go
+++ b/connectors.go
@@ -12,12 +12,17 @@ import (
 	"github.com/amp-labs/connectors/salesforce"
 )
 
-// BasicConnector is an interface that can be used to implement a connector with
+// Connector is an interface that can be used to implement a connector with
 // basic configuration about the provider.
-type BasicConnector interface {
+type Connector interface {
 	fmt.Stringer
 	io.Closer
 
+	// JSONHTTPClient returns the underlying JSON HTTP client. This is useful for
+	// testing, or for calling methods that aren't exposed by the Connector
+	// interface directly. Authentication and token refreshes will be handled automatically.
+	JSONHTTPClient() *common.JSONHTTPClient
+
 	// HTTPClient returns the underlying HTTP client. This is useful for proxy requests.
 	HTTPClient() *common.HTTPClient
 
@@ -25,9 +30,9 @@ type BasicConnector interface {
 	Provider() providers.Provider
 }
 
-// Connector is an interface that all connectors must implement.
-type Connector interface {
-	BasicConnector
+// ReadConnector is an interface that extends the Connector interface with read capabilities.
+type ReadConnector interface {
+	Connector
 
 	// Read reads a page of data from the connector. This can be called multiple
 	// times to read all the data. The caller is responsible for paging, by
@@ -36,15 +41,21 @@ type Connector interface {
 	// Authentication corner cases are handled internally, but all other errors
 	// are returned to the caller.
 	Read(ctx context.Context, params ReadParams) (*ReadResult, error)
+}
+
+// WriteConnector is an interface that extends the Connector interface with write capabilities.
+type WriteConnector interface {
+	Connector
 
 	Write(ctx context.Context, params WriteParams) (*WriteResult, error)
+}
 
-	ListObjectMetadata(ctx context.Context, objectNames []string) (*ListObjectMetadataResult, error)
+// ObjectMetadataConnector is an interface that extends the Connector interface with
+// the ability to list object metadata.
+type ObjectMetadataConnector interface {
+	Connector
 
-	// JSONHTTPClient returns the underlying JSON HTTP client. This is useful for
-	// testing, or for calling methods that aren't exposed by the Connector
-	// interface directly. Authentication and token refreshes will be handled automatically.
-	JSONHTTPClient() *common.JSONHTTPClient
+	ListObjectMetadata(ctx context.Context, objectNames []string) (*ListObjectMetadataResult, error)
 }
 
 // API is a function that returns a Connector. It's used as a factory.
diff --git a/providers/catalog.go b/providers/catalog.go
index 15848541..040a2e87 100644
--- a/providers/catalog.go
+++ b/providers/catalog.go
@@ -401,7 +401,7 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 	// Dropbox configuration
 	Dropbox: {
 		AuthType: Oauth2,
-		BaseURL:  "https://api.dropboxapi.com/2/",
+		BaseURL:  "https://api.dropboxapi.com",
 		OauthOpts: OauthOpts{
 			AuthURL:                   "https://www.dropbox.com/oauth2/authorize",
 			TokenURL:                  "https://api.dropboxapi.com/oauth2/token",
@@ -765,32 +765,6 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 		},
 	},
 
-	GoogleCalendar: {
-		AuthType: Oauth2,
-		BaseURL:  "https://www.googleapis.com/calendar",
-		OauthOpts: OauthOpts{
-			AuthURL:                   "https://accounts.google.com/o/oauth2/v2/auth",
-			TokenURL:                  "https://oauth2.googleapis.com/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,
-		},
-	},
-
 	// Zendesk Support configuration
 	ZendeskSupport: {
 		AuthType: Oauth2,
diff --git a/scripts/proxy/proxy.go b/scripts/proxy/proxy.go
index 7f381c63..fd9b1fa4 100644
--- a/scripts/proxy/proxy.go
+++ b/scripts/proxy/proxy.go
@@ -13,7 +13,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/amp-labs/connectors/basic"
+	"github.com/amp-labs/connectors/connector"
 	"github.com/amp-labs/connectors/providers"
 	"github.com/amp-labs/connectors/utils"
 	"golang.org/x/oauth2"
@@ -203,7 +203,6 @@ func buildProxy(provider string, scopes []string, clientId, clientSecret string,
 func getProviderConfig(provider string, substitutions map[string]string) *providers.ProviderInfo {
 	config, err := providers.ReadInfo(provider, &substitutions)
 	if err != nil {
-
 		panic(fmt.Errorf("%w: %s", err, provider))
 	}
 
@@ -227,9 +226,9 @@ func configureOAuth(clientId, clientSecret string, scopes []string, providerInfo
 func setupHttpClient(cfg *oauth2.Config, accessToken, refreshToken, provider string, expiry time.Time, providerInfo *providers.ProviderInfo) *http.Client {
 	ctx := context.Background()
 
-	conn, err := basic.NewConnector(
+	conn, err := connector.NewConnector(
 		provider,
-		basic.WithClient(ctx, http.DefaultClient, cfg, &oauth2.Token{
+		connector.WithClient(ctx, http.DefaultClient, cfg, &oauth2.Token{
 			AccessToken:  accessToken,
 			RefreshToken: refreshToken,
 			Expiry:       expiry, // will trigger reuse of refresh token


Test patch:
diff --git a/providers/catalog_test.go b/providers/catalog_test.go
index bdb60fa5..c2e19ff9 100644
--- a/providers/catalog_test.go
+++ b/providers/catalog_test.go
@@ -460,7 +460,7 @@ var testCases = []struct { // nolint
 				Subscribe: false,
 				Write:     false,
 			},
-			BaseURL: "https://api.dropboxapi.com/2/",
+			BaseURL: "https://api.dropboxapi.com",
 		},
 		expectedErr: nil,
 	},
@@ -862,36 +862,6 @@ var testCases = []struct { // nolint
 		},
 		expectedErr: nil,
 	},
-	{
-		provider:    GoogleCalendar,
-		description: "Google Calendar provider config with no substitutions",
-		expected: &ProviderInfo{
-			Support: Support{
-				Read:  false,
-				Write: false,
-				BulkWrite: BulkWriteSupport{
-					Insert: false,
-					Update: false,
-					Upsert: false,
-					Delete: false,
-				},
-				Subscribe: false,
-				Proxy:     false,
-			},
-			AuthType: Oauth2,
-			OauthOpts: OauthOpts{
-				AuthURL:                   "https://accounts.google.com/o/oauth2/v2/auth",
-				TokenURL:                  "https://oauth2.googleapis.com/token",
-				ExplicitWorkspaceRequired: false,
-				ExplicitScopesRequired:    true,
-				TokenMetadataFields: TokenMetadataFields{
-					ScopesField: "scope",
-				},
-			},
-			BaseURL: "https://www.googleapis.com/calendar",
-		},
-		expectedErr: nil,
-	},
 	{
 		provider:    ZendeskSupport,
 		description: "Zendesk Support provider config with valid substitutions",
diff --git a/test/salesforce/read-write/read-write.go b/test/salesforce/read-write/read-write.go
index a8aaca0f..54201965 100644
--- a/test/salesforce/read-write/read-write.go
+++ b/test/salesforce/read-write/read-write.go
@@ -66,7 +66,13 @@ func mainFn() int { //nolint:funlen
 		_ = sfc.Close()
 	}()
 
-	if err := testConnector(ctx, sfc); err != nil {
+	if err := testReadConnector(ctx, sfc); err != nil {
+		slog.Error("Error testing", "connector", sfc, "error", err)
+
+		return 1
+	}
+
+	if err := testWriteConnector(ctx, sfc); err != nil {
 		slog.Error("Error testing", "connector", sfc, "error", err)
 
 		return 1
@@ -75,7 +81,7 @@ func mainFn() int { //nolint:funlen
 	return 0
 }
 
-func testConnector(ctx context.Context, conn connectors.Connector) error {
+func testReadConnector(ctx context.Context, conn connectors.ReadConnector) error {
 	// Create a context with a timeout
 	ctx, done := context.WithTimeout(ctx, TimeoutSeconds*time.Second)
 	defer done()
@@ -98,6 +104,10 @@ func testConnector(ctx context.Context, conn connectors.Connector) error {
 	_, _ = os.Stdout.Write(jsonStr)
 	_, _ = os.Stdout.WriteString("\n")
 
+	return nil
+}
+
+func testWriteConnector(ctx context.Context, conn connectors.WriteConnector) error {
 	// IMPORTANT: every time this test is run, it will create a new Account
 	// in SFDC instance. Will need to delete those out at later date.
 	writtenRecordId, err := testSalesforceValidCreate(ctx, conn)
@@ -115,7 +125,7 @@ func testConnector(ctx context.Context, conn connectors.Connector) error {
 const accountNumber = 123
 
 // testSalesforceValidCreate will create a valid record in Salesforce.
-func testSalesforceValidCreate(ctx context.Context, conn connectors.Connector) (string, error) {
+func testSalesforceValidCreate(ctx context.Context, conn connectors.WriteConnector) (string, error) {
 	writeRes, err := conn.Write(ctx, connectors.WriteParams{
 		ObjectName: "Account",
 		RecordData: map[string]interface{}{
@@ -142,7 +152,7 @@ func testSalesforceValidCreate(ctx context.Context, conn connectors.Connector) (
 const accountNumber2 = 456
 
 // testSalesforceValidUpdate will update existing record in Salesforce.
-func testSalesforceValidUpdate(ctx context.Context, conn connectors.Connector, writtenRecordId string) error {
+func testSalesforceValidUpdate(ctx context.Context, conn connectors.WriteConnector, writtenRecordId string) error {
 	writeRes, err := conn.Write(ctx, connectors.WriteParams{
 		ObjectName: "Account",
 		RecordData: map[string]interface{}{