swift-patterns-mcp 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +377 -0
- package/build/cli/auth.d.ts +3 -0
- package/build/cli/auth.d.ts.map +1 -0
- package/build/cli/auth.js +43 -0
- package/build/cli/auth.js.map +1 -0
- package/build/cli/setup.d.ts +2 -0
- package/build/cli/setup.d.ts.map +1 -0
- package/build/cli/setup.js +149 -0
- package/build/cli/setup.js.map +1 -0
- package/build/cli/source-manager.d.ts +3 -0
- package/build/cli/source-manager.d.ts.map +1 -0
- package/build/cli/source-manager.js +117 -0
- package/build/cli/source-manager.js.map +1 -0
- package/build/config/creators.d.ts +11 -0
- package/build/config/creators.d.ts.map +1 -0
- package/build/config/creators.js +32 -0
- package/build/config/creators.js.map +1 -0
- package/build/config/sources.d.ts +65 -0
- package/build/config/sources.d.ts.map +1 -0
- package/build/config/sources.js +184 -0
- package/build/config/sources.js.map +1 -0
- package/build/config/sources.test.d.ts +2 -0
- package/build/config/sources.test.d.ts.map +1 -0
- package/build/config/sources.test.js +195 -0
- package/build/config/sources.test.js.map +1 -0
- package/build/config/swift-keywords.d.ts +21 -0
- package/build/config/swift-keywords.d.ts.map +1 -0
- package/build/config/swift-keywords.js +67 -0
- package/build/config/swift-keywords.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +295 -0
- package/build/index.js.map +1 -0
- package/build/integration/mcp-client.test.d.ts +2 -0
- package/build/integration/mcp-client.test.d.ts.map +1 -0
- package/build/integration/mcp-client.test.js +82 -0
- package/build/integration/mcp-client.test.js.map +1 -0
- package/build/integration/response-quality.test.d.ts +2 -0
- package/build/integration/response-quality.test.d.ts.map +1 -0
- package/build/integration/response-quality.test.js +139 -0
- package/build/integration/response-quality.test.js.map +1 -0
- package/build/integration/test-client.d.ts +25 -0
- package/build/integration/test-client.d.ts.map +1 -0
- package/build/integration/test-client.js +93 -0
- package/build/integration/test-client.js.map +1 -0
- package/build/sources/free/rssPatternSource.d.ts +41 -0
- package/build/sources/free/rssPatternSource.d.ts.map +1 -0
- package/build/sources/free/rssPatternSource.js +122 -0
- package/build/sources/free/rssPatternSource.js.map +1 -0
- package/build/sources/free/rssPatternSource.test.d.ts +2 -0
- package/build/sources/free/rssPatternSource.test.d.ts.map +1 -0
- package/build/sources/free/rssPatternSource.test.js +92 -0
- package/build/sources/free/rssPatternSource.test.js.map +1 -0
- package/build/sources/free/sundell.d.ts +9 -0
- package/build/sources/free/sundell.d.ts.map +1 -0
- package/build/sources/free/sundell.js +31 -0
- package/build/sources/free/sundell.js.map +1 -0
- package/build/sources/free/sundell.test.d.ts +2 -0
- package/build/sources/free/sundell.test.d.ts.map +1 -0
- package/build/sources/free/sundell.test.js +63 -0
- package/build/sources/free/sundell.test.js.map +1 -0
- package/build/sources/free/vanderlee.d.ts +9 -0
- package/build/sources/free/vanderlee.d.ts.map +1 -0
- package/build/sources/free/vanderlee.js +71 -0
- package/build/sources/free/vanderlee.js.map +1 -0
- package/build/sources/free/vanderlee.test.d.ts +2 -0
- package/build/sources/free/vanderlee.test.d.ts.map +1 -0
- package/build/sources/free/vanderlee.test.js +73 -0
- package/build/sources/free/vanderlee.test.js.map +1 -0
- package/build/sources/premium/patreon-dl.d.ts +45 -0
- package/build/sources/premium/patreon-dl.d.ts.map +1 -0
- package/build/sources/premium/patreon-dl.js +189 -0
- package/build/sources/premium/patreon-dl.js.map +1 -0
- package/build/sources/premium/patreon-fetch.d.ts +3 -0
- package/build/sources/premium/patreon-fetch.d.ts.map +1 -0
- package/build/sources/premium/patreon-fetch.js +18 -0
- package/build/sources/premium/patreon-fetch.js.map +1 -0
- package/build/sources/premium/patreon-oauth.d.ts +24 -0
- package/build/sources/premium/patreon-oauth.d.ts.map +1 -0
- package/build/sources/premium/patreon-oauth.js +207 -0
- package/build/sources/premium/patreon-oauth.js.map +1 -0
- package/build/sources/premium/patreon-zip.d.ts +17 -0
- package/build/sources/premium/patreon-zip.d.ts.map +1 -0
- package/build/sources/premium/patreon-zip.js +128 -0
- package/build/sources/premium/patreon-zip.js.map +1 -0
- package/build/sources/premium/patreon.d.ts +48 -0
- package/build/sources/premium/patreon.d.ts.map +1 -0
- package/build/sources/premium/patreon.js +248 -0
- package/build/sources/premium/patreon.js.map +1 -0
- package/build/sources/premium/youtube.d.ts +14 -0
- package/build/sources/premium/youtube.d.ts.map +1 -0
- package/build/sources/premium/youtube.js +92 -0
- package/build/sources/premium/youtube.js.map +1 -0
- package/build/tools/extract-cookie.d.ts +2 -0
- package/build/tools/extract-cookie.d.ts.map +1 -0
- package/build/tools/extract-cookie.js +40 -0
- package/build/tools/extract-cookie.js.map +1 -0
- package/build/tools/handlers/enableSource.d.ts +3 -0
- package/build/tools/handlers/enableSource.d.ts.map +1 -0
- package/build/tools/handlers/enableSource.js +39 -0
- package/build/tools/handlers/enableSource.js.map +1 -0
- package/build/tools/handlers/getSwiftPattern.d.ts +3 -0
- package/build/tools/handlers/getSwiftPattern.d.ts.map +1 -0
- package/build/tools/handlers/getSwiftPattern.js +78 -0
- package/build/tools/handlers/getSwiftPattern.js.map +1 -0
- package/build/tools/handlers/handlers.test.d.ts +2 -0
- package/build/tools/handlers/handlers.test.d.ts.map +1 -0
- package/build/tools/handlers/handlers.test.js +189 -0
- package/build/tools/handlers/handlers.test.js.map +1 -0
- package/build/tools/handlers/listContentSources.d.ts +3 -0
- package/build/tools/handlers/listContentSources.d.ts.map +1 -0
- package/build/tools/handlers/listContentSources.js +38 -0
- package/build/tools/handlers/listContentSources.js.map +1 -0
- package/build/tools/handlers/searchSwiftContent.d.ts +3 -0
- package/build/tools/handlers/searchSwiftContent.d.ts.map +1 -0
- package/build/tools/handlers/searchSwiftContent.js +44 -0
- package/build/tools/handlers/searchSwiftContent.js.map +1 -0
- package/build/tools/index.d.ts +3 -0
- package/build/tools/index.d.ts.map +1 -0
- package/build/tools/index.js +14 -0
- package/build/tools/index.js.map +1 -0
- package/build/tools/registry.d.ts +14 -0
- package/build/tools/registry.d.ts.map +1 -0
- package/build/tools/registry.js +21 -0
- package/build/tools/registry.js.map +1 -0
- package/build/tools/registry.test.d.ts +2 -0
- package/build/tools/registry.test.d.ts.map +1 -0
- package/build/tools/registry.test.js +54 -0
- package/build/tools/registry.test.js.map +1 -0
- package/build/tools/types.d.ts +25 -0
- package/build/tools/types.d.ts.map +1 -0
- package/build/tools/types.js +3 -0
- package/build/tools/types.js.map +1 -0
- package/build/utils/cache.d.ts +17 -0
- package/build/utils/cache.d.ts.map +1 -0
- package/build/utils/cache.js +144 -0
- package/build/utils/cache.js.map +1 -0
- package/build/utils/errors.d.ts +19 -0
- package/build/utils/errors.d.ts.map +1 -0
- package/build/utils/errors.js +34 -0
- package/build/utils/errors.js.map +1 -0
- package/build/utils/paths.d.ts +27 -0
- package/build/utils/paths.d.ts.map +1 -0
- package/build/utils/paths.js +43 -0
- package/build/utils/paths.js.map +1 -0
- package/build/utils/search.d.ts +29 -0
- package/build/utils/search.d.ts.map +1 -0
- package/build/utils/search.js +165 -0
- package/build/utils/search.js.map +1 -0
- package/build/utils/search.test.d.ts +2 -0
- package/build/utils/search.test.d.ts.map +1 -0
- package/build/utils/search.test.js +199 -0
- package/build/utils/search.test.js.map +1 -0
- package/build/utils/swift-analysis.d.ts +27 -0
- package/build/utils/swift-analysis.d.ts.map +1 -0
- package/build/utils/swift-analysis.js +78 -0
- package/build/utils/swift-analysis.js.map +1 -0
- package/build/utils/swift-analysis.test.d.ts +2 -0
- package/build/utils/swift-analysis.test.d.ts.map +1 -0
- package/build/utils/swift-analysis.test.js +215 -0
- package/build/utils/swift-analysis.test.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
// src/sources/premium/patreon.ts
|
|
2
|
+
import { loadTokens, getValidAccessToken } from './patreon-oauth.js';
|
|
3
|
+
import { getChannelVideos, searchVideos } from './youtube.js';
|
|
4
|
+
import { scanDownloadedContent } from './patreon-dl.js';
|
|
5
|
+
import { getByPatreonId } from '../../config/creators.js';
|
|
6
|
+
import { getPatreonCreatorsPath } from '../../utils/paths.js';
|
|
7
|
+
import { detectTopics, hasCodeContent, calculateRelevance } from '../../utils/swift-analysis.js';
|
|
8
|
+
import { BASE_TOPIC_KEYWORDS, BASE_QUALITY_SIGNALS, mergeKeywords, mergeQualitySignals } from '../../config/swift-keywords.js';
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
const PATREON_API = 'https://www.patreon.com/api/oauth2/v2';
|
|
12
|
+
// Patreon-specific keywords (extends base)
|
|
13
|
+
const patreonSpecificTopics = {
|
|
14
|
+
'swiftui': ['@observable'], // Adds to base
|
|
15
|
+
'architecture': ['clean architecture'], // Adds to base
|
|
16
|
+
};
|
|
17
|
+
const patreonSpecificSignals = {
|
|
18
|
+
'swift': 10,
|
|
19
|
+
'ios': 8,
|
|
20
|
+
'pattern': 6,
|
|
21
|
+
'best practice': 8,
|
|
22
|
+
};
|
|
23
|
+
const patreonTopicKeywords = mergeKeywords(BASE_TOPIC_KEYWORDS, patreonSpecificTopics);
|
|
24
|
+
const patreonQualitySignals = mergeQualitySignals(BASE_QUALITY_SIGNALS, patreonSpecificSignals);
|
|
25
|
+
// Patreon-specific scoring constants
|
|
26
|
+
const PATREON_CODE_BONUS = 15; // Higher bonus for code-heavy Patreon content
|
|
27
|
+
const PATREON_BASE_SCORE = 0; // Start at 0 for Patreon to rely on quality signals
|
|
28
|
+
function isSwiftRelated(name, summary) {
|
|
29
|
+
const text = `${name} ${summary || ''}`.toLowerCase();
|
|
30
|
+
const keywords = ['swift', 'swiftui', 'ios', 'apple', 'xcode', 'uikit', 'iphone', 'ipad'];
|
|
31
|
+
return keywords.some(k => text.includes(k));
|
|
32
|
+
}
|
|
33
|
+
export class PatreonSource {
|
|
34
|
+
clientId;
|
|
35
|
+
clientSecret;
|
|
36
|
+
enabledCreators = [];
|
|
37
|
+
constructor() {
|
|
38
|
+
this.clientId = process.env.PATREON_CLIENT_ID || '';
|
|
39
|
+
this.clientSecret = process.env.PATREON_CLIENT_SECRET || '';
|
|
40
|
+
this.loadEnabledCreators();
|
|
41
|
+
}
|
|
42
|
+
loadEnabledCreators() {
|
|
43
|
+
try {
|
|
44
|
+
const configPath = getPatreonCreatorsPath();
|
|
45
|
+
if (fs.existsSync(configPath)) {
|
|
46
|
+
const data = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
47
|
+
this.enabledCreators = data.enabledCreators || [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
this.enabledCreators = [];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
saveEnabledCreators(creatorIds) {
|
|
55
|
+
this.enabledCreators = creatorIds;
|
|
56
|
+
const configPath = getPatreonCreatorsPath();
|
|
57
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
58
|
+
fs.writeFileSync(configPath, JSON.stringify({ enabledCreators: creatorIds }, null, 2));
|
|
59
|
+
}
|
|
60
|
+
async isConfigured() {
|
|
61
|
+
if (!this.clientId || !this.clientSecret)
|
|
62
|
+
return false;
|
|
63
|
+
const tokens = await loadTokens();
|
|
64
|
+
return tokens !== null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns creators the user PAYS (patron memberships).
|
|
68
|
+
*
|
|
69
|
+
* IMPORTANT: This uses the identity endpoint with memberships.campaign include,
|
|
70
|
+
* NOT the /campaigns endpoint. The /campaigns endpoint only returns campaigns
|
|
71
|
+
* you OWN as a creator, not campaigns you subscribe to as a patron.
|
|
72
|
+
*
|
|
73
|
+
* Correct API: GET /identity?include=memberships.campaign
|
|
74
|
+
*/
|
|
75
|
+
async getSubscribedCreators() {
|
|
76
|
+
const accessToken = await getValidAccessToken(this.clientId, this.clientSecret);
|
|
77
|
+
if (!accessToken)
|
|
78
|
+
return [];
|
|
79
|
+
try {
|
|
80
|
+
// Use identity endpoint with memberships to get campaigns user is subscribed to
|
|
81
|
+
// This is the ONLY correct way to get patron memberships
|
|
82
|
+
const url = `${PATREON_API}/identity?include=memberships.campaign&fields[user]=full_name,email&fields[member]=patron_status&fields[campaign]=creation_name,url,summary`;
|
|
83
|
+
console.log(`Fetching: ${url}`);
|
|
84
|
+
const response = await fetch(url, {
|
|
85
|
+
headers: { 'Authorization': `Bearer ${accessToken}` }
|
|
86
|
+
});
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
const errorBody = await response.text();
|
|
89
|
+
console.error(`Failed to fetch memberships: ${response.status}`);
|
|
90
|
+
console.error(`Response: ${errorBody}`);
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
const data = await response.json();
|
|
94
|
+
if (!data.included) {
|
|
95
|
+
console.error('No memberships data in response. User may not have any active patron memberships.');
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
console.log(`Memberships response: ${JSON.stringify(data, null, 2).slice(0, 500)}`);
|
|
99
|
+
// Extract active memberships and their campaigns
|
|
100
|
+
const members = data.included.filter((item) => item.type === 'member' &&
|
|
101
|
+
item.attributes?.patron_status === 'active_patron');
|
|
102
|
+
const campaigns = data.included.filter((item) => item.type === 'campaign');
|
|
103
|
+
// Get campaign IDs from active memberships
|
|
104
|
+
const activeCampaignIds = new Set(members
|
|
105
|
+
.map(m => m.relationships?.campaign?.data?.id)
|
|
106
|
+
.filter((id) => !!id));
|
|
107
|
+
// Return campaigns user is actively subscribed to
|
|
108
|
+
const creators = campaigns
|
|
109
|
+
.filter(c => activeCampaignIds.has(c.id))
|
|
110
|
+
.map(campaign => ({
|
|
111
|
+
id: campaign.id,
|
|
112
|
+
name: campaign.attributes.creation_name,
|
|
113
|
+
url: campaign.attributes.url,
|
|
114
|
+
isSwiftRelated: isSwiftRelated(campaign.attributes.creation_name, campaign.attributes.summary),
|
|
115
|
+
}));
|
|
116
|
+
if (creators.length === 0) {
|
|
117
|
+
console.warn('No active Patreon memberships found. ' +
|
|
118
|
+
'You must be a paying patron of at least one creator to use Patreon with swift-mcp.');
|
|
119
|
+
}
|
|
120
|
+
return creators;
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
console.error('Failed to fetch subscribed creators:', error);
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async detectSwiftCreators() {
|
|
128
|
+
const creators = await this.getSubscribedCreators();
|
|
129
|
+
return creators.filter(c => c.isSwiftRelated);
|
|
130
|
+
}
|
|
131
|
+
async fetchPatterns(creatorId) {
|
|
132
|
+
const patterns = [];
|
|
133
|
+
const creatorsToFetch = creatorId
|
|
134
|
+
? [creatorId]
|
|
135
|
+
: this.enabledCreators;
|
|
136
|
+
console.log(`Fetching patterns for ${creatorsToFetch.length} creators:`, creatorsToFetch);
|
|
137
|
+
// 1. Scan locally downloaded content (from patreon-dl)
|
|
138
|
+
const downloadedPosts = scanDownloadedContent();
|
|
139
|
+
console.log(`Found ${downloadedPosts.length} downloaded posts`);
|
|
140
|
+
for (const post of downloadedPosts) {
|
|
141
|
+
// Filter by creator if specified
|
|
142
|
+
const creator = creatorsToFetch.length > 0
|
|
143
|
+
? getByPatreonId(creatorsToFetch.find(id => {
|
|
144
|
+
const c = getByPatreonId(id);
|
|
145
|
+
return c?.name === post.creator;
|
|
146
|
+
}) || '')
|
|
147
|
+
: null;
|
|
148
|
+
if (creatorsToFetch.length > 0 && !creator)
|
|
149
|
+
continue;
|
|
150
|
+
patterns.push(...this.downloadedPostToPatterns(post));
|
|
151
|
+
}
|
|
152
|
+
// 2. Fetch YouTube videos for additional metadata
|
|
153
|
+
for (const patreonId of creatorsToFetch) {
|
|
154
|
+
const creator = getByPatreonId(patreonId);
|
|
155
|
+
if (!creator?.youtubeChannelId) {
|
|
156
|
+
console.log(`No YouTube channel for creator ${patreonId}`);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
const videos = await getChannelVideos(creator.youtubeChannelId, 50);
|
|
161
|
+
console.log(`Found ${videos.length} videos for ${creator.name}`);
|
|
162
|
+
for (const video of videos) {
|
|
163
|
+
// Add video as pattern (skip if we already have downloaded content for this)
|
|
164
|
+
const hasDownloaded = patterns.some(p => p.url === video.patreonLink || p.title.includes(video.title));
|
|
165
|
+
if (!hasDownloaded) {
|
|
166
|
+
patterns.push(this.videoToPattern(video, creator.name));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
console.error(`Failed to fetch videos for ${creator.name}:`, error);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Sort by date (newest first)
|
|
175
|
+
patterns.sort((a, b) => new Date(b.publishDate).getTime() - new Date(a.publishDate).getTime());
|
|
176
|
+
return patterns;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Convert downloaded post to patterns
|
|
180
|
+
*/
|
|
181
|
+
downloadedPostToPatterns(post) {
|
|
182
|
+
const patterns = [];
|
|
183
|
+
for (const file of post.files) {
|
|
184
|
+
if (file.type === 'other')
|
|
185
|
+
continue;
|
|
186
|
+
const content = file.content || '';
|
|
187
|
+
const text = `${file.filename} ${content}`;
|
|
188
|
+
const topics = detectTopics(text, patreonTopicKeywords);
|
|
189
|
+
const hasCode = file.type === 'swift' || hasCodeContent(content);
|
|
190
|
+
const relevanceScore = calculateRelevance(text, hasCode, patreonQualitySignals, PATREON_BASE_SCORE, PATREON_CODE_BONUS);
|
|
191
|
+
patterns.push({
|
|
192
|
+
id: `dl-${post.postId}-${file.filename}`,
|
|
193
|
+
title: `${post.title} - ${file.filename}`,
|
|
194
|
+
url: `file://${file.filepath}`,
|
|
195
|
+
publishDate: post.publishDate || new Date().toISOString(),
|
|
196
|
+
excerpt: content.substring(0, 300),
|
|
197
|
+
content,
|
|
198
|
+
creator: post.creator,
|
|
199
|
+
topics,
|
|
200
|
+
relevanceScore,
|
|
201
|
+
hasCode,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return patterns;
|
|
205
|
+
}
|
|
206
|
+
videoToPattern(video, creatorName) {
|
|
207
|
+
const text = `${video.title} ${video.description}`;
|
|
208
|
+
const topics = detectTopics(text, patreonTopicKeywords);
|
|
209
|
+
const hasCode = hasCodeContent(video.description) || (video.codeLinks?.length ?? 0) > 0;
|
|
210
|
+
const relevanceScore = calculateRelevance(text, hasCode, patreonQualitySignals, PATREON_BASE_SCORE, PATREON_CODE_BONUS);
|
|
211
|
+
return {
|
|
212
|
+
id: `yt-${video.id}`,
|
|
213
|
+
title: video.title,
|
|
214
|
+
url: video.patreonLink || `https://youtube.com/watch?v=${video.id}`,
|
|
215
|
+
publishDate: video.publishedAt,
|
|
216
|
+
excerpt: video.description.substring(0, 300),
|
|
217
|
+
content: video.description,
|
|
218
|
+
creator: creatorName,
|
|
219
|
+
topics,
|
|
220
|
+
relevanceScore,
|
|
221
|
+
hasCode,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
async searchPatterns(query) {
|
|
225
|
+
const patterns = [];
|
|
226
|
+
// Search YouTube for each enabled creator
|
|
227
|
+
for (const patreonId of this.enabledCreators) {
|
|
228
|
+
const creator = getByPatreonId(patreonId);
|
|
229
|
+
if (!creator?.youtubeChannelId)
|
|
230
|
+
continue;
|
|
231
|
+
try {
|
|
232
|
+
const videos = await searchVideos(query, creator.youtubeChannelId, 25);
|
|
233
|
+
for (const video of videos) {
|
|
234
|
+
patterns.push(this.videoToPattern(video, creator.name));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
console.error(`Search failed for ${creator.name}:`, error);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return patterns;
|
|
242
|
+
}
|
|
243
|
+
isAvailable() {
|
|
244
|
+
return !!(this.clientId && this.clientSecret);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
export default PatreonSource;
|
|
248
|
+
//# sourceMappingURL=patreon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patreon.js","sourceRoot":"","sources":["../../../src/sources/premium/patreon.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface Video {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
description: string;
|
|
5
|
+
publishedAt: string;
|
|
6
|
+
channelId: string;
|
|
7
|
+
channelTitle: string;
|
|
8
|
+
tags?: string[];
|
|
9
|
+
patreonLink?: string;
|
|
10
|
+
codeLinks?: string[];
|
|
11
|
+
}
|
|
12
|
+
export declare function getChannelVideos(channelId: string, maxResults?: number): Promise<Video[]>;
|
|
13
|
+
export declare function searchVideos(query: string, channelId?: string, maxResults?: number): Promise<Video[]>;
|
|
14
|
+
//# sourceMappingURL=youtube.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"youtube.d.ts","sourceRoot":"","sources":["../../../src/sources/premium/youtube.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAYD,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,UAAU,SAAK,GACd,OAAO,CAAC,KAAK,EAAE,CAAC,CAgFlB;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,SAAK,GACd,OAAO,CAAC,KAAK,EAAE,CAAC,CAuClB"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// src/sources/premium/youtube.ts
|
|
2
|
+
// YouTube Data API client
|
|
3
|
+
const API_BASE = 'https://www.googleapis.com/youtube/v3';
|
|
4
|
+
function extractPatreonLink(text) {
|
|
5
|
+
const match = text.match(/https?:\/\/(www\.)?patreon\.com\/[^\s\)]+/i);
|
|
6
|
+
return match?.[0];
|
|
7
|
+
}
|
|
8
|
+
function extractCodeLinks(text) {
|
|
9
|
+
const matches = text.match(/https?:\/\/(github\.com|gist\.github\.com)[^\s\)]+/gi);
|
|
10
|
+
return matches || [];
|
|
11
|
+
}
|
|
12
|
+
export async function getChannelVideos(channelId, maxResults = 50) {
|
|
13
|
+
const apiKey = process.env.YOUTUBE_API_KEY;
|
|
14
|
+
if (!apiKey) {
|
|
15
|
+
console.error('YOUTUBE_API_KEY not set');
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
// Search for videos
|
|
20
|
+
const searchUrl = `${API_BASE}/search?key=${apiKey}&channelId=${channelId}&part=snippet&type=video&order=date&maxResults=${maxResults}`;
|
|
21
|
+
const searchRes = await fetch(searchUrl);
|
|
22
|
+
if (!searchRes.ok) {
|
|
23
|
+
console.error(`YouTube search failed: ${searchRes.status}`);
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
const searchData = await searchRes.json();
|
|
27
|
+
const videoIds = searchData.items.map(i => i.id.videoId).join(',');
|
|
28
|
+
if (!videoIds)
|
|
29
|
+
return [];
|
|
30
|
+
// Get full video details (includes tags)
|
|
31
|
+
const videosUrl = `${API_BASE}/videos?key=${apiKey}&id=${videoIds}&part=snippet`;
|
|
32
|
+
const videosRes = await fetch(videosUrl);
|
|
33
|
+
if (!videosRes.ok) {
|
|
34
|
+
// Fallback to search results
|
|
35
|
+
return searchData.items.map(i => ({
|
|
36
|
+
id: i.id.videoId,
|
|
37
|
+
title: i.snippet.title,
|
|
38
|
+
description: i.snippet.description,
|
|
39
|
+
publishedAt: i.snippet.publishedAt,
|
|
40
|
+
channelId: i.snippet.channelId,
|
|
41
|
+
channelTitle: i.snippet.channelTitle,
|
|
42
|
+
patreonLink: extractPatreonLink(i.snippet.description),
|
|
43
|
+
codeLinks: extractCodeLinks(i.snippet.description),
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
const videosData = await videosRes.json();
|
|
47
|
+
return videosData.items.map(i => ({
|
|
48
|
+
id: i.id,
|
|
49
|
+
title: i.snippet.title,
|
|
50
|
+
description: i.snippet.description,
|
|
51
|
+
publishedAt: i.snippet.publishedAt,
|
|
52
|
+
channelId: i.snippet.channelId,
|
|
53
|
+
channelTitle: i.snippet.channelTitle,
|
|
54
|
+
tags: i.snippet.tags,
|
|
55
|
+
patreonLink: extractPatreonLink(i.snippet.description),
|
|
56
|
+
codeLinks: extractCodeLinks(i.snippet.description),
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
console.error('YouTube API error:', err);
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export async function searchVideos(query, channelId, maxResults = 25) {
|
|
65
|
+
const apiKey = process.env.YOUTUBE_API_KEY;
|
|
66
|
+
if (!apiKey)
|
|
67
|
+
return [];
|
|
68
|
+
try {
|
|
69
|
+
let url = `${API_BASE}/search?key=${apiKey}&q=${encodeURIComponent(query)}&part=snippet&type=video&maxResults=${maxResults}`;
|
|
70
|
+
if (channelId) {
|
|
71
|
+
url += `&channelId=${channelId}`;
|
|
72
|
+
}
|
|
73
|
+
const res = await fetch(url);
|
|
74
|
+
if (!res.ok)
|
|
75
|
+
return [];
|
|
76
|
+
const data = await res.json();
|
|
77
|
+
return data.items.map(i => ({
|
|
78
|
+
id: i.id.videoId,
|
|
79
|
+
title: i.snippet.title,
|
|
80
|
+
description: i.snippet.description,
|
|
81
|
+
publishedAt: i.snippet.publishedAt,
|
|
82
|
+
channelId: i.snippet.channelId,
|
|
83
|
+
channelTitle: i.snippet.channelTitle,
|
|
84
|
+
patreonLink: extractPatreonLink(i.snippet.description),
|
|
85
|
+
codeLinks: extractCodeLinks(i.snippet.description),
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=youtube.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"youtube.js","sourceRoot":"","sources":["../../../src/sources/premium/youtube.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-cookie.d.ts","sourceRoot":"","sources":["../../src/tools/extract-cookie.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { chromium } from 'playwright';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
const PROFILE_DIR = path.join(process.cwd(), '.patreon-profile');
|
|
5
|
+
const COOKIE_FILE = '.patreon-session';
|
|
6
|
+
(async () => {
|
|
7
|
+
// Use persistent context - preserves login sessions across runs
|
|
8
|
+
const context = await chromium.launchPersistentContext(PROFILE_DIR, {
|
|
9
|
+
headless: false,
|
|
10
|
+
});
|
|
11
|
+
const page = context.pages()[0] || await context.newPage();
|
|
12
|
+
// Check if already logged in by looking for existing session cookie
|
|
13
|
+
const existingCookies = await context.cookies('https://www.patreon.com');
|
|
14
|
+
const existingSession = existingCookies.find(c => c.name === 'session_id');
|
|
15
|
+
if (existingSession) {
|
|
16
|
+
console.log('Found existing session from persistent profile!');
|
|
17
|
+
fs.writeFileSync(COOKIE_FILE, existingSession.value);
|
|
18
|
+
console.log('Saved session_id!');
|
|
19
|
+
await context.close();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
// No existing session, need to log in
|
|
23
|
+
await page.goto('https://www.patreon.com/login');
|
|
24
|
+
console.log('Please log in. Waiting for session cookie...');
|
|
25
|
+
// Poll for session cookie instead of waiting for Enter
|
|
26
|
+
let cookies = await context.cookies('https://www.patreon.com');
|
|
27
|
+
let sessionCookie = cookies.find(c => c.name === 'session_id');
|
|
28
|
+
while (!sessionCookie) {
|
|
29
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
30
|
+
cookies = await context.cookies('https://www.patreon.com');
|
|
31
|
+
sessionCookie = cookies.find(c => c.name === 'session_id');
|
|
32
|
+
}
|
|
33
|
+
console.log('Login detected!');
|
|
34
|
+
// Debug: log all cookie names
|
|
35
|
+
console.log('Available cookies:', cookies.map(c => c.name).join(', '));
|
|
36
|
+
fs.writeFileSync(COOKIE_FILE, sessionCookie.value);
|
|
37
|
+
console.log('Saved session_id!');
|
|
38
|
+
await context.close();
|
|
39
|
+
})();
|
|
40
|
+
//# sourceMappingURL=extract-cookie.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-cookie.js","sourceRoot":"","sources":["../../src/tools/extract-cookie.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,kBAAkB,CAAC,CAAC;AACjE,MAAM,WAAW,GAAG,kBAAkB,CAAC;AAEvC,CAAC,KAAK,IAAI,EAAE;IACV,gEAAgE;IAChE,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,uBAAuB,CAAC,WAAW,EAAE;QAClE,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IAE3D,oEAAoE;IACpE,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACzE,MAAM,eAAe,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IAE3E,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QAC/D,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACjC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO;IACT,CAAC;IAED,sCAAsC;IACtC,MAAM,IAAI,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAE5D,uDAAuD;IACvD,IAAI,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC/D,IAAI,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IAE/D,OAAO,CAAC,aAAa,EAAE,CAAC;QACtB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACxD,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;QAC3D,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAE/B,8BAA8B;IAC9B,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAEvE,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACjC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;AACxB,CAAC,CAAC,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enableSource.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/enableSource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,eAAO,MAAM,mBAAmB,EAAE,WAwCjC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/tools/handlers/enableSource.ts
|
|
2
|
+
export const enableSourceHandler = async (args, context) => {
|
|
3
|
+
const sourceId = args?.source;
|
|
4
|
+
const source = context.sourceManager.getSource(sourceId);
|
|
5
|
+
if (!source) {
|
|
6
|
+
return {
|
|
7
|
+
content: [{
|
|
8
|
+
type: "text",
|
|
9
|
+
text: `Unknown source: "${sourceId}"
|
|
10
|
+
|
|
11
|
+
Available sources:
|
|
12
|
+
${context.sourceManager.getAllSources().map(s => `- ${s.id}: ${s.name}`).join('\n')}`,
|
|
13
|
+
}],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (source.requiresAuth && !context.sourceManager.isSourceConfigured(sourceId)) {
|
|
17
|
+
return {
|
|
18
|
+
content: [{
|
|
19
|
+
type: "text",
|
|
20
|
+
text: `āļø ${source.name} requires setup first.
|
|
21
|
+
|
|
22
|
+
Run: swift-mcp setup --${sourceId}
|
|
23
|
+
|
|
24
|
+
This will guide you through:
|
|
25
|
+
${sourceId === 'patreon' ? '- Patreon OAuth authentication\n- Connecting your subscriptions' : '- Authentication setup'}`,
|
|
26
|
+
}],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
context.sourceManager.enableSource(sourceId);
|
|
30
|
+
return {
|
|
31
|
+
content: [{
|
|
32
|
+
type: "text",
|
|
33
|
+
text: `ā
${source.name} enabled!
|
|
34
|
+
|
|
35
|
+
You can now use patterns from this source.`,
|
|
36
|
+
}],
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=enableSource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enableSource.js","sourceRoot":"","sources":["../../../src/tools/handlers/enableSource.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAIrC,MAAM,CAAC,MAAM,mBAAmB,GAAgB,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IACtE,MAAM,QAAQ,GAAG,IAAI,EAAE,MAAgB,CAAC;IACxC,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAEzD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,oBAAoB,QAAQ;;;EAGxC,OAAO,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;iBAC9E,CAAC;SACH,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/E,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,MAAM,MAAM,CAAC,IAAI;;yBAEN,QAAQ;;;EAG/B,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,iEAAiE,CAAC,CAAC,CAAC,wBAAwB,EAAE;iBAClH,CAAC;SACH,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO;QACL,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,KAAK,MAAM,CAAC,IAAI;;2CAEe;aACtC,CAAC;KACH,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getSwiftPattern.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/getSwiftPattern.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,eAAO,MAAM,sBAAsB,EAAE,WAkFpC,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// src/tools/handlers/getSwiftPattern.ts
|
|
2
|
+
import SundellSource from '../../sources/free/sundell.js';
|
|
3
|
+
import VanderLeeSource from '../../sources/free/vanderlee.js';
|
|
4
|
+
export const getSwiftPatternHandler = async (args, context) => {
|
|
5
|
+
const topic = args?.topic;
|
|
6
|
+
if (!topic) {
|
|
7
|
+
return {
|
|
8
|
+
content: [{
|
|
9
|
+
type: "text",
|
|
10
|
+
text: `Missing required argument: topic
|
|
11
|
+
|
|
12
|
+
Usage: get_swift_pattern({ topic: "swiftui" })
|
|
13
|
+
|
|
14
|
+
Example topics:
|
|
15
|
+
- swiftui, concurrency, testing, networking
|
|
16
|
+
- performance, architecture, protocols
|
|
17
|
+
- async-await, combine, coredata`,
|
|
18
|
+
}],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const source = args?.source || "all";
|
|
22
|
+
const minQuality = args?.minQuality || 60;
|
|
23
|
+
const results = [];
|
|
24
|
+
// Get from free sources
|
|
25
|
+
if (source === "all" || source === "sundell") {
|
|
26
|
+
const sundell = new SundellSource();
|
|
27
|
+
const patterns = await sundell.searchPatterns(topic);
|
|
28
|
+
results.push(...patterns.filter(p => p.relevanceScore >= minQuality));
|
|
29
|
+
}
|
|
30
|
+
if (source === "all" || source === "vanderlee") {
|
|
31
|
+
const vanderlee = new VanderLeeSource();
|
|
32
|
+
const patterns = await vanderlee.searchPatterns(topic);
|
|
33
|
+
results.push(...patterns.filter(p => p.relevanceScore >= minQuality));
|
|
34
|
+
}
|
|
35
|
+
if (results.length === 0) {
|
|
36
|
+
return {
|
|
37
|
+
content: [{
|
|
38
|
+
type: "text",
|
|
39
|
+
text: `No patterns found for "${topic}" with quality ā„ ${minQuality}.
|
|
40
|
+
|
|
41
|
+
Try:
|
|
42
|
+
- Broader search terms
|
|
43
|
+
- Lower minQuality
|
|
44
|
+
- Different topic
|
|
45
|
+
|
|
46
|
+
Available sources: Swift by Sundell, Antoine van der Lee
|
|
47
|
+
${context.sourceManager.isSourceConfigured('patreon') ? '\nš” Enable Patreon for more premium content!' : ''}`,
|
|
48
|
+
}],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Sort by relevance
|
|
52
|
+
results.sort((a, b) => b.relevanceScore - a.relevanceScore);
|
|
53
|
+
const formatted = results.slice(0, 10).map(p => `
|
|
54
|
+
## ${p.title}
|
|
55
|
+
**Source**: ${p.id.split('-')[0]}
|
|
56
|
+
**Quality**: ${p.relevanceScore}/100
|
|
57
|
+
**Topics**: ${p.topics.join(', ')}
|
|
58
|
+
${p.hasCode ? '**Has Code**: ā
' : ''}
|
|
59
|
+
|
|
60
|
+
${p.excerpt}...
|
|
61
|
+
|
|
62
|
+
**[Read full article](${p.url})**
|
|
63
|
+
`).join('\n---\n');
|
|
64
|
+
return {
|
|
65
|
+
content: [{
|
|
66
|
+
type: "text",
|
|
67
|
+
text: `# Swift Patterns: ${topic}
|
|
68
|
+
|
|
69
|
+
Found ${results.length} patterns from free sources:
|
|
70
|
+
|
|
71
|
+
${formatted}
|
|
72
|
+
|
|
73
|
+
${results.length > 10 ? `\n*Showing top 10 of ${results.length} results*` : ''}
|
|
74
|
+
`,
|
|
75
|
+
}],
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=getSwiftPattern.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getSwiftPattern.js","sourceRoot":"","sources":["../../../src/tools/handlers/getSwiftPattern.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.test.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/handlers.test.ts"],"names":[],"mappings":""}
|