@o3co/ts.hocon 1.3.0 → 1.4.1
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/README.md +55 -6
- package/dist/config-BwjvKeZ5.d.cts +271 -0
- package/dist/config-BwjvKeZ5.d.ts +271 -0
- package/dist/index.cjs +1109 -360
- package/dist/index.d.cts +45 -2
- package/dist/index.d.ts +45 -2
- package/dist/index.js +1098 -359
- package/dist/zod.cjs +829 -200
- package/dist/zod.d.cts +1 -1
- package/dist/zod.d.ts +1 -1
- package/dist/zod.js +828 -200
- package/package.json +3 -1
- package/dist/parse-nNbyqnOh.d.cts +0 -53
- package/dist/parse-nNbyqnOh.d.ts +0 -53
package/README.md
CHANGED
|
@@ -105,18 +105,60 @@ parseFileAsync(path: string, opts?: ParseOptions): Promise<Config>
|
|
|
105
105
|
| Method | Returns | Throws if |
|
|
106
106
|
|--------|---------|-----------|
|
|
107
107
|
| `get(path)` | `unknown \| undefined` | — |
|
|
108
|
-
| `getString(path)` | `string` | missing, wrong type |
|
|
109
|
-
| `getNumber(path)` | `number` | missing, wrong type |
|
|
110
|
-
| `getBoolean(path)` | `boolean` | missing, wrong type |
|
|
111
|
-
| `getConfig(path)` | `Config` | missing, not an object |
|
|
112
|
-
| `getList(path)` | `unknown[]` | missing, not an array |
|
|
108
|
+
| `getString(path)` | `string` | missing, wrong type, or unresolved |
|
|
109
|
+
| `getNumber(path)` | `number` | missing, wrong type, or unresolved |
|
|
110
|
+
| `getBoolean(path)` | `boolean` | missing, wrong type, or unresolved |
|
|
111
|
+
| `getConfig(path)` | `Config` | missing, not an object, or unresolved |
|
|
112
|
+
| `getList(path)` | `unknown[]` | missing, not an array, or unresolved |
|
|
113
113
|
| `getDuration(path, unit?)` | `number` | missing, not a string, or invalid duration format |
|
|
114
114
|
| `getBytes(path, unit?)` | `number` | missing, not a string, or invalid byte size format |
|
|
115
115
|
| `has(path)` | `boolean` | — |
|
|
116
116
|
| `keys()` | `string[]` | — |
|
|
117
117
|
| `withFallback(fallback)` | `Config` | — |
|
|
118
|
+
| `resolve(opts?)` | `Config` | unresolvable substitution (unless `allowUnresolved: true`) |
|
|
119
|
+
| `resolveWith(source, opts?)` | `Config` | source unresolved, or unresolvable substitution |
|
|
120
|
+
| `isResolved()` | `boolean` | — |
|
|
118
121
|
| `toObject()` | `unknown` | — |
|
|
119
122
|
|
|
123
|
+
### Deferred resolution API (E12)
|
|
124
|
+
|
|
125
|
+
Separate the parse, fallback-layering, and resolve steps for runtime config injection.
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import { parseStringWithOptions, fromMap, empty } from '@o3co/ts.hocon'
|
|
129
|
+
import type { ResolveOptions } from '@o3co/ts.hocon'
|
|
130
|
+
|
|
131
|
+
// 1. Parse without resolving — substitutions deferred
|
|
132
|
+
const cfg = parseStringWithOptions(
|
|
133
|
+
'version = ${shortversion}-${CI_RUN_NUMBER}\nvariables { shortversion = "1.2.3" }',
|
|
134
|
+
{ resolveSubstitutions: false }
|
|
135
|
+
)
|
|
136
|
+
cfg.isResolved() // false — ${CI_RUN_NUMBER} still pending
|
|
137
|
+
|
|
138
|
+
// 2. Layer runtime fallbacks
|
|
139
|
+
const runtime = fromMap({ CI_RUN_NUMBER: '42' })
|
|
140
|
+
const vars = cfg.getConfig('variables') // already available (not a substitution)
|
|
141
|
+
const merged = cfg.withFallback(runtime).withFallback(vars)
|
|
142
|
+
|
|
143
|
+
// 3. Resolve the full fallback stack
|
|
144
|
+
const resolved = merged.resolve({ useSystemEnvironment: false })
|
|
145
|
+
resolved.getString('version') // "1.2.3-42"
|
|
146
|
+
|
|
147
|
+
// resolveWith: resolve receiver using source for lookup, source keys NOT in result
|
|
148
|
+
const receiver = parseStringWithOptions('r = ${key}', { resolveSubstitutions: false })
|
|
149
|
+
const source = fromMap({ key: 'val' })
|
|
150
|
+
const result = receiver.resolveWith(source)
|
|
151
|
+
result.has('key') // false — source keys excluded
|
|
152
|
+
result.getString('r') // "val"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`ResolveOptions`:
|
|
156
|
+
|
|
157
|
+
| Option | Type | Default | Description |
|
|
158
|
+
|--------|------|---------|-------------|
|
|
159
|
+
| `useSystemEnvironment` | `boolean` | `true` | Consult `process.env` for substitution fallback |
|
|
160
|
+
| `allowUnresolved` | `boolean` | `false` | Leave unresolvable substitutions in place (no error) |
|
|
161
|
+
|
|
120
162
|
### Zod integration
|
|
121
163
|
|
|
122
164
|
```ts
|
|
@@ -216,7 +258,14 @@ Conformance against the [Lightbend HOCON specification](https://github.com/light
|
|
|
216
258
|
| In-scope only | **83.3%** |
|
|
217
259
|
| Lightbend `test01`–`test13` suite | 13/13 passing |
|
|
218
260
|
|
|
219
|
-
|
|
261
|
+
**Extra-spec conventions (E-series) — implementation status:**
|
|
262
|
+
|
|
263
|
+
| Item | Description | Status |
|
|
264
|
+
|------|-------------|--------|
|
|
265
|
+
| E11 | `include package(...)` service-locator includes | ✅ v1.3.0 |
|
|
266
|
+
| E12 | Deferred substitution resolution (`parse → withFallback → resolve()` lifecycle) | ✅ v1.4.0 |
|
|
267
|
+
|
|
268
|
+
Not supported:
|
|
220
269
|
|
|
221
270
|
- `include url(...)`
|
|
222
271
|
- `include classpath(...)`
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
type DurationUnit = 'ns' | 'us' | 'ms' | 's' | 'm' | 'h' | 'd';
|
|
2
|
+
type ByteUnit = 'B' | 'KB' | 'KiB' | 'MB' | 'MiB' | 'GB' | 'GiB' | 'TB' | 'TiB';
|
|
3
|
+
|
|
4
|
+
type ScalarValueType = 'string' | 'number' | 'boolean' | 'null';
|
|
5
|
+
type HoconValue = {
|
|
6
|
+
kind: 'object';
|
|
7
|
+
fields: Map<string, HoconValue>;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'array';
|
|
10
|
+
items: HoconValue[];
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'scalar';
|
|
13
|
+
raw: string;
|
|
14
|
+
valueType: ScalarValueType;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
interface Segment {
|
|
18
|
+
readonly text: string;
|
|
19
|
+
readonly line: number;
|
|
20
|
+
readonly col: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type SubstPlaceholder = {
|
|
24
|
+
_kind: 'subst-placeholder';
|
|
25
|
+
segments: Segment[];
|
|
26
|
+
optional: boolean;
|
|
27
|
+
listSuffix: boolean;
|
|
28
|
+
line: number;
|
|
29
|
+
col: number;
|
|
30
|
+
prefixLen: number;
|
|
31
|
+
};
|
|
32
|
+
type ConcatPlaceholder = {
|
|
33
|
+
_kind: 'concat-placeholder';
|
|
34
|
+
nodes: ResolverValue[];
|
|
35
|
+
/** 1-based line of the concat value in the source file (from AST Concat pos). */
|
|
36
|
+
line: number;
|
|
37
|
+
/** 1-based column of the concat value in the source file (from AST Concat pos). */
|
|
38
|
+
col: number;
|
|
39
|
+
};
|
|
40
|
+
type AppendPlaceholder = {
|
|
41
|
+
_kind: 'append-placeholder';
|
|
42
|
+
existing: ResolverValue;
|
|
43
|
+
elem: ResolverValue;
|
|
44
|
+
};
|
|
45
|
+
type ResObj = {
|
|
46
|
+
_kind: 'res-obj';
|
|
47
|
+
fields: Map<string, ResolverValue>;
|
|
48
|
+
priorValues: Map<string, ResolverValue>;
|
|
49
|
+
};
|
|
50
|
+
type ResolverValue = HoconValue | SubstPlaceholder | ConcatPlaceholder | AppendPlaceholder | ResObj;
|
|
51
|
+
/**
|
|
52
|
+
* Custom resolver for `include package("id", "file")`.
|
|
53
|
+
*
|
|
54
|
+
* Receives:
|
|
55
|
+
* - `identifier`, `file`: the qualifier arguments (post HOCON unescape, byte-exact)
|
|
56
|
+
* - `includingFile`: absolute path of the including `.conf` file when known
|
|
57
|
+
* (currently always `undefined`; reserved for future threading from a future
|
|
58
|
+
* `parseFile` integration)
|
|
59
|
+
* - `baseDir`: the directory context active when the include is resolved
|
|
60
|
+
* (typically `path.dirname(includingFile)` of the parent, or the caller-set
|
|
61
|
+
* `baseDir` parse option). Set when known, `undefined` for parses of literal
|
|
62
|
+
* input strings without a directory context.
|
|
63
|
+
*
|
|
64
|
+
* Must return an absolute path or throw.
|
|
65
|
+
*
|
|
66
|
+
* When not provided, the default resolver uses `createRequire(import.meta.url)`
|
|
67
|
+
* which works in both CJS and ESM Node contexts. The default resolver picks the
|
|
68
|
+
* lookup starting paths in priority order:
|
|
69
|
+
* `resolveFrom` > `baseDir` > `path.dirname(includingFile)` > `process.cwd()`
|
|
70
|
+
*/
|
|
71
|
+
type PackageResolver = (identifier: string, file: string, includingFile: string | undefined, baseDir: string | undefined) => string;
|
|
72
|
+
type ResolveOptions$1 = {
|
|
73
|
+
env: Record<string, string>;
|
|
74
|
+
baseDir: string | undefined;
|
|
75
|
+
readFileSync: (filePath: string) => string;
|
|
76
|
+
readFile?: (filePath: string) => Promise<string>;
|
|
77
|
+
includeStack?: string[];
|
|
78
|
+
/** Override the starting directory for `require.resolve` used by the default package resolver. */
|
|
79
|
+
resolveFrom?: string | string[];
|
|
80
|
+
/** Custom resolver for `include package(...)`. When provided, takes full control; `resolveFrom` is ignored. */
|
|
81
|
+
packageResolver?: PackageResolver;
|
|
82
|
+
/**
|
|
83
|
+
* When false (default), env var lookups inside SubstitutionResolver are
|
|
84
|
+
* suppressed. Set to true to preserve the current fused-resolve behaviour
|
|
85
|
+
* where process.env is consulted as fallback. Phase-2 callers (resolveTree)
|
|
86
|
+
* receive this flag explicitly; the fused resolve() path passes true for
|
|
87
|
+
* backward compat.
|
|
88
|
+
*
|
|
89
|
+
* E12 ResolveOptions.useSystemEnvironment.
|
|
90
|
+
*/
|
|
91
|
+
useSystemEnvironment?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* When true, leaves unresolved (non-optional) substitution placeholders in
|
|
94
|
+
* place instead of throwing ResolveError. Phase 2 only; ignored by buildTree.
|
|
95
|
+
*
|
|
96
|
+
* E12 ResolveOptions.allowUnresolved.
|
|
97
|
+
*/
|
|
98
|
+
allowUnresolved?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Human-readable origin for error messages (e.g. file name or description).
|
|
101
|
+
* When set, ResolveError messages include this as a prefix to help callers
|
|
102
|
+
* identify which config source caused the error.
|
|
103
|
+
*
|
|
104
|
+
* E12 origin preservation.
|
|
105
|
+
*/
|
|
106
|
+
originDescription?: string;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
type ParseOptions = {
|
|
110
|
+
baseDir?: string;
|
|
111
|
+
env?: Record<string, string>;
|
|
112
|
+
readFile?: (filePath: string) => Promise<string>;
|
|
113
|
+
readFileSync?: (filePath: string) => string;
|
|
114
|
+
/** When true (default), run substitution resolution after parse. When false,
|
|
115
|
+
* return an unresolved Config with placeholders intact. E12 §"ParseOptions". */
|
|
116
|
+
resolveSubstitutions?: boolean;
|
|
117
|
+
/** Source name surfaced in error messages when no file path is available. E12. */
|
|
118
|
+
originDescription?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Override the starting directory (or directories) used when resolving
|
|
121
|
+
* `include package("id", "file")` via Node module resolution.
|
|
122
|
+
*
|
|
123
|
+
* Default: `path.dirname(includingConfFile)` when known, `process.cwd()` otherwise.
|
|
124
|
+
* Ignored when `packageResolver` is also provided.
|
|
125
|
+
*/
|
|
126
|
+
resolveFrom?: string | string[];
|
|
127
|
+
/**
|
|
128
|
+
* Custom resolver for `include package("id", "file")`.
|
|
129
|
+
* See {@link PackageResolver} for the full callback signature and contract
|
|
130
|
+
* (parameters, lookup-starting-path priority, error semantics).
|
|
131
|
+
*
|
|
132
|
+
* When provided, takes full control of resolution; `resolveFrom` is ignored.
|
|
133
|
+
* Use this for Yarn Berry PnP, bundler contexts, edge runtimes, or test isolation.
|
|
134
|
+
*
|
|
135
|
+
* Note: on macOS/Windows (case-insensitive filesystems), the default resolver may
|
|
136
|
+
* resolve case-insensitively for intermediate path segments. Use a custom
|
|
137
|
+
* `packageResolver` for strict cross-platform enforcement.
|
|
138
|
+
*/
|
|
139
|
+
packageResolver?: PackageResolver;
|
|
140
|
+
};
|
|
141
|
+
type ResolveOptions = {
|
|
142
|
+
/** When true (default), env var lookups are available during resolve. E12. */
|
|
143
|
+
useSystemEnvironment?: boolean;
|
|
144
|
+
/** When true, leaves unresolved non-optional substitutions in place instead
|
|
145
|
+
* of throwing ResolveError. Default false. E12. */
|
|
146
|
+
allowUnresolved?: boolean;
|
|
147
|
+
};
|
|
148
|
+
/** Returns a ParseOptions object with Lightbend-aligned defaults:
|
|
149
|
+
* resolveSubstitutions=true, originDescription=undefined. */
|
|
150
|
+
declare function defaultParseOptions(): Required<Pick<ParseOptions, 'resolveSubstitutions'>> & ParseOptions;
|
|
151
|
+
/** Returns a ResolveOptions object with Lightbend-aligned defaults:
|
|
152
|
+
* useSystemEnvironment=true, allowUnresolved=false. */
|
|
153
|
+
declare function defaultResolveOptions(): Required<ResolveOptions>;
|
|
154
|
+
declare function parse(input: string, opts?: ParseOptions): Config;
|
|
155
|
+
/** Lightbend-aligned alias for parse(). Produces a fully resolved Config. */
|
|
156
|
+
declare const parseString: typeof parse;
|
|
157
|
+
/** Parse a HOCON string with explicit options. When opts.resolveSubstitutions
|
|
158
|
+
* is false, returns an unresolved Config with substitution placeholders intact.
|
|
159
|
+
* Use Config.resolve() or Config.resolveWith() to complete resolution later. */
|
|
160
|
+
declare function parseStringWithOptions(input: string, opts?: ParseOptions): Config;
|
|
161
|
+
/** Parse a HOCON file with explicit options. */
|
|
162
|
+
declare function parseFileWithOptions(filePath: string, opts?: ParseOptions): Config;
|
|
163
|
+
/**
|
|
164
|
+
* Truly async version of `parse()`. Include directives are resolved
|
|
165
|
+
* asynchronously via `readFile` when provided.
|
|
166
|
+
*/
|
|
167
|
+
declare function parseAsync(input: string, opts?: ParseOptions): Promise<Config>;
|
|
168
|
+
declare function parseFile(filePath: string, opts?: ParseOptions): Config;
|
|
169
|
+
declare function parseFileAsync(filePath: string, opts?: ParseOptions): Promise<Config>;
|
|
170
|
+
|
|
171
|
+
declare class Config {
|
|
172
|
+
private readonly root;
|
|
173
|
+
/** @internal resolved flag: true when no substitution placeholders remain. */
|
|
174
|
+
private readonly _resolved;
|
|
175
|
+
/** @internal base directory for re-runs (file-parsed configs). */
|
|
176
|
+
readonly _parseBaseDir: string | undefined;
|
|
177
|
+
/** @internal origin description for error messages. */
|
|
178
|
+
readonly _originDescription: string | undefined;
|
|
179
|
+
/** @internal ResObj tree for deferred-resolution path. Set when resolved=false. */
|
|
180
|
+
readonly _resObjRoot: ResObj | undefined;
|
|
181
|
+
/** @internal ResolveOptions stored for the resolve() call. */
|
|
182
|
+
private readonly _resolveOpts;
|
|
183
|
+
constructor(root: HoconValue & {
|
|
184
|
+
kind: 'object';
|
|
185
|
+
}, opts?: {
|
|
186
|
+
resolved?: boolean;
|
|
187
|
+
parseBaseDir?: string;
|
|
188
|
+
originDescription?: string;
|
|
189
|
+
resObjRoot?: ResObj;
|
|
190
|
+
resolveOpts?: ResolveOptions$1;
|
|
191
|
+
});
|
|
192
|
+
/** Returns true when the Config's value tree contains no unresolved
|
|
193
|
+
* substitution placeholders. Whole-config granularity (E12 decision 11). */
|
|
194
|
+
isResolved(): boolean;
|
|
195
|
+
/** @internal Test-only: construct a resolved Config from a HoconValue. */
|
|
196
|
+
static _fromResolvedValue(root: HoconValue & {
|
|
197
|
+
kind: 'object';
|
|
198
|
+
}, opts?: {
|
|
199
|
+
originDescription?: string;
|
|
200
|
+
}): Config;
|
|
201
|
+
/** @internal Construct an unresolved Config carrying a ResObj tree.
|
|
202
|
+
* Used by parseStringWithOptions (deferred path) in T6. */
|
|
203
|
+
static _fromUnresolvedResObj(tree: ResObj, opts: {
|
|
204
|
+
parseBaseDir?: string;
|
|
205
|
+
originDescription?: string;
|
|
206
|
+
resolved: boolean;
|
|
207
|
+
resolveOpts: ResolveOptions$1;
|
|
208
|
+
}): Config;
|
|
209
|
+
get(path: string): unknown;
|
|
210
|
+
getString(path: string): string;
|
|
211
|
+
getNumber(path: string): number;
|
|
212
|
+
getBoolean(path: string): boolean;
|
|
213
|
+
getDuration(path: string, unit?: DurationUnit): number;
|
|
214
|
+
getBytes(path: string, unit?: ByteUnit): number;
|
|
215
|
+
getConfig(path: string): Config;
|
|
216
|
+
getList(path: string): unknown[];
|
|
217
|
+
has(path: string): boolean;
|
|
218
|
+
keys(): string[];
|
|
219
|
+
withFallback(fallback: Config | undefined): Config;
|
|
220
|
+
/**
|
|
221
|
+
* Runs substitution resolution (phase 2) on the stored unresolved tree.
|
|
222
|
+
* Idempotent: calling resolve() on an already-resolved Config returns an
|
|
223
|
+
* equivalent resolved Config.
|
|
224
|
+
*
|
|
225
|
+
* opts.allowUnresolved (default false) — when true, leaves unresolved
|
|
226
|
+
* non-optional placeholders in place rather than throwing.
|
|
227
|
+
* opts.useSystemEnvironment (default true) — when false, env var lookups
|
|
228
|
+
* are suppressed (hermetic resolution).
|
|
229
|
+
*
|
|
230
|
+
* E12 decision 3.
|
|
231
|
+
*/
|
|
232
|
+
resolve(opts?: ResolveOptions): Config;
|
|
233
|
+
/**
|
|
234
|
+
* Resolves receiver substitutions using source as lookup context.
|
|
235
|
+
* Source's keys are NOT merged into the result — differs from
|
|
236
|
+
* `this.withFallback(source).resolve()` which includes source keys.
|
|
237
|
+
*
|
|
238
|
+
* Precondition (E12 decision 10): source must be resolved. If
|
|
239
|
+
* source.isResolved() is false, throws NotResolvedError.
|
|
240
|
+
*
|
|
241
|
+
* On an already-resolved receiver, resolveWith is a no-op (returns an
|
|
242
|
+
* equivalent resolved Config, source keys not included).
|
|
243
|
+
*
|
|
244
|
+
* E12 decisions 9, 10.
|
|
245
|
+
*/
|
|
246
|
+
resolveWith(source: Config, opts?: ResolveOptions): Config;
|
|
247
|
+
toObject(): unknown;
|
|
248
|
+
/**
|
|
249
|
+
* @internal Test-only: renders this resolved Config's value tree as canonical
|
|
250
|
+
* JSON (sorted keys, no whitespace). Used by Layer-2 fixture tests to compare
|
|
251
|
+
* against Lightbend ground truth. NOT part of the public API.
|
|
252
|
+
*
|
|
253
|
+
* Throws if the Config is unresolved (contains placeholders).
|
|
254
|
+
*/
|
|
255
|
+
_renderJSONForTest(): string;
|
|
256
|
+
private lookupNode;
|
|
257
|
+
/**
|
|
258
|
+
* _resObjRootSubtreeHasPlaceholders — walk _resObjRoot to the given path and
|
|
259
|
+
* return true if the subtree there contains any unresolved placeholder.
|
|
260
|
+
* Used by getConfig / getList (T2) to detect transitive unresolved placeholders
|
|
261
|
+
* in object / array subtrees that would otherwise appear to be "resolved" in the
|
|
262
|
+
* partial HoconValue root (because individual leaf fields are omitted rather than
|
|
263
|
+
* the whole subtree when their value is a direct placeholder scalar, but object
|
|
264
|
+
* sub-containers are retained in the partial root with the placeholder-keyed
|
|
265
|
+
* fields omitted from them — so the object appears "present but empty-ish").
|
|
266
|
+
*/
|
|
267
|
+
private _resObjRootSubtreeHasPlaceholders;
|
|
268
|
+
private requireScalar;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export { type ByteUnit as B, Config as C, type DurationUnit as D, type HoconValue as H, type PackageResolver as P, type ResolveOptions as R, type ScalarValueType as S, type ParseOptions as a, defaultResolveOptions as b, parseAsync as c, defaultParseOptions as d, parseFile as e, parseFileAsync as f, parseFileWithOptions as g, parseString as h, parseStringWithOptions as i, parse as p };
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
type DurationUnit = 'ns' | 'us' | 'ms' | 's' | 'm' | 'h' | 'd';
|
|
2
|
+
type ByteUnit = 'B' | 'KB' | 'KiB' | 'MB' | 'MiB' | 'GB' | 'GiB' | 'TB' | 'TiB';
|
|
3
|
+
|
|
4
|
+
type ScalarValueType = 'string' | 'number' | 'boolean' | 'null';
|
|
5
|
+
type HoconValue = {
|
|
6
|
+
kind: 'object';
|
|
7
|
+
fields: Map<string, HoconValue>;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'array';
|
|
10
|
+
items: HoconValue[];
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'scalar';
|
|
13
|
+
raw: string;
|
|
14
|
+
valueType: ScalarValueType;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
interface Segment {
|
|
18
|
+
readonly text: string;
|
|
19
|
+
readonly line: number;
|
|
20
|
+
readonly col: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type SubstPlaceholder = {
|
|
24
|
+
_kind: 'subst-placeholder';
|
|
25
|
+
segments: Segment[];
|
|
26
|
+
optional: boolean;
|
|
27
|
+
listSuffix: boolean;
|
|
28
|
+
line: number;
|
|
29
|
+
col: number;
|
|
30
|
+
prefixLen: number;
|
|
31
|
+
};
|
|
32
|
+
type ConcatPlaceholder = {
|
|
33
|
+
_kind: 'concat-placeholder';
|
|
34
|
+
nodes: ResolverValue[];
|
|
35
|
+
/** 1-based line of the concat value in the source file (from AST Concat pos). */
|
|
36
|
+
line: number;
|
|
37
|
+
/** 1-based column of the concat value in the source file (from AST Concat pos). */
|
|
38
|
+
col: number;
|
|
39
|
+
};
|
|
40
|
+
type AppendPlaceholder = {
|
|
41
|
+
_kind: 'append-placeholder';
|
|
42
|
+
existing: ResolverValue;
|
|
43
|
+
elem: ResolverValue;
|
|
44
|
+
};
|
|
45
|
+
type ResObj = {
|
|
46
|
+
_kind: 'res-obj';
|
|
47
|
+
fields: Map<string, ResolverValue>;
|
|
48
|
+
priorValues: Map<string, ResolverValue>;
|
|
49
|
+
};
|
|
50
|
+
type ResolverValue = HoconValue | SubstPlaceholder | ConcatPlaceholder | AppendPlaceholder | ResObj;
|
|
51
|
+
/**
|
|
52
|
+
* Custom resolver for `include package("id", "file")`.
|
|
53
|
+
*
|
|
54
|
+
* Receives:
|
|
55
|
+
* - `identifier`, `file`: the qualifier arguments (post HOCON unescape, byte-exact)
|
|
56
|
+
* - `includingFile`: absolute path of the including `.conf` file when known
|
|
57
|
+
* (currently always `undefined`; reserved for future threading from a future
|
|
58
|
+
* `parseFile` integration)
|
|
59
|
+
* - `baseDir`: the directory context active when the include is resolved
|
|
60
|
+
* (typically `path.dirname(includingFile)` of the parent, or the caller-set
|
|
61
|
+
* `baseDir` parse option). Set when known, `undefined` for parses of literal
|
|
62
|
+
* input strings without a directory context.
|
|
63
|
+
*
|
|
64
|
+
* Must return an absolute path or throw.
|
|
65
|
+
*
|
|
66
|
+
* When not provided, the default resolver uses `createRequire(import.meta.url)`
|
|
67
|
+
* which works in both CJS and ESM Node contexts. The default resolver picks the
|
|
68
|
+
* lookup starting paths in priority order:
|
|
69
|
+
* `resolveFrom` > `baseDir` > `path.dirname(includingFile)` > `process.cwd()`
|
|
70
|
+
*/
|
|
71
|
+
type PackageResolver = (identifier: string, file: string, includingFile: string | undefined, baseDir: string | undefined) => string;
|
|
72
|
+
type ResolveOptions$1 = {
|
|
73
|
+
env: Record<string, string>;
|
|
74
|
+
baseDir: string | undefined;
|
|
75
|
+
readFileSync: (filePath: string) => string;
|
|
76
|
+
readFile?: (filePath: string) => Promise<string>;
|
|
77
|
+
includeStack?: string[];
|
|
78
|
+
/** Override the starting directory for `require.resolve` used by the default package resolver. */
|
|
79
|
+
resolveFrom?: string | string[];
|
|
80
|
+
/** Custom resolver for `include package(...)`. When provided, takes full control; `resolveFrom` is ignored. */
|
|
81
|
+
packageResolver?: PackageResolver;
|
|
82
|
+
/**
|
|
83
|
+
* When false (default), env var lookups inside SubstitutionResolver are
|
|
84
|
+
* suppressed. Set to true to preserve the current fused-resolve behaviour
|
|
85
|
+
* where process.env is consulted as fallback. Phase-2 callers (resolveTree)
|
|
86
|
+
* receive this flag explicitly; the fused resolve() path passes true for
|
|
87
|
+
* backward compat.
|
|
88
|
+
*
|
|
89
|
+
* E12 ResolveOptions.useSystemEnvironment.
|
|
90
|
+
*/
|
|
91
|
+
useSystemEnvironment?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* When true, leaves unresolved (non-optional) substitution placeholders in
|
|
94
|
+
* place instead of throwing ResolveError. Phase 2 only; ignored by buildTree.
|
|
95
|
+
*
|
|
96
|
+
* E12 ResolveOptions.allowUnresolved.
|
|
97
|
+
*/
|
|
98
|
+
allowUnresolved?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Human-readable origin for error messages (e.g. file name or description).
|
|
101
|
+
* When set, ResolveError messages include this as a prefix to help callers
|
|
102
|
+
* identify which config source caused the error.
|
|
103
|
+
*
|
|
104
|
+
* E12 origin preservation.
|
|
105
|
+
*/
|
|
106
|
+
originDescription?: string;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
type ParseOptions = {
|
|
110
|
+
baseDir?: string;
|
|
111
|
+
env?: Record<string, string>;
|
|
112
|
+
readFile?: (filePath: string) => Promise<string>;
|
|
113
|
+
readFileSync?: (filePath: string) => string;
|
|
114
|
+
/** When true (default), run substitution resolution after parse. When false,
|
|
115
|
+
* return an unresolved Config with placeholders intact. E12 §"ParseOptions". */
|
|
116
|
+
resolveSubstitutions?: boolean;
|
|
117
|
+
/** Source name surfaced in error messages when no file path is available. E12. */
|
|
118
|
+
originDescription?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Override the starting directory (or directories) used when resolving
|
|
121
|
+
* `include package("id", "file")` via Node module resolution.
|
|
122
|
+
*
|
|
123
|
+
* Default: `path.dirname(includingConfFile)` when known, `process.cwd()` otherwise.
|
|
124
|
+
* Ignored when `packageResolver` is also provided.
|
|
125
|
+
*/
|
|
126
|
+
resolveFrom?: string | string[];
|
|
127
|
+
/**
|
|
128
|
+
* Custom resolver for `include package("id", "file")`.
|
|
129
|
+
* See {@link PackageResolver} for the full callback signature and contract
|
|
130
|
+
* (parameters, lookup-starting-path priority, error semantics).
|
|
131
|
+
*
|
|
132
|
+
* When provided, takes full control of resolution; `resolveFrom` is ignored.
|
|
133
|
+
* Use this for Yarn Berry PnP, bundler contexts, edge runtimes, or test isolation.
|
|
134
|
+
*
|
|
135
|
+
* Note: on macOS/Windows (case-insensitive filesystems), the default resolver may
|
|
136
|
+
* resolve case-insensitively for intermediate path segments. Use a custom
|
|
137
|
+
* `packageResolver` for strict cross-platform enforcement.
|
|
138
|
+
*/
|
|
139
|
+
packageResolver?: PackageResolver;
|
|
140
|
+
};
|
|
141
|
+
type ResolveOptions = {
|
|
142
|
+
/** When true (default), env var lookups are available during resolve. E12. */
|
|
143
|
+
useSystemEnvironment?: boolean;
|
|
144
|
+
/** When true, leaves unresolved non-optional substitutions in place instead
|
|
145
|
+
* of throwing ResolveError. Default false. E12. */
|
|
146
|
+
allowUnresolved?: boolean;
|
|
147
|
+
};
|
|
148
|
+
/** Returns a ParseOptions object with Lightbend-aligned defaults:
|
|
149
|
+
* resolveSubstitutions=true, originDescription=undefined. */
|
|
150
|
+
declare function defaultParseOptions(): Required<Pick<ParseOptions, 'resolveSubstitutions'>> & ParseOptions;
|
|
151
|
+
/** Returns a ResolveOptions object with Lightbend-aligned defaults:
|
|
152
|
+
* useSystemEnvironment=true, allowUnresolved=false. */
|
|
153
|
+
declare function defaultResolveOptions(): Required<ResolveOptions>;
|
|
154
|
+
declare function parse(input: string, opts?: ParseOptions): Config;
|
|
155
|
+
/** Lightbend-aligned alias for parse(). Produces a fully resolved Config. */
|
|
156
|
+
declare const parseString: typeof parse;
|
|
157
|
+
/** Parse a HOCON string with explicit options. When opts.resolveSubstitutions
|
|
158
|
+
* is false, returns an unresolved Config with substitution placeholders intact.
|
|
159
|
+
* Use Config.resolve() or Config.resolveWith() to complete resolution later. */
|
|
160
|
+
declare function parseStringWithOptions(input: string, opts?: ParseOptions): Config;
|
|
161
|
+
/** Parse a HOCON file with explicit options. */
|
|
162
|
+
declare function parseFileWithOptions(filePath: string, opts?: ParseOptions): Config;
|
|
163
|
+
/**
|
|
164
|
+
* Truly async version of `parse()`. Include directives are resolved
|
|
165
|
+
* asynchronously via `readFile` when provided.
|
|
166
|
+
*/
|
|
167
|
+
declare function parseAsync(input: string, opts?: ParseOptions): Promise<Config>;
|
|
168
|
+
declare function parseFile(filePath: string, opts?: ParseOptions): Config;
|
|
169
|
+
declare function parseFileAsync(filePath: string, opts?: ParseOptions): Promise<Config>;
|
|
170
|
+
|
|
171
|
+
declare class Config {
|
|
172
|
+
private readonly root;
|
|
173
|
+
/** @internal resolved flag: true when no substitution placeholders remain. */
|
|
174
|
+
private readonly _resolved;
|
|
175
|
+
/** @internal base directory for re-runs (file-parsed configs). */
|
|
176
|
+
readonly _parseBaseDir: string | undefined;
|
|
177
|
+
/** @internal origin description for error messages. */
|
|
178
|
+
readonly _originDescription: string | undefined;
|
|
179
|
+
/** @internal ResObj tree for deferred-resolution path. Set when resolved=false. */
|
|
180
|
+
readonly _resObjRoot: ResObj | undefined;
|
|
181
|
+
/** @internal ResolveOptions stored for the resolve() call. */
|
|
182
|
+
private readonly _resolveOpts;
|
|
183
|
+
constructor(root: HoconValue & {
|
|
184
|
+
kind: 'object';
|
|
185
|
+
}, opts?: {
|
|
186
|
+
resolved?: boolean;
|
|
187
|
+
parseBaseDir?: string;
|
|
188
|
+
originDescription?: string;
|
|
189
|
+
resObjRoot?: ResObj;
|
|
190
|
+
resolveOpts?: ResolveOptions$1;
|
|
191
|
+
});
|
|
192
|
+
/** Returns true when the Config's value tree contains no unresolved
|
|
193
|
+
* substitution placeholders. Whole-config granularity (E12 decision 11). */
|
|
194
|
+
isResolved(): boolean;
|
|
195
|
+
/** @internal Test-only: construct a resolved Config from a HoconValue. */
|
|
196
|
+
static _fromResolvedValue(root: HoconValue & {
|
|
197
|
+
kind: 'object';
|
|
198
|
+
}, opts?: {
|
|
199
|
+
originDescription?: string;
|
|
200
|
+
}): Config;
|
|
201
|
+
/** @internal Construct an unresolved Config carrying a ResObj tree.
|
|
202
|
+
* Used by parseStringWithOptions (deferred path) in T6. */
|
|
203
|
+
static _fromUnresolvedResObj(tree: ResObj, opts: {
|
|
204
|
+
parseBaseDir?: string;
|
|
205
|
+
originDescription?: string;
|
|
206
|
+
resolved: boolean;
|
|
207
|
+
resolveOpts: ResolveOptions$1;
|
|
208
|
+
}): Config;
|
|
209
|
+
get(path: string): unknown;
|
|
210
|
+
getString(path: string): string;
|
|
211
|
+
getNumber(path: string): number;
|
|
212
|
+
getBoolean(path: string): boolean;
|
|
213
|
+
getDuration(path: string, unit?: DurationUnit): number;
|
|
214
|
+
getBytes(path: string, unit?: ByteUnit): number;
|
|
215
|
+
getConfig(path: string): Config;
|
|
216
|
+
getList(path: string): unknown[];
|
|
217
|
+
has(path: string): boolean;
|
|
218
|
+
keys(): string[];
|
|
219
|
+
withFallback(fallback: Config | undefined): Config;
|
|
220
|
+
/**
|
|
221
|
+
* Runs substitution resolution (phase 2) on the stored unresolved tree.
|
|
222
|
+
* Idempotent: calling resolve() on an already-resolved Config returns an
|
|
223
|
+
* equivalent resolved Config.
|
|
224
|
+
*
|
|
225
|
+
* opts.allowUnresolved (default false) — when true, leaves unresolved
|
|
226
|
+
* non-optional placeholders in place rather than throwing.
|
|
227
|
+
* opts.useSystemEnvironment (default true) — when false, env var lookups
|
|
228
|
+
* are suppressed (hermetic resolution).
|
|
229
|
+
*
|
|
230
|
+
* E12 decision 3.
|
|
231
|
+
*/
|
|
232
|
+
resolve(opts?: ResolveOptions): Config;
|
|
233
|
+
/**
|
|
234
|
+
* Resolves receiver substitutions using source as lookup context.
|
|
235
|
+
* Source's keys are NOT merged into the result — differs from
|
|
236
|
+
* `this.withFallback(source).resolve()` which includes source keys.
|
|
237
|
+
*
|
|
238
|
+
* Precondition (E12 decision 10): source must be resolved. If
|
|
239
|
+
* source.isResolved() is false, throws NotResolvedError.
|
|
240
|
+
*
|
|
241
|
+
* On an already-resolved receiver, resolveWith is a no-op (returns an
|
|
242
|
+
* equivalent resolved Config, source keys not included).
|
|
243
|
+
*
|
|
244
|
+
* E12 decisions 9, 10.
|
|
245
|
+
*/
|
|
246
|
+
resolveWith(source: Config, opts?: ResolveOptions): Config;
|
|
247
|
+
toObject(): unknown;
|
|
248
|
+
/**
|
|
249
|
+
* @internal Test-only: renders this resolved Config's value tree as canonical
|
|
250
|
+
* JSON (sorted keys, no whitespace). Used by Layer-2 fixture tests to compare
|
|
251
|
+
* against Lightbend ground truth. NOT part of the public API.
|
|
252
|
+
*
|
|
253
|
+
* Throws if the Config is unresolved (contains placeholders).
|
|
254
|
+
*/
|
|
255
|
+
_renderJSONForTest(): string;
|
|
256
|
+
private lookupNode;
|
|
257
|
+
/**
|
|
258
|
+
* _resObjRootSubtreeHasPlaceholders — walk _resObjRoot to the given path and
|
|
259
|
+
* return true if the subtree there contains any unresolved placeholder.
|
|
260
|
+
* Used by getConfig / getList (T2) to detect transitive unresolved placeholders
|
|
261
|
+
* in object / array subtrees that would otherwise appear to be "resolved" in the
|
|
262
|
+
* partial HoconValue root (because individual leaf fields are omitted rather than
|
|
263
|
+
* the whole subtree when their value is a direct placeholder scalar, but object
|
|
264
|
+
* sub-containers are retained in the partial root with the placeholder-keyed
|
|
265
|
+
* fields omitted from them — so the object appears "present but empty-ish").
|
|
266
|
+
*/
|
|
267
|
+
private _resObjRootSubtreeHasPlaceholders;
|
|
268
|
+
private requireScalar;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export { type ByteUnit as B, Config as C, type DurationUnit as D, type HoconValue as H, type PackageResolver as P, type ResolveOptions as R, type ScalarValueType as S, type ParseOptions as a, defaultResolveOptions as b, parseAsync as c, defaultParseOptions as d, parseFile as e, parseFileAsync as f, parseFileWithOptions as g, parseString as h, parseStringWithOptions as i, parse as p };
|