simpleforce

package module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: May 16, 2024 License: Apache-2.0, BSD-3-Clause Imports: 13 Imported by: 0

README

simpleforce

A simple Golang client for Salesforce

GoDoc

Features

simpleforce is a library written in Go (Golang) that connects to Salesforce via the REST and Tooling APIs. Currently, the following functions are implemented and more features could be added based on need:

  • Execute SOQL queries
  • Get records via record (sobject) type and ID
  • Create records
  • Update records
  • Delete records
  • Upsert (create or update) records based on an external ID
  • Download a file
  • Execute anonymous apex
  • Send request to a custom Apex Rest endpoint

Most of the implementation referenced Salesforce documentation here: https://developer.salesforce.com/docs/atlas.en-us.214.0.api_rest.meta/api_rest/intro_what_is_rest_api.htm

Installation

simpleforce can be acquired as any other Go libraries via go get:

go get github.com/simpleforce/simpleforce

Quick Start

Setup the Client

A client instance is the main entrance to access Salesforce using simpleforce. Create a client instance with the NewClient function, with the proper endpoint URL:

package main

import "github.com/simpleforce/simpleforce"

var (
	sfURL      = "Custom or instance URL, for example, 'https://na01.salesforce.com/'"
	sfUser     = "Username of the Salesforce account."
	sfPassword = "Password of the Salesforce account."
	sfToken    = "Security token, could be omitted if Trusted IP is configured."
)

func createClient() *simpleforce.Client {
	client := simpleforce.NewClient(sfURL, simpleforce.DefaultClientID, simpleforce.DefaultAPIVersion)
	if client == nil {
		// handle the error

		return nil
	}

	err := client.LoginPassword(sfUser, sfPassword, sfToken)
	if err != nil {
		// handle the error

		return nil
	}

	// Do some other stuff with the client instance if needed.

	return client
}
Execute a SOQL Query

The client provides an interface to run an SOQL Query. Refer to https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_query.htm for more details about SOQL.

package main

import (
    "fmt"
    "github.com/simpleforce/simpleforce"
)

func Query() {
	client := simpleforce.NewClient(...)
	client.LoginPassword(...)

	q := "Some SOQL Query String"
	result, err := client.Query(q) // Note: for Tooling API, use client.Tooling().Query(q)
	if err != nil {
		// handle the error
		return
	}

	for _, record := range result.Records {
		// access the record as SObjects.
		fmt.Println(record)
	}
}

Work with Records

SObject instances are created by client instance, either through the return values of client.Query() or through client.SObject() directly. Once an SObject instance is created, it can be used to Create, Delete, Update, or Get records through the Salesforce REST API. Here are some examples of using SObject instances to work on the records.

package main

import (
    "fmt"
    "github.com/simpleforce/simpleforce"
)

func WorkWithRecords() {
	client := simpleforce.NewClient(...)
	client.LoginPassword(...)

	// Get an SObject with given type and external ID
	obj := client.SObject("Case").Get("__ID__")
	if obj == nil {
		// Object doesn't exist, handle the error
		return
	}

	// Attributes are associated with all Salesforce returned SObjects, and can be accessed with the
	// `AttributesField` method.
	attrs := obj.AttributesField()
	if attrs != nil {
	 	fmt.Println(attrs.Type)    // "Case"
		fmt.Println(attrs.URL)     // "/services/data/v43.0/case/__ID__"
	}

	// Linked objects can be accessed with the `SObjectField` method.
	userObj := obj.SObjectField("User", "CreatedById")
	if userObj == nil {
		// Object doesn't exist, or field "CreatedById" is invalid.
		return
	}

	// Linked objects returned normally contains the type and ID field only. A `Get` operation is needed to
	// retrieve all the information of linked objects.
	fmt.Println(userObj.StringField("Name"))    // FAIL: fields are not populated.

	// If an SObject instance already has an ID (e.g. linked object), `Get` can retrieve the object directly without
	// parameter.
	userObj.Get()
	fmt.Println(userObj.StringField("Name"))    // SUCCESS: returns the name of the user.

	// For Update(), start with a blank SObject.
	// Set "Id" with an existing ID and any updated fields.
	//
	// Update() will return the updated object, or nil and print an error.
	updateObj := client.SObject("Contact").								// Create an empty object of type "Contact".
		Set("Id", "__ID__").											// Set the Id to an existing Contact ID.
		Set("FirstName", "New Name").									// Set any updated fields.
		Update()														// Update the record on Salesforce server.
	fmt.Println(updateObj)

	// For Upsert(), start with a blank SObject.
	// Upsert will create the object if it does not already exist and will update the object if it already exists.
	// Set "ExternalIDField" to the name of your external ID field
	// and populate that field with an your external ID and any updated fields.
	//
	// Upsert() will return the updated object, or nil and print an error.
	upsertObj := client.SObject("Contact").						// Create an empty object of type "Contact".
		Set("ExternalIDField", "customExtIdField__c").	// Set the ExternalIDField to the name of your external ID field.
		Set("customExtIdField__c", "__ExtID__").				// Set the specified ID field to your external ID.
		Set("FirstName", "New Name").										// Set any updated fields.
		Upsert()																				// Update the record on Salesforce server.
	fmt.Println(upsertObj)

	// Many SObject methods return the instance of the SObject, allowing chained access and operations to the
	// object. In the following example, all methods, except "Delete", returns *SObject so that the next method
	// can be invoked on the returned value directly.
	//
	// Delete() methods returns `error` instead, as Delete is supposed to delete the record from the server.
	err := client.SObject("Case").                               // Create an empty object of type "Case"
    		Set("Subject", "Case created by simpleforce").              // Set the "Subject" field.
	        Set("Comments", "Case commented by simpleforce").           // Set the "Comments" field.
    		Create().                                                   // Create the record on Salesforce server.
    		Get().                                                      // Refresh the fields from Salesforce server.
    		Delete()                                                    // Delete the record from Salesforce server.
	fmt.Println(err)
}
Download a File
// Setup client and login
// ...

