webpeel 0.12.0 → 0.12.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/README.md +82 -9
- package/dist/cli.js +97 -6
- package/dist/cli.js.map +1 -1
- package/dist/core/actions.d.ts +28 -0
- package/dist/core/actions.d.ts.map +1 -1
- package/dist/core/actions.js +60 -0
- package/dist/core/actions.js.map +1 -1
- package/dist/core/bm25-filter.d.ts +10 -0
- package/dist/core/bm25-filter.d.ts.map +1 -1
- package/dist/core/bm25-filter.js +40 -0
- package/dist/core/bm25-filter.js.map +1 -1
- package/dist/core/content-pruner.d.ts +12 -5
- package/dist/core/content-pruner.d.ts.map +1 -1
- package/dist/core/content-pruner.js +247 -190
- package/dist/core/content-pruner.js.map +1 -1
- package/dist/core/research.d.ts +67 -0
- package/dist/core/research.d.ts.map +1 -0
- package/dist/core/research.js +254 -0
- package/dist/core/research.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +107 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/server/app.d.ts +14 -0
- package/dist/server/app.d.ts.map +1 -0
- package/dist/server/app.js +189 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/auth-store.d.ts +28 -0
- package/dist/server/auth-store.d.ts.map +1 -0
- package/dist/server/auth-store.js +89 -0
- package/dist/server/auth-store.js.map +1 -0
- package/dist/server/job-queue.d.ts +93 -0
- package/dist/server/job-queue.d.ts.map +1 -0
- package/dist/server/job-queue.js +144 -0
- package/dist/server/job-queue.js.map +1 -0
- package/dist/server/middleware/auth.d.ts +28 -0
- package/dist/server/middleware/auth.d.ts.map +1 -0
- package/dist/server/middleware/auth.js +183 -0
- package/dist/server/middleware/auth.js.map +1 -0
- package/dist/server/middleware/rate-limit.d.ts +23 -0
- package/dist/server/middleware/rate-limit.d.ts.map +1 -0
- package/dist/server/middleware/rate-limit.js +126 -0
- package/dist/server/middleware/rate-limit.js.map +1 -0
- package/dist/server/middleware/url-validator.d.ts +16 -0
- package/dist/server/middleware/url-validator.d.ts.map +1 -0
- package/dist/server/middleware/url-validator.js +187 -0
- package/dist/server/middleware/url-validator.js.map +1 -0
- package/dist/server/pg-auth-store.d.ts +129 -0
- package/dist/server/pg-auth-store.d.ts.map +1 -0
- package/dist/server/pg-auth-store.js +457 -0
- package/dist/server/pg-auth-store.js.map +1 -0
- package/dist/server/pg-job-queue.d.ts +60 -0
- package/dist/server/pg-job-queue.d.ts.map +1 -0
- package/dist/server/pg-job-queue.js +365 -0
- package/dist/server/pg-job-queue.js.map +1 -0
- package/dist/server/premium/domain-intel.d.ts +17 -0
- package/dist/server/premium/domain-intel.d.ts.map +1 -0
- package/dist/server/premium/domain-intel.js +134 -0
- package/dist/server/premium/domain-intel.js.map +1 -0
- package/dist/server/premium/index.d.ts +18 -0
- package/dist/server/premium/index.d.ts.map +1 -0
- package/dist/server/premium/index.js +36 -0
- package/dist/server/premium/index.js.map +1 -0
- package/dist/server/premium/swr-cache.d.ts +15 -0
- package/dist/server/premium/swr-cache.d.ts.map +1 -0
- package/dist/server/premium/swr-cache.js +35 -0
- package/dist/server/premium/swr-cache.js.map +1 -0
- package/dist/server/routes/activity.d.ts +7 -0
- package/dist/server/routes/activity.d.ts.map +1 -0
- package/dist/server/routes/activity.js +66 -0
- package/dist/server/routes/activity.js.map +1 -0
- package/dist/server/routes/agent.d.ts +12 -0
- package/dist/server/routes/agent.d.ts.map +1 -0
- package/dist/server/routes/agent.js +356 -0
- package/dist/server/routes/agent.js.map +1 -0
- package/dist/server/routes/answer.d.ts +6 -0
- package/dist/server/routes/answer.d.ts.map +1 -0
- package/dist/server/routes/answer.js +124 -0
- package/dist/server/routes/answer.js.map +1 -0
- package/dist/server/routes/batch.d.ts +7 -0
- package/dist/server/routes/batch.d.ts.map +1 -0
- package/dist/server/routes/batch.js +287 -0
- package/dist/server/routes/batch.js.map +1 -0
- package/dist/server/routes/cli-usage.d.ts +7 -0
- package/dist/server/routes/cli-usage.d.ts.map +1 -0
- package/dist/server/routes/cli-usage.js +121 -0
- package/dist/server/routes/cli-usage.js.map +1 -0
- package/dist/server/routes/compat.d.ts +24 -0
- package/dist/server/routes/compat.d.ts.map +1 -0
- package/dist/server/routes/compat.js +651 -0
- package/dist/server/routes/compat.js.map +1 -0
- package/dist/server/routes/extract.d.ts +9 -0
- package/dist/server/routes/extract.d.ts.map +1 -0
- package/dist/server/routes/extract.js +121 -0
- package/dist/server/routes/extract.js.map +1 -0
- package/dist/server/routes/fetch.d.ts +7 -0
- package/dist/server/routes/fetch.d.ts.map +1 -0
- package/dist/server/routes/fetch.js +537 -0
- package/dist/server/routes/fetch.js.map +1 -0
- package/dist/server/routes/health.d.ts +8 -0
- package/dist/server/routes/health.d.ts.map +1 -0
- package/dist/server/routes/health.js +36 -0
- package/dist/server/routes/health.js.map +1 -0
- package/dist/server/routes/jobs.d.ts +8 -0
- package/dist/server/routes/jobs.d.ts.map +1 -0
- package/dist/server/routes/jobs.js +374 -0
- package/dist/server/routes/jobs.js.map +1 -0
- package/dist/server/routes/mcp.d.ts +16 -0
- package/dist/server/routes/mcp.d.ts.map +1 -0
- package/dist/server/routes/mcp.js +475 -0
- package/dist/server/routes/mcp.js.map +1 -0
- package/dist/server/routes/oauth.d.ts +10 -0
- package/dist/server/routes/oauth.d.ts.map +1 -0
- package/dist/server/routes/oauth.js +296 -0
- package/dist/server/routes/oauth.js.map +1 -0
- package/dist/server/routes/screenshot.d.ts +10 -0
- package/dist/server/routes/screenshot.d.ts.map +1 -0
- package/dist/server/routes/screenshot.js +217 -0
- package/dist/server/routes/screenshot.js.map +1 -0
- package/dist/server/routes/search.d.ts +7 -0
- package/dist/server/routes/search.d.ts.map +1 -0
- package/dist/server/routes/search.js +287 -0
- package/dist/server/routes/search.js.map +1 -0
- package/dist/server/routes/stats.d.ts +7 -0
- package/dist/server/routes/stats.d.ts.map +1 -0
- package/dist/server/routes/stats.js +65 -0
- package/dist/server/routes/stats.js.map +1 -0
- package/dist/server/routes/stripe.d.ts +9 -0
- package/dist/server/routes/stripe.d.ts.map +1 -0
- package/dist/server/routes/stripe.js +233 -0
- package/dist/server/routes/stripe.js.map +1 -0
- package/dist/server/routes/users.d.ts +9 -0
- package/dist/server/routes/users.d.ts.map +1 -0
- package/dist/server/routes/users.js +954 -0
- package/dist/server/routes/users.js.map +1 -0
- package/dist/server/routes/webhooks.d.ts +15 -0
- package/dist/server/routes/webhooks.d.ts.map +1 -0
- package/dist/server/routes/webhooks.js +73 -0
- package/dist/server/routes/webhooks.js.map +1 -0
- package/dist/server/sentry.d.ts +14 -0
- package/dist/server/sentry.d.ts.map +1 -0
- package/dist/server/sentry.js +39 -0
- package/dist/server/sentry.js.map +1 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search endpoint with caching — supports DuckDuckGo (default) and Brave (BYOK)
|
|
3
|
+
*/
|
|
4
|
+
import { Router } from 'express';
|
|
5
|
+
import { fetch as undiciFetch } from 'undici';
|
|
6
|
+
import { load } from 'cheerio';
|
|
7
|
+
import { LRUCache } from 'lru-cache';
|
|
8
|
+
import { peel } from '../../index.js';
|
|
9
|
+
import { getSearchProvider, } from '../../core/search-provider.js';
|
|
10
|
+
export function createSearchRouter(authStore) {
|
|
11
|
+
const router = Router();
|
|
12
|
+
// LRU cache: 15 minute TTL, max 500 entries, 50MB total size
|
|
13
|
+
const cache = new LRUCache({
|
|
14
|
+
max: 500,
|
|
15
|
+
ttl: 15 * 60 * 1000, // 15 minutes
|
|
16
|
+
maxSize: 50 * 1024 * 1024, // 50MB
|
|
17
|
+
sizeCalculation: (entry) => {
|
|
18
|
+
return JSON.stringify(entry).length;
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
router.get('/v1/search', async (req, res) => {
|
|
22
|
+
try {
|
|
23
|
+
const { q, count, scrapeResults, sources, categories, tbs, country, location } = req.query;
|
|
24
|
+
// --- Search provider (new: BYOK Brave support) ---
|
|
25
|
+
const providerParam = (req.query.provider || '').toLowerCase() || 'duckduckgo';
|
|
26
|
+
const validProviders = ['duckduckgo', 'brave'];
|
|
27
|
+
const providerId = validProviders.includes(providerParam)
|
|
28
|
+
? providerParam
|
|
29
|
+
: 'duckduckgo';
|
|
30
|
+
// API key: query param, header, or empty
|
|
31
|
+
const searchApiKey = req.query.searchApiKey ||
|
|
32
|
+
req.headers['x-search-api-key'] ||
|
|
33
|
+
'';
|
|
34
|
+
// Validate query parameter
|
|
35
|
+
if (!q || typeof q !== 'string') {
|
|
36
|
+
res.status(400).json({
|
|
37
|
+
error: 'invalid_request',
|
|
38
|
+
message: 'Missing or invalid "q" parameter. Pass a search query: GET /v1/search?q=your+search+terms',
|
|
39
|
+
example: 'curl "https://api.webpeel.dev/v1/search?q=latest+AI+news&count=5"',
|
|
40
|
+
docs: 'https://webpeel.dev/docs/api-reference#search',
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
// Parse and validate count
|
|
45
|
+
const resultCount = count ? parseInt(count, 10) : 5;
|
|
46
|
+
if (isNaN(resultCount) || resultCount < 1 || resultCount > 10) {
|
|
47
|
+
res.status(400).json({
|
|
48
|
+
error: 'invalid_request',
|
|
49
|
+
message: 'Invalid "count" parameter: must be between 1 and 10',
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// Parse sources parameter (comma-separated: web,news,images)
|
|
54
|
+
const sourcesStr = sources || 'web';
|
|
55
|
+
const sourcesArray = sourcesStr.split(',').map(s => s.trim());
|
|
56
|
+
const shouldScrape = scrapeResults === 'true';
|
|
57
|
+
// Parse new search parameters
|
|
58
|
+
const categoriesStr = categories || '';
|
|
59
|
+
const tbsStr = tbs || '';
|
|
60
|
+
const countryStr = country || '';
|
|
61
|
+
const locationStr = location || '';
|
|
62
|
+
// Build cache key (include all parameters)
|
|
63
|
+
const cacheKey = `search:${providerId}:${q}:${resultCount}:${sourcesStr}:${shouldScrape}:${categoriesStr}:${tbsStr}:${countryStr}:${locationStr}`;
|
|
64
|
+
// Check cache
|
|
65
|
+
const cached = cache.get(cacheKey);
|
|
66
|
+
if (cached) {
|
|
67
|
+
res.setHeader('X-Cache', 'HIT');
|
|
68
|
+
res.setHeader('X-Cache-Age', Math.floor((Date.now() - cached.timestamp) / 1000).toString());
|
|
69
|
+
res.json({
|
|
70
|
+
success: true,
|
|
71
|
+
data: cached.data,
|
|
72
|
+
});
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const startTime = Date.now();
|
|
76
|
+
const data = {};
|
|
77
|
+
// Fetch web results via the search-provider abstraction
|
|
78
|
+
if (sourcesArray.includes('web')) {
|
|
79
|
+
const provider = getSearchProvider(providerId);
|
|
80
|
+
const providerResults = await provider.searchWeb(q, {
|
|
81
|
+
count: resultCount,
|
|
82
|
+
apiKey: searchApiKey || undefined,
|
|
83
|
+
tbs: tbsStr || undefined,
|
|
84
|
+
country: countryStr || undefined,
|
|
85
|
+
location: locationStr || undefined,
|
|
86
|
+
});
|
|
87
|
+
// Map to SearchResult (with optional content field)
|
|
88
|
+
let results = providerResults.map(r => ({
|
|
89
|
+
title: r.title,
|
|
90
|
+
url: r.url,
|
|
91
|
+
snippet: r.snippet,
|
|
92
|
+
}));
|
|
93
|
+
// Apply category filtering if specified
|
|
94
|
+
if (categoriesStr) {
|
|
95
|
+
const categoryList = categoriesStr.split(',').map(c => c.trim().toLowerCase());
|
|
96
|
+
results = results.filter(result => {
|
|
97
|
+
const urlLower = result.url.toLowerCase();
|
|
98
|
+
return categoryList.some(category => {
|
|
99
|
+
switch (category) {
|
|
100
|
+
case 'github':
|
|
101
|
+
return urlLower.includes('github.com');
|
|
102
|
+
case 'pdf':
|
|
103
|
+
return urlLower.endsWith('.pdf');
|
|
104
|
+
case 'docs':
|
|
105
|
+
case 'documentation':
|
|
106
|
+
return urlLower.includes('/docs') || urlLower.includes('/documentation');
|
|
107
|
+
case 'blog':
|
|
108
|
+
return urlLower.includes('blog') || urlLower.includes('/post/');
|
|
109
|
+
case 'news':
|
|
110
|
+
return urlLower.includes('news') || urlLower.includes('/article/');
|
|
111
|
+
case 'video':
|
|
112
|
+
return urlLower.includes('youtube.com') || urlLower.includes('vimeo.com');
|
|
113
|
+
case 'social':
|
|
114
|
+
return urlLower.includes('twitter.com') || urlLower.includes('x.com') ||
|
|
115
|
+
urlLower.includes('facebook.com') || urlLower.includes('linkedin.com');
|
|
116
|
+
default:
|
|
117
|
+
return urlLower.includes(category);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// Scrape each result URL if requested
|
|
123
|
+
if (shouldScrape) {
|
|
124
|
+
for (const result of results) {
|
|
125
|
+
try {
|
|
126
|
+
const peelResult = await peel(result.url, {
|
|
127
|
+
format: 'markdown',
|
|
128
|
+
maxTokens: 2000,
|
|
129
|
+
});
|
|
130
|
+
result.content = peelResult.content;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
result.content = `[Failed to scrape: ${error.message}]`;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
data.web = results;
|
|
138
|
+
}
|
|
139
|
+
// Fetch news results (DDG only — Brave news is not supported via HTML scraping)
|
|
140
|
+
if (sourcesArray.includes('news')) {
|
|
141
|
+
const newsUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(q)}&t=news`;
|
|
142
|
+
const response = await undiciFetch(newsUrl, {
|
|
143
|
+
headers: {
|
|
144
|
+
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
if (response.ok) {
|
|
148
|
+
const html = await response.text();
|
|
149
|
+
const $ = load(html);
|
|
150
|
+
const results = [];
|
|
151
|
+
$('.result').each((_i, elem) => {
|
|
152
|
+
if (results.length >= resultCount)
|
|
153
|
+
return;
|
|
154
|
+
const $result = $(elem);
|
|
155
|
+
let title = $result.find('.result__title').text().trim();
|
|
156
|
+
const rawUrl = $result.find('.result__a').attr('href') || '';
|
|
157
|
+
let snippet = $result.find('.result__snippet').text().trim();
|
|
158
|
+
const sourceText = $result.find('.result__extras__url').text().trim();
|
|
159
|
+
if (!title || !rawUrl)
|
|
160
|
+
return;
|
|
161
|
+
let url = rawUrl;
|
|
162
|
+
try {
|
|
163
|
+
const ddgUrl = new URL(rawUrl, 'https://duckduckgo.com');
|
|
164
|
+
const uddg = ddgUrl.searchParams.get('uddg');
|
|
165
|
+
if (uddg) {
|
|
166
|
+
url = decodeURIComponent(uddg);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// Use raw URL if parsing fails
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const parsed = new URL(url);
|
|
174
|
+
if (!['http:', 'https:'].includes(parsed.protocol)) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
url = parsed.href;
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
title = title.slice(0, 200);
|
|
183
|
+
snippet = snippet.slice(0, 500);
|
|
184
|
+
results.push({
|
|
185
|
+
title,
|
|
186
|
+
url,
|
|
187
|
+
snippet,
|
|
188
|
+
source: sourceText.slice(0, 100),
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
data.news = results;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// Fetch image results (DDG only)
|
|
195
|
+
if (sourcesArray.includes('images')) {
|
|
196
|
+
const imagesUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(q)}&t=images`;
|
|
197
|
+
const response = await undiciFetch(imagesUrl, {
|
|
198
|
+
headers: {
|
|
199
|
+
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
if (response.ok) {
|
|
203
|
+
const html = await response.text();
|
|
204
|
+
const $ = load(html);
|
|
205
|
+
const results = [];
|
|
206
|
+
$('.result').each((_i, elem) => {
|
|
207
|
+
if (results.length >= resultCount)
|
|
208
|
+
return;
|
|
209
|
+
const $result = $(elem);
|
|
210
|
+
const title = $result.find('.result__title').text().trim();
|
|
211
|
+
const thumbnail = $result.find('.result__image img').attr('src') || '';
|
|
212
|
+
const rawUrl = $result.find('.result__a').attr('href') || '';
|
|
213
|
+
const sourceText = $result.find('.result__extras__url').text().trim();
|
|
214
|
+
if (!title || !rawUrl || !thumbnail)
|
|
215
|
+
return;
|
|
216
|
+
let url = rawUrl;
|
|
217
|
+
try {
|
|
218
|
+
const ddgUrl = new URL(rawUrl, 'https://duckduckgo.com');
|
|
219
|
+
const uddg = ddgUrl.searchParams.get('uddg');
|
|
220
|
+
if (uddg) {
|
|
221
|
+
url = decodeURIComponent(uddg);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// Use raw URL if parsing fails
|
|
226
|
+
}
|
|
227
|
+
results.push({
|
|
228
|
+
title: title.slice(0, 200),
|
|
229
|
+
url,
|
|
230
|
+
thumbnail,
|
|
231
|
+
source: sourceText.slice(0, 100),
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
data.images = results;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
const elapsed = Date.now() - startTime;
|
|
238
|
+
// Track usage
|
|
239
|
+
const isSoftLimited = req.auth?.softLimited === true;
|
|
240
|
+
const hasExtraUsage = req.auth?.extraUsageAvailable === true;
|
|
241
|
+
const pgStore = authStore;
|
|
242
|
+
if (req.auth?.keyInfo?.key && typeof pgStore.trackBurstUsage === 'function') {
|
|
243
|
+
// Track burst usage (always)
|
|
244
|
+
await pgStore.trackBurstUsage(req.auth.keyInfo.key);
|
|
245
|
+
// If soft-limited with extra usage available, charge to extra usage
|
|
246
|
+
if (isSoftLimited && hasExtraUsage) {
|
|
247
|
+
const extraResult = await pgStore.trackExtraUsage(req.auth.keyInfo.key, 'search', `search:${q}`, elapsed, 200);
|
|
248
|
+
if (extraResult.success) {
|
|
249
|
+
res.setHeader('X-Extra-Usage-Charged', `$${extraResult.cost.toFixed(4)}`);
|
|
250
|
+
res.setHeader('X-Extra-Usage-New-Balance', extraResult.newBalance.toFixed(2));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
else if (!isSoftLimited) {
|
|
254
|
+
// Normal weekly usage tracking
|
|
255
|
+
await pgStore.trackUsage(req.auth.keyInfo.key, 'search');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Cache results
|
|
259
|
+
cache.set(cacheKey, {
|
|
260
|
+
data,
|
|
261
|
+
timestamp: Date.now(),
|
|
262
|
+
});
|
|
263
|
+
// Add headers
|
|
264
|
+
res.setHeader('X-Cache', 'MISS');
|
|
265
|
+
res.setHeader('X-Credits-Used', '1');
|
|
266
|
+
res.setHeader('X-Processing-Time', elapsed.toString());
|
|
267
|
+
res.setHeader('X-Fetch-Type', 'search');
|
|
268
|
+
res.json({
|
|
269
|
+
success: true,
|
|
270
|
+
data,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
const err = error;
|
|
275
|
+
// SECURITY: Generic error message to prevent information disclosure
|
|
276
|
+
console.error('Search error:', err); // Log full error server-side
|
|
277
|
+
res.status(500).json({
|
|
278
|
+
error: 'search_failed',
|
|
279
|
+
message: 'Search request failed. If using Brave provider, verify your API key. Otherwise try again.',
|
|
280
|
+
hint: 'Free search uses DuckDuckGo (no key required). For higher quality, add provider=brave&searchApiKey=YOUR_KEY',
|
|
281
|
+
docs: 'https://webpeel.dev/docs/api-reference#search',
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
return router;
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/server/routes/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../src/server/routes/stats.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAkE9D"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stats endpoint - provides dashboard statistics
|
|
3
|
+
*/
|
|
4
|
+
import { Router } from 'express';
|
|
5
|
+
import { PostgresAuthStore } from '../pg-auth-store.js';
|
|
6
|
+
export function createStatsRouter(authStore) {
|
|
7
|
+
const router = Router();
|
|
8
|
+
router.get('/v1/stats', async (req, res) => {
|
|
9
|
+
try {
|
|
10
|
+
// Require authentication (API key or JWT session token)
|
|
11
|
+
const userId = req.auth?.keyInfo?.accountId || req.user?.userId;
|
|
12
|
+
if (!userId) {
|
|
13
|
+
res.status(401).json({
|
|
14
|
+
error: 'unauthorized',
|
|
15
|
+
message: 'Authentication required',
|
|
16
|
+
});
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
// Only works with PostgreSQL backend
|
|
20
|
+
if (!(authStore instanceof PostgresAuthStore)) {
|
|
21
|
+
res.status(501).json({
|
|
22
|
+
error: 'not_implemented',
|
|
23
|
+
message: 'Stats endpoint requires PostgreSQL backend',
|
|
24
|
+
});
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// Access pool via any cast (pool is private but we need direct DB access)
|
|
28
|
+
const pgStore = authStore;
|
|
29
|
+
// Get stats from usage_logs table
|
|
30
|
+
const statsQuery = `
|
|
31
|
+
SELECT
|
|
32
|
+
COUNT(*) as total_requests,
|
|
33
|
+
AVG(CASE WHEN status_code >= 200 AND status_code < 300 THEN 1.0 ELSE 0.0 END) * 100 as success_rate,
|
|
34
|
+
AVG(processing_time_ms) as avg_response_time
|
|
35
|
+
FROM usage_logs
|
|
36
|
+
WHERE user_id = $1
|
|
37
|
+
`;
|
|
38
|
+
const result = await pgStore.pool.query(statsQuery, [userId]);
|
|
39
|
+
if (result.rows.length === 0) {
|
|
40
|
+
// No data yet - return defaults
|
|
41
|
+
res.json({
|
|
42
|
+
totalRequests: 0,
|
|
43
|
+
successRate: 100,
|
|
44
|
+
avgResponseTime: 0,
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const row = result.rows[0];
|
|
49
|
+
res.json({
|
|
50
|
+
totalRequests: parseInt(row.total_requests) || 0,
|
|
51
|
+
successRate: parseFloat(row.success_rate) || 100,
|
|
52
|
+
avgResponseTime: Math.round(parseFloat(row.avg_response_time)) || 0,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error('Stats error:', error);
|
|
57
|
+
res.status(500).json({
|
|
58
|
+
error: 'internal_error',
|
|
59
|
+
message: 'Failed to retrieve stats',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return router;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/server/routes/stats.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,MAAM,UAAU,iBAAiB,CAAC,SAAoB;IACpD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;QAC5D,IAAI,CAAC;YACH,wDAAwD;YACxD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,IAAK,GAAW,CAAC,IAAI,EAAE,MAAM,CAAC;YACzE,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,yBAAyB;iBACnC,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,qCAAqC;YACrC,IAAI,CAAC,CAAC,SAAS,YAAY,iBAAiB,CAAC,EAAE,CAAC;gBAC9C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,KAAK,EAAE,iBAAiB;oBACxB,OAAO,EAAE,4CAA4C;iBACtD,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,0EAA0E;YAC1E,MAAM,OAAO,GAAG,SAAgB,CAAC;YAEjC,kCAAkC;YAClC,MAAM,UAAU,GAAG;;;;;;;OAOlB,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;YAE9D,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7B,gCAAgC;gBAChC,GAAG,CAAC,IAAI,CAAC;oBACP,aAAa,EAAE,CAAC;oBAChB,WAAW,EAAE,GAAG;oBAChB,eAAe,EAAE,CAAC;iBACnB,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAE3B,GAAG,CAAC,IAAI,CAAC;gBACP,aAAa,EAAE,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC;gBAChD,WAAW,EAAE,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,GAAG;gBAChD,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC;aACpE,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;YACrC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,gBAAgB;gBACvB,OAAO,EAAE,0BAA0B;aACpC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripe.d.ts","sourceRoot":"","sources":["../../../src/server/routes/stripe.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAepD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CA4G3C"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stripe webhook handler for subscription management
|
|
3
|
+
*/
|
|
4
|
+
import { Router } from 'express';
|
|
5
|
+
import Stripe from 'stripe';
|
|
6
|
+
import pg from 'pg';
|
|
7
|
+
const { Pool } = pg;
|
|
8
|
+
/**
|
|
9
|
+
* Tier configuration (weekly usage model)
|
|
10
|
+
*/
|
|
11
|
+
const TIER_LIMITS = {
|
|
12
|
+
free: { weekly_limit: 125, burst_limit: 25, rate_limit: 10 },
|
|
13
|
+
pro: { weekly_limit: 1250, burst_limit: 100, rate_limit: 60 },
|
|
14
|
+
max: { weekly_limit: 6250, burst_limit: 500, rate_limit: 200 },
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Create Stripe webhook router
|
|
18
|
+
*/
|
|
19
|
+
export function createStripeRouter() {
|
|
20
|
+
const router = Router();
|
|
21
|
+
const stripeSecretKey = process.env.STRIPE_SECRET_KEY;
|
|
22
|
+
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
|
|
23
|
+
const dbUrl = process.env.DATABASE_URL;
|
|
24
|
+
if (!stripeSecretKey) {
|
|
25
|
+
console.warn('STRIPE_SECRET_KEY not configured - Stripe webhooks disabled');
|
|
26
|
+
return router;
|
|
27
|
+
}
|
|
28
|
+
if (!webhookSecret) {
|
|
29
|
+
console.warn('STRIPE_WEBHOOK_SECRET not configured - Stripe webhooks disabled');
|
|
30
|
+
return router;
|
|
31
|
+
}
|
|
32
|
+
if (!dbUrl) {
|
|
33
|
+
throw new Error('DATABASE_URL environment variable is required');
|
|
34
|
+
}
|
|
35
|
+
const stripe = new Stripe(stripeSecretKey);
|
|
36
|
+
const pool = new Pool({
|
|
37
|
+
connectionString: dbUrl,
|
|
38
|
+
// TLS: enabled when DATABASE_URL contains sslmode=require.
|
|
39
|
+
// Secure by default (rejectUnauthorized: true); set PG_REJECT_UNAUTHORIZED=false
|
|
40
|
+
// only for managed DBs (Render/Neon/Supabase) that use self-signed certs.
|
|
41
|
+
ssl: process.env.DATABASE_URL?.includes('sslmode=require')
|
|
42
|
+
? { rejectUnauthorized: process.env.PG_REJECT_UNAUTHORIZED !== 'false' }
|
|
43
|
+
: undefined,
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* POST /v1/webhooks/stripe
|
|
47
|
+
* Handle Stripe webhook events
|
|
48
|
+
* SECURITY: Verifies webhook signature
|
|
49
|
+
*/
|
|
50
|
+
router.post('/', async (req, res) => {
|
|
51
|
+
try {
|
|
52
|
+
const sig = req.headers['stripe-signature'];
|
|
53
|
+
if (!sig || typeof sig !== 'string') {
|
|
54
|
+
res.status(400).json({
|
|
55
|
+
error: 'missing_signature',
|
|
56
|
+
message: 'Stripe signature header missing',
|
|
57
|
+
});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
// SECURITY: Verify webhook signature
|
|
61
|
+
let event;
|
|
62
|
+
try {
|
|
63
|
+
event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
console.error('Webhook signature verification failed:', err.message);
|
|
67
|
+
res.status(400).json({
|
|
68
|
+
error: 'invalid_signature',
|
|
69
|
+
message: 'Webhook signature verification failed',
|
|
70
|
+
});
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// Handle different event types
|
|
74
|
+
switch (event.type) {
|
|
75
|
+
case 'checkout.session.completed': {
|
|
76
|
+
const session = event.data.object;
|
|
77
|
+
await handleCheckoutCompleted(pool, session);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
case 'customer.subscription.updated': {
|
|
81
|
+
const subscription = event.data.object;
|
|
82
|
+
await handleSubscriptionUpdated(pool, subscription);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case 'customer.subscription.deleted': {
|
|
86
|
+
const subscription = event.data.object;
|
|
87
|
+
await handleSubscriptionDeleted(pool, subscription);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case 'invoice.payment_failed': {
|
|
91
|
+
const invoice = event.data.object;
|
|
92
|
+
await handlePaymentFailed(pool, invoice);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
default:
|
|
96
|
+
console.log(`Unhandled event type: ${event.type}`);
|
|
97
|
+
}
|
|
98
|
+
res.json({ received: true });
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error('Webhook error:', error);
|
|
102
|
+
res.status(500).json({
|
|
103
|
+
error: 'webhook_failed',
|
|
104
|
+
message: 'Failed to process webhook',
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return router;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Handle checkout.session.completed
|
|
112
|
+
* Upgrade user tier and set limits
|
|
113
|
+
*/
|
|
114
|
+
async function handleCheckoutCompleted(pool, session) {
|
|
115
|
+
try {
|
|
116
|
+
const customerId = session.customer;
|
|
117
|
+
const subscriptionId = session.subscription;
|
|
118
|
+
// Get subscription to determine tier
|
|
119
|
+
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
|
120
|
+
const subscription = await stripe.subscriptions.retrieve(subscriptionId);
|
|
121
|
+
// Determine tier from price ID (you'll need to configure these)
|
|
122
|
+
const priceId = subscription.items.data[0]?.price.id;
|
|
123
|
+
const tier = getTierFromPriceId(priceId);
|
|
124
|
+
const limits = TIER_LIMITS[tier];
|
|
125
|
+
// Update user
|
|
126
|
+
await pool.query(`UPDATE users
|
|
127
|
+
SET
|
|
128
|
+
stripe_customer_id = $1,
|
|
129
|
+
stripe_subscription_id = $2,
|
|
130
|
+
tier = $3,
|
|
131
|
+
weekly_limit = $4,
|
|
132
|
+
burst_limit = $5,
|
|
133
|
+
rate_limit = $6,
|
|
134
|
+
updated_at = now()
|
|
135
|
+
WHERE stripe_customer_id = $1 OR email = $7`, [
|
|
136
|
+
customerId,
|
|
137
|
+
subscriptionId,
|
|
138
|
+
tier,
|
|
139
|
+
limits.weekly_limit,
|
|
140
|
+
limits.burst_limit,
|
|
141
|
+
limits.rate_limit,
|
|
142
|
+
session.customer_email,
|
|
143
|
+
]);
|
|
144
|
+
console.log(`Checkout completed for customer ${customerId}: upgraded to ${tier}`);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
console.error('Failed to handle checkout completion:', error);
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Handle customer.subscription.updated
|
|
153
|
+
* Update user tier based on subscription changes
|
|
154
|
+
*/
|
|
155
|
+
async function handleSubscriptionUpdated(pool, subscription) {
|
|
156
|
+
try {
|
|
157
|
+
const customerId = subscription.customer;
|
|
158
|
+
const priceId = subscription.items.data[0]?.price.id;
|
|
159
|
+
const tier = getTierFromPriceId(priceId);
|
|
160
|
+
const limits = TIER_LIMITS[tier];
|
|
161
|
+
await pool.query(`UPDATE users
|
|
162
|
+
SET
|
|
163
|
+
tier = $1,
|
|
164
|
+
weekly_limit = $2,
|
|
165
|
+
burst_limit = $3,
|
|
166
|
+
rate_limit = $4,
|
|
167
|
+
stripe_subscription_id = $5,
|
|
168
|
+
updated_at = now()
|
|
169
|
+
WHERE stripe_customer_id = $6`, [tier, limits.weekly_limit, limits.burst_limit, limits.rate_limit, subscription.id, customerId]);
|
|
170
|
+
console.log(`Subscription updated for customer ${customerId}: tier=${tier}`);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
console.error('Failed to handle subscription update:', error);
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Handle customer.subscription.deleted
|
|
179
|
+
* Downgrade user to free tier
|
|
180
|
+
*/
|
|
181
|
+
async function handleSubscriptionDeleted(pool, subscription) {
|
|
182
|
+
try {
|
|
183
|
+
const customerId = subscription.customer;
|
|
184
|
+
const limits = TIER_LIMITS.free;
|
|
185
|
+
await pool.query(`UPDATE users
|
|
186
|
+
SET
|
|
187
|
+
tier = 'free',
|
|
188
|
+
weekly_limit = $1,
|
|
189
|
+
burst_limit = $2,
|
|
190
|
+
rate_limit = $3,
|
|
191
|
+
stripe_subscription_id = NULL,
|
|
192
|
+
updated_at = now()
|
|
193
|
+
WHERE stripe_customer_id = $4`, [limits.weekly_limit, limits.burst_limit, limits.rate_limit, customerId]);
|
|
194
|
+
console.log(`Subscription deleted for customer ${customerId}: downgraded to free`);
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
console.error('Failed to handle subscription deletion:', error);
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Handle invoice.payment_failed
|
|
203
|
+
* Log payment failure (could add email notification here)
|
|
204
|
+
*/
|
|
205
|
+
async function handlePaymentFailed(pool, invoice) {
|
|
206
|
+
try {
|
|
207
|
+
const customerId = invoice.customer;
|
|
208
|
+
// Get user email for logging
|
|
209
|
+
const result = await pool.query('SELECT email FROM users WHERE stripe_customer_id = $1', [customerId]);
|
|
210
|
+
if (result.rows.length > 0) {
|
|
211
|
+
console.warn(`Payment failed for customer ${customerId} (${result.rows[0].email})`);
|
|
212
|
+
// Note: Email notification not implemented. Log only for now.
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
console.error('Failed to handle payment failure:', error);
|
|
217
|
+
throw error;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Map Stripe price ID to tier
|
|
222
|
+
* Maps Stripe price IDs to tiers (configured via STRIPE_PRICE_PRO and STRIPE_PRICE_MAX env vars)
|
|
223
|
+
*/
|
|
224
|
+
function getTierFromPriceId(priceId) {
|
|
225
|
+
// Map price IDs to tiers
|
|
226
|
+
const priceMap = {
|
|
227
|
+
// Add your Stripe price IDs here
|
|
228
|
+
[process.env.STRIPE_PRICE_PRO || '']: 'pro',
|
|
229
|
+
[process.env.STRIPE_PRICE_MAX || '']: 'max',
|
|
230
|
+
};
|
|
231
|
+
return priceMap[priceId] || 'free';
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=stripe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../../src/server/routes/stripe.ts"],"names":[],"mappings":"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"}
|