@designofadecade/salesforce-marketing-cloud
v1.5.0
Published
Salesforce Marketing Cloud SDK for Node.js
Downloads
596
Maintainers
Readme
Salesforce Marketing Cloud SDK
A modern, type-safe Node.js SDK for interacting with the Salesforce Marketing Cloud API. Built with TypeScript and designed for Node.js 24+.
Features
- ✅ Full TypeScript support with comprehensive type definitions
- ✅ ESM (ES Modules) compatible
- ✅ Support for both REST and SOAP APIs
- ✅ Comprehensive error handling with custom error types
- ✅ Automatic OAuth 2.0 authentication
- ✅ Well-tested with Vitest
- ✅ Modern async/await API
- ✅ Zero dependencies (except soap for SOAP API support)
📦 Installation
npm install @designofadecade/salesforce-marketing-cloudRequirements
- Node.js >= 24.0.0
- ES Modules support (package uses
"type": "module") - TypeScript >= 5.0 (if using TypeScript)
Quick Start
import SalesForceClient, { Assets, DataExtensions, AutomationStudio, Scopes } from '@designofadecade/salesforce-marketing-cloud';
// Initialize the client
const client = new SalesForceClient({
clientDomain: 'your-subdomain',
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
accountId: 'your-account-id',
// Scope is optional - use built-in constants or omit to use all package permissions
scope: Scopes.buildScope([
Scopes.EMAIL_READ,
Scopes.DATA_EXTENSIONS_WRITE
])
});
// Use the client directly
const endpoints = await client.endpoints();
// Or use specialized modules
const assets = new Assets(client);
const assetList = await assets.list();
const dataExtensions = new DataExtensions(client);
const rows = await dataExtensions.getAllRows('customer-de');
const automation = new AutomationStudio(client);
const automations = await automation.getAll();API Reference
SalesForceClient
The main client for authenticating and making API requests.
Constructor
new SalesForceClient(config: SalesForceClientConfig)Parameters:
clientDomain(string, required): Your Marketing Cloud subdomainclientId(string, required): OAuth client IDclientSecret(string, required): OAuth client secretaccountId(string, required): Marketing Cloud account IDscope(string, optional): OAuth scope
Throws:
SalesForceConfigError: If required configuration is missing
Methods
api<T>(endpoint: string, method?: string, body?: any): Promise<T>
Makes an authenticated REST API request.
const result = await client.api('/asset/v1/content/assets', 'GET');
const created = await client.api('/asset/v1/content/assets', 'POST', { name: 'New Asset' });Throws:
SalesForceAuthError: If authentication failsSalesForceAPIError: If the API request fails
endpoints(): Promise<any>
Retrieves available API endpoints.
const endpoints = await client.endpoints();soapClient(): Promise<SoapClientInterface>
Creates a configured SOAP client.
const soapClient = await client.soapClient();
const result = await soapClient.RetrieveAsync({ /* ... */ });Assets
Manage Marketing Cloud content assets.
Constructor
const assets = new Assets(salesForceClient);Methods
list(): Promise<AssetsListResponse>
Lists all assets of type 205 (HTML content blocks).
const assets = await assetsClient.list();
console.log(`Found ${assets.count} assets`);update(id: string, data: Record<string, any>): Promise<AssetResponse>
Updates an asset.
const updated = await assetsClient.update('12345', {
name: 'Updated Asset Name',
content: '<html>...</html>'
});DataExtensions
Manage data extensions and their records.
Constructor
const dataExtensions = new DataExtensions(salesForceClient);Methods
get(externalKey: string): Promise<DataExtensionResponse>
Retrieves rows from a data extension.
const data = await dataExtensions.get('customer-de');getData(externalKey: string, primaryKey: string, primaryKeyValue: string): Promise<Record<string, any> | undefined>
Gets a specific record by primary key.
const customer = await dataExtensions.getData('customer-de', 'email', '[email protected]');insert(externalKey: string, items: DataExtensionRow[]): Promise<any>
Inserts records.
await dataExtensions.insert('customer-de', [
{ keys: { email: '[email protected]' }, values: { name: 'John', status: 'active' } }
]);update(externalKey: string, primaryKey: string, primaryKeyValue: string, values: Record<string, any>): Promise<any>
Updates a record.
await dataExtensions.update('customer-de', 'email', '[email protected]', {
status: 'inactive',
lastUpdated: new Date().toISOString()
});delete(externalKey: string, primaryKey: string, primaryKeyValue: string): Promise<any>
Deletes a record.
await dataExtensions.delete('customer-de', 'email', '[email protected]');getAllRows(externalKey: string): Promise<DataExtensionRow[]>
Gets all rows with automatic pagination.
const allRows = await dataExtensions.getAllRows('customer-de');
console.log(`Total rows: ${allRows.length}`);insertAsync(externalKey: string, items: Record<string, any>[]): Promise<any>
Inserts records asynchronously (for large batches).
const result = await dataExtensions.insertAsync('customer-de', [
{ email: '[email protected]', name: 'John' }
]);updateAsync(externalKey: string, items: Record<string, any>[]): Promise<any>
Updates records asynchronously.
clearRecords(externalKey: string, primaryKey?: string): Promise<void>
Deletes all records from a data extension.
await dataExtensions.clearRecords('temp-de', 'id');Static: jsonToValues(data: any, attribute: string, count?: number, size?: number): Record<string, string>
Splits JSON into chunks for storage in multiple fields.
const chunked = DataExtensions.jsonToValues(
{ large: 'object' },
'json',
4,
3900
);
// Returns: { json1: '...', json2: '...', json3: '...', json4: '...' }AutomationStudio
Manage Marketing Cloud automations.
Constructor
const automation = new AutomationStudio(salesForceClient);Timezone Constants
AutomationStudio provides timezone constants for easier automation scheduling:
// Available timezone constants
AutomationStudio.TIME_ZONE_AMERICA_TORONTO // 76 - Eastern Time
AutomationStudio.TIME_ZONE_AMERICA_CHICAGO // 27 - Central TimeMethods
getAll(): Promise<AutomationsListResponse>
Gets all automations.
const automations = await automation.getAll();get(externalKey: string): Promise<AutomationResponse>
Gets a specific automation.
const auto = await automation.get('my-automation-key');create(options?: CreateAutomationOptions): Promise<AutomationResponse>
Creates a new automation. All parameters are optional but typically all should be provided.
Parameters:
name(optional): Name of the automationdescription(optional): Description of the automationsteps(optional): Array of automation steps with activitiesstartDate(optional): Start date in ISO 8601 formattimeZoneId(optional): Timezone ID
// Create with all parameters
const newAuto = await automation.create({
name: 'Daily Email Campaign',
description: 'Sends daily promotional emails',
startDate: '2026-03-01T09:00:00',
timeZoneId: AutomationStudio.TIME_ZONE_AMERICA_CHICAGO,
steps: [{
stepNumber: 0,
activities: [{
name: 'Send Email',
objectTypeId: 42,
displayOrder: 1,
activityObjectId: 'your-activity-id'
}]
}]
});activate(automationId: string, date: string, timeZoneId?: number): Promise<boolean>
Activates an automation. Uses timezone constants for automatic date formatting.
const success = await automation.activate(
'automation-id',
'2026-03-01T10:00:00',
AutomationStudio.TIME_ZONE_AMERICA_TORONTO // Default if not specified
);
// Or with Central Time
const success = await automation.activate(
'automation-id',
'2026-03-01T10:00:00',
AutomationStudio.TIME_ZONE_AMERICA_CHICAGO
);
##### `pause(automationId: string): Promise<boolean>`
Pauses an automation.
```typescript
await automation.pause('automation-id');run(automationId: string): Promise<any>
Runs an automation immediately.
const result = await automation.run('automation-id');Error Handling
The SDK provides custom error classes for better error handling:
SalesForceConfigError
Thrown when configuration is invalid or missing.
try {
const client = new SalesForceClient({});
} catch (error) {
if (error instanceof SalesForceConfigError) {
console.error('Configuration error:', error.message);
}
}SalesForceAuthError
Thrown when authentication fails.
try {
await client.api('/some/endpoint');
} catch (error) {
if (error instanceof SalesForceAuthError) {
console.error('Auth failed:', error.statusCode, error.message);
}
}SalesForceAPIError
Thrown when API requests fail.
try {
await client.api('/invalid/endpoint');
} catch (error) {
if (error instanceof SalesForceAPIError) {
console.error('API error:', {
statusCode: error.statusCode,
endpoint: error.endpoint,
method: error.method,
message: error.message
});
}
}Development
Setup
npm installBuild
npm run buildTest
# Run tests once
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage
# Run tests with UI
npm run test:uiLint
npm run lintFormat
npm run format🚀 Releasing New Versions
This package uses semantic versioning. To release a new version:
Using VS Code Tasks (Recommended)
Press Cmd+Shift+P (Mac) or Ctrl+Shift+P (Windows/Linux) and select "Tasks: Run Task", then choose:
- Version: Patch (Bug Fix) - For backward-compatible bug fixes (1.0.0 → 1.0.1)
- Version: Minor (New Feature) - For backward-compatible new features (1.0.0 → 1.1.0)
- Version: Major (Breaking Change) - For breaking changes (1.0.0 → 2.0.0)
Each task will:
- Run all tests
- Build the package
- Bump the version in package.json
- Create a git commit and tag
- Push the tag to GitHub
- GitHub Actions will automatically publish to GitHub Packages
Manual Release
# Run tests and build
npm test && npm run build
# Bump version (patch, minor, or major)
npm version patch # or minor, or major
# Push the tag
git push --follow-tagsThe GitHub Actions workflow will automatically:
- Build the package
- Publish to GitHub Packages
- Create a GitHub release with auto-generated release notes
License
MIT
Contributing
Contributions are welcome! Please ensure:
- All tests pass
- Code is formatted with Prettier
- TypeScript types are properly defined
- New features include tests and documentation
Support
For issues and questions, please use the GitHub issue tracker.
