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.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +377 -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 +43 -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 +149 -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 +65 -0
  20. package/build/config/sources.d.ts.map +1 -0
  21. package/build/config/sources.js +184 -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 +195 -0
  26. package/build/config/sources.test.js.map +1 -0
  27. package/build/config/swift-keywords.d.ts +21 -0
  28. package/build/config/swift-keywords.d.ts.map +1 -0
  29. package/build/config/swift-keywords.js +67 -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 +295 -0
  34. package/build/index.js.map +1 -0
  35. package/build/integration/mcp-client.test.d.ts +2 -0
  36. package/build/integration/mcp-client.test.d.ts.map +1 -0
  37. package/build/integration/mcp-client.test.js +82 -0
  38. package/build/integration/mcp-client.test.js.map +1 -0
  39. package/build/integration/response-quality.test.d.ts +2 -0
  40. package/build/integration/response-quality.test.d.ts.map +1 -0
  41. package/build/integration/response-quality.test.js +139 -0
  42. package/build/integration/response-quality.test.js.map +1 -0
  43. package/build/integration/test-client.d.ts +25 -0
  44. package/build/integration/test-client.d.ts.map +1 -0
  45. package/build/integration/test-client.js +93 -0
  46. package/build/integration/test-client.js.map +1 -0
  47. package/build/sources/free/rssPatternSource.d.ts +41 -0
  48. package/build/sources/free/rssPatternSource.d.ts.map +1 -0
  49. package/build/sources/free/rssPatternSource.js +122 -0
  50. package/build/sources/free/rssPatternSource.js.map +1 -0
  51. package/build/sources/free/rssPatternSource.test.d.ts +2 -0
  52. package/build/sources/free/rssPatternSource.test.d.ts.map +1 -0
  53. package/build/sources/free/rssPatternSource.test.js +92 -0
  54. package/build/sources/free/rssPatternSource.test.js.map +1 -0
  55. package/build/sources/free/sundell.d.ts +9 -0
  56. package/build/sources/free/sundell.d.ts.map +1 -0
  57. package/build/sources/free/sundell.js +31 -0
  58. package/build/sources/free/sundell.js.map +1 -0
  59. package/build/sources/free/sundell.test.d.ts +2 -0
  60. package/build/sources/free/sundell.test.d.ts.map +1 -0
  61. package/build/sources/free/sundell.test.js +63 -0
  62. package/build/sources/free/sundell.test.js.map +1 -0
  63. package/build/sources/free/vanderlee.d.ts +9 -0
  64. package/build/sources/free/vanderlee.d.ts.map +1 -0
  65. package/build/sources/free/vanderlee.js +71 -0
  66. package/build/sources/free/vanderlee.js.map +1 -0
  67. package/build/sources/free/vanderlee.test.d.ts +2 -0
  68. package/build/sources/free/vanderlee.test.d.ts.map +1 -0
  69. package/build/sources/free/vanderlee.test.js +73 -0
  70. package/build/sources/free/vanderlee.test.js.map +1 -0
  71. package/build/sources/premium/patreon-dl.d.ts +45 -0
  72. package/build/sources/premium/patreon-dl.d.ts.map +1 -0
  73. package/build/sources/premium/patreon-dl.js +189 -0
  74. package/build/sources/premium/patreon-dl.js.map +1 -0
  75. package/build/sources/premium/patreon-fetch.d.ts +3 -0
  76. package/build/sources/premium/patreon-fetch.d.ts.map +1 -0
  77. package/build/sources/premium/patreon-fetch.js +18 -0
  78. package/build/sources/premium/patreon-fetch.js.map +1 -0
  79. package/build/sources/premium/patreon-oauth.d.ts +24 -0
  80. package/build/sources/premium/patreon-oauth.d.ts.map +1 -0
  81. package/build/sources/premium/patreon-oauth.js +207 -0
  82. package/build/sources/premium/patreon-oauth.js.map +1 -0
  83. package/build/sources/premium/patreon-zip.d.ts +17 -0
  84. package/build/sources/premium/patreon-zip.d.ts.map +1 -0
  85. package/build/sources/premium/patreon-zip.js +128 -0
  86. package/build/sources/premium/patreon-zip.js.map +1 -0
  87. package/build/sources/premium/patreon.d.ts +48 -0
  88. package/build/sources/premium/patreon.d.ts.map +1 -0
  89. package/build/sources/premium/patreon.js +248 -0
  90. package/build/sources/premium/patreon.js.map +1 -0
  91. package/build/sources/premium/youtube.d.ts +14 -0
  92. package/build/sources/premium/youtube.d.ts.map +1 -0
  93. package/build/sources/premium/youtube.js +92 -0
  94. package/build/sources/premium/youtube.js.map +1 -0
  95. package/build/tools/extract-cookie.d.ts +2 -0
  96. package/build/tools/extract-cookie.d.ts.map +1 -0
  97. package/build/tools/extract-cookie.js +40 -0
  98. package/build/tools/extract-cookie.js.map +1 -0
  99. package/build/tools/handlers/enableSource.d.ts +3 -0
  100. package/build/tools/handlers/enableSource.d.ts.map +1 -0
  101. package/build/tools/handlers/enableSource.js +39 -0
  102. package/build/tools/handlers/enableSource.js.map +1 -0
  103. package/build/tools/handlers/getSwiftPattern.d.ts +3 -0
  104. package/build/tools/handlers/getSwiftPattern.d.ts.map +1 -0
  105. package/build/tools/handlers/getSwiftPattern.js +78 -0
  106. package/build/tools/handlers/getSwiftPattern.js.map +1 -0
  107. package/build/tools/handlers/handlers.test.d.ts +2 -0
  108. package/build/tools/handlers/handlers.test.d.ts.map +1 -0
  109. package/build/tools/handlers/handlers.test.js +189 -0
  110. package/build/tools/handlers/handlers.test.js.map +1 -0
  111. package/build/tools/handlers/listContentSources.d.ts +3 -0
  112. package/build/tools/handlers/listContentSources.d.ts.map +1 -0
  113. package/build/tools/handlers/listContentSources.js +38 -0
  114. package/build/tools/handlers/listContentSources.js.map +1 -0
  115. package/build/tools/handlers/searchSwiftContent.d.ts +3 -0
  116. package/build/tools/handlers/searchSwiftContent.d.ts.map +1 -0
  117. package/build/tools/handlers/searchSwiftContent.js +44 -0
  118. package/build/tools/handlers/searchSwiftContent.js.map +1 -0
  119. package/build/tools/index.d.ts +3 -0
  120. package/build/tools/index.d.ts.map +1 -0
  121. package/build/tools/index.js +14 -0
  122. package/build/tools/index.js.map +1 -0
  123. package/build/tools/registry.d.ts +14 -0
  124. package/build/tools/registry.d.ts.map +1 -0
  125. package/build/tools/registry.js +21 -0
  126. package/build/tools/registry.js.map +1 -0
  127. package/build/tools/registry.test.d.ts +2 -0
  128. package/build/tools/registry.test.d.ts.map +1 -0
  129. package/build/tools/registry.test.js +54 -0
  130. package/build/tools/registry.test.js.map +1 -0
  131. package/build/tools/types.d.ts +25 -0
  132. package/build/tools/types.d.ts.map +1 -0
  133. package/build/tools/types.js +3 -0
  134. package/build/tools/types.js.map +1 -0
  135. package/build/utils/cache.d.ts +17 -0
  136. package/build/utils/cache.d.ts.map +1 -0
  137. package/build/utils/cache.js +144 -0
  138. package/build/utils/cache.js.map +1 -0
  139. package/build/utils/errors.d.ts +19 -0
  140. package/build/utils/errors.d.ts.map +1 -0
  141. package/build/utils/errors.js +34 -0
  142. package/build/utils/errors.js.map +1 -0
  143. package/build/utils/paths.d.ts +27 -0
  144. package/build/utils/paths.d.ts.map +1 -0
  145. package/build/utils/paths.js +43 -0
  146. package/build/utils/paths.js.map +1 -0
  147. package/build/utils/search.d.ts +29 -0
  148. package/build/utils/search.d.ts.map +1 -0
  149. package/build/utils/search.js +165 -0
  150. package/build/utils/search.js.map +1 -0
  151. package/build/utils/search.test.d.ts +2 -0
  152. package/build/utils/search.test.d.ts.map +1 -0
  153. package/build/utils/search.test.js +199 -0
  154. package/build/utils/search.test.js.map +1 -0
  155. package/build/utils/swift-analysis.d.ts +27 -0
  156. package/build/utils/swift-analysis.d.ts.map +1 -0
  157. package/build/utils/swift-analysis.js +78 -0
  158. package/build/utils/swift-analysis.js.map +1 -0
  159. package/build/utils/swift-analysis.test.d.ts +2 -0
  160. package/build/utils/swift-analysis.test.d.ts.map +1 -0
  161. package/build/utils/swift-analysis.test.js +215 -0
  162. package/build/utils/swift-analysis.test.js.map +1 -0
  163. package/package.json +73 -0
