@mudah-cli/config 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
+ import { type Schema, type SchemaResult } from './schema.js';
1
2
  /**
2
3
  * Dotted-key configuration repository.
3
4
  *
@@ -24,4 +25,12 @@ export declare class ConfigRepository {
24
25
  merge(key: string, defaults: Record<string, unknown>): this;
25
26
  /** Replace the entire configuration tree. */
26
27
  clear(): this;
28
+ /**
29
+ * Check a subtree against `schema`. Reports every problem at once, with
30
+ * paths relative to `key` (`db.pool` for `validate('db', …)`).
31
+ *
32
+ * Use at boot: a config typo then fails loudly instead of surfacing as a
33
+ * confusing `undefined` three layers down.
34
+ */
35
+ validate<T>(key: string, schema: Schema<T>): SchemaResult<T>;
27
36
  }
@@ -1,4 +1,5 @@
1
1
  import { assignPath, deepMerge, hasPath, isPlainObject, readPath, removePath } from './paths.js';
2
+ import { validateSchema } from './schema.js';
2
3
  /**
3
4
  * Dotted-key configuration repository.
4
5
  *
@@ -44,5 +45,16 @@ export class ConfigRepository {
44
45
  this.root = {};
45
46
  return this;
46
47
  }
48
+ /**
49
+ * Check a subtree against `schema`. Reports every problem at once, with
50
+ * paths relative to `key` (`db.pool` for `validate('db', …)`).
51
+ *
52
+ * Use at boot: a config typo then fails loudly instead of surfacing as a
53
+ * confusing `undefined` three layers down.
54
+ */
55
+ validate(key, schema) {
56
+ const value = key === '' ? this.root : this.get(key, undefined);
57
+ return validateSchema(schema, value, key);
58
+ }
47
59
  }
48
60
  //# sourceMappingURL=config-repository.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-repository.js","sourceRoot":"","sources":["../src/config-repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEjG;;;;;;GAMG;AACH,MAAM,OAAO,gBAAgB;IACnB,IAAI,GAA4B,EAAE,CAAC;IAE3C,4EAA4E;IAC5E,GAAG,CAAC,GAAW,EAAE,KAAc;QAC7B,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oEAAoE;IACpE,GAAG,CAAc,GAAW,EAAE,YAAgB;QAC5C,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,YAAY,CAAM,CAAC;IACrD,CAAC;IAED,0CAA0C;IAC1C,GAAG,CAAC,GAAW;QACb,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,iEAAiE;IACjE,MAAM,CAAC,GAAW;QAChB,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACpC,CAAC;IAED,qEAAqE;IACrE,GAAG;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAW,EAAE,QAAiC;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAsC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/E,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6CAA6C;IAC7C,KAAK;QACH,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
