Derived Values
Derived Values
Derived values let you keep config composition inside CNOS instead of re-implementing it in app code.
Template shorthand:
app: origin: $derive: "${value.app.protocol}://${value.app.host}:${value.app.port}"Expression form:
app: effective_port: $derive: expr: "coalesce(process.env.PORT, value.app.default_port, '3000')"Write from the CLI
cnos value set app.origin --derive '${value.app.protocol}://${value.app.host}'cnos value set app.effective_port --derive --expr "coalesce(process.env.PORT, value.app.default_port, '3000')"Built-ins
Supported functions:
concat(...)coalesce(...)when(condition, thenValue, elseValue)exists(ref)eq(a, b)ne(a, b)
The language is intentionally small and safe. There is no arbitrary JavaScript execution.
Runtime Namespaces
process.* is the built-in runtime namespace. It stays live between reads.
app: effective_port: $derive: expr: "coalesce(process.env.PORT, value.app.default_port, '3000')"Custom runtime namespaces are declared in the manifest and populated by the host app:
namespaces: runtime: request: description: HTTP request context server_only: trueimport cnos from '@kitsy/cnos';
await cnos.ready();
cnos.registerRuntimeProvider('request', (key) => { if (key === 'headers.host') { return currentRequest?.headers.host; }
return undefined;});Caching Rules
- config-only derivations are cached once per resolution pass
- runtime-dependent derivations are never cached
That means value.app.origin is stable until the next createCnos() or cnos.ready(), while value.app.effective_port can change between reads when process.env.PORT changes.
Browser and Server Behavior
Browser/public outputs always need concrete values.
- config-only derived values can be promoted and embedded normally
- runtime-dependent derived values that rely on server-only namespaces are rejected for browser/public builds
Server projections split the result:
valuescontains concrete non-secret values, including config-only derivationsderivedcontains live runtime-dependent formulasruntimeNamespaceslists which runtime providers the server runtime needs
Use Cases
Cross-app browser links:
apps: cnos: origin: $derive: "${value.platform.protocol}://${value.apps.cnos.host}"
public: promote: - value.apps.cnos.originimport cnos from '@kitsy/cnos/browser';
const cnosOrigin = cnos('public.apps.cnos.origin');Server fallback port:
server: port: $derive: expr: "coalesce(process.env.PORT, value.server.default_port, '3000')"