@@ -0,0 +1,207 @@
1
+ // src/sources/premium/patreon-oauth.ts
2
+ import http from 'http';
3
+ import { exec } from 'child_process';
4
+ import { URL } from 'url';
5
+ import { join } from 'path';
6
+ import { homedir } from 'os';
7
+ import fs from 'fs/promises';
8
+ import keytar from 'keytar';
9
+ const SERVICE_NAME = 'swift-mcp';
10
+ const ACCOUNT_NAME = 'patreon-tokens';
11
+ const CALLBACK_PORT = 9876;
12
+ const PATREON_AUTH_URL = 'https://www.patreon.com/oauth2/authorize';
13
+ const PATREON_TOKEN_URL = 'https://www.patreon.com/api/oauth2/token';
14
+ // Scopes explained:
15
+ // - identity: Basic user info
16
+ // - identity.memberships: REQUIRED - access to patron memberships via /identity endpoint
17
+ // - campaigns: Access campaigns you manage (creator-only, optional)
18
+ // - campaigns.members: Access members of your own campaign (creator-only, optional)
19
+ export const PATREON_SCOPES = [
20
+ 'identity',
21
+ 'identity.memberships', // REQUIRED: patron memberships live here
22
+ 'campaigns',
23
+ 'campaigns.members',
24
+ ].join(' ');
25
+ export async function saveTokens(tokens) {
26
+ const encrypted = JSON.stringify(tokens);
27
+ await keytar.setPassword(SERVICE_NAME, ACCOUNT_NAME, encrypted);
28
+ }
29
+ export async function loadTokens() {
30
+ try {
31
+ const encrypted = await keytar.getPassword(SERVICE_NAME, ACCOUNT_NAME);
32
+ if (!encrypted)
33
+ return null;
34
+ return JSON.parse(encrypted);
35
+ }
36
+ catch {
37
+ return null;
38
+ }
39
+ }
40
+ export async function clearTokens() {
41
+ await keytar.deletePassword(SERVICE_NAME, ACCOUNT_NAME);
42
+ }
43
+ export function isTokenExpired(tokens) {
44
+ // Refresh 5 minutes before actual expiry
45
+ return Date.now() >= (tokens.expires_at - 5 * 60 * 1000);
46
+ }
47
+ export async function refreshAccessToken(clientId, clientSecret, refreshToken) {
48
+ const response = await fetch(PATREON_TOKEN_URL, {
49
+ method: 'POST',
50
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
51
+ body: new URLSearchParams({
52
+ grant_type: 'refresh_token',
53
+ refresh_token: refreshToken,
54
+ client_id: clientId,
55
+ client_secret: clientSecret,
56
+ }),
57
+ });
58
+ if (!response.ok) {
59
+ throw new Error(`Token refresh failed: ${response.status}`);
60
+ }
61
+ const data = await response.json();
62
+ const tokens = {
63
+ access_token: data.access_token,
64
+ refresh_token: data.refresh_token,
65
+ expires_at: Date.now() + data.expires_in * 1000,
66
+ scope: data.scope,
67
+ };
68
+ await saveTokens(tokens);
69
+ return tokens;
70
+ }
71
+ export async function startOAuthFlow(clientId, clientSecret) {
72
+ return new Promise((resolve) => {
73
+ const redirectUri = `http://localhost:${CALLBACK_PORT}/callback`;
74
+ const authUrl = new URL(PATREON_AUTH_URL);
75
+ authUrl.searchParams.set('client_id', clientId);
76
+ authUrl.searchParams.set('redirect_uri', redirectUri);
77
+ authUrl.searchParams.set('response_type', 'code');
78
+ authUrl.searchParams.set('scope', PATREON_SCOPES);
79
+ let serverClosed = false;
80
+ const server = http.createServer(async (req, res) => {
81
+ if (!req.url?.startsWith('/callback')) {
82
+ res.writeHead(404);
83
+ res.end('Not found');
84
+ return;
85
+ }
86
+ const url = new URL(req.url, `http://localhost:${CALLBACK_PORT}`);
87
+ const code = url.searchParams.get('code');
88
+ const error = url.searchParams.get('error');
89
+ if (error) {
90
+ res.writeHead(200, { 'Content-Type': 'text/html' });
91
+ res.end('<h1>Authorization Denied</h1><p>You can close this window.</p>');
92
+ if (!serverClosed) {
93
+ serverClosed = true;
94
+ server.close();
95
+ resolve({ success: false, error });
96
+ }
97
+ return;
98
+ }
99
+ if (!code) {
100
+ res.writeHead(400, { 'Content-Type': 'text/html' });
101
+ res.end('<h1>Error</h1><p>No authorization code received.</p>');
102
+ return;
103
+ }
104
+ try {
105
+ // Exchange code for tokens
106
+ const tokenResponse = await fetch(PATREON_TOKEN_URL, {
107
+ method: 'POST',
108
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
109
+ body: new URLSearchParams({
110
+ code,
111
+ grant_type: 'authorization_code',
112
+ client_id: clientId,
113
+ client_secret: clientSecret,
114
+ redirect_uri: redirectUri,
115
+ }),
116
+ });
117
+ if (!tokenResponse.ok) {
118
+ throw new Error(`Token exchange failed: ${tokenResponse.status}`);
119
+ }
120
+ const data = await tokenResponse.json();
121
+ const tokens = {
122
+ access_token: data.access_token,
123
+ refresh_token: data.refresh_token,
124
+ expires_at: Date.now() + data.expires_in * 1000,
125
+ scope: data.scope,
126
+ };
127
+ await saveTokens(tokens);
128
+ res.writeHead(200, { 'Content-Type': 'text/html' });
129
+ res.end(`
130
+ <html>
131
+ <body style="font-family: system-ui; text-align: center; padding: 50px;">
132
+ <h1>Authorization Successful!</h1>
133
+ <p>You can close this window and return to the terminal.</p>
134
+ </body>
135
+ </html>
136
+ `);
137
+ if (!serverClosed) {
138
+ serverClosed = true;
139
+ server.close();
140
+ resolve({ success: true, tokens });
141
+ }
142
+ }
143
+ catch (err) {
144
+ res.writeHead(500, { 'Content-Type': 'text/html' });
145
+ res.end('<h1>Error</h1><p>Failed to complete authorization.</p>');
146
+ if (!serverClosed) {
147
+ serverClosed = true;
148
+ server.close();
149
+ resolve({ success: false, error: String(err) });
150
+ }
151
+ }
152
+ });
153
+ server.listen(CALLBACK_PORT, '127.0.0.1', () => {
154
+ console.log(`\nOpening browser for Patreon authorization...`);
155
+ console.log(`If browser doesn't open, visit: ${authUrl.toString()}\n`);
156
+ // Open browser
157
+ const cmd = process.platform === 'darwin' ? 'open' :
158
+ process.platform === 'win32' ? 'start' : 'xdg-open';
159
+ exec(`${cmd} "${authUrl.toString()}"`);
160
+ });
161
+ // Timeout after 60 seconds
162
+ setTimeout(() => {
163
+ if (!serverClosed) {
164
+ serverClosed = true;
165
+ server.close();
166
+ resolve({ success: false, error: 'Authorization timed out after 60 seconds' });
167
+ }
168
+ }, 60000);
169
+ });
170
+ }
171
+ export async function getValidAccessToken(clientId, clientSecret) {
172
+ const tokens = await loadTokens();
173
+ if (!tokens)
174
+ return null;
175
+ if (isTokenExpired(tokens)) {
176
+ try {
177
+ const refreshed = await refreshAccessToken(clientId, clientSecret, tokens.refresh_token);
178
+ return refreshed.access_token;
179
+ }
180
+ catch {
181
+ // Refresh failed, need to re-authenticate
182
+ await clearTokens();
183
+ return null;
184
+ }
185
+ }
186
+ return tokens.access_token;
187
+ }
188
+ // =============================================================================
189
+ // Cleanup & Reset
190
+ // =============================================================================
191
+ /**
192
+ * Clear all Patreon authentication data (keytar + legacy tokens.json)
193
+ */
194
+ export async function clearPatreonAuth() {
195
+ // Clear from keytar
196
+ await keytar.deletePassword(SERVICE_NAME, "patreon");
197
+ await keytar.deletePassword(SERVICE_NAME, ACCOUNT_NAME);
198
+ // Clear legacy tokens.json file
199
+ const tokensPath = join(homedir(), ".swift-mcp", "tokens.json");
200
+ try {
201
+ await fs.rm(tokensPath, { force: true });
202
+ }
203
+ catch {
204
+ // Ignore if file doesn't exist
205
+ }
206
+ }
207
+ //# sourceMappingURL=patreon-oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patreon-oauth.js","sourceRoot":"","sources":["../../../src/sources/premium/patreon-oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface ExtractedPattern {
2
+ filename: string;
3
+ content: string;
4
+ type: 'swift' | 'markdown' | 'playground' | 'other';
5
+ hasCode: boolean;
6
+ topics: string[];
7
+ }
8
+ export interface ZipExtractionResult {
9
+ success: boolean;
10
+ patterns: ExtractedPattern[];
11
+ warnings: string[];
12
+ }
13
+ export declare function downloadZip(url: string, postId: string, accessToken: string): Promise<string | null>;
14
+ export declare function extractZip(zipPath: string, postId: string): ZipExtractionResult;
15
+ export declare function extractFromAttachment(attachmentUrl: string, postId: string, accessToken: string): Promise<ZipExtractionResult>;
16
+ export declare function clearZipCache(): void;
17
+ //# sourceMappingURL=patreon-zip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patreon-zip.d.ts","sourceRoot":"","sources":["../../../src/sources/premium/patreon-zip.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,YAAY,GAAG,OAAO,CAAC;IACpD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAuBD,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoCxB;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAwD/E;AAED,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,mBAAmB,CAAC,CAY9B;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC"}
@@ -0,0 +1,128 @@
1
+ // src/sources/premium/patreon-zip.ts
2
+ import AdmZip from 'adm-zip';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { getCacheDir } from '../../utils/paths.js';
6
+ import { detectTopics, hasCodeContent } from '../../utils/swift-analysis.js';
7
+ import { BASE_TOPIC_KEYWORDS, mergeKeywords } from '../../config/swift-keywords.js';
8
+ const MAX_ZIP_SIZE = 50 * 1024 * 1024; // 50MB
9
+ const MAX_FILES = 100;
10
+ // Zip-specific keywords (extends base with more detailed patterns)
11
+ const zipSpecificTopics = {
12
+ 'concurrency': ['sendable'], // Adds to base
13
+ 'networking': ['request'], // Adds to base
14
+ 'testing': ['stub'], // Adds to base
15
+ 'architecture': ['repository', 'usecase'], // Adds to base
16
+ 'uikit': ['uitableview', 'uicollectionview'], // Adds to base
17
+ };
18
+ const zipTopicKeywords = mergeKeywords(BASE_TOPIC_KEYWORDS, zipSpecificTopics);
19
+ function detectFileType(filename) {
20
+ const ext = path.extname(filename).toLowerCase();
21
+ switch (ext) {
22
+ case '.swift': return 'swift';
23
+ case '.md':
24
+ case '.markdown': return 'markdown';
25
+ case '.playground': return 'playground';
26
+ default: return 'other';
27
+ }
28
+ }
29
+ export async function downloadZip(url, postId, accessToken) {
30
+ const cacheDir = getCacheDir('zips');
31
+ const zipPath = path.join(cacheDir, `${postId}.zip`);
32
+ // Check if already cached
33
+ if (fs.existsSync(zipPath)) {
34
+ return zipPath;
35
+ }
36
+ try {
37
+ const response = await fetch(url, {
38
+ headers: { 'Authorization': `Bearer ${accessToken}` },
39
+ });
40
+ if (!response.ok) {
41
+ console.error(`Failed to download zip: ${response.status}`);
42
+ return null;
43
+ }
44
+ const contentLength = response.headers.get('content-length');
45
+ if (contentLength && parseInt(contentLength, 10) > MAX_ZIP_SIZE) {
46
+ console.warn(`Zip file too large (${contentLength} bytes), skipping`);
47
+ return null;
48
+ }
49
+ // Ensure cache directory exists
50
+ fs.mkdirSync(cacheDir, { recursive: true });
51
+ const buffer = Buffer.from(await response.arrayBuffer());
52
+ fs.writeFileSync(zipPath, buffer);
53
+ return zipPath;
54
+ }
55
+ catch (error) {
56
+ console.error('Zip download failed:', error);
57
+ return null;
58
+ }
59
+ }
60
+ export function extractZip(zipPath, postId) {
61
+ const warnings = [];
62
+ const patterns = [];
63
+ const destDir = path.join(getCacheDir('zips'), postId);
64
+ try {
65
+ const zip = new AdmZip(zipPath);
66
+ const entries = zip.getEntries();
67
+ if (entries.length > MAX_FILES) {
68
+ warnings.push(`Zip contains ${entries.length} files, extracting first ${MAX_FILES}`);
69
+ }
70
+ // Ensure destination exists
71
+ fs.mkdirSync(destDir, { recursive: true });
72
+ let count = 0;
73
+ for (const entry of entries) {
74
+ if (count >= MAX_FILES)
75
+ break;
76
+ if (entry.isDirectory)
77
+ continue;
78
+ const filename = entry.entryName;
79
+ const type = detectFileType(filename);
80
+ // Skip non-relevant files
81
+ if (type === 'other')
82
+ continue;
83
+ try {
84
+ const content = entry.getData().toString('utf8');
85
+ const text = `${filename} ${content}`;
86
+ const topics = detectTopics(text, zipTopicKeywords);
87
+ const hasCode = hasCodeContent(content);
88
+ patterns.push({
89
+ filename,
90
+ content,
91
+ type,
92
+ hasCode,
93
+ topics,
94
+ });
95
+ count++;
96
+ }
97
+ catch (err) {
98
+ warnings.push(`Failed to read ${filename}: ${err}`);
99
+ }
100
+ }
101
+ return { success: true, patterns, warnings };
102
+ }
103
+ catch (error) {
104
+ return {
105
+ success: false,
106
+ patterns: [],
107
+ warnings: [`Extraction failed: ${error}`],
108
+ };
109
+ }
110
+ }
111
+ export async function extractFromAttachment(attachmentUrl, postId, accessToken) {
112
+ const zipPath = await downloadZip(attachmentUrl, postId, accessToken);
113
+ if (!zipPath) {
114
+ return {
115
+ success: false,
116
+ patterns: [],
117
+ warnings: ['Failed to download zip attachment'],
118
+ };
119
+ }
120
+ return extractZip(zipPath, postId);
121
+ }
122
+ export function clearZipCache() {
123
+ const cacheDir = getCacheDir('zips');
124
+ if (fs.existsSync(cacheDir)) {
125
+ fs.rmSync(cacheDir, { recursive: true });
126
+ }
127
+ }
128
+ //# sourceMappingURL=patreon-zip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patreon-zip.js","sourceRoot":"","sources":["../../../src/sources/premium/patreon-zip.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ export interface PatreonPattern {
2
+ id: string;
3
+ title: string;
4
+ url: string;
5
+ publishDate: string;
6
+ excerpt: string;
7
+ content: string;
8
+ creator: string;
9
+ topics: string[];
10
+ relevanceScore: number;
11
+ hasCode: boolean;
12
+ }
13
+ export interface CreatorInfo {
14
+ id: string;
15
+ name: string;
16
+ url: string;
17
+ isSwiftRelated: boolean;
18
+ }
19
+ export declare class PatreonSource {
20
+ private clientId;
21
+ private clientSecret;
22
+ private enabledCreators;
23
+ constructor();
24
+ private loadEnabledCreators;
25
+ saveEnabledCreators(creatorIds: string[]): void;
26
+ isConfigured(): Promise<boolean>;
27
+ /**
28
+ * Returns creators the user PAYS (patron memberships).
29
+ *
30
+ * IMPORTANT: This uses the identity endpoint with memberships.campaign include,
31
+ * NOT the /campaigns endpoint. The /campaigns endpoint only returns campaigns
32
+ * you OWN as a creator, not campaigns you subscribe to as a patron.
33
+ *
34
+ * Correct API: GET /identity?include=memberships.campaign
35
+ */
36
+ getSubscribedCreators(): Promise<CreatorInfo[]>;
37
+ detectSwiftCreators(): Promise<CreatorInfo[]>;
38
+ fetchPatterns(creatorId?: string): Promise<PatreonPattern[]>;
39
+ /**
40
+ * Convert downloaded post to patterns
41
+ */
42
+ private downloadedPostToPatterns;
43
+ private videoToPattern;
44
+ searchPatterns(query: string): Promise<PatreonPattern[]>;
45
+ isAvailable(): boolean;
46
+ }
47
+ export default PatreonSource;
48
+ //# sourceMappingURL=patreon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patreon.d.ts","sourceRoot":"","sources":["../../../src/sources/premium/patreon.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,OAAO,CAAC;CACzB;AA0DD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAgB;;IAQvC,OAAO,CAAC,mBAAmB;IAY3B,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI;IAOzC,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IAMtC;;;;;;;;OAQG;IACG,qBAAqB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IA2E/C,mBAAmB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAK7C,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA4DlE;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA8BhC,OAAO,CAAC,cAAc;IAoBhB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAqB9D,WAAW,IAAI,OAAO;CAGvB;AAED,eAAe,aAAa,CAAC"}