Balena Settings Client
balena-settings-client is a low-level utility module designed to provide read-only access to user-configurable balena application settings. It consolidates configuration from various sources, including default settings, user-specific `.balenarc.yml` files (e.g., `$HOME/.balenarc.yml` on Unix), project-specific `.balenarc.yml` files (`$PWD/balenarc.yml`), and environment variables prefixed with `BALENARC_`. Values are merged with a clear precedence hierarchy, allowing for flexible overrides. The current stable version is 6.0.3, with recent releases indicating active maintenance and development. Key differentiators include its role in the balena ecosystem for managing client-side settings, its ability to merge configurations from multiple sources, and its explicit read-only nature. This module is not intended for direct end-user consumption; instead, users are typically directed to the higher-level `balena-sdk` for interacting with balena services.
Common errors
-
ERR_REQUIRE_ESM: Must use import to load ES Module
cause Attempting to use `require()` to import `balena-settings-client` in a project configured as an ES Module, or when the package itself is treated as ESM.fixChange your import statement from `const settings = require('balena-settings-client');` to `import settings from 'balena-settings-client';`. Ensure your project's `package.json` has `"type": "module"` or uses `.mjs` file extensions for ESM. -
TypeError: settings.get is not a function
cause This error typically occurs if `settings` was not correctly imported or if a named import was attempted instead of the default export pattern.fixVerify that `balena-settings-client` is imported as `import settings from 'balena-settings-client';` and that `settings.get()` is called on the default exported object. -
TypeError: settings.get('nested.path') - Property path access no longer supportedcause In v6.0.0 and later, the `get` method removed support for retrieving values using dot-notation property paths.fixInstead of `settings.get('parent.child')`, first get the parent object: `const parent = settings.get('parent');` then access the child property: `const child = parent?.child;`. -
Unsupported Node.js version. balena-settings-client requires Node.js >=20.12.0.
cause Running the application with a Node.js version older than 20.12.0, which is no longer supported by v6.0.0+.fixUpdate your Node.js environment to version 20.12.0 or newer. Use a tool like `nvm` (Node Version Manager) to easily switch Node.js versions.
Warnings
- breaking Version 6.0.0 dropped support for Node.js versions older than 20.12.0 and requires ES2019 features. Ensure your Node.js environment meets these requirements to avoid runtime errors.
- breaking The `get` method no longer supports property paths (e.g., `settings.get('a.b.c')`). Attempting to use property paths will result in the method trying to retrieve a top-level setting with that literal name, likely returning `undefined` or incorrect values.
- gotcha This module is explicitly designed for low-level, read-only access to settings. It does not provide any API to modify or persist settings because it merges from multiple sources and cannot determine where to write changes back. For persisting data, consider `balena-settings-storage`.
- gotcha This module is considered low-level and is not meant for direct use by end-user applications. Balena recommends using the `balena-sdk` which provides a more abstract and user-friendly interface for interacting with balena services, including settings.
- breaking Version 6.0.0 replaced `lodash` with `es-toolkit` and dropped `Bluebird`. While these are internal dependency changes, if you were relying on implicit `lodash` or `Bluebird` functionality exposed through `balena-settings-client`'s internals, your code might break.
Install
-
npm install balena-settings-client -
yarn add balena-settings-client -
pnpm add balena-settings-client
Imports
- settings
const settings = require('balena-settings-client');import settings from 'balena-settings-client';
- get
import { get } from 'balena-settings-client'; get('balenaUrl');import settings from 'balena-settings-client'; settings.get('balenaUrl'); - getAll
import { getAll } from 'balena-settings-client'; getAll();import settings from 'balena-settings-client'; settings.getAll();
Quickstart
import settings from 'balena-settings-client';
import * as fs from 'fs';
import * as path from 'path';
// Create a dummy .balenarc.yml in the current working directory for demonstration
const cwdBalenarcPath = path.join(process.cwd(), 'balenarc.yml');
fs.writeFileSync(cwdBalenarcPath, 'projectsDirectory: "/tmp/my-projects-dir"\n');
// Simulate an environment variable
process.env.BALENARC_CUSTOM_SETTING = 'some-custom-value';
async function demonstrateSettings() {
console.log('--- Reading individual settings ---');
const balenaUrl = settings.get('balenaUrl');
console.log(`balenaUrl: ${balenaUrl || 'Not set (default)'}`);
const projectsDirectory = settings.get('projectsDirectory');
console.log(`projectsDirectory (from CWD config): ${projectsDirectory}`);
const customSetting = settings.get('customSetting');
console.log(`customSetting (from ENV): ${customSetting}`);
console.log('\n--- Reading all settings ---');
const allSettings = settings.getAll();
console.log(JSON.stringify(allSettings, null, 2));
// Clean up the dummy file
fs.unlinkSync(cwdBalenarcPath);
}
demonstrateSettings().catch(console.error);