donobu
Version:
Create browser automations with an LLM agent and replay them as Playwright scripts.
159 lines • 5.91 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnvDataManager = void 0;
const v4_1 = require("zod/v4");
const Logger_1 = require("../utils/Logger");
/**
* Business-logic layer over the {@link EnvPersistenceRegistry} for Donobu flow
* environment data - the user-managed key-value store that supplies
* configuration values (API keys, base URLs, etc.) to flows at runtime.
*
* Responsibilities:
* - **Validation** - enforces key format, max key length, and max value size.
* - **Multi-layer orchestration** - writes fan out to every persistence layer;
* reads resolve from the first layer that holds a value.
* - **Selective hydration** - {@link getByNames} fetches only the variables a
* flow has declared in its allow-list, keeping the runtime env minimal.
*
* Exposed via REST at `/api/env` (see `EnvDataApi`) and consumed internally by
* `PageAi` and `DonobuFlowsManager` during flow execution.
*/
class EnvDataManager {
constructor(envPersistenceFactory, maxKeyLength = EnvDataManager.DEFAULT_MAX_KEY_LENGTH, maxValueLength = EnvDataManager.DEFAULT_MAX_VALUE_LENGTH) {
this.envPersistenceFactory = envPersistenceFactory;
this.maxKeyLength = maxKeyLength;
this.maxValueLength = maxValueLength;
}
/**
* Stores an environment datum with validation.
*
* @param key The key for the environment datum
* @param value The value to store
* @throws InvalidParamValueException if the key or value is invalid
*/
async setEnvironmentDatum(key, value) {
// Validate the key and value
this.validateKey(key);
this.validateValue(value);
// Store in all persistence layers
const persistenceLayers = await this.envPersistenceFactory.getAll();
for (const persistence of persistenceLayers) {
await persistence.setEnvironmentDatum(key, value);
}
}
/**
* Deletes an environment datum by key.
*
* @param key The key of the datum to delete
*/
async deleteEnvironmentDatum(key) {
this.validateKey(key);
const persistenceLayers = await this.envPersistenceFactory.getAll();
for (const persistence of persistenceLayers) {
await persistence.deleteEnvironmentDatum(key);
}
}
/**
* Retrieves an environment datum by key.
*
* @param key The key of the datum to retrieve
* @returns The environment datum value or undefined if not found
*/
async getEnvironmentDatum(key) {
this.validateKey(key);
const persistenceLayers = await this.envPersistenceFactory.getAll();
for (const persistence of persistenceLayers) {
try {
const value = await persistence.getEnvironmentDatum(key);
if (value !== undefined) {
return value;
}
}
catch (error) {
Logger_1.appLogger.warn(`Failed to get environment datum from persistence layer: ${error}`);
}
}
return undefined;
}
/**
* Retrieves all environment data.
*
* @returns A record of all environment data where keys are datum keys and values are datum values
*/
async getEnvironmentData() {
const result = {};
const persistenceLayers = await this.envPersistenceFactory.getAll();
for (const persistence of persistenceLayers) {
try {
const data = await persistence.getEnvironmentData();
// Merge data, giving preference to values from earlier persistence layers
for (const [key, value] of Object.entries(data)) {
if (!(key in result)) {
result[key] = value;
}
}
}
catch (error) {
Logger_1.appLogger.warn(`Failed to get environment data from persistence layer: ${error}`);
}
}
return result;
}
/**
* Returns a dictionary of environment variable values for the provided names.
* Missing variables are simply omitted so callers can pass optional names
* without extra guards. Used by flows to hydrate runtime env data from the
* persisted allow-list.
*
* @example
* await getByNames(["API_KEY", "BASE_URL", "MISSING_VAR"]);
* // => { API_KEY: "abc123", BASE_URL: "https://example.com" }
*/
async getByNames(envVarNames) {
const result = {};
for (const envVarName of envVarNames) {
const envVarValue = await this.getEnvironmentDatum(envVarName);
if (envVarValue) {
result[envVarName] = envVarValue;
}
}
return result;
}
/**
* Validates an environment data key against business rules.
*
* @param key The key to validate
*/
validateKey(key) {
v4_1.z.object({
key: v4_1.z
.string()
.trim()
.min(1)
.max(this.maxKeyLength)
.regex(/^(?!.*[\s\\\/:*?"<>|]).+$/, {
message: 'key contains invalid characters (space or one of \\ / : * ? " < > |)',
}),
}).parse({ key });
}
/**
* Validates an environment data value against business rules.
*
* @param value The value to validate
*/
validateValue(value) {
v4_1.z.object({
value: v4_1.z.string().max(this.maxValueLength),
}).parse({ value });
}
}
exports.EnvDataManager = EnvDataManager;
/**
* Maximum length allowed for an environment data key.
*/
EnvDataManager.DEFAULT_MAX_KEY_LENGTH = 128;
/**
* Maximum length allowed for environment data value
*/
EnvDataManager.DEFAULT_MAX_VALUE_LENGTH = 1024 * 1024; // 1MB
//# sourceMappingURL=EnvDataManager.js.map