common

package
v0.0.0-...-22dd133 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2025 License: MIT Imports: 39 Imported by: 1

Documentation

Overview

nolint:ireturn

Index

Constants

View Source
const (

	// HeaderModeAppend appends the header to the request.
	HeaderModeAppend

	// HeaderModeOverwrite unconditionally overwrites the header in the request.
	HeaderModeOverwrite

	// HeaderModeSetIfMissing sets the header in the request if it is not already set.
	HeaderModeSetIfMissing
)
View Source
const (

	// QueryParamModeAppend appends the QueryParam to the request.
	QueryParamModeAppend

	// QueryParamModeOverwrite unconditionally overwrites the QueryParam in the request.
	QueryParamModeOverwrite

	// QueryParamModeSetIfMissing sets the QueryParam in the request if it is not already set.
	QueryParamModeSetIfMissing
)
View Source
const (
	ValueTypeString  = "string"
	ValueTypeBoolean = "boolean"
	ValueTypeFloat   = "float" // float is more preferred than int if provider doesn't differentiate.
	ValueTypeInt     = "int"

	ValueTypeDate     = "date"
	ValueTypeDateTime = "datetime"

	ValueTypeSingleSelect = "singleSelect"
	ValueTypeMultiSelect  = "multiSelect"

	ValueTypeOther = "other"
)
View Source
const AWSServiceContextKey ctxKey = "AWSService"

Variables

View Source
var (
	// ErrInvalidModuleDeclaration is returned when a module entry in the Modules map is incorrectly defined.
	// This may occur if the map key does not match the module's declared ID,
	// or if required provider/module metadata is missing or malformed.
	ErrInvalidModuleDeclaration = errors.New("supported modules are not correctly defined")

	// ErrMissingModule can be returned when connector cannot resolve ModuleID.
	ErrMissingModule = errors.New("module not found")

	// ErrUnsupportedModule returned when provided module is not supported.
	ErrUnsupportedModule = errors.New("provided module is not supported")
)
View Source
var (
	ErrValidationFailed  = errors.New("validation failed")
	ErrMissingAuthClient = errors.New("authenticated client not given")
	ErrMissingMetadata   = errors.New("metadata not given")
	ErrMissingWorkspace  = errors.New("workspace not given")
)
View Source
var (
	// ErrAccessToken is a token which isn't valid.
	ErrAccessToken = errors.New("access token invalid")

	// ErrApiDisabled means a customer didn't enable this API on their SaaS instance.
	ErrApiDisabled = errors.New("API disabled")

	// ErrForbidden means the user doesn't have access to this resource.
	ErrForbidden = errors.New("forbidden")

	// ErrInvalidSessionId means the session ID is invalid.
	ErrInvalidSessionId = errors.New("invalid session id")

	// ErrUnableToLockRow means the resource couldn't be locked.
	ErrUnableToLockRow = errors.New("unable to lock row")

	// ErrInvalidGrant means the OAuth grant is invalid.
	ErrInvalidGrant = errors.New("invalid grant")

	// ErrLimitExceeded means a quota limit was exceeded.
	ErrLimitExceeded = errors.New("request limit exceeded")

	// ErrRetryable represents a temporary error. Can retry.
	ErrRetryable = errors.New("retryable error")

	// ErrCaller represents non-retryable errors caused by bad input from the caller.
	ErrCaller = errors.New("caller error")

	// ErrServer represents non-retryable errors caused by something on the server.
	ErrServer = errors.New("server error")

	// ErrUnknown represents an unknown status code response.
	ErrUnknown = errors.New("unknown error")

	// ErrNotJSON is returned when a response is not JSON.
	ErrNotJSON = errors.New("response is not JSON")

	// ErrNotXML is returned when a response is not XML.
	ErrNotXML = errors.New("response is not XML")

	// ErrMissingOauthConfig is returned when the OAuth config is missing.
	ErrMissingOauthConfig = errors.New("missing OAuth config")

	// ErrMissingRefreshToken is returned when the refresh token is missing.
	ErrMissingRefreshToken = errors.New("missing refresh token")

	// ErrEmptyBaseURL is returned when the URL is relative, and the base URL is empty.
	ErrEmptyBaseURL = errors.New("empty base URL")

	// ErrNotImplemented is returned when a method is not implemented.
	ErrNotImplemented = errors.New("not implemented")

	// ErrRequestFailed is returned when the request failed.
	ErrRequestFailed = errors.New("request failed")

	// ErrParseError is returned data parsing failed.
	ErrParseError = errors.New("parse error")

	// ErrBadRequest is returned when we get a 400 response from the provider.
	ErrBadRequest = errors.New("bad request")

	// ErrNotFound is returned when we get a 404 response from the provider.
	ErrNotFound = errors.New("not found")

	// ErrCursorGone is returned when a cursor used for pagination is no longer valid.
	ErrCursorGone = errors.New("pagination cursor gone or expired")

	// ErrMissingExpectedValues is returned when response data doesn't have values expected for processing.
	ErrMissingExpectedValues = errors.New("response data is missing expected values")

	// ErrPreprocessingWritePayload is returned when request payload supplied to connector "Write" method
	// couldn't be processed. Likely, the issue is within provided WriteParams.RecordData or implementation.
	ErrPreprocessingWritePayload = errors.New("failed preprocessing write payload")

	// ErrEmptyJSONHTTPResponse is returned when the JSONHTTPResponse is nil.
	ErrEmptyJSONHTTPResponse = errors.New("empty json http response")

	// ErrEmptyRecordIdResponse is returned when the response body doesn't have record id.
	ErrEmptyRecordIdResponse = errors.New("empty record id in response body")

	// ErrRecordDataNotJSON is returned when the record data in WriteParams is not JSON.
	ErrRecordDataNotJSON = errors.New("record data is not JSON")

	// ErrOperationNotSupportedForObject is returned when operation is not supported for this object.
	ErrOperationNotSupportedForObject = errors.New("operation is not supported for this object in this module")

	// ErrObjectNotSupported is returned when operation is not supported for this object.
	ErrObjectNotSupported = errors.New("operation is not supported for this object")

	// ErrResolvingURLPathForObject is returned when URL cannot be implied for object name.
	ErrResolvingURLPathForObject = errors.New("cannot resolve URL path for given object name")

	// ErrFailedToUnmarshalBody is returned when response body cannot be marshalled into some type.
	ErrFailedToUnmarshalBody = errors.New("failed to unmarshal response body")

	// ErrNextPageInvalid is returned when next page token provided in Read operation cannot be understood.
	ErrNextPageInvalid = errors.New("next page token is invalid")

	// ErrInvalidImplementation is returned when implementation assumption is broken.
	// This is not a client issue.
	ErrInvalidImplementation = errors.New("invalid implementation")

	// ErrPayloadNotURLForm is returned when payload is not string key-value pair
	// which could be encoded for POST with content type of application/x-www-form-urlencoded.
	ErrPayloadNotURLForm = errors.New("payload cannot be url-form encoded")

	// ErrResolvingCustomFields is returned when custom fields cannot be retrieved for Read or ListObjectMetadata.
	ErrResolvingCustomFields = errors.New("cannot resolve custom fields")

	ErrGetRecordNotSupportedForObject = errors.New("getRecord is not supported for the object")

	// ErrImplementation is returned when the code takes an unexpected or logically invalid execution path.
	// It should be used to explicitly catch cases that would otherwise lead to panics (e.g., nil pointer dereference).
	// This typically indicates a broken assumption or inconsistency in the implementation logic.
	ErrImplementation = errors.New("code took invalid execution path")
)
View Source
var (
	// ErrMissingObjects is returned when no objects are provided in the request.
	ErrMissingObjects = errors.New("no objects provided")

	// ErrEmptyObject is returned when empty string is used as an object name.
	// Some APIs, connectors could be strict about it.
	ErrEmptyObject = errors.New("object name is empty")

	// ErrMissingRecordID is returned when resource id is missing in the request.
	ErrMissingRecordID = errors.New("no object ID provided")

	// ErrMissingRecordData is returned when write data is missing in the request.
	ErrMissingRecordData = errors.New("no data provided")

	// ErrMissingFields is returned when no fields are provided for reading.
	ErrMissingFields = errors.New("no fields provided in ReadParams")

	// ErrSinceUntilChronOrder is returned when the 'since' timestamp is after the 'until' timestamp in ReadParams.
	ErrSinceUntilChronOrder = errors.New("since cannot come after until")
)
View Source
var (
	ErrNotXMLChildren = errors.New("children must be of type 'XMLData' or 'XMLString'")
	ErrNoSelfClosing  = errors.New("selfClosing cannot be true if children are not present")
	ErrNoParens       = errors.New("value cannot contain < or >")
)
View Source
var ErrFieldTypeUnknown = errors.New("unrecognized field type")
View Source
var ErrMissingAccessToken = errors.New("missing access token")

