My App
RoomKitBackend

ConfigService

Hierarchical configuration with location-based inheritance

Overview

ConfigService provides a cascading configuration system that inherits settings through the location hierarchy. Configuration values set at a higher level (e.g., institution) are inherited by all descendants (campuses, buildings, floors, rooms) unless overridden at a more specific level.

import { ConfigService } from '@roomkit/nestjs';

Methods

set

Set a configuration value at a specific location node or globally.

async set(locationNodeId: string | null, key: string, value: string): Promise<ConfigEntry>
ParameterTypeDescription
locationNodeIdstring | nullLocation node ID, or null for a global default
keystringConfiguration key (must match [a-zA-Z0-9._]+)
valuestringConfiguration value
// Set a global default
await configService.set(null, 'booking.maxDurationMinutes', '480');

// Override for a specific building
await configService.set('building-science', 'booking.maxDurationMinutes', '240');

Throws ConfigKeyInvalidError if the key does not match the pattern [a-zA-Z0-9._]+.

resolve

Resolve a single configuration key for a location node. Walks up the location hierarchy until a value is found.

async resolve(locationNodeId: string, key: string): Promise<ConfigEntry | null>
ParameterTypeDescription
locationNodeIdstringThe location node to resolve from
keystringThe configuration key to look up

Returns the most specific ConfigEntry found, or null if the key is not set at any level.

// If 'room-a1' has no override, walks up to floor, building, campus, institution, then global
const entry = await configService.resolve('room-a1', 'booking.maxDurationMinutes');
if (entry) {
    console.log(`Max duration: ${entry.value} (set at ${entry.locationNodeId ?? 'global'})`);
}

resolveMany

Batch-resolve multiple configuration keys for a location node.

async resolveMany(locationNodeId: string, keys: string[]): Promise<Map<string, ConfigEntry | null>>
ParameterTypeDescription
locationNodeIdstringThe location node to resolve from
keysstring[]Array of configuration keys to look up

Returns a Map where each key maps to its resolved ConfigEntry or null.

const config = await configService.resolveMany('room-a1', [
    'booking.maxDurationMinutes',
    'booking.advanceBookingDays',
    'booking.requireApproval',
]);

for (const [key, entry] of config) {
    console.log(`${key}: ${entry?.value ?? '(not set)'}`);
}

getEffectiveConfig

Get the full effective configuration for a location node by merging configs from all ancestors (root to node). More specific values override less specific ones.

async getEffectiveConfig(locationNodeId: string): Promise<Map<string, ConfigEntry>>
ParameterTypeDescription
locationNodeIdstringThe location node to compute effective config for

Returns a Map of all configuration keys and their effective values. When a ConfigEntry has inheritFromParent set to false, that key is locked at that level and parent values are ignored.

const effectiveConfig = await configService.getEffectiveConfig('room-a1');

for (const [key, entry] of effectiveConfig) {
    console.log(`${key} = ${entry.value} (from ${entry.locationNodeId ?? 'global'})`);
}

ConfigEntry

interface ConfigEntry {
    locationNodeId: string | null; // null for global entries
    key: string;
    value: string;
    inheritFromParent: boolean;    // false locks the key at this level
    createdAt: Date;
    updatedAt: Date;
}

Setting inheritFromParent to false on a config entry prevents descendant nodes from inheriting overrides from ancestors above that level. This is useful for locking a configuration value at a specific point in the hierarchy.

On this page