
Shared internal utilities for @simplysf Salesforce CLI plugins. This is not a Salesforce CLI plugin itself — it's a plain library consumed by the other packages in this monorepo.
It deliberately does not depend on @salesforce/sf-plugins-core. Anything needing the oclif flag or command layer belongs in @simplysf/simply-plugin-kit instead.
npm install @simplysf/simply-core
Everything below is exported from the package root.
| Export |
Description |
authenticateClientCredentials(options) |
Authenticates via the OAuth 2.0 Client Credentials grant — a flow the Salesforce CLI has no built-in support for (only web, JWT, and SFDX auth-url). Proxies @jsforce/jsforce-node's OAuth2 token exchange into @salesforce/core's AuthInfo, the same way the JWT flow hands off its own token internally, so the resulting org is persisted and alias-able like any other sf-authenticated org. |
ClientCredentialsAuthOptions, ClientCredentialsAuthResult |
Option and result types. |
import { authenticateClientCredentials } from '@simplysf/simply-core';
const { username } = await authenticateClientCredentials({
loginUrl: 'https://my-org.my.salesforce.com',
consumerKey: 'consumer-key',
consumerSecret: 'consumer-secret',
alias: 'my-org',
setDefault: true,
});
The Connected App's OAuth policy must include the api and id/openid scopes — AuthInfo resolves the username/org ID via services/oauth2/userinfo, which depends on them. Client Credentials tokens run as the single "run as" user configured on the Connected App in Setup, not a per-request user.
| Export |
Description |
queryRecords(conn, soql, options?) |
Async generator yielding flat, string-valued records. Picks its own transport: below bulkThreshold (default 2000) it uses Connection#autoFetchQuery; above it, streamBulkQuery, so memory stays flat at any result size. Not for Tooling API queries — Bulk API v2 doesn't support them. |
chunkedInQuery(conn, values, buildSoql, options) |
Runs a query once per chunk of values, splicing each chunk into a quoted IN (...) clause, and returns every record from every chunk. Use when an IN list would otherwise exceed SOQL's length limit. |
escapeSoqlLiteral(value) |
Escapes a value for use inside a single-quoted SOQL string literal. |
ChunkedInQueryOptions, QueryRecordsOptions |
Option types for the two query helpers. |
| Export |
Description |
streamBulkQuery(conn, soql, opts?) |
Runs a SOQL query through Bulk API v2 and returns the merged CSV results as one Readable. |
streamBulkQueryToFile(conn, soql, path, opts?) |
The same, written straight to a file — the common case. |
SkipFirstLineTransform |
Strips the duplicate header row from each result page after the first. |
StreamBulkQueryOptions, StreamBulkQueryResult, StreamBulkQueryToFileOptions, StreamBulkQueryToFileResult |
Option and result types. |
Connection.bulk2.query() (jsforce's own convenience method) routes each result page through jsforce's legacy HTTP transport, which fully buffers each page into memory before your code can consume it — defeating streaming for large exports. These helpers avoid that by fetching result pages directly with undici, converting the response body straight to a Node stream, and piping it onward. jsforce is still used for job creation and polling; only the result-page fetch bypasses it.
import { streamBulkQueryToFile } from '@simplysf/simply-core';
const result = await streamBulkQueryToFile(connection, 'SELECT Id, Name FROM Account', './accounts.csv');
| Export |
Description |
createCsvFileWriter(outputPath, columns) |
Opens a streaming CSV writer, for writing rows incrementally without holding them all in memory. |
writeRecordsToCsvFile(records, outputPath, columns) |
Pipes an AsyncIterable of records — e.g. queryRecords() — straight to a CSV file. Resolves to { recordCount }. |
CsvFileWriter |
The writer handle returned by createCsvFileWriter. |
| Export |
Description |
readSfdxProject(dir?) |
Reads and parses the project file. |
getDefaultPackageDirectory(project) |
Returns the entry flagged default: true. |
getPluginConfig(source, keyPath) |
Walks a dot-delimited path (e.g. plugins.simply.dependencies.ignore) through any object, returning undefined if any segment is missing. |
SFDX_PROJECT_FILE_NAME |
'sfdx-project.json'. |
SfdxProject, SfdxPackageDirectory, SfdxPackageDirectoryDependency |
Types for the parsed file. |
| Export |
Description |
isPackage2Id, isPackage2VersionId, isSubscriberPackageId, isSubscriberPackageVersionId |
Prefix predicates for the four package ID kinds. |
PACKAGE_PREFIX_PACKAGE2, PACKAGE_PREFIX_PACKAGE2_VERSION, PACKAGE_PREFIX_SUBSCRIBER_PACKAGE, PACKAGE_PREFIX_SUBSCRIBER_PACKAGE_VERSION |
The prefixes those predicates check (0Ho, 05i, 033, 04t). |
| Export |
Description |
resolvePackageNamesByApiName(conn, apiNames, options?) |
Maps metadata API names to the installed package that owns them. |
resolvePackageNamesBySubjectId(conn, subjectIds, options?) |
The same, keyed by subject ID. |
normalizePublisherName(publisherName, fallbackLabel) |
Normalizes a publisher name for display, falling back to fallbackLabel when absent. |
LOCAL_PACKAGE_LABEL, LOCAL_PUBLISHER_NAME |
Labels used for metadata that belongs to the org itself rather than an installed package. |
ResolvePackageNamesByApiNameOptions, ResolvePackageNamesOptions |
Option types. |
| Export |
Description |
loadJsonConfig(path, schema) / loadJsonConfigSync |
Reads a JSON config file and validates it against a schema. |
parseJsonConfig(contents, schema) |
The same, from an already-read string. |
ConfigSchema, JsonConfigResult |
Schema and result types. |
| Export |
Description |
chunk(items, size) |
Splits an array into fixed-size chunks. |
mapChunked(items, size, mapper) |
Maps an async mapper over an array one chunk at a time, awaiting each chunk before the next. |
ensureDirectory(path) |
Creates a directory (and parents) if it doesn't already exist. |
timestampForFileName(date?) |
A filesystem-safe timestamp, for generated output file names. |
Please report any issues at https://github.com/SimplySF/simply-node/issues
This package is part of the @simplysf/simply monorepo. See CONTRIBUTING.md for what's specific to this package, and the repo's root CONTRIBUTING.md for repo structure, setup, commit conventions, and how to submit a pull request. Please also read our Code of Conduct.
Licensed under the Apache-2.0 license.