ErrMissingAccessToken returned when access token was not present in the context.Context.

View Source
var ErrMissingCSVData = errors.New("no CSV data provided")

ErrMissingCSVData is returned when no CSV data was given for the upload.

View Source
var ErrMissingContentType = errors.New("missing content type")
View Source
var ErrRequestAWSMissingService = errors.New("AWS request is missing Service name, supplied via context")

ErrRequestAWSMissingService is returned when deep connector implementation doesn't attach AWS service name into the context, therefore the request cannot be constructed for sending.

View Source
var HeaderFormURLEncoded = Header{
	Key:   "Content-Type",
	Value: "application/x-www-form-urlencoded",
}
View Source
var WithTrailingSlash = "/" //nolint:gochecknoglobals

Functions

func AddJSONContentTypeIfNotPresent

func AddJSONContentTypeIfNotPresent(req *http.Request) *http.Request

AddJSONContentTypeIfNotPresent adds the Content-Type header if it is not already present.

func AddSuffixIfNotExists

func AddSuffixIfNotExists(str string, suffix string) string

AddSuffixIfNotExists appends the suffix to the provided string.

func AssertType

func AssertType[T any](val any) (T, error)

func EnsureContentType

func EnsureContentType(pattern string, res *http.Response, errOnMissing bool) error

EnsureContentType ensures that the content type matches the given pattern. If errOnMissing is true, an error is returned if the content type is missing. Otherwise, the function returns nil.

func ExtractLowercaseFieldsFromRaw

func ExtractLowercaseFieldsFromRaw(fields []string, record map[string]any) map[string]any

ExtractLowercaseFieldsFromRaw returns a map of fields from a record. The fields are all returned in lowercase.

func GetResponseBodyOnce

func GetResponseBodyOnce(response *http.Response) []byte

func InterpretError

func InterpretError(res *http.Response, body []byte) error

InterpretError interprets the given HTTP response (in a fairly straightforward way) and returns an error that can be handled by the caller.

func MakeGetRequest

func MakeGetRequest(ctx context.Context, url string, headers []Header) (*http.Request, error)

MakeGetRequest creates a GET request with the given headers.

func MakeJSONGetRequest

func MakeJSONGetRequest(ctx context.Context, url string, headers []Header) (*http.Request, error)

MakeJSONGetRequest creates a GET request with the given headers and adds the Accept: application/json header. It then returns the request.

func NewHTTPError

func NewHTTPError(status int, body []byte, headers Headers, err error) error

NewHTTPError creates a new error with the given HTTP status.

func PrintRequestAndResponse

func PrintRequestAndResponse(req *http.Request, rsp *http.Response)

func RecordDataToMap

func RecordDataToMap(recordData any) (map[string]any, error)

RecordDataToMap converts WriteParams.RecordData into a map[string]any. If RecordData is already a map, it is returned directly. Otherwise, it is serialized to JSON and then deserialized back into a map.

func UnmarshalJSON

func UnmarshalJSON[T any](rsp *JSONHTTPResponse) (*T, error)

UnmarshalJSON deserializes the response body into the given type.

func ValidateParameters

func ValidateParameters(conn any, params ConnectorParams) error

ValidateParameters sees which interfaces conn implements, calls the relevant validation methods. nolint:cyclop

func WithAuthToken

func WithAuthToken(ctx context.Context, token AuthToken) context.Context

WithAuthToken returns a new context with the given auth token.

func WithRequestModifier

func WithRequestModifier(ctx context.Context, modifier RequestModifier) context.Context

WithRequestModifier adds a request modifier to the context. The request modifier will be called with the request before it is sent. This allows the caller to inject logic into the request, such as adding/removing headers or modifying the request body. Generally this should be used for debugging purposes only. Although there may be some use cases where it is useful to modify the request before it is sent. It can also double as an injectable observer function.

Types

type AWSClient

type AWSClient struct {
	// contains filtered or unexported fields
}

func (AWSClient) CloseIdleConnections

func (c AWSClient) CloseIdleConnections()

func (AWSClient) Do

func (c AWSClient) Do(req *http.Request) (*http.Response, error)

type Association

type Association struct {
	// ObjectID is the ID of the associated object.
	ObjectId string `json:"objectId"`
	// AssociationType is the type of association.
	AssociationType string         `json:"associationType,omitempty"`
	Raw             map[string]any `json:"raw,omitempty"`
}

Association is a struct that represents an association between two objects. If you think of an association as a directed edge between two nodes, then the ObjectID is the target node, and the AssociationType is the type of edge. The source node is represented by ReadResultRow.

type AssociationCardinality

type AssociationCardinality string

AssociationCardinality represents the cardinality of an association/relationship.

const (

	// AssociationCardinalityManyToOne indicates that many records in the referencing object
	// can reference a single record in the target object.
	AssociationCardinalityManyToOne AssociationCardinality = "many-to-one"

	// AssociationCardinalityOneToOne indicates that each record in the referencing object
	// can reference only one record in the target object, and vice versa.
	AssociationCardinalityOneToOne AssociationCardinality = "one-to-one"
)

func (AssociationCardinality) IsValid

func (ac AssociationCardinality) IsValid() bool

IsValid checks if the AssociationCardinality is known.

type AssociationDefinition

type AssociationDefinition struct {
	// AssociationType is the high-level association variety (e.g., 'foreignKey', 'lookup', 'ref').
	// The provider determines the exact behavior.
	AssociationType string `json:"associationType"`
	// TargetObject is the name of the referenced/parent object.
	TargetObject string `json:"targetObject"`
	// TargetField is the name of the referenced field on the target object.
	// Defaults to the target's primary key when omitted.
	TargetField string `json:"targetField,omitempty"`
	// Association cardinality from the referencing field's perspective (e.g., 'many-to-one', 'one-to-one').
	Cardinality AssociationCardinality `json:"cardinality,omitempty"`
	// OnDelete defines the behavior upon foreign object deletion, where supported.
	// E.g., 'cascade', 'restrict', 'setNull'.
	OnDelete AssociationOnDeleteAction `json:"onDelete,omitempty"`
	// Required means that, if true, a referenced record must exist (i.e., NOT NULL foreign key).
	Required bool `json:"required,omitempty"`
	// ReverseLookupFieldName is an optional inverse relationship/property name exposed on the target object.
	ReverseLookupFieldName string `json:"reverseLookupFieldName,omitempty"`
	// Labels represents optional UI labels for the association
	Labels *AssociationLabels `json:"labels,omitempty"`
}

AssociationDefinition defines relationship information for a field to another object. Note that not all providers will support all aspects of the association. This is a best-effort attempt to create a common schema for associations across providers.

In the event that a provider doesn't support a particular aspect of the association, and assuming that the field has a value, then the value should be ignored, and a warning should be added to the UpsertMetadataResult.

type AssociationLabels

type AssociationLabels struct {
	Singular string `json:"singular"`
	Plural   string `json:"plural"`
}

AssociationLabels represents UI labels for an association.

type AssociationOnDeleteAction

type AssociationOnDeleteAction string
const (

	// AssociationOnDeleteActionCascade means that when the parent record is deleted,
	// all child records referencing it are also deleted.
	AssociationOnDeleteActionCascade AssociationOnDeleteAction = "cascade"

	// AssociationOnDeleteActionRestrict means that the parent record cannot be deleted
	// if there are any child records referencing it.
	AssociationOnDeleteActionRestrict AssociationOnDeleteAction = "restrict"

	// AssociationOnDeleteActionSetNull means that when the parent record is deleted,
	// the foreign key field in the child records is set to NULL.
	AssociationOnDeleteActionSetNull AssociationOnDeleteAction = "setNull"
)

func (AssociationOnDeleteAction) IsValid

func (a AssociationOnDeleteAction) IsValid() bool

type AuthToken

type AuthToken string

AuthToken is a type alias for a string representing an authentication token. This can be used to store the token in a context.

func GetAuthToken

func GetAuthToken(ctx context.Context) (AuthToken, bool)

GetAuthToken returns the auth token from the context, if it exists.

func (AuthToken) String

func (t AuthToken) String() string

type AuthenticatedHTTPClient

type AuthenticatedHTTPClient interface {
	Do(req *http.Request) (*http.Response, error)
	CloseIdleConnections()
}

AuthenticatedHTTPClient is an interface for an http client which can automatically authenticate itself. This is useful for OAuth authentication, where the access token needs to be refreshed automatically. The signatures are a subset of http.Client, so it can be used as a (mostly) drop-in replacement.

