connectors

package module
v0.0.0-...-d136c4b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 24, 2024 License: MIT Imports: 14 Imported by: 1

README

Ampersand Connectors

This is a Go library that makes it easier to make API calls to SaaS products such as Salesforce and Hubspot. It handles constructing the correct API requests given desired objects and fields.

It can be either be used as a standalone library, or as a part of the Ampersand platform, which offers additional benefits such as:

  • Handling auth flows
  • Orchestration of scheduled reads, real-time writes, or bulk writes
  • Handling API quotas from SaaS APIs
  • A dashboard for observability and troubleshooting

Sample usage:

import (
  "context"
  "fmt"
  "net/http"
  "time"

  "github.com/amp-labs/connectors"
  "github.com/amp-labs/connectors/salesforce"
  "golang.org/x/oauth2"
)

const (
  // Replace these with your own values.
  Workspace = "<workspace>"
  OAuthClientId = "<client id>"
  OAuthClentSecret = "<client secret>"
  OAuthAccessToken = "<access token>"
  OAuthRefreshToken = "<refresh token>"

)

// Replace with when the access token will expire,
// or leave as-is to have the token be refreshed right away.
var AccessTokenExpiry = time.Now().Add(-1 * time.Hour)

func main() {
  // Set up the OAuth2 config
  cfg := &oauth2.Config{
    ClientID:     OAuthClientId,
    ClientSecret: OAuthClentSecret,
    Endpoint: oauth2.Endpoint{
      AuthURL:   fmt.Sprintf("https://%s.my.salesforce.com/services/oauth2/authorize", Workspace),
      TokenURL:  fmt.Sprintf("https://%s.my.salesforce.com/services/oauth2/token", Workspace),
      AuthStyle: oauth2.AuthStyleInParams,
    },
  }

  // Set up the OAuth2 token (obtained from Salesforce by authenticating)
  tok := &oauth2.Token{
    AccessToken:  OAuthAccessToken,
    RefreshToken: OAuthRefreshToken,
    TokenType:    "bearer",
    Expiry:       AccessTokenExpiry,
  }

  // Create the Salesforce client
  client, err := connectors.Salesforce(
    salesforce.WithClient(context.Background(), http.DefaultClient, cfg, tok),
    salesforce.WithWorkspace(Workspace))
  if err != nil {
    panic(err)
  }

  // Make a request to Salesforce
  result, err := client.Read(context.Background(), connectors.ReadParams{
    ObjectName: "Contact",
    Fields: []string{"FirstName", "LastName", "Email"},
  })
  if err == nil {
    fmt.Printf("Result is %v", result)
  }
}

Supported connectors

Browse the catalog file to see a list of all the connectors that Ampersand supports, and which features are supported for connector.

Ways to initialize a Connector

There are 3 ways to initialize a Connector:

  1. Initializing a provider-specific Connector (returns a concrete type). This method of initialization will allow you to use methods that only exist for that provider.
client, err := connectors.Salesforce(
    salesforce.WithClient(context.Background(), http.DefaultClient, cfg, tok),
    salesforce.WithWorkspace(Workspace))
  1. Initializing a generic Connector (returns an interface). This method of initialization will only allow you to use methods that are common to all providers. This is helpful if you would like your code to be provider-agnostic.
client, err := connectors.Salesforce.New(
    salesforce.WithClient(context.Background(), http.DefaultClient, cfg, tok),
    salesforce.WithWorkspace(Workspace))
  1. With string parameter for API name (this is useful if you are parsing the API name from a config file, but should be avoided otherwise because it is not typesafe). This returns a generic Connector (returns an interface).
client, err := connectors.New("salesforce", map[string]any{"workspace": "salesforce-instance-name"})

Basic connectors

Basic connectors allow you to proxy through requests to a SaaS provider via Ampersand.

Adding a new provider

To add a new basic connector that allows proxying through the ampersand platform, you need to add a new entry to the providers.yaml file. The entry should have some required fields which are tagged with validate: required in the providers/types.go file.

Initialization

Note: If your provider requires variables to be replaced in the catalog (providers.yaml), use the WithCatalogSubstitutions option to replace placeholders with actual values. If you don't, the provider info will be incomplete and the connector will not work.

For example, a provider may use {{workspace}} in an option (maybe in the base URL) which needs to be replaced with an actual customer instance name. In that case, you would initialize the connector like this:

