@vibe-agent-toolkit/resources 0.1.3 → 0.1.4
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 +0 -17
- package/dist/collection-matcher.d.ts +63 -0
- package/dist/collection-matcher.d.ts.map +1 -0
- package/dist/collection-matcher.js +127 -0
- package/dist/collection-matcher.js.map +1 -0
- package/dist/config-parser.d.ts +63 -0
- package/dist/config-parser.d.ts.map +1 -0
- package/dist/config-parser.js +113 -0
- package/dist/config-parser.js.map +1 -0
- package/dist/frontmatter-validator.d.ts +12 -2
- package/dist/frontmatter-validator.d.ts.map +1 -1
- package/dist/frontmatter-validator.js +174 -18
- package/dist/frontmatter-validator.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/link-validator.d.ts +25 -3
- package/dist/link-validator.d.ts.map +1 -1
- package/dist/link-validator.js +52 -40
- package/dist/link-validator.js.map +1 -1
- package/dist/multi-schema-validator.d.ts +42 -0
- package/dist/multi-schema-validator.d.ts.map +1 -0
- package/dist/multi-schema-validator.js +107 -0
- package/dist/multi-schema-validator.js.map +1 -0
- package/dist/pattern-expander.d.ts +63 -0
- package/dist/pattern-expander.d.ts.map +1 -0
- package/dist/pattern-expander.js +93 -0
- package/dist/pattern-expander.js.map +1 -0
- package/dist/resource-registry.d.ts +87 -6
- package/dist/resource-registry.d.ts.map +1 -1
- package/dist/resource-registry.js +215 -46
- package/dist/resource-registry.js.map +1 -1
- package/dist/schema-assignment.d.ts +49 -0
- package/dist/schema-assignment.d.ts.map +1 -0
- package/dist/schema-assignment.js +95 -0
- package/dist/schema-assignment.js.map +1 -0
- package/dist/schemas/project-config.d.ts +254 -0
- package/dist/schemas/project-config.d.ts.map +1 -0
- package/dist/schemas/project-config.js +57 -0
- package/dist/schemas/project-config.js.map +1 -0
- package/dist/schemas/resource-metadata.d.ts +3 -0
- package/dist/schemas/resource-metadata.d.ts.map +1 -1
- package/dist/schemas/resource-metadata.js +2 -0
- package/dist/schemas/resource-metadata.js.map +1 -1
- package/dist/schemas/validation-result.d.ts +2 -26
- package/dist/schemas/validation-result.d.ts.map +1 -1
- package/dist/schemas/validation-result.js +4 -20
- package/dist/schemas/validation-result.js.map +1 -1
- package/dist/types/resource-parser.d.ts +53 -0
- package/dist/types/resource-parser.d.ts.map +1 -0
- package/dist/types/resource-parser.js +233 -0
- package/dist/types/resource-parser.js.map +1 -0
- package/dist/types/resource-path-utils.d.ts +43 -0
- package/dist/types/resource-path-utils.d.ts.map +1 -0
- package/dist/types/resource-path-utils.js +89 -0
- package/dist/types/resource-path-utils.js.map +1 -0
- package/dist/types/resources.d.ts +140 -0
- package/dist/types/resources.d.ts.map +1 -0
- package/dist/types/resources.js +58 -0
- package/dist/types/resources.js.map +1 -0
- package/dist/types.d.ts +14 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +18 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +39 -0
- package/dist/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/collection-matcher.ts +148 -0
- package/src/config-parser.ts +125 -0
- package/src/frontmatter-validator.ts +202 -18
- package/src/index.ts +7 -2
- package/src/link-validator.ts +70 -43
- package/src/multi-schema-validator.ts +128 -0
- package/src/pattern-expander.ts +100 -0
- package/src/resource-registry.ts +322 -54
- package/src/schema-assignment.ts +119 -0
- package/src/schemas/project-config.ts +71 -0
- package/src/schemas/resource-metadata.ts +2 -0
- package/src/schemas/validation-result.ts +4 -23
- package/src/types/resource-parser.ts +302 -0
- package/src/types/resource-path-utils.ts +102 -0
- package/src/types/resources.ts +211 -0
- package/src/types.ts +81 -1
- package/src/utils.ts +43 -0
package/README.md
CHANGED
|
@@ -63,9 +63,6 @@ Main class for managing collections of markdown resources.
|
|
|
63
63
|
new ResourceRegistry(options?: ResourceRegistryOptions)
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
**Options:**
|
|
67
|
-
- `validateOnAdd?: boolean` - Validate resources immediately when added (default: `false`)
|
|
68
|
-
|
|
69
66
|
#### Methods
|
|
70
67
|
|
|
71
68
|
##### addResource(filePath: string): Promise<ResourceMetadata>
|
|
@@ -906,20 +903,6 @@ for (const [path, issues] of issuesByResource) {
|
|
|
906
903
|
}
|
|
907
904
|
```
|
|
908
905
|
|
|
909
|
-
### Validate on Add
|
|
910
|
-
|
|
911
|
-
Enable strict validation mode to fail fast on broken links:
|
|
912
|
-
|
|
913
|
-
```typescript
|
|
914
|
-
const registry = new ResourceRegistry({ validateOnAdd: true });
|
|
915
|
-
|
|
916
|
-
try {
|
|
917
|
-
await registry.addResource('./docs/broken.md');
|
|
918
|
-
} catch (error) {
|
|
919
|
-
console.error('Validation failed:', error.message);
|
|
920
|
-
}
|
|
921
|
-
```
|
|
922
|
-
|
|
923
906
|
## Examples
|
|
924
907
|
|
|
925
908
|
### Validate Project Documentation
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection matching utilities for determining which collections a file belongs to.
|
|
3
|
+
*
|
|
4
|
+
* Applies include/exclude pattern rules with precedence (exclude wins).
|
|
5
|
+
*/
|
|
6
|
+
import type { CollectionConfig } from './schemas/project-config.js';
|
|
7
|
+
/**
|
|
8
|
+
* Check if a file path matches a collection's include/exclude rules.
|
|
9
|
+
*
|
|
10
|
+
* Rules:
|
|
11
|
+
* - File must match at least one include pattern
|
|
12
|
+
* - File must NOT match any exclude pattern
|
|
13
|
+
* - Exclude always wins over include
|
|
14
|
+
* - Pattern order does not matter
|
|
15
|
+
*
|
|
16
|
+
* Special handling for root-level patterns (*.md, *.json):
|
|
17
|
+
* - These match against the basename only, not the full path
|
|
18
|
+
* - Allows matching root-level files regardless of their absolute path
|
|
19
|
+
*
|
|
20
|
+
* Paths are normalized to forward slashes before matching for cross-platform consistency.
|
|
21
|
+
*
|
|
22
|
+
* @param filePath - Absolute file path to check
|
|
23
|
+
* @param collection - Collection configuration with include/exclude patterns
|
|
24
|
+
* @returns True if file belongs to collection
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const collection = {
|
|
29
|
+
* include: ['docs'],
|
|
30
|
+
* exclude: ['**\/README.md']
|
|
31
|
+
* };
|
|
32
|
+
*
|
|
33
|
+
* matchesCollection('/project/docs/guide.md', collection) // true
|
|
34
|
+
* matchesCollection('/project/docs/README.md', collection) // false (excluded)
|
|
35
|
+
* matchesCollection('/project/src/index.ts', collection) // false (not included)
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function matchesCollection(filePath: string, collection: CollectionConfig): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Find all collections that a file belongs to.
|
|
41
|
+
*
|
|
42
|
+
* A file can belong to multiple collections if it matches their rules.
|
|
43
|
+
*
|
|
44
|
+
* @param filePath - Absolute file path to check
|
|
45
|
+
* @param collections - Map of collection name to collection config
|
|
46
|
+
* @returns Array of collection names the file belongs to
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const collections = {
|
|
51
|
+
* 'rag-kb': { include: ['docs'], exclude: ['**\/README.md'] },
|
|
52
|
+
* 'skills': { include: ['**\/SKILL.md'] }
|
|
53
|
+
* };
|
|
54
|
+
*
|
|
55
|
+
* getCollectionsForFile('/project/docs/guide.md', collections)
|
|
56
|
+
* // ['rag-kb']
|
|
57
|
+
*
|
|
58
|
+
* getCollectionsForFile('/project/docs/SKILL.md', collections)
|
|
59
|
+
* // ['rag-kb', 'skills']
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare function getCollectionsForFile(filePath: string, collections: Record<string, CollectionConfig>): string[];
|
|
63
|
+
//# sourceMappingURL=collection-matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-matcher.d.ts","sourceRoot":"","sources":["../src/collection-matcher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAWpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAuDzF;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAC5C,MAAM,EAAE,CAUV"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection matching utilities for determining which collections a file belongs to.
|
|
3
|
+
*
|
|
4
|
+
* Applies include/exclude pattern rules with precedence (exclude wins).
|
|
5
|
+
*/
|
|
6
|
+
import { basename as getBasename } from 'node:path';
|
|
7
|
+
import { toForwardSlash } from '@vibe-agent-toolkit/utils';
|
|
8
|
+
import picomatch from 'picomatch';
|
|
9
|
+
import { expandPatterns } from './pattern-expander.js';
|
|
10
|
+
/**
|
|
11
|
+
* Check if a pattern is a root-level pattern (e.g., *.md, *.json).
|
|
12
|
+
*
|
|
13
|
+
* Root-level patterns start with * but not **.
|
|
14
|
+
*/
|
|
15
|
+
function isRootLevelPattern(pattern) {
|
|
16
|
+
return pattern.startsWith('*') && !pattern.startsWith('**');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Check if a file path matches a collection's include/exclude rules.
|
|
20
|
+
*
|
|
21
|
+
* Rules:
|
|
22
|
+
* - File must match at least one include pattern
|
|
23
|
+
* - File must NOT match any exclude pattern
|
|
24
|
+
* - Exclude always wins over include
|
|
25
|
+
* - Pattern order does not matter
|
|
26
|
+
*
|
|
27
|
+
* Special handling for root-level patterns (*.md, *.json):
|
|
28
|
+
* - These match against the basename only, not the full path
|
|
29
|
+
* - Allows matching root-level files regardless of their absolute path
|
|
30
|
+
*
|
|
31
|
+
* Paths are normalized to forward slashes before matching for cross-platform consistency.
|
|
32
|
+
*
|
|
33
|
+
* @param filePath - Absolute file path to check
|
|
34
|
+
* @param collection - Collection configuration with include/exclude patterns
|
|
35
|
+
* @returns True if file belongs to collection
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const collection = {
|
|
40
|
+
* include: ['docs'],
|
|
41
|
+
* exclude: ['**\/README.md']
|
|
42
|
+
* };
|
|
43
|
+
*
|
|
44
|
+
* matchesCollection('/project/docs/guide.md', collection) // true
|
|
45
|
+
* matchesCollection('/project/docs/README.md', collection) // false (excluded)
|
|
46
|
+
* matchesCollection('/project/src/index.ts', collection) // false (not included)
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function matchesCollection(filePath, collection) {
|
|
50
|
+
// Normalize to forward slashes for cross-platform consistency
|
|
51
|
+
const normalizedPath = toForwardSlash(filePath);
|
|
52
|
+
// Extract basename for root-level pattern matching
|
|
53
|
+
const basename = getBasename(filePath);
|
|
54
|
+
// Expand patterns (paths → globs)
|
|
55
|
+
const includePatterns = expandPatterns(collection.include);
|
|
56
|
+
const excludePatterns = collection.exclude ? expandPatterns(collection.exclude) : [];
|
|
57
|
+
// Separate root-level patterns from other patterns
|
|
58
|
+
const includeRootPatterns = includePatterns.filter(isRootLevelPattern);
|
|
59
|
+
const includeNonRootPatterns = includePatterns.filter((p) => !isRootLevelPattern(p));
|
|
60
|
+
const excludeRootPatterns = excludePatterns.filter(isRootLevelPattern);
|
|
61
|
+
const excludeNonRootPatterns = excludePatterns.filter((p) => !isRootLevelPattern(p));
|
|
62
|
+
// Check excludes first (exclude wins)
|
|
63
|
+
// Check non-root excludes against full path
|
|
64
|
+
if (excludeNonRootPatterns.length > 0) {
|
|
65
|
+
const excludeMatcher = picomatch(excludeNonRootPatterns);
|
|
66
|
+
if (excludeMatcher(normalizedPath)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Check root-level excludes against basename
|
|
71
|
+
if (excludeRootPatterns.length > 0) {
|
|
72
|
+
const excludeRootMatcher = picomatch(excludeRootPatterns);
|
|
73
|
+
if (excludeRootMatcher(basename)) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Check includes (need to match at least one)
|
|
78
|
+
let matched = false;
|
|
79
|
+
// Check non-root includes against full path
|
|
80
|
+
if (includeNonRootPatterns.length > 0) {
|
|
81
|
+
const includeMatcher = picomatch(includeNonRootPatterns);
|
|
82
|
+
if (includeMatcher(normalizedPath)) {
|
|
83
|
+
matched = true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Check root-level includes against basename
|
|
87
|
+
if (!matched && includeRootPatterns.length > 0) {
|
|
88
|
+
const includeRootMatcher = picomatch(includeRootPatterns);
|
|
89
|
+
if (includeRootMatcher(basename)) {
|
|
90
|
+
matched = true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return matched;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Find all collections that a file belongs to.
|
|
97
|
+
*
|
|
98
|
+
* A file can belong to multiple collections if it matches their rules.
|
|
99
|
+
*
|
|
100
|
+
* @param filePath - Absolute file path to check
|
|
101
|
+
* @param collections - Map of collection name to collection config
|
|
102
|
+
* @returns Array of collection names the file belongs to
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const collections = {
|
|
107
|
+
* 'rag-kb': { include: ['docs'], exclude: ['**\/README.md'] },
|
|
108
|
+
* 'skills': { include: ['**\/SKILL.md'] }
|
|
109
|
+
* };
|
|
110
|
+
*
|
|
111
|
+
* getCollectionsForFile('/project/docs/guide.md', collections)
|
|
112
|
+
* // ['rag-kb']
|
|
113
|
+
*
|
|
114
|
+
* getCollectionsForFile('/project/docs/SKILL.md', collections)
|
|
115
|
+
* // ['rag-kb', 'skills']
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export function getCollectionsForFile(filePath, collections) {
|
|
119
|
+
const matchingCollections = [];
|
|
120
|
+
for (const [name, config] of Object.entries(collections)) {
|
|
121
|
+
if (matchesCollection(filePath, config)) {
|
|
122
|
+
matchingCollections.push(name);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return matchingCollections;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=collection-matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-matcher.js","sourceRoot":"","sources":["../src/collection-matcher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,SAAS,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,OAAe;IACzC,OAAO,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,UAA4B;IAC9E,8DAA8D;IAC9D,MAAM,cAAc,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAEhD,mDAAmD;IACnD,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAEvC,kCAAkC;IAClC,MAAM,eAAe,GAAG,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC3D,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAErF,mDAAmD;IACnD,MAAM,mBAAmB,GAAG,eAAe,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvE,MAAM,sBAAsB,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;IAErF,MAAM,mBAAmB,GAAG,eAAe,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvE,MAAM,sBAAsB,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;IAErF,sCAAsC;IACtC,4CAA4C;IAC5C,IAAI,sBAAsB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,cAAc,GAAG,SAAS,CAAC,sBAAsB,CAAC,CAAC;QACzD,IAAI,cAAc,CAAC,cAAc,CAAC,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,6CAA6C;IAC7C,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,kBAAkB,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC1D,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjC,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,8CAA8C;IAC9C,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,4CAA4C;IAC5C,IAAI,sBAAsB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,cAAc,GAAG,SAAS,CAAC,sBAAsB,CAAC,CAAC;QACzD,IAAI,cAAc,CAAC,cAAc,CAAC,EAAE,CAAC;YACnC,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAED,6CAA6C;IAC7C,IAAI,CAAC,OAAO,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,kBAAkB,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC1D,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjC,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAgB,EAChB,WAA6C;IAE7C,MAAM,mBAAmB,GAAa,EAAE,CAAC;IAEzC,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QACzD,IAAI,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;YACxC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,OAAO,mBAAmB,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration file parser for vibe-agent-toolkit.config.yaml
|
|
3
|
+
*
|
|
4
|
+
* Discovers and parses project configuration files with directory tree walk-up.
|
|
5
|
+
*/
|
|
6
|
+
import { type ProjectConfig } from './schemas/project-config.js';
|
|
7
|
+
/**
|
|
8
|
+
* Find the config file by walking up the directory tree.
|
|
9
|
+
*
|
|
10
|
+
* Starts from the current directory and walks up until the config file is found
|
|
11
|
+
* or the root directory is reached.
|
|
12
|
+
*
|
|
13
|
+
* @param startDir - Directory to start searching from (default: process.cwd())
|
|
14
|
+
* @returns Absolute path to config file, or undefined if not found
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const configPath = await findConfigFile();
|
|
19
|
+
* if (configPath) {
|
|
20
|
+
* console.log(`Found config: ${configPath}`);
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function findConfigFile(startDir?: string): Promise<string | undefined>;
|
|
25
|
+
/**
|
|
26
|
+
* Parse a project configuration file.
|
|
27
|
+
*
|
|
28
|
+
* Reads the YAML file, parses it, and validates against the schema.
|
|
29
|
+
*
|
|
30
|
+
* @param configPath - Absolute path to config file
|
|
31
|
+
* @returns Parsed and validated configuration
|
|
32
|
+
* @throws Error if file cannot be read, YAML is invalid, or validation fails
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const config = await parseConfigFile('/project/vibe-agent-toolkit.config.yaml');
|
|
37
|
+
* console.log(`Version: ${config.version}`);
|
|
38
|
+
* console.log(`Collections: ${Object.keys(config.resources?.collections ?? {}).join(', ')}`);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function parseConfigFile(configPath: string): Promise<ProjectConfig>;
|
|
42
|
+
/**
|
|
43
|
+
* Load project configuration by discovering and parsing config file.
|
|
44
|
+
*
|
|
45
|
+
* Walks up the directory tree from startDir to find the config file,
|
|
46
|
+
* then parses and validates it.
|
|
47
|
+
*
|
|
48
|
+
* @param startDir - Directory to start searching from (default: process.cwd())
|
|
49
|
+
* @returns Parsed configuration, or undefined if no config file found
|
|
50
|
+
* @throws Error if config file is found but cannot be parsed or is invalid
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const config = await loadConfig();
|
|
55
|
+
* if (config) {
|
|
56
|
+
* console.log('Using project config');
|
|
57
|
+
* } else {
|
|
58
|
+
* console.log('No config found, using defaults');
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare function loadConfig(startDir?: string): Promise<ProjectConfig | undefined>;
|
|
63
|
+
//# sourceMappingURL=config-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-parser.d.ts","sourceRoot":"","sources":["../src/config-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAItF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,cAAc,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAwBlG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAqBhF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,UAAU,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAOrG"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration file parser for vibe-agent-toolkit.config.yaml
|
|
3
|
+
*
|
|
4
|
+
* Discovers and parses project configuration files with directory tree walk-up.
|
|
5
|
+
*/
|
|
6
|
+
import { readFile } from 'node:fs/promises';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { load as loadYaml } from 'js-yaml';
|
|
9
|
+
import { ProjectConfigSchema } from './schemas/project-config.js';
|
|
10
|
+
const CONFIG_FILENAME = 'vibe-agent-toolkit.config.yaml';
|
|
11
|
+
/**
|
|
12
|
+
* Find the config file by walking up the directory tree.
|
|
13
|
+
*
|
|
14
|
+
* Starts from the current directory and walks up until the config file is found
|
|
15
|
+
* or the root directory is reached.
|
|
16
|
+
*
|
|
17
|
+
* @param startDir - Directory to start searching from (default: process.cwd())
|
|
18
|
+
* @returns Absolute path to config file, or undefined if not found
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const configPath = await findConfigFile();
|
|
23
|
+
* if (configPath) {
|
|
24
|
+
* console.log(`Found config: ${configPath}`);
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export async function findConfigFile(startDir = process.cwd()) {
|
|
29
|
+
let currentDir = path.resolve(startDir);
|
|
30
|
+
const { root } = path.parse(currentDir);
|
|
31
|
+
while (true) {
|
|
32
|
+
const configPath = path.join(currentDir, CONFIG_FILENAME);
|
|
33
|
+
try {
|
|
34
|
+
// Check if file exists by attempting to read metadata
|
|
35
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- constructing path during tree walk
|
|
36
|
+
await readFile(configPath, 'utf-8');
|
|
37
|
+
return configPath;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// File doesn't exist, continue walking up
|
|
41
|
+
}
|
|
42
|
+
// Check if we've reached the root
|
|
43
|
+
if (currentDir === root) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
// Move up one directory
|
|
47
|
+
currentDir = path.dirname(currentDir);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Parse a project configuration file.
|
|
52
|
+
*
|
|
53
|
+
* Reads the YAML file, parses it, and validates against the schema.
|
|
54
|
+
*
|
|
55
|
+
* @param configPath - Absolute path to config file
|
|
56
|
+
* @returns Parsed and validated configuration
|
|
57
|
+
* @throws Error if file cannot be read, YAML is invalid, or validation fails
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const config = await parseConfigFile('/project/vibe-agent-toolkit.config.yaml');
|
|
62
|
+
* console.log(`Version: ${config.version}`);
|
|
63
|
+
* console.log(`Collections: ${Object.keys(config.resources?.collections ?? {}).join(', ')}`);
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export async function parseConfigFile(configPath) {
|
|
67
|
+
// Read file content
|
|
68
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- configPath is from findConfigFile() walk-up
|
|
69
|
+
const content = await readFile(configPath, 'utf-8');
|
|
70
|
+
// Parse YAML
|
|
71
|
+
let parsed;
|
|
72
|
+
try {
|
|
73
|
+
parsed = loadYaml(content);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
throw new Error(`Invalid YAML in config file: ${error instanceof Error ? error.message : String(error)}`);
|
|
77
|
+
}
|
|
78
|
+
// Validate against schema
|
|
79
|
+
const result = ProjectConfigSchema.safeParse(parsed);
|
|
80
|
+
if (!result.success) {
|
|
81
|
+
const errors = result.error.errors.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
|
82
|
+
throw new Error(`Invalid config file: ${errors}`);
|
|
83
|
+
}
|
|
84
|
+
return result.data;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Load project configuration by discovering and parsing config file.
|
|
88
|
+
*
|
|
89
|
+
* Walks up the directory tree from startDir to find the config file,
|
|
90
|
+
* then parses and validates it.
|
|
91
|
+
*
|
|
92
|
+
* @param startDir - Directory to start searching from (default: process.cwd())
|
|
93
|
+
* @returns Parsed configuration, or undefined if no config file found
|
|
94
|
+
* @throws Error if config file is found but cannot be parsed or is invalid
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const config = await loadConfig();
|
|
99
|
+
* if (config) {
|
|
100
|
+
* console.log('Using project config');
|
|
101
|
+
* } else {
|
|
102
|
+
* console.log('No config found, using defaults');
|
|
103
|
+
* }
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export async function loadConfig(startDir = process.cwd()) {
|
|
107
|
+
const configPath = await findConfigFile(startDir);
|
|
108
|
+
if (!configPath) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
return await parseConfigFile(configPath);
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=config-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-parser.js","sourceRoot":"","sources":["../src/config-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,EAAE,mBAAmB,EAAsB,MAAM,6BAA6B,CAAC;AAEtF,MAAM,eAAe,GAAG,gCAAgC,CAAC;AAEzD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IACnE,IAAI,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAExC,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QAE1D,IAAI,CAAC;YACH,sDAAsD;YACtD,yGAAyG;YACzG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACpC,OAAO,UAAU,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,0CAA0C;QAC5C,CAAC;QAED,kCAAkC;QAClC,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,wBAAwB;QACxB,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAkB;IACtD,oBAAoB;IACpB,kHAAkH;IAClH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAEpD,aAAa;IACb,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5G,CAAC;IAED,0BAA0B;IAC1B,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACrD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9F,MAAM,IAAI,KAAK,CAAC,wBAAwB,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IAC/D,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;IAClD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,MAAM,eAAe,CAAC,UAAU,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* This is the ONLY place in the codebase that should use AJV.
|
|
14
14
|
*/
|
|
15
|
+
import type { ValidationMode } from './schemas/project-config.js';
|
|
15
16
|
import type { ValidationIssue } from './schemas/validation-result.js';
|
|
16
17
|
/**
|
|
17
18
|
* Validate frontmatter against a JSON Schema.
|
|
@@ -20,10 +21,13 @@ import type { ValidationIssue } from './schemas/validation-result.js';
|
|
|
20
21
|
* - Missing frontmatter: Error only if schema has required fields
|
|
21
22
|
* - Extra fields: Allowed by default (unless schema sets additionalProperties: false)
|
|
22
23
|
* - Type mismatches: Always reported as errors
|
|
24
|
+
* - Permissive mode: Ignores additionalProperties: false (allows schema layering)
|
|
23
25
|
*
|
|
24
26
|
* @param frontmatter - Parsed frontmatter object (or undefined if no frontmatter)
|
|
25
27
|
* @param schema - JSON Schema object
|
|
26
28
|
* @param resourcePath - File path for error reporting
|
|
29
|
+
* @param mode - Validation mode: 'strict' (default) or 'permissive'
|
|
30
|
+
* @param schemaPath - Path to schema file (for error context)
|
|
27
31
|
* @returns Array of validation issues (empty if valid)
|
|
28
32
|
*
|
|
29
33
|
* @example
|
|
@@ -33,8 +37,14 @@ import type { ValidationIssue } from './schemas/validation-result.js';
|
|
|
33
37
|
* required: ['title'],
|
|
34
38
|
* properties: { title: { type: 'string' } }
|
|
35
39
|
* };
|
|
36
|
-
* const issues = validateFrontmatter(
|
|
40
|
+
* const issues = validateFrontmatter(
|
|
41
|
+
* frontmatter,
|
|
42
|
+
* schema,
|
|
43
|
+
* '/docs/guide.md',
|
|
44
|
+
* 'strict',
|
|
45
|
+
* '/schema.json'
|
|
46
|
+
* );
|
|
37
47
|
* ```
|
|
38
48
|
*/
|
|
39
|
-
export declare function validateFrontmatter(frontmatter: Record<string, unknown> | undefined, schema: object, resourcePath: string): ValidationIssue[];
|
|
49
|
+
export declare function validateFrontmatter(frontmatter: Record<string, unknown> | undefined, schema: object, resourcePath: string, mode?: ValidationMode, schemaPath?: string): ValidationIssue[];
|
|
40
50
|
//# sourceMappingURL=frontmatter-validator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter-validator.d.ts","sourceRoot":"","sources":["../src/frontmatter-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE
|
|
1
|
+
{"version":3,"file":"frontmatter-validator.d.ts","sourceRoot":"","sources":["../src/frontmatter-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAChD,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE,cAAyB,EAC/B,UAAU,CAAC,EAAE,MAAM,GAClB,eAAe,EAAE,CA0DnB"}
|