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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@dynau/sf-utils

v1.0.8

Published

wrappers for Salesforce REST APIs

Downloads

4

Readme

@dynau/sf-utils

Provides convenient JS/TS wrappers for basic Salesforce REST APIs.

For assistance reach out to author - Anton Dynau.

What's included:

  1. Apex
    • execute anonymous apex
  2. Bulk API
    • Ingest
      • execute full job & return results
      • single operations:
        • create job
        • upload job data
        • finalize data upload
        • get job status
        • await completion
        • get successful results
        • get failed results
    • Query
      • execute full job & return results
      • single operations:
        • create job
        • get job status
        • await completion
        • get job results
  3. Sobject
    • get record count
    • Record
      • all DML operations
    • Collection
      • all DML operations
  4. Soql
    • execute soql query
  5. TS type generation
    • generate type for CSV
    • generate type for Sobject

General Concepts

Design

All actions that you can perform work with the same arguments:

  1. target org alias
  2. action config - parameters specific to each action
  3. log config - if provided, will output information about action progress into console
await Salesforce.doSomething(
	"your-org-alias",
	{ paramA: 3.14, paramB: false },
	{ actionName: "doSomething", logLevel: "ANNOUNCE" }
);

Static vs instance usage

You have 2 ways to use the library:

  1. Static methods of Salesforce class
await Salesforce.Apex.executeAnonymous("org-alias", {
	anonymousBody: "System.debug('hello');",
});
  1. create an instance of Salesforce
const MY_ORG = new Salesforce("org-alias");
await MY_ORG.Apex.executeAnonymous({
	anonymousBody: "System.debug('hello');",
});

The 2 options are identical in result, Salesforce instance can be duplicated if needed - it does not store any callout results, it's only purpose is to pass pre-populated org alias and log config to function calls

Authentication

All authentication is handled under the hood via SF CLI based on proviede targetOrg parameter. You can pass either an org alias or a username for one of orgs authenticated on your machine (run sf org list in terminal to see the list of orgs)

I understand that different people have different org aliases and usernamed for the same org, so to make it possible for multiple people to use the same codebase with hardcoded org aliases, I implemented a config system for this library.

Instance URL, resource URL, resource parameters etc.

The library handles all technical details of rest callouts and more, including:

  • Salesforce instance URL
  • REST resource URL
  • REST resource API version
  • REST resource bodies
  • REST resource URL parameters
  • REST resource headers

You just pass all action-specific parameters as function arguments, and they are applied in a context-aware manner. For exaple, the URL for this callout:

Salesforce.Sobject.Record.get("your-org-alias", {
	sObjectName: "Account",
	fields: ["Id", "Name"],
	recordId: "0010700000oq6XHAAY",
});

... will be:

Notice how the url got an API version auto-populated, sobject name & record id populated from function arguments, and a list of fields appended as query parameters

Caching

Some data is either cached at runtime or stored locally as files to reduce the amount of callouts and execution time

Here's the list of all caches:

  • org connection info is runtime-cached (sf org display is only called once per JS execution for each unique org alias)
  • sobject list callouts are runtime-cached (executed only once per JS execution for each org and scope - regular sobjects of tooling sobjects)
  • sobject schema is both runtime-cached and stored as json file cache. Any request to retrieve object schema follows this logic:
    • if schema is already loaded in runtime, return it
    • else if it's present in file storage, parse the json file and return contained schema*
    • else perform callout to retrieve schema and store it locally

Library config

Config file is not necessary for the library to work, but it allows you to change the default locations for storage of some files and map one org alias to another

Config file should be located at the root of the project and be named sf-utils-config.json.

Config has the following structure:

{
	"sobjectSchemaStoragePath": "./sobject-schema-storage", // default value
	"generatedTypesPath": "./generated-types", // default value
	"orgAliasReplacements": [
		{
			"enteredValue": "[email protected]",
			"resultValue": "[email protected]"
		}
	]
}

Action examples

Execute anonymous apex

Used resource: /services/data/vXX.X/tooling/executeAnonymous/

If createTraceFlag == true, debug logs will be generated as if the user was executing the code in dev console. Otherwise the logs will not be generated.

await Salesforce.Apex.executeAnonymous("sf-org-alias", {
	apex: "System.debug(Date.today());",
	createTraceFlag: true, // simulates your user opening dev console
});

/* 
=> {
    line: -1,
    column: -1,
    compiled: true,
    success: true,
    compileProblem: null,
    exceptionStackTrace: null,
    exceptionMessage: null
}
*/

Bulk API Ingest

Opinions

This library is opinionated in some aspects:

  1. allOrNone -- DML actions that deal with Sobject collections have a "allOrNone" parameter. Salesforce REST APIs treat is as optional and false by default. In this library it's the other way round -- the parameter is still optional, but is true by default, meaning that it will treat true or === undefined as true. In other words, transaction logic is close to Apex.
  2. Callout results -- any action that fails will throw a native JS error that you can process in a try-catch block. Notable exceptions from this list are actions working with Sobject collection that have allOrNone flag. In this case no error will be thrown so that you could iterate over returned DML results and process record-level errors yourself (also Salesforce itself considers callout successful even if all records fail even with allOrNone = true)
  3. Datatypes of Sobject fields are type-casted in all actions to provide consistency between different sources and APIs (CSV vs JSON, BULK API v2 vs sogject/get)