Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions providers/hubspot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@ result, err := client.Search(context.Background(), hubspot.SearchParams{
},
})
```

# Docs

[Hubspot CRM](https://developers.hubspot.com/docs/guides/crm/understanding-the-crm)
55 changes: 35 additions & 20 deletions providers/hubspot/connector.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package hubspot

import (
"context"

"github.com/amp-labs/connectors"
"github.com/amp-labs/connectors/common"
"github.com/amp-labs/connectors/internal/components"
"github.com/amp-labs/connectors/internal/components/deleter"
"github.com/amp-labs/connectors/internal/components/operations"
"github.com/amp-labs/connectors/providers"
"github.com/amp-labs/connectors/providers/hubspot/internal/crm"
"github.com/amp-labs/connectors/providers/hubspot/internal/crm/associations"
"github.com/amp-labs/connectors/providers/hubspot/internal/crm/batch"
"github.com/amp-labs/connectors/providers/hubspot/internal/crm/core"
"github.com/amp-labs/connectors/providers/hubspot/internal/crm/custom"
"github.com/amp-labs/connectors/providers/hubspot/internal/crm/search"
)

// Connector implements the HubSpot integration.
Expand All @@ -29,23 +32,25 @@ type Connector struct {
// Provides access to an authenticated client.
common.RequireAuthenticatedClient

// Temporary grouping.
// TODO this adapter contents should dissolve into this connector.
// The idea of CRM module should cease to exist. Hubspot is but one entity.
delegate *crm.Adapter
// Operations
components.Deleter

// These delegate complex functionality to keep Connector modular and prevent code bloat.
customAdapter *custom.Adapter // used for connectors.UpsertMetadataConnector capabilities.
batchAdapter *batch.Adapter // used for connectors.BatchWriteConnector capabilities.
searchStrategy *search.Strategy // used for connectors.SearchConnector capabilities.
associationsFiller associations.Filler
}

var _ connectors.WebhookVerifierConnector = &Connector{}

// NewConnector returns a new Hubspot connector.
// Hubspot connector still owns CRM functionality. Not every CRM feature is located under `crm` package.
func NewConnector(params common.ConnectorParams) (*Connector, error) {
return components.Initialize(providers.Hubspot, params, func(base *components.Connector) (*Connector, error) {
return constructor(base, &params)
})
return components.Initialize(providers.Hubspot, params, constructor)
}

func constructor(base *components.Connector, params *common.ConnectorParams) (*Connector, error) {
func constructor(base *components.Connector) (*Connector, error) {
connector := &Connector{
Connector: base,
}
Expand All @@ -54,16 +59,26 @@ func constructor(base *components.Connector, params *common.ConnectorParams) (*C
// Check method in the internal package "custom", method "readGroupName" which relies on error casting.
connector.SetErrorHandler(core.InterpretJSONError)

var err error
connector.Deleter = deleter.NewHTTPDeleter(
connector.HTTPClient().Client,
components.NewEmptyEndpointRegistry(),
connector.ProviderContext.Module(),
operations.DeleteHandlers{
BuildRequest: connector.buildDeleteRequest,
ParseResponse: connector.parseDeleteResponse,
ErrorHandler: core.InterpretJSONError,
},
)

connector.delegate, err = crm.NewAdapter(params)
if err != nil {
return nil, err
}
connector.customAdapter = custom.NewAdapter(connector.JSONHTTPClient(), connector.ModuleInfo())
associationsStrategy := associations.NewStrategy(
connector.JSONHTTPClient(), connector.ModuleInfo(), connector.ProviderInfo(),
)
connector.associationsFiller = associationsStrategy
connector.batchAdapter = batch.NewAdapter(connector.HTTPClient(), connector.ModuleInfo(), associationsStrategy)
connector.searchStrategy = search.NewStrategy(
connector.JSONHTTPClient(), connector.ModuleInfo(), connector.associationsFiller,
)

return connector, nil
}

func (c *Connector) Search(ctx context.Context, params *common.SearchParams) (*common.SearchResult, error) {
Comment thread
Cobalt0s marked this conversation as resolved.
return c.delegate.Search(ctx, params)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package crm
package hubspot

import (
"context"
Expand All @@ -9,8 +9,8 @@ import (
"github.com/amp-labs/connectors/internal/httpkit"
)

func (a *Adapter) buildDeleteRequest(ctx context.Context, params common.DeleteParams) (*http.Request, error) {
url, err := a.getDeleteURL(params.ObjectName, params.RecordId)
func (c *Connector) buildDeleteRequest(ctx context.Context, params common.DeleteParams) (*http.Request, error) {
url, err := c.getDeleteURL(params.ObjectName, params.RecordId)
if err != nil {
return nil, err
}
Expand All @@ -23,7 +23,7 @@ func (a *Adapter) buildDeleteRequest(ctx context.Context, params common.DeletePa
return req, nil
}

func (a *Adapter) parseDeleteResponse(
func (c *Connector) parseDeleteResponse(
ctx context.Context,
params common.DeleteParams,
request *http.Request,
Expand Down
5 changes: 0 additions & 5 deletions providers/hubspot/internal/crm/README.md

This file was deleted.

95 changes: 0 additions & 95 deletions providers/hubspot/internal/crm/adapter.go

This file was deleted.

2 changes: 1 addition & 1 deletion providers/hubspot/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type objectMetadataError struct {
func (c *Connector) UpsertMetadata(
ctx context.Context, params *common.UpsertMetadataParams,
) (*common.UpsertMetadataResult, error) {
return c.delegate.UpsertMetadata(ctx, params)
return c.customAdapter.UpsertMetadata(ctx, params)
}

// ListObjectMetadata returns object metadata for each object name provided.
Expand Down
3 changes: 0 additions & 3 deletions providers/hubspot/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,6 @@ func constructTestConnector(serverURL string) (*Connector, error) {

// for testing we want to redirect calls to our mock server
connector.SetUnitTestMockServerBaseURL(serverURL)
if connector.delegate != nil {
connector.delegate.SetUnitTestMockServerBaseURL(serverURL)
}

return connector, nil
}
Expand Down
2 changes: 1 addition & 1 deletion providers/hubspot/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (c *Connector) Read(ctx context.Context, config common.ReadParams) (*common
core.GetRecords,
core.GetNextRecordsURL,
associations.CreateDataMarshallerWithAssociations(
ctx, c.delegate.AssociationsFiller, config.ObjectName, config.AssociatedObjects),
ctx, c.associationsFiller, config.ObjectName, config.AssociatedObjects),
config.Fields,
)
}
Expand Down
2 changes: 1 addition & 1 deletion providers/hubspot/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (c *Connector) GetRecordsByIds(
}

marshaller := associations.CreateDataMarshallerWithAssociations(
ctx, c.delegate.AssociationsFiller, objectName, associationsList,
ctx, c.associationsFiller, objectName, associationsList,
)

return marshaller(records, fields)
Expand Down
6 changes: 5 additions & 1 deletion providers/hubspot/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ const (
searchPageSize = "200"
)

func (c *Connector) Search(ctx context.Context, params *common.SearchParams) (*common.SearchResult, error) {
return c.searchStrategy.Search(ctx, params)
}

// ReadUsingSearchAPI uses the POST /search endpoint to filter object records and return the result.
// This endpoint has a limit of 10,000 records. If the result has more than 10,000 records,
// the caller should employ sorting to paginate through the result on the client side.
Expand Down Expand Up @@ -72,7 +76,7 @@ func (c *Connector) ReadUsingSearchAPI(ctx context.Context, config SearchParams)
core.GetRecords,
core.GetNextRecordsAfter,
associations.CreateDataMarshallerWithAssociations(
ctx, c.delegate.AssociationsFiller, config.ObjectName, config.AssociatedObjects),
ctx, c.associationsFiller, config.ObjectName, config.AssociatedObjects),
config.Fields,
)
}
Expand Down
5 changes: 5 additions & 0 deletions providers/hubspot/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,8 @@ func (c *Connector) getURLFromRoot(relativePath string) string {
func (c *Connector) getRootProviderURL() string {
return c.ProviderInfo().BaseURL
}

// https://developers.hubspot.com/docs/api-reference/latest/crm/objects/contacts/delete-contact
func (c *Connector) getDeleteURL(objectName, recordID string) (*urlbuilder.URL, error) {
return urlbuilder.New(c.ModuleInfo().BaseURL, "objects", core.APIVersion2026March, objectName, recordID)
}
7 changes: 1 addition & 6 deletions providers/hubspot/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"strings"

"github.com/amp-labs/connectors"
"github.com/amp-labs/connectors/common"
"github.com/amp-labs/connectors/common/logging"
"github.com/amp-labs/connectors/internal/datautils"
Expand Down Expand Up @@ -74,9 +73,5 @@ func (c *Connector) Write(ctx context.Context, config common.WriteParams) (*comm
}

func (c *Connector) BatchWrite(ctx context.Context, params *common.BatchWriteParam) (*common.BatchWriteResult, error) {
return c.delegate.BatchWrite(ctx, params)
}

func (c *Connector) Delete(ctx context.Context, params connectors.DeleteParams) (*connectors.DeleteResult, error) {
return c.delegate.Delete(ctx, params)
Comment thread
Cobalt0s marked this conversation as resolved.
return c.batchAdapter.BatchWrite(ctx, params)
}
Loading