Adaptor Registry
What is the AdaptorRegistry?
The AdaptorRegistry is a manager that keeps track of all your SDK adaptors. It tells CDF which adaptor to use when your app starts and can switch between adaptors at runtime.
Simple job: Register adaptors → pick one to be active → CDF uses it
You need it when:
- Starting your app (register adaptors before
initCDF) - Supporting multiple SDKs at the same time
- Building a custom adaptor for a backend that CDF doesn't support yet
API at a glance
| Method | Purpose |
|---|---|
getInstance() | Get the singleton registry |
register(adaptor) | Add an adaptor (identified by _identifier) |
setActiveAdaptor(identifier) | Choose which adaptor to use |
getActiveAdaptor() | Get the active adaptor instance |
getAdaptor(identifier) | Get a specific adaptor without switching |
getActiveAdaptorIdentifier() | Get the active adaptor's ID |
getRegisteredAdaptorIdentifiers() | List all registered IDs |
unregister(identifier) | Remove an adaptor |
clear() | Remove all adaptors and reset |
Basic Setup
Minimal: Register RainMaker Base SDK
import { AdaptorRegistry, initCDF } from "@espressif/rainmaker-base-cdf";
import { ESPRMBaseSDKAdaptor, ESPRMBaseAdaptorIdentifier } from "@sdk-adaptors/ESPRMBase";
const registry = AdaptorRegistry.getInstance();
// Register RainMaker Base SDK adaptor
registry.register(
new ESPRMBaseSDKAdaptor({
baseUrl: "https://api.rainmaker.espressif.com",
region: "us-east-1",
// Add other SDK config as needed
})
);
// Set as active
registry.setActiveAdaptor(ESPRMBaseAdaptorIdentifier);
// Initialize CDF
const cdf = await initCDF({ sdkAdaptorRegistry: registry });
Production: Multiple adaptors with a factory
For real apps supporting multiple SDKs, use a factory and bootstrap service. See the RainMaker Home app for the complete pattern:
import { AdaptorRegistry, initCDF } from "@espressif/rainmaker-base-cdf";
import { ESPRMBaseSDKAdaptor, ESPRMBaseAdaptorIdentifier } from "@sdk-adaptors/ESPRMBase";
import { ESPRMMatterBaseSDKAdaptor, ESPRMMatterBaseAdaptorIdentifier } from "@sdk-adaptors/ESPRMMatterBase";
import { getResolvedActiveSdk, getRMSDKConfig, getMatterSDKConfig } from "@config/sdk.config";
/**
* Factory that instantiates all adaptors.
* Add new adaptors here as integrations are added.
*/
class AdaptorFactory {
createAll() {
return [
new ESPRMBaseSDKAdaptor(getRMSDKConfig()),
new ESPRMMatterBaseSDKAdaptor(getMatterSDKConfig()),
];
}
}
/**
* Bootstrap service — handles registry setup and CDF initialization.
* Singleton so you initialize once and reuse throughout the app.
*/
class CDFBootstrap {
private static instance: CDFBootstrap;
private cdfInstance = null;
private sdkRegistry = AdaptorRegistry.getInstance();
static getInstance(factory = new AdaptorFactory()) {
if (!CDFBootstrap.instance) {
CDFBootstrap.instance = new CDFBootstrap(factory);
}
return CDFBootstrap.instance;
}
async initialize() {
const adaptors = this.adaptorFactory.createAll();
// Register all adaptors
adaptors.forEach(adaptor => {
this.sdkRegistry.register(adaptor);
});
// Set the active one
this.sdkRegistry.setActiveAdaptor(getResolvedActiveSdk());
// Initialize CDF
this.cdfInstance = await initCDF({ sdkAdaptorRegistry: this.sdkRegistry });
return this.cdfInstance;
}
}
// In your app entry point, call once:
export async function initializeApp() {
const cdf = await CDFBootstrap.getInstance().initialize();
// Now use cdf throughout your app
}
Switch adaptors at runtime
const registry = AdaptorRegistry.getInstance();
registry.setActiveAdaptor("matter-sdk"); // Switches immediately
// Your UI sees the new adaptor's data next
How the Registry Works
First, understand the architecture. Here's how adaptors and the registry fit together:
Proxy error surfacing
When a registered adaptor does not implement a method, the registry proxy throws a structured ESPCDFRegistryError with code ADAPTOR_METHOD_PROPERTY_NOT_IMPLEMENTED — failing early rather than silently returning undefined. This surfaces missing implementations during development instead of at runtime.
Build Your Own Adaptor
An adaptor implements ESPSDKAdaptor. Key rules:
- Every method returns
{ status, data, error }— Never raw SDK objects - Use transformers — Convert SDK entities to CDF entities with operations
_identifiermust be unique — Used insetActiveAdaptor()
Pattern:
import { ESPSDKAdaptor } from "@espressif/rainmaker-base-cdf";
import MySDK from "my-custom-sdk";
import { transformToMyCDFUser } from "./transformers";
export class MySDKAdaptor implements ESPSDKAdaptor {
_identifier = "my-custom-sdk";
constructor(config: any) {
MySDK.init(config);
}
async login(input: any) {
const sdkUser = await MySDK.auth.login(input.request.username, input.request.password);
return { status: "success", data: transformToMyCDFUser(sdkUser) };
}
async getCurrentLoggedInUser() {
const sdkUser = await MySDK.auth.getCurrentUser();
return { status: "success", data: transformToMyCDFUser(sdkUser) };
}
// Implement all other required methods (see TypeDoc)
}
Refer to the RainMaker Base Adaptor for a complete implementation.
Create a Transformer
A transformer converts SDK data to CDF entities and wires up operations:
import { ESPCDFUser } from "@espressif/rainmaker-base-cdf";
export function transformToMyCDFUser(sdkUser: any) {
return new ESPCDFUser({
userInfo: {
id: sdkUser.userId,
name: sdkUser.fullName,
email: sdkUser.email,
},
operations: {
async getUserInfo() {
return { status: "success", data: await sdkUser.getProfile() };
},
async logout() {
await sdkUser.logout();
},
},
_raw: sdkUser, // Keep original SDK object
identifier: "my-custom-sdk",
});
}
Three steps:
- Map SDK fields to CDF fields
- Wire operations that call the SDK
- Store the original SDK object in
_raw
For every interface method and transformer detail, refer to the TypeScript API (TypeDoc).