func NewAWSClient

func NewAWSClient(ctx context.Context, client *http.Client,
	accessKeyID, accessKeySecret, region string,
) (AuthenticatedHTTPClient, error)

NewAWSClient constructs an AWSClient using Access Key ID and Secret. Keys can be obtained as described here: https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/getting-started.html#get-your-aws-access-keys

The HTTP client is scoped to a single AWS region but supports multiple AWS services. The request context must pass service domain via context key AWSServiceContextKey.

Features: * SHA256 payload hashing * SigV4 request signing: https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html

func NewApiKeyHeaderAuthHTTPClient

func NewApiKeyHeaderAuthHTTPClient(
	ctx context.Context,
	headerName, headerValue string,
	opts ...HeaderAuthClientOption,
) (AuthenticatedHTTPClient, error)

NewApiKeyHeaderAuthHTTPClient returns a new http client, with automatic API key authentication. Specifically this means that the client will automatically add the API key (as a header) to every request. HeaderValue must be in the correct format. This sometimes means adding prefix to the API Key.

func NewApiKeyQueryParamAuthHTTPClient

func NewApiKeyQueryParamAuthHTTPClient(
	ctx context.Context,
	queryParamName, apiKey string,
	opts ...QueryParamAuthClientOption,
) (AuthenticatedHTTPClient, error)

NewApiKeyQueryParamAuthHTTPClient returns a new http client, with automatic API key authentication. Specifically this means that the client will automatically add the API key (as a query param) to every request.

func NewBasicAuthHTTPClient

func NewBasicAuthHTTPClient(
	ctx context.Context,
	user, pass string,
	opts ...HeaderAuthClientOption,
) (AuthenticatedHTTPClient, error)

NewBasicAuthHTTPClient returns a new http client, with automatic Basic authentication. Specifically this means that the client will automatically add the Basic auth header to every request. The username and password are provided as arguments.

func NewCustomAuthHTTPClient

func NewCustomAuthHTTPClient(
	ctx context.Context,
	opts ...CustomAuthClientOption,
) (AuthenticatedHTTPClient, error)

NewCustomAuthHTTPClient returns a new http client, which will do generic header or query-param-based authentication. It does this by automatically adding the provided headers and/or query params to every request. There's no additional logic for refreshing tokens or anything like that. This is appropriate for APIs that require static but somewhat odd authentication mechanisms involving headers or query params.

func NewHeaderAuthHTTPClient

func NewHeaderAuthHTTPClient(
	ctx context.Context,
	opts ...HeaderAuthClientOption,
) (AuthenticatedHTTPClient, error)

NewHeaderAuthHTTPClient returns a new http client, which will do generic header-based authentication. It does this by automatically adding the provided headers to every request. There's no additional logic for refreshing tokens or anything like that. This is appropriate for APIs that use keys or basic auth.

func NewOAuthHTTPClient

func NewOAuthHTTPClient(ctx context.Context, opts ...OAuthOption) (AuthenticatedHTTPClient, error)

NewOAuthHTTPClient returns a new http client, with automatic OAuth authentication. Specifically this means that the client will automatically refresh the access token whenever it expires.

func NewQueryParamAuthHTTPClient

func NewQueryParamAuthHTTPClient(
	ctx context.Context,
	opts ...QueryParamAuthClientOption,
) (AuthenticatedHTTPClient, error)

NewQueryParamAuthHTTPClient returns a new http client, which will do generic query-param-based authentication. It does this by automatically adding the provided query params to every request. There's no additional logic for refreshing tokens or anything like that. This is appropriate for APIs that use keys encoded in the query params.

type CollapsedSubscriptionEvent

type CollapsedSubscriptionEvent interface {
	SubscriptionEventList() ([]SubscriptionEvent, error)
	RawMap() (map[string]any, error)
}

Some providers send multiple events in a single webhook payload. This interface is used to extract individual events to SubscriptionEvent type from a collapsed event for webhook parsing and processing.

type ConnectorParams

type ConnectorParams struct {
	Module ModuleID

	// AuthenticatedClient is a client for the connector that knows how to handle authentication for the provider.
	AuthenticatedClient AuthenticatedHTTPClient

	// Workspace is the provider workspace that the connector is connecting to. It could be a part of the metadata
	// map, but it is a common enough field that it is included here.
	Workspace string

	// Metadata is a map of key-value pairs that can be used to pass in additional information to the connector.
	// Generally this is used to substitute placeholders in the providerInfo, like workspace, server, etc, which is
	// information that is specific to the connection.
	Metadata map[string]string
}

ConnectorParams can be used to pass input parameters to the connector.

type CustomAuthClientOption

type CustomAuthClientOption func(params *customClientParams)

func WithCustomClient

func WithCustomClient(client *http.Client) CustomAuthClientOption

WithCustomClient sets the http client to use for the connector. Its usage is optional.

func WithCustomDebug

func WithCustomDebug(f func(req *http.Request, rsp *http.Response)) CustomAuthClientOption

WithCustomDebug sets a debug function to be called on every request and response, after the response has been received from the downstream API.

func WithCustomDynamicHeaders

func WithCustomDynamicHeaders(f DynamicHeadersGenerator) CustomAuthClientOption

WithCustomDynamicHeaders sets a function that will be called on every request to get additional headers to use. Use this for things like time-based tokens or loading headers from some external authority. The function can access a copy of the request object to use its metadata for generating headers.

func WithCustomDynamicQueryParams

func WithCustomDynamicQueryParams(f DynamicQueryParamsGenerator) CustomAuthClientOption

WithCustomDynamicQueryParams sets a function that will be called on every request to get additional query params to use. Use this for things like time-based tokens or loading query params from some external authority. The function can access a copy of the request object to use its metadata for generating query params.

func WithCustomHeaders

func WithCustomHeaders(headers ...Header) CustomAuthClientOption

WithCustomHeaders sets the headers to use for the connector. Its usage is optional.

func WithCustomIsUnauthorizedHandler

func WithCustomIsUnauthorizedHandler(
	f func(rsp *http.Response) bool,
) CustomAuthClientOption

WithCustomIsUnauthorizedHandler sets the function to call whenever the response is unauthorized (not necessarily 401). This is useful for handling the case where the server has invalidated the token, and the client needs to forcefully refresh. It's optional.

func WithCustomQueryParams

func WithCustomQueryParams(ps ...QueryParam) CustomAuthClientOption

WithCustomQueryParams sets the query params to use for the connector. Its usage is optional.

func WithCustomUnauthorizedHandler

func WithCustomUnauthorizedHandler(
	f func(hdrs []Header, params []QueryParam, req *http.Request, rsp *http.Response) (*http.Response, error),
) CustomAuthClientOption

WithCustomUnauthorizedHandler sets the function to call whenever the response is 401 unauthorized. This is useful for handling the case where the server has invalidated the credentials, and the client needs to refresh. It's optional.

type DeleteParams

type DeleteParams struct {
	// The name of the object we are deleting, e.g. "Account"
	ObjectName string // required

	// The external ID of the object instance we are removing.
	RecordId string // required
}

DeleteParams defines how we are deleting data in SaaS API.

func (DeleteParams) ValidateParams

func (p DeleteParams) ValidateParams() error

type DeleteResult

type DeleteResult struct {
	// Success is true if deletion succeeded.
	Success bool `json:"success"`
}

DeleteResult is what's returned from deleting data via the Delete call.

type DynamicHeadersGenerator

type DynamicHeadersGenerator func(*http.Request) ([]Header, error)

type DynamicQueryParamsGenerator

type DynamicQueryParamsGenerator func(*http.Request) (QueryParams, error)

type ErrorHandler

type ErrorHandler func(rsp *http.Response, body []byte) error

ErrorHandler allows the caller to inject their own HTTP error handling logic. All non-2xx responses will be passed to the error handler. If the error handler returns nil, then the error is ignored and the caller is responsible for handling the error. If the error handler returns an error, then that error is returned to the caller, as-is. Both the response and the response body are passed to the error handler as arguments.

type ErrorPostProcessor

type ErrorPostProcessor struct {
	Process func(err error) error
}

type FieldDefinition

