@rhombus-std/config.core 0.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Thomas Butler
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # @rhombus-std/config.core
2
+
3
+ Types-only configuration abstractions: the `IConfiguration*` interfaces
4
+ (`IConfiguration`, `IConfigurationBuilder`, `IConfigurationRoot`,
5
+ `IConfigurationSection`, `IConfigurationSource`, `IConfigurationProvider`,
6
+ `IConfigurationManager`) plus the `ITryGetResult` tuple type.
7
+
8
+ This package ships **zero runtime** — no JavaScript, only a `.d.ts` bundle.
9
+ `@rhombus-std/config` and the provider packages (`@rhombus-std/config.json`, `@rhombus-std/config.env`,
10
+ `@rhombus-std/config.commandline`) depend on it for shared interface types via `import
11
+ type`, so those types erase at compile time and never appear in any built
12
+ bundle.
13
+
14
+ ## Install
15
+
16
+ You generally don't install this package directly — `@rhombus-std/config`
17
+ re-exports every type it defines, and installing `@rhombus-std/config` pulls it
18
+ in as a dependency automatically. Install it explicitly only if you're
19
+ writing a package that implements one of these interfaces (for example a
20
+ custom `IConfigurationSource`) without depending on `@rhombus-std/config`
21
+ itself.
22
+
23
+ ```sh
24
+ npm install @rhombus-std/config.core
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```ts
30
+ import type {
31
+ IConfiguration,
32
+ IConfigurationSource,
33
+ } from "@rhombus-std/config.core";
34
+
35
+ function readPort(config: IConfiguration): string | undefined {
36
+ return config.get("Server:Port");
37
+ }
38
+ ```
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Propagates notifications that a change has occurred.
3
+ */
4
+ interface IChangeToken {
5
+ /**
6
+ * A value that indicates if a change has occurred.
7
+ */
8
+ readonly hasChanged: boolean;
9
+ /**
10
+ * A value that indicates whether this token will proactively raise
11
+ * callbacks. If `false`, the token consumer must poll {@link hasChanged}
12
+ * to detect changes.
13
+ *
14
+ * A `true` value does not guarantee that callbacks will be raised for all
15
+ * changes. Consumers should also check {@link hasChanged} when complete
16
+ * accuracy is required.
17
+ */
18
+ readonly activeChangeCallbacks: boolean;
19
+ /**
20
+ * Registers a callback that will be invoked when the token has changed.
21
+ * {@link hasChanged} MUST be set before the callback is invoked.
22
+ *
23
+ * @param callback The callback to invoke.
24
+ * @param state State to be passed into the callback.
25
+ * @returns A {@link Disposable} that is used to unregister the callback.
26
+ */
27
+ registerChangeCallback(callback: (state: unknown) => void, state?: unknown): Disposable;
28
+ }
29
+
30
+ /** Represents a section of application configuration values. */
31
+ interface IConfigurationSection extends IConfiguration {
32
+ /** The key this section occupies in its parent. */
33
+ get key(): string;
34
+ /** The full path to this section within the {@link IConfiguration}. */
35
+ get path(): string;
36
+ /** The section value. */
37
+ get value(): string | undefined;
38
+ set value(value: string);
39
+ }
40
+
41
+ /**
42
+ * A node's subtree as a nested plain string object. A node that has children
43
+ * is a nested record (its own scalar value, if any, is dropped -- see
44
+ * {@link IConfiguration.toObject}); a pure leaf is its string value.
45
+ */
46
+ type ConfigObject = {
47
+ readonly [key: string]: string | ConfigObject;
48
+ };
49
+ /**
50
+ * The index-navigable Section type: an {@link IConfigurationSection} whose
51
+ * unknown string keys resolve to further sections, so `config.Server.Port`
52
+ * dot/bracket navigation type-checks.
53
+ *
54
+ * INLINE self-referential intersection by design -- routing the recursive
55
+ * self-reference through a generic alias trips TS2456 ("Type alias circularly
56
+ * references itself"). Real members (`value`, `get`, `getSection`, ...) win
57
+ * over the index signature; only genuinely-unknown keys resolve to
58
+ * `IndexedSection`. Under `noUncheckedIndexedAccess` the index-access site
59
+ * (`config.Server`) types as `IndexedSection | undefined` -- a conservative
60
+ * false-positive for navigation (runtime always returns a Section for a string
61
+ * key), by design. The typed path without that tax is a runtime schema
62
+ * (`ConfigurationBuilder.withSchema`), whose result has named keys and no
63
+ * index signature.
64
+ */
65
+ type IndexedSection = IConfigurationSection & {
66
+ readonly [key: string]: IndexedSection;
67
+ };
68
+ /**
69
+ * The result of a try-get lookup: `[false]` on a miss, `[true, value]` on a
70
+ * hit. Replaces ME's `bool TryGet(out string?)` out-param pattern, which has
71
+ * no direct TS equivalent.
72
+ */
73
+ type ITryGetResult<T> = [success: false] | [success: true, value: T];
74
+
75
+ /**
76
+ * A set of key/value application configuration properties. Every value is a
77
+ * raw string unless explicitly coerced; navigation always yields a Section and
78
+ * leaf reads always yield the requested scalar type (no accessor returns a
79
+ * string for one input and a section for another).
80
+ */
81
+ interface IConfiguration {
82
+ /** This node's own value (undefined on the root, or when absent). */
83
+ readonly value: string | undefined;
84
+ /** The raw string at a flat colon-delimited path (undefined if absent). */
85
+ get(path: string): string | undefined;
86
+ /** A typed leaf via a caller-supplied factory (undefined if the path is absent). */
87
+ get<T>(path: string, factory: (value: string) => T): T | undefined;
88
+ /**
89
+ * Coerces a leaf to a finite number. Returns `dflt` (or undefined) when the
90
+ * path is absent; THROWS when the path is present but not a finite number.
91
+ */
92
+ getNum(path: string): number | undefined;
93
+ getNum(path: string, dflt: number): number;
94
+ /**
95
+ * Coerces a leaf to a boolean, LIBERAL and case-insensitive (true/1/yes/on
96
+ * -> true, false/0/no/off -> false). Returns `dflt` (or undefined) when
97
+ * absent; THROWS when present but unrecognized.
98
+ */
99
+ getBool(path: string): boolean | undefined;
100
+ getBool(path: string, dflt: boolean): boolean;
101
+ /** Writes a descendant key (index-based writes are not supported). */
102
+ set(key: string, value: string): this;
103
+ /**
104
+ * A sub-section with the specified key. Never returns `null`: a missing key
105
+ * yields an empty {@link IConfigurationSection}.
106
+ */
107
+ getSection(key: string): IConfigurationSection;
108
+ /** The immediate descendant configuration sub-sections. */
109
+ getChildren(): Iterable<IConfigurationSection>;
110
+ /** This node's subtree as a nested plain string object. */
111
+ toObject(): ConfigObject;
112
+ /**
113
+ * A token that fires when this configuration is reloaded -- the root
114
+ * composes its providers' tokens into its own; a section delegates to its
115
+ * root.
116
+ */
117
+ getReloadToken(): IChangeToken;
118
+ }
119
+
120
+ /** Provides configuration key/values for an application. */
121
+ interface IConfigurationProvider {
122
+ /** Tries to get a configuration value for the specified key. */
123
+ tryGet(key: string): ITryGetResult<string>;
124
+ /** Sets a configuration value for the specified key. */
125
+ set(key: string, value?: string): void;
126
+ /**
127
+ * Attempts to get an {@link IChangeToken} for change tracking. Returns a
128
+ * token if this provider supports change tracking.
129
+ */
130
+ getReloadToken(): IChangeToken;
131
+ /** Loads configuration values from the source represented by this provider. */
132
+ load(): void;
133
+ /**
134
+ * Returns the immediate descendant configuration keys for a given parent
135
+ * path based on the data of this provider and the set of keys returned by
136
+ * all the preceding providers.
137
+ *
138
+ * @param earlierKeys The child keys returned by the preceding providers for the same parent path.
139
+ * @param parentPath The parent path.
140
+ */
141
+ getChildKeys(earlierKeys: Iterable<string>, parentPath?: string): Iterable<string>;
142
+ }
143
+
144
+ /** Represents the root of an {@link IConfiguration} hierarchy. */
145
+ interface IConfigurationRoot extends IConfiguration {
146
+ /**
147
+ * Forces the configuration values to be reloaded from the underlying
148
+ * {@link IConfigurationProvider} providers.
149
+ */
150
+ reload(): void;
151
+ /** The {@link IConfigurationProvider} providers for this configuration. */
152
+ get providers(): Iterable<IConfigurationProvider>;
153
+ }
154
+
155
+ /** Represents a source of configuration key/values for an application. */
156
+ interface IConfigurationSource {
157
+ /** Builds the {@link IConfigurationProvider} for this source. */
158
+ build(builder: IConfigurationBuilder): IConfigurationProvider;
159
+ }
160
+
161
+ /** Represents a type used to build application configuration. */
162
+ interface IConfigurationBuilder {
163
+ /** The sources used to obtain configuration values. */
164
+ get sources(): readonly IConfigurationSource[];
165
+ /** Adds a new configuration source. Returns the same {@link IConfigurationBuilder}. */
166
+ add(source: IConfigurationSource): IConfigurationBuilder;
167
+ /**
168
+ * Builds an {@link IConfiguration} with keys and values from the set of
169
+ * sources registered in {@link IConfigurationBuilder.sources}.
170
+ */
171
+ build(): IConfigurationRoot;
172
+ }
173
+
174
+ /**
175
+ * Represents a mutable configuration object. It is both an
176
+ * {@link IConfigurationBuilder} and an {@link IConfiguration} -- as sources
177
+ * are added, it updates its current view of configuration.
178
+ */
179
+ interface IConfigurationManager extends IConfiguration, IConfigurationBuilder {
180
+ }
181
+
182
+ export type { ConfigObject, IConfiguration, IConfigurationBuilder, IConfigurationManager, IConfigurationProvider, IConfigurationRoot, IConfigurationSection, IConfigurationSource, ITryGetResult, IndexedSection };
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@rhombus-std/config.core",
3
+ "version": "0.0.0-alpha.0",
4
+ "description": "Types-only configuration abstractions: the IConfiguration* interfaces and ITryGetResult. Zero runtime; depends on @rhombus-std/primitives for the IChangeToken type only.",
5
+ "keywords": [
6
+ "configuration",
7
+ "config",
8
+ "abstractions",
9
+ "types",
10
+ "typescript"
11
+ ],
12
+ "license": "MIT",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/fnioc/std.git",
16
+ "directory": "libraries/config.core"
17
+ },
18
+ "type": "module",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "default": "./dist/index.d.ts"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "dependencies": {
30
+ "@rhombus-std/primitives": "0.0.0-alpha.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public",
34
+ "provenance": true
35
+ },
36
+ "scripts": {
37
+ "build": "bun build.ts",
38
+ "lint": "bun x tsc --noEmit -p tsconfig.json"
39
+ }
40
+ }