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
5 changes: 1 addition & 4 deletions connector/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,10 +343,7 @@ func newSalesforceJWTConnector(params common.ConnectorParams) (*salesforce.Conne
}

func newHubspotConnector(params common.ConnectorParams) (*hubspot.Connector, error) {
return hubspot.NewConnector(
hubspot.WithAuthenticatedClient(params.AuthenticatedClient),
hubspot.WithModule(params.Module),
)
return hubspot.NewConnector(params)
}

func newDocusignConnector(
Expand Down
12 changes: 0 additions & 12 deletions providers/hubspot/client.go

This file was deleted.

76 changes: 34 additions & 42 deletions providers/hubspot/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,73 +5,65 @@ import (

"github.com/amp-labs/connectors"
"github.com/amp-labs/connectors/common"
"github.com/amp-labs/connectors/common/paramsbuilder"
"github.com/amp-labs/connectors/internal/components"
"github.com/amp-labs/connectors/providers"
"github.com/amp-labs/connectors/providers/hubspot/internal/crm"
"github.com/amp-labs/connectors/providers/hubspot/internal/crm/core"
)

// Connector provides integration with Hubspot provider.
// Connector implements the HubSpot integration.
//
// The CRM module is undergoing partial migration: some operations are implemented directly within Connector,
// while others are delegated to specialized sub-adapters (see below).
// These sub-adapters will be consolidated as the migration completes under "crm.Adapter".
// HubSpot is modeled as a single connector.
// Unlike multi-module providers, all supported operations belong directly to Connector.
//
// Complex feature sets may still live in dedicated internal packages
// (for example batch, search, or subscriptions), but those packages are
// implementation details rather than top-level modules.
//
// The long-term direction is for Connector to own all operations directly,
// with reusable feature strategies embedded as needed.
type Connector struct {
Client *common.JSONHTTPClient
providerInfo *providers.ProviderInfo
moduleInfo *providers.ModuleInfo
moduleID common.ModuleID
// Shared connector infrastructure.
*components.Connector

// crmAdapter handles the core Hubspot CRM module.
// It provides dedicated support for HubspotCRM-specific functionality.
crmAdapter *crm.Adapter
// 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
}

var _ connectors.WebhookVerifierConnector = &Connector{}

// NewConnector returns a new Hubspot connector.
// Nearly all of the logic for this connector assumes that the module is CRM (url construction, etc)
// When we have to add support for other modules, it might be best to create a separate internal package.
func NewConnector(opts ...Option) (conn *Connector, outErr error) {
params, err := paramsbuilder.Apply(parameters{}, opts,
WithModule(common.ModuleRoot), // The module is resolved on behalf of the user if the option is missing.
)
if err != nil {
return nil, err
}

conn = &Connector{
Client: &common.JSONHTTPClient{
HTTPClient: params.Client.Caller,
},
moduleID: params.Module.Selection.ID,
}
// 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)
})
}

