@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.
Files changed (183) hide show
  1. package/AGENTS.md +180 -0
  2. package/BMAD_ADAPTER_SPEC.md +489 -0
  3. package/LICENSE +14 -0
  4. package/README.md +500 -0
  5. package/dist/aps-markdown/adapter.d.ts +102 -0
  6. package/dist/aps-markdown/adapter.d.ts.map +1 -0
  7. package/dist/aps-markdown/adapter.js +351 -0
  8. package/dist/aps-markdown/index.d.ts +8 -0
  9. package/dist/aps-markdown/index.d.ts.map +1 -0
  10. package/dist/aps-markdown/index.js +7 -0
  11. package/dist/base/file-discovery.d.ts +63 -0
  12. package/dist/base/file-discovery.d.ts.map +1 -0
  13. package/dist/base/file-discovery.js +246 -0
  14. package/dist/base/index.d.ts +10 -0
  15. package/dist/base/index.d.ts.map +1 -0
  16. package/dist/base/index.js +9 -0
  17. package/dist/base/registry.d.ts +155 -0
  18. package/dist/base/registry.d.ts.map +1 -0
  19. package/dist/base/registry.js +227 -0
  20. package/dist/base/testing.d.ts +102 -0
  21. package/dist/base/testing.d.ts.map +1 -0
  22. package/dist/base/testing.js +221 -0
  23. package/dist/base/types.d.ts +255 -0
  24. package/dist/base/types.d.ts.map +1 -0
  25. package/dist/base/types.js +78 -0
  26. package/dist/base/utils.d.ts +127 -0
  27. package/dist/base/utils.d.ts.map +1 -0
  28. package/dist/base/utils.js +254 -0
  29. package/dist/bmad/format-adapter.d.ts +76 -0
  30. package/dist/bmad/format-adapter.d.ts.map +1 -0
  31. package/dist/bmad/format-adapter.js +186 -0
  32. package/dist/bmad/index.d.ts +12 -0
  33. package/dist/bmad/index.d.ts.map +1 -0
  34. package/dist/bmad/index.js +10 -0
  35. package/dist/bmad/parser.d.ts +12 -0
  36. package/dist/bmad/parser.d.ts.map +1 -0
  37. package/dist/bmad/parser.js +181 -0
  38. package/dist/bmad/serializer.d.ts +16 -0
  39. package/dist/bmad/serializer.d.ts.map +1 -0
  40. package/dist/bmad/serializer.js +170 -0
  41. package/dist/bmad/types.d.ts +127 -0
  42. package/dist/bmad/types.d.ts.map +1 -0
  43. package/dist/bmad/types.js +47 -0
  44. package/dist/bmad/utils.d.ts +120 -0
  45. package/dist/bmad/utils.d.ts.map +1 -0
  46. package/dist/bmad/utils.js +480 -0
  47. package/dist/common/index.d.ts +3 -0
  48. package/dist/common/index.d.ts.map +1 -0
  49. package/dist/common/index.js +2 -0
  50. package/dist/common/registry.d.ts +18 -0
  51. package/dist/common/registry.d.ts.map +1 -0
  52. package/dist/common/registry.js +58 -0
  53. package/dist/common/types.d.ts +68 -0
  54. package/dist/common/types.d.ts.map +1 -0
  55. package/dist/common/types.js +12 -0
  56. package/dist/generic/format-adapter.d.ts +64 -0
  57. package/dist/generic/format-adapter.d.ts.map +1 -0
  58. package/dist/generic/format-adapter.js +159 -0
  59. package/dist/generic/index.d.ts +10 -0
  60. package/dist/generic/index.d.ts.map +1 -0
  61. package/dist/generic/index.js +9 -0
  62. package/dist/generic/parser.d.ts +11 -0
  63. package/dist/generic/parser.d.ts.map +1 -0
  64. package/dist/generic/parser.js +106 -0
  65. package/dist/generic/serializer.d.ts +11 -0
  66. package/dist/generic/serializer.d.ts.map +1 -0
  67. package/dist/generic/serializer.js +118 -0
  68. package/dist/generic/types.d.ts +52 -0
  69. package/dist/generic/types.d.ts.map +1 -0
  70. package/dist/generic/types.js +6 -0
  71. package/dist/generic/utils.d.ts +51 -0
  72. package/dist/generic/utils.d.ts.map +1 -0
  73. package/dist/generic/utils.js +232 -0
  74. package/dist/index.d.ts +15 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +31 -0
  77. package/dist/speckit/export.d.ts +22 -0
  78. package/dist/speckit/export.d.ts.map +1 -0
  79. package/dist/speckit/export.js +384 -0
  80. package/dist/speckit/format-adapter.d.ts +104 -0
  81. package/dist/speckit/format-adapter.d.ts.map +1 -0
  82. package/dist/speckit/format-adapter.js +488 -0
  83. package/dist/speckit/import-v2.d.ts +33 -0
  84. package/dist/speckit/import-v2.d.ts.map +1 -0
  85. package/dist/speckit/import-v2.js +361 -0
  86. package/dist/speckit/import.d.ts +16 -0
  87. package/dist/speckit/import.d.ts.map +1 -0
  88. package/dist/speckit/import.js +247 -0
  89. package/dist/speckit/index.d.ts +5 -0
  90. package/dist/speckit/index.d.ts.map +1 -0
  91. package/dist/speckit/index.js +4 -0
  92. package/dist/speckit/parser.d.ts +28 -0
  93. package/dist/speckit/parser.d.ts.map +1 -0
  94. package/dist/speckit/parser.js +283 -0
  95. package/dist/speckit/parsers/plan-parser.d.ts +71 -0
  96. package/dist/speckit/parsers/plan-parser.d.ts.map +1 -0
  97. package/dist/speckit/parsers/plan-parser.js +216 -0
  98. package/dist/speckit/parsers/spec-parser.d.ts +67 -0
  99. package/dist/speckit/parsers/spec-parser.d.ts.map +1 -0
  100. package/dist/speckit/parsers/spec-parser.js +255 -0
  101. package/dist/speckit/parsers/tasks-parser.d.ts +57 -0
  102. package/dist/speckit/parsers/tasks-parser.d.ts.map +1 -0
  103. package/dist/speckit/parsers/tasks-parser.js +157 -0
  104. package/package.json +23 -0
  105. package/project.json +29 -0
  106. package/src/__tests__/adapter-edge-cases.test.ts +937 -0
  107. package/src/__tests__/bmad-format-adapter.test.ts +1470 -0
  108. package/src/__tests__/fixtures/aps/expected-output.json +83 -0
  109. package/src/__tests__/fixtures/bmad/invalid-malformed-yaml.md +16 -0
  110. package/src/__tests__/fixtures/bmad/invalid-no-requirements.md +23 -0
  111. package/src/__tests__/fixtures/bmad/invalid-only-yaml.md +16 -0
  112. package/src/__tests__/fixtures/bmad/invalid-too-short.md +3 -0
  113. package/src/__tests__/fixtures/bmad/invalid-wrong-format.md +40 -0
  114. package/src/__tests__/fixtures/bmad/valid-agent.md +27 -0
  115. package/src/__tests__/fixtures/bmad/valid-architecture.md +116 -0
  116. package/src/__tests__/fixtures/bmad/valid-complex-prd.md +161 -0
  117. package/src/__tests__/fixtures/bmad/valid-epic.md +73 -0
  118. package/src/__tests__/fixtures/bmad/valid-minimal-prd.md +19 -0
  119. package/src/__tests__/fixtures/bmad/valid-prd.md +107 -0
  120. package/src/__tests__/fixtures/bmad/valid-story.md +107 -0
  121. package/src/__tests__/fixtures/bmad/valid-task.md +79 -0
  122. package/src/__tests__/fixtures/bmad/valid-v6-prd.md +35 -0
  123. package/src/__tests__/fixtures/generic/plan-detailed.md +39 -0
  124. package/src/__tests__/fixtures/generic/prd-simple.md +27 -0
  125. package/src/__tests__/fixtures/generic/rfc-example.md +26 -0
  126. package/src/__tests__/fixtures/generic/todo-list.md +23 -0
  127. package/src/__tests__/fixtures/speckit/sample-plan.md +63 -0
  128. package/src/__tests__/fixtures/speckit/sample-spec-namespaced.md +50 -0
  129. package/src/__tests__/fixtures/speckit/sample-spec.md +105 -0
  130. package/src/__tests__/fixtures/speckit/sample-tasks.md +87 -0
  131. package/src/__tests__/fixtures/speckit-official/auth-feature/plan.md +272 -0
  132. package/src/__tests__/fixtures/speckit-official/auth-feature/spec.md +149 -0
  133. package/src/__tests__/fixtures/speckit-official/auth-feature/tasks.md +169 -0
  134. package/src/__tests__/generic-format-adapter.test.ts +398 -0
  135. package/src/__tests__/speckit-export.test.ts +233 -0
  136. package/src/__tests__/speckit-format-adapter.test.ts +832 -0
  137. package/src/__tests__/speckit-import-v2.test.ts +253 -0
  138. package/src/__tests__/speckit-import.test.ts +209 -0
  139. package/src/__tests__/speckit-parser.test.ts +219 -0
  140. package/src/__tests__/speckit-spec-parser.test.ts +120 -0
  141. package/src/aps-markdown/__tests__/__fixtures__/simple-leaf.aps.md +17 -0
  142. package/src/aps-markdown/__tests__/adapter.test.ts +393 -0
  143. package/src/aps-markdown/adapter.ts +455 -0
  144. package/src/aps-markdown/index.ts +8 -0
  145. package/src/base/__tests__/registry.test.ts +515 -0
  146. package/src/base/file-discovery.ts +305 -0
  147. package/src/base/index.ts +10 -0
  148. package/src/base/registry.ts +263 -0
  149. package/src/base/testing.ts +334 -0
  150. package/src/base/types.ts +342 -0
  151. package/src/base/utils.ts +306 -0
  152. package/src/bmad/format-adapter.ts +227 -0
  153. package/src/bmad/index.ts +21 -0
  154. package/src/bmad/parser.ts +224 -0
  155. package/src/bmad/serializer.ts +206 -0
  156. package/src/bmad/types.ts +135 -0
  157. package/src/bmad/utils.ts +575 -0
  158. package/src/common/index.ts +2 -0
  159. package/src/common/registry.ts +72 -0
  160. package/src/common/types.ts +84 -0
  161. package/src/generic/__tests__/serializer.test.ts +167 -0
  162. package/src/generic/format-adapter.ts +200 -0
  163. package/src/generic/index.ts +11 -0
  164. package/src/generic/parser.ts +129 -0
  165. package/src/generic/serializer.ts +134 -0
  166. package/src/generic/types.ts +53 -0
  167. package/src/generic/utils.ts +270 -0
  168. package/src/index.ts +48 -0
  169. package/src/speckit/export.ts +489 -0
  170. package/src/speckit/format-adapter.ts +595 -0
  171. package/src/speckit/import-v2.ts +445 -0
  172. package/src/speckit/import.ts +305 -0
  173. package/src/speckit/index.ts +4 -0
  174. package/src/speckit/parser.ts +351 -0
  175. package/src/speckit/parsers/plan-parser.ts +342 -0
  176. package/src/speckit/parsers/spec-parser.ts +379 -0
  177. package/src/speckit/parsers/tasks-parser.ts +246 -0
  178. package/tsconfig.json +26 -0
  179. package/tsconfig.lib.json +21 -0
  180. package/tsconfig.lib.tsbuildinfo +1 -0
  181. package/tsconfig.spec.json +9 -0
  182. package/tsconfig.tsbuildinfo +1 -0
  183. 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,9 @@
1
+ /**
2
+ * Base Adapter Framework
3
+ *
4
+ * Core types, interfaces, and registry for format adapters.
5
+ */
6
+ export * from './types.js';
7
+ export * from './registry.js';
8
+ export * from './utils.js';
9
+ export * from './file-discovery.js';
@@ -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"}