type FieldDefinition struct {
	// FieldName is the identifier of the field, e.g. "My_Custom_Field".
	FieldName string `json:"fieldName"`
	// DisplayName is the human-readable name of the field, e.g. "My Custom Field".
	DisplayName string `json:"displayName"`
	// Description is an optional description of the field.
	Description string `json:"description,omitempty"`
	// ValueType is the data type of the field.
	ValueType FieldType `json:"valueType"`
	// Required indicates if the field is required.
	Required bool `json:"required,omitempty"`
	// Unique indicates if the field must be unique across all records.
	Unique bool `json:"unique,omitempty"`
	// Indexed indicates if the field should be indexed for faster search.
	Indexed bool `json:"indexed,omitempty"`
	// StringOptions contains additional options for string fields (if any).
	StringOptions *StringFieldOptions `json:"stringOptions,omitempty"`
	// NumericOptions contains additional options for numeric fields (if any).
	NumericOptions *NumericFieldOptions `json:"numericOptions,omitempty"`
	// Association defines association/relationship information for the field (if any).
	Association *AssociationDefinition `json:"association,omitempty"`
}

FieldDefinition represents a field definition. Note that not all providers will support all fields. This is a best-effort attempt to create a common schema for custom fields across providers.

In the event that a provider doesn't support a particular field, and assuming that the field has a value, then the value should be ignored, and a warning should be added to the UpsertMetadataResult.

type FieldMetadata

type FieldMetadata struct {
	// DisplayName is a human-readable field name.
	DisplayName string

	// ValueType is a set of Ampersand defined field types.
	ValueType ValueType

	// ProviderType is the raw type, a term used by provider API.
	// Each is mapped to an Ampersand ValueType.
	ProviderType string

	// ReadOnly would indicate if field can be modified or only read.
	ReadOnly bool

	// Values is a list of possible values for this field.
	// It is applicable only if the type is either singleSelect or multiSelect, otherwise slice is nil.
	Values []FieldValue
}

type FieldType

type FieldType string

FieldType represents the data type of a field.

const (
	FieldTypeString       FieldType = "string"
	FieldTypeBoolean      FieldType = "boolean"
	FieldTypeDate         FieldType = "date"
	FieldTypeDateTime     FieldType = "datetime"
	FieldTypeSingleSelect FieldType = "singleSelect"
	FieldTypeMultiSelect  FieldType = "multiSelect"
	FieldTypeInt          FieldType = "int"
	FieldTypeFloat        FieldType = "float"
)

func (FieldType) IsSelectionType

func (ft FieldType) IsSelectionType() bool

func (FieldType) IsValid

func (ft FieldType) IsValid() bool

IsValid checks if the FieldType is known.

type FieldUpsertResult

type FieldUpsertResult struct {
	// FieldName is the name of the field.
	FieldName string `json:"fieldName"`
	// Action indicates what action was taken (create, update, none).
	Action UpsertMetadataAction `json:"action"`
	// Metadata contains provider-specific metadata about the field (if any).
	// Specific keys/values will vary by provider. Considered strictly informational.
	Metadata map[string]any `json:"metadata,omitempty"`
	// Warnings contains any warnings that occurred during the upsert operation,
	// such as unsupported field attributes.
	Warnings []string `json:"warnings,omitempty"`
}

FieldUpsertResult is the result of an upsert operation for a single field. It indicates what action was taken (create, update, none) and any provider-specific metadata or warnings.

type FieldValue

type FieldValue struct {
	Value        string
	DisplayValue string
}

type FieldValues

type FieldValues []FieldValue

type FieldsMetadata

type FieldsMetadata map[string]FieldMetadata

func (FieldsMetadata) AddFieldWithDisplayOnly

func (f FieldsMetadata) AddFieldWithDisplayOnly(fieldName string, displayName string)

type HTTPClient

type HTTPClient struct {
	Base            string                  // optional base URL. If not set, then all URLs must be absolute.
	Client          AuthenticatedHTTPClient // underlying HTTP client. Required.
	ErrorHandler    ErrorHandler            // optional error handler. If not set, then the default error handler is used.
	ResponseHandler ResponseHandler         // optional, Allows mutation of the http.Response from the Saas API response.
}

HTTPClient is an HTTP client that handles OAuth access token refreshes.

func (*HTTPClient) Delete

func (h *HTTPClient) Delete(ctx context.Context,
	url string, headers ...Header,
) (*http.Response, []byte, error)

func (*HTTPClient) Get

func (h *HTTPClient) Get(ctx context.Context, url string, headers ...Header) (*http.Response, []byte, error)

Get makes a GET request to the given URL and returns the response. If the response is not a 2xx, an error is returned. If the response is a 401, the caller should refresh the access token and retry the request. If errorHandler is nil, then the default error handler is used. If not, the caller can inject their own error handling logic.

func (*HTTPClient) Patch

func (h *HTTPClient) Patch(ctx context.Context,
	url string, reqBody any, headers ...Header,
) (*http.Response, []byte, error)

Patch makes a PATCH request to the given URL and returns the response & response body. If the response is not a 2xx, an error is returned. If the response is a 401, the caller should refresh the access token and retry the request. If errorHandler is nil, then the default error handler is used. If not, the caller can inject their own error handling logic.

func (*HTTPClient) Post

func (h *HTTPClient) Post(ctx context.Context,
	url string, reqBody []byte, headers ...Header,
) (*http.Response, []byte, error)

Post makes a POST request to the given URL and returns the response & response body. If the response is not a 2xx, an error is returned. If the response is a 401, the caller should refresh the access token and retry the request. If errorHandler is nil, then the default error handler is used. If not, the caller can inject their own error handling logic.

func (*HTTPClient) Put

func (h *HTTPClient) Put(ctx context.Context,
	url string, reqBody any, headers ...Header,
) (*http.Response, []byte, error)

type HTTPError

type HTTPError struct {
	// Status is the original HTTP status.
	Status int

	// Headers are the HTTP headers of the response, if available.
	Headers Headers // optional

	// Body is the raw response body, if available.
	Body []byte // optional
	// contains filtered or unexported fields
}

HTTPError is an error that contains both an error and details about the HTTP response that caused the error. It includes the HTTP status code, headers, and body of the response. Body and Headers are optional and may be nil if not available.

func (HTTPError) Error

func (r HTTPError) Error() string

func (HTTPError) Unwrap

func (r HTTPError) Unwrap() error
type Header struct {
	Key   string     `json:"key"`
	Value string     `json:"value"`
	Mode  HeaderMode `json:"mode"`
}

Header is a key/value pair that can be added to a request.

func (Header) ApplyToRequest

func (h Header) ApplyToRequest(req *http.Request)

func (Header) String

func (h Header) String() string

type HeaderAuthClientOption

type HeaderAuthClientOption func(params *headerClientParams)

func WithDynamicHeaders

func WithDynamicHeaders(f DynamicHeadersGenerator) HeaderAuthClientOption

WithDynamicHeaders sets a function that will be called on every request to get additional headers to use. Use this for things like time-based tokens or loading headers from some external authority. The function can access a copy of the request object to use its metadata for generating headers.

func WithHeaderClient

func WithHeaderClient(client *http.Client) HeaderAuthClientOption

WithHeaderClient sets the http client to use for the connector. Its usage is optional.

func WithHeaderDebug

func WithHeaderDebug(f func(req *http.Request, rsp *http.Response)) HeaderAuthClientOption

WithHeaderDebug sets a debug function to be called on every request and response, after the response has been received from the downstream API.

func WithHeaderIsUnauthorizedHandler

func WithHeaderIsUnauthorizedHandler(
	f func(rsp *http.Response) bool,
) HeaderAuthClientOption

WithHeaderIsUnauthorizedHandler sets the function to call whenever the response is unauthorized (not necessarily 401). This is useful for handling the case where the server has invalidated the token, and the client needs to forcefully refresh. It's optional.

func WithHeaderUnauthorizedHandler

func WithHeaderUnauthorizedHandler(
	f func(hdrs []Header, req *http.Request, rsp *http.Response) (*http.Response, error),
) HeaderAuthClientOption

WithHeaderUnauthorizedHandler sets the function to call whenever the response is 401 unauthorized. This is useful for handling the case where the server has invalidated the credentials, and the client needs to refresh. It's optional.

func WithHeaders

func WithHeaders(headers ...Header) HeaderAuthClientOption

WithHeaders sets the headers to use for the connector. Its usage is optional.

type HeaderMode

type HeaderMode int

HeaderMode determines how the header should be applied to the request.

type Headers

type Headers []Header

func GetRequestHeaders

func GetRequestHeaders(request *http.Request) Headers

func GetResponseHeaders

func GetResponseHeaders(response *http.Response) Headers

func (Headers) ApplyToRequest

func (h Headers) ApplyToRequest(req *http.Request)

func (Headers) Has

func (h Headers) Has(target Header) bool

func (Headers) LogValue

func (h Headers) LogValue() slog.Value

type JSONHTTPClient

type JSONHTTPClient struct {
	HTTPClient         *HTTPClient        // underlying HTTP client. Required.
	ErrorPostProcessor ErrorPostProcessor // Errors returned from CRUD methods will go via this method. Optional.
}