conn.providerInfo, err = providers.ReadInfo(providers.Hubspot)
if err != nil {
return nil, err
func constructor(base *components.Connector, params *common.ConnectorParams) (*Connector, error) {
connector := &Connector{
Connector: base,
}

conn.Client.HTTPClient.Base = conn.providerInfo.BaseURL
// Note: error handler must return common.HTTPError.
// Check method in the internal package "custom", method "readGroupName" which relies on error casting.
conn.Client.HTTPClient.ErrorHandler = core.InterpretJSONError
conn.moduleInfo = conn.providerInfo.ReadModuleInfo(conn.moduleID)
connector.SetErrorHandler(core.InterpretJSONError)

connectorParams, err := newParams(opts)
if err != nil {
return nil, err
}
var err error

conn.crmAdapter, err = crm.NewAdapter(connectorParams)
connector.delegate, err = crm.NewAdapter(params)
if err != nil {
return nil, err
}

return conn, nil
return connector, nil
}

func (c *Connector) Search(ctx context.Context, params *common.SearchParams) (*common.SearchResult, error) {
// Delegated.
return c.crmAdapter.Search(ctx, params)
return c.delegate.Search(ctx, params)
}
15 changes: 7 additions & 8 deletions providers/hubspot/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ type objectMetadataError struct {
func (c *Connector) UpsertMetadata(
ctx context.Context, params *common.UpsertMetadataParams,
) (*common.UpsertMetadataResult, error) {
// Delegated.
return c.crmAdapter.UpsertMetadata(ctx, params)
return c.delegate.UpsertMetadata(ctx, params)
}

// ListObjectMetadata returns object metadata for each object name provided.
Expand Down Expand Up @@ -128,7 +127,7 @@ func (c *Connector) getObjectMetadataFromPropertyAPI(
return nil, err
}

rsp, err := c.Client.Get(ctx, url.String())
rsp, err := c.JSONHTTPClient().Get(ctx, url.String())
if err != nil {
return nil, fmt.Errorf("error fetching HubSpot fields: %w", err)
}
Expand Down Expand Up @@ -171,12 +170,12 @@ func (c *Connector) getObjectMetadataFromCRMSearch(
})
if err != nil {
// Ignore an error and fallback to static schema.
return metadata.Schemas.SelectOne(c.moduleID, objectName)
return metadata.Schemas.SelectOne(c.Module(), objectName)
}

if len(readResult.Data) == 0 {
// Read returned no rows.
return metadata.Schemas.SelectOne(c.moduleID, objectName)
return metadata.Schemas.SelectOne(c.Module(), objectName)
}

fields := make(map[string]common.FieldMetadata)
Expand Down Expand Up @@ -225,7 +224,7 @@ func (c *Connector) GetAccountInfo(ctx context.Context) (*AccountInfo, *common.J
return nil, nil, err
}

resp, err := c.Client.Get(ctx, url.String())
resp, err := c.JSONHTTPClient().Get(ctx, url.String())
if err != nil {
return nil, resp, fmt.Errorf("error fetching HubSpot token info: %w", err)
}
Expand Down Expand Up @@ -393,7 +392,7 @@ func (c *Connector) fetchExternalMetadataEnumValues(
// For each external field that we support make an API call to fetch enumeration options.
// Store this values for each field within each object.
for _, discovery := range externalFields {
rsp, err := c.Client.Get(ctx, c.getURLFromRoot(discovery.EndpointPath))
rsp, err := c.JSONHTTPClient().Get(ctx, c.getURLFromRoot(discovery.EndpointPath))
if err != nil {
return nil, fmt.Errorf("error resolving external metadata values for HubSpot: %w", err)
}
Expand Down Expand Up @@ -525,7 +524,7 @@ func (c *Connector) fetchRequiredFieldsBestEffort(
return nil, err
}

rsp, err := c.Client.Get(ctx, url.String())
rsp, err := c.JSONHTTPClient().Get(ctx, url.String())
if err != nil {
if isMissingSchemasScope(err) {
// User does not have permission to access the schema endpoint.
Expand Down
13 changes: 8 additions & 5 deletions providers/hubspot/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,17 +386,20 @@ func TestListObjectMetadata(t *testing.T) { // nolint:funlen,gocognit,cyclop,mai

func constructTestConnector(serverURL string) (*Connector, error) {
connector, err := NewConnector(
WithAuthenticatedClient(mockutils.NewClient()),
WithModule(providers.ModuleHubspotCRM),
common.ConnectorParams{
Module: providers.ModuleHubspotCRM,
AuthenticatedClient: mockutils.NewClient(),
},
)
if err != nil {
return nil, err
}

// for testing we want to redirect calls to our mock server
connector.providerInfo.BaseURL = mockutils.ReplaceURLOrigin(connector.providerInfo.BaseURL, serverURL)
connector.moduleInfo.BaseURL = mockutils.ReplaceURLOrigin(connector.moduleInfo.BaseURL, serverURL)
connector.crmAdapter.SetUnitTestBaseURL(mockutils.ReplaceURLOrigin(connector.moduleInfo.BaseURL, serverURL))
connector.SetUnitTestMockServerBaseURL(serverURL)
if connector.delegate != nil {
connector.delegate.SetUnitTestMockServerBaseURL(serverURL)
}

return connector, nil
}
Expand Down
22 changes: 0 additions & 22 deletions providers/hubspot/modules.go

This file was deleted.

64 changes: 0 additions & 64 deletions providers/hubspot/params.go

This file was deleted.

10 changes: 0 additions & 10 deletions providers/hubspot/provider.go

This file was deleted.

4 changes: 2 additions & 2 deletions providers/hubspot/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (c *Connector) Read(ctx context.Context, config common.ReadParams) (*common
return nil, err
}

rsp, err := c.Client.Get(ctx, url)
rsp, err := c.JSONHTTPClient().Get(ctx, url)
if err != nil {
return nil, err
}
Expand All @@ -83,7 +83,7 @@ func (c *Connector) Read(ctx context.Context, config common.ReadParams) (*common
core.GetRecords,
core.GetNextRecordsURL,
associations.CreateDataMarshallerWithAssociations(
ctx, c.crmAdapter.AssociationsFiller, config.ObjectName, config.AssociatedObjects),
ctx, c.delegate.AssociationsFiller, config.ObjectName, config.AssociatedObjects),
config.Fields,
)
}
Expand Down
2 changes: 1 addition & 1 deletion providers/hubspot/record-count.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (c *Connector) GetRecordCount(
}

// Execute the search request
response, err := c.Client.Post(ctx, url, filterBody)
response, err := c.JSONHTTPClient().Post(ctx, url, filterBody)
if err != nil {
return nil, fmt.Errorf("failed to execute search request: %w", err)
}
Expand Down
4 changes: 2 additions & 2 deletions providers/hubspot/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (c *Connector) GetRecordsByIds(
"properties": fields,
}

resp, err := c.Client.Post(ctx, u, body)
resp, err := c.JSONHTTPClient().Post(ctx, u, body)
if err != nil {
return nil, err
}
Expand All @@ -82,7 +82,7 @@ func (c *Connector) GetRecordsByIds(
}

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

return marshaller(records, fields)
Expand Down
6 changes: 3 additions & 3 deletions providers/hubspot/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (c *Connector) ReadUsingSearchAPI(ctx context.Context, config SearchParams)
return nil, err
}

rsp, err := c.Client.Post(ctx, url, makeFilterBody(config))
rsp, err := c.JSONHTTPClient().Post(ctx, url, makeFilterBody(config))
if err != nil {
return nil, err
}
Expand All @@ -72,7 +72,7 @@ func (c *Connector) ReadUsingSearchAPI(ctx context.Context, config SearchParams)
core.GetRecords,
core.GetNextRecordsAfter,
associations.CreateDataMarshallerWithAssociations(
ctx, c.crmAdapter.AssociationsFiller, config.ObjectName, config.AssociatedObjects),
ctx, c.delegate.AssociationsFiller, config.ObjectName, config.AssociatedObjects),
config.Fields,
)
}
Expand All @@ -97,7 +97,7 @@ func (c *Connector) searchCRM(
return nil, err
}

rsp, err := c.Client.Post(ctx, url, payload)
rsp, err := c.JSONHTTPClient().Post(ctx, url, payload)
if err != nil {
return nil, err
}
Expand Down
8 changes: 0 additions & 8 deletions providers/hubspot/string.go

This file was deleted.

Loading
Loading