@eddacraft/anvil-adapters 0.1.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/AGENTS.md +180 -0
- package/BMAD_ADAPTER_SPEC.md +489 -0
- package/LICENSE +14 -0
- package/README.md +500 -0
- package/dist/aps-markdown/adapter.d.ts +102 -0
- package/dist/aps-markdown/adapter.d.ts.map +1 -0
- package/dist/aps-markdown/adapter.js +351 -0
- package/dist/aps-markdown/index.d.ts +8 -0
- package/dist/aps-markdown/index.d.ts.map +1 -0
- package/dist/aps-markdown/index.js +7 -0
- package/dist/base/file-discovery.d.ts +63 -0
- package/dist/base/file-discovery.d.ts.map +1 -0
- package/dist/base/file-discovery.js +246 -0
- package/dist/base/index.d.ts +10 -0
- package/dist/base/index.d.ts.map +1 -0
- package/dist/base/index.js +9 -0
- package/dist/base/registry.d.ts +155 -0
- package/dist/base/registry.d.ts.map +1 -0
- package/dist/base/registry.js +227 -0
- package/dist/base/testing.d.ts +102 -0
- package/dist/base/testing.d.ts.map +1 -0
- package/dist/base/testing.js +221 -0
- package/dist/base/types.d.ts +255 -0
- package/dist/base/types.d.ts.map +1 -0
- package/dist/base/types.js +78 -0
- package/dist/base/utils.d.ts +127 -0
- package/dist/base/utils.d.ts.map +1 -0
- package/dist/base/utils.js +254 -0
- package/dist/bmad/format-adapter.d.ts +76 -0
- package/dist/bmad/format-adapter.d.ts.map +1 -0
- package/dist/bmad/format-adapter.js +186 -0
- package/dist/bmad/index.d.ts +12 -0
- package/dist/bmad/index.d.ts.map +1 -0
- package/dist/bmad/index.js +10 -0
- package/dist/bmad/parser.d.ts +12 -0
- package/dist/bmad/parser.d.ts.map +1 -0
- package/dist/bmad/parser.js +181 -0
- package/dist/bmad/serializer.d.ts +16 -0
- package/dist/bmad/serializer.d.ts.map +1 -0
- package/dist/bmad/serializer.js +170 -0
- package/dist/bmad/types.d.ts +127 -0
- package/dist/bmad/types.d.ts.map +1 -0
- package/dist/bmad/types.js +47 -0
- package/dist/bmad/utils.d.ts +120 -0
- package/dist/bmad/utils.d.ts.map +1 -0
- package/dist/bmad/utils.js +480 -0
- package/dist/common/index.d.ts +3 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/index.js +2 -0
- package/dist/common/registry.d.ts +18 -0
- package/dist/common/registry.d.ts.map +1 -0
- package/dist/common/registry.js +58 -0
- package/dist/common/types.d.ts +68 -0
- package/dist/common/types.d.ts.map +1 -0
- package/dist/common/types.js +12 -0
- package/dist/generic/format-adapter.d.ts +64 -0
- package/dist/generic/format-adapter.d.ts.map +1 -0
- package/dist/generic/format-adapter.js +159 -0
- package/dist/generic/index.d.ts +10 -0
- package/dist/generic/index.d.ts.map +1 -0
- package/dist/generic/index.js +9 -0
- package/dist/generic/parser.d.ts +11 -0
- package/dist/generic/parser.d.ts.map +1 -0
- package/dist/generic/parser.js +106 -0
- package/dist/generic/serializer.d.ts +11 -0
- package/dist/generic/serializer.d.ts.map +1 -0
- package/dist/generic/serializer.js +118 -0
- package/dist/generic/types.d.ts +52 -0
- package/dist/generic/types.d.ts.map +1 -0
- package/dist/generic/types.js +6 -0
- package/dist/generic/utils.d.ts +51 -0
- package/dist/generic/utils.d.ts.map +1 -0
- package/dist/generic/utils.js +232 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/speckit/export.d.ts +22 -0
- package/dist/speckit/export.d.ts.map +1 -0
- package/dist/speckit/export.js +384 -0
- package/dist/speckit/format-adapter.d.ts +104 -0
- package/dist/speckit/format-adapter.d.ts.map +1 -0
- package/dist/speckit/format-adapter.js +488 -0
- package/dist/speckit/import-v2.d.ts +33 -0
- package/dist/speckit/import-v2.d.ts.map +1 -0
- package/dist/speckit/import-v2.js +361 -0
- package/dist/speckit/import.d.ts +16 -0
- package/dist/speckit/import.d.ts.map +1 -0
- package/dist/speckit/import.js +247 -0
- package/dist/speckit/index.d.ts +5 -0
- package/dist/speckit/index.d.ts.map +1 -0
- package/dist/speckit/index.js +4 -0
- package/dist/speckit/parser.d.ts +28 -0
- package/dist/speckit/parser.d.ts.map +1 -0
- package/dist/speckit/parser.js +283 -0
- package/dist/speckit/parsers/plan-parser.d.ts +71 -0
- package/dist/speckit/parsers/plan-parser.d.ts.map +1 -0
- package/dist/speckit/parsers/plan-parser.js +216 -0
- package/dist/speckit/parsers/spec-parser.d.ts +67 -0
- package/dist/speckit/parsers/spec-parser.d.ts.map +1 -0
- package/dist/speckit/parsers/spec-parser.js +255 -0
- package/dist/speckit/parsers/tasks-parser.d.ts +57 -0
- package/dist/speckit/parsers/tasks-parser.d.ts.map +1 -0
- package/dist/speckit/parsers/tasks-parser.js +157 -0
- package/package.json +23 -0
- package/project.json +29 -0
- package/src/__tests__/adapter-edge-cases.test.ts +937 -0
- package/src/__tests__/bmad-format-adapter.test.ts +1470 -0
- package/src/__tests__/fixtures/aps/expected-output.json +83 -0
- package/src/__tests__/fixtures/bmad/invalid-malformed-yaml.md +16 -0
- package/src/__tests__/fixtures/bmad/invalid-no-requirements.md +23 -0
- package/src/__tests__/fixtures/bmad/invalid-only-yaml.md +16 -0
- package/src/__tests__/fixtures/bmad/invalid-too-short.md +3 -0
- package/src/__tests__/fixtures/bmad/invalid-wrong-format.md +40 -0
- package/src/__tests__/fixtures/bmad/valid-agent.md +27 -0
- package/src/__tests__/fixtures/bmad/valid-architecture.md +116 -0
- package/src/__tests__/fixtures/bmad/valid-complex-prd.md +161 -0
- package/src/__tests__/fixtures/bmad/valid-epic.md +73 -0
- package/src/__tests__/fixtures/bmad/valid-minimal-prd.md +19 -0
- package/src/__tests__/fixtures/bmad/valid-prd.md +107 -0
- package/src/__tests__/fixtures/bmad/valid-story.md +107 -0
- package/src/__tests__/fixtures/bmad/valid-task.md +79 -0
- package/src/__tests__/fixtures/bmad/valid-v6-prd.md +35 -0
- package/src/__tests__/fixtures/generic/plan-detailed.md +39 -0
- package/src/__tests__/fixtures/generic/prd-simple.md +27 -0
- package/src/__tests__/fixtures/generic/rfc-example.md +26 -0
- package/src/__tests__/fixtures/generic/todo-list.md +23 -0
- package/src/__tests__/fixtures/speckit/sample-plan.md +63 -0
- package/src/__tests__/fixtures/speckit/sample-spec-namespaced.md +50 -0
- package/src/__tests__/fixtures/speckit/sample-spec.md +105 -0
- package/src/__tests__/fixtures/speckit/sample-tasks.md +87 -0
- package/src/__tests__/fixtures/speckit-official/auth-feature/plan.md +272 -0
- package/src/__tests__/fixtures/speckit-official/auth-feature/spec.md +149 -0
- package/src/__tests__/fixtures/speckit-official/auth-feature/tasks.md +169 -0
- package/src/__tests__/generic-format-adapter.test.ts +398 -0
- package/src/__tests__/speckit-export.test.ts +233 -0
- package/src/__tests__/speckit-format-adapter.test.ts +832 -0
- package/src/__tests__/speckit-import-v2.test.ts +253 -0
- package/src/__tests__/speckit-import.test.ts +209 -0
- package/src/__tests__/speckit-parser.test.ts +219 -0
- package/src/__tests__/speckit-spec-parser.test.ts +120 -0
- package/src/aps-markdown/__tests__/__fixtures__/simple-leaf.aps.md +17 -0
- package/src/aps-markdown/__tests__/adapter.test.ts +393 -0
- package/src/aps-markdown/adapter.ts +455 -0
- package/src/aps-markdown/index.ts +8 -0
- package/src/base/__tests__/registry.test.ts +515 -0
- package/src/base/file-discovery.ts +305 -0
- package/src/base/index.ts +10 -0
- package/src/base/registry.ts +263 -0
- package/src/base/testing.ts +334 -0
- package/src/base/types.ts +342 -0
- package/src/base/utils.ts +306 -0
- package/src/bmad/format-adapter.ts +227 -0
- package/src/bmad/index.ts +21 -0
- package/src/bmad/parser.ts +224 -0
- package/src/bmad/serializer.ts +206 -0
- package/src/bmad/types.ts +135 -0
- package/src/bmad/utils.ts +575 -0
- package/src/common/index.ts +2 -0
- package/src/common/registry.ts +72 -0
- package/src/common/types.ts +84 -0
- package/src/generic/__tests__/serializer.test.ts +167 -0
- package/src/generic/format-adapter.ts +200 -0
- package/src/generic/index.ts +11 -0
- package/src/generic/parser.ts +129 -0
- package/src/generic/serializer.ts +134 -0
- package/src/generic/types.ts +53 -0
- package/src/generic/utils.ts +270 -0
- package/src/index.ts +48 -0
- package/src/speckit/export.ts +489 -0
- package/src/speckit/format-adapter.ts +595 -0
- package/src/speckit/import-v2.ts +445 -0
- package/src/speckit/import.ts +305 -0
- package/src/speckit/index.ts +4 -0
- package/src/speckit/parser.ts +351 -0
- package/src/speckit/parsers/plan-parser.ts +342 -0
- package/src/speckit/parsers/spec-parser.ts +379 -0
- package/src/speckit/parsers/tasks-parser.ts +246 -0
- package/tsconfig.json +26 -0
- package/tsconfig.lib.json +21 -0
- package/tsconfig.lib.tsbuildinfo +1 -0
- package/tsconfig.spec.json +9 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +14 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/base/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter Registry
|
|
3
|
+
*
|
|
4
|
+
* Central registry for format adapters with auto-detection and lookup capabilities.
|
|
5
|
+
*/
|
|
6
|
+
import type { FormatAdapter, DetectionResult, PathDetectionHint } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Registry for managing format adapters
|
|
9
|
+
*
|
|
10
|
+
* Provides:
|
|
11
|
+
* - Adapter registration and lookup
|
|
12
|
+
* - Auto-detection of formats from content
|
|
13
|
+
* - Extension-based adapter selection
|
|
14
|
+
*/
|
|
15
|
+
export declare class AdapterRegistry {
|
|
16
|
+
private static instance;
|
|
17
|
+
private adapters;
|
|
18
|
+
private constructor();
|
|
19
|
+
/**
|
|
20
|
+
* Get singleton instance
|
|
21
|
+
*/
|
|
22
|
+
static getInstance(): AdapterRegistry;
|
|
23
|
+
/**
|
|
24
|
+
* Reset singleton instance (useful for testing)
|
|
25
|
+
*/
|
|
26
|
+
static resetInstance(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Register an adapter
|
|
29
|
+
*
|
|
30
|
+
* @param adapter - Adapter to register
|
|
31
|
+
* @throws Error if adapter with same name already registered
|
|
32
|
+
*/
|
|
33
|
+
register(adapter: FormatAdapter): void;
|
|
34
|
+
/**
|
|
35
|
+
* Unregister an adapter by name
|
|
36
|
+
*
|
|
37
|
+
* @param name - Name of adapter to unregister
|
|
38
|
+
* @returns True if adapter was removed, false if not found
|
|
39
|
+
*/
|
|
40
|
+
unregister(name: string): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Get adapter by name
|
|
43
|
+
*
|
|
44
|
+
* @param name - Adapter name
|
|
45
|
+
* @returns Adapter instance or undefined
|
|
46
|
+
*/
|
|
47
|
+
getAdapter(name: string): FormatAdapter | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Get adapter for a specific format identifier or extension
|
|
50
|
+
*
|
|
51
|
+
* @param format - Format identifier (e.g., "speckit") or extension (e.g., ".md")
|
|
52
|
+
* @returns First matching adapter or undefined
|
|
53
|
+
*/
|
|
54
|
+
getAdapterForFormat(format: string): FormatAdapter | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Detect adapter from content
|
|
57
|
+
*
|
|
58
|
+
* Runs detection on all registered adapters and returns the best match.
|
|
59
|
+
*
|
|
60
|
+
* @param content - Content to analyze
|
|
61
|
+
* @param minConfidence - Minimum confidence score (0-100) to accept
|
|
62
|
+
* @returns Best matching adapter and detection result, or undefined
|
|
63
|
+
*/
|
|
64
|
+
detectAdapter(content: string, minConfidence?: number): {
|
|
65
|
+
adapter: FormatAdapter;
|
|
66
|
+
detection: DetectionResult;
|
|
67
|
+
} | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Detect adapter from content with path hints
|
|
70
|
+
*
|
|
71
|
+
* Like detectAdapter but passes file path information to adapters
|
|
72
|
+
* that implement detectWithPath for improved accuracy.
|
|
73
|
+
*
|
|
74
|
+
* @param content - Content to analyze
|
|
75
|
+
* @param hint - File path and directory information
|
|
76
|
+
* @param minConfidence - Minimum confidence score (0-100) to accept
|
|
77
|
+
* @returns Best matching adapter and detection result, or undefined
|
|
78
|
+
*/
|
|
79
|
+
detectAdapterWithPath(content: string, hint: PathDetectionHint, minConfidence?: number): {
|
|
80
|
+
adapter: FormatAdapter;
|
|
81
|
+
detection: DetectionResult;
|
|
82
|
+
} | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Get all detection results for content
|
|
85
|
+
*
|
|
86
|
+
* Useful for debugging or showing user multiple format possibilities.
|
|
87
|
+
*
|
|
88
|
+
* @param content - Content to analyze
|
|
89
|
+
* @returns Array of detection results for all adapters, sorted by confidence
|
|
90
|
+
*/
|
|
91
|
+
detectAll(content: string): Array<{
|
|
92
|
+
adapter: FormatAdapter;
|
|
93
|
+
detection: DetectionResult;
|
|
94
|
+
}>;
|
|
95
|
+
/**
|
|
96
|
+
* List all registered adapters
|
|
97
|
+
*
|
|
98
|
+
* @returns Array of all adapters
|
|
99
|
+
*/
|
|
100
|
+
listAdapters(): ReadonlyArray<FormatAdapter>;
|
|
101
|
+
/**
|
|
102
|
+
* List all adapter names
|
|
103
|
+
*
|
|
104
|
+
* @returns Array of adapter names
|
|
105
|
+
*/
|
|
106
|
+
listAdapterNames(): ReadonlyArray<string>;
|
|
107
|
+
/**
|
|
108
|
+
* List all supported formats across all adapters
|
|
109
|
+
*
|
|
110
|
+
* @returns Array of unique format identifiers
|
|
111
|
+
*/
|
|
112
|
+
listSupportedFormats(): ReadonlyArray<string>;
|
|
113
|
+
/**
|
|
114
|
+
* List all supported extensions across all adapters
|
|
115
|
+
*
|
|
116
|
+
* @returns Array of unique file extensions
|
|
117
|
+
*/
|
|
118
|
+
listSupportedExtensions(): ReadonlyArray<string>;
|
|
119
|
+
/**
|
|
120
|
+
* Get adapters that can import a specific format
|
|
121
|
+
*
|
|
122
|
+
* @param format - Format identifier or extension
|
|
123
|
+
* @returns Array of adapters that support this format for import
|
|
124
|
+
*/
|
|
125
|
+
getImportAdapters(format: string): ReadonlyArray<FormatAdapter>;
|
|
126
|
+
/**
|
|
127
|
+
* Get adapters that can export to a specific format
|
|
128
|
+
*
|
|
129
|
+
* @param format - Format identifier or extension
|
|
130
|
+
* @returns Array of adapters that support this format for export
|
|
131
|
+
*/
|
|
132
|
+
getExportAdapters(format: string): ReadonlyArray<FormatAdapter>;
|
|
133
|
+
/**
|
|
134
|
+
* Check if any adapter supports a format
|
|
135
|
+
*
|
|
136
|
+
* @param format - Format identifier or extension
|
|
137
|
+
* @returns True if at least one adapter supports this format
|
|
138
|
+
*/
|
|
139
|
+
isFormatSupported(format: string): boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Clear all registered adapters
|
|
142
|
+
*
|
|
143
|
+
* Mainly useful for testing.
|
|
144
|
+
*/
|
|
145
|
+
clear(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Get number of registered adapters
|
|
148
|
+
*/
|
|
149
|
+
get size(): number;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Default singleton instance
|
|
153
|
+
*/
|
|
154
|
+
export declare const registry: AdapterRegistry;
|
|
155
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/base/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpF;;;;;;;GAOG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAyC;IAEzD,OAAO;IAEP;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,eAAe;IAOrC;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI;IAI5B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAOtC;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAInD;;;;;OAKG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAS9D;;;;;;;;OAQG;IACH,aAAa,CACX,OAAO,EAAE,MAAM,EACf,aAAa,GAAE,MAAW,GACzB;QAAE,OAAO,EAAE,aAAa,CAAC;QAAC,SAAS,EAAE,eAAe,CAAA;KAAE,GAAG,SAAS;IAerE;;;;;;;;;;OAUG;IACH,qBAAqB,CACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,iBAAiB,EACvB,aAAa,GAAE,MAAW,GACzB;QAAE,OAAO,EAAE,aAAa,CAAC;QAAC,SAAS,EAAE,eAAe,CAAA;KAAE,GAAG,SAAS;IAkBrE;;;;;;;OAOG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,OAAO,EAAE,aAAa,CAAC;QAAC,SAAS,EAAE,eAAe,CAAA;KAAE,CAAC;IASzF;;;;OAIG;IACH,YAAY,IAAI,aAAa,CAAC,aAAa,CAAC;IAI5C;;;;OAIG;IACH,gBAAgB,IAAI,aAAa,CAAC,MAAM,CAAC;IAIzC;;;;OAIG;IACH,oBAAoB,IAAI,aAAa,CAAC,MAAM,CAAC;IAU7C;;;;OAIG;IACH,uBAAuB,IAAI,aAAa,CAAC,MAAM,CAAC;IAUhD;;;;;OAKG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,aAAa,CAAC;IAI/D;;;;;OAKG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,aAAa,CAAC;IAI/D;;;;;OAKG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAI1C;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ,iBAAgC,CAAC"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter Registry
|
|
3
|
+
*
|
|
4
|
+
* Central registry for format adapters with auto-detection and lookup capabilities.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Registry for managing format adapters
|
|
8
|
+
*
|
|
9
|
+
* Provides:
|
|
10
|
+
* - Adapter registration and lookup
|
|
11
|
+
* - Auto-detection of formats from content
|
|
12
|
+
* - Extension-based adapter selection
|
|
13
|
+
*/
|
|
14
|
+
export class AdapterRegistry {
|
|
15
|
+
static instance = null;
|
|
16
|
+
adapters = new Map();
|
|
17
|
+
constructor() { }
|
|
18
|
+
/**
|
|
19
|
+
* Get singleton instance
|
|
20
|
+
*/
|
|
21
|
+
static getInstance() {
|
|
22
|
+
if (!AdapterRegistry.instance) {
|
|
23
|
+
AdapterRegistry.instance = new AdapterRegistry();
|
|
24
|
+
}
|
|
25
|
+
return AdapterRegistry.instance;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Reset singleton instance (useful for testing)
|
|
29
|
+
*/
|
|
30
|
+
static resetInstance() {
|
|
31
|
+
AdapterRegistry.instance = null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Register an adapter
|
|
35
|
+
*
|
|
36
|
+
* @param adapter - Adapter to register
|
|
37
|
+
* @throws Error if adapter with same name already registered
|
|
38
|
+
*/
|
|
39
|
+
register(adapter) {
|
|
40
|
+
if (this.adapters.has(adapter.metadata.name)) {
|
|
41
|
+
throw new Error(`Adapter '${adapter.metadata.name}' is already registered`);
|
|
42
|
+
}
|
|
43
|
+
this.adapters.set(adapter.metadata.name, adapter);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Unregister an adapter by name
|
|
47
|
+
*
|
|
48
|
+
* @param name - Name of adapter to unregister
|
|
49
|
+
* @returns True if adapter was removed, false if not found
|
|
50
|
+
*/
|
|
51
|
+
unregister(name) {
|
|
52
|
+
return this.adapters.delete(name);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get adapter by name
|
|
56
|
+
*
|
|
57
|
+
* @param name - Adapter name
|
|
58
|
+
* @returns Adapter instance or undefined
|
|
59
|
+
*/
|
|
60
|
+
getAdapter(name) {
|
|
61
|
+
return this.adapters.get(name);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get adapter for a specific format identifier or extension
|
|
65
|
+
*
|
|
66
|
+
* @param format - Format identifier (e.g., "speckit") or extension (e.g., ".md")
|
|
67
|
+
* @returns First matching adapter or undefined
|
|
68
|
+
*/
|
|
69
|
+
getAdapterForFormat(format) {
|
|
70
|
+
for (const adapter of this.adapters.values()) {
|
|
71
|
+
if (adapter.canImport(format)) {
|
|
72
|
+
return adapter;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Detect adapter from content
|
|
79
|
+
*
|
|
80
|
+
* Runs detection on all registered adapters and returns the best match.
|
|
81
|
+
*
|
|
82
|
+
* @param content - Content to analyze
|
|
83
|
+
* @param minConfidence - Minimum confidence score (0-100) to accept
|
|
84
|
+
* @returns Best matching adapter and detection result, or undefined
|
|
85
|
+
*/
|
|
86
|
+
detectAdapter(content, minConfidence = 50) {
|
|
87
|
+
let bestMatch;
|
|
88
|
+
let bestConfidence = minConfidence - 1;
|
|
89
|
+
for (const adapter of this.adapters.values()) {
|
|
90
|
+
const detection = adapter.detect(content);
|
|
91
|
+
if (detection.detected && detection.confidence > bestConfidence) {
|
|
92
|
+
bestConfidence = detection.confidence;
|
|
93
|
+
bestMatch = { adapter, detection };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return bestMatch;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Detect adapter from content with path hints
|
|
100
|
+
*
|
|
101
|
+
* Like detectAdapter but passes file path information to adapters
|
|
102
|
+
* that implement detectWithPath for improved accuracy.
|
|
103
|
+
*
|
|
104
|
+
* @param content - Content to analyze
|
|
105
|
+
* @param hint - File path and directory information
|
|
106
|
+
* @param minConfidence - Minimum confidence score (0-100) to accept
|
|
107
|
+
* @returns Best matching adapter and detection result, or undefined
|
|
108
|
+
*/
|
|
109
|
+
detectAdapterWithPath(content, hint, minConfidence = 50) {
|
|
110
|
+
let bestMatch;
|
|
111
|
+
let bestConfidence = minConfidence - 1;
|
|
112
|
+
for (const adapter of this.adapters.values()) {
|
|
113
|
+
const detection = adapter.detectWithPath
|
|
114
|
+
? adapter.detectWithPath(content, hint)
|
|
115
|
+
: adapter.detect(content);
|
|
116
|
+
if (detection.detected && detection.confidence > bestConfidence) {
|
|
117
|
+
bestConfidence = detection.confidence;
|
|
118
|
+
bestMatch = { adapter, detection };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return bestMatch;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get all detection results for content
|
|
125
|
+
*
|
|
126
|
+
* Useful for debugging or showing user multiple format possibilities.
|
|
127
|
+
*
|
|
128
|
+
* @param content - Content to analyze
|
|
129
|
+
* @returns Array of detection results for all adapters, sorted by confidence
|
|
130
|
+
*/
|
|
131
|
+
detectAll(content) {
|
|
132
|
+
const results = Array.from(this.adapters.values()).map((adapter) => ({
|
|
133
|
+
adapter,
|
|
134
|
+
detection: adapter.detect(content),
|
|
135
|
+
}));
|
|
136
|
+
return results.sort((a, b) => b.detection.confidence - a.detection.confidence);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* List all registered adapters
|
|
140
|
+
*
|
|
141
|
+
* @returns Array of all adapters
|
|
142
|
+
*/
|
|
143
|
+
listAdapters() {
|
|
144
|
+
return Array.from(this.adapters.values());
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* List all adapter names
|
|
148
|
+
*
|
|
149
|
+
* @returns Array of adapter names
|
|
150
|
+
*/
|
|
151
|
+
listAdapterNames() {
|
|
152
|
+
return Array.from(this.adapters.keys());
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* List all supported formats across all adapters
|
|
156
|
+
*
|
|
157
|
+
* @returns Array of unique format identifiers
|
|
158
|
+
*/
|
|
159
|
+
listSupportedFormats() {
|
|
160
|
+
const formats = new Set();
|
|
161
|
+
for (const adapter of this.adapters.values()) {
|
|
162
|
+
for (const format of adapter.metadata.formats) {
|
|
163
|
+
formats.add(format);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return Array.from(formats).sort();
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* List all supported extensions across all adapters
|
|
170
|
+
*
|
|
171
|
+
* @returns Array of unique file extensions
|
|
172
|
+
*/
|
|
173
|
+
listSupportedExtensions() {
|
|
174
|
+
const extensions = new Set();
|
|
175
|
+
for (const adapter of this.adapters.values()) {
|
|
176
|
+
for (const ext of adapter.metadata.extensions) {
|
|
177
|
+
extensions.add(ext);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return Array.from(extensions).sort();
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get adapters that can import a specific format
|
|
184
|
+
*
|
|
185
|
+
* @param format - Format identifier or extension
|
|
186
|
+
* @returns Array of adapters that support this format for import
|
|
187
|
+
*/
|
|
188
|
+
getImportAdapters(format) {
|
|
189
|
+
return Array.from(this.adapters.values()).filter((adapter) => adapter.canImport(format));
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get adapters that can export to a specific format
|
|
193
|
+
*
|
|
194
|
+
* @param format - Format identifier or extension
|
|
195
|
+
* @returns Array of adapters that support this format for export
|
|
196
|
+
*/
|
|
197
|
+
getExportAdapters(format) {
|
|
198
|
+
return Array.from(this.adapters.values()).filter((adapter) => adapter.canExport(format));
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Check if any adapter supports a format
|
|
202
|
+
*
|
|
203
|
+
* @param format - Format identifier or extension
|
|
204
|
+
* @returns True if at least one adapter supports this format
|
|
205
|
+
*/
|
|
206
|
+
isFormatSupported(format) {
|
|
207
|
+
return this.getAdapterForFormat(format) !== undefined;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Clear all registered adapters
|
|
211
|
+
*
|
|
212
|
+
* Mainly useful for testing.
|
|
213
|
+
*/
|
|
214
|
+
clear() {
|
|
215
|
+
this.adapters.clear();
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Get number of registered adapters
|
|
219
|
+
*/
|
|
220
|
+
get size() {
|
|
221
|
+
return this.adapters.size;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Default singleton instance
|
|
226
|
+
*/
|
|
227
|
+
export const registry = AdapterRegistry.getInstance();
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter Testing Utilities
|
|
3
|
+
*
|
|
4
|
+
* Helpers for testing format adapters with common patterns and assertions.
|
|
5
|
+
*/
|
|
6
|
+
import type { FormatAdapter, ParseResult, SerializeResult, DetectionResult, ParseContext, AdapterOptions } from './types.js';
|
|
7
|
+
import type { APSPlan } from '@eddacraft/anvil-core';
|
|
8
|
+
/**
|
|
9
|
+
* Test fixture for adapter testing
|
|
10
|
+
*/
|
|
11
|
+
export interface AdapterTestFixture {
|
|
12
|
+
/** Name of the test case */
|
|
13
|
+
name: string;
|
|
14
|
+
/** Raw content in external format */
|
|
15
|
+
content: string;
|
|
16
|
+
/** Expected detection result (optional) */
|
|
17
|
+
expectedDetection?: Partial<DetectionResult>;
|
|
18
|
+
/** Expected parse success (optional) */
|
|
19
|
+
expectParseSuccess?: boolean;
|
|
20
|
+
/** Context for parsing */
|
|
21
|
+
parseContext?: ParseContext;
|
|
22
|
+
/** Options for operations */
|
|
23
|
+
options?: AdapterOptions;
|
|
24
|
+
/** Expected values in parsed plan (optional) */
|
|
25
|
+
expectedPlan?: Partial<APSPlan>;
|
|
26
|
+
/** Expected error codes (if parse should fail) */
|
|
27
|
+
expectedErrors?: string[];
|
|
28
|
+
/** Expected warning codes */
|
|
29
|
+
expectedWarnings?: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Test helper for adapter detection
|
|
33
|
+
*/
|
|
34
|
+
export declare class AdapterTester {
|
|
35
|
+
private adapter;
|
|
36
|
+
constructor(adapter: FormatAdapter);
|
|
37
|
+
/**
|
|
38
|
+
* Test detection with a fixture
|
|
39
|
+
*/
|
|
40
|
+
testDetection(fixture: AdapterTestFixture): DetectionResult;
|
|
41
|
+
/**
|
|
42
|
+
* Test parsing with a fixture
|
|
43
|
+
*/
|
|
44
|
+
testParse(fixture: AdapterTestFixture): Promise<ParseResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Test serialization
|
|
47
|
+
*/
|
|
48
|
+
testSerialize(plan: APSPlan, options?: AdapterOptions): Promise<SerializeResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Test round-trip: parse then serialize then parse again
|
|
51
|
+
*/
|
|
52
|
+
testRoundTrip(fixture: AdapterTestFixture): Promise<{
|
|
53
|
+
firstParse: ParseResult;
|
|
54
|
+
serialized: SerializeResult;
|
|
55
|
+
secondParse: ParseResult;
|
|
56
|
+
planMatches: boolean;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Assert that parsed plan matches expected values
|
|
60
|
+
*/
|
|
61
|
+
private assertPlanMatches;
|
|
62
|
+
/**
|
|
63
|
+
* Compare two plans for equality (ignoring hash and timestamps)
|
|
64
|
+
*/
|
|
65
|
+
private plansEqual;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Create a test adapter tester
|
|
69
|
+
*/
|
|
70
|
+
export declare function createTester(adapter: FormatAdapter): AdapterTester;
|
|
71
|
+
/**
|
|
72
|
+
* Create a basic parse context for testing
|
|
73
|
+
*/
|
|
74
|
+
export declare function createTestContext(overrides?: Partial<ParseContext>): ParseContext;
|
|
75
|
+
/**
|
|
76
|
+
* Create basic adapter options for testing
|
|
77
|
+
*/
|
|
78
|
+
export declare function createTestOptions(overrides?: Partial<AdapterOptions>): AdapterOptions;
|
|
79
|
+
/**
|
|
80
|
+
* Assert detection result
|
|
81
|
+
*/
|
|
82
|
+
export declare function assertDetection(result: DetectionResult, expected: {
|
|
83
|
+
detected: boolean;
|
|
84
|
+
minConfidence?: number;
|
|
85
|
+
}): void;
|
|
86
|
+
/**
|
|
87
|
+
* Assert parse success
|
|
88
|
+
*/
|
|
89
|
+
export declare function assertParseSuccess(result: ParseResult): asserts result is ParseResult & {
|
|
90
|
+
data: APSPlan;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Assert parse failure
|
|
94
|
+
*/
|
|
95
|
+
export declare function assertParseFailure(result: ParseResult, expectedErrorCode?: string): void;
|
|
96
|
+
/**
|
|
97
|
+
* Assert serialize success
|
|
98
|
+
*/
|
|
99
|
+
export declare function assertSerializeSuccess(result: SerializeResult): asserts result is SerializeResult & {
|
|
100
|
+
content: string;
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/base/testing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,eAAe,EACf,eAAe,EACf,YAAY,EACZ,cAAc,EACf,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,iBAAiB,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC7C,wCAAwC;IACxC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,0BAA0B;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,6BAA6B;IAC7B,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,gDAAgD;IAChD,YAAY,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,6BAA6B;IAC7B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAE1C;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,eAAe;IAwB3D;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC;IAgDlE;;OAEG;IACG,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAItF;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC;QACxD,UAAU,EAAE,WAAW,CAAC;QACxB,UAAU,EAAE,eAAe,CAAC;QAC5B,WAAW,EAAE,WAAW,CAAC;QACzB,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC;IAyCF;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAuBzB;;OAEG;IACH,OAAO,CAAC,UAAU;CAmBnB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAElE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CASjF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAOrF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GACtD,IAAI,CAYN;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,MAAM,IAAI,WAAW,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAUnD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAaxF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,MAAM,IAAI,eAAe,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAUzD"}
|