1
+ {"version":3,"file":"config-repository.js","sourceRoot":"","sources":["../src/config-repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjG,OAAO,EAAE,cAAc,EAAkC,MAAM,aAAa,CAAC;AAE7E;;;;;;GAMG;AACH,MAAM,OAAO,gBAAgB;IACnB,IAAI,GAA4B,EAAE,CAAC;IAE3C,4EAA4E;IAC5E,GAAG,CAAC,GAAW,EAAE,KAAc;QAC7B,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oEAAoE;IACpE,GAAG,CAAc,GAAW,EAAE,YAAgB;QAC5C,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,YAAY,CAAM,CAAC;IACrD,CAAC;IAED,0CAA0C;IAC1C,GAAG,CAAC,GAAW;QACb,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,iEAAiE;IACjE,MAAM,CAAC,GAAW;QAChB,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACpC,CAAC;IAED,qEAAqE;IACrE,GAAG;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAW,EAAE,QAAiC;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAsC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/E,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6CAA6C;IAC7C,KAAK;QACH,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;OAMG;IACH,QAAQ,CAAI,GAAW,EAAE,MAAiB;QACxC,MAAM,KAAK,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAChE,OAAO,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5C,CAAC;CACF"}
@@ -1,3 +1,4 @@
1
+ import { type Schema } from './schema.js';
1
2
  /**
2
3
  * Define a typed configuration file. Identity at runtime — the value exists
3
4
  * for type inference, giving apps full completion on `config.get('app.x')`
@@ -12,3 +13,14 @@
12
13
  * ```
13
14
  */
14
15
  export declare function defineConfig<T extends Record<string, unknown>>(config: T): T;
16
+ /**
17
+ * Define a validated configuration file. The schema runs immediately, so a
18
+ * bad config fails at import time with every offending key listed.
19
+ *
20
+ * ```ts
21
+ * export default defineConfig(s.object({ url: s.string(), pool: s.number().default(5) }), {
22
+ * url: env('DATABASE_URL', 'sqlite:///local.db'),
23
+ * });
24
+ * ```
25
+ */
26
+ export declare function defineConfig<T>(schema: Schema<T>, config: unknown): T;
@@ -1,17 +1,14 @@
1
- /**
2
- * Define a typed configuration file. Identity at runtime — the value exists
3
- * for type inference, giving apps full completion on `config.get('app.x')`
4
- * when the config file is typed.
5
- *
6
- * ```ts
7
- * // config/app.ts
8
- * export default defineConfig({
9
- * name: 'my-cli',
10
- * env: env('APP_ENV', 'production'),
11
- * });
12
- * ```
13
- */
14
- export function defineConfig(config) {
15
- return config;
1
+ import { assertSchema } from './schema.js';
2
+ export function defineConfig(schemaOrConfig, config) {
3
+ if (isSchema(schemaOrConfig)) {
4
+ return assertSchema(schemaOrConfig, config);
5
+ }
6
+ return schemaOrConfig;
7
+ }
8
+ function isSchema(value) {
9
+ return (typeof value === 'object' &&
10
+ value !== null &&
11
+ typeof value.parse === 'function' &&
12
+ typeof value.type === 'string');
16
13
  }
17
14
  //# sourceMappingURL=define-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"define-config.js","sourceRoot":"","sources":["../src/define-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAoC,MAAS;IACvE,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"define-config.js","sourceRoot":"","sources":["../src/define-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AA2BxD,MAAM,UAAU,YAAY,CAAI,cAA6B,EAAE,MAAgB;IAC7E,IAAI,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QAC7B,OAAO,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,SAAS,QAAQ,CAAI,KAA0B;IAC7C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,OAAQ,KAAmB,CAAC,KAAK,KAAK,UAAU;QAChD,OAAQ,KAAmB,CAAC,IAAI,KAAK,QAAQ,CAC9C,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -3,3 +3,4 @@ export { defineConfig } from './define-config.js';
3
3
  export { env, loadEnvFile } from './env.js';
4
4
  export { loadConfigFiles, type LoadConfigOptions } from './load-config-files.js';
5
5
  export { deepMerge, isPlainObject } from './paths.js';
6
+ export { assertSchema, ConfigValidationError, s, validateSchema, type AnySchemaBuilder, type ArraySchemaBuilder, type BooleanSchemaBuilder, type NumberSchemaBuilder, type ObjectShape, type ObjectSchemaBuilder, type Schema, type SchemaIssue, type SchemaResult, type StringSchemaBuilder, } from './schema.js';
package/dist/index.js CHANGED
@@ -3,4 +3,5 @@ export { defineConfig } from './define-config.js';
3
3
  export { env, loadEnvFile } from './env.js';
4
4
  export { loadConfigFiles } from './load-config-files.js';
5
5
  export { deepMerge, isPlainObject } from './paths.js';
6
+ export { assertSchema, ConfigValidationError, s, validateSchema, } from './schema.js';
6
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,eAAe,EAA0B,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,eAAe,EAA0B,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,CAAC,EACD,cAAc,GAWf,MAAM,aAAa,CAAC"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Minimal, zero-dependency config schema validation.
3
+ *
4
+ * Schemas describe the shape of a config file, validate it at boot, and
5
+ * report every problem at once with dotted paths (`db.pool`) instead of
6
+ * failing on the first bad key.
7
+ *
8
+ * ```ts
9
+ * // config/database.ts
10
+ * import { defineConfig, s } from '@mudah-cli/config';
11
+ *
12
+ * export default defineConfig(
13
+ * s.object({
14
+ * url: s.string(),
15
+ * pool: s.number().min(1).default(5),
16
+ * ssl: s.boolean().default(false),
17
+ * }),
18
+ * );
19
+ * ```
20
+ */
21
+ export interface SchemaIssue {
22
+ /** Dotted path to the offending value (`db.pool`, `servers.0.host`). */
23
+ readonly path: string;
24
+ /** What went wrong. */
25
+ readonly message: string;
26
+ }
27
+ export interface SchemaResult<T> {
28
+ readonly ok: boolean;
29
+ /** The parsed value: coerced, defaults filled in. Only valid when `ok`. */
30
+ readonly value: T;
31
+ /** Every problem found, in document order. Empty when `ok`. */
32
+ readonly issues: readonly SchemaIssue[];
33
+ }
34
+ export declare class ConfigValidationError extends Error {
35
+ readonly issues: readonly SchemaIssue[];
36
+ constructor(issues: readonly SchemaIssue[]);
37
+ }
38
+ /** What every schema node exposes. */
39
+ export interface Schema<T> {
40
+ readonly type: string;
41
+ /** True when a missing value is acceptable (via `optional()`/`default()`). */
42
+ readonly isOptional: boolean;
43
+ /** Human-readable type name used in error messages. */
44
+ readonly label: string;
45
+ /** Validate (and coerce) an unknown value. Returns issues; never throws. */
46
+ parse(value: unknown, path: string, issues: SchemaIssue[]): T;
47
+ /** Whether a missing value is acceptable for this node. */
48
+ acceptsMissing(): boolean;
49
+ /** The value this node contributes when nothing is supplied. */
50
+ fallback(): T | undefined;
51
+ /** Documentation string set by `describe()`, when present. */
52
+ describeText(): string | undefined;
53
+ }
54
+ type ObjectShape = Record<string, Schema<unknown>>;
55
+ type ObjectOutput<S extends ObjectShape> = {
56
+ [K in keyof S]: S[K] extends Schema<infer V> ? V : never;
57
+ };
58
+ /**
59
+ * Fluent builders. Each returns the public interface, not the class, so a
60
+ * schema can be exported from a module (declaration emit can't describe a
61
+ * class with private state).
62
+ */
63
+ export interface StringSchemaBuilder extends Schema<string> {
64
+ min(length: number): StringSchemaBuilder;
65
+ max(length: number): StringSchemaBuilder;
66
+ match(pattern: RegExp): StringSchemaBuilder;
67
+ optional(): StringSchemaBuilder;
68
+ default(value: string): StringSchemaBuilder;
69
+ describe(text: string): StringSchemaBuilder;
70
+ }
71
+ export interface NumberSchemaBuilder extends Schema<number> {
72
+ min(value: number): NumberSchemaBuilder;
73
+ max(value: number): NumberSchemaBuilder;
74
+ int(): NumberSchemaBuilder;
75
+ optional(): NumberSchemaBuilder;
76
+ default(value: number): NumberSchemaBuilder;
77
+ describe(text: string): NumberSchemaBuilder;
78
+ }
79
+ export interface BooleanSchemaBuilder extends Schema<boolean> {
80
+ optional(): BooleanSchemaBuilder;
81
+ default(value: boolean): BooleanSchemaBuilder;
82
+ describe(text: string): BooleanSchemaBuilder;
83
+ }
84
+ export interface ArraySchemaBuilder<T> extends Schema<T[]> {
85
+ min(length: number): ArraySchemaBuilder<T>;
86
+ max(length: number): ArraySchemaBuilder<T>;
87
+ optional(): ArraySchemaBuilder<T>;
88
+ default(value: T[]): ArraySchemaBuilder<T>;
89
+ describe(text: string): ArraySchemaBuilder<T>;
90
+ }
91
+ export interface ObjectSchemaBuilder<S extends ObjectShape> extends Schema<ObjectOutput<S>> {
92
+ /** Reject keys the schema doesn't declare. */
93
+ strict(): ObjectSchemaBuilder<S>;
94
+ optional(): ObjectSchemaBuilder<S>;
95
+ default(value: ObjectOutput<S>): ObjectSchemaBuilder<S>;
96
+ describe(text: string): ObjectSchemaBuilder<S>;
97
+ readonly shape: S;
98
+ }
99
+ export interface AnySchemaBuilder extends Schema<unknown> {
100
+ optional(): AnySchemaBuilder;
101
+ default(value: unknown): AnySchemaBuilder;
102
+ describe(text: string): AnySchemaBuilder;
103
+ }
104
+ /** Schema builders. Compose them into `s.object({ … })`. */
105
+ export declare const s: {
106
+ string(): StringSchemaBuilder;
107
+ /** A string restricted to `values`. */
108
+ enum<T extends string>(values: readonly T[]): StringSchemaBuilder;
109
+ number(): NumberSchemaBuilder;
110
+ boolean(): BooleanSchemaBuilder;
111
+ array<T>(item: Schema<T>): ArraySchemaBuilder<T>;
112
+ object<S extends ObjectShape>(shape: S): ObjectSchemaBuilder<S>;
113
+ /** Accept anything at this key. */
114
+ any(): AnySchemaBuilder;
115
+ };
116
+ /** Validate `value` against `schema`. Collects every issue; never throws. */
117
+ export declare function validateSchema<T>(schema: Schema<T>, value: unknown, path?: string): SchemaResult<T>;
118
+ /**
119
+ * Validate and throw a `ConfigValidationError` when anything is wrong. Use
120
+ * this at boot — one error listing every bad key beats failing on the first.
121
+ */
122
+ export declare function assertSchema<T>(schema: Schema<T>, value: unknown, path?: string): T;
123
+ export type { ObjectShape };
package/dist/schema.js ADDED
@@ -0,0 +1,297 @@
1
+ /**
2
+ * Minimal, zero-dependency config schema validation.
3
+ *
4
+ * Schemas describe the shape of a config file, validate it at boot, and
5
+ * report every problem at once with dotted paths (`db.pool`) instead of
6
+ * failing on the first bad key.
7
+ *
8
+ * ```ts
9
+ * // config/database.ts
10
+ * import { defineConfig, s } from '@mudah-cli/config';
11
+ *
12
+ * export default defineConfig(
13
+ * s.object({
14
+ * url: s.string(),
15
+ * pool: s.number().min(1).default(5),
16
+ * ssl: s.boolean().default(false),
17
+ * }),
18
+ * );
19
+ * ```
20
+ */
21
+ export class ConfigValidationError extends Error {
22
+ issues;
23
+ constructor(issues) {
24
+ super(`Invalid configuration:\n${issues.map((i) => ` ${i.path === '' ? '(root)' : i.path}: ${i.message}`).join('\n')}`);
25
+ this.name = 'ConfigValidationError';
26
+ this.issues = issues;
27
+ }
28
+ }
29
+ class BaseSchema {
30
+ isOptional = false;
31
+ defaulted = undefined;
32
+ documented = undefined;
33
+ /** Allow this key to be missing. */
34
+ optional() {
35
+ this.isOptional = true;
36
+ return this;
37
+ }
38
+ /** Value used when the key is absent. Implies optional. */
39
+ default(value) {
40
+ this.defaulted = { value };
41
+ this.isOptional = true;
42
+ return this;
43
+ }
44
+ /** Documentation only — surfaced by `describeText()`. */
45
+ describe(text) {
46
+ this.documented = text;
47
+ return this;
48
+ }
49
+ acceptsMissing() {
50
+ return this.isOptional;
51
+ }
52
+ fallback() {
53
+ return this.defaulted?.value;
54
+ }
55
+ describeText() {
56
+ return this.documented;
57
+ }
58
+ /** Run the checks common to every node, then the node's own rules. */
59
+ parse(value, path, issues) {
60
+ if (value === undefined) {
61
+ const fallback = this.fallback();
62
+ if (fallback !== undefined)
63
+ return fallback;
64
+ if (!this.isOptional) {
65
+ issues.push({ path, message: `is required` });
66
+ }
67
+ return undefined;
68
+ }
69
+ return this.check(value, path, issues);
70
+ }
71
+ fail(issues, path, message) {
72
+ issues.push({ path, message });
73
+ }
74
+ }
75
+ class StringSchema extends BaseSchema {
76
+ type = 'string';
77
+ label = 'string';
78
+ minLength;
79
+ maxLength;
80
+ pattern;
81
+ allowed;
82
+ constructor(allowed) {
83
+ super();
84
+ this.allowed = allowed;
85
+ }
86
+ min(length) {
87
+ this.minLength = length;
88
+ return this;
89
+ }
90
+ max(length) {
91
+ this.maxLength = length;
92
+ return this;
93
+ }
94
+ match(pattern) {
95
+ this.pattern = pattern;
96
+ return this;
97
+ }
98
+ check(value, path, issues) {
99
+ if (typeof value !== 'string') {
100
+ this.fail(issues, path, `expected string, got ${typeName(value)}`);
101
+ return '';
102
+ }
103
+ if (this.minLength !== undefined && value.length < this.minLength) {
104
+ this.fail(issues, path, `must be at least ${this.minLength} characters`);
105
+ }
106
+ if (this.maxLength !== undefined && value.length > this.maxLength) {
107
+ this.fail(issues, path, `must be at most ${this.maxLength} characters`);
108
+ }
109
+ if (this.pattern !== undefined && !this.pattern.test(value)) {
110
+ this.fail(issues, path, `must match ${String(this.pattern)}`);
111
+ }
112
+ if (this.allowed !== undefined && !this.allowed.includes(value)) {
113
+ this.fail(issues, path, `must be one of: ${this.allowed.join(', ')}`);
114
+ }
115
+ return value;
116
+ }
117
+ }
118
+ class NumberSchema extends BaseSchema {
119
+ type = 'number';
120
+ label = 'number';
121
+ minimum;
122
+ maximum;
123
+ integerOnly = false;
124
+ min(value) {
125
+ this.minimum = value;
126
+ return this;
127
+ }
128
+ max(value) {
129
+ this.maximum = value;
130
+ return this;
131
+ }
132
+ int() {
133
+ this.integerOnly = true;
134
+ return this;
135
+ }
136
+ check(value, path, issues) {
137
+ if (typeof value !== 'number' || Number.isNaN(value)) {
138
+ this.fail(issues, path, `expected number, got ${typeName(value)}`);
139
+ return 0;
140
+ }
141
+ if (this.integerOnly && !Number.isInteger(value)) {
142
+ this.fail(issues, path, `must be an integer`);
143
+ }
144
+ if (this.minimum !== undefined && value < this.minimum) {
145
+ this.fail(issues, path, `must be >= ${this.minimum}`);
146
+ }
147
+ if (this.maximum !== undefined && value > this.maximum) {
148
+ this.fail(issues, path, `must be <= ${this.maximum}`);
149
+ }
150
+ return value;
151
+ }
152
+ }
153
+ class BooleanSchema extends BaseSchema {
154
+ type = 'boolean';
155
+ label = 'boolean';
156
+ check(value, path, issues) {
157
+ if (typeof value !== 'boolean') {
158
+ this.fail(issues, path, `expected boolean, got ${typeName(value)}`);
159
+ return false;
160
+ }
161
+ return value;
162
+ }
163
+ }
164
+ class ArraySchema extends BaseSchema {
165
+ item;
166
+ type = 'array';
167
+ label = 'array';
168
+ minimum;
169
+ maximum;
170
+ constructor(item) {
171
+ super();
172
+ this.item = item;
173
+ }
174
+ min(length) {
175
+ this.minimum = length;
176
+ return this;
177
+ }
178
+ max(length) {
179
+ this.maximum = length;
180
+ return this;
181
+ }
182
+ check(value, path, issues) {
183
+ if (!Array.isArray(value)) {
184
+ this.fail(issues, path, `expected array, got ${typeName(value)}`);
185
+ return [];
186
+ }
187
+ if (this.minimum !== undefined && value.length < this.minimum) {
188
+ this.fail(issues, path, `must have at least ${this.minimum} item(s)`);
189
+ }
190
+ if (this.maximum !== undefined && value.length > this.maximum) {
191
+ this.fail(issues, path, `must have at most ${this.maximum} item(s)`);
192
+ }
193
+ return value.map((entry, index) => this.item.parse(entry, `${path}.${index}`, issues));
194
+ }
195
+ }
196
+ class ObjectSchema extends BaseSchema {
197
+ shape;
198
+ type = 'object';
199
+ label = 'object';
200
+ strictMode = false;
201
+ constructor(shape) {
202
+ super();
203
+ this.shape = shape;
204
+ }
205
+ /** Reject keys the schema doesn't declare. */
206
+ strict() {
207
+ this.strictMode = true;
208
+ return this;
209
+ }
210
+ check(value, path, issues) {
211
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
212
+ this.fail(issues, path, `expected object, got ${typeName(value)}`);
213
+ return {};
214
+ }
215
+ const source = value;
216
+ const output = {};
217
+ for (const [key, node] of Object.entries(this.shape)) {
218
+ const childPath = path === '' ? key : `${path}.${key}`;
219
+ const present = Object.prototype.hasOwnProperty.call(source, key);
220
+ const parsed = node.parse(present ? source[key] : undefined, childPath, issues);
221
+ if (present || parsed !== undefined)
222
+ output[key] = parsed;
223
+ }
224
+ if (this.strictMode) {
225
+ for (const key of Object.keys(source)) {
226
+ if (!(key in this.shape)) {
227
+ this.fail(issues, path === '' ? key : `${path}.${key}`, `is not a known key`);
228
+ }
229
+ }
230
+ }
231
+ else {
232
+ // Keep undeclared keys so partial schemas don't silently drop config.
233
+ for (const key of Object.keys(source)) {
234
+ if (!(key in this.shape))
235
+ output[key] = source[key];
236
+ }
237
+ }
238
+ return output;
239
+ }
240
+ }
241
+ class AnySchema extends BaseSchema {
242
+ type = 'any';
243
+ label = 'any';
244
+ check(value) {
245
+ return value;
246
+ }
247
+ }
248
+ function typeName(value) {
249
+ if (value === null)
250
+ return 'null';
251
+ if (Array.isArray(value))
252
+ return 'array';
253
+ return typeof value;
254
+ }
255
+ /** Schema builders. Compose them into `s.object({ … })`. */
256
+ export const s = {
257
+ string() {
258
+ return new StringSchema();
259
+ },
260
+ /** A string restricted to `values`. */
261
+ enum(values) {
262
+ return new StringSchema(values);
263
+ },
264
+ number() {
265
+ return new NumberSchema();
266
+ },
267
+ boolean() {
268
+ return new BooleanSchema();
269
+ },
270
+ array(item) {
271
+ return new ArraySchema(item);
272
+ },
273
+ object(shape) {
274
+ return new ObjectSchema(shape);
275
+ },
276
+ /** Accept anything at this key. */
277
+ any() {
278
+ return new AnySchema();
279
+ },
280
+ };
281
+ /** Validate `value` against `schema`. Collects every issue; never throws. */
282
+ export function validateSchema(schema, value, path = '') {
283
+ const issues = [];
284
+ const parsed = schema.parse(value, path, issues);
285
+ return { ok: issues.length === 0, value: parsed, issues };
286
+ }
287
+ /**
288
+ * Validate and throw a `ConfigValidationError` when anything is wrong. Use
289
+ * this at boot — one error listing every bad key beats failing on the first.
290
+ */
291
+ export function assertSchema(schema, value, path = '') {
292
+ const result = validateSchema(schema, value, path);
293
+ if (!result.ok)
294
+ throw new ConfigValidationError(result.issues);
295
+ return result.value;
296
+ }
297
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mudah-cli/config",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Typed configuration repository, .env loading, and dotted-key access.",
5
5
  "type": "module",
6
6
  "license": "MIT",