// Get the content version ID
query := "SELECT Id FROM ContentVersion WHERE ContentDocumentId = '" + YOUR_CONTENTDOCUMENTID + "' AND IsLatest = true"
result, err = client.Query(query)
if err != nil {
    // handle the error
}
contentVersionID := ""
for _, record := range result.Records {
    contentVersionID = record.StringField("Id")
}

// Download file
downloadFilePath := "/absolute/path/to/yourfile.txt"

err = client.DownloadFile(contentVersionID, downloadFilePath)
if err != nil {
    // handle error
    return
}
Execute Anonymous Apex
// Setup client and login
// ...

result, err := client.ExecuteAnonymous("System.debug('test anonymous apex');")
if err != nil {
    // handle error
    return
}

Development and Unit Test

A set of unit test cases are provided to validate the basic functions of simpleforce. Please do not run these unit tests with a production instance of Salesforce as it would create, modify and delete data from the provided Salesforce account.

The unit test requires a custom field customExtIdField__c to be present on the Type Case in your Salesforce setup.

License and Acknowledgement

This package is released under BSD license. Part of the code referenced the simple-salesforce (https://github.com/simple-salesforce/simple-salesforce) project and the credit goes to Nick Catalano and the community maintaining simple-salesforce.

Contributions are welcome, cheers :-)

Documentation

Index

Constants

View Source
const (
	DefaultAPIVersion = "54.0"
	DefaultClientID   = "simpleforce"
	DefaultURL        = "https://login.salesforce.com"
)

Variables

View Source
var (
	// ErrFailure is a generic error if none of the other errors are appropriate.
	ErrFailure = errors.New("general failure")

	// ErrAuthentication is returned when authentication failed.
	ErrAuthentication = errors.New("authentication failure")
)

Functions

func ParseSalesforceError

func ParseSalesforceError(statusCode int, responseBody []byte) (err error)

Need to get information out of this package.

Types

type Client

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

Client is the main instance to access salesforce.

func NewClient

func NewClient(url, clientID, apiVersion string) *Client

NewClient creates a new instance of the client.

func (*Client) ApexREST

func (client *Client) ApexREST(method, path string, requestBody io.Reader) ([]byte, error)

ApexREST executes a custom rest request with the provided method, path, and body. The path is relative to the domain.

func (*Client) DescribeGlobal

func (client *Client) DescribeGlobal() (*SObjectMeta, error)

Get the List of all available objects and their metadata for your organization's data

func (*Client) DownloadAttachment

func (client *Client) DownloadAttachment(attachmentId string, filepath string) error

func (*Client) DownloadFile

func (client *Client) DownloadFile(contentVersionID string, filepath string) error

DownloadFile downloads a file based on the REST API path given. Saves to filePath.

func (*Client) ExecuteAnonymous

func (client *Client) ExecuteAnonymous(apexBody string) (*ExecuteAnonymousResult, error)

ExecuteAnonymous executes a body of Apex code

func (*Client) GetLoc

func (client *Client) GetLoc() (loc string)

Expose Loc to save in admin settings

func (*Client) GetSid

func (client *Client) GetSid() (sid string)

Expose sid to save in admin settings

func (*Client) LoginPassword

func (client *Client) LoginPassword(username, password, token string) error

LoginPassword signs into salesforce using password. token is optional if trusted IP is configured. Ref: https://developer.salesforce.com/docs/atlas.en-us.214.0.api_rest.meta/api_rest/intro_understanding_username_password_oauth_flow.htm Ref: https://developer.salesforce.com/docs/atlas.en-us.214.0.api.meta/api/sforce_api_calls_login.htm

func (*Client) Query

func (client *Client) Query(q string) (*QueryResult, error)

Query runs an SOQL query. q could either be the SOQL string or the nextRecordsURL.

func (*Client) SObject

func (client *Client) SObject(typeName ...string) *SObject

SObject creates an SObject instance with provided type name and associate the SObject with the client.

func (*Client) SetHttpClient

func (client *Client) SetHttpClient(c *http.Client)

func (*Client) SetSidLoc

func (client *Client) SetSidLoc(sid string, loc string)

Set SID and Loc as a means to log in without LoginPassword

