swift-skills-mcp 0.0.1

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 (247) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +410 -0
  3. package/build/cli/auth.d.ts +3 -0
  4. package/build/cli/auth.d.ts.map +1 -0
  5. package/build/cli/auth.js +44 -0
  6. package/build/cli/auth.js.map +1 -0
  7. package/build/cli/setup.d.ts +2 -0
  8. package/build/cli/setup.d.ts.map +1 -0
  9. package/build/cli/setup.js +150 -0
  10. package/build/cli/setup.js.map +1 -0
  11. package/build/cli/source-manager.d.ts +3 -0
  12. package/build/cli/source-manager.d.ts.map +1 -0
  13. package/build/cli/source-manager.js +117 -0
  14. package/build/cli/source-manager.js.map +1 -0
  15. package/build/config/creators.d.ts +11 -0
  16. package/build/config/creators.d.ts.map +1 -0
  17. package/build/config/creators.js +32 -0
  18. package/build/config/creators.js.map +1 -0
  19. package/build/config/sources.d.ts +91 -0
  20. package/build/config/sources.d.ts.map +1 -0
  21. package/build/config/sources.js +231 -0
  22. package/build/config/sources.js.map +1 -0
  23. package/build/config/sources.test.d.ts +2 -0
  24. package/build/config/sources.test.d.ts.map +1 -0
  25. package/build/config/sources.test.js +199 -0
  26. package/build/config/sources.test.js.map +1 -0
  27. package/build/config/swift-keywords.d.ts +29 -0
  28. package/build/config/swift-keywords.d.ts.map +1 -0
  29. package/build/config/swift-keywords.js +77 -0
  30. package/build/config/swift-keywords.js.map +1 -0
  31. package/build/index.d.ts +3 -0
  32. package/build/index.d.ts.map +1 -0
  33. package/build/index.js +181 -0
  34. package/build/index.js.map +1 -0
  35. package/build/integration/cache-behavior.test.d.ts +2 -0
  36. package/build/integration/cache-behavior.test.d.ts.map +1 -0
  37. package/build/integration/cache-behavior.test.js +521 -0
  38. package/build/integration/cache-behavior.test.js.map +1 -0
  39. package/build/integration/mcp-client.test.d.ts +2 -0
  40. package/build/integration/mcp-client.test.d.ts.map +1 -0
  41. package/build/integration/mcp-client.test.js +82 -0
  42. package/build/integration/mcp-client.test.js.map +1 -0
  43. package/build/integration/response-quality.test.d.ts +2 -0
  44. package/build/integration/response-quality.test.d.ts.map +1 -0
  45. package/build/integration/response-quality.test.js +230 -0
  46. package/build/integration/response-quality.test.js.map +1 -0
  47. package/build/integration/test-client.d.ts +25 -0
  48. package/build/integration/test-client.d.ts.map +1 -0
  49. package/build/integration/test-client.js +93 -0
  50. package/build/integration/test-client.js.map +1 -0
  51. package/build/sources/free/nilcoalescing.d.ts +8 -0
  52. package/build/sources/free/nilcoalescing.d.ts.map +1 -0
  53. package/build/sources/free/nilcoalescing.js +26 -0
  54. package/build/sources/free/nilcoalescing.js.map +1 -0
  55. package/build/sources/free/nilcoalescing.test.d.ts +2 -0
  56. package/build/sources/free/nilcoalescing.test.d.ts.map +1 -0
  57. package/build/sources/free/nilcoalescing.test.js +63 -0
  58. package/build/sources/free/nilcoalescing.test.js.map +1 -0
  59. package/build/sources/free/pointfree.d.ts +15 -0
  60. package/build/sources/free/pointfree.d.ts.map +1 -0
  61. package/build/sources/free/pointfree.js +175 -0
  62. package/build/sources/free/pointfree.js.map +1 -0
  63. package/build/sources/free/pointfree.test.d.ts +2 -0
  64. package/build/sources/free/pointfree.test.d.ts.map +1 -0
  65. package/build/sources/free/pointfree.test.js +86 -0
  66. package/build/sources/free/pointfree.test.js.map +1 -0
  67. package/build/sources/free/rssPatternSource.d.ts +42 -0
  68. package/build/sources/free/rssPatternSource.d.ts.map +1 -0
  69. package/build/sources/free/rssPatternSource.js +109 -0
  70. package/build/sources/free/rssPatternSource.js.map +1 -0
  71. package/build/sources/free/rssPatternSource.test.d.ts +2 -0
  72. package/build/sources/free/rssPatternSource.test.d.ts.map +1 -0
  73. package/build/sources/free/rssPatternSource.test.js +89 -0
  74. package/build/sources/free/rssPatternSource.test.js.map +1 -0
  75. package/build/sources/free/sundell.d.ts +8 -0
  76. package/build/sources/free/sundell.d.ts.map +1 -0
  77. package/build/sources/free/sundell.js +17 -0
  78. package/build/sources/free/sundell.js.map +1 -0
  79. package/build/sources/free/sundell.test.d.ts +2 -0
  80. package/build/sources/free/sundell.test.d.ts.map +1 -0
  81. package/build/sources/free/sundell.test.js +63 -0
  82. package/build/sources/free/sundell.test.js.map +1 -0
  83. package/build/sources/free/vanderlee.d.ts +8 -0
  84. package/build/sources/free/vanderlee.d.ts.map +1 -0
  85. package/build/sources/free/vanderlee.js +63 -0
  86. package/build/sources/free/vanderlee.js.map +1 -0
  87. package/build/sources/free/vanderlee.test.d.ts +2 -0
  88. package/build/sources/free/vanderlee.test.d.ts.map +1 -0
  89. package/build/sources/free/vanderlee.test.js +77 -0
  90. package/build/sources/free/vanderlee.test.js.map +1 -0
  91. package/build/sources/premium/patreon-dl.d.ts +45 -0
  92. package/build/sources/premium/patreon-dl.d.ts.map +1 -0
  93. package/build/sources/premium/patreon-dl.js +189 -0
  94. package/build/sources/premium/patreon-dl.js.map +1 -0
  95. package/build/sources/premium/patreon-fetch.d.ts +3 -0
  96. package/build/sources/premium/patreon-fetch.d.ts.map +1 -0
  97. package/build/sources/premium/patreon-fetch.js +18 -0
  98. package/build/sources/premium/patreon-fetch.js.map +1 -0
  99. package/build/sources/premium/patreon-oauth.d.ts +24 -0
  100. package/build/sources/premium/patreon-oauth.d.ts.map +1 -0
  101. package/build/sources/premium/patreon-oauth.js +208 -0
  102. package/build/sources/premium/patreon-oauth.js.map +1 -0
  103. package/build/sources/premium/patreon-zip.d.ts +17 -0
  104. package/build/sources/premium/patreon-zip.d.ts.map +1 -0
  105. package/build/sources/premium/patreon-zip.js +127 -0
  106. package/build/sources/premium/patreon-zip.js.map +1 -0
  107. package/build/sources/premium/patreon.d.ts +48 -0
  108. package/build/sources/premium/patreon.d.ts.map +1 -0
  109. package/build/sources/premium/patreon.js +221 -0
  110. package/build/sources/premium/patreon.js.map +1 -0
  111. package/build/sources/premium/youtube.d.ts +14 -0
  112. package/build/sources/premium/youtube.d.ts.map +1 -0
  113. package/build/sources/premium/youtube.js +92 -0
  114. package/build/sources/premium/youtube.js.map +1 -0
  115. package/build/tools/extract-cookie.d.ts +2 -0
  116. package/build/tools/extract-cookie.d.ts.map +1 -0
  117. package/build/tools/extract-cookie.js +40 -0
  118. package/build/tools/extract-cookie.js.map +1 -0
  119. package/build/tools/handlers/enableSource.d.ts +3 -0
  120. package/build/tools/handlers/enableSource.d.ts.map +1 -0
  121. package/build/tools/handlers/enableSource.js +25 -0
  122. package/build/tools/handlers/enableSource.js.map +1 -0
  123. package/build/tools/handlers/getPatreonPatterns.d.ts +3 -0
  124. package/build/tools/handlers/getPatreonPatterns.d.ts.map +1 -0
  125. package/build/tools/handlers/getPatreonPatterns.js +43 -0
  126. package/build/tools/handlers/getPatreonPatterns.js.map +1 -0
  127. package/build/tools/handlers/getSwiftPattern.d.ts +3 -0
  128. package/build/tools/handlers/getSwiftPattern.d.ts.map +1 -0
  129. package/build/tools/handlers/getSwiftPattern.js +72 -0
  130. package/build/tools/handlers/getSwiftPattern.js.map +1 -0
  131. package/build/tools/handlers/handlers.test.d.ts +2 -0
  132. package/build/tools/handlers/handlers.test.d.ts.map +1 -0
  133. package/build/tools/handlers/handlers.test.js +359 -0
  134. package/build/tools/handlers/handlers.test.js.map +1 -0
  135. package/build/tools/handlers/listContentSources.d.ts +3 -0
  136. package/build/tools/handlers/listContentSources.d.ts.map +1 -0
  137. package/build/tools/handlers/listContentSources.js +34 -0
  138. package/build/tools/handlers/listContentSources.js.map +1 -0
  139. package/build/tools/handlers/searchSwiftContent.d.ts +3 -0
  140. package/build/tools/handlers/searchSwiftContent.d.ts.map +1 -0
  141. package/build/tools/handlers/searchSwiftContent.js +121 -0
  142. package/build/tools/handlers/searchSwiftContent.js.map +1 -0
  143. package/build/tools/handlers/setupPatreon.d.ts +3 -0
  144. package/build/tools/handlers/setupPatreon.d.ts.map +1 -0
  145. package/build/tools/handlers/setupPatreon.js +40 -0
  146. package/build/tools/handlers/setupPatreon.js.map +1 -0
  147. package/build/tools/index.d.ts +3 -0
  148. package/build/tools/index.d.ts.map +1 -0
  149. package/build/tools/index.js +18 -0
  150. package/build/tools/index.js.map +1 -0
  151. package/build/tools/registry.d.ts +14 -0
  152. package/build/tools/registry.d.ts.map +1 -0
  153. package/build/tools/registry.js +21 -0
  154. package/build/tools/registry.js.map +1 -0
  155. package/build/tools/registry.test.d.ts +2 -0
  156. package/build/tools/registry.test.d.ts.map +1 -0
  157. package/build/tools/registry.test.js +54 -0
  158. package/build/tools/registry.test.js.map +1 -0
  159. package/build/tools/types.d.ts +67 -0
  160. package/build/tools/types.d.ts.map +1 -0
  161. package/build/tools/types.js +3 -0
  162. package/build/tools/types.js.map +1 -0
  163. package/build/utils/cache.d.ts +20 -0
  164. package/build/utils/cache.d.ts.map +1 -0
  165. package/build/utils/cache.js +186 -0
  166. package/build/utils/cache.js.map +1 -0
  167. package/build/utils/concurrency.d.ts +13 -0
  168. package/build/utils/concurrency.d.ts.map +1 -0
  169. package/build/utils/concurrency.js +33 -0
  170. package/build/utils/concurrency.js.map +1 -0
  171. package/build/utils/errors.d.ts +19 -0
  172. package/build/utils/errors.d.ts.map +1 -0
  173. package/build/utils/errors.js +35 -0
  174. package/build/utils/errors.js.map +1 -0
  175. package/build/utils/fetch.d.ts +6 -0
  176. package/build/utils/fetch.d.ts.map +1 -0
  177. package/build/utils/fetch.js +6 -0
  178. package/build/utils/fetch.js.map +1 -0
  179. package/build/utils/http.d.ts +21 -0
  180. package/build/utils/http.d.ts.map +1 -0
  181. package/build/utils/http.js +53 -0
  182. package/build/utils/http.js.map +1 -0
  183. package/build/utils/intent-cache.d.ts +94 -0
  184. package/build/utils/intent-cache.d.ts.map +1 -0
  185. package/build/utils/intent-cache.js +164 -0
  186. package/build/utils/intent-cache.js.map +1 -0
  187. package/build/utils/intent-cache.test.d.ts +2 -0
  188. package/build/utils/intent-cache.test.d.ts.map +1 -0
  189. package/build/utils/intent-cache.test.js +290 -0
  190. package/build/utils/intent-cache.test.js.map +1 -0
  191. package/build/utils/logger.d.ts +4 -0
  192. package/build/utils/logger.d.ts.map +1 -0
  193. package/build/utils/logger.js +9 -0
  194. package/build/utils/logger.js.map +1 -0
  195. package/build/utils/paths.d.ts +27 -0
  196. package/build/utils/paths.d.ts.map +1 -0
  197. package/build/utils/paths.js +43 -0
  198. package/build/utils/paths.js.map +1 -0
  199. package/build/utils/pattern-formatter.d.ts +40 -0
  200. package/build/utils/pattern-formatter.d.ts.map +1 -0
  201. package/build/utils/pattern-formatter.js +124 -0
  202. package/build/utils/pattern-formatter.js.map +1 -0
  203. package/build/utils/response-helpers.d.ts +17 -0
  204. package/build/utils/response-helpers.d.ts.map +1 -0
  205. package/build/utils/response-helpers.js +34 -0
  206. package/build/utils/response-helpers.js.map +1 -0
  207. package/build/utils/search-terms.d.ts +17 -0
  208. package/build/utils/search-terms.d.ts.map +1 -0
  209. package/build/utils/search-terms.js +71 -0
  210. package/build/utils/search-terms.js.map +1 -0
  211. package/build/utils/search-terms.test.d.ts +2 -0
  212. package/build/utils/search-terms.test.d.ts.map +1 -0
  213. package/build/utils/search-terms.test.js +107 -0
  214. package/build/utils/search-terms.test.js.map +1 -0
  215. package/build/utils/search.d.ts +48 -0
  216. package/build/utils/search.d.ts.map +1 -0
  217. package/build/utils/search.js +158 -0
  218. package/build/utils/search.js.map +1 -0
  219. package/build/utils/search.test.d.ts +2 -0
  220. package/build/utils/search.test.d.ts.map +1 -0
  221. package/build/utils/search.test.js +199 -0
  222. package/build/utils/search.test.js.map +1 -0
  223. package/build/utils/semantic-recall.d.ts +38 -0
  224. package/build/utils/semantic-recall.d.ts.map +1 -0
  225. package/build/utils/semantic-recall.js +134 -0
  226. package/build/utils/semantic-recall.js.map +1 -0
  227. package/build/utils/semantic-recall.test.d.ts +2 -0
  228. package/build/utils/semantic-recall.test.d.ts.map +1 -0
  229. package/build/utils/semantic-recall.test.js +326 -0
  230. package/build/utils/semantic-recall.test.js.map +1 -0
  231. package/build/utils/source-registry.d.ts +45 -0
  232. package/build/utils/source-registry.d.ts.map +1 -0
  233. package/build/utils/source-registry.js +113 -0
  234. package/build/utils/source-registry.js.map +1 -0
  235. package/build/utils/source-registry.test.d.ts +2 -0
  236. package/build/utils/source-registry.test.d.ts.map +1 -0
  237. package/build/utils/source-registry.test.js +206 -0
  238. package/build/utils/source-registry.test.js.map +1 -0
  239. package/build/utils/swift-analysis.d.ts +61 -0
  240. package/build/utils/swift-analysis.d.ts.map +1 -0
  241. package/build/utils/swift-analysis.js +339 -0
  242. package/build/utils/swift-analysis.js.map +1 -0
  243. package/build/utils/swift-analysis.test.d.ts +2 -0
  244. package/build/utils/swift-analysis.test.d.ts.map +1 -0
  245. package/build/utils/swift-analysis.test.js +473 -0
  246. package/build/utils/swift-analysis.test.js.map +1 -0
  247. package/package.json +85 -0