conn, err := basic.NewConnector(
    providers.SomeProvider,
    basic.WithClient(context.Background(), http.DefaultClient, cfg, tok),
    
    // WithCatalogSubstitutions allows you to replace placeholders in the catalog (providers.yaml) with actual values.
    basic.WithCatalogSubstitutions(map[string]string{
		"workspace": "customer-instance-ref"
	}),
)

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrAccessToken represents a token which isn't valid.
	ErrAccessToken = common.ErrAccessToken

	// ErrApiDisabled means a customer didn't enable this API on their SaaS instance.
	ErrApiDisabled = common.ErrApiDisabled

	// ErrRetryable represents a temporary error. Can retry.
	ErrRetryable = common.ErrRetryable

	// ErrCaller represents non-retryable errors caused by bad input from the caller.
	ErrCaller = common.ErrCaller

	// ErrServer represents non-retryable errors caused by something on the server.
	ErrServer = common.ErrServer

	// ErrUnknownConnector represents an unknown connector.
	ErrUnknownConnector = errors.New("unknown connector")
)

We re-export the following errors so that they can be handled by consumers of this library.

Functions

This section is empty.

Types

type API

type API[Conn Connector, Option any] func(opts ...Option) (Conn, error)

API is a function that returns a Connector. It's used as a factory.

var Hubspot API[*hubspot.Connector, hubspot.Option] = hubspot.NewConnector //nolint:gochecknoglobals

Hubspot is an API that returns a new Hubspot Connector.

var Intercom API[*intercom.Connector, intercom.Option] = intercom.NewConnector //nolint:gochecknoglobals

Intercom is an API that returns a new Intercom Connector.

var MSDynamicsCRM API[*microsoftdynamicscrm.Connector, microsoftdynamicscrm.Option] = microsoftdynamicscrm.NewConnector //nolint:gochecknoglobals,lll

MSDynamicsCRM is an API that returns a new MS Dynamics 365 Sales Connector.

var Mock API[*mock.Connector, mock.Option] = mock.NewConnector //nolint:gochecknoglobals

Mock is an API that returns a new Mock Connector.

var Outreach API[*outreach.Connector, outreach.Option] = outreach.NewConnector //nolint:gochecknoglobals

Outreach is an API that returns a new Outreach Connector.

var Salesforce API[*salesforce.Connector, salesforce.Option] = salesforce.NewConnector //nolint:gochecknoglobals

Salesforce is an API that returns a new Salesforce Connector.

var Salesloft API[*salesloft.Connector, salesloft.Option] = salesloft.NewConnector //nolint:gochecknoglobals

Salesloft is an API that returns a new Salesloft Connector.

func (API[Conn, Option]) New

func (a API[Conn, Option]) New(opts ...Option) (Connector, error)

New returns a new Connector. It's a convenience wrapper around the API.

type AuthMetadataConnector

type AuthMetadataConnector interface {
	Connector

	GetPostAuthInfo(ctx context.Context) (*common.PostAuthInfo, error)
}

type Connector

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

	// Provider returns the connector provider.
	Provider() providers.Provider
}

Connector is an interface that can be used to implement a connector with basic configuration about the provider.

func New

func New(provider providers.Provider, opts map[string]any) (Connector, error)

New returns a new Connector. The signature is generic to facilitate more flexible caller setup (e.g. constructing a new connector based on parsing a config file, whose exact params aren't known until runtime). However, if you can use the API.New form, it's preferred, since you get type safety and more readable code.

type DeleteConnector

type DeleteConnector interface {
	Connector

	Delete(ctx context.Context, params DeleteParams) (*DeleteResult, error)
}

DeleteConnector is an interface that extends the Connector interface with delete capabilities.

type DeleteParams

type DeleteParams = common.DeleteParams

We re-export the following types so that they can be used by consumers of this library.

type DeleteResult

type DeleteResult = common.DeleteResult

We re-export the following types so that they can be used by consumers of this library.

type ErrorWithStatus

type ErrorWithStatus = common.HTTPStatusError

We re-export the following types so that they can be used by consumers of this library.

type ListObjectMetadataResult

type ListObjectMetadataResult = common.ListObjectMetadataResult

We re-export the following types so that they can be used by consumers of this library.

type ObjectMetadataConnector

type ObjectMetadataConnector interface {
	Connector

	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 ReadConnector

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
	// passing the NextPage value correctly, and by terminating the loop when
	// Done is true. The caller is also responsible for handling errors.
	// Authentication corner cases are handled internally, but all other errors
	// are returned to the caller.
	Read(ctx context.Context, params ReadParams) (*ReadResult, error)
}

ReadConnector is an interface that extends the Connector interface with read capabilities.

type ReadParams

type ReadParams = common.ReadParams

We re-export the following types so that they can be used by consumers of this library.

type ReadResult

type ReadResult = common.ReadResult

We re-export the following types so that they can be used by consumers of this library.

type WriteConnector

type WriteConnector interface {
	Connector

	Write(ctx context.Context, params WriteParams) (*WriteResult, error)
}

WriteConnector is an interface that extends the Connector interface with write capabilities.

type WriteParams

type WriteParams = common.WriteParams

We re-export the following types so that they can be used by consumers of this library.

type WriteResult

type WriteResult = common.WriteResult

We re-export the following types so that they can be used by consumers of this library.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL