{"_id":"@onlineapps/runtime-config","_rev":"5-53f8b4b7ec435be2e4b0644cca623a46","name":"@onlineapps/runtime-config","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.1":{"name":"@onlineapps/runtime-config","version":"1.0.1","keywords":["config","runtime","configuration","resolver","env","defaults"],"author":{"name":"OnlineApps"},"license":"MIT","_id":"@onlineapps/runtime-config@1.0.1","maintainers":[{"name":"onlineapps","email":"npmjs@onlineapps.cz"}],"dist":{"shasum":"a56ddb72885256acd0182d5caf6c323d5137403f","tarball":"https://registry.npmjs.org/@onlineapps/runtime-config/-/runtime-config-1.0.1.tgz","fileCount":4,"integrity":"sha512-iMuYN7uKbzF3ywRGaP2bMnx7wtdKC/fjJC+0UsyTuv5uOl7x0lY4Ygxfq6IyYuGz4Vxzy0bXzxri+qUIAVorAg==","signatures":[{"sig":"MEUCIQDfry7sJF66WOPyp5ceMqRUqbhBB/QF/YvpvkRLr7L+UgIgTUwhYTzNK7e7kCv68KewCPe+idLHSqgh1+8YiI95QV4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11603},"main":"src/index.js","gitHead":"3af93721cbc5cc3849955583c61a29d47933834c","scripts":{"test":"jest --testMatch='**/tests/**/*.test.js'","test:unit":"jest --testMatch='**/tests/unit/**/*.test.js'","test:coverage":"jest --testMatch='**/tests/**/*.test.js' --coverage"},"_npmUser":{"name":"onlineapps","email":"npmjs@onlineapps.cz"},"_npmVersion":"9.2.0","description":"Runtime configuration resolver with schema-driven priority (explicit config → ENV → owner defaults)","directories":{},"_nodeVersion":"18.19.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0"},"_npmOperationalInternal":{"tmp":"tmp/runtime-config_1.0.1_1766397731289_0.7663380590957145","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@onlineapps/runtime-config","version":"1.0.2","keywords":["config","runtime","configuration","resolver","env","defaults"],"author":{"name":"OnlineApps"},"license":"MIT","_id":"@onlineapps/runtime-config@1.0.2","maintainers":[{"name":"onlineapps","email":"npmjs@onlineapps.cz"}],"dist":{"shasum":"e395309e4aaf344f239381eec1f754ca0d8430d5","tarball":"https://registry.npmjs.org/@onlineapps/runtime-config/-/runtime-config-1.0.2.tgz","fileCount":4,"integrity":"sha512-DqT1NqoQoB8yjGf3vxWcmMgBFzdqKFrSAgc/hReP9h6qskbnvx3H+ikL3krRnDuB2MZobffupMqVoz7y3fvzcA==","signatures":[{"sig":"MEUCIQDUWyU/utqcoWBYC8aM8cmC8PJCb4p/F/9amLt5hCegLAIgJvxkw/8Bd7wVOPevbivM5uybT8PPaWHetnl8aFVaBH0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11603},"main":"src/index.js","gitHead":"3af93721cbc5cc3849955583c61a29d47933834c","scripts":{"test":"jest --testMatch='**/tests/**/*.test.js'","test:unit":"jest --testMatch='**/tests/unit/**/*.test.js'","test:coverage":"jest --testMatch='**/tests/**/*.test.js' --coverage"},"_npmUser":{"name":"onlineapps","email":"npmjs@onlineapps.cz"},"_npmVersion":"9.2.0","description":"Runtime configuration resolver with schema-driven priority (explicit config → ENV → owner defaults)","directories":{},"_nodeVersion":"18.19.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0"},"_npmOperationalInternal":{"tmp":"tmp/runtime-config_1.0.2_1766402578157_0.6558786146474342","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@onlineapps/runtime-config","version":"1.0.3","keywords":["config","runtime","configuration","resolver","env","defaults"],"author":{"name":"OnlineApps"},"license":"MIT","_id":"@onlineapps/runtime-config@1.0.3","maintainers":[{"name":"onlineapps","email":"npmjs@onlineapps.cz"}],"dist":{"shasum":"f44886c46be0313e936de1b593e962400525c4c1","tarball":"https://registry.npmjs.org/@onlineapps/runtime-config/-/runtime-config-1.0.3.tgz","fileCount":4,"integrity":"sha512-ti0xC8ehenlNOFF4AdKSPT1fBPdTB66ZtumrmjndGJUaiw1VapYU2YAOevBW4lSmr+sL3QvUXNc8YT2levf+Jw==","signatures":[{"sig":"MEYCIQDgiFiSDzMjl2UQhWlohCfNpWvjnhhUiFoHmlhItBcjewIhAPT5JlRT9SX5UBkMzvyuyQWsjHElyp44Mbql5+Oc8cA7","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13024},"main":"src/index.js","gitHead":"3ca26bf53c2f9a592e1773c167f2c1b120af4e03","scripts":{"test":"jest --testMatch='**/tests/**/*.test.js'","test:unit":"jest --testMatch='**/tests/unit/**/*.test.js'","test:coverage":"jest --testMatch='**/tests/**/*.test.js' --coverage"},"_npmUser":{"name":"onlineapps","email":"npmjs@onlineapps.cz"},"_npmVersion":"11.12.1","description":"Runtime configuration resolver with schema-driven priority (explicit config → ENV → owner defaults)","directories":{},"_nodeVersion":"25.9.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0"},"_npmOperationalInternal":{"tmp":"tmp/runtime-config_1.0.3_1788033060344_0.8338360486925089","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@onlineapps/runtime-config","version":"1.1.0","keywords":["config","runtime","configuration","resolver","env","defaults"],"author":{"name":"OnlineApps"},"license":"MIT","_id":"@onlineapps/runtime-config@1.1.0","maintainers":[{"name":"onlineapps","email":"npmjs@onlineapps.cz"}],"oa":{"category":"core"},"dist":{"shasum":"1974ff6a76de9126f4ef18ab1abedba9196f0888","tarball":"https://registry.npmjs.org/@onlineapps/runtime-config/-/runtime-config-1.1.0.tgz","fileCount":4,"integrity":"sha512-jdgzxxGTt5C4bA3cvl/LtmJxE1YLyKQwlfwu4Hokwr+n1zaPFgjnr6HYoixRt/xlsBeIeUC+n3opgZYqydQc5w==","signatures":[{"sig":"MEUCIQCH4hcM869H7EwY2CCkwDe4TTUqs/fHoJTinrHrby/5ZAIgLQlLGse0e5DZE8ON0sVR3lM5wnNtxpYrAinCIojkItE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25353},"main":"src/index.js","engines":{"node":">=24.0.0 <25"},"gitHead":"117e5a093880faec566bca9498fa4bf447576608","scripts":{"test":"npm run test:unit","test:unit":"jest tests/unit","test:coverage":"jest --coverage"},"_npmUser":{"name":"onlineapps","email":"npmjs@onlineapps.cz"},"_npmVersion":"11.12.1","description":"Runtime configuration resolver with schema-driven priority (explicit config → ENV → owner defaults)","directories":{},"_nodeVersion":"25.9.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0"},"_npmOperationalInternal":{"tmp":"tmp/runtime-config_1.1.0_1789403161854_0.25754549628989687","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@onlineapps/runtime-config","version":"1.2.0","description":"Runtime configuration resolver with schema-driven priority (explicit config → ENV → owner defaults)","oa":{"category":"core"},"engines":{"node":">=24.0.0 <25"},"main":"src/index.js","publishConfig":{"access":"public"},"scripts":{"test":"npm run test:unit","test:unit":"jest tests/unit","test:coverage":"jest --coverage"},"keywords":["config","runtime","configuration","resolver","env","defaults"],"author":{"name":"OnlineApps"},"license":"MIT","devDependencies":{"jest":"^29.7.0"},"dependencies":{},"gitHead":"9841faf5b224b9d6b0d1cb1ae8bff98d876486d6","_id":"@onlineapps/runtime-config@1.2.0","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-XsuiRvyEnEdsVx1GeUBjw3qmY7XeswZAC3Q+MKKY8tBaW5NiK/Qw3Jl9WpFEMF6yjeKCrcM2fQOwE/XfWHQ4oA==","shasum":"e3f6c84c972b13587132b4bf57c6c30c56818d36","tarball":"https://registry.npmjs.org/@onlineapps/runtime-config/-/runtime-config-1.2.0.tgz","fileCount":4,"unpackedSize":27041,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAy7py0YmO6tCmmasFwKkTZKa0SJXokcoQFFfWJpcstZAiAj83xtd3iNujv2dnTnhb6bpzV6z0r1JDaiW1o4tYRGbg=="}]},"_npmUser":{"name":"onlineapps","email":"npmjs@onlineapps.cz"},"directories":{},"maintainers":[{"name":"onlineapps","email":"npmjs@onlineapps.cz"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/runtime-config_1.2.0_1789476484323_0.7631170732050196"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-22T10:02:11.203Z","modified":"2026-09-15T12:48:04.591Z","1.0.1":"2025-12-22T10:02:11.440Z","1.0.2":"2025-12-22T11:22:58.316Z","1.0.3":"2026-08-29T19:51:00.494Z","1.1.0":"2026-09-14T16:26:01.995Z","1.2.0":"2026-09-15T12:48:04.453Z"},"author":{"name":"OnlineApps"},"license":"MIT","keywords":["config","runtime","configuration","resolver","env","defaults"],"description":"Runtime configuration resolver with schema-driven priority (explicit config → ENV → owner defaults)","maintainers":[{"name":"onlineapps","email":"npmjs@onlineapps.cz"}],"readme":"> Status: current\n> Owns: the resolution of a module's runtime configuration against its declared schema — explicit config, then ENV, then the owner's default\n\n<!-- BEGIN GENERATED: library-uniform — regenerate: npx oa-sync-template readme-uniform --all -->\nUniform: [library/core](../connector/conn-orch-validator/manifests/library.manifest.json)\n\nDuty sections that apply:\n\n- `all`: L-MAIN, L-ENGINES, L-TESTS, L-TEST-SCRIPT, L-PACK-TESTS, L-PINS, L-NO-FILE-RANGE, L-CHANGELOG, L-README, L-README-REGION, L-CONSUMER\n- `core`: L-CORE-DEPS, L-CORE-EXPORTS\n<!-- END GENERATED: library-uniform -->\n\n# @onlineapps/runtime-config\n\nRuntime configuration resolver with schema-driven priority.\n\n## Features\n\n- **Single mechanism**: One resolver for all runtime config resolution\n- **Schema-driven**: Each module declares its config schema once\n- **Priority order**: explicit config → ENV → owner defaults\n- **Fail-fast**: `required: true` throws if value missing\n- **Type coercion**: Auto-parses strings to number/boolean\n\n## Installation\n\n```bash\nnpm install @onlineapps/runtime-config\n```\n\n## Usage\n\n```javascript\nconst { createRuntimeConfig } = require('@onlineapps/runtime-config');\nconst DEFAULTS = require('./defaults');\n\nconst runtimeCfg = createRuntimeConfig({\n  defaults: DEFAULTS,\n  schema: {\n    host:     { env: 'REDIS_HOST', defaultKey: 'defaultHost' },\n    port:     { env: 'REDIS_PORT', defaultKey: 'defaultPort', type: 'number' },\n    password: { env: 'REDIS_PASSWORD' },\n    ttl:      { env: 'CACHE_TTL', defaultKey: 'defaultTTLSeconds', type: 'number' },\n    // Infra topology - FAIL-FAST (no default)\n    url:      { env: 'REDIS_URL', required: true },\n  }\n});\n\n// Get single value\nconst host = runtimeCfg.get('host');\n\n// Resolve all with explicit overrides\nconst config = runtimeCfg.resolve({ password: 'secret' });\n```\n\n## Priority Order\n\n1. **Explicit config**: Value passed to `resolve()` or `get()`\n2. **Environment variable**: `process.env[spec.env]`\n3. **Owner defaults**: Value from `defaults` object\n\n## Schema Spec Properties\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `env` | string | Environment variable name |\n| `defaultKey` | string | Key in `defaults` object |\n| `default` | any | Inline default value |\n| `type` | string | Value type: `'string'`, `'number'` (whole numbers only), `'float'`, `'boolean'` |\n| `required` | boolean | If `true`, throws when value is missing |\n| `file` | string | Bare name of the `env-active` file that owns this key (`'shared.env'`). Every fail-fast message about the key — missing value and malformed value alike — then says where to set it. Requires `env` |\n\n### `file` — who writes the `Fix:` sentence\n\n`architecture-principles.md` §5 requires a missing key to be reported with\n`Fix: set <ENV_KEY> in env-active/*.env (or pass explicit config).` The resolver\ncomposes that sentence for every caller, and with `file` it names the exact file\ninstead of the glob:\n\n```javascript\ncreateRuntimeConfig({\n  defaults: {},\n  schema: { url: { env: 'REDIS_URL', required: true, file: 'shared.env' } }\n}).get('url');\n// [RuntimeConfig] Missing environment variable - REDIS_URL is required for config key \"url\".\n// Fix: set REDIS_URL in config/env-active/shared.env.\n\ncreateRuntimeConfig({\n  defaults: {},\n  schema: { url: { env: 'REDIS_URL', required: true } }\n}).get('url');\n// … Fix: set REDIS_URL in env-active/*.env (or pass explicit config).\n```\n\nSame shape, word for word, as `requireEnv(name, description, { file })` in\n`@onlineapps/service-common` (d.399) — the schema spec is this library's call\nsite, and the sentence has one shape rather than as many as there are spellings.\n\n`file` is a **bare file name**: the resolver writes the `config/env-active/`\nprefix, so a value carrying a path (`config/env-active/shared.env`), a different\nsuffix (`shared`), an empty string or a non-string is refused **when the schema\nis built** — a typo must fail on the happy path too, not on the day the variable\ngoes missing (principle 4).\n\n`file` also **requires `env`**, and is refused at the same moment without it. The\nfile names where an env KEY is set; with no key there is nothing to set there, so\nthe value is read at no point of the resolution — a declaration without a\nconsumer, which `change-discipline.md` (§ Removing something removes its\ndeclaration) resolves two ways only: wire it (`env`) or drop it. An empty `env`\nname is the same case, because `get()` reads the variable behind `if (spec.env)`\nand never consults it.\n\nThe same location closes the sentence about a value that IS set and cannot be\ncoerced — `Fix: set REDIS_PORT to a whole number in config/env-active/shared.env.`\nUntil d.466 it did not: the operator was told which key to correct and left to\nfind out on their own which file carries it, although the schema beside it knew.\nBoth sentences describe one key in one file.\n\nIt is an INPUT and never a derivation: `api/config/shared-env.json` owns the\nplatform's shared key set, but only build-time tooling reads it\n(`oa-sync-template shared-env`); it is absent from a service's runtime, and a\nlibrary hunting for it through `__dirname`/cwd would break principle 1. Without\n`file` the sentence is §5's own generic wording, which is correct rather than\nmissing.\n\n## Type Coercion\n\n- `number`: **whole numbers only** — the value must be an integer (`\"7\"`, `\"0\"`,\n  `\"-1\"`, surrounding whitespace is trimmed). Anything else throws: a fraction\n  (`\"2.5\"`), a trailing remainder (`\"3abc\"`), another base (`\"0x10\"`),\n  exponent notation (`\"1e3\"`), an empty string. A fractional value is a\n  configuration error here, never something to round — use `float` for it.\n- `float`: **a decimal number written in full** — optional sign, at least one\n  digit, optionally `.` and at least one digit (`\"0.8\"`, `\"-1.5\"`, `\"+0.25\"`,\n  `\"7\"`; surrounding whitespace is trimmed). Anything else throws: a trailing\n  remainder (`\"3abc\"`), exponent notation (`\"1e3\"`, `\"1e400\"`), a missing digit\n  beside the point (`\".5\"`, `\"5.\"`), another base (`\"0x10\"`), a comma decimal\n  (`\"1,5\"`), `\"NaN\"`, `\"Infinity\"`, an empty string. The result is checked for\n  finiteness separately, because a value can satisfy the grammar and still\n  overflow the double range.\n- `boolean`: Accepts `true`, `false`, `'true'`, `'false'`, `'1'`, `'0'`\n- `string`: Converts to string\n\n## Fail-Fast for Infra Topology\n\nFor infrastructure URLs/hosts, use `required: true` without defaults:\n\n```javascript\nconst runtimeCfg = createRuntimeConfig({\n  defaults: {},\n  schema: {\n    rabbitmqUrl: { env: 'RABBITMQ_URL', required: true },\n    redisUrl: { env: 'REDIS_URL', required: true },\n  }\n});\n\n// Throws if RABBITMQ_URL or REDIS_URL are not set\nconst config = runtimeCfg.resolve();\n```\n\n## Error Contract for Missing Config\n\n`required: true` must throw explicit and actionable exceptions:\n\n- Missing env-backed key, with the owning file declared (`file: 'shared.env'`):\n  - `[RuntimeConfig] Missing environment variable - <ENV_KEY> is required for config key \"<key>\". Fix: set <ENV_KEY> in config/env-active/shared.env.`\n- Missing env-backed key, without one:\n  - `[RuntimeConfig] Missing environment variable - <ENV_KEY> is required for config key \"<key>\". Fix: set <ENV_KEY> in env-active/*.env (or pass explicit config).`\n- Malformed `file` in a schema spec (refused when the schema is built):\n  - `[RuntimeConfig] Invalid schema for key \"<key>\" - file must be a bare env file name such as \"shared.env\", got: \"<value>\". Fix: pass the file name alone; the resolver writes the config/env-active/ prefix.`\n- `file` without `env` in a schema spec (refused when the schema is built):\n  - `[RuntimeConfig] Invalid schema for key \"<key>\" - file is declared without env; the owning file only names where an env key is set. Fix: add env, or drop file.`\n- Missing non-env key:\n  - `[RuntimeConfig] Missing required config key - \"<key>\" has no explicit/env/default value. Fix: define env/default/explicit value for \"<key>\".`\n- Invalid typed value:\n  - `[RuntimeConfig] Invalid <type> value for \"<key>\" (env: <ENV_KEY>) - Expected <type>, got \"<value>\".`\n- Invalid `number` value (names the expected shape and the fix):\n  - `[RuntimeConfig] Invalid number value for \"<key>\" (env: <ENV_KEY>) - Expected a whole number (e.g. \"7\", \"0\", \"-1\"), got \"<value>\". Fix: set <ENV_KEY> to a whole number.`\n  - without `env`: `… for \"<key>\" - Expected a whole number (e.g. \"7\", \"0\", \"-1\"), got \"<value>\". Fix: set \"<key>\" to a whole number.`\n- Invalid typed value of a key whose spec declares the owning `file`: the `Fix:`\n  half ends in that file, the same location the missing-key sentence names —\n  `… got \"<value>\". Fix: set <ENV_KEY> to a whole number in config/env-active/shared.env.`\n  (and, word for word, `to a decimal number in …` / `to true, false, 1 or 0 in …`).\n  Without a declared `file` the sentence is the one above, unchanged.\n\nThis contract aligns with:\n\n- `api/docs/standards/ARCHITECTURE_PRINCIPLES.md` (\"Config Contract Exceptions\")\n- `.claude/rules/architecture-principles.md` (§5 Clear Error Messages)\n\n## Naming Convention\n\n- **ServiceConfig** = biz-specific config (per-service, loaded by `ServiceConfigLoader`)\n- **RuntimeConfig** = runtime config (env/defaults, resolved by this library)\n\n## API\n\n### `createRuntimeConfig(options)`\n\nCreates a new resolver instance.\n\n**Options:**\n- `defaults` (Object): Owner defaults object\n- `schema` (Object): Config schema definition\n- `env` (Object): Environment object (defaults to `process.env`)\n\n**Returns:** `RuntimeConfigResolver` instance\n\n### `resolver.get(key, [explicitValue])`\n\nGet a single config value.\n\n**Parameters:**\n- `key` (string): Config key name\n- `explicitValue` (any): Explicit value (highest priority)\n\n**Returns:** Resolved value\n\n**Throws:** Error if key is unknown or required value is missing\n\n### `resolver.resolve([explicitConfig])`\n\nResolve all config values at once.\n\n**Parameters:**\n- `explicitConfig` (Object): Explicit config object (highest priority)\n\n**Returns:** Object with all resolved config values\n\n**Throws:** Error if any required value is missing\n\n### `resolver.keys()`\n\nGet all schema keys.\n\n**Returns:** Array of config key names\n\n### `resolver.has(key)`\n\nCheck if a key exists in schema.\n\n**Returns:** Boolean\n","readmeFilename":"README.md"}