JSONHTTPClient is an HTTP client which makes certain assumptions, such as that the response body is JSON. It also handles OAuth access token refreshes.

func (*JSONHTTPClient) Delete

func (j *JSONHTTPClient) Delete(ctx context.Context, url string, headers ...Header) (*JSONHTTPResponse, error)

func (*JSONHTTPClient) Get

func (j *JSONHTTPClient) Get(ctx context.Context, url string, headers ...Header) (*JSONHTTPResponse, error)

Get makes a GET request to the given URL and returns the response body as a JSON object. If the response is not a 2xx, an error is returned. If the response is a 401, the caller should refresh the access token and retry the request. If errorHandler is nil, then the default error handler is used. If not, the caller can inject their own error handling logic.

func (*JSONHTTPClient) Patch

func (j *JSONHTTPClient) Patch(ctx context.Context,
	url string, reqBody any, headers ...Header,
) (*JSONHTTPResponse, error)

func (*JSONHTTPClient) Post

func (j *JSONHTTPClient) Post(ctx context.Context,
	url string, reqBody any, headers ...Header,
) (*JSONHTTPResponse, error)

Post makes a POST request to the given URL and returns the response body as a JSON object. ReqBody must be JSON-serializable. If it is not, an error is returned. If the response is not a 2xx, an error is returned. If the response is a 401, the caller should refresh the access token and retry the request. If errorHandler is nil, then the default error handler is used. If not, the caller can inject their own error handling logic.

func (*JSONHTTPClient) Put

func (j *JSONHTTPClient) Put(ctx context.Context,
	url string, reqBody any, headers ...Header,
) (*JSONHTTPResponse, error)

func (*JSONHTTPClient) PutCSV

func (j *JSONHTTPClient) PutCSV(ctx context.Context, url string, reqBody []byte, headers ...Header) ([]byte, error)

type JSONHTTPResponse

type JSONHTTPResponse struct {

	// Code is the HTTP status code of the response.
	Code int

	// Headers are the HTTP headers of the response.
	Headers http.Header
	// contains filtered or unexported fields
}

JSONHTTPResponse is a JSON response from an HTTP request. Consider using Body to operate on ajson.Node or Unmarshal into the struct of your choosing via UnmarshalJSON.

func ParseJSONResponse

func ParseJSONResponse(res *http.Response, body []byte) (*JSONHTTPResponse, error)

ParseJSONResponse parses the given HTTP response and returns a JSONHTTPResponse.

func (*JSONHTTPResponse) Body

func (j *JSONHTTPResponse) Body() (*ajson.Node, bool)

Body returns JSON node. If it is empty the flag will indicate so. Empty response body is a special case and should be handled explicitly.

type ListObjectMetadataResult

type ListObjectMetadataResult struct {
	// Result is a map of object names to object metadata
	Result map[string]ObjectMetadata

	// Errors is a map of object names to errors
	Errors map[string]error
}

func NewListObjectMetadataResult

func NewListObjectMetadataResult() *ListObjectMetadataResult

func (ListObjectMetadataResult) AppendError

func (r ListObjectMetadataResult) AppendError(objectName string, err error)

AppendError will associate an error with the object. It is possible that single object may have multiple errors.

type MarshalFromNodeFunc

type MarshalFromNodeFunc func(records []*ajson.Node, fields []string) ([]ReadResultRow, error)

MarshalFromNodeFunc converts a list of ajson.Node records into ReadResultRow format.

func MakeMarshaledDataFunc

func MakeMarshaledDataFunc(nodeRecordFunc RecordTransformer) MarshalFromNodeFunc

MakeMarshaledDataFunc produces ReadResultRow where raw record differs from the fields. This usually includes a set of actions to preprocess, usually to flatten the raw record and then extract fields requested by the user.

type MarshalFunc

type MarshalFunc func(records []map[string]any, fields []string) ([]ReadResultRow, error)

MarshalFunc converts a list of map[string]any records into ReadResultRow format.

type Module

type Module struct {
	ID      ModuleID
	Label   string // e.g. "crm"
	Version string // e.g. "v3"
}

Module represents a set of endpoints and functionality available by provider. Single provider may support multiple modules, requiring the user to choose a module before making requests. Modules may differ by version or by theme, covering different systems or functionalities.

func (Module) Path

func (a Module) Path() string

type ModuleID

type ModuleID string
const ModuleRoot ModuleID = "root"

type ModuleObjectNameToFieldName

type ModuleObjectNameToFieldName map[ModuleID]datautils.DefaultMap[string, string]

ModuleObjectNameToFieldName is a grouping of ObjectName to response field name mappings defined for each Module.

Explanation: modules have objects, each object is located under certain field name in the response body. This mapping stores the general relationship between the said ObjectName and FieldName. Those objects that do not follow the pattern described in the fallback method are hard code as exceptions.

Ex:

Given:	Connector has 2 modules -- Commerce, Messaging.
		Commerce module has objects stored under "data" field name, except "carts".
		Messaging module has objects stored under the same name as object, except "chats".
Then:	It will be represented as follows:

	ModuleObjectNameToFieldName{
		ModuleCommerce: datautils.NewDefaultMap(map[string]string{
			"carts": "carts",
		},
			func(objectName string) string {
				return "data" // always under "data" field {"data": [{},{},...]}
			},
		),
		ModuleHelpCenter: datautils.NewDefaultMap(map[string]string{
			"chats":        "active_chats",
		}, func(objectName string) string {
			fieldName := objectName // Object "messages" is stored under {"messages": [{},{},...]}
			return fieldName
		}),
	}

type Modules

type Modules = datautils.Map[ModuleID, Module]

type NextPageFunc

type NextPageFunc func(*ajson.Node) (string, error)

NextPageFunc extracts the next page token/URL from the response body.

type NextPageToken

type NextPageToken string

NextPageToken is an opaque token that can be used to get the next page of results. Callers are encouraged to treat this as an opaque string, and not attempt to parse it. And although each provider will be different, callers should expect that this token will expire after some period of time. So long-term storage of this token is not recommended.

func (NextPageToken) String

func (t NextPageToken) String() string

type NodeRecordsFunc

type NodeRecordsFunc func(*ajson.Node) ([]*ajson.Node, error)

NodeRecordsFunc extracts a list of records as ajson.Node from the response body.

type NumericFieldOptions

type NumericFieldOptions struct {
	// Precision is the total number of digits (for decimal types).
	Precision *int `json:"precision,omitempty"`
	// Scale is the number of digits to the right of the decimal point (for decimal types).
	Scale *int `json:"scale,omitempty"`
	// Min is the minimum value for numeric fields (if any).
	Min *float64 `json:"min,omitempty"`
	// Max is the maximum value for numeric fields (if any).
	Max *float64 `json:"max,omitempty"`
	// DefaultValue is the default value for the field (if any).
	DefaultValue *float64 `json:"defaultValue,omitempty"`
}

NumericFieldOptions contains additional options for numeric fields. Note that not all providers will support all options. This is a best-effort attempt to create a common schema for numeric field options across providers.

In the event that a provider doesn't support a particular option, and assuming that the option has a value, then the value should be ignored, and a warning should be added to the UpsertMetadataResult.

type OAuthOption

type OAuthOption func(*oauthClientParams)

func WithOAuthClient

func WithOAuthClient(client *http.Client) OAuthOption

WithOAuthClient sets the http client to use for the connector. Its usage is optional.

func WithOAuthConfig

func WithOAuthConfig(config *oauth2.Config) OAuthOption

WithOAuthConfig sets the oauth config to use for the connector. It's required, unless a token source is provided.

func WithOAuthDebug

func WithOAuthDebug(f func(req *http.Request, rsp *http.Response)) OAuthOption

WithOAuthDebug sets a debug function to be called on every request and response, after the response has been received from the downstream API.

func WithOAuthIsUnauthorizedHandler

func WithOAuthIsUnauthorizedHandler(
	f func(rsp *http.Response) bool,
) OAuthOption

WithOAuthIsUnauthorizedHandler sets the function to call whenever the response is unauthorized (not necessarily 401). This is useful for handling the case where the server has invalidated the token, and the client needs to forcefully refresh. It's optional.

func WithOAuthToken

func WithOAuthToken(token *oauth2.Token) OAuthOption

WithOAuthToken sets the oauth token to use for the connector. It's required, unless a token source is provided.

func WithOAuthUnauthorizedHandler

func WithOAuthUnauthorizedHandler(
	f func(token *oauth2.Token, req *http.Request, rsp *http.Response) (*http.Response, error),
) OAuthOption

