@theunwalked/cardigantime 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/cardigantime.cjs +107 -110
- package/dist/cardigantime.cjs.map +1 -1
- package/dist/cardigantime.js +1 -1
- package/dist/cardigantime.js.map +1 -1
- package/dist/error/ArgumentError.js +14 -14
- package/dist/error/ArgumentError.js.map +1 -1
- package/dist/error/ConfigurationError.js +4 -4
- package/dist/error/ConfigurationError.js.map +1 -1
- package/dist/error/FileSystemError.js +4 -4
- package/dist/error/FileSystemError.js.map +1 -1
- package/dist/read.js +4 -2
- package/dist/read.js.map +1 -1
- package/dist/types.d.ts +3 -14
- package/dist/util/schema-defaults.d.ts +27 -9
- package/dist/util/schema-defaults.js +48 -45
- package/dist/util/schema-defaults.js.map +1 -1
- package/dist/validate.js +31 -39
- package/dist/validate.js.map +1 -1
- package/package.json +33 -30
package/README.md
CHANGED
|
@@ -29,9 +29,9 @@ Cardigantime provides a complete, battle-tested solution for all of this complex
|
|
|
29
29
|
```bash
|
|
30
30
|
npm install @theunwalked/cardigantime
|
|
31
31
|
# or
|
|
32
|
-
pnpm add @theunwalked/cardigantime
|
|
33
|
-
# or
|
|
34
32
|
yarn add @theunwalked/cardigantime
|
|
33
|
+
# or
|
|
34
|
+
pnpm add @theunwalked/cardigantime
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
## Quick Start
|
|
@@ -149,16 +149,16 @@ Comprehensive error handling with detailed, actionable error messages to help us
|
|
|
149
149
|
|
|
150
150
|
## Documentation
|
|
151
151
|
|
|
152
|
-
📚 **[Complete Documentation](https://
|
|
152
|
+
📚 **[Complete Documentation](https://tobrien.github.io/cardigantime/)** - Full documentation site
|
|
153
153
|
|
|
154
154
|
**Quick Links:**
|
|
155
|
-
- [Getting Started Guide](https://
|
|
156
|
-
- [Core Concepts](https://
|
|
157
|
-
- [API Reference](https://
|
|
158
|
-
- [Configuration Options](https://
|
|
159
|
-
- [Debugging & Analysis](https://
|
|
160
|
-
- [Advanced Usage](https://
|
|
161
|
-
- [Error Handling](https://
|
|
155
|
+
- [Getting Started Guide](https://tobrien.github.io/cardigantime/#getting-started) - Detailed setup and basic concepts
|
|
156
|
+
- [Core Concepts](https://tobrien.github.io/cardigantime/#core-concepts) - Configuration sources, hierarchical discovery
|
|
157
|
+
- [API Reference](https://tobrien.github.io/cardigantime/#api-reference) - Complete API documentation
|
|
158
|
+
- [Configuration Options](https://tobrien.github.io/cardigantime/#configuration-options) - All available options
|
|
159
|
+
- [Debugging & Analysis](https://tobrien.github.io/cardigantime/#debugging-analysis) - Tools for analyzing config
|
|
160
|
+
- [Advanced Usage](https://tobrien.github.io/cardigantime/#advanced-usage) - Complex examples and scenarios
|
|
161
|
+
- [Error Handling](https://tobrien.github.io/cardigantime/#error-handling) - Comprehensive error handling guide
|
|
162
162
|
|
|
163
163
|
## Contributing
|
|
164
164
|
|
package/dist/cardigantime.cjs
CHANGED
|
@@ -30,6 +30,19 @@ const yaml__namespace = /*#__PURE__*/_interopNamespaceDefault(yaml);
|
|
|
30
30
|
const path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
31
31
|
const fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
32
32
|
|
|
33
|
+
function _define_property$2(obj, key, value) {
|
|
34
|
+
if (key in obj) {
|
|
35
|
+
Object.defineProperty(obj, key, {
|
|
36
|
+
value: value,
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
writable: true
|
|
40
|
+
});
|
|
41
|
+
} else {
|
|
42
|
+
obj[key] = value;
|
|
43
|
+
}
|
|
44
|
+
return obj;
|
|
45
|
+
}
|
|
33
46
|
/**
|
|
34
47
|
* Error thrown when CLI arguments or function parameters are invalid.
|
|
35
48
|
*
|
|
@@ -43,20 +56,7 @@ const fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
|
43
56
|
* // Error message: "Path cannot be empty"
|
|
44
57
|
* // error.argument: "config-directory"
|
|
45
58
|
* ```
|
|
46
|
-
*/
|
|
47
|
-
if (key in obj) {
|
|
48
|
-
Object.defineProperty(obj, key, {
|
|
49
|
-
value: value,
|
|
50
|
-
enumerable: true,
|
|
51
|
-
configurable: true,
|
|
52
|
-
writable: true
|
|
53
|
-
});
|
|
54
|
-
} else {
|
|
55
|
-
obj[key] = value;
|
|
56
|
-
}
|
|
57
|
-
return obj;
|
|
58
|
-
}
|
|
59
|
-
class ArgumentError extends Error {
|
|
59
|
+
*/ class ArgumentError extends Error {
|
|
60
60
|
/**
|
|
61
61
|
* Gets the name of the argument that caused this error.
|
|
62
62
|
*
|
|
@@ -217,9 +217,7 @@ class ArgumentError extends Error {
|
|
|
217
217
|
silly: ()=>{}
|
|
218
218
|
};
|
|
219
219
|
|
|
220
|
-
|
|
221
|
-
* Error thrown when file system operations fail
|
|
222
|
-
*/ function _define_property$1(obj, key, value) {
|
|
220
|
+
function _define_property$1(obj, key, value) {
|
|
223
221
|
if (key in obj) {
|
|
224
222
|
Object.defineProperty(obj, key, {
|
|
225
223
|
value: value,
|
|
@@ -232,7 +230,9 @@ class ArgumentError extends Error {
|
|
|
232
230
|
}
|
|
233
231
|
return obj;
|
|
234
232
|
}
|
|
235
|
-
|
|
233
|
+
/**
|
|
234
|
+
* Error thrown when file system operations fail
|
|
235
|
+
*/ class FileSystemError extends Error {
|
|
236
236
|
/**
|
|
237
237
|
* Creates an error for when a required directory doesn't exist
|
|
238
238
|
*/ static directoryNotFound(path, isRequired = false) {
|
|
@@ -973,7 +973,8 @@ const create$1 = (params)=>{
|
|
|
973
973
|
let discoveredConfigDirs = [];
|
|
974
974
|
let resolvedConfigDirs = [];
|
|
975
975
|
// Check if hierarchical configuration discovery is enabled
|
|
976
|
-
|
|
976
|
+
// Use optional chaining for safety although options.features is defaulted
|
|
977
|
+
if (options.features && options.features.includes('hierarchical')) {
|
|
977
978
|
logger.verbose('Hierarchical configuration discovery enabled');
|
|
978
979
|
try {
|
|
979
980
|
var _options_defaults_pathResolution1, _options_defaults_pathResolution2;
|
|
@@ -1252,7 +1253,8 @@ const create$1 = (params)=>{
|
|
|
1252
1253
|
let resolvedConfigDirs = [];
|
|
1253
1254
|
let tracker = {};
|
|
1254
1255
|
// Check if hierarchical configuration discovery is enabled
|
|
1255
|
-
|
|
1256
|
+
// Use optional chaining for safety although options.features is defaulted
|
|
1257
|
+
if (options.features && options.features.includes('hierarchical')) {
|
|
1256
1258
|
logger.verbose('Using hierarchical configuration discovery for source tracking');
|
|
1257
1259
|
try {
|
|
1258
1260
|
var _options_defaults_pathResolution1, _options_defaults_pathResolution2;
|
|
@@ -1389,9 +1391,7 @@ const create$1 = (params)=>{
|
|
|
1389
1391
|
displayConfigWithSources(finalConfig, tracker, discoveredDirs, logger);
|
|
1390
1392
|
};
|
|
1391
1393
|
|
|
1392
|
-
|
|
1393
|
-
* Error thrown when configuration validation fails
|
|
1394
|
-
*/ function _define_property(obj, key, value) {
|
|
1394
|
+
function _define_property(obj, key, value) {
|
|
1395
1395
|
if (key in obj) {
|
|
1396
1396
|
Object.defineProperty(obj, key, {
|
|
1397
1397
|
value: value,
|
|
@@ -1404,7 +1404,9 @@ const create$1 = (params)=>{
|
|
|
1404
1404
|
}
|
|
1405
1405
|
return obj;
|
|
1406
1406
|
}
|
|
1407
|
-
|
|
1407
|
+
/**
|
|
1408
|
+
* Error thrown when configuration validation fails
|
|
1409
|
+
*/ class ConfigurationError extends Error {
|
|
1408
1410
|
/**
|
|
1409
1411
|
* Creates a validation error for when config doesn't match the schema
|
|
1410
1412
|
*/ static validation(message, zodError, configPath) {
|
|
@@ -1444,22 +1446,22 @@ class ConfigurationError extends Error {
|
|
|
1444
1446
|
|
|
1445
1447
|
/**
|
|
1446
1448
|
* Recursively extracts all keys from a Zod schema in dot notation.
|
|
1447
|
-
*
|
|
1449
|
+
*
|
|
1448
1450
|
* This function traverses a Zod schema structure and builds a flat list
|
|
1449
1451
|
* of all possible keys, using dot notation for nested objects. It handles
|
|
1450
1452
|
* optional/nullable types by unwrapping them and supports arrays by
|
|
1451
1453
|
* introspecting their element type.
|
|
1452
|
-
*
|
|
1454
|
+
*
|
|
1453
1455
|
* Special handling for:
|
|
1454
1456
|
* - ZodOptional/ZodNullable: Unwraps to get the underlying type
|
|
1455
1457
|
* - ZodAny/ZodRecord: Accepts any keys, returns the prefix or empty array
|
|
1456
1458
|
* - ZodArray: Introspects the element type
|
|
1457
1459
|
* - ZodObject: Recursively processes all shape properties
|
|
1458
|
-
*
|
|
1460
|
+
*
|
|
1459
1461
|
* @param schema - The Zod schema to introspect
|
|
1460
1462
|
* @param prefix - Internal parameter for building nested key paths
|
|
1461
1463
|
* @returns Array of strings representing all possible keys in dot notation
|
|
1462
|
-
*
|
|
1464
|
+
*
|
|
1463
1465
|
* @example
|
|
1464
1466
|
* ```typescript
|
|
1465
1467
|
* const schema = z.object({
|
|
@@ -1469,32 +1471,26 @@ class ConfigurationError extends Error {
|
|
|
1469
1471
|
* }),
|
|
1470
1472
|
* debug: z.boolean()
|
|
1471
1473
|
* });
|
|
1472
|
-
*
|
|
1474
|
+
*
|
|
1473
1475
|
* const keys = listZodKeys(schema);
|
|
1474
1476
|
* // Returns: ['user.name', 'user.settings.theme', 'debug']
|
|
1475
1477
|
* ```
|
|
1476
1478
|
*/ const listZodKeys = (schema, prefix = '')=>{
|
|
1477
|
-
//
|
|
1478
|
-
if (schema
|
|
1479
|
-
|
|
1480
|
-
const unwrappable = schema;
|
|
1481
|
-
return listZodKeys(unwrappable.unwrap(), prefix);
|
|
1479
|
+
// Handle ZodOptional and ZodNullable - unwrap to get the underlying type
|
|
1480
|
+
if (schema instanceof zod.z.ZodOptional || schema instanceof zod.z.ZodNullable) {
|
|
1481
|
+
return listZodKeys(schema.unwrap(), prefix);
|
|
1482
1482
|
}
|
|
1483
1483
|
// Handle ZodAny and ZodRecord - these accept any keys, so don't introspect
|
|
1484
|
-
if (schema
|
|
1484
|
+
if (schema instanceof zod.z.ZodAny || schema instanceof zod.z.ZodRecord) {
|
|
1485
1485
|
return prefix ? [
|
|
1486
1486
|
prefix
|
|
1487
1487
|
] : [];
|
|
1488
1488
|
}
|
|
1489
|
-
if (schema
|
|
1490
|
-
|
|
1491
|
-
const arraySchema = schema;
|
|
1492
|
-
return listZodKeys(arraySchema.element, prefix);
|
|
1489
|
+
if (schema instanceof zod.z.ZodArray) {
|
|
1490
|
+
return listZodKeys(schema.element, prefix);
|
|
1493
1491
|
}
|
|
1494
|
-
if (schema
|
|
1495
|
-
|
|
1496
|
-
const objectSchema = schema;
|
|
1497
|
-
return Object.entries(objectSchema.shape).flatMap(([key, subschema])=>{
|
|
1492
|
+
if (schema instanceof zod.z.ZodObject) {
|
|
1493
|
+
return Object.entries(schema.shape).flatMap(([key, subschema])=>{
|
|
1498
1494
|
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
1499
1495
|
const nested = listZodKeys(subschema, fullKey);
|
|
1500
1496
|
return nested.length ? nested : fullKey;
|
|
@@ -1504,7 +1500,7 @@ class ConfigurationError extends Error {
|
|
|
1504
1500
|
};
|
|
1505
1501
|
/**
|
|
1506
1502
|
* Type guard to check if a value is a plain object (not array, null, or other types).
|
|
1507
|
-
*
|
|
1503
|
+
*
|
|
1508
1504
|
* @param value - The value to check
|
|
1509
1505
|
* @returns True if the value is a plain object
|
|
1510
1506
|
*/ const isPlainObject = (value)=>{
|
|
@@ -1552,26 +1548,26 @@ class ConfigurationError extends Error {
|
|
|
1552
1548
|
};
|
|
1553
1549
|
/**
|
|
1554
1550
|
* Validates that the configuration object contains only keys allowed by the schema.
|
|
1555
|
-
*
|
|
1551
|
+
*
|
|
1556
1552
|
* This function prevents configuration errors by detecting typos or extra keys
|
|
1557
1553
|
* that aren't defined in the Zod schema. It intelligently handles:
|
|
1558
1554
|
* - ZodRecord types that accept arbitrary keys
|
|
1559
1555
|
* - Nested objects and their key structures
|
|
1560
1556
|
* - Arrays and their element key structures
|
|
1561
|
-
*
|
|
1557
|
+
*
|
|
1562
1558
|
* The function throws a ConfigurationError if extra keys are found, providing
|
|
1563
1559
|
* helpful information about what keys are allowed vs. what was found.
|
|
1564
|
-
*
|
|
1560
|
+
*
|
|
1565
1561
|
* @param mergedSources - The merged configuration object to validate
|
|
1566
1562
|
* @param fullSchema - The complete Zod schema including base and user schemas
|
|
1567
1563
|
* @param logger - Logger for error reporting
|
|
1568
1564
|
* @throws {ConfigurationError} When extra keys are found that aren't in the schema
|
|
1569
|
-
*
|
|
1565
|
+
*
|
|
1570
1566
|
* @example
|
|
1571
1567
|
* ```typescript
|
|
1572
1568
|
* const schema = z.object({ name: z.string(), age: z.number() });
|
|
1573
1569
|
* const config = { name: 'John', age: 30, typo: 'invalid' };
|
|
1574
|
-
*
|
|
1570
|
+
*
|
|
1575
1571
|
* checkForExtraKeys(config, schema, console);
|
|
1576
1572
|
* // Throws: ConfigurationError with details about 'typo' being an extra key
|
|
1577
1573
|
* ```
|
|
@@ -1582,18 +1578,16 @@ class ConfigurationError extends Error {
|
|
|
1582
1578
|
const recordPrefixes = new Set();
|
|
1583
1579
|
// Find all prefixes that are ZodRecord types
|
|
1584
1580
|
const findRecordPrefixes = (schema, prefix = '')=>{
|
|
1585
|
-
if (schema
|
|
1586
|
-
|
|
1587
|
-
findRecordPrefixes(unwrappable.unwrap(), prefix);
|
|
1581
|
+
if (schema instanceof zod.z.ZodOptional || schema instanceof zod.z.ZodNullable) {
|
|
1582
|
+
findRecordPrefixes(schema.unwrap(), prefix);
|
|
1588
1583
|
return;
|
|
1589
1584
|
}
|
|
1590
|
-
if (schema
|
|
1585
|
+
if (schema instanceof zod.z.ZodAny || schema instanceof zod.z.ZodRecord) {
|
|
1591
1586
|
if (prefix) recordPrefixes.add(prefix);
|
|
1592
1587
|
return;
|
|
1593
1588
|
}
|
|
1594
|
-
if (schema
|
|
1595
|
-
|
|
1596
|
-
Object.entries(objectSchema.shape).forEach(([key, subschema])=>{
|
|
1589
|
+
if (schema instanceof zod.z.ZodObject) {
|
|
1590
|
+
Object.entries(schema.shape).forEach(([key, subschema])=>{
|
|
1597
1591
|
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
1598
1592
|
findRecordPrefixes(subschema, fullKey);
|
|
1599
1593
|
});
|
|
@@ -1620,11 +1614,11 @@ class ConfigurationError extends Error {
|
|
|
1620
1614
|
};
|
|
1621
1615
|
/**
|
|
1622
1616
|
* Validates that a configuration directory exists and is accessible.
|
|
1623
|
-
*
|
|
1617
|
+
*
|
|
1624
1618
|
* This function performs file system checks to ensure the configuration
|
|
1625
1619
|
* directory can be used. It handles the isRequired flag to determine
|
|
1626
1620
|
* whether a missing directory should cause an error or be silently ignored.
|
|
1627
|
-
*
|
|
1621
|
+
*
|
|
1628
1622
|
* @param configDirectory - Path to the configuration directory
|
|
1629
1623
|
* @param isRequired - Whether the directory must exist
|
|
1630
1624
|
* @param logger - Optional logger for debug information
|
|
@@ -1647,30 +1641,30 @@ class ConfigurationError extends Error {
|
|
|
1647
1641
|
};
|
|
1648
1642
|
/**
|
|
1649
1643
|
* Validates a configuration object against the combined Zod schema.
|
|
1650
|
-
*
|
|
1644
|
+
*
|
|
1651
1645
|
* This is the main validation function that:
|
|
1652
1646
|
* 1. Validates the configuration directory (if config feature enabled)
|
|
1653
1647
|
* 2. Combines the base ConfigSchema with user-provided schema shape
|
|
1654
1648
|
* 3. Checks for extra keys not defined in the schema
|
|
1655
1649
|
* 4. Validates all values against their schema definitions
|
|
1656
1650
|
* 5. Provides detailed error reporting for validation failures
|
|
1657
|
-
*
|
|
1651
|
+
*
|
|
1658
1652
|
* The validation is comprehensive and catches common configuration errors
|
|
1659
1653
|
* including typos, missing required fields, wrong types, and invalid values.
|
|
1660
|
-
*
|
|
1654
|
+
*
|
|
1661
1655
|
* @template T - The Zod schema shape type for configuration validation
|
|
1662
1656
|
* @param config - The merged configuration object to validate
|
|
1663
1657
|
* @param options - Cardigantime options containing schema, defaults, and logger
|
|
1664
1658
|
* @throws {ConfigurationError} When configuration validation fails
|
|
1665
1659
|
* @throws {FileSystemError} When configuration directory validation fails
|
|
1666
|
-
*
|
|
1660
|
+
*
|
|
1667
1661
|
* @example
|
|
1668
1662
|
* ```typescript
|
|
1669
1663
|
* const schema = z.object({
|
|
1670
1664
|
* apiKey: z.string().min(1),
|
|
1671
1665
|
* timeout: z.number().positive(),
|
|
1672
1666
|
* });
|
|
1673
|
-
*
|
|
1667
|
+
*
|
|
1674
1668
|
* await validate(config, {
|
|
1675
1669
|
* configShape: schema.shape,
|
|
1676
1670
|
* defaults: { configDirectory: './config', isRequired: true },
|
|
@@ -1703,18 +1697,17 @@ class ConfigurationError extends Error {
|
|
|
1703
1697
|
};
|
|
1704
1698
|
|
|
1705
1699
|
/**
|
|
1706
|
-
* Extracts default values from a Zod schema recursively.
|
|
1707
|
-
*
|
|
1708
|
-
* This function
|
|
1709
|
-
*
|
|
1710
|
-
*
|
|
1711
|
-
*
|
|
1712
|
-
*
|
|
1713
|
-
*
|
|
1714
|
-
*
|
|
1700
|
+
* Extracts default values from a Zod schema recursively using Zod v4's parsing mechanisms.
|
|
1701
|
+
*
|
|
1702
|
+
* This function leverages Zod's own parsing behavior to extract defaults rather than
|
|
1703
|
+
* accessing internal properties. It works by:
|
|
1704
|
+
* 1. For ZodDefault types: parsing undefined to trigger the default
|
|
1705
|
+
* 2. For ZodObject types: creating a minimal object and parsing to get all defaults
|
|
1706
|
+
* 3. For wrapped types: unwrapping and recursing
|
|
1707
|
+
*
|
|
1715
1708
|
* @param schema - The Zod schema to extract defaults from
|
|
1716
1709
|
* @returns An object containing all default values from the schema
|
|
1717
|
-
*
|
|
1710
|
+
*
|
|
1718
1711
|
* @example
|
|
1719
1712
|
* ```typescript
|
|
1720
1713
|
* const schema = z.object({
|
|
@@ -1726,68 +1719,72 @@ class ConfigurationError extends Error {
|
|
|
1726
1719
|
* port: z.number().default(5432)
|
|
1727
1720
|
* })
|
|
1728
1721
|
* });
|
|
1729
|
-
*
|
|
1722
|
+
*
|
|
1730
1723
|
* const defaults = extractSchemaDefaults(schema);
|
|
1731
1724
|
* // Returns: { name: 'app', port: 3000, debug: false, database: { host: 'localhost', port: 5432 } }
|
|
1732
1725
|
* ```
|
|
1733
1726
|
*/ const extractSchemaDefaults = (schema)=>{
|
|
1734
|
-
// Handle ZodDefault -
|
|
1735
|
-
if (schema
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
const unwrappable = schema;
|
|
1742
|
-
const unwrapped = unwrappable.unwrap();
|
|
1743
|
-
// Only provide defaults if the unwrapped schema has explicit defaults
|
|
1744
|
-
// This prevents optional arrays/objects from automatically getting [] or {} defaults
|
|
1745
|
-
if (unwrapped._def && unwrapped._def.typeName === 'ZodDefault') {
|
|
1746
|
-
return extractSchemaDefaults(unwrapped);
|
|
1727
|
+
// Handle ZodDefault - parse undefined to get the default value
|
|
1728
|
+
if (schema instanceof zod.z.ZodDefault) {
|
|
1729
|
+
try {
|
|
1730
|
+
return schema.parse(undefined);
|
|
1731
|
+
} catch {
|
|
1732
|
+
// If parsing undefined fails, return undefined
|
|
1733
|
+
return undefined;
|
|
1747
1734
|
}
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1735
|
+
}
|
|
1736
|
+
// Handle ZodOptional and ZodNullable by unwrapping
|
|
1737
|
+
if (schema instanceof zod.z.ZodOptional || schema instanceof zod.z.ZodNullable) {
|
|
1738
|
+
return extractSchemaDefaults(schema.unwrap());
|
|
1739
|
+
}
|
|
1740
|
+
// Handle ZodObject - create an object with defaults by parsing an empty object
|
|
1741
|
+
if (schema instanceof zod.z.ZodObject) {
|
|
1742
|
+
const defaults = {};
|
|
1743
|
+
const shape = schema.shape;
|
|
1744
|
+
// First, try to extract defaults from individual fields
|
|
1745
|
+
for (const [key, subschema] of Object.entries(shape)){
|
|
1756
1746
|
const defaultValue = extractSchemaDefaults(subschema);
|
|
1757
1747
|
if (defaultValue !== undefined) {
|
|
1758
|
-
|
|
1748
|
+
defaults[key] = defaultValue;
|
|
1759
1749
|
}
|
|
1760
1750
|
}
|
|
1761
|
-
|
|
1751
|
+
// Then parse an empty object to trigger any schema-level defaults
|
|
1752
|
+
const result = schema.safeParse({});
|
|
1753
|
+
if (result.success) {
|
|
1754
|
+
// Merge the parsed result with our extracted defaults
|
|
1755
|
+
return {
|
|
1756
|
+
...defaults,
|
|
1757
|
+
...result.data
|
|
1758
|
+
};
|
|
1759
|
+
}
|
|
1760
|
+
return Object.keys(defaults).length > 0 ? defaults : undefined;
|
|
1762
1761
|
}
|
|
1763
|
-
// Handle ZodArray -
|
|
1764
|
-
if (schema
|
|
1765
|
-
const
|
|
1766
|
-
const elementDefaults = extractSchemaDefaults(arraySchema.element);
|
|
1767
|
-
// Return an empty array, or an array with one example element if it has defaults
|
|
1762
|
+
// Handle ZodArray - return empty array as a reasonable default
|
|
1763
|
+
if (schema instanceof zod.z.ZodArray) {
|
|
1764
|
+
const elementDefaults = extractSchemaDefaults(schema.element);
|
|
1768
1765
|
return elementDefaults !== undefined ? [
|
|
1769
1766
|
elementDefaults
|
|
1770
1767
|
] : [];
|
|
1771
1768
|
}
|
|
1772
|
-
// Handle ZodRecord -
|
|
1773
|
-
if (schema
|
|
1769
|
+
// Handle ZodRecord - return empty object as default
|
|
1770
|
+
if (schema instanceof zod.z.ZodRecord) {
|
|
1774
1771
|
return {};
|
|
1775
1772
|
}
|
|
1776
|
-
//
|
|
1773
|
+
// No default available for other schema types
|
|
1777
1774
|
return undefined;
|
|
1778
1775
|
};
|
|
1779
1776
|
/**
|
|
1780
1777
|
* Generates a complete configuration object with all default values populated.
|
|
1781
|
-
*
|
|
1778
|
+
*
|
|
1782
1779
|
* This function combines the base ConfigSchema with a user-provided schema shape
|
|
1783
1780
|
* and extracts all available default values to create a complete configuration
|
|
1784
1781
|
* example that can be serialized to YAML.
|
|
1785
|
-
*
|
|
1782
|
+
*
|
|
1786
1783
|
* @template T - The Zod schema shape type
|
|
1787
1784
|
* @param configShape - The user's configuration schema shape
|
|
1788
1785
|
* @param configDirectory - The configuration directory to include in the defaults
|
|
1789
1786
|
* @returns An object containing all default values suitable for YAML serialization
|
|
1790
|
-
*
|
|
1787
|
+
*
|
|
1791
1788
|
* @example
|
|
1792
1789
|
* ```typescript
|
|
1793
1790
|
* const shape = z.object({
|
|
@@ -1795,7 +1792,7 @@ class ConfigurationError extends Error {
|
|
|
1795
1792
|
* timeout: z.number().default(5000).describe('Request timeout in milliseconds'),
|
|
1796
1793
|
* features: z.array(z.string()).default(['auth', 'logging'])
|
|
1797
1794
|
* }).shape;
|
|
1798
|
-
*
|
|
1795
|
+
*
|
|
1799
1796
|
* const config = generateDefaultConfig(shape, './config');
|
|
1800
1797
|
* // Returns: { timeout: 5000, features: ['auth', 'logging'] }
|
|
1801
1798
|
* // Note: apiKey is not included since it has no default
|
|
@@ -1939,7 +1936,7 @@ class ConfigurationError extends Error {
|
|
|
1939
1936
|
# Modify the values below to customize your application's behavior.
|
|
1940
1937
|
#
|
|
1941
1938
|
# For more information about Cardigantime configuration:
|
|
1942
|
-
# https://github.
|
|
1939
|
+
# https://tobrien.github.io/cardigantime/
|
|
1943
1940
|
|
|
1944
1941
|
`;
|
|
1945
1942
|
const finalContent = header + yamlContent;
|