@utilarium/cardigantime 0.0.24-dev.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.
- package/LICENSE +65 -0
- package/README.md +398 -0
- package/dist/cardigantime.cjs +2169 -0
- package/dist/cardigantime.cjs.map +1 -0
- package/dist/cardigantime.d.ts +92 -0
- package/dist/cardigantime.js +198 -0
- package/dist/cardigantime.js.map +1 -0
- package/dist/config/executable-security.d.ts +32 -0
- package/dist/config/format-detector.d.ts +59 -0
- package/dist/configure.d.ts +55 -0
- package/dist/configure.js +125 -0
- package/dist/configure.js.map +1 -0
- package/dist/constants.d.ts +25 -0
- package/dist/constants.js +38 -0
- package/dist/constants.js.map +1 -0
- package/dist/discovery/discoverer.d.ts +62 -0
- package/dist/discovery/hierarchical-modes.d.ts +64 -0
- package/dist/discovery/index.d.ts +15 -0
- package/dist/discovery/patterns.d.ts +77 -0
- package/dist/discovery/root-detection.d.ts +100 -0
- package/dist/discovery/traversal-security.d.ts +106 -0
- package/dist/env/errors.d.ts +18 -0
- package/dist/env/index.d.ts +7 -0
- package/dist/env/naming.d.ts +38 -0
- package/dist/env/parser.d.ts +61 -0
- package/dist/env/reader.d.ts +45 -0
- package/dist/env/resolver.d.ts +25 -0
- package/dist/env/schema-utils.d.ts +33 -0
- package/dist/env/types.d.ts +43 -0
- package/dist/error/ArgumentError.d.ts +31 -0
- package/dist/error/ArgumentError.js +48 -0
- package/dist/error/ArgumentError.js.map +1 -0
- package/dist/error/ConfigParseError.d.ts +26 -0
- package/dist/error/ConfigurationError.d.ts +21 -0
- package/dist/error/ConfigurationError.js +46 -0
- package/dist/error/ConfigurationError.js.map +1 -0
- package/dist/error/FileSystemError.d.ts +30 -0
- package/dist/error/FileSystemError.js +58 -0
- package/dist/error/FileSystemError.js.map +1 -0
- package/dist/error/index.d.ts +4 -0
- package/dist/mcp/discovery.d.ts +105 -0
- package/dist/mcp/errors.d.ts +75 -0
- package/dist/mcp/index.d.ts +22 -0
- package/dist/mcp/integration.d.ts +184 -0
- package/dist/mcp/parser.d.ts +141 -0
- package/dist/mcp/resolver.d.ts +165 -0
- package/dist/mcp/tools/check-config-types.d.ts +208 -0
- package/dist/mcp/tools/check-config.d.ts +85 -0
- package/dist/mcp/tools/index.d.ts +12 -0
- package/dist/mcp/types.d.ts +210 -0
- package/dist/parsers/index.d.ts +25 -0
- package/dist/parsers/javascript-parser.d.ts +12 -0
- package/dist/parsers/json-parser.d.ts +6 -0
- package/dist/parsers/typescript-parser.d.ts +15 -0
- package/dist/parsers/yaml-parser.d.ts +6 -0
- package/dist/read.d.ts +56 -0
- package/dist/read.js +653 -0
- package/dist/read.js.map +1 -0
- package/dist/security/audit-logger.d.ts +135 -0
- package/dist/security/cli-validator.d.ts +73 -0
- package/dist/security/config-validator.d.ts +95 -0
- package/dist/security/defaults.d.ts +17 -0
- package/dist/security/index.d.ts +14 -0
- package/dist/security/numeric-guard.d.ts +111 -0
- package/dist/security/path-guard.d.ts +53 -0
- package/dist/security/profiles.d.ts +127 -0
- package/dist/security/security-validator.d.ts +109 -0
- package/dist/security/string-guard.d.ts +92 -0
- package/dist/security/types.d.ts +126 -0
- package/dist/security/zod-secure-enum.d.ts +20 -0
- package/dist/security/zod-secure-number.d.ts +39 -0
- package/dist/security/zod-secure-path.d.ts +24 -0
- package/dist/security/zod-secure-string.d.ts +38 -0
- package/dist/types.d.ts +584 -0
- package/dist/types.js +56 -0
- package/dist/types.js.map +1 -0
- package/dist/util/hierarchical.d.ts +136 -0
- package/dist/util/hierarchical.js +436 -0
- package/dist/util/hierarchical.js.map +1 -0
- package/dist/util/schema-defaults.d.ts +80 -0
- package/dist/util/schema-defaults.js +118 -0
- package/dist/util/schema-defaults.js.map +1 -0
- package/dist/util/storage.d.ts +31 -0
- package/dist/util/storage.js +154 -0
- package/dist/util/storage.js.map +1 -0
- package/dist/validate.d.ts +113 -0
- package/dist/validate.js +260 -0
- package/dist/validate.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ConfigDiscoveryOptions, DiscoveryResult, Logger } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Discovers configuration files in a directory using multiple naming patterns.
|
|
4
|
+
*
|
|
5
|
+
* Checks patterns in priority order and returns the first match.
|
|
6
|
+
* If `warnOnMultipleConfigs` is enabled (default), continues scanning after
|
|
7
|
+
* the first match to detect and warn about additional config files.
|
|
8
|
+
*
|
|
9
|
+
* @param directory - Directory to search for configuration files
|
|
10
|
+
* @param options - Discovery options including app name and patterns
|
|
11
|
+
* @param logger - Optional logger for debug/info/warn messages
|
|
12
|
+
* @returns Discovery result containing the found config and any warnings
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const result = await discoverConfig('/path/to/project', {
|
|
17
|
+
* appName: 'myapp',
|
|
18
|
+
* extensions: ['yaml', 'json'],
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* if (result.config) {
|
|
22
|
+
* console.log(`Found config: ${result.config.absolutePath}`);
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* if (result.multipleConfigWarning) {
|
|
26
|
+
* console.warn(`Multiple configs found. Using ${result.multipleConfigWarning.used.path}`);
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function discoverConfig(directory: string, options: ConfigDiscoveryOptions, logger?: Logger): Promise<DiscoveryResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Discovers configuration files across multiple directories.
|
|
33
|
+
* Useful for hierarchical configuration where multiple directories may contain config files.
|
|
34
|
+
*
|
|
35
|
+
* @param directories - Directories to search, in order of precedence (first = highest)
|
|
36
|
+
* @param options - Discovery options
|
|
37
|
+
* @param logger - Optional logger
|
|
38
|
+
* @returns Array of discovery results, one per directory that had a config
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const results = await discoverConfigsInHierarchy(
|
|
43
|
+
* ['/project/subdir', '/project', '/home/user'],
|
|
44
|
+
* { appName: 'myapp' }
|
|
45
|
+
* );
|
|
46
|
+
*
|
|
47
|
+
* // results[0] = config from /project/subdir (if exists)
|
|
48
|
+
* // results[1] = config from /project (if exists)
|
|
49
|
+
* // etc.
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function discoverConfigsInHierarchy(directories: string[], options: ConfigDiscoveryOptions, logger?: Logger): Promise<DiscoveryResult[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Quickly checks if any config file exists in a directory.
|
|
55
|
+
* More efficient than `discoverConfig` when you only need to know if a config exists,
|
|
56
|
+
* not which one it is.
|
|
57
|
+
*
|
|
58
|
+
* @param directory - Directory to check
|
|
59
|
+
* @param options - Discovery options
|
|
60
|
+
* @returns True if any config file exists
|
|
61
|
+
*/
|
|
62
|
+
export declare function hasConfigFile(directory: string, options: ConfigDiscoveryOptions): Promise<boolean>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { HierarchicalMode, HierarchicalOptions, ConfigDiscoveryOptions, DiscoveredConfig, Logger } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Result of hierarchical config discovery with mode awareness.
|
|
4
|
+
*/
|
|
5
|
+
export interface HierarchicalDiscoveryResult {
|
|
6
|
+
/** The mode that was used for discovery */
|
|
7
|
+
mode: HierarchicalMode;
|
|
8
|
+
/** Primary config (if found) */
|
|
9
|
+
primaryConfig: DiscoveredConfig | null;
|
|
10
|
+
/** All configs found during traversal (for 'enabled' mode) */
|
|
11
|
+
configs: DiscoveredConfig[];
|
|
12
|
+
/** Directories that were searched */
|
|
13
|
+
searchedDirectories: string[];
|
|
14
|
+
/** Whether hierarchical loading should occur */
|
|
15
|
+
shouldMerge: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolves hierarchical options with defaults.
|
|
19
|
+
*
|
|
20
|
+
* @param options - User-provided options
|
|
21
|
+
* @returns Resolved options with defaults applied
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveHierarchicalOptions(options?: Partial<HierarchicalOptions>): Required<HierarchicalOptions>;
|
|
24
|
+
/**
|
|
25
|
+
* Discovers configuration files using the specified hierarchical mode.
|
|
26
|
+
*
|
|
27
|
+
* @param startPath - Starting directory for discovery
|
|
28
|
+
* @param discoveryOptions - Config discovery options (app name, patterns, etc.)
|
|
29
|
+
* @param hierarchicalOptions - Hierarchical mode options
|
|
30
|
+
* @param logger - Optional logger
|
|
31
|
+
* @returns Hierarchical discovery result
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* // Disabled mode - only check starting directory
|
|
36
|
+
* const result = await discoverWithMode('/project/src',
|
|
37
|
+
* { appName: 'myapp' },
|
|
38
|
+
* { mode: 'disabled' }
|
|
39
|
+
* );
|
|
40
|
+
*
|
|
41
|
+
* // Enabled mode - full hierarchical traversal
|
|
42
|
+
* const result = await discoverWithMode('/project/src',
|
|
43
|
+
* { appName: 'myapp' },
|
|
44
|
+
* { mode: 'enabled', maxDepth: 5 }
|
|
45
|
+
* );
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function discoverWithMode(startPath: string, discoveryOptions: ConfigDiscoveryOptions, hierarchicalOptions?: Partial<HierarchicalOptions>, logger?: Logger): Promise<HierarchicalDiscoveryResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Checks if a config content specifies a hierarchical mode override.
|
|
51
|
+
* Configs can set `hierarchical.mode: disabled` to prevent parent merging.
|
|
52
|
+
*
|
|
53
|
+
* @param configContent - Parsed config content
|
|
54
|
+
* @returns The override mode if specified, undefined otherwise
|
|
55
|
+
*/
|
|
56
|
+
export declare function getHierarchicalModeOverride(configContent: unknown): HierarchicalMode | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Gets hierarchical options from a config content.
|
|
59
|
+
* Extracts any hierarchical settings from the config.
|
|
60
|
+
*
|
|
61
|
+
* @param configContent - Parsed config content
|
|
62
|
+
* @returns Partial hierarchical options, or undefined if none
|
|
63
|
+
*/
|
|
64
|
+
export declare function getHierarchicalOptionsFromConfig(configContent: unknown): Partial<HierarchicalOptions> | undefined;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Discovery Module
|
|
3
|
+
*
|
|
4
|
+
* Provides functionality for discovering configuration files in various
|
|
5
|
+
* standard locations using customizable naming patterns.
|
|
6
|
+
*
|
|
7
|
+
* @module discovery
|
|
8
|
+
*/
|
|
9
|
+
export { STANDARD_PATTERNS, DEFAULT_EXTENSIONS, expandPattern, getDiscoveryPaths, } from './patterns';
|
|
10
|
+
export { discoverConfig, discoverConfigsInHierarchy, hasConfigFile, } from './discoverer';
|
|
11
|
+
export { isProjectRoot, findProjectRoot, shouldStopAt, walkUpToRoot, getDirectoriesToRoot, } from './root-detection';
|
|
12
|
+
export type { RootDetectionResult } from './root-detection';
|
|
13
|
+
export { discoverWithMode, resolveHierarchicalOptions, getHierarchicalModeOverride, getHierarchicalOptionsFromConfig, } from './hierarchical-modes';
|
|
14
|
+
export type { HierarchicalDiscoveryResult } from './hierarchical-modes';
|
|
15
|
+
export { DEFAULT_TRAVERSAL_BOUNDARY, expandEnvironmentVariables, normalizePath, getPathDepth, isPathWithin, isPathAtOrAbove, checkTraversalBoundary, resolveTraversalBoundary, createBoundaryChecker, filterAllowedPaths, } from './traversal-security';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ConfigNamingPattern } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Standard configuration file naming patterns.
|
|
4
|
+
*
|
|
5
|
+
* These patterns cover the most common conventions used by modern JavaScript tools:
|
|
6
|
+
*
|
|
7
|
+
* 1. **Modern explicit pattern** (`{app}.config.{ext}`) - Used by Vite, Next.js, etc.
|
|
8
|
+
* 2. **Short explicit pattern** (`{app}.conf.{ext}`) - Unix-style configuration
|
|
9
|
+
* 3. **Hidden directory pattern** (`.{app}/config.{ext}`) - Current CardiganTime default
|
|
10
|
+
* 4. **RC file with extension** (`.{app}rc.{ext}`) - ESLint legacy, Babel
|
|
11
|
+
* 5. **RC file without extension** (`.{app}rc`) - Prettier, npm
|
|
12
|
+
*
|
|
13
|
+
* Patterns are ordered by priority (lower = checked first). This order prefers:
|
|
14
|
+
* - Visible files over hidden files (easier to discover)
|
|
15
|
+
* - Explicit naming over implicit (clearer intent)
|
|
16
|
+
* - Modern conventions over legacy conventions
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { STANDARD_PATTERNS, expandPattern } from './patterns';
|
|
21
|
+
*
|
|
22
|
+
* // List all patterns for 'protokoll' app with YAML extension
|
|
23
|
+
* const files = STANDARD_PATTERNS.map(p =>
|
|
24
|
+
* expandPattern(p.pattern, 'protokoll', 'yaml')
|
|
25
|
+
* );
|
|
26
|
+
* // ['protokoll.config.yaml', 'protokoll.conf.yaml', '.protokoll/config.yaml', ...]
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare const STANDARD_PATTERNS: ConfigNamingPattern[];
|
|
30
|
+
/**
|
|
31
|
+
* Expands a naming pattern into an actual file path segment.
|
|
32
|
+
*
|
|
33
|
+
* @param pattern - The pattern template with placeholders
|
|
34
|
+
* @param appName - The application name to substitute for `{app}`
|
|
35
|
+
* @param extension - The file extension to substitute for `{ext}` (optional)
|
|
36
|
+
* @returns The expanded file path segment
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* expandPattern('{app}.config.{ext}', 'myapp', 'yaml');
|
|
41
|
+
* // Returns: 'myapp.config.yaml'
|
|
42
|
+
*
|
|
43
|
+
* expandPattern('.{app}rc', 'myapp');
|
|
44
|
+
* // Returns: '.myapprc'
|
|
45
|
+
*
|
|
46
|
+
* expandPattern('.{app}/config.{ext}', 'protokoll', 'json');
|
|
47
|
+
* // Returns: '.protokoll/config.json'
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function expandPattern(pattern: string, appName: string, extension?: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Gets all file paths to check for a given app name and extensions.
|
|
53
|
+
* Expands all standard patterns with the provided extensions.
|
|
54
|
+
*
|
|
55
|
+
* @param appName - The application name
|
|
56
|
+
* @param extensions - Array of file extensions to search for
|
|
57
|
+
* @param options - Optional configuration
|
|
58
|
+
* @param options.includeHidden - Whether to include hidden file patterns (default: true)
|
|
59
|
+
* @param options.patterns - Custom patterns to use instead of STANDARD_PATTERNS
|
|
60
|
+
* @returns Array of file paths to check, ordered by priority
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const paths = getDiscoveryPaths('myapp', ['yaml', 'json']);
|
|
65
|
+
* // Returns (in priority order):
|
|
66
|
+
* // ['myapp.config.yaml', 'myapp.config.json', 'myapp.conf.yaml', ...]
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare function getDiscoveryPaths(appName: string, extensions: string[], options?: {
|
|
70
|
+
includeHidden?: boolean;
|
|
71
|
+
patterns?: ConfigNamingPattern[];
|
|
72
|
+
}): string[];
|
|
73
|
+
/**
|
|
74
|
+
* Default file extensions supported for configuration discovery.
|
|
75
|
+
* Ordered by priority (TypeScript > JavaScript > JSON > YAML).
|
|
76
|
+
*/
|
|
77
|
+
export declare const DEFAULT_EXTENSIONS: string[];
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { RootMarker, Logger } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Result of root detection operation.
|
|
4
|
+
*/
|
|
5
|
+
export interface RootDetectionResult {
|
|
6
|
+
/** Whether a root was found */
|
|
7
|
+
found: boolean;
|
|
8
|
+
/** Path to the detected root directory (if found) */
|
|
9
|
+
rootPath?: string;
|
|
10
|
+
/** The marker that triggered root detection (if found) */
|
|
11
|
+
matchedMarker?: RootMarker;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Checks if a directory is a project root based on the presence of root markers.
|
|
15
|
+
*
|
|
16
|
+
* @param directory - Directory to check
|
|
17
|
+
* @param markers - Root markers to look for (defaults to DEFAULT_ROOT_MARKERS)
|
|
18
|
+
* @param logger - Optional logger for debug output
|
|
19
|
+
* @returns True if the directory contains any of the root markers
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const isRoot = await isProjectRoot('/path/to/dir');
|
|
24
|
+
* // Returns true if directory contains package.json, .git, etc.
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function isProjectRoot(directory: string, markers?: RootMarker[], logger?: Logger): Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Finds the project root by walking up from the starting directory.
|
|
30
|
+
*
|
|
31
|
+
* @param startPath - Starting directory for the search
|
|
32
|
+
* @param markers - Root markers to look for (defaults to DEFAULT_ROOT_MARKERS)
|
|
33
|
+
* @param maxDepth - Maximum number of directories to traverse (default: 20)
|
|
34
|
+
* @param logger - Optional logger for debug output
|
|
35
|
+
* @returns Detection result with the root path if found
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const result = await findProjectRoot('/path/to/deep/nested/dir');
|
|
40
|
+
* if (result.found) {
|
|
41
|
+
* console.log(`Project root: ${result.rootPath}`);
|
|
42
|
+
* console.log(`Detected by: ${result.matchedMarker?.name}`);
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function findProjectRoot(startPath: string, markers?: RootMarker[], maxDepth?: number, logger?: Logger): Promise<RootDetectionResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Checks if a directory name is in the stop-at list.
|
|
49
|
+
*
|
|
50
|
+
* @param directory - Directory path to check
|
|
51
|
+
* @param stopAtNames - List of directory names to stop at
|
|
52
|
+
* @returns True if the directory should stop traversal
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const shouldStop = shouldStopAt('/path/to/node_modules/pkg', ['node_modules', 'vendor']);
|
|
57
|
+
* // Returns false (parent 'node_modules' triggers stop, but current dir is 'pkg')
|
|
58
|
+
*
|
|
59
|
+
* const shouldStop2 = shouldStopAt('/path/to/node_modules', ['node_modules', 'vendor']);
|
|
60
|
+
* // Returns true (current directory is 'node_modules')
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function shouldStopAt(directory: string, stopAtNames: string[]): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Walks up the directory tree, checking each directory against root markers and stop conditions.
|
|
66
|
+
* Yields each directory until a stop condition is met.
|
|
67
|
+
*
|
|
68
|
+
* @param startPath - Starting directory
|
|
69
|
+
* @param options - Walk options
|
|
70
|
+
* @param logger - Optional logger
|
|
71
|
+
* @yields Directory paths from start to root/stop condition
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* for await (const dir of walkUpToRoot('/path/to/start', { maxDepth: 5 })) {
|
|
76
|
+
* console.log(`Processing: ${dir}`);
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare function walkUpToRoot(startPath: string, options?: {
|
|
81
|
+
maxDepth?: number;
|
|
82
|
+
rootMarkers?: RootMarker[];
|
|
83
|
+
stopAt?: string[];
|
|
84
|
+
stopAtRoot?: boolean;
|
|
85
|
+
}, logger?: Logger): AsyncGenerator<string, void, undefined>;
|
|
86
|
+
/**
|
|
87
|
+
* Gets all directories from start to root (or stop condition) as an array.
|
|
88
|
+
* Convenience wrapper around walkUpToRoot for when you need all directories at once.
|
|
89
|
+
*
|
|
90
|
+
* @param startPath - Starting directory
|
|
91
|
+
* @param options - Walk options
|
|
92
|
+
* @param logger - Optional logger
|
|
93
|
+
* @returns Array of directory paths
|
|
94
|
+
*/
|
|
95
|
+
export declare function getDirectoriesToRoot(startPath: string, options?: {
|
|
96
|
+
maxDepth?: number;
|
|
97
|
+
rootMarkers?: RootMarker[];
|
|
98
|
+
stopAt?: string[];
|
|
99
|
+
stopAtRoot?: boolean;
|
|
100
|
+
}, logger?: Logger): Promise<string[]>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { TraversalBoundary, TraversalCheckResult, TraversalSecurityOptions, Logger } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Default traversal boundaries.
|
|
4
|
+
* These provide safe defaults for most use cases.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_TRAVERSAL_BOUNDARY: TraversalBoundary;
|
|
7
|
+
/**
|
|
8
|
+
* Expands environment variable placeholders in a path.
|
|
9
|
+
* Supports $HOME, $USER, and $TMPDIR.
|
|
10
|
+
*
|
|
11
|
+
* @param pathStr - Path string with potential variable placeholders
|
|
12
|
+
* @returns Expanded path string
|
|
13
|
+
*/
|
|
14
|
+
export declare function expandEnvironmentVariables(pathStr: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Normalizes a path for comparison.
|
|
17
|
+
* Resolves to absolute path and normalizes separators.
|
|
18
|
+
*
|
|
19
|
+
* @param pathStr - Path to normalize
|
|
20
|
+
* @returns Normalized absolute path
|
|
21
|
+
*/
|
|
22
|
+
export declare function normalizePath(pathStr: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Calculates the depth of a path (number of segments from root).
|
|
25
|
+
*
|
|
26
|
+
* @param pathStr - Absolute path
|
|
27
|
+
* @returns Number of path segments
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* getPathDepth('/'); // 0
|
|
32
|
+
* getPathDepth('/home'); // 1
|
|
33
|
+
* getPathDepth('/home/user/project'); // 3
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function getPathDepth(pathStr: string): number;
|
|
37
|
+
/**
|
|
38
|
+
* Checks if a path is at or within a boundary path.
|
|
39
|
+
*
|
|
40
|
+
* @param checkPath - Path to check
|
|
41
|
+
* @param boundaryPath - Boundary path
|
|
42
|
+
* @returns True if checkPath is at or within boundaryPath
|
|
43
|
+
*/
|
|
44
|
+
export declare function isPathWithin(checkPath: string, boundaryPath: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Checks if a path is at or above a boundary path.
|
|
47
|
+
* Used to check if traversal would go beyond soft boundaries.
|
|
48
|
+
*
|
|
49
|
+
* @param checkPath - Path to check
|
|
50
|
+
* @param boundaryPath - Boundary path
|
|
51
|
+
* @returns True if checkPath is at or above (parent of) boundaryPath
|
|
52
|
+
*/
|
|
53
|
+
export declare function isPathAtOrAbove(checkPath: string, boundaryPath: string): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Checks if a path is allowed according to traversal boundaries.
|
|
56
|
+
*
|
|
57
|
+
* @param pathToCheck - Path to check
|
|
58
|
+
* @param boundary - Traversal boundaries to enforce
|
|
59
|
+
* @param startPath - Optional starting path for relative depth calculation
|
|
60
|
+
* @returns Check result with allowed status and reason
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const result = checkTraversalBoundary('/etc/passwd', DEFAULT_TRAVERSAL_BOUNDARY);
|
|
65
|
+
* if (!result.allowed) {
|
|
66
|
+
* console.error(`Access denied: ${result.reason}`);
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function checkTraversalBoundary(pathToCheck: string, boundary: TraversalBoundary, startPath?: string): TraversalCheckResult;
|
|
71
|
+
/**
|
|
72
|
+
* Resolves traversal boundaries with defaults.
|
|
73
|
+
*
|
|
74
|
+
* @param options - User-provided options
|
|
75
|
+
* @returns Complete traversal boundary configuration
|
|
76
|
+
*/
|
|
77
|
+
export declare function resolveTraversalBoundary(options?: Partial<TraversalBoundary>): TraversalBoundary;
|
|
78
|
+
/**
|
|
79
|
+
* Creates a boundary checker function with the specified options.
|
|
80
|
+
* Useful for repeated checks with the same configuration.
|
|
81
|
+
*
|
|
82
|
+
* @param options - Security options
|
|
83
|
+
* @param logger - Optional logger
|
|
84
|
+
* @returns Boundary checker function
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const checker = createBoundaryChecker({ allowUnsafeTraversal: false });
|
|
89
|
+
*
|
|
90
|
+
* const result = checker('/path/to/check', '/start/path');
|
|
91
|
+
* if (!result.allowed) {
|
|
92
|
+
* console.error(result.reason);
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function createBoundaryChecker(options?: TraversalSecurityOptions, logger?: Logger): (pathToCheck: string, startPath?: string) => TraversalCheckResult;
|
|
97
|
+
/**
|
|
98
|
+
* Filters an array of paths to only include those within traversal boundaries.
|
|
99
|
+
*
|
|
100
|
+
* @param paths - Paths to filter
|
|
101
|
+
* @param options - Security options
|
|
102
|
+
* @param startPath - Starting path for relative depth calculation
|
|
103
|
+
* @param logger - Optional logger
|
|
104
|
+
* @returns Filtered array of allowed paths
|
|
105
|
+
*/
|
|
106
|
+
export declare function filterAllowedPaths(paths: string[], options?: TraversalSecurityOptions, startPath?: string, logger?: Logger): string[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Error thrown when env var parsing fails
|
|
4
|
+
*/
|
|
5
|
+
export declare class EnvVarParseError extends Error {
|
|
6
|
+
readonly value: string;
|
|
7
|
+
readonly expectedType: string;
|
|
8
|
+
envVarName?: string | undefined;
|
|
9
|
+
constructor(message: string, value: string, expectedType: string, envVarName?: string | undefined);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Error thrown when env var validation fails
|
|
13
|
+
*/
|
|
14
|
+
export declare class EnvVarValidationError extends Error {
|
|
15
|
+
readonly envVarName: string;
|
|
16
|
+
readonly zodError: z.ZodError;
|
|
17
|
+
constructor(message: string, envVarName: string, zodError: z.ZodError);
|
|
18
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { toScreamingSnakeCase, generateEnvVarName, flattenFieldPath } from './naming';
|
|
2
|
+
export { parseEnvVar, parseBoolean, parseNumber, parseArray } from './parser';
|
|
3
|
+
export { readEnvVar, readEnvVarForField, readEnvVarsForSchema } from './reader';
|
|
4
|
+
export { extractSchemaFields, getSchemaForField } from './schema-utils';
|
|
5
|
+
export { resolveEnvVarConfig } from './resolver';
|
|
6
|
+
export { EnvVarParseError, EnvVarValidationError } from './errors';
|
|
7
|
+
export type { EnvVarNamingConfig, EnvVarName, EnvVarReadResult, EnvVarConfigSource } from './types';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert camelCase to SCREAMING_SNAKE_CASE
|
|
3
|
+
*
|
|
4
|
+
* Examples:
|
|
5
|
+
* planDirectory -> PLAN_DIRECTORY
|
|
6
|
+
* apiKey -> API_KEY
|
|
7
|
+
* maxRetryCount -> MAX_RETRY_COUNT
|
|
8
|
+
* openaiAPIKey -> OPENAI_API_KEY
|
|
9
|
+
* api.key -> API_KEY (dots converted to underscores)
|
|
10
|
+
*
|
|
11
|
+
* @param camelCase - The camelCase string to convert
|
|
12
|
+
* @returns The SCREAMING_SNAKE_CASE version
|
|
13
|
+
*/
|
|
14
|
+
export declare function toScreamingSnakeCase(camelCase: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Flatten nested field path to single-underscore format
|
|
17
|
+
*
|
|
18
|
+
* Examples:
|
|
19
|
+
* ['api', 'key'] -> 'api.key'
|
|
20
|
+
* ['config', 'server', 'port'] -> 'config.server.port'
|
|
21
|
+
*
|
|
22
|
+
* @param path - Array of field path segments
|
|
23
|
+
* @returns Dot-notation string
|
|
24
|
+
*/
|
|
25
|
+
export declare function flattenFieldPath(path: string[]): string;
|
|
26
|
+
/**
|
|
27
|
+
* Generate full env var name with prefix
|
|
28
|
+
*
|
|
29
|
+
* Examples:
|
|
30
|
+
* ('riotplan', 'planDirectory') -> 'RIOTPLAN_PLAN_DIRECTORY'
|
|
31
|
+
* ('protokoll', ['api', 'key']) -> 'PROTOKOLL_API_KEY'
|
|
32
|
+
* ('MyApp', 'setting') -> 'MYAPP_SETTING'
|
|
33
|
+
*
|
|
34
|
+
* @param appName - Application name to use as prefix
|
|
35
|
+
* @param fieldPath - Field path as string or array
|
|
36
|
+
* @returns Full environment variable name
|
|
37
|
+
*/
|
|
38
|
+
export declare function generateEnvVarName(appName: string, fieldPath: string | string[]): string;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ZodTypeAny } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Parse environment variable value based on Zod schema type
|
|
4
|
+
*
|
|
5
|
+
* This function inspects the Zod schema type and delegates to the appropriate
|
|
6
|
+
* parser function. It supports boolean, number, array, and string types.
|
|
7
|
+
*
|
|
8
|
+
* @param value - Raw string value from process.env
|
|
9
|
+
* @param zodType - Zod schema type to parse into
|
|
10
|
+
* @returns Parsed value of appropriate type
|
|
11
|
+
* @throws EnvVarParseError if parsing fails
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseEnvVar(value: string | undefined, zodType: ZodTypeAny): unknown;
|
|
14
|
+
/**
|
|
15
|
+
* Parse boolean from various string formats
|
|
16
|
+
*
|
|
17
|
+
* Uses the 'yn' library (https://github.com/sindresorhus/yn) which is
|
|
18
|
+
* well-maintained with 7.1M weekly downloads. Supports case-insensitive:
|
|
19
|
+
* - true/false
|
|
20
|
+
* - yes/no
|
|
21
|
+
* - y/n
|
|
22
|
+
* - 1/0
|
|
23
|
+
* - on/off
|
|
24
|
+
*
|
|
25
|
+
* Empty string is treated as false.
|
|
26
|
+
*
|
|
27
|
+
* @param value - String value to parse
|
|
28
|
+
* @returns Boolean value
|
|
29
|
+
* @throws EnvVarParseError if value cannot be parsed as boolean
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseBoolean(value: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Parse number from string
|
|
34
|
+
*
|
|
35
|
+
* Supports:
|
|
36
|
+
* - Integers: 42, -10, 0
|
|
37
|
+
* - Floats: 3.14, -2.7, 0.5
|
|
38
|
+
* - Scientific notation: 1e6, 1.5e3, 2e-3
|
|
39
|
+
* - Hexadecimal: 0xFF, 0x10
|
|
40
|
+
*
|
|
41
|
+
* @param value - String value to parse
|
|
42
|
+
* @returns Number value
|
|
43
|
+
* @throws EnvVarParseError if value cannot be parsed as number
|
|
44
|
+
*/
|
|
45
|
+
export declare function parseNumber(value: string): number;
|
|
46
|
+
/**
|
|
47
|
+
* Parse array from space-separated string
|
|
48
|
+
*
|
|
49
|
+
* Example: "tag1 tag2 tag3" -> ['tag1', 'tag2', 'tag3']
|
|
50
|
+
*
|
|
51
|
+
* Each item is parsed according to the element type of the array schema.
|
|
52
|
+
* Multiple spaces are treated as a single separator.
|
|
53
|
+
* Leading and trailing whitespace is trimmed.
|
|
54
|
+
*
|
|
55
|
+
* Note: Items with spaces are not supported in this version.
|
|
56
|
+
*
|
|
57
|
+
* @param value - Space-separated string value
|
|
58
|
+
* @param elementType - Zod schema type for array elements
|
|
59
|
+
* @returns Array of parsed values
|
|
60
|
+
*/
|
|
61
|
+
export declare function parseArray(value: string, elementType: ZodTypeAny): unknown[];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { EnvVarNamingConfig, EnvVarReadResult } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Read environment variable value
|
|
4
|
+
*
|
|
5
|
+
* This is a simple wrapper around process.env access for testability
|
|
6
|
+
* and consistency. It does not throw errors for missing variables.
|
|
7
|
+
*
|
|
8
|
+
* @param envVarName - Full env var name (e.g., 'RIOTPLAN_PLAN_DIRECTORY')
|
|
9
|
+
* @returns Value from process.env or undefined if not set
|
|
10
|
+
*/
|
|
11
|
+
export declare function readEnvVar(envVarName: string): string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Read environment variable for a config field
|
|
14
|
+
*
|
|
15
|
+
* Checks custom mapping first (from envVarMap), then falls back to
|
|
16
|
+
* auto-generated name. This allows users to override the default
|
|
17
|
+
* naming convention for specific fields.
|
|
18
|
+
*
|
|
19
|
+
* Example:
|
|
20
|
+
* readEnvVarForField('openaiApiKey', {
|
|
21
|
+
* appName: 'riotplan',
|
|
22
|
+
* envVarMap: { openaiApiKey: 'OPENAI_API_KEY' }
|
|
23
|
+
* })
|
|
24
|
+
* // Reads from OPENAI_API_KEY instead of RIOTPLAN_OPENAI_API_KEY
|
|
25
|
+
*
|
|
26
|
+
* @param fieldPath - Field path in config (e.g., 'planDirectory' or ['api', 'key'])
|
|
27
|
+
* @param config - Naming configuration with appName and envVarMap
|
|
28
|
+
* @returns Object with env var name and value
|
|
29
|
+
*/
|
|
30
|
+
export declare function readEnvVarForField(fieldPath: string | string[], config: EnvVarNamingConfig): EnvVarReadResult;
|
|
31
|
+
/**
|
|
32
|
+
* Read all environment variables for a schema
|
|
33
|
+
*
|
|
34
|
+
* Returns a map of field paths to env var values. Only includes
|
|
35
|
+
* fields that have corresponding environment variables set.
|
|
36
|
+
* Missing env vars are not included in the result.
|
|
37
|
+
*
|
|
38
|
+
* This is useful for batch reading all env vars for a config schema
|
|
39
|
+
* at once, which can then be merged with other config sources.
|
|
40
|
+
*
|
|
41
|
+
* @param fieldPaths - All field paths from schema
|
|
42
|
+
* @param config - Naming configuration
|
|
43
|
+
* @returns Map of field paths to read results (only includes set vars)
|
|
44
|
+
*/
|
|
45
|
+
export declare function readEnvVarsForSchema(fieldPaths: string[], config: EnvVarNamingConfig): Map<string, EnvVarReadResult>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ZodObject, ZodRawShape, z } from 'zod';
|
|
2
|
+
import { EnvVarNamingConfig, EnvVarConfigSource } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve configuration from environment variables
|
|
5
|
+
*
|
|
6
|
+
* This is the main entry point for the env module. It orchestrates:
|
|
7
|
+
* 1. Extracting field paths from the schema
|
|
8
|
+
* 2. Reading environment variables
|
|
9
|
+
* 3. Parsing values according to schema types
|
|
10
|
+
* 4. Validating the final config with Zod
|
|
11
|
+
*
|
|
12
|
+
* Returns null if no environment variables are found, allowing
|
|
13
|
+
* the caller to fall back to other config sources.
|
|
14
|
+
*
|
|
15
|
+
* Throws EnvVarParseError if a value cannot be parsed.
|
|
16
|
+
* Throws EnvVarValidationError if the parsed config fails Zod validation.
|
|
17
|
+
*
|
|
18
|
+
* @param schema - Zod schema defining config structure
|
|
19
|
+
* @param config - Naming configuration (appName, envVarMap)
|
|
20
|
+
* @returns Parsed config object and source information, or null if no env vars found
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveEnvVarConfig<T extends ZodRawShape>(schema: ZodObject<T>, config: EnvVarNamingConfig): Promise<{
|
|
23
|
+
config: z.infer<ZodObject<T>>;
|
|
24
|
+
source: EnvVarConfigSource;
|
|
25
|
+
} | null>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ZodObject, ZodTypeAny } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Extract all field paths from a Zod schema
|
|
4
|
+
*
|
|
5
|
+
* Handles nested objects by flattening to dot notation.
|
|
6
|
+
* This allows us to generate environment variable names for all
|
|
7
|
+
* fields in a schema, including nested ones.
|
|
8
|
+
*
|
|
9
|
+
* Example:
|
|
10
|
+
* schema = z.object({ api: z.object({ key: z.string() }) })
|
|
11
|
+
* extractSchemaFields(schema) => ['api', 'api.key']
|
|
12
|
+
*
|
|
13
|
+
* @param schema - Zod object schema
|
|
14
|
+
* @returns Array of field paths in dot notation
|
|
15
|
+
*/
|
|
16
|
+
export declare function extractSchemaFields(schema: ZodObject<any>): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Get Zod schema for a specific field path
|
|
19
|
+
*
|
|
20
|
+
* Navigates through nested objects using dot notation to find
|
|
21
|
+
* the schema for a specific field. This is used to determine
|
|
22
|
+
* the correct parser for each field.
|
|
23
|
+
*
|
|
24
|
+
* Example:
|
|
25
|
+
* schema = z.object({ api: z.object({ key: z.string() }) })
|
|
26
|
+
* getSchemaForField(schema, 'api.key') => z.string()
|
|
27
|
+
*
|
|
28
|
+
* @param schema - Zod object schema
|
|
29
|
+
* @param fieldPath - Field path in dot notation
|
|
30
|
+
* @returns Zod schema for the field
|
|
31
|
+
* @throws Error if field path is invalid
|
|
32
|
+
*/
|
|
33
|
+
export declare function getSchemaForField(schema: ZodObject<any>, fieldPath: string): ZodTypeAny;
|