A hybrid (ESM and CJS) library to manage PingOne Advanced Identity Cloud environments, ForgeOps deployments, and classic deployments.
Frodo-lib powers frodo-cli, the command line tool to manage SaaS and self-hosted deployments. This includes the capability metadata and registry (frodo-lib's mcp module) behind frodo-cli's turn-key MCP server — see frodo-cli's MCP Server docs if you're looking to use MCP; frodo-lib itself doesn't run one, though it's the primitive a custom MCP integration built directly on the library could use.
Since 4.12.0, all 120 data-model types (skeletons, export/import option
interfaces, shared model types) are exported from the root entry — see
Using the library for the TypeScript import pattern.
The per-file ./types/* deep-import subpath is deprecated.
Full migration guidance — every removed and deprecated function per major version, with replacements — is maintained in the Migration Guide. Summary:
get*/put* naming, replaced by read*/update*/create*/
delete* equivalents on the same module). Four deprecated
frodo.cloud.variable functions and the journey/node classification
functions were overlooked; 5.0.0 removes them.frodo.cloud.variable functions
(getVariable, getVariables, putVariable, setVariableDescription;
replaced by readVariable, readVariables, createVariable/
updateVariable, updateVariableDescription) and the journey/node
classification functions deprecated in 4.0.0: frodo.authn.journey
(isCustomJourney, isPremiumJourney, isCloudOnlyJourney,
getJourneyClassification, JourneyClassificationType,
JourneyClassification) and frodo.authn.node (isPremiumNode,
isCloudOnlyNode, isCloudExcludedNode, isDeprecatedNode,
isCustomNode, getNodeClassification, NodeClassificationType,
NodeClassification) — removed without replacement, as the product no
longer classifies journeys or nodes../types/* deep-import subpath (see
Using the library).@rockcarver/frodo-lib/types/<module> deep-import
subpath since 4.12.0: it only resolves under the legacy
moduleResolution: node mode, which TypeScript 6 deprecates and 7
removes. Migrate to root imports — see
Using the library. Planned for removal in a
future major.The library is multi-instantiable: each frodo instance connects to one Ping Identity Platform instance at a time, and multiple instances can run concurrently — e.g. to synchronize configuration between a source and a target environment. (Frodo Library 1.x operated using a global singleton, making it impossible to connect to more than one platform instance at a time.)
The library exposes two main types describing its modules (Frodo) and state (State). Each module in turn exports its collection of functions as a type as well. Exposing the library structure as types enables auto-completion for both JS and TS developers with properly configured IDEs like Visual Studio Code and also serves as an abstraction layer between what the library exposes vs what and how it's implemented.
The frodo default instance (and each factory-created instance) organizes functionality into modules — see the module table below — and every module function takes the instance's state (connection details, tokens, and settings) implicitly, so calls stay concise. A default singleton-style instance is available as frodo for quick scripts; use the createInstance* factory functions when you need concurrent connections to more than one instance.
List of modules that have been updated and/or added by version:
| Module | Since | Capabilities |
|---|---|---|
| frodo.admin | 1.0.0 | Library of common and complex admin tasks. |
| frodo.agent | 1.0.0 | Manage web, java, and gateway agents. |
| frodo.am.config | 3.0.1 | Manage all AM entities that are not otherwise managed in Frodo (chains, modules, tree config, servers, webhooks, etc.) |
| frodo.app | 2.0.0 | Manage platform applications and dependencies. |
| frodo.authn.journey | 1.0.0 | Manage authentication journeys. |
| frodo.authn.node | 1.0.0 | Manage authentication nodes. |
| frodo.authn.settings | 2.0.0 | Manage realm-wide authentication settings. |
| frodo.authz.policy | 1.0.0 | Manage authorization policies and dependencies. |
| frodo.authz.policySet | 1.0.0 | Manage policy sets and dependencies. |
| frodo.authz.resourceType | 1.0.0 | Manage resource types and dependencies. |
| frodo.cache | 2.0.0 | Token cache management exposed through the library but primarily used internally. |
| frodo.cloud.adminFed | 1.0.0 | Manage PingOne Advanced Identity Cloud admin federation. |
| frodo.cloud.env | 2.0.3 | Manage PingOne Advanced Identity Cloud environment settings (custom domains, cookie domains, federation enforcement, release, SSO cookie config, etc.). |
| frodo.cloud.env.cert | 2.0.3 | Manage certificates in PingOne Advanced Identity Cloud |
| frodo.cloud.env.csr | 2.0.3 | Manage certificate signing requests in PingOne Advanced Identity Cloud |
| frodo.cloud.env.promotion | 2.0.3 | Manage promotions in PingOne Advanced Identity Cloud |
| frodo.cloud.esvCount | 2.0.2 | Obtain environment secrets and variables (ESV) count information for PingOne Advanced Identity Cloud. |
| frodo.cloud.feature | 1.0.0 | Obtain info on PingOne Advanced Identity Cloud features. |
| frodo.cloud.idmFeature | 4.6.0 | Read, validate, and install IDM tenant-configuration features (distinct from frodo.cloud.feature, which covers AM-side platform features). |
| frodo.cloud.iga | 4.0.0 | Manage Identity Governance (IGA) configuration: workflows, certification templates, events, glossary, request forms, and request types. |
| frodo.cloud.iga.workflow | 4.0.0 | Export, import, and delete IGA workflows. |
| frodo.cloud.log | 1.0.0 | Access PingOne Advanced Identity Cloud debug and audit logs. |
| frodo.cloud.secret | 1.0.0 | Manage secrets in PingOne Advanced Identity Cloud. |
| frodo.cloud.serviceAccount | 1.0.0 | Manage service accounts in PingOne Advanced Identity Cloud. |
| frodo.cloud.startup | 1.0.0 | Apply changes to secrets and variables and restart services in PingOne Advanced Identity Cloud. |
| frodo.cloud.variable | 1.0.0 | Manage variables in PingOne Advanced Identity Cloud. |
| frodo.cloud.wsfed | 4.0.0 | Manage WS-Federation in PingOne Advanced Identity Cloud (SP connections, IdP adapters, authentication policies, signing keys, federation info, virtual host names). |
| frodo.config | 2.0.0 | Manage the whole platform configuration. |
| frodo.conn | 1.0.0 | Manage connection profiles. |
| frodo.email.template | 1.0.0 | Manage email templates (IDM). |
| frodo.idm.config | 2.0.0 | Manage any IDM configuration object. |
| frodo.idm.connector | 2.0.0 | Manage IDM connector configuration. |
| frodo.idm.crypto | 2.0.0 | Encrypt and decrypt IDM configuration values (attribute-level encryption for sensitive configuration data). |
| frodo.idm.managed | 1.0.0 | Manage IDM managed object schema (managed.json). |
| frodo.idm.managed.schema | 4.6.0 | Manage individual managed-object schema properties. Relationship-property CRUD (readManagedObjectSchemaProperty/updateManagedObjectSchemaProperty/removeManagedObjectSchemaProperty) via IDM's dedicated v2 schema API requires IDM 7.5+ (Cloud always qualifies; not reachable on classic, which has no IDM at all); also supports auto-creating a bidirectional relationship's reverse side in the same write. |
| frodo.idm.managedSystem | 4.6.0 | Manage managed-system-object (svcacct, teammember) records. Read-only for schema (see frodo.idm.managedSystem.schema). |
| frodo.idm.managedSystem.schema | 4.6.0 | Read managed-system-object schema (svcacct, teammember). Read-only -- these are Ping-owned system types, not user-customizable. |
| frodo.idm.mapping | 2.0.0 | Manage IDM mappings (sync.json). |
| frodo.idm.organization | 1.0.0 | Limited Org Model management exposed through the library but primarily used internally. |
| frodo.idm.recon | 2.0.0 | Read, start, cancel IDM recons. |
| frodo.idm.script | 2.0.0 | Compile and evaluate IDM scripts. |
| frodo.idm.system | 2.0.0 | Manage data in connected systems. |
| frodo.info | 1.0.0 | Obtain information about the connected instance and authenticated identity. |
| frodo.login | 1.0.0 | Authenticate and obtain necessary tokens. |
| frodo.oauth2oidc.client | 1.0.0 | Manage OAuth 2.0 clients. |
| frodo.oauth2oidc.endpoint | 2.0.0 | Limited OAuth 2.0 grant flows exposed through the library but primarily used internally. |
| frodo.oauth2oidc.external | 1.0.0 | Manage external OAuth 2.0/OIDC 1.0 (social) identity providers. |
| frodo.oauth2oidc.issuer | 2.0.0 | Manage trusted OAuth 2.0 JWT issuers. |
| frodo.oauth2oidc.provider | 1.0.0 | Manage the realm OAuth 2.0 provider. |
| frodo.rawConfig | 4.0.0 | Export raw IDM configuration. |
| frodo.realm | 1.0.0 | Manage realms. |
| frodo.role | 3.0.1 | Manage Internal Roles. |
| frodo.saml.circlesOfTrust | 1.0.0 | Manage SAML 2.0 circles of trust. |
| frodo.saml.entityProvider | 1.0.0 | Manage SAML 2.0 entity providers. |
| frodo.script | 1.0.0 | Manage access management scripts. |
| frodo.scriptType | 3.0.1 | Manage access management script types. Since 4.6.0, also introspects the bindings (available objects/APIs) exposed to scripts running in a given scripting context via readScriptBindings. |
| frodo.secretStore | 3.0.1 | Manage access management secret stores in classic and forgeops deployments. |
| frodo.server | 3.0.1 | Manage access management servers in classic and forgeops deployments. |
| frodo.service | 1.0.0 | Manage access management services. |
| frodo.session | 2.0.0 | Limited session management exposed through the library but primarily used internally. |
| frodo.site | 3.0.1 | Manage access management sites in classic and forgeops deployments. |
| frodo.state | 1.0.0 | Manage library state. |
| frodo.theme | 1.0.0 | Manage platform themes (hosted pages). |
| frodo.user | 3.0.1 | Manage access management users in classic deployments. |
| frodo.utils.constants | 1.0.0 | Access relevant library constants. |
| frodo.utils.jose | 1.0.0 | Jose utility functions exposed through the library but primarily used internally. |
| frodo.utils.json | 1.0.0 | JSON utility functions exposed through the library but primarily used internally. |
| frodo.utils.version | 1.0.0 | Utility functions to obtain current library version and available released versions. |
The library uses a secure token cache, which is active by default. The cache makes it so that when the frodo.login.getTokens() method is called, available tokens are updated in state from cache and if none are available, they are obtained from the instance configured in state. The cache is tokenized and encrypted on disk, so it persists across library instantiations. You can disable the cache by either setting the FRODO_NO_CACHE environment variable or by calling state.setUseTokenCache(false) from your application.
You can change the default location of the cache file (~/.frodo/TokenCache.json) by either setting the FRODO_TOKEN_CACHE_PATH environment variable or by calling state.setTokenCachePath('/path/to/cache.json').
The library automatically refreshes session and access tokens before they expire. Combined with the token cache, the library maintains a set of valid tokens in state at all times until it is shut down. If you do not want to automatically refresh tokens, set the autoRefresh parameter (2nd param) of your frodo.login.getTokens() call to false.
| Node.js | frodo-lib 1.x | frodo-lib 2.x | frodo-lib 3.x. | frodo-lib 4.x | frodo-lib 5.x |
|---|---|---|---|---|---|
| 14 | :white_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: |
| 16 | :white_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: |
| 18 | :heavy_minus_sign: | :white_check_mark: | :white_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
| 20 | :heavy_minus_sign: | :white_check_mark: | :white_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
| 22 | :heavy_minus_sign: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| 24 | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :white_check_mark: | :white_check_mark: |
| 26 | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :white_check_mark: | :white_check_mark: |
| 28 | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: |
The table reflects the Node.js versions each release line was tested against. The test matrix currently runs Node 22, 24, and 26.
Platform passwords and secrets are configuration values that are stored encrypted as part of platform configuration. Examples are oauth2 client secrets or service account passwords.
Frodo generally doesn't export platform passwords and secrets. The platform supports configuration placeholders and environment secrets and variables allowing administrators to separate the functional configuration from sensitive secrets and variable configuration values. frodo assumes administrators take full advantage of these capabilities so that there is no need or expectation that exports include passwords and secrets. However, where the APIs support it, administrators can seed import data with raw secrets and frodo will import them.
Frodo supports exporting and importing of ESV secret values. To leave stuartship of secret values with the cloud environment where they belong, frodo always encrypts values using either encryption keys from the source environment (default) or the target environment. Frodo never exports secrets in the clear.
For those who want to contribute or are just curious about the build process.
git clone https://github.com/rockcarver/frodo-lib.git
cd frodo-lib
npm ci
If you are a node developer and want to use frodo-lib as a library for your own applications, you can install the npm package:
npm i @rockcarver/frodo-lib
npm i @rockcarver/frodo-lib@next
import {
// default instance
frodo,
// default state
state,
} from '@rockcarver/frodo-lib';
const {
// default instance
frodo,
// default state
state,
} = require('@rockcarver/frodo-lib');
All 120 data-model types (skeletons, export/import option interfaces,
shared model types — e.g. TreeSkeleton, ScriptExportInterface,
IdObjectSkeletonInterface) are exported from the root entry and work
under every TypeScript moduleResolution mode:
import {
frodo,
type FullExportInterface,
type TreeSkeleton,
} from '@rockcarver/frodo-lib';
The per-file @rockcarver/frodo-lib/types/<module> deep-import subpath is
deprecated (it only resolves under the legacy moduleResolution: node
mode, which TypeScript 6 deprecates and TypeScript 7 removes) and will be
removed in a future major release. Use root imports instead.
Create a new instance using factory helper function and login as service account (ESM | CJS):
async function newFactoryHelperServiceAccountLogin() {
const myFrodo1 = frodo.createInstanceWithServiceAccount(
host1, // host base URL
said1, // service account id
jwk1 // service account jwk as a string
);
// destructure default instance for easier use of library functions
const { getTokens } = myFrodo1.login;
const { getInfo } = myFrodo1.info;
// login and obtain tokens
if (await getTokens()) {
// obtain and print information about the instance you are connected to
const info = await getInfo();
console.log(
`newFactoryHelperServiceAccountLogin: Logged in to: ${info.host}`
);
console.log(
`newFactoryHelperServiceAccountLogin: Logged in as: ${info.authenticatedSubject}`
);
console.log(
`newFactoryHelperServiceAccountLogin: Using bearer token: \n${info.bearerToken}`
);
} else {
console.log('error getting tokens');
}
}
newFactoryHelperServiceAccountLogin();
Create a new instance using factory helper function and login as admin user (ESM | CJS):
async function newFactoryHelperAdminLogin() {
const myFrodo1 = frodo.createInstanceWithAdminAccount(
host1, // host base URL
user1, // admin username
pass1 // admin password
);
// destructure default instance for easier use of library functions
const { getTokens } = myFrodo1.login;
const { getInfo } = myFrodo1.info;
// login and obtain tokens
if (await getTokens()) {
// obtain and print information about the instance you are connected to
const info = await getInfo();
console.log(`newFactoryHelperAdminLogin: Logged in to: ${info.host}`);
console.log(
`newFactoryHelperAdminLogin: Logged in as: ${info.authenticatedSubject}`
);
console.log(
`newFactoryHelperAdminLogin: Using bearer token: \n${info.bearerToken}`
);
} else {
console.log('error getting tokens');
}
}
newFactoryHelperAdminLogin();
Create a new instance using factory function and login as service account (ESM | CJS):
async function newFactoryServiceAccountLogin() {
const myFrodo2 = frodo.createInstance({
host: host2, // host base URL
serviceAccountId: said2, // service account id
serviceAccountJwk: JSON.parse(jwk2), // service account jwk as a JwkRsa object
});
// destructure default instance for easier use of library functions
const { getTokens } = myFrodo2.login;
const { getInfo } = myFrodo2.info;
// login and obtain tokens
if (await getTokens()) {
// obtain and print information about the instance you are connected to
const info = await getInfo();
console.log(`newFactoryServiceAccountLogin: Logged in to: ${info.host}`);
console.log(
`newFactoryServiceAccountLogin: Logged in as: ${info.authenticatedSubject}`
);
console.log(
`newFactoryServiceAccountLogin: Using bearer token: \n${info.bearerToken}`
);
} else {
console.log('error getting tokens');
}
}
newFactoryServiceAccountLogin();
Create a new instance using factory function and login as admin user (ESM | CJS):
async function newFactoryAdminLogin() {
const myFrodo2 = frodo.createInstance({
host: host2, // host base URL
username: user2, // admin username
password: pass2, // admin password
});
// destructure default instance for easier use of library functions
const { getTokens } = myFrodo2.login;
const { getInfo } = myFrodo2.info;
// login and obtain tokens
if (await getTokens()) {
// obtain and print information about the instance you are connected to
const info = await getInfo();
console.log(`newFactoryAdminLogin: Logged in to: ${info.host}`);
console.log(
`newFactoryAdminLogin: Logged in as: ${info.authenticatedSubject}`
);
console.log(
`newFactoryAdminLogin: Using bearer token: \n${info.bearerToken}`
);
} else {
console.log('error getting tokens');
}
}
newFactoryAdminLogin();
Use default instance and state and login as service account (ESM | CJS):
async function defaultServiceAccountLogin() {
// destructure default instance for easier use of library functions
const { getTokens } = frodo.login;
const { getInfo } = frodo.info;
// The default state instance is a singleton. It is best to reset() the state before
// logging in to avoid interference. In this particular case no previous method in
// this file is using the default state but it is good practice to call reset() if
// you are not sure and need a clean state.
state.reset();
// host base URL
state.setHost(host0);
// service account id
state.setServiceAccountId(said0);
// service account jwk as a JwkRsa object
state.setServiceAccountJwk(JSON.parse(jwk0));
// login and obtain tokens
if (await getTokens()) {
// obtain and print information about the instance you are connected to
const info = await getInfo();
console.log(`defaultServiceAccountLogin: Logged in to: ${info.host}`);
console.log(
`defaultServiceAccountLogin: Logged in as: ${info.authenticatedSubject}`
);
console.log(
`defaultServiceAccountLogin: Using bearer token: \n${info.bearerToken}`
);
} else {
console.log('error getting tokens');
}
}
await defaultServiceAccountLogin();
Use default instance and state and login as admin user (ESM | CJS):
async function defaultAdminLogin() {
// destructure default instance for easier use of library functions
const { getTokens } = frodo.login;
const { getInfo } = frodo.info;
// The default state instance is a singleton. It is best to reset() the state before
// logging in to avoid interference. In this particular case the previous method in
// this file is populating the state with a service account login and the admin login
// could possibly fail.
state.reset();
// host base URL
state.setHost(host0);
// username of an admin user
state.setUsername(user0);
// password of the admin user
state.setPassword(pass0);
// login and obtain tokens
if (await getTokens()) {
// obtain and print information about the instance you are connected to
const info = await getInfo();
console.log(`defaultAdminLogin: Logged in to: ${info.host}`);
console.log(
`defaultAdminLogin: Logged in as: ${info.authenticatedSubject}`
);
console.log(`defaultAdminLogin: Using bearer token: \n${info.bearerToken}`);
} else {
console.log('error getting tokens');
}
}
await defaultAdminLogin();
Check out all the examples in /path/to/frodo-lib/examples.
frodo-lib can record the HTTP traffic it produces against a real environment and replay it later with no network access. frodo-cli runs its whole end-to-end test suite this way, and any tool built on frodo-lib can do the same: set FRODO_MOCK=record to record and FRODO_MOCK=1 to replay.
See the record and replay developer guide for how to record and replay, where recordings are stored, how login is shared between runs, and how secrets and expiration are handled.
Please use the repository's issues to request new features/enhancements or report bugs/issues.
If you would like to contribute to frodo, please refer to the contributing instructions.
If you are a maintainer of this repository, please refer to the pipeline and release process instructions, the build environment documentation (toolchain, bundler details, dependency policy), and the migration guide (breaking changes per major — keep it updated when removing or deprecating public functions).