@ontrails/config 1.0.0-beta.14 → 1.0.0-beta.15

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.
Files changed (136) hide show
  1. package/.turbo/turbo-lint.log +1 -1
  2. package/CHANGELOG.md +7 -0
  3. package/README.md +20 -28
  4. package/dist/app-config.d.ts +4 -4
  5. package/dist/app-config.d.ts.map +1 -1
  6. package/dist/app-config.js +12 -7
  7. package/dist/app-config.js.map +1 -1
  8. package/dist/compose.d.ts +11 -15
  9. package/dist/compose.d.ts.map +1 -1
  10. package/dist/compose.js +7 -9
  11. package/dist/compose.js.map +1 -1
  12. package/dist/config-layer.d.ts +3 -3
  13. package/dist/config-resource.d.ts +3 -0
  14. package/dist/config-resource.d.ts.map +1 -0
  15. package/dist/{config-provision.js → config-resource.js} +6 -6
  16. package/dist/config-resource.js.map +1 -0
  17. package/dist/define-config.d.ts +9 -9
  18. package/dist/define-config.d.ts.map +1 -1
  19. package/dist/define-config.js +9 -12
  20. package/dist/define-config.js.map +1 -1
  21. package/dist/{generate → derive}/env.d.ts +1 -1
  22. package/dist/derive/env.d.ts.map +1 -0
  23. package/dist/{generate → derive}/env.js +3 -3
  24. package/dist/derive/env.js.map +1 -0
  25. package/dist/{generate → derive}/example.d.ts +1 -1
  26. package/dist/derive/example.d.ts.map +1 -0
  27. package/dist/{generate → derive}/example.js +1 -1
  28. package/dist/derive/example.js.map +1 -0
  29. package/dist/{generate → derive}/helpers.d.ts +1 -1
  30. package/dist/derive/helpers.d.ts.map +1 -0
  31. package/dist/{generate → derive}/helpers.js +1 -1
  32. package/dist/derive/helpers.js.map +1 -0
  33. package/dist/derive/index.d.ts +4 -0
  34. package/dist/derive/index.d.ts.map +1 -0
  35. package/dist/derive/index.js +4 -0
  36. package/dist/derive/index.js.map +1 -0
  37. package/dist/{generate → derive}/json-schema.d.ts +1 -1
  38. package/dist/derive/json-schema.d.ts.map +1 -0
  39. package/dist/{generate → derive}/json-schema.js +1 -1
  40. package/dist/derive/json-schema.js.map +1 -0
  41. package/dist/{describe.d.ts → derive-fields.d.ts} +2 -2
  42. package/dist/derive-fields.d.ts.map +1 -0
  43. package/dist/{describe.js → derive-fields.js} +2 -2
  44. package/dist/derive-fields.js.map +1 -0
  45. package/dist/{explain.d.ts → derive-provenance.d.ts} +5 -5
  46. package/dist/derive-provenance.d.ts.map +1 -0
  47. package/dist/{explain.js → derive-provenance.js} +3 -3
  48. package/dist/derive-provenance.js.map +1 -0
  49. package/dist/index.d.ts +7 -8
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +6 -7
  52. package/dist/index.js.map +1 -1
  53. package/dist/registry.d.ts +2 -2
  54. package/dist/resolve.d.ts +6 -6
  55. package/dist/resolve.d.ts.map +1 -1
  56. package/dist/resolve.js +7 -7
  57. package/dist/resolve.js.map +1 -1
  58. package/dist/trails/config-check.d.ts +1 -1
  59. package/dist/trails/config-check.d.ts.map +1 -1
  60. package/dist/trails/config-check.js +3 -3
  61. package/dist/trails/config-check.js.map +1 -1
  62. package/dist/trails/config-describe.d.ts +1 -1
  63. package/dist/trails/config-describe.d.ts.map +1 -1
  64. package/dist/trails/config-describe.js +5 -5
  65. package/dist/trails/config-describe.js.map +1 -1
  66. package/dist/trails/config-explain.d.ts +1 -1
  67. package/dist/trails/config-explain.d.ts.map +1 -1
  68. package/dist/trails/config-explain.js +8 -8
  69. package/dist/trails/config-explain.js.map +1 -1
  70. package/dist/trails/config-init.d.ts +1 -1
  71. package/dist/trails/config-init.d.ts.map +1 -1
  72. package/dist/trails/config-init.js +7 -7
  73. package/dist/trails/config-init.js.map +1 -1
  74. package/package.json +2 -2
  75. package/src/__tests__/app-config.test.ts +19 -6
  76. package/src/__tests__/compose.test.ts +15 -15
  77. package/src/__tests__/config-check.test.ts +7 -7
  78. package/src/__tests__/config-describe.test.ts +7 -7
  79. package/src/__tests__/config-explain.test.ts +7 -7
  80. package/src/__tests__/config-init.test.ts +7 -7
  81. package/src/__tests__/{config-provision.test.ts → config-resource.test.ts} +12 -12
  82. package/src/__tests__/define-config.test.ts +24 -18
  83. package/src/__tests__/{describe.test.ts → derive-fields.test.ts} +11 -11
  84. package/src/__tests__/{explain.test.ts → derive-provenance.test.ts} +18 -18
  85. package/src/__tests__/{generate.test.ts → derive.test.ts} +30 -30
  86. package/src/__tests__/resolve.test.ts +31 -31
  87. package/src/app-config.ts +23 -12
  88. package/src/compose.ts +16 -22
  89. package/src/{config-provision.ts → config-resource.ts} +5 -5
  90. package/src/define-config.ts +12 -15
  91. package/src/{generate → derive}/env.ts +3 -3
  92. package/src/{generate → derive}/example.ts +1 -1
  93. package/src/{generate → derive}/helpers.ts +1 -1
  94. package/src/derive/index.ts +3 -0
  95. package/src/{generate → derive}/json-schema.ts +1 -1
  96. package/src/{describe.ts → derive-fields.ts} +1 -1
  97. package/src/{explain.ts → derive-provenance.ts} +6 -6
  98. package/src/index.ts +12 -18
  99. package/src/registry.ts +2 -2
  100. package/src/resolve.ts +13 -13
  101. package/src/trails/config-check.ts +3 -3
  102. package/src/trails/config-describe.ts +5 -5
  103. package/src/trails/config-explain.ts +13 -13
  104. package/src/trails/config-init.ts +10 -10
  105. package/tsconfig.tests.json +10 -0
  106. package/tsconfig.tsbuildinfo +1 -1
  107. package/dist/config-gate.d.ts +0 -11
  108. package/dist/config-gate.d.ts.map +0 -1
  109. package/dist/config-gate.js +0 -6
  110. package/dist/config-gate.js.map +0 -1
  111. package/dist/config-provision.d.ts +0 -3
  112. package/dist/config-provision.d.ts.map +0 -1
  113. package/dist/config-provision.js.map +0 -1
  114. package/dist/config-service.d.ts +0 -3
  115. package/dist/config-service.d.ts.map +0 -1
  116. package/dist/config-service.js +0 -26
  117. package/dist/config-service.js.map +0 -1
  118. package/dist/describe.d.ts.map +0 -1
  119. package/dist/describe.js.map +0 -1
  120. package/dist/explain.d.ts.map +0 -1
  121. package/dist/explain.js.map +0 -1
  122. package/dist/generate/env.d.ts.map +0 -1
  123. package/dist/generate/env.js.map +0 -1
  124. package/dist/generate/example.d.ts.map +0 -1
  125. package/dist/generate/example.js.map +0 -1
  126. package/dist/generate/helpers.d.ts.map +0 -1
  127. package/dist/generate/helpers.js.map +0 -1
  128. package/dist/generate/index.d.ts +0 -4
  129. package/dist/generate/index.d.ts.map +0 -1
  130. package/dist/generate/index.js +0 -4
  131. package/dist/generate/index.js.map +0 -1
  132. package/dist/generate/json-schema.d.ts.map +0 -1
  133. package/dist/generate/json-schema.js.map +0 -1
  134. package/src/__tests__/config-gate.test.ts +0 -53
  135. package/src/config-gate.ts +0 -15
  136. package/src/generate/index.ts +0 -3
