npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@designofadecade/salesforce-marketing-cloud

v1.5.0

Published

Salesforce Marketing Cloud SDK for Node.js

Downloads

596

Readme

Salesforce Marketing Cloud SDK

License: MIT

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-cloud

Requirements

  • 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 subdomain
  • clientId (string, required): OAuth client ID
  • clientSecret (string, required): OAuth client secret
  • accountId (string, required): Marketing Cloud account ID
  • scope (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 fails
  • SalesForceAPIError: 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 Time

Methods

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 automation
  • description (optional): Description of the automation
  • steps (optional): Array of automation steps with activities
  • startDate (optional): Start date in ISO 8601 format
  • timeZoneId (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 install

Build

npm run build

Test

# 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:ui

Lint

npm run lint

Format

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:

  1. Run all tests
  2. Build the package
  3. Bump the version in package.json
  4. Create a git commit and tag
  5. Push the tag to GitHub
  6. 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-tags

The 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.