WithOAuthUnauthorizedHandler sets the function to call whenever the response is 401 unauthorized. This is useful for handling the case where the server has invalidated the token, and the client needs to forcefully refresh. It's optional.

func WithTokenSource

func WithTokenSource(tokenSource oauth2.TokenSource) OAuthOption

WithTokenSource sets the oauth token source to use for the connector. Whenever the token expires, this will be called to refresh it.

func WithTokenUpdated

func WithTokenUpdated(onTokenUpdated func(oldToken, newToken *oauth2.Token) error) OAuthOption

This is useful for persisting the refreshed tokens somewhere, so that it can be used later. It's optional.

type ObjectEvents

type ObjectEvents struct {
	// ["create", "update", "delete"] our regular CRUD operation events
	// we translate to provider-specific names contact.creation
	Events []SubscriptionEventType
	// ["email", "fax"] fields to watch for an update subscription
	WatchFields []string
	// true if all fields should be watched for an update subscription
	// this is provider specific, and not all providers support this.
	WatchFieldsAll bool
	// any non CRUD operations with provider specific event names
	// eg)  ["contact.merged"] for hubspot or ["jira_issue:restored", "jira_issue:archived"] for jira.
	PassThroughEvents []string
}

type ObjectMetadata

type ObjectMetadata struct {
	// Provider's display name for the object.
	DisplayName string

	// Fields is a map of field names to FieldMetadata.
	// Some legacy connectors do not populate this, but only populates FieldsMap.
	Fields FieldsMetadata

	// Deprecated: for new connectors, please only populate and read `ObjectMetadata.Fields`.
	// FieldsMap is a map of field names to field display names.
	// TODO: Remove this field once all connectors populate Fields.
	FieldsMap map[string]string
}

func NewObjectMetadata

func NewObjectMetadata(displayName string, fields FieldsMetadata) *ObjectMetadata

NewObjectMetadata constructs ObjectMetadata. This will automatically infer fields map from field metadata map. This construct exists for such convenience.

func (*ObjectMetadata) AddFieldMetadata

func (m *ObjectMetadata) AddFieldMetadata(fieldName string, fieldMetadata FieldMetadata)

AddFieldMetadata updates Fields and FieldsMap fields ensuring data consistency.

type ObjectName

type ObjectName string

type PostAuthInfo

type PostAuthInfo struct {
	CatalogVars          *map[string]string
	RawResponse          *JSONHTTPResponse
	ProviderWorkspaceRef string
}

type PrintablePayload

type PrintablePayload struct {
	Base64          bool   `json:"base64,omitempty"`
	Content         string `json:"content"`
	Length          int64  `json:"length"`
	TruncatedLength int64  `json:"truncatedLength,omitempty"`
}

PrintablePayload represents a payload that can be printed or displayed. It contains the content, its length, and whether it is base64 encoded. It also includes a truncated length for cases where the content is too large.

func PrintableRequest

func PrintableRequest(req *http.Request, body []byte) (*PrintablePayload, error)

PrintableRequest creates a PrintablePayload from an HTTP request. The body parameter can be nil, in which case it will read the request body.

func PrintableResponse

func PrintableResponse(resp *http.Response, body []byte) (*PrintablePayload, error)

PrintableResponse creates a PrintablePayload from an HTTP response. The body parameter can be nil, in which case it will read the response body.

func (*PrintablePayload) Clone

func (p *PrintablePayload) Clone() *PrintablePayload

func (*PrintablePayload) GetContent

func (p *PrintablePayload) GetContent() string

func (*PrintablePayload) GetContentBytes

func (p *PrintablePayload) GetContentBytes() ([]byte, error)

func (*PrintablePayload) GetLength

func (p *PrintablePayload) GetLength() int64

func (*PrintablePayload) GetTruncatedLength

func (p *PrintablePayload) GetTruncatedLength() int64

func (*PrintablePayload) IsBase64

func (p *PrintablePayload) IsBase64() bool

func (*PrintablePayload) IsEmpty

func (p *PrintablePayload) IsEmpty() bool

func (*PrintablePayload) IsJSON

func (p *PrintablePayload) IsJSON() (bool, error)

func (*PrintablePayload) IsTruncated

func (p *PrintablePayload) IsTruncated() bool

func (*PrintablePayload) LogValue

func (p *PrintablePayload) LogValue() slog.Value

func (*PrintablePayload) String

func (p *PrintablePayload) String() string

func (*PrintablePayload) Truncate

func (p *PrintablePayload) Truncate(size int64) (*PrintablePayload, error)

type ProviderReadResponseType

type ProviderReadResponseType interface {
	map[string]any | *ajson.Node
}

ProviderReadResponseType defines the types of records that ParseResult can process. It determines which callback function is used for parsing.

type QueryParam

type QueryParam struct {
	Key   string         `json:"key"`
	Value string         `json:"value"`
	Mode  QueryParamMode `json:"mode"`
}

func (QueryParam) ApplyToRequest

func (q QueryParam) ApplyToRequest(vals *url.Values)

func (QueryParam) String

func (q QueryParam) String() string

type QueryParamAuthClientOption

type QueryParamAuthClientOption func(params *queryParamClientParams)

func WithQueryParamClient

func WithQueryParamClient(client *http.Client) QueryParamAuthClientOption

WithQueryParamClient sets the http client to use for the connector. Its usage is optional.

func WithQueryParamDebug

func WithQueryParamDebug(f func(req *http.Request, rsp *http.Response)) QueryParamAuthClientOption

WithQueryParamDebug sets a debug function to be called on every request and response, after the response has been received from the downstream API.

func WithQueryParamIsUnauthorizedHandler

func WithQueryParamIsUnauthorizedHandler(
	f func(rsp *http.Response) bool,
) QueryParamAuthClientOption

WithQueryParamIsUnauthorizedHandler sets the function to call whenever the response is unauthorized (not necessarily 401). This is useful for handling the case where the server has invalidated the token, and the client needs to forcefully refresh. It's optional.

func WithQueryParamUnauthorizedHandler

func WithQueryParamUnauthorizedHandler(
	f func(params []QueryParam, req *http.Request, rsp *http.Response) (*http.Response, error),
) QueryParamAuthClientOption

WithQueryParamUnauthorizedHandler sets the function to call whenever the response is 401 unauthorized. This is useful for handling the case where the server has invalidated the credentials, and the client needs to refresh. It's optional.

func WithQueryParams

func WithQueryParams(ps ...QueryParam) QueryParamAuthClientOption

type QueryParamMode

type QueryParamMode int

QueryParamMode determines how the query param should be applied to the request.

type QueryParams

type QueryParams []QueryParam

func (QueryParams) ApplyToRequest

func (q QueryParams) ApplyToRequest(req *http.Request)

func (QueryParams) Has

func (q QueryParams) Has(target QueryParam) bool

type ReadParams

type ReadParams struct {
	// The name of the object we are reading, e.g. "Account"
	ObjectName string // required

	// The fields we are reading from the object, e.g. ["Id", "Name", "BillingCity"]
	Fields datautils.StringSet // required, at least one field needed

	// NextPage is an opaque token that can be used to get the next page of results.
	NextPage NextPageToken // optional, only set this if you want to read the next page of results

	// Since is an optional timestamp to fetch only records updated **after** this time.
	// Used for incremental reads.
	Since time.Time

	// Until is an optional timestamp to fetch only records updated **up to and including** this time.
	// Pagination stops when records exceed this timestamp.
	Until time.Time

	// Deleted is true if we want to read deleted records instead of active records.
	Deleted bool // optional, defaults to false

	// Filter defines the filtering criteria for supported connectors.
	// It is optional and behaves differently depending on the connector:
	//	* Salesforce: It is a SOQL string that comes after the WHERE clause which will be used to filter the records.
	//		Reference: https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql.htm
	//	* Klaviyo: Comma separated methods following JSON:API filtering syntax.
	//		Note: timing is already handled by Since argument.
	//		Reference: https://developers.klaviyo.com/en/docs/filtering_
	//	* Marketo: Comma-separated activityTypeIds for filtering lead activities.
	//		Note: Only supported when reading Lead Activities (not other endpoints).
	//		Example: "1,6,12" (for visitWebpage, fillOutForm, emailClicked)
	//		Reference: https://developer.adobe.com/marketo-apis/api/mapi/#tag/Activities
	Filter string // optional

	// AssociatedObjects specifies a list of related objects to fetch along with the main object.
	// It is optional and supported by the following connectors:
	//	* HubSpot: Supported in Read operation, but not Search.
	//	* Stripe: Only nested objects can be expanded. Specify a dot-separated path
	//		to the property to fetch and expand those objects.
	//		Reference: https://docs.stripe.com/expand#how-it-works
	//	* Capsule: Embeds objects in response.
	//		Reference: https://developer.capsulecrm.com/v2/overview/reading-from-the-api
	AssociatedObjects []string // optional

	// PageSize specifies the # of records to request when making a read request.
	PageSize int // optional
}

