@ontrails/config 1.0.0-beta.14 → 1.0.0-beta.16
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/CHANGELOG.md +41 -0
- package/README.md +20 -28
- package/package.json +10 -2
- package/src/app-config.ts +23 -12
- package/src/compose.ts +16 -22
- package/src/{config-provision.ts → config-resource.ts} +5 -5
- package/src/define-config.ts +18 -18
- package/src/{generate → derive}/env.ts +3 -3
- package/src/{generate → derive}/example.ts +1 -1
- package/src/{generate → derive}/helpers.ts +1 -1
- package/src/derive/index.ts +3 -0
- package/src/{generate → derive}/json-schema.ts +1 -1
- package/src/{describe.ts → derive-fields.ts} +1 -1
- package/src/{explain.ts → derive-provenance.ts} +6 -6
- package/src/extensions.ts +1 -1
- package/src/index.ts +12 -19
- package/src/registry.ts +2 -2
- package/src/resolve.ts +17 -15
- package/src/trails/config-check.ts +3 -3
- package/src/trails/config-describe.ts +5 -5
- package/src/trails/config-explain.ts +13 -13
- package/src/trails/config-init.ts +10 -10
- package/.turbo/turbo-build.log +0 -1
- package/.turbo/turbo-lint.log +0 -3
- package/.turbo/turbo-typecheck.log +0 -1
- package/dist/app-config.d.ts +0 -65
- package/dist/app-config.d.ts.map +0 -1
- package/dist/app-config.js +0 -172
- package/dist/app-config.js.map +0 -1
- package/dist/collect.d.ts +0 -11
- package/dist/collect.d.ts.map +0 -1
- package/dist/collect.js +0 -81
- package/dist/collect.js.map +0 -1
- package/dist/compose.d.ts +0 -30
- package/dist/compose.d.ts.map +0 -1
- package/dist/compose.js +0 -21
- package/dist/compose.js.map +0 -1
- package/dist/config-gate.d.ts +0 -11
- package/dist/config-gate.d.ts.map +0 -1
- package/dist/config-gate.js +0 -6
- package/dist/config-gate.js.map +0 -1
- package/dist/config-layer.d.ts +0 -11
- package/dist/config-layer.d.ts.map +0 -1
- package/dist/config-layer.js +0 -6
- package/dist/config-layer.js.map +0 -1
- package/dist/config-provision.d.ts +0 -3
- package/dist/config-provision.d.ts.map +0 -1
- package/dist/config-provision.js +0 -26
- package/dist/config-provision.js.map +0 -1
- package/dist/config-service.d.ts +0 -3
- package/dist/config-service.d.ts.map +0 -1
- package/dist/config-service.js +0 -26
- package/dist/config-service.js.map +0 -1
- package/dist/define-config.d.ts +0 -61
- package/dist/define-config.d.ts.map +0 -1
- package/dist/define-config.js +0 -90
- package/dist/define-config.js.map +0 -1
- package/dist/describe.d.ts +0 -25
- package/dist/describe.d.ts.map +0 -1
- package/dist/describe.js +0 -147
- package/dist/describe.js.map +0 -1
- package/dist/doctor.d.ts +0 -27
- package/dist/doctor.d.ts.map +0 -1
- package/dist/doctor.js +0 -131
- package/dist/doctor.js.map +0 -1
- package/dist/explain.d.ts +0 -30
- package/dist/explain.d.ts.map +0 -1
- package/dist/explain.js +0 -101
- package/dist/explain.js.map +0 -1
- package/dist/extensions.d.ts +0 -38
- package/dist/extensions.d.ts.map +0 -1
- package/dist/extensions.js +0 -35
- package/dist/extensions.js.map +0 -1
- package/dist/generate/env.d.ts +0 -15
- package/dist/generate/env.d.ts.map +0 -1
- package/dist/generate/env.js +0 -65
- package/dist/generate/env.js.map +0 -1
- package/dist/generate/example.d.ts +0 -16
- package/dist/generate/example.d.ts.map +0 -1
- package/dist/generate/example.js +0 -138
- package/dist/generate/example.js.map +0 -1
- package/dist/generate/helpers.d.ts +0 -35
- package/dist/generate/helpers.d.ts.map +0 -1
- package/dist/generate/helpers.js +0 -116
- package/dist/generate/helpers.js.map +0 -1
- package/dist/generate/index.d.ts +0 -4
- package/dist/generate/index.d.ts.map +0 -1
- package/dist/generate/index.js +0 -4
- package/dist/generate/index.js.map +0 -1
- package/dist/generate/json-schema.d.ts +0 -18
- package/dist/generate/json-schema.d.ts.map +0 -1
- package/dist/generate/json-schema.js +0 -97
- package/dist/generate/json-schema.js.map +0 -1
- package/dist/index.d.ts +0 -21
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -21
- package/dist/index.js.map +0 -1
- package/dist/merge.d.ts +0 -16
- package/dist/merge.d.ts.map +0 -1
- package/dist/merge.js +0 -34
- package/dist/merge.js.map +0 -1
- package/dist/ref.d.ts +0 -29
- package/dist/ref.d.ts.map +0 -1
- package/dist/ref.js +0 -30
- package/dist/ref.js.map +0 -1
- package/dist/registry.d.ts +0 -24
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -12
- package/dist/registry.js.map +0 -1
- package/dist/resolve.d.ts +0 -21
- package/dist/resolve.d.ts.map +0 -1
- package/dist/resolve.js +0 -177
- package/dist/resolve.js.map +0 -1
- package/dist/secret-heuristics.d.ts +0 -10
- package/dist/secret-heuristics.d.ts.map +0 -1
- package/dist/secret-heuristics.js +0 -11
- package/dist/secret-heuristics.js.map +0 -1
- package/dist/trails/config-check.d.ts +0 -11
- package/dist/trails/config-check.d.ts.map +0 -1
- package/dist/trails/config-check.js +0 -53
- package/dist/trails/config-check.js.map +0 -1
- package/dist/trails/config-describe.d.ts +0 -12
- package/dist/trails/config-describe.d.ts.map +0 -1
- package/dist/trails/config-describe.js +0 -41
- package/dist/trails/config-describe.js.map +0 -1
- package/dist/trails/config-explain.d.ts +0 -8
- package/dist/trails/config-explain.d.ts.map +0 -1
- package/dist/trails/config-explain.js +0 -74
- package/dist/trails/config-explain.js.map +0 -1
- package/dist/trails/config-init.d.ts +0 -9
- package/dist/trails/config-init.d.ts.map +0 -1
- package/dist/trails/config-init.js +0 -78
- package/dist/trails/config-init.js.map +0 -1
- package/dist/workspace.d.ts +0 -9
- package/dist/workspace.d.ts.map +0 -1
- package/dist/workspace.js +0 -49
- package/dist/workspace.js.map +0 -1
- package/dist/zod-utils.d.ts +0 -14
- package/dist/zod-utils.d.ts.map +0 -1
- package/dist/zod-utils.js +0 -41
- package/dist/zod-utils.js.map +0 -1
- package/src/__tests__/app-config.test.ts +0 -329
- package/src/__tests__/compose.test.ts +0 -59
- package/src/__tests__/config-check.test.ts +0 -171
- package/src/__tests__/config-describe.test.ts +0 -154
- package/src/__tests__/config-explain.test.ts +0 -167
- package/src/__tests__/config-gate.test.ts +0 -53
- package/src/__tests__/config-init.test.ts +0 -210
- package/src/__tests__/config-provision.test.ts +0 -87
- package/src/__tests__/define-config.test.ts +0 -263
- package/src/__tests__/describe.test.ts +0 -158
- package/src/__tests__/doctor.test.ts +0 -172
- package/src/__tests__/explain.test.ts +0 -139
- package/src/__tests__/extensions.test.ts +0 -134
- package/src/__tests__/generate.test.ts +0 -269
- package/src/__tests__/ref.test.ts +0 -35
- package/src/__tests__/resolve.test.ts +0 -246
- package/src/__tests__/workspace.test.ts +0 -64
- package/src/config-gate.ts +0 -15
- package/src/generate/index.ts +0 -3
- package/src/workspace.ts +0 -56
- package/tsconfig.json +0 -9
- package/tsconfig.tsbuildinfo +0 -1
package/src/registry.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Module-level config state registry.
|
|
3
3
|
*
|
|
4
4
|
* Config is resolved once at bootstrap (two-phase init per ADR-010) and
|
|
5
|
-
* registered here so `
|
|
5
|
+
* registered here so `configResource` can expose it to surfaces. This is
|
|
6
6
|
* a process-level singleton — config resolution is inherently global.
|
|
7
7
|
*/
|
|
8
8
|
import type { z } from 'zod';
|
|
@@ -12,7 +12,7 @@ export interface ConfigState {
|
|
|
12
12
|
readonly schema: z.ZodObject<Record<string, z.ZodType>>;
|
|
13
13
|
readonly resolved: Record<string, unknown>;
|
|
14
14
|
readonly base?: Record<string, unknown>;
|
|
15
|
-
readonly
|
|
15
|
+
readonly profile?: Record<string, unknown>;
|
|
16
16
|
readonly local?: Record<string, unknown>;
|
|
17
17
|
readonly env?: Record<string, string | undefined>;
|
|
18
18
|
}
|
package/src/resolve.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Config resolution engine — merges config from multiple sources through
|
|
3
|
-
* a deterministic stack: defaults → base →
|
|
3
|
+
* a deterministic stack: defaults → base → profile → local → env.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { z } from 'zod';
|
|
7
7
|
|
|
8
|
-
import { Result } from '@ontrails/core';
|
|
8
|
+
import { Result, ValidationError } from '@ontrails/core';
|
|
9
9
|
|
|
10
10
|
import { collectConfigMeta } from './collect.js';
|
|
11
11
|
import { deepMerge } from './merge.js';
|
|
@@ -16,11 +16,11 @@ import { zodDef } from './zod-utils.js';
|
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
17
|
|
|
18
18
|
/** Options for resolving config through the full stack. */
|
|
19
|
-
export interface
|
|
19
|
+
export interface DeriveConfigOptions<T extends z.ZodType> {
|
|
20
20
|
readonly schema: T;
|
|
21
21
|
readonly base?: Record<string, unknown> | undefined;
|
|
22
|
-
readonly
|
|
23
|
-
readonly
|
|
22
|
+
readonly profiles?: Record<string, Record<string, unknown>> | undefined;
|
|
23
|
+
readonly profile?: string | undefined;
|
|
24
24
|
readonly localOverrides?: Record<string, unknown> | undefined;
|
|
25
25
|
readonly env?: Record<string, string | undefined> | undefined;
|
|
26
26
|
}
|
|
@@ -219,11 +219,11 @@ const applyEnvOverrides = (
|
|
|
219
219
|
// Merge pipeline
|
|
220
220
|
// ---------------------------------------------------------------------------
|
|
221
221
|
|
|
222
|
-
/** Apply the layered merge: base →
|
|
222
|
+
/** Apply the layered merge: base → profile → local overrides. */
|
|
223
223
|
const mergeLayers = (
|
|
224
224
|
base: Record<string, unknown> | undefined,
|
|
225
|
-
|
|
226
|
-
|
|
225
|
+
profiles: Record<string, Record<string, unknown>> | undefined,
|
|
226
|
+
profile: string | undefined,
|
|
227
227
|
localOverrides: Record<string, unknown> | undefined
|
|
228
228
|
): Record<string, unknown> => {
|
|
229
229
|
let merged: Record<string, unknown> = {};
|
|
@@ -231,7 +231,7 @@ const mergeLayers = (
|
|
|
231
231
|
merged = deepMerge(merged, base);
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
const selected =
|
|
234
|
+
const selected = profile && profiles ? profiles[profile] : undefined;
|
|
235
235
|
if (selected) {
|
|
236
236
|
merged = deepMerge(merged, selected);
|
|
237
237
|
}
|
|
@@ -253,16 +253,16 @@ const formatValidationError = (
|
|
|
253
253
|
// ---------------------------------------------------------------------------
|
|
254
254
|
|
|
255
255
|
/**
|
|
256
|
-
*
|
|
256
|
+
* Derive config through the full stack: defaults → base → profile → local → env.
|
|
257
257
|
* Returns `Result.ok` with the validated config, or `Result.err` on validation failure.
|
|
258
258
|
*/
|
|
259
|
-
export const
|
|
260
|
-
options:
|
|
259
|
+
export const deriveConfig = <T extends z.ZodType>(
|
|
260
|
+
options: DeriveConfigOptions<T>
|
|
261
261
|
): Result<z.infer<T>, Error> => {
|
|
262
262
|
let merged = mergeLayers(
|
|
263
263
|
options.base,
|
|
264
|
-
options.
|
|
265
|
-
options.
|
|
264
|
+
options.profiles,
|
|
265
|
+
options.profile,
|
|
266
266
|
options.localOverrides
|
|
267
267
|
);
|
|
268
268
|
|
|
@@ -275,5 +275,7 @@ export const resolveConfig = <T extends z.ZodType>(
|
|
|
275
275
|
return Result.ok(parsed.data as z.infer<T>);
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
-
return Result.err(
|
|
278
|
+
return Result.err(
|
|
279
|
+
new ValidationError(formatValidationError(parsed.error.issues))
|
|
280
|
+
);
|
|
279
281
|
};
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { Result, trail } from '@ontrails/core';
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { configResource } from '../config-resource.js';
|
|
11
11
|
import { checkConfig } from '../doctor.js';
|
|
12
12
|
import { deepMerge } from '../merge.js';
|
|
13
13
|
|
|
@@ -33,7 +33,7 @@ const mergeValues = (
|
|
|
33
33
|
|
|
34
34
|
export const configCheck = trail('config.check', {
|
|
35
35
|
blaze: (input, ctx) => {
|
|
36
|
-
const state =
|
|
36
|
+
const state = configResource.from(ctx);
|
|
37
37
|
const effective = mergeValues(state.resolved, input.values);
|
|
38
38
|
const checked = checkConfig(state.schema, effective);
|
|
39
39
|
return Result.ok({
|
|
@@ -56,5 +56,5 @@ export const configCheck = trail('config.check', {
|
|
|
56
56
|
intent: 'read',
|
|
57
57
|
meta: { category: 'infrastructure' },
|
|
58
58
|
output: outputSchema,
|
|
59
|
-
|
|
59
|
+
resources: [configResource],
|
|
60
60
|
});
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
import { Result, trail } from '@ontrails/core';
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { configResource } from '../config-resource.js';
|
|
11
|
+
import { deriveConfigFields } from '../derive-fields.js';
|
|
12
12
|
|
|
13
13
|
const fieldSchema = z.object({
|
|
14
14
|
deprecated: z.string().optional(),
|
|
@@ -26,8 +26,8 @@ const outputSchema = z.object({
|
|
|
26
26
|
|
|
27
27
|
export const configDescribe = trail('config.describe', {
|
|
28
28
|
blaze: (_input, ctx) => {
|
|
29
|
-
const state =
|
|
30
|
-
const fields =
|
|
29
|
+
const state = configResource.from(ctx);
|
|
30
|
+
const fields = deriveConfigFields(state.schema);
|
|
31
31
|
return Result.ok({ fields: [...fields] });
|
|
32
32
|
},
|
|
33
33
|
examples: [
|
|
@@ -40,5 +40,5 @@ export const configDescribe = trail('config.describe', {
|
|
|
40
40
|
intent: 'read',
|
|
41
41
|
meta: { category: 'infrastructure' },
|
|
42
42
|
output: outputSchema,
|
|
43
|
-
|
|
43
|
+
resources: [configResource],
|
|
44
44
|
});
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
import { Result, trail } from '@ontrails/core';
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import type {
|
|
12
|
-
import {
|
|
10
|
+
import { configResource } from '../config-resource.js';
|
|
11
|
+
import type { DeriveConfigProvenanceOptions } from '../derive-provenance.js';
|
|
12
|
+
import { deriveConfigProvenance } from '../derive-provenance.js';
|
|
13
13
|
import type { ConfigState } from '../registry.js';
|
|
14
14
|
|
|
15
15
|
const provenanceEntrySchema = z.object({
|
|
@@ -34,11 +34,11 @@ const filterByPath = (
|
|
|
34
34
|
)
|
|
35
35
|
: entries;
|
|
36
36
|
|
|
37
|
-
/** Build
|
|
37
|
+
/** Build DeriveConfigProvenanceOptions from ConfigState, omitting undefined source overrides. */
|
|
38
38
|
const toExplainOptions = (
|
|
39
39
|
state: ConfigState
|
|
40
|
-
):
|
|
41
|
-
const base:
|
|
40
|
+
): DeriveConfigProvenanceOptions<typeof state.schema> => {
|
|
41
|
+
const base: DeriveConfigProvenanceOptions<typeof state.schema> = {
|
|
42
42
|
resolved: state.resolved,
|
|
43
43
|
schema: state.schema,
|
|
44
44
|
};
|
|
@@ -51,14 +51,14 @@ const toExplainOptions = (
|
|
|
51
51
|
/** Enrich explain options with env and source overrides from state. */
|
|
52
52
|
const enrichOptions = (
|
|
53
53
|
state: ConfigState,
|
|
54
|
-
options:
|
|
55
|
-
):
|
|
54
|
+
options: DeriveConfigProvenanceOptions<typeof state.schema>
|
|
55
|
+
): DeriveConfigProvenanceOptions<typeof state.schema> => {
|
|
56
56
|
let enriched = options;
|
|
57
57
|
if (state.env) {
|
|
58
58
|
enriched = { ...enriched, env: state.env };
|
|
59
59
|
}
|
|
60
|
-
if (state.
|
|
61
|
-
enriched = { ...enriched,
|
|
60
|
+
if (state.profile) {
|
|
61
|
+
enriched = { ...enriched, profile: state.profile };
|
|
62
62
|
}
|
|
63
63
|
if (state.local) {
|
|
64
64
|
enriched = { ...enriched, local: state.local };
|
|
@@ -68,9 +68,9 @@ const enrichOptions = (
|
|
|
68
68
|
|
|
69
69
|
export const configExplain = trail('config.explain', {
|
|
70
70
|
blaze: (input, ctx) => {
|
|
71
|
-
const state =
|
|
71
|
+
const state = configResource.from(ctx);
|
|
72
72
|
const options = enrichOptions(state, toExplainOptions(state));
|
|
73
|
-
const entries =
|
|
73
|
+
const entries = deriveConfigProvenance(options);
|
|
74
74
|
const filtered = filterByPath(entries, input.path);
|
|
75
75
|
return Result.ok({ entries: [...filtered] });
|
|
76
76
|
},
|
|
@@ -89,5 +89,5 @@ export const configExplain = trail('config.explain', {
|
|
|
89
89
|
intent: 'read',
|
|
90
90
|
meta: { category: 'infrastructure' },
|
|
91
91
|
output: outputSchema,
|
|
92
|
-
|
|
92
|
+
resources: [configResource],
|
|
93
93
|
});
|
|
@@ -14,12 +14,12 @@ import { Result, trail } from '@ontrails/core';
|
|
|
14
14
|
import type { z } from 'zod';
|
|
15
15
|
import { z as zod } from 'zod';
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { configResource } from '../config-resource.js';
|
|
18
18
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} from '../
|
|
19
|
+
deriveConfigEnvExample,
|
|
20
|
+
deriveConfigExample,
|
|
21
|
+
deriveConfigJsonSchema,
|
|
22
|
+
} from '../derive/index.js';
|
|
23
23
|
|
|
24
24
|
const formatEnum = zod.enum(['toml', 'json', 'jsonc', 'yaml']);
|
|
25
25
|
|
|
@@ -34,13 +34,13 @@ const collectArtifacts = (
|
|
|
34
34
|
schema: z.ZodObject<Record<string, z.ZodType>>
|
|
35
35
|
): [string, string][] => {
|
|
36
36
|
const artifacts: [string, string][] = [];
|
|
37
|
-
const envContent =
|
|
37
|
+
const envContent = deriveConfigEnvExample(schema);
|
|
38
38
|
if (envContent.length > 0) {
|
|
39
39
|
artifacts.push(['.env.example', envContent]);
|
|
40
40
|
}
|
|
41
41
|
artifacts.push([
|
|
42
42
|
'.schema.json',
|
|
43
|
-
JSON.stringify(
|
|
43
|
+
JSON.stringify(deriveConfigJsonSchema(schema), null, 2),
|
|
44
44
|
]);
|
|
45
45
|
return artifacts;
|
|
46
46
|
};
|
|
@@ -63,9 +63,9 @@ const writeArtifacts = async (
|
|
|
63
63
|
|
|
64
64
|
export const configInit = trail('config.init', {
|
|
65
65
|
blaze: async (input, ctx) => {
|
|
66
|
-
const state =
|
|
66
|
+
const state = configResource.from(ctx);
|
|
67
67
|
const schema = state.schema as z.ZodObject<Record<string, z.ZodType>>;
|
|
68
|
-
const content =
|
|
68
|
+
const content = deriveConfigExample(schema, input.format);
|
|
69
69
|
|
|
70
70
|
if (input.dir) {
|
|
71
71
|
const writtenFiles = await writeArtifacts(input.dir, schema);
|
|
@@ -92,5 +92,5 @@ export const configInit = trail('config.init', {
|
|
|
92
92
|
intent: 'write',
|
|
93
93
|
meta: { category: 'infrastructure' },
|
|
94
94
|
output: outputSchema,
|
|
95
|
-
|
|
95
|
+
resources: [configResource],
|
|
96
96
|
});
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
$ tsc -b
|
package/.turbo/turbo-lint.log
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
$ tsc --noEmit
|
package/dist/app-config.d.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* App config factory — declare a config contract once, discover and validate at runtime.
|
|
3
|
-
*/
|
|
4
|
-
import { Result } from '@ontrails/core';
|
|
5
|
-
import type { z } from 'zod';
|
|
6
|
-
import type { CheckResult } from './doctor.js';
|
|
7
|
-
import type { FieldDescription } from './describe.js';
|
|
8
|
-
import type { ExplainConfigOptions, ProvenanceEntry } from './explain.js';
|
|
9
|
-
import type { ConfigRef } from './ref.js';
|
|
10
|
-
/** Supported config file formats. */
|
|
11
|
-
export type ConfigFormat = 'toml' | 'json' | 'jsonc' | 'yaml';
|
|
12
|
-
/** Options for creating an app config. */
|
|
13
|
-
export interface AppConfigOptions<T extends z.ZodType> {
|
|
14
|
-
readonly schema: T;
|
|
15
|
-
readonly formats?: readonly ConfigFormat[];
|
|
16
|
-
readonly dotfile?: boolean;
|
|
17
|
-
}
|
|
18
|
-
/** Options for resolving (discovering + parsing) a config file. */
|
|
19
|
-
export interface ResolveOptions {
|
|
20
|
-
/** Working directory for discovery. Defaults to `process.cwd()`. */
|
|
21
|
-
readonly cwd?: string;
|
|
22
|
-
/** Explicit file path — skips discovery when provided. */
|
|
23
|
-
readonly path?: string;
|
|
24
|
-
}
|
|
25
|
-
/** Options for the `explain()` method on AppConfig, excluding schema. */
|
|
26
|
-
export type AppConfigExplainOptions = Omit<ExplainConfigOptions<z.ZodType>, 'schema'>;
|
|
27
|
-
/** The resolved config contract returned by `appConfig()`. */
|
|
28
|
-
export interface AppConfig<T extends z.ZodType> {
|
|
29
|
-
readonly name: string;
|
|
30
|
-
readonly schema: T;
|
|
31
|
-
readonly formats: readonly ConfigFormat[];
|
|
32
|
-
readonly dotfile: boolean;
|
|
33
|
-
resolve(options?: ResolveOptions): Promise<Result<z.infer<T>, Error>>;
|
|
34
|
-
/** Describe all fields in the schema without needing values. */
|
|
35
|
-
describe(): readonly FieldDescription[];
|
|
36
|
-
/** Check a config object against the schema and return diagnostics. */
|
|
37
|
-
check(values: Record<string, unknown>, options?: {
|
|
38
|
-
readonly env?: Record<string, string | undefined>;
|
|
39
|
-
}): CheckResult;
|
|
40
|
-
/** Show which source won for each config field. */
|
|
41
|
-
explain(options: AppConfigExplainOptions): readonly ProvenanceEntry[];
|
|
42
|
-
/** Create a lazy reference to a config field for use as a trail input default. */
|
|
43
|
-
ref(fieldPath: string): ConfigRef;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Declare a config contract for an app.
|
|
47
|
-
*
|
|
48
|
-
* The returned `AppConfig` exposes `resolve()` to discover, parse, and validate
|
|
49
|
-
* a config file matching the app name and format conventions.
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* ```ts
|
|
53
|
-
* const config = appConfig('myapp', {
|
|
54
|
-
* schema: z.object({
|
|
55
|
-
* output: z.string().default('./output'),
|
|
56
|
-
* verbose: z.boolean().default(false),
|
|
57
|
-
* }),
|
|
58
|
-
* });
|
|
59
|
-
*
|
|
60
|
-
* const result = await config.resolve();
|
|
61
|
-
* if (result.isOk()) console.log(result.value.output);
|
|
62
|
-
* ```
|
|
63
|
-
*/
|
|
64
|
-
export declare const appConfig: <T extends z.ZodType>(name: string, options: AppConfigOptions<T>) => AppConfig<T>;
|
|
65
|
-
//# sourceMappingURL=app-config.d.ts.map
|
package/dist/app-config.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"app-config.d.ts","sourceRoot":"","sources":["../src/app-config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAiB,MAAM,EAAmB,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAO1C,qCAAqC;AACrC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAE9D,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO;IACnD,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,mEAAmE;AACnE,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,yEAAyE;AACzE,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC,EAC/B,QAAQ,CACT,CAAC;AAEF,8DAA8D;AAC9D,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnB,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAEtE,gEAAgE;IAChE,QAAQ,IAAI,SAAS,gBAAgB,EAAE,CAAC;IAExC,uEAAuE;IACvE,KAAK,CACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;KAAE,GAC9D,WAAW,CAAC;IAEf,mDAAmD;IACnD,OAAO,CAAC,OAAO,EAAE,uBAAuB,GAAG,SAAS,eAAe,EAAE,CAAC;IAEtE,kFAAkF;IAClF,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAmMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAC3C,MAAM,MAAM,EACZ,SAAS,gBAAgB,CAAC,CAAC,CAAC,KAC3B,SAAS,CAAC,CAAC,CAqBb,CAAC"}
|
package/dist/app-config.js
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* App config factory — declare a config contract once, discover and validate at runtime.
|
|
3
|
-
*/
|
|
4
|
-
import { dirname, join } from 'node:path';
|
|
5
|
-
import { NotFoundError, Result, ValidationError } from '@ontrails/core';
|
|
6
|
-
import { checkConfig } from './doctor.js';
|
|
7
|
-
import { describeConfig } from './describe.js';
|
|
8
|
-
import { explainConfig } from './explain.js';
|
|
9
|
-
import { configRef } from './ref.js';
|
|
10
|
-
// ---------------------------------------------------------------------------
|
|
11
|
-
// Default values
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
const DEFAULT_FORMATS = ['toml', 'json', 'yaml'];
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
|
-
// Internal helpers (defined before consumers — no-use-before-define)
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
|
-
/** Build the config filename for a given format. */
|
|
18
|
-
const configFileName = (name, format, dotfile) => (dotfile ? `.${name}rc.${format}` : `${name}.config.${format}`);
|
|
19
|
-
/** Check whether a file exists at the given path. */
|
|
20
|
-
const fileExists = (filePath) => Bun.file(filePath).exists();
|
|
21
|
-
/** Known config suffixes, ordered to avoid `.json` matching `.jsonc`. */
|
|
22
|
-
const FORMAT_SUFFIXES = [
|
|
23
|
-
['jsonc', '.jsonc'],
|
|
24
|
-
['json', '.json'],
|
|
25
|
-
['toml', '.toml'],
|
|
26
|
-
['yaml', '.yaml'],
|
|
27
|
-
];
|
|
28
|
-
/** Detect the declared config format from a file path. */
|
|
29
|
-
const detectFormat = (filePath) => {
|
|
30
|
-
for (const [format, suffix] of FORMAT_SUFFIXES) {
|
|
31
|
-
if (filePath.endsWith(suffix)) {
|
|
32
|
-
return format;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return undefined;
|
|
36
|
-
};
|
|
37
|
-
/** Parse config file text with Bun's native format parsers. */
|
|
38
|
-
const parseConfigText = (filePath, text) => {
|
|
39
|
-
const format = detectFormat(filePath);
|
|
40
|
-
try {
|
|
41
|
-
switch (format) {
|
|
42
|
-
case 'json': {
|
|
43
|
-
return Result.ok(JSON.parse(text));
|
|
44
|
-
}
|
|
45
|
-
case 'jsonc': {
|
|
46
|
-
return Result.ok(Bun.JSONC.parse(text));
|
|
47
|
-
}
|
|
48
|
-
case 'toml': {
|
|
49
|
-
return Result.ok(Bun.TOML.parse(text));
|
|
50
|
-
}
|
|
51
|
-
case 'yaml': {
|
|
52
|
-
return Result.ok(Bun.YAML.parse(text));
|
|
53
|
-
}
|
|
54
|
-
default: {
|
|
55
|
-
return Result.err(new ValidationError(`Unsupported config file format: ${filePath}`, {
|
|
56
|
-
context: { path: filePath },
|
|
57
|
-
}));
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
return Result.err(new ValidationError(`Failed to parse config file: ${filePath}`, {
|
|
63
|
-
cause: error instanceof Error ? error : new Error(String(error)),
|
|
64
|
-
context: { path: filePath },
|
|
65
|
-
}));
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
/** Read and parse a config file, always reflecting the latest on-disk content. */
|
|
69
|
-
const readConfigFile = async (filePath) => {
|
|
70
|
-
const exists = await fileExists(filePath);
|
|
71
|
-
if (!exists) {
|
|
72
|
-
return Result.err(new NotFoundError(`Config file not found: ${filePath}`, {
|
|
73
|
-
context: { path: filePath },
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
const text = await Bun.file(filePath).text();
|
|
77
|
-
return parseConfigText(filePath, text);
|
|
78
|
-
};
|
|
79
|
-
/** Validate parsed data against a Zod schema. */
|
|
80
|
-
const validateConfig = (schema, data, filePath) => {
|
|
81
|
-
const parsed = schema.safeParse(data);
|
|
82
|
-
if (parsed.success) {
|
|
83
|
-
return Result.ok(parsed.data);
|
|
84
|
-
}
|
|
85
|
-
return Result.err(new ValidationError(`Config validation failed: ${filePath}`, {
|
|
86
|
-
context: {
|
|
87
|
-
issues: parsed.error.issues,
|
|
88
|
-
path: filePath,
|
|
89
|
-
},
|
|
90
|
-
}));
|
|
91
|
-
};
|
|
92
|
-
/** Check all format candidates in a single directory. */
|
|
93
|
-
const findInDir = async (dir, name, formats, dotfile) => {
|
|
94
|
-
for (const format of formats) {
|
|
95
|
-
const candidate = join(dir, configFileName(name, format, dotfile));
|
|
96
|
-
if (await fileExists(candidate)) {
|
|
97
|
-
return candidate;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return undefined;
|
|
101
|
-
};
|
|
102
|
-
/** Walk up from `startDir` looking for any matching config filename. */
|
|
103
|
-
const discoverConfigFile = async (name, formats, dotfile, startDir) => {
|
|
104
|
-
let dir = startDir;
|
|
105
|
-
for (let depth = 0; depth < 64; depth += 1) {
|
|
106
|
-
const found = await findInDir(dir, name, formats, dotfile);
|
|
107
|
-
if (found !== undefined) {
|
|
108
|
-
return found;
|
|
109
|
-
}
|
|
110
|
-
const parent = dirname(dir);
|
|
111
|
-
// Reached filesystem root
|
|
112
|
-
if (parent === dir) {
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
dir = parent;
|
|
116
|
-
}
|
|
117
|
-
return undefined;
|
|
118
|
-
};
|
|
119
|
-
/** Resolve a config file — either from an explicit path or via discovery. */
|
|
120
|
-
const resolveConfig = async (name, schema, formats, dotfile, options) => {
|
|
121
|
-
const filePath = options?.path ??
|
|
122
|
-
(await discoverConfigFile(name, formats, dotfile, options?.cwd ?? process.cwd()));
|
|
123
|
-
if (filePath === undefined) {
|
|
124
|
-
return Result.err(new NotFoundError(`No config file found for "${name}"`, {
|
|
125
|
-
context: { dotfile, formats: [...formats], name },
|
|
126
|
-
}));
|
|
127
|
-
}
|
|
128
|
-
const readResult = await readConfigFile(filePath);
|
|
129
|
-
if (readResult.isErr()) {
|
|
130
|
-
return readResult;
|
|
131
|
-
}
|
|
132
|
-
return validateConfig(schema, readResult.value, filePath);
|
|
133
|
-
};
|
|
134
|
-
// ---------------------------------------------------------------------------
|
|
135
|
-
// Factory
|
|
136
|
-
// ---------------------------------------------------------------------------
|
|
137
|
-
/**
|
|
138
|
-
* Declare a config contract for an app.
|
|
139
|
-
*
|
|
140
|
-
* The returned `AppConfig` exposes `resolve()` to discover, parse, and validate
|
|
141
|
-
* a config file matching the app name and format conventions.
|
|
142
|
-
*
|
|
143
|
-
* @example
|
|
144
|
-
* ```ts
|
|
145
|
-
* const config = appConfig('myapp', {
|
|
146
|
-
* schema: z.object({
|
|
147
|
-
* output: z.string().default('./output'),
|
|
148
|
-
* verbose: z.boolean().default(false),
|
|
149
|
-
* }),
|
|
150
|
-
* });
|
|
151
|
-
*
|
|
152
|
-
* const result = await config.resolve();
|
|
153
|
-
* if (result.isOk()) console.log(result.value.output);
|
|
154
|
-
* ```
|
|
155
|
-
*/
|
|
156
|
-
export const appConfig = (name, options) => {
|
|
157
|
-
const formats = options.formats ?? DEFAULT_FORMATS;
|
|
158
|
-
const dotfile = options.dotfile ?? false;
|
|
159
|
-
const { schema } = options;
|
|
160
|
-
return {
|
|
161
|
-
check: (values, checkOpts) => checkConfig(schema, values, checkOpts),
|
|
162
|
-
describe: () => describeConfig(schema),
|
|
163
|
-
dotfile,
|
|
164
|
-
explain: (explainOpts) => explainConfig({ ...explainOpts, schema }),
|
|
165
|
-
formats,
|
|
166
|
-
name,
|
|
167
|
-
ref: (fieldPath) => configRef(fieldPath),
|
|
168
|
-
resolve: (resolveOptions) => resolveConfig(name, schema, formats, dotfile, resolveOptions),
|
|
169
|
-
schema,
|
|
170
|
-
};
|
|
171
|
-
};
|
|
172
|
-
//# sourceMappingURL=app-config.js.map
|
package/dist/app-config.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"app-config.js","sourceRoot":"","sources":["../src/app-config.ts"],"names":[],"mappings":"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"}
|
package/dist/collect.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { z } from 'zod';
|
|
2
|
-
import type { ConfigFieldMeta } from './extensions.js';
|
|
3
|
-
/**
|
|
4
|
-
* Walk a Zod object schema and collect `ConfigFieldMeta` for each field.
|
|
5
|
-
*
|
|
6
|
-
* Handles unwrapping `.default()`, `.optional()`, `.nullable()` wrappers
|
|
7
|
-
* that don't carry inner metadata forward. Recurses into nested `ZodObject`
|
|
8
|
-
* fields using dot-separated paths.
|
|
9
|
-
*/
|
|
10
|
-
export declare const collectConfigMeta: (schema: z.ZodObject<Record<string, z.ZodType>>, prefix?: string) => Map<string, ConfigFieldMeta>;
|
|
11
|
-
//# sourceMappingURL=collect.d.ts.map
|
package/dist/collect.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../src/collect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AA+FvD;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,EAC9C,eAAW,KACV,GAAG,CAAC,MAAM,EAAE,eAAe,CAS7B,CAAC"}
|
package/dist/collect.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { globalRegistry } from 'zod';
|
|
2
|
-
import { isZodObject, unwrapToBase } from './zod-utils.js';
|
|
3
|
-
/** Config meta keys we look for in Zod registry entries. */
|
|
4
|
-
const META_EXTRACTORS = [
|
|
5
|
-
{
|
|
6
|
-
extract: (r) => ({ env: r['env'] }),
|
|
7
|
-
test: (r) => typeof r['env'] === 'string',
|
|
8
|
-
},
|
|
9
|
-
{
|
|
10
|
-
extract: () => ({ secret: true }),
|
|
11
|
-
test: (r) => r['secret'] === true,
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
extract: (r) => ({ deprecated: r['deprecationMessage'] }),
|
|
15
|
-
test: (r) => typeof r['deprecationMessage'] === 'string',
|
|
16
|
-
},
|
|
17
|
-
];
|
|
18
|
-
/**
|
|
19
|
-
* Pick only `ConfigFieldMeta` keys from a raw registry entry.
|
|
20
|
-
* Uses a lookup table to stay under the max-statements limit.
|
|
21
|
-
*/
|
|
22
|
-
const pickConfigMeta = (raw) => {
|
|
23
|
-
if (!raw) {
|
|
24
|
-
return undefined;
|
|
25
|
-
}
|
|
26
|
-
const parts = META_EXTRACTORS.filter((e) => e.test(raw)).map((e) => e.extract(raw));
|
|
27
|
-
return parts.length > 0
|
|
28
|
-
? Object.assign({}, ...parts)
|
|
29
|
-
: undefined;
|
|
30
|
-
};
|
|
31
|
-
/**
|
|
32
|
-
* Extract `ConfigFieldMeta` from a schema, unwrapping through
|
|
33
|
-
* `.default()`, `.optional()`, `.nullable()` wrappers as needed.
|
|
34
|
-
*/
|
|
35
|
-
const extractConfigMeta = (schema) => {
|
|
36
|
-
let current = schema;
|
|
37
|
-
while (current) {
|
|
38
|
-
const meta = pickConfigMeta(globalRegistry.get(current));
|
|
39
|
-
if (meta) {
|
|
40
|
-
return meta;
|
|
41
|
-
}
|
|
42
|
-
const def = current.def;
|
|
43
|
-
current = def['innerType'];
|
|
44
|
-
}
|
|
45
|
-
return undefined;
|
|
46
|
-
};
|
|
47
|
-
/** Process one level of an object schema, queuing nested objects. */
|
|
48
|
-
const walkObjectShape = (schema, prefix, result, queue) => {
|
|
49
|
-
const shape = schema.shape;
|
|
50
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
51
|
-
const path = prefix ? `${prefix}.${key}` : key;
|
|
52
|
-
if (isZodObject(fieldSchema)) {
|
|
53
|
-
queue.push({
|
|
54
|
-
prefix: path,
|
|
55
|
-
schema: unwrapToBase(fieldSchema),
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
const meta = extractConfigMeta(fieldSchema);
|
|
60
|
-
if (meta) {
|
|
61
|
-
result.set(path, meta);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* Walk a Zod object schema and collect `ConfigFieldMeta` for each field.
|
|
68
|
-
*
|
|
69
|
-
* Handles unwrapping `.default()`, `.optional()`, `.nullable()` wrappers
|
|
70
|
-
* that don't carry inner metadata forward. Recurses into nested `ZodObject`
|
|
71
|
-
* fields using dot-separated paths.
|
|
72
|
-
*/
|
|
73
|
-
export const collectConfigMeta = (schema, prefix = '') => {
|
|
74
|
-
const result = new Map();
|
|
75
|
-
const queue = [{ prefix, schema }];
|
|
76
|
-
for (let entry = queue.pop(); entry; entry = queue.pop()) {
|
|
77
|
-
walkObjectShape(entry.schema, entry.prefix, result, queue);
|
|
78
|
-
}
|
|
79
|
-
return result;
|
|
80
|
-
};
|
|
81
|
-
//# sourceMappingURL=collect.js.map
|
package/dist/collect.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"collect.js","sourceRoot":"","sources":["../src/collect.ts"],"names":[],"mappings":"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"}
|