@@ -0,0 +1,230 @@
1
+ // src/integration/response-quality.test.ts
2
+ // End-to-end tests validating response quality for AI assistant consumption
3
+ // Skipped on CI due to native dependency issues (keytar)
4
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
5
+ import { MCPTestClient, isCI } from './test-client.js';
6
+ const describeIntegration = isCI ? describe.skip : describe;
7
+ describeIntegration('Response Quality Validation', () => {
8
+ let client;
9
+ beforeAll(async () => {
10
+ client = new MCPTestClient();
11
+ await client.start();
12
+ }, 10000);
13
+ afterAll(async () => {
14
+ await client.stop();
15
+ });
16
+ describe('list_content_sources response format', () => {
17
+ it('should have clear markdown structure', async () => {
18
+ const response = await client.callToolText('list_content_sources');
19
+ expect(response).toMatch(/^# /m);
20
+ expect(response).toMatch(/## /m);
21
+ expect(response).toContain('Free Sources');
22
+ expect(response).toContain('Premium Sources');
23
+ });
24
+ it('should list all expected free sources', async () => {
25
+ const response = await client.callToolText('list_content_sources');
26
+ // Verify all free sources are listed
27
+ expect(response).toContain('Swift by Sundell');
28
+ expect(response).toContain('Antoine van der Lee');
29
+ expect(response).toContain('Nil Coalescing');
30
+ expect(response).toContain('Point-Free');
31
+ });
32
+ it('should show status indicators for each source', async () => {
33
+ const response = await client.callToolText('list_content_sources');
34
+ // Each source should have a status indicator
35
+ expect(response).toMatch(/✅|⚙️|⬜/);
36
+ });
37
+ it('should include actionable setup instructions', async () => {
38
+ const response = await client.callToolText('list_content_sources');
39
+ expect(response).toContain('swift-patterns-mcp setup');
40
+ });
41
+ });
42
+ describe('get_swift_pattern response validation', () => {
43
+ it('should return patterns relevant to the requested topic', async () => {
44
+ const response = await client.callToolText('get_swift_pattern', {
45
+ topic: 'swiftui',
46
+ minQuality: 50,
47
+ });
48
+ // Response should contain SwiftUI-related content
49
+ const lowerResponse = response.toLowerCase();
50
+ const hasRelevantContent = lowerResponse.includes('swiftui') ||
51
+ lowerResponse.includes('view') ||
52
+ lowerResponse.includes('state') ||
53
+ lowerResponse.includes('binding');
54
+ expect(hasRelevantContent).toBe(true);
55
+ }, 60000);
56
+ it('should exclude low-quality patterns when minQuality is high', async () => {
57
+ const highQualityResponse = await client.callToolText('get_swift_pattern', {
58
+ topic: 'swift',
59
+ minQuality: 80,
60
+ });
61
+ const lowQualityResponse = await client.callToolText('get_swift_pattern', {
62
+ topic: 'swift',
63
+ minQuality: 30,
64
+ });
65
+ // With higher minQuality, we should get fewer or equal results
66
+ // Count the number of pattern headers (## Title)
67
+ const highQualityCount = (highQualityResponse.match(/^## /gm) || []).length;
68
+ const lowQualityCount = (lowQualityResponse.match(/^## /gm) || []).length;
69
+ expect(lowQualityCount).toBeGreaterThanOrEqual(highQualityCount);
70
+ }, 120000);
71
+ it('should include quality scores in pattern output', async () => {
72
+ const response = await client.callToolText('get_swift_pattern', {
73
+ topic: 'swiftui',
74
+ minQuality: 60,
75
+ });
76
+ if (!response.includes('No patterns found')) {
77
+ // Each pattern should have a quality score
78
+ expect(response).toMatch(/Quality.*:\s*\d+\/100/i);
79
+ }
80
+ }, 60000);
81
+ it('should include source attribution for each pattern', async () => {
82
+ const response = await client.callToolText('get_swift_pattern', {
83
+ topic: 'swiftui',
84
+ minQuality: 60,
85
+ });
86
+ if (!response.includes('No patterns found')) {
87
+ // Each pattern should have a source
88
+ expect(response).toMatch(/Source.*:/i);
89
+ }
90
+ }, 60000);
91
+ it('should include valid URLs in pattern output', async () => {
92
+ const response = await client.callToolText('get_swift_pattern', {
93
+ topic: 'swiftui',
94
+ minQuality: 60,
95
+ });
96
+ if (!response.includes('No patterns found')) {
97
+ // Should have clickable markdown links
98
+ const urlMatch = response.match(/\[.+\]\((https?:\/\/[^)]+)\)/);
99
+ expect(urlMatch).not.toBeNull();
100
+ // URL should be from a known source
101
+ if (urlMatch) {
102
+ const url = urlMatch[1];
103
+ const isValidSource = url.includes('swiftbysundell.com') ||
104
+ url.includes('avanderlee.com') ||
105
+ url.includes('nilcoalescing.com') ||
106
+ url.includes('pointfree.co') ||
107
+ url.includes('github.com/pointfreeco');
108
+ expect(isValidSource).toBe(true);
109
+ }
110
+ }
111
+ }, 60000);
112
+ it('should handle no results with helpful message', async () => {
113
+ const response = await client.callToolText('get_swift_pattern', {
114
+ topic: 'xyznonexistenttopic123',
115
+ minQuality: 100,
116
+ });
117
+ expect(response).toContain('No patterns found');
118
+ // Should suggest alternatives
119
+ expect(response).toMatch(/[Tt]ry|[Ll]ower|[Dd]ifferent/);
120
+ }, 30000);
121
+ });
122
+ describe('search_swift_content response validation', () => {
123
+ it('should return results containing search terms', async () => {
124
+ const response = await client.callToolText('search_swift_content', {
125
+ query: 'async await',
126
+ });
127
+ expect(response).toMatch(/# Search Results/);
128
+ // Results should be relevant to the query
129
+ const lowerResponse = response.toLowerCase();
130
+ const hasRelevantContent = lowerResponse.includes('async') ||
131
+ lowerResponse.includes('await') ||
132
+ lowerResponse.includes('concurrency');
133
+ expect(hasRelevantContent).toBe(true);
134
+ }, 60000);
135
+ it('should filter by requireCode when specified', async () => {
136
+ const withCodeResponse = await client.callToolText('search_swift_content', {
137
+ query: 'swift',
138
+ requireCode: true,
139
+ });
140
+ // When requireCode is true, results should have code indicators
141
+ // This is hard to verify without parsing, but at minimum we should get results
142
+ expect(withCodeResponse.length).toBeGreaterThan(50);
143
+ }, 60000);
144
+ it('should include excerpts in search results', async () => {
145
+ const response = await client.callToolText('search_swift_content', {
146
+ query: 'concurrency',
147
+ });
148
+ // Results should have some content beyond just titles
149
+ expect(response.length).toBeGreaterThan(200);
150
+ }, 60000);
151
+ });
152
+ describe('enable_source response validation', () => {
153
+ it('should confirm enabling a valid free source', async () => {
154
+ const response = await client.callToolText('enable_source', {
155
+ source: 'sundell',
156
+ });
157
+ expect(response).toContain('enabled');
158
+ expect(response).toContain('Swift by Sundell');
159
+ });
160
+ it('should show helpful error for invalid source with alternatives', async () => {
161
+ const response = await client.callToolText('enable_source', {
162
+ source: 'invalid_source_xyz',
163
+ });
164
+ expect(response).toContain('Unknown source');
165
+ expect(response).toContain('invalid_source_xyz');
166
+ // Should list available alternatives
167
+ expect(response).toContain('Available sources');
168
+ expect(response).toContain('sundell');
169
+ });
170
+ it('should require setup for premium sources', async () => {
171
+ const response = await client.callToolText('enable_source', {
172
+ source: 'patreon',
173
+ });
174
+ expect(response).toMatch(/setup|enabled/i);
175
+ });
176
+ });
177
+ describe('Response characteristics for AI consumption', () => {
178
+ it('should use markdown formatting without HTML', async () => {
179
+ const responses = await Promise.all([
180
+ client.callToolText('list_content_sources'),
181
+ client.callToolText('get_swift_pattern', { topic: 'testing', minQuality: 50 }),
182
+ ]);
183
+ for (const response of responses) {
184
+ // Should have markdown headers
185
+ expect(response).toMatch(/^#+ /m);
186
+ // Should NOT have HTML tags
187
+ expect(response).not.toMatch(/<div|<span|<p>|<br>/);
188
+ }
189
+ }, 60000);
190
+ it('should have reasonable response length (not too short, not too long)', async () => {
191
+ const response = await client.callToolText('get_swift_pattern', {
192
+ topic: 'swiftui',
193
+ minQuality: 70,
194
+ });
195
+ // Should have meaningful content
196
+ expect(response.length).toBeGreaterThan(50);
197
+ // Should not be excessively long
198
+ expect(response.length).toBeLessThan(50000);
199
+ }, 60000);
200
+ it('should use separators between multiple patterns', async () => {
201
+ const response = await client.callToolText('get_swift_pattern', {
202
+ topic: 'swift',
203
+ minQuality: 50,
204
+ });
205
+ if (!response.includes('No patterns found')) {
206
+ // Multiple patterns should be separated
207
+ const patternCount = (response.match(/^## /gm) || []).length;
208
+ if (patternCount > 1) {
209
+ expect(response).toMatch(/---/);
210
+ }
211
+ }
212
+ }, 60000);
213
+ it('should sort patterns by quality (highest first)', async () => {
214
+ const response = await client.callToolText('get_swift_pattern', {
215
+ topic: 'swift',
216
+ minQuality: 50,
217
+ });
218
+ if (!response.includes('No patterns found')) {
219
+ // Extract quality scores from the response
220
+ const qualityMatches = response.matchAll(/Quality.*?(\d+)\/100/gi);
221
+ const scores = Array.from(qualityMatches, m => parseInt(m[1], 10));
222
+ // Verify scores are in descending order
223
+ for (let i = 1; i < scores.length; i++) {
224
+ expect(scores[i]).toBeLessThanOrEqual(scores[i - 1]);
225
+ }
226
+ }
227
+ }, 60000);
228
+ });
229
+ });
230
+ //# sourceMappingURL=response-quality.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-quality.test.js","sourceRoot":"","sources":["../../src/integration/response-quality.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export interface JsonRpcResponse {
2
+ jsonrpc: '2.0';
3
+ id: number;
4
+ result?: unknown;
5
+ error?: {
6
+ code: number;
7
+ message: string;
8
+ data?: unknown;
9
+ };
10
+ }
11
+ export declare class MCPTestClient {
12
+ private process;
13
+ private requestId;
14
+ private pendingRequests;
15
+ private rl;
16
+ start(): Promise<void>;
17
+ stop(): Promise<void>;
18
+ send(method: string, params?: Record<string, unknown>): Promise<JsonRpcResponse>;
19
+ initialize(): Promise<JsonRpcResponse>;
20
+ listTools(): Promise<JsonRpcResponse>;
21
+ callTool(name: string, args?: Record<string, unknown>): Promise<JsonRpcResponse>;
22
+ callToolText(name: string, args?: Record<string, unknown>): Promise<string>;
23
+ }
24
+ export declare const isCI: boolean;
25
+ //# sourceMappingURL=test-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-client.d.ts","sourceRoot":"","sources":["../../src/integration/test-client.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3D;AASD,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,eAAe,CAGlB;IACL,OAAO,CAAC,EAAE,CAAmC;IAEvC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiCtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAWrB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;IA0BhF,UAAU,IAAI,OAAO,CAAC,eAAe,CAAC;IAQtC,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC;IAIrC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAIpF,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAMtF;AAGD,eAAO,MAAM,IAAI,SAA4B,CAAC"}
@@ -0,0 +1,93 @@
1
+ // src/integration/test-client.ts
2
+ // Shared MCP test client for integration tests
3
+ import { spawn } from 'child_process';
4
+ import * as readline from 'readline';
5
+ import * as path from 'path';
6
+ export class MCPTestClient {
7
+ process = null;
8
+ requestId = 0;
9
+ pendingRequests = new Map();
10
+ rl = null;
11
+ async start() {
12
+ const serverPath = path.join(process.cwd(), 'build', 'index.js');
13
+ this.process = spawn('node', [serverPath], {
14
+ stdio: ['pipe', 'pipe', 'pipe'],
15
+ cwd: process.cwd(),
16
+ });
17
+ this.rl = readline.createInterface({
18
+ input: this.process.stdout,
19
+ crlfDelay: Infinity,
20
+ });
21
+ this.rl.on('line', (line) => {
22
+ try {
23
+ const response = JSON.parse(line);
24
+ const pending = this.pendingRequests.get(response.id);
25
+ if (pending) {
26
+ this.pendingRequests.delete(response.id);
27
+ pending.resolve(response);
28
+ }
29
+ }
30
+ catch {
31
+ // Ignore non-JSON lines
32
+ }
33
+ });
34
+ // Consume stderr to prevent blocking
35
+ this.process.stderr?.on('data', () => { });
36
+ // Wait for server to start
37
+ await new Promise(resolve => setTimeout(resolve, 500));
38
+ }
39
+ async stop() {
40
+ if (this.process) {
41
+ this.process.kill();
42
+ this.process = null;
43
+ }
44
+ if (this.rl) {
45
+ this.rl.close();
46
+ this.rl = null;
47
+ }
48
+ }
49
+ async send(method, params) {
50
+ if (!this.process) {
51
+ throw new Error('Client not started');
52
+ }
53
+ const id = ++this.requestId;
54
+ const request = { jsonrpc: '2.0', id, method, params };
55
+ return new Promise((resolve, reject) => {
56
+ this.pendingRequests.set(id, { resolve, reject });
57
+ const timeout = setTimeout(() => {
58
+ this.pendingRequests.delete(id);
59
+ reject(new Error(`Request ${id} timed out`));
60
+ }, 30000);
61
+ this.process.stdin.write(JSON.stringify(request) + '\n', (err) => {
62
+ if (err) {
63
+ clearTimeout(timeout);
64
+ this.pendingRequests.delete(id);
65
+ reject(err);
66
+ }
67
+ });
68
+ });
69
+ }
70
+ async initialize() {
71
+ return this.send('initialize', {
72
+ protocolVersion: '2024-11-05',
73
+ capabilities: {},
74
+ clientInfo: { name: 'test-client', version: '1.0.0' },
75
+ });
76
+ }
77
+ async listTools() {
78
+ return this.send('tools/list', {});
79
+ }
80
+ async callTool(name, args = {}) {
81
+ return this.send('tools/call', { name, arguments: args });
82
+ }
83
+ async callToolText(name, args = {}) {
84
+ const response = await this.callTool(name, args);
85
+ if (response.error)
86
+ throw new Error(response.error.message);
87
+ const result = response.result;
88
+ return result.content[0]?.text ?? '';
89
+ }
90
+ }
91
+ // Skip integration tests on CI
92
+ export const isCI = process.env.CI === 'true';
93
+ //# sourceMappingURL=test-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-client.js","sourceRoot":"","sources":["../../src/integration/test-client.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,+CAA+C;AAE/C,OAAO,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AACrC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAgB7B,MAAM,OAAO,aAAa;IAChB,OAAO,GAAwB,IAAI,CAAC;IACpC,SAAS,GAAG,CAAC,CAAC;IACd,eAAe,GAAG,IAAI,GAAG,EAG7B,CAAC;IACG,EAAE,GAA8B,IAAI,CAAC;IAE7C,KAAK,CAAC,KAAK;QACT,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QAEjE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE;YACzC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;SACnB,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YACjC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAO;YAC3B,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAC1B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAoB,CAAC;gBACrD,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBACtD,IAAI,OAAO,EAAE,CAAC;oBACZ,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;oBACzC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,qCAAqC;QACrC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAE1C,2BAA2B;QAC3B,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACpB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;QACD,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAgC;QACzD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC;QAC5B,MAAM,OAAO,GAAmB,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAEvE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAElD,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC9B,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAChC,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;YAC/C,CAAC,EAAE,KAAK,CAAC,CAAC;YAEV,IAAI,CAAC,OAAQ,CAAC,KAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE;gBACjE,IAAI,GAAG,EAAE,CAAC;oBACR,YAAY,CAAC,OAAO,CAAC,CAAC;oBACtB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBAChC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YAC7B,eAAe,EAAE,YAAY;YAC7B,YAAY,EAAE,EAAE;YAChB,UAAU,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE;SACtD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,OAAgC,EAAE;QAC7D,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAY,EAAE,OAAgC,EAAE;QACjE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjD,IAAI,QAAQ,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAA8C,CAAC;QACvE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;IACvC,CAAC;CACF;AAED,+BAA+B;AAC/B,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,MAAM,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { RssPatternSource, type BasePattern } from './rssPatternSource.js';
2
+ export interface NilCoalescingPattern extends BasePattern {
3
+ }
4
+ export declare class NilCoalescingSource extends RssPatternSource<NilCoalescingPattern> {
5
+ constructor();
6
+ }
7
+ export default NilCoalescingSource;
8
+ //# sourceMappingURL=nilcoalescing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nilcoalescing.d.ts","sourceRoot":"","sources":["../../../src/sources/free/nilcoalescing.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAI3E,MAAM,WAAW,oBAAqB,SAAQ,WAAW;CAAG;AAgB5D,qBAAa,mBAAoB,SAAQ,gBAAgB,CAAC,oBAAoB,CAAC;;CAU9E;AAED,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,26 @@
1
+ // src/sources/free/nilcoalescing.ts
2
+ import { RssPatternSource } from './rssPatternSource.js';
3
+ import { createSourceConfig } from '../../config/swift-keywords.js';
4
+ const { topicKeywords, qualitySignals } = createSourceConfig({
5
+ 'swiftui': ['navigation', 'animation', 'layout', 'viewbuilder'],
6
+ 'concurrency': ['async/await', 'task', 'actor'],
7
+ 'testing': ['snapshot', 'unit test'],
8
+ 'accessibility': ['accessibility', 'voiceover'],
9
+ }, {
10
+ 'swiftui': 7, 'navigation': 5, 'animation': 4, 'layout': 4,
11
+ 'accessibility': 6, 'async': 6, 'await': 6, 'actor': 6,
12
+ 'testing': 7, 'snapshot': 6,
13
+ });
14
+ export class NilCoalescingSource extends RssPatternSource {
15
+ constructor() {
16
+ super({
17
+ feedUrl: 'https://nilcoalescing.com/feed.rss',
18
+ cacheKey: 'nilcoalescing-patterns',
19
+ rssCacheTtl: 3600,
20
+ topicKeywords,
21
+ qualitySignals,
22
+ });
23
+ }
24
+ }
25
+ export default NilCoalescingSource;
26
+ //# sourceMappingURL=nilcoalescing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nilcoalescing.js","sourceRoot":"","sources":["../../../src/sources/free/nilcoalescing.ts"],"names":[],"mappings":"AAAA,oCAAoC;AAEpC,OAAO,EAAE,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAKpE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,GAAG,kBAAkB,CAC1D;IACE,SAAS,EAAE,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,CAAC;IAC/D,aAAa,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC;IAC/C,SAAS,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC;IACpC,eAAe,EAAE,CAAC,eAAe,EAAE,WAAW,CAAC;CAChD,EACD;IACE,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC1D,eAAe,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;IACtD,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;CAC5B,CACF,CAAC;AAEF,MAAM,OAAO,mBAAoB,SAAQ,gBAAsC;IAC7E;QACE,KAAK,CAAC;YACJ,OAAO,EAAE,oCAAoC;YAC7C,QAAQ,EAAE,wBAAwB;YAClC,WAAW,EAAE,IAAI;YACjB,aAAa;YACb,cAAc;SACf,CAAC,CAAC;IACL,CAAC;CACF;AAED,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=nilcoalescing.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nilcoalescing.test.d.ts","sourceRoot":"","sources":["../../../src/sources/free/nilcoalescing.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ // src/sources/free/nilcoalescing.test.ts
2
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
3
+ import NilCoalescingSource from './nilcoalescing.js';
4
+ vi.mock('rss-parser', () => {
5
+ return {
6
+ default: class Parser {
7
+ async parseURL(_url) {
8
+ return {
9
+ items: [
10
+ {
11
+ guid: '1',
12
+ title: 'SwiftUI Navigation Patterns',
13
+ link: 'https://example.com/1',
14
+ pubDate: '2026-01-01',
15
+ contentSnippet: 'Navigation and layout tips for SwiftUI',
16
+ content: '<p>Some content <code>NavigationStack</code></p>',
17
+ },
18
+ {
19
+ guid: '2',
20
+ title: 'Snapshot Testing in Swift',
21
+ link: 'https://example.com/2',
22
+ pubDate: '2026-01-02',
23
+ contentSnippet: 'Snapshot testing for UIKit and SwiftUI',
24
+ content: '<p>Testing <pre>assertSnapshot()</pre></p>',
25
+ },
26
+ ],
27
+ };
28
+ }
29
+ },
30
+ };
31
+ });
32
+ vi.mock('../../utils/cache.js', () => ({
33
+ rssCache: {
34
+ get: vi.fn(async () => undefined),
35
+ set: vi.fn(async () => undefined),
36
+ },
37
+ }));
38
+ describe('NilCoalescingSource', () => {
39
+ let source;
40
+ beforeEach(() => {
41
+ source = new NilCoalescingSource();
42
+ });
43
+ it('fetches and parses patterns', async () => {
44
+ const patterns = await source.fetchPatterns();
45
+ expect(patterns).toHaveLength(2);
46
+ expect(patterns[0].title).toBe('SwiftUI Navigation Patterns');
47
+ expect(patterns[0].topics).toContain('swiftui');
48
+ expect(patterns[1].topics).toContain('testing');
49
+ expect(patterns[0].hasCode).toBe(true);
50
+ expect(patterns[1].hasCode).toBe(true);
51
+ });
52
+ it('calculates relevance score', async () => {
53
+ const patterns = await source.fetchPatterns();
54
+ expect(patterns[0].relevanceScore).toBeGreaterThanOrEqual(66);
55
+ expect(patterns[1].relevanceScore).toBeGreaterThanOrEqual(66);
56
+ });
57
+ it('searchPatterns returns relevant results', async () => {
58
+ const results = await source.searchPatterns('snapshot');
59
+ expect(results[0].title).toMatch(/snapshot/i);
60
+ expect(results[0].topics).toContain('testing');
61
+ });
62
+ });
63
+ //# sourceMappingURL=nilcoalescing.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nilcoalescing.test.js","sourceRoot":"","sources":["../../../src/sources/free/nilcoalescing.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { BasePattern } from './rssPatternSource.js';
2
+ export interface PointFreePattern extends BasePattern {
3
+ sourcePath: string;
4
+ }
5
+ export declare class PointFreeSource {
6
+ private cachedSearch;
7
+ private getDefaultBranch;
8
+ private getRepoTree;
9
+ private fetchContentFiles;
10
+ private fetchFileContent;
11
+ fetchPatterns(): Promise<PointFreePattern[]>;
12
+ searchPatterns(query: string): Promise<PointFreePattern[]>;
13
+ }
14
+ export default PointFreeSource;
15
+ //# sourceMappingURL=pointfree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointfree.d.ts","sourceRoot":"","sources":["../../../src/sources/free/pointfree.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,UAAU,EAAE,MAAM,CAAC;CACpB;AAwGD,qBAAa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAA2E;YAEjF,gBAAgB;YAYhB,WAAW;YAaX,iBAAiB;YAUjB,gBAAgB;IASxB,aAAa,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAmD5C,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAIjE;AAED,eAAe,eAAe,CAAC"}