ReadParams defines how we are reading data from a SaaS API.

func (ReadParams) ValidateParams

func (p ReadParams) ValidateParams(withRequiredFields bool) error

type ReadResult

type ReadResult struct {
	// Rows is the number of total rows in the result.
	Rows int64 `json:"rows"`
	// Data is an array where each element represents a ReadResultRow.
	Data []ReadResultRow `json:"data"`
	// NextPage is an opaque token that can be used to get the next page of results.
	NextPage NextPageToken `json:"nextPage,omitempty"`
	// Done is true if there are no more pages to read.
	Done bool `json:"done,omitempty"`
}

ReadResult is what's returned from reading data via the Read call.

func ParseResult

func ParseResult[R ProviderReadResponseType](
	resp *JSONHTTPResponse,
	extractRecords func(*ajson.Node) ([]R, error),
	extractNextPage func(*ajson.Node) (string, error),
	marshalFunc func([]R, []string) ([]ReadResultRow, error),
	fields datautils.Set[string],
) (*ReadResult, error)

ParseResult parses the response from a provider into a ReadResult. A 2xx return type is assumed. The sizeFunc returns the total number of records in the response. The extractRecords returns the records in the response. The extractNextPage returns the URL for the next page of results. The marshalFunc is used to structure the data into an array of ReadResultRows. The fields are used to populate ReadResultRow.Fields.

type ReadResultRow

type ReadResultRow struct {
	// Fields is a map of requested provider field names to values.
	// All field names are in lowercase (eg: accountid, name, billingcityid)
	Fields map[string]any `json:"fields"`
	// Associations is a map of associated objects to the main object.
	// The key is the associated object name, and the value is an array of associated object ids.
	Associations map[string][]Association `json:"associations,omitempty"`
	// Raw is the raw JSON response from the provider.
	Raw map[string]any `json:"raw"`
	// RecordId is the ID of the record. Currently only populated for hubspot GetRecord and GetRecordsWithId function
	Id string `json:"id,omitempty"`
}

ReadResultRow is a single row of data returned from a Read call, which contains the requested fields, as well as the raw JSON response from the provider.

func GetMarshaledData

func GetMarshaledData(records []map[string]any, fields []string) ([]ReadResultRow, error)

func GetMarshalledDataWithId

func GetMarshalledDataWithId(records []map[string]any, fields []string) ([]ReadResultRow, error)

GetMarshalledDataWithId is very similar to GetMarshaledData, but it also extracts the "id" field from the raw record.

type RecordTransformer

type RecordTransformer func(node *ajson.Node) (map[string]any, error)

RecordTransformer is a function that processes a JSON node and transforms it into a map representation, potentially applying structural modifications.

Common use cases include: - Flattening nested objects (see FlattenNestedFields) - Filtering out unwanted fields - Converting field formats - Renaming fields - Adding computed fields

Example usage: - FlattenNestedFields("attributes") - Replacing GUIDs with human-readable fields - Enhancing fields with custom data from the API response. - Adding a relationships property to the root level from a nested object.

func FlattenNestedFields

func FlattenNestedFields(nestedKey string) RecordTransformer

FlattenNestedFields returns a procedure which copies fields of a nested object to the top level.

Ex: Every object has special field "attributes" which holds all the object specific fields. Therefore, nested "attributes" will be removed and fields will be moved to the top level of the object.

Example accounts(shortened response):

 "data": [
    {
        "type": "",
        "id": "",
        "attributes": {
            "test_account": false,
            "contact_information": {},
            "locale": ""
        },
        "links": {}
    }
],

The resulting fields for the above will be: [ type, id, test_account, contact_information, locale, links ].

type RecordsFunc

type RecordsFunc func(*ajson.Node) ([]map[string]any, error)

RecordsFunc extracts a list of records as map[string]any from the response body.

func ExtractOptionalRecordsFromPath

func ExtractOptionalRecordsFromPath(jsonPath string, nestedPath ...string) RecordsFunc

func ExtractRecordsFromPath

func ExtractRecordsFromPath(jsonPath string, nestedPath ...string) RecordsFunc

type RegistrationResult

type RegistrationResult struct {
	RegistrationRef string
	Result          any // struct depends on the provider
	Status          RegistrationStatus
}

type RegistrationStatus

type RegistrationStatus string
const (
	// registration is pending and not yet complete.
	RegistrationStatusPending RegistrationStatus = "pending"
	// registration returned error, and all intermittent steps are rolled back.
	RegistrationStatusFailed RegistrationStatus = "failed"
	// successful registration.
	RegistrationStatusSuccess RegistrationStatus = "success"
	// registration returned error, and failed to rollback some intermittent steps.
	RegistrationStatusFailedToRollback RegistrationStatus = "failed_to_rollback"
)

type RequestModifier

type RequestModifier func(req *http.Request)

type RequireAuthenticatedClient

type RequireAuthenticatedClient struct{}

type RequireMetadata

type RequireMetadata struct {
	ExpectedMetadataKeys []string
}

RequireMetadata defines required metadata for validation. Metadata keys are case-insensitive.

type RequireModule

type RequireModule struct {
	ExpectedModules []ModuleID
}

type RequireWorkspace

type RequireWorkspace struct{}

type ResponseHandler

type ResponseHandler func(rsp *http.Response) (*http.Response, error)

type StringFieldOptions

type StringFieldOptions struct {
	// Length is the maximum length of the string field.
	Length *int `json:"length,omitempty"`
	// Pattern is a regex pattern that the string field value must match (if any).
	Pattern string `json:"pattern,omitempty"`
	// Values is a list of allowed values for enum fields (if any).
	Values []string `json:"values,omitempty"`
	// ValuesRestricted indicates if the field value must be limited to what's in Values.
	ValuesRestricted bool `json:"valuesRestricted,omitempty"`
	// DefaultValue is the default value for the field (if any).
	DefaultValue *string `json:"defaultValue,omitempty"`
	// NumDisplayLines defines how many lines of text are shown in the UI.
	// If the text exceeds this number, it will be truncated.
	NumDisplayLines *int `json:"lines,omitempty"`
}

StringFieldOptions contains additional options for string fields. Note that not all providers will support all options. This is a best-effort attempt to create a common schema for string field options across providers.

In the event that a provider doesn't support a particular option, and assuming that the option has a value, then the value should be ignored, and a warning should be added to the UpsertMetadataResult.

type StringMap

type StringMap map[string]any

func ToStringMap

func ToStringMap(m map[string]any) StringMap

func (StringMap) AsFloat

func (m StringMap) AsFloat(key string) (float64, error)

AsFloat is a helper function that extracts a float from the map. This function will convert number values such as int, uint, and float to float64. By doing so, it may lose precision for large numbers. This is helpful when you are not sure about the type of the number.

func (StringMap) AsInt

func (m StringMap) AsInt(key string) (int64, error)

AsInt is a helper function that extracts an integer from the map. This function will convert number values such as int, uint, and float to int64. By doing so, it may lose precision for large numbers. This is helpful when you are not sure about the type of the number.

func (StringMap) Get

func (m StringMap) Get(key string) (any, error)

func (StringMap) GetBool

func (m StringMap) GetBool(key string) (bool, error)

func (StringMap) GetCaseInsensitive

func (m StringMap) GetCaseInsensitive(key string) (any, bool)

func (StringMap) GetFloat

func (m StringMap) GetFloat(key string) (float64, error)

GetFloat extracts a float from the map.

func (StringMap) GetInt

func (m StringMap) GetInt(key string) (int64, error)

GetInt extracts an integer from the map.

func (StringMap) GetNumber

func (m StringMap) GetNumber(key string) (float64, error)

func (StringMap) GetString

func (m StringMap) GetString(key string) (string, error)

func (StringMap) Has

func (m StringMap) Has(key string) bool

func (StringMap) Keys

func (m StringMap) Keys() []string

func (StringMap) Len

func (m StringMap) Len() int

func (StringMap) Values

func (m StringMap) Values() []any

type SubscribeParams

type SubscribeParams struct {
	Request any
	// RegistrationResult is the result of the Connector.Register call.
	// Connector.Subscribe requires information from the registration.
	// Not all providers require registration, so this is optional.
	// eg) Salesforce and HubSpot require registration because
	RegistrationResult *RegistrationResult
	SubscriptionEvents map[ObjectName]ObjectEvents
}