func (*Client) Tooling

func (client *Client) Tooling() *Client

Tooling is called to specify Tooling API, e.g. client.Tooling().Query(q)

func (*Client) UnTooling

func (client *Client) UnTooling()

type ExecuteAnonymousResult

type ExecuteAnonymousResult struct {
	Line                int         `json:"line"`
	Column              int         `json:"column"`
	Compiled            bool        `json:"compiled"`
	Success             bool        `json:"success"`
	CompileProblem      interface{} `json:"compileProblem"`
	ExceptionStackTrace interface{} `json:"exceptionStackTrace"`
	ExceptionMessage    interface{} `json:"exceptionMessage"`
}

ExecuteAnonymousResult is returned by ExecuteAnonymous function

type QueryResult

type QueryResult struct {
	TotalSize      int       `json:"totalSize"`
	Done           bool      `json:"done"`
	NextRecordsURL string    `json:"nextRecordsUrl"`
	Records        []SObject `json:"records"`
}

QueryResult holds the response data from an SOQL query.

type SObject

type SObject map[string]interface{}

SObject describes an instance of SObject. Ref: https://developer.salesforce.com/docs/atlas.en-us.214.0.api_rest.meta/api_rest/resources_sobject_basic_info.htm

func (*SObject) AttributesField

func (obj *SObject) AttributesField() *SObjectAttributes

AttributesField returns a read-only copy of the attributes field of an SObject.

func (*SObject) Create

func (obj *SObject) Create() *SObject

Create posts the JSON representation of the SObject to salesforce to create the entry. If the creation is successful, the ID of the SObject instance is updated with the ID returned. Otherwise, nil is returned for failures. Ref: https://developer.salesforce.com/docs/atlas.en-us.214.0.api_rest.meta/api_rest/dome_sobject_create.htm

func (*SObject) Delete

func (obj *SObject) Delete(id ...string) error

Delete deletes an SObject record identified by external ID. nil is returned if the operation completes successfully; otherwise an error is returned

func (*SObject) Describe

func (obj *SObject) Describe() *SObjectMeta

Describe queries the metadata of an SObject using the "describe" API. Ref: https://developer.salesforce.com/docs/atlas.en-us.214.0.api_rest.meta/api_rest/resources_sobject_describe.htm

func (*SObject) ExternalID

func (obj *SObject) ExternalID() string

ExternalID returns the external ID of the SObject.

func (*SObject) ExternalIDFieldName

func (obj *SObject) ExternalIDFieldName() string

ExternalIDField returns the external ID field of the SObject.

func (*SObject) Get

func (obj *SObject) Get(id ...string) *SObject

Get retrieves all the data fields of an SObject. If id is provided, the SObject with the provided external ID will be retrieved; otherwise, the existing ID of the SObject will be checked. If the SObject doesn't contain an ID field and id is not provided as the parameter, nil is returned. If query is successful, the SObject is updated in-place and exact same address is returned; otherwise, nil is returned if failed.

func (*SObject) ID

func (obj *SObject) ID() string

ID returns the external ID of the SObject.

func (*SObject) InterfaceField

func (obj *SObject) InterfaceField(key string) interface{}

InterfaceField accesses a field in the SObject as raw interface. This allows access to any type of fields.

func (*SObject) SObjectField

func (obj *SObject) SObjectField(typeName, key string) *SObject

SObjectField accesses a field in the SObject as another SObject. This is only applicable if the field is an external ID to another object. The typeName of the SObject must be provided. <nil> is returned if the field is empty.

func (*SObject) Set

func (obj *SObject) Set(key string, value interface{}) *SObject

Set indexes value into SObject instance with provided key. The same SObject pointer is returned to allow chained access.

func (*SObject) StringField

func (obj *SObject) StringField(key string) string

StringField accesses a field in the SObject as string. Empty string is returned if the field doesn't exist.

func (*SObject) Type

func (obj *SObject) Type() string

Type returns the type, or sometimes referred to as name, of an SObject.

func (*SObject) Update

func (obj *SObject) Update() *SObject

Update updates SObject in place. Upon successful, same SObject is returned for chained access. ID is required.

func (*SObject) Upsert

func (obj *SObject) Upsert() (*SObject, error)

Upsert creates SObject or updates existing SObject in place. Upon successful upsert, same SObject is returned for chained access. ID, ExternalIDField and Type are required. ID is the value of the external ID in this case.

type SObjectAttributes

type SObjectAttributes struct {
	Type string `json:"type"`
	URL  string `json:"url"`
}

SObjectAttributes describes the basic attributes (type and url) of an SObject.

type SObjectMeta

type SObjectMeta map[string]interface{}

SObjectMeta describes the metadata returned by describing the object. Ref: https://developer.salesforce.com/docs/atlas.en-us.214.0.api_rest.meta/api_rest/resources_sobject_describe.htm

type SalesforceError

type SalesforceError struct {
	Message      string
	HttpCode     int
	ErrorCode    string
	ErrorMessage string
}

func (SalesforceError) Error

func (err SalesforceError) Error() string

Jump to

Keyboard shortcuts

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