Skip to content

simply-flow-core

Flow deactivation/deletion and obsolete Flow version pruning logic. Full signatures and types are in the API reference.

Terminal window
npm install @simplysf/simply-flow-core

Every example below assumes you already have an authenticated @salesforce/core Connection — see Get Started.

Per-item failures (a Flow that won’t deactivate, a version that won’t delete, a name that matches no Flow in the org) are collected into the result’s failures and never thrown, so one bad Flow doesn’t stop the rest. A failed query rejects.

Deleting Flows before a destructive deploy

Section titled “Deleting Flows before a destructive deploy”

Salesforce won’t remove a Flow that still has an active version. deleteFlows deactivates each Flow’s definition once, then destroys every version of it:

import fs from 'node:fs/promises';
import { readPackageManifestMembers } from '@simplysf/simply-core';
import { deleteFlows } from '@simplysf/simply-flow-core';
const manifest = await fs.readFile('manifest/destructiveChanges.xml', 'utf-8');
const flowNames = readPackageManifestMembers(manifest, 'Flow');
const result = await deleteFlows(connection, flowNames, {
onStage: (stage) => console.log(`${stage}...`), // 'deactivate', then 'delete'
});
for (const failure of result.failures) {
console.error(`${failure.developerName} (${failure.stage}): ${failure.message}`);
}

pruneObsoleteFlowVersions only ever deletes versions the org has already marked Status = 'Obsolete' — never an active Flow. Pass dryRun to see what it would delete:

import { findFlowNamesInSource, pruneObsoleteFlowVersions } from '@simplysf/simply-flow-core';
const flowNames = await findFlowNamesInSource(['force-app']);
const preview = await pruneObsoleteFlowVersions(connection, flowNames, { dryRun: true });
console.table(preview.candidates); // [{ id, developerName }, ...]
const result = await pruneObsoleteFlowVersions(connection, flowNames);
console.log(`Deleted ${result.deleted.length}, failed ${result.failures.length}`);

When a person (or an MCP client’s approval prompt) needs to approve the exact list, use the two halves separately. deleteFlowVersions deletes exactly the candidates it’s given, without querying again:

import { deleteFlowVersions, findObsoleteFlowVersions } from '@simplysf/simply-flow-core';
const candidates = await findObsoleteFlowVersions(connection, flowNames);
if (candidates.length > 0 && (await askForApproval(candidates))) {
const { deleted, failures } = await deleteFlowVersions(connection, candidates);
}