type SubscriptionEvent

type SubscriptionEvent interface {
	EventType() (SubscriptionEventType, error)
	RawEventName() (string, error)
	ObjectName() (string, error)
	Workspace() (string, error)
	RecordId() (string, error)
	EventTimeStampNano() (int64, error)
	RawMap() (map[string]any, error)
}

SubscriptionEvent is an interface for webhook events coming from the provider. This interface defines methods to extract information from the webhook event.

type SubscriptionEventType

type SubscriptionEventType string
const (
	SubscriptionEventTypeCreate            SubscriptionEventType = "create"
	SubscriptionEventTypeUpdate            SubscriptionEventType = "update"
	SubscriptionEventTypeDelete            SubscriptionEventType = "delete"
	SubscriptionEventTypeAssociationUpdate SubscriptionEventType = "associationUpdate"
	SubscriptionEventTypeOther             SubscriptionEventType = "other"
)

type SubscriptionRegistrationParams

type SubscriptionRegistrationParams struct {
	Request any `json:"request" validate:"required"`
}

type SubscriptionResult

type SubscriptionResult struct {
	Result       any
	ObjectEvents map[ObjectName]ObjectEvents
	Status       SubscriptionStatus

	Objects []ObjectName
	Events  []SubscriptionEventType
	// ["create", "update", "delete"]
	// our regular CRUD operation events we translate to provider-specific names contact.creation
	UpdateFields []string
	// ["email", "fax"]
	PassThroughEvents []string
}

type SubscriptionStatus

type SubscriptionStatus string
const (
	// registration is pending and not yet complete.
	SubscriptionStatusPending SubscriptionStatus = "pending"
	// registration returned error, and all intermittent steps are rolled back.
	SubscriptionStatusFailed SubscriptionStatus = "failed"
	// successful registration.
	SubscriptionStatusSuccess SubscriptionStatus = "success"
	// registration returned error, and failed to rollback some intermittent steps.
	SubscriptionStatusFailedToRollback SubscriptionStatus = "failed_to_rollback"
)

type SubscriptionUpdateEvent

type SubscriptionUpdateEvent interface {
	SubscriptionEvent
	// GetUpdatedFields returns the fields that were updated in the event.
	UpdatedFields() ([]string, error)
}

type TokenSourceWithContext

type TokenSourceWithContext interface {
	oauth2.TokenSource

	// TokenWithContext returns a token or an error.
	// Token must be safe for concurrent use by multiple goroutines.
	// The returned Token must not be modified.
	// Similar semantics to oauth2.TokenSource, but with a context.
	TokenWithContext(ctx context.Context) (*oauth2.Token, error)
}

TokenSourceWithContext is an interface that extends the oauth2.TokenSource interface with a context. This is useful for token sources that need to be aware of the context in which they are being called. The use of this interface is optional, but if the token source conforms to it, then the context version of the Token method will be called instead of the normal one.

type UpsertMetadataAction

type UpsertMetadataAction string

UpsertMetadataAction represents the action taken during an upsert operation.

const (
	// UpsertMetadataActionCreate indicates that the object/field was created.
	UpsertMetadataActionCreate UpsertMetadataAction = "create"
	// UpsertMetadataActionUpdate indicates that the object/field was updated.
	UpsertMetadataActionUpdate UpsertMetadataAction = "update"
	// UpsertMetadataActionNone indicates that the object/field was not changed.
	UpsertMetadataActionNone UpsertMetadataAction = "none"
)

func (UpsertMetadataAction) IsValid

func (a UpsertMetadataAction) IsValid() bool

IsValid checks if the UpsertMetadataAction is known.

type UpsertMetadataParams

type UpsertMetadataParams struct {
	// Maps object names to field definitions.
	Fields map[string][]FieldDefinition `json:"fields"`
}

UpsertMetadataParams represents parameters for upserting metadata.

type UpsertMetadataResult

type UpsertMetadataResult struct {
	// Indicates if the upsert operation was successful.
	Success bool `json:"success"`

	// Maps object name -> field name -> upsert result.
	Fields map[string]map[string]FieldUpsertResult `json:"fields"`
}

UpsertMetadataResult contains results for all created/updated objects and fields.

type ValueType

type ValueType string

type VerificationParams

type VerificationParams struct {
	Param any
}

VerificationParams is a struct that contains the parameters specific to the provider.

type WebhookRequest

type WebhookRequest struct {
	Headers http.Header
	Body    []byte
	URL     string
	Method  string
}

WebhookRequest is a struct that contains the request parameters for a webhook.

type WriteMethod

type WriteMethod func(context.Context, string, any, ...Header) (*JSONHTTPResponse, error)

WriteMethod is signature for any HTTP method that performs write modifications. Ex: Post/Put/Patch.

type WriteParams

type WriteParams struct {
	// The name of the object we are writing, e.g. "Account"
	ObjectName string // required

	// The external ID of the object instance we are updating. Provided in the case of UPDATE, but not CREATE.
	RecordId string // optional

	// RecordData is a JSON node representing the record of data we want to insert in the case of CREATE
	// or fields of data we want to modify in case of an update
	RecordData any // required

	// Associations contains associations between the object and other objects.
	Associations any // optional
}

WriteParams defines how we are writing data to a SaaS API.

func (WriteParams) ValidateParams

func (p WriteParams) ValidateParams() error

type WriteResult

type WriteResult struct {
	// Success is true if write succeeded.
	Success bool `json:"success"`
	// RecordId is the ID of the written record.
	RecordId string `json:"recordId,omitempty"` // optional
	// Errors is list of error record returned by the API.
	Errors []any `json:"errors,omitempty"` // optional
	// Data is a JSON node containing data about the properties that were updated.
	Data map[string]any `json:"data,omitempty"` // optional
}

WriteResult is what's returned from writing data via the Write call.

type XMLAttributes

type XMLAttributes struct {
	Key   string `json:"key"   validate:"required,excludesall=<>,excludesrune=<>"`
	Value string `json:"value" validate:"excludesall=<>,excludesrune=<>"`
}

func (*XMLAttributes) String

func (attr *XMLAttributes) String() string

func (*XMLAttributes) Validate

func (attr *XMLAttributes) Validate() error

type XMLData

type XMLData struct {
	XMLName     string           `json:"xmlName,omitempty"     validate:"required,excludesall=<>"`
	Attributes  []*XMLAttributes `json:"attributes,omitempty"`
	Children    []XMLSchema      `json:"children,omitempty"`
	SelfClosing bool             `json:"selfClosing,omitempty"`
}

func (*XMLData) String

func (x *XMLData) String() string

func (*XMLData) UnmarshalJSON

func (x *XMLData) UnmarshalJSON(b []byte) error

func (*XMLData) Validate

func (x *XMLData) Validate() error

type XMLHTTPClient

type XMLHTTPClient struct {
	HTTPClient         *HTTPClient        // underlying HTTP client. Required.
	ErrorPostProcessor ErrorPostProcessor // Errors returned from CRUD methods will go via this method. Optional.
}

XMLHTTPClient is an HTTP client that can parse XML response.

func (*XMLHTTPClient) Get

func (c *XMLHTTPClient) Get(ctx context.Context, url string, headers ...Header) (*XMLHTTPResponse, error)

Get makes a GET request to the given URL and returns the response body as a XML object. If the response is not a 2xx, an error is returned. If the response is a 401, the caller should refresh the access token and retry the request. If errorHandler is nil, then the default error handler is used. If not, the caller can inject their own error handling logic.

func (*XMLHTTPClient) Post

func (c *XMLHTTPClient) Post(ctx context.Context,
	url string, node *xquery.XML, headers ...Header,
) (*XMLHTTPResponse, error)

Post sends XML request and receives XML as a response.

type XMLHTTPResponse

type XMLHTTPResponse struct {

	// Code is the HTTP status code of the response.
	Code int

	// Headers are the HTTP headers of the response.
	Headers http.Header

	// Body is the unmarshalled response body in XML form. Content is the same as bodyBytes
	Body *xquery.XML
	// contains filtered or unexported fields
}

type XMLSchema

type XMLSchema interface {
	String() string
	Validate() error
}

type XMLString

type XMLString string

func (XMLString) String

func (str XMLString) String() string

func (XMLString) Validate

func (str XMLString) Validate() error

Directories

Path Synopsis
nolint:ireturn
nolint:ireturn
Package paramsbuilder provides common parameters used to initialize connectors.
Package paramsbuilder provides common parameters used to initialize connectors.
nolint: ireturn
nolint: ireturn
credscanning
Package credscanning is a wrapper for scanning package.
Package credscanning is a wrapper for scanning package.

Jump to

Keyboard shortcuts

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