package/src/compose.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Config composition utilities for provisions.
2
+ * Config composition utilities for resources.
3
3
  *
4
- * Collects config schemas from provision declarations so they can be
4
+ * Collects config schemas from resource declarations so they can be
5
5
  * composed into a unified config structure via `defineConfig`.
6
6
  */
7
7
 
@@ -11,17 +11,14 @@ import type { z } from 'zod';
11
11
  // Types
12
12
  // ---------------------------------------------------------------------------
13
13
 
14
- /** A provision config schema entry extracted from a provision declaration. */
15
- export interface ProvisionConfigEntry {
16
- readonly provisionId: string;
14
+ /** A resource config schema entry extracted from a resource declaration. */
15
+ export interface ResourceConfigEntry {
16
+ readonly resourceId: string;
17
17
  readonly schema: z.ZodType;
18
18
  }
19
19
 
20
- /** Backward-compatible alias while the migration is in flight. */
21
- export type ServiceConfigEntry = ProvisionConfigEntry;
22
-
23
- /** Minimal shape needed to extract config from a provision-like object. */
24
- interface ProvisionWithOptionalConfig {
20
+ /** Minimal shape needed to extract config from a resource-like object. */
21
+ interface ResourceWithOptionalConfig {
25
22
  readonly id: string;
26
23
  readonly config?: z.ZodType | undefined;
27
24
  }
@@ -31,22 +28,19 @@ interface ProvisionWithOptionalConfig {
31
28
  // ---------------------------------------------------------------------------
32
29
 
33
30
  /**
34
- * Collect config schemas from provisions that declare them.
31
+ * Collect config schemas from resources that declare them.
35
32
  *
36
- * Returns entries keyed by provision ID for composition into `defineConfig`.
37
- * Provisions without a `config` schema are excluded.
33
+ * Returns entries keyed by resource ID for composition into `defineConfig`.
34
+ * Resources without a `config` schema are excluded.
38
35
  */
39
- export const collectProvisionConfigs = (
40
- provisions: readonly ProvisionWithOptionalConfig[]
41
- ): ProvisionConfigEntry[] =>
42
- provisions
36
+ export const collectResourceConfigs = (
37
+ resources: readonly ResourceWithOptionalConfig[]
38
+ ): ResourceConfigEntry[] =>
39
+ resources
43
40
  .filter(
44
41
  (
45
42
  svc
46
- ): svc is ProvisionWithOptionalConfig & { readonly config: z.ZodType } =>
43
+ ): svc is ResourceWithOptionalConfig & { readonly config: z.ZodType } =>
47
44
  svc.config !== undefined
48
45
  )
49
- .map((svc) => ({ provisionId: svc.id, schema: svc.config }));
50
-
51
- /** Backward-compatible alias while the migration is in flight. */
52
- export const collectServiceConfigs = collectProvisionConfigs;
46
+ .map((svc) => ({ resourceId: svc.id, schema: svc.config }));
@@ -1,17 +1,17 @@
1
1
  /**
2
- * Config provision — manages resolved config lifecycle.
2
+ * Config resource — manages resolved config lifecycle.
3
3
  *
4
4
  * The config is resolved during bootstrap (two-phase init per ADR-010)
5
- * and registered via `registerConfigState`. This provision reads from the
6
- * global registry so trails can access it through `configProvision.from(ctx)`.
5
+ * and registered via `registerConfigState`. This resource reads from the
6
+ * global registry so trails can access it through `configResource.from(ctx)`.
7
7
  */
8
- import { InternalError, Result, provision } from '@ontrails/core';
8
+ import { InternalError, Result, resource } from '@ontrails/core';
9
9
  import { z } from 'zod';
10
10
 
11
11
  import type { ConfigState } from './registry.js';
12
12
  import { getConfigState } from './registry.js';
13
13
 
14
- export const configProvision = provision<ConfigState>('config', {
14
+ export const configResource = resource<ConfigState>('config', {
15
15
  create: () => {
16
16
  const state = getConfigState();
17
17
  if (state === undefined) {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Trails-specific config wrapper — `appConfig('trails', ...)` with
3
- * framework conventions for loadout selection and local overrides.
3
+ * framework conventions for profile selection and local overrides.
4
4
  */
5
5
 
6
6
  import { existsSync } from 'node:fs';
@@ -9,7 +9,7 @@ import { join } from 'node:path';
9
9
  import type { z } from 'zod';
10
10
 
11
11
  import { appConfig } from './app-config.js';
12
- import { resolveConfig } from './resolve.js';
12
+ import { deriveConfig } from './resolve.js';
13
13
 
14
14
  // ---------------------------------------------------------------------------
15
15
  // Types
@@ -19,14 +19,14 @@ import { resolveConfig } from './resolve.js';
19
19
  export interface DefineConfigOptions<T extends z.ZodType> {
20
20
  readonly schema: T;
21
21
  readonly base?: Partial<z.infer<T>>;
22
- readonly loadouts?: Record<string, Partial<z.infer<T>>>;
22
+ readonly profiles?: Record<string, Partial<z.infer<T>>>;
23
23
  /** When true, fall back to `NODE_ENV` when `TRAILS_ENV` is unset. */
24
24
  readonly envFromNodeEnv?: boolean;
25
25
  }
26
26
 
27
27
  /** Options passed to `resolve()` on a defined config. */
28
28
  interface DefineConfigResolveOptions {
29
- readonly loadout?: string;
29
+ readonly profile?: string;
30
30
  readonly env?: Record<string, string | undefined>;
31
31
  /** Working directory for local overrides discovery. Defaults to `process.cwd()`. */
32
32
  readonly cwd?: string;
@@ -70,7 +70,7 @@ const discoverLocalOverrides = async (
70
70
  * Define Trails app config.
71
71
  *
72
72
  * This is `appConfig('trails', ...)` with the framework's own conventions:
73
- * `TRAILS_ENV` selects the loadout. When `envFromNodeEnv` is true,
73
+ * `TRAILS_ENV` selects the profile. When `envFromNodeEnv` is true,
74
74
  * `NODE_ENV` is used as a fallback when `TRAILS_ENV` is unset.
75
75
  *
76
76
  * @example
@@ -81,7 +81,7 @@ const discoverLocalOverrides = async (
81
81
  * debug: z.boolean().default(false),
82
82
  * }),
83
83
  * base: { port: 8080 },
84
- * loadouts: {
84
+ * profiles: {
85
85
  * production: { debug: false },
86
86
  * test: { debug: true, port: 0 },
87
87
  * },
@@ -93,15 +93,12 @@ const discoverLocalOverrides = async (
93
93
  export const defineConfig = <T extends z.ZodType>(
94
94
  options: DefineConfigOptions<T>
95
95
  ) => {
96
- const config = appConfig('trails', {
97
- formats: ['toml', 'json'],
98
- schema: options.schema,
99
- });
96
+ const config = appConfig('trails', { schema: options.schema });
100
97
 
101
98
  return {
102
99
  ...config,
103
100
  base: options.base,
104
- loadouts: options.loadouts,
101
+ profiles: options.profiles,
105
102
  resolve: async (resolveOpts?: DefineConfigResolveOptions) => {
106
103
  const envRecord = {
107
104
  ...(resolveOpts?.env ?? process.env),
@@ -118,14 +115,14 @@ export const defineConfig = <T extends z.ZodType>(
118
115
  const cwd = resolveOpts?.cwd ?? process.cwd();
119
116
  const localOverrides = await discoverLocalOverrides(cwd, envRecord);
120
117
 
121
- return resolveConfig({
118
+ return deriveConfig({
122
119
  base: options.base as Record<string, unknown> | undefined,
123
120
  env: envRecord,
124
- loadout: resolveOpts?.loadout ?? envRecord['TRAILS_ENV'],
125
- loadouts: options.loadouts as
121
+ localOverrides,
122
+ profile: resolveOpts?.profile ?? envRecord['TRAILS_ENV'],
123
+ profiles: options.profiles as
126
124
  | Record<string, Record<string, unknown>>
127
125
  | undefined,
128
- localOverrides,
129
126
  schema: options.schema,
130
127
  });
131
128
  },
@@ -15,7 +15,7 @@ import {
15
15
  formatValue,
16
16
  getDefault,
17
17
  getDescription,
18
- resolveFieldByPath,
18
+ deriveFieldByPath,
19
19
  unwrap,
20
20
  zodTypeName,
21
21
  zodTypeToJsonSchema,
@@ -76,7 +76,7 @@ const collectEnvEntries = (
76
76
  if (!fieldMeta.env) {
77
77
  continue;
78
78
  }
79
- const fieldSchema = resolveFieldByPath(schema, path);
79
+ const fieldSchema = deriveFieldByPath(schema, path);
80
80
  if (!fieldSchema) {
81
81
  continue;
82
82
  }
@@ -96,7 +96,7 @@ const collectEnvEntries = (
96
96
  * Lists each env var with its type, default, and whether it is a secret.
97
97
  * Returns an empty string when no env bindings are present.
98
98
  */
99
- export const generateEnvExample = (
99
+ export const deriveConfigEnvExample = (
100
100
  schema: z.ZodObject<Record<string, z.ZodType>>
101
101
  ): string => {
102
102
  const entries = collectEnvEntries(schema, collectConfigMeta(schema));
@@ -216,7 +216,7 @@ const formatters: Record<
216
216
  *
217
217
  * Includes descriptions as comments, defaults shown, deprecated fields annotated.
218
218
  */
219
- export const generateExample = (
219
+ export const deriveConfigExample = (
220
220
  schema: z.ZodObject<Record<string, z.ZodType>>,
221
221
  format: ExampleFormat
222
222
  ): string => formatters[format](schema);
@@ -86,7 +86,7 @@ export const getObjectShape = (
86
86
  };
87
87
 
88
88
  /** Resolve a dot-separated path to the field schema within an object. */
89
- export const resolveFieldByPath = (
89
+ export const deriveFieldByPath = (
90
90
  schema: z.ZodObject<Record<string, z.ZodType>>,
91
91
  path: string
92
92
  ): z.ZodType | undefined => {
@@ -0,0 +1,3 @@
1
+ export { deriveConfigEnvExample } from './env.js';
2
+ export { deriveConfigExample } from './example.js';
3
+ export { deriveConfigJsonSchema } from './json-schema.js';
@@ -112,7 +112,7 @@ const buildSchemaProperties = (
112
112
  * Includes descriptions, defaults, deprecated annotations, and constraints.
113
113
  * Produces JSON Schema Draft 2020-12.
114
114
  */
115
- export const generateJsonSchema = (
115
+ export const deriveConfigJsonSchema = (
116
116
  schema: z.ZodObject<Record<string, z.ZodType>>,
117
117
  options?: { readonly description?: string; readonly title?: string }
118
118
  ): Record<string, unknown> => {
@@ -228,7 +228,7 @@ const walkShapeLevel = (
228
228
  *
229
229
  * Returns a structured catalog suitable for CLI rendering or agent inspection.
230
230
  */
231
- export const describeConfig = (
231
+ export const deriveConfigFields = (
232
232
  schema: z.ZodObject<Record<string, z.ZodType>>
233
233
  ): readonly FieldDescription[] => {
234
234
  const configMeta = collectConfigMeta(schema);
@@ -18,15 +18,15 @@ import { getAtPath, isZodObject, unwrapToBase, zodDef } from './zod-utils.js';
18
18
  export interface ProvenanceEntry {
19
19
  readonly path: string;
20
20
  readonly value: unknown;
21
- readonly source: 'default' | 'base' | 'loadout' | 'local' | 'env';
21
+ readonly source: 'default' | 'base' | 'profile' | 'local' | 'env';
22
22
  readonly redacted: boolean;
23
23
  }
24
24
 
25
25
  /** Options for explaining config provenance. */
26
- export interface ExplainConfigOptions<T extends z.ZodType> {
26
+ export interface DeriveConfigProvenanceOptions<T extends z.ZodType> {
27
27
  readonly schema: T;
28
28
  readonly base?: Record<string, unknown>;
29
- readonly loadout?: Record<string, unknown>;
29
+ readonly profile?: Record<string, unknown>;
30
30
  readonly local?: Record<string, unknown>;
31
31
  readonly env?: Record<string, string | undefined>;
32
32
  readonly resolved: Record<string, unknown>;
@@ -135,8 +135,8 @@ const collectLeafPaths = (schema: z.ZodType, prefix: string): string[] => {
135
135
  * Used for debugging — answers "where did this value come from?"
136
136
  *
137
137
  */
138
- export const explainConfig = <T extends z.ZodType>(
139
- options: ExplainConfigOptions<T>
138
+ export const deriveConfigProvenance = <T extends z.ZodType>(
139
+ options: DeriveConfigProvenanceOptions<T>
140
140
  ): readonly ProvenanceEntry[] => {
141
141
  const objSchema = options.schema as unknown as z.ZodObject<
142
142
  Record<string, z.ZodType>
@@ -146,7 +146,7 @@ export const explainConfig = <T extends z.ZodType>(
146
146
 
147
147
  const sources: readonly SourceEntry[] = [
148
148
  ['local', options.local],
149
- ['loadout', options.loadout],
149
+ ['profile', options.profile],
150
150
  ['base', options.base],
151
151
  ];
152
152
 
package/src/index.ts CHANGED
@@ -1,20 +1,15 @@
1
1
  export {
2
2
  appConfig,
3
3
  type AppConfig,
4
- type AppConfigExplainOptions,
4
+ type AppConfigDeriveProvenanceOptions,
5
5
  type AppConfigOptions,
6
6
  type ConfigFormat,
7
7
  type ResolveOptions,
8
8
  } from './app-config.js';
9
9
  export { collectConfigMeta } from './collect.js';
10
- export {
11
- collectProvisionConfigs,
12
- collectServiceConfigs,
13
- type ProvisionConfigEntry,
14
- type ServiceConfigEntry,
15
- } from './compose.js';
10
+ export { collectResourceConfigs, type ResourceConfigEntry } from './compose.js';
16
11
  export { defineConfig, type DefineConfigOptions } from './define-config.js';
17
- export { describeConfig, type FieldDescription } from './describe.js';
12
+ export { deriveConfigFields, type FieldDescription } from './derive-fields.js';
18
13
  export {
19
14
  checkConfig,
20
15
  type CheckResult,
@@ -22,17 +17,16 @@ export {
22
17
  } from './doctor.js';
23
18
  export { env, secret, deprecated, type ConfigFieldMeta } from './extensions.js';
24
19
  export {
25
- explainConfig,
26
- type ExplainConfigOptions,
20
+ deriveConfigProvenance,
21
+ type DeriveConfigProvenanceOptions,
27
22
  type ProvenanceEntry,
28
- } from './explain.js';
23
+ } from './derive-provenance.js';
29
24
  export {
30
- generateEnvExample,
31
- generateExample,
32
- generateJsonSchema,
33
- } from './generate/index.js';
34
- export { configGate } from './config-gate.js';
35
- export { configProvision } from './config-provision.js';
25
+ deriveConfigEnvExample,
26
+ deriveConfigExample,
27
+ deriveConfigJsonSchema,
28
+ } from './derive/index.js';
29
+ export { configResource } from './config-resource.js';
36
30
  export {
37
31
  clearConfigState,
38
32
  type ConfigState,
@@ -41,7 +35,7 @@ export {
41
35
  } from './registry.js';
42
36
  export { deepMerge } from './merge.js';
43
37
  export { configRef, isConfigRef, type ConfigRef } from './ref.js';
44
- export { resolveConfig, type ResolveConfigOptions } from './resolve.js';
38
+ export { deriveConfig, type DeriveConfigOptions } from './resolve.js';
45
39
  export { configCheck } from './trails/config-check.js';
46
40
  export { configDescribe } from './trails/config-describe.js';
47
41
  export { configExplain } from './trails/config-explain.js';
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 `configProvision` can expose it to trailheads. This is
5
+ * registered here so `configResource` can expose it to trailheads. 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 loadout?: Record<string, unknown>;
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,6 +1,6 @@
1
1
  /**
2
2
  * Config resolution engine — merges config from multiple sources through
3
- * a deterministic stack: defaults → base → loadout → local → env.
3
+ * a deterministic stack: defaults → base → profile → local → env.
4
4
  */
5
5
 
6
6
  import type { z } from 'zod';
@@ -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 ResolveConfigOptions<T extends z.ZodType> {
19
+ export interface DeriveConfigOptions<T extends z.ZodType> {
20
20
  readonly schema: T;
21
21
  readonly base?: Record<string, unknown> | undefined;
22
- readonly loadouts?: Record<string, Record<string, unknown>> | undefined;
23
- readonly loadout?: string | undefined;
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 → loadout → local overrides. */
222
+ /** Apply the layered merge: base → profile → local overrides. */
223
223
  const mergeLayers = (
224
224
  base: Record<string, unknown> | undefined,
225
- loadouts: Record<string, Record<string, unknown>> | undefined,
226
- loadout: string | undefined,
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 = loadout && loadouts ? loadouts[loadout] : undefined;
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
- * Resolve config through the full stack: defaults → base → loadout → local → env.
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 resolveConfig = <T extends z.ZodType>(
260
- options: ResolveConfigOptions<T>
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.loadouts,
265
- options.loadout,
264
+ options.profiles,
265
+ options.profile,
266
266
  options.localOverrides
267
267
  );
268
268
 
@@ -7,7 +7,7 @@
7
7
  import { Result, trail } from '@ontrails/core';
8
8
  import { z } from 'zod';
9
9
 
10
- import { configProvision } from '../config-provision.js';
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 = configProvision.from(ctx);
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
- provisions: [configProvision],
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 { configProvision } from '../config-provision.js';
11
- import { describeConfig } from '../describe.js';
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 = configProvision.from(ctx);
30
- const fields = describeConfig(state.schema);
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
- provisions: [configProvision],
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 { configProvision } from '../config-provision.js';
11
- import type { ExplainConfigOptions } from '../explain.js';
12
- import { explainConfig } from '../explain.js';
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 ExplainConfigOptions from ConfigState, omitting undefined source overrides. */
37
+ /** Build DeriveConfigProvenanceOptions from ConfigState, omitting undefined source overrides. */
38
38
  const toExplainOptions = (
39
39
  state: ConfigState
40
- ): ExplainConfigOptions<typeof state.schema> => {
41
- const base: ExplainConfigOptions<typeof state.schema> = {
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: ExplainConfigOptions<typeof state.schema>
55
- ): ExplainConfigOptions<typeof state.schema> => {
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.loadout) {
61
- enriched = { ...enriched, loadout: state.loadout };
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 = configProvision.from(ctx);
71
+ const state = configResource.from(ctx);
72
72
  const options = enrichOptions(state, toExplainOptions(state));
73
- const entries = explainConfig(options);
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
- provisions: [configProvision],
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 { configProvision } from '../config-provision.js';
17
+ import { configResource } from '../config-resource.js';
18
18
  import {
19
- generateEnvExample,
20
- generateExample,
21
- generateJsonSchema,
22
- } from '../generate/index.js';
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 = generateEnvExample(schema);
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(generateJsonSchema(schema), null, 2),
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 = configProvision.from(ctx);
66
+ const state = configResource.from(ctx);
67
67
  const schema = state.schema as z.ZodObject<Record<string, z.ZodType>>;
68
- const content = generateExample(schema, input.format);
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
- provisions: [configProvision],
95
+ resources: [configResource],
96
96
  });
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": true,
5
+ "rootDir": "./src",
6
+ "types": ["bun"]
7
+ },
8
+ "include": ["src/**/*.test.ts", "src/__tests__/**/*.ts"],
9
+ "exclude": []
10
+ }
@@ -1 +1 @@
1
- {"root":["./src/app-config.ts","./src/collect.ts","./src/compose.ts","./src/config-gate.ts","./src/config-provision.ts","./src/define-config.ts","./src/describe.ts","./src/doctor.ts","./src/explain.ts","./src/extensions.ts","./src/index.ts","./src/merge.ts","./src/ref.ts","./src/registry.ts","./src/resolve.ts","./src/secret-heuristics.ts","./src/workspace.ts","./src/zod-utils.ts","./src/generate/env.ts","./src/generate/example.ts","./src/generate/helpers.ts","./src/generate/index.ts","./src/generate/json-schema.ts","./src/trails/config-check.ts","./src/trails/config-describe.ts","./src/trails/config-explain.ts","./src/trails/config-init.ts"],"version":"5.9.3"}
1
+ {"root":["./src/app-config.ts","./src/collect.ts","./src/compose.ts","./src/config-resource.ts","./src/define-config.ts","./src/derive-fields.ts","./src/derive-provenance.ts","./src/doctor.ts","./src/extensions.ts","./src/index.ts","./src/merge.ts","./src/ref.ts","./src/registry.ts","./src/resolve.ts","./src/secret-heuristics.ts","./src/workspace.ts","./src/zod-utils.ts","./src/derive/env.ts","./src/derive/example.ts","./src/derive/helpers.ts","./src/derive/index.ts","./src/derive/json-schema.ts","./src/trails/config-check.ts","./src/trails/config-describe.ts","./src/trails/config-explain.ts","./src/trails/config-init.ts"],"version":"5.9.3"}
@@ -1,11 +0,0 @@
1
- /**
2
- * Config gate — attaches resolved config to the execution context.
3
- *
4
- * For v1, the gate is a pass-through: config resolution happens at
5
- * bootstrap time and the provision pipeline (TRL-91) injects the resolved
6
- * config before any trail runs. The gate reserves a named slot so future
7
- * versions can add per-trail config overrides or validation.
8
- */
9
- import type { Gate } from '@ontrails/core';
10
- export declare const configGate: Gate;
11
- //# sourceMappingURL=config-gate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-gate.d.ts","sourceRoot":"","sources":["../src/config-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE3C,eAAO,MAAM,UAAU,EAAE,IAIxB,CAAC"}
@@ -1,6 +0,0 @@
1
- export const configGate = {
2
- description: 'Ensures resolved config is available in the execution context',
3
- name: 'config',
4
- wrap: (_trail, impl) => (input, ctx) => impl(input, ctx),
5
- };
6
- //# sourceMappingURL=config-gate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-gate.js","sourceRoot":"","sources":["../src/config-gate.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,WAAW,EAAE,+DAA+D;IAC5E,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC;CACzD,CAAC"}