webpeel 0.3.0 → 0.3.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 +51 -35
- package/dist/cli-auth.d.ts +84 -0
- package/dist/cli-auth.d.ts.map +1 -0
- package/dist/cli-auth.js +428 -0
- package/dist/cli-auth.js.map +1 -0
- package/dist/cli.js +133 -4
- package/dist/cli.js.map +1 -1
- package/dist/core/crawler.js +1 -1
- package/dist/core/fetcher.d.ts.map +1 -1
- package/dist/core/fetcher.js +8 -2
- package/dist/core/fetcher.js.map +1 -1
- package/dist/mcp/server.js +12 -1
- package/dist/mcp/server.js.map +1 -1
- package/llms.txt +3 -1
- package/package.json +6 -2
package/dist/cli-auth.js
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Authentication & Usage Tracking
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Anonymous usage (25 free fetches)
|
|
6
|
+
* - API key authentication
|
|
7
|
+
* - Usage checking against API
|
|
8
|
+
* - Config file management (~/.webpeel/config.json)
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from 'fs';
|
|
11
|
+
import { homedir } from 'os';
|
|
12
|
+
import { join } from 'path';
|
|
13
|
+
import * as readline from 'readline';
|
|
14
|
+
// Config file location: ~/.webpeel/config.json
|
|
15
|
+
const CONFIG_DIR = join(homedir(), '.webpeel');
|
|
16
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
17
|
+
// API base URL (configurable via env var)
|
|
18
|
+
const API_BASE_URL = process.env.WEBPEEL_API_URL || 'https://api.webpeel.dev';
|
|
19
|
+
/**
|
|
20
|
+
* Load config from ~/.webpeel/config.json
|
|
21
|
+
*/
|
|
22
|
+
export function loadConfig() {
|
|
23
|
+
try {
|
|
24
|
+
if (!existsSync(CONFIG_FILE)) {
|
|
25
|
+
return {
|
|
26
|
+
anonymousUsage: 0,
|
|
27
|
+
lastReset: getLastMonday().toISOString(),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const content = readFileSync(CONFIG_FILE, 'utf-8');
|
|
31
|
+
const config = JSON.parse(content);
|
|
32
|
+
// Ensure lastReset exists
|
|
33
|
+
if (!config.lastReset) {
|
|
34
|
+
config.lastReset = getLastMonday().toISOString();
|
|
35
|
+
}
|
|
36
|
+
return config;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
// If config is corrupted, start fresh
|
|
40
|
+
return {
|
|
41
|
+
anonymousUsage: 0,
|
|
42
|
+
lastReset: getLastMonday().toISOString(),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Save config to ~/.webpeel/config.json
|
|
48
|
+
*/
|
|
49
|
+
export function saveConfig(config) {
|
|
50
|
+
try {
|
|
51
|
+
// Ensure directory exists
|
|
52
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
53
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.error(`Warning: Failed to save config: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Delete config file
|
|
63
|
+
*/
|
|
64
|
+
export function deleteConfig() {
|
|
65
|
+
try {
|
|
66
|
+
if (existsSync(CONFIG_FILE)) {
|
|
67
|
+
unlinkSync(CONFIG_FILE);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error(`Warning: Failed to delete config: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get the last Monday 00:00 UTC (start of current week)
|
|
76
|
+
*/
|
|
77
|
+
function getLastMonday() {
|
|
78
|
+
const now = new Date();
|
|
79
|
+
const day = now.getUTCDay();
|
|
80
|
+
const diff = day === 0 ? 6 : day - 1; // Days since last Monday
|
|
81
|
+
const lastMonday = new Date(now);
|
|
82
|
+
lastMonday.setUTCDate(now.getUTCDate() - diff);
|
|
83
|
+
lastMonday.setUTCHours(0, 0, 0, 0);
|
|
84
|
+
return lastMonday;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if anonymous usage counter needs to be reset (weekly reset)
|
|
88
|
+
*/
|
|
89
|
+
function shouldResetAnonymousUsage(config) {
|
|
90
|
+
const lastReset = new Date(config.lastReset);
|
|
91
|
+
const currentWeekStart = getLastMonday();
|
|
92
|
+
return lastReset < currentWeekStart;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Check usage quota before making a request
|
|
96
|
+
*/
|
|
97
|
+
export async function checkUsage() {
|
|
98
|
+
const config = loadConfig();
|
|
99
|
+
// Check if anonymous usage needs reset
|
|
100
|
+
if (shouldResetAnonymousUsage(config)) {
|
|
101
|
+
config.anonymousUsage = 0;
|
|
102
|
+
config.lastReset = getLastMonday().toISOString();
|
|
103
|
+
saveConfig(config);
|
|
104
|
+
}
|
|
105
|
+
// Anonymous user - allow first 25 fetches
|
|
106
|
+
if (!config.apiKey) {
|
|
107
|
+
const limit = 25;
|
|
108
|
+
const used = config.anonymousUsage;
|
|
109
|
+
const remaining = limit - used;
|
|
110
|
+
if (used >= limit) {
|
|
111
|
+
return {
|
|
112
|
+
allowed: false,
|
|
113
|
+
message: `You've used your ${limit} free fetches.\n\nSign up for free at https://app.webpeel.dev/signup to get 125 fetches/week.\nOr run: webpeel login\n`,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// Increment usage counter
|
|
117
|
+
config.anonymousUsage++;
|
|
118
|
+
saveConfig(config);
|
|
119
|
+
return {
|
|
120
|
+
allowed: true,
|
|
121
|
+
isAnonymous: true,
|
|
122
|
+
usageInfo: {
|
|
123
|
+
used: used + 1,
|
|
124
|
+
limit,
|
|
125
|
+
remaining: remaining - 1,
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// Authenticated user - check with API
|
|
130
|
+
try {
|
|
131
|
+
const response = await fetch(`${API_BASE_URL}/v1/cli/usage`, {
|
|
132
|
+
headers: {
|
|
133
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
134
|
+
},
|
|
135
|
+
signal: AbortSignal.timeout(5000),
|
|
136
|
+
});
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
if (response.status === 401) {
|
|
139
|
+
return {
|
|
140
|
+
allowed: false,
|
|
141
|
+
message: `Authentication failed. Your API key may be invalid.\n\nRun: webpeel logout\nThen: webpeel login\n`,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// If API returns other errors, allow gracefully
|
|
145
|
+
return { allowed: true };
|
|
146
|
+
}
|
|
147
|
+
const data = await response.json();
|
|
148
|
+
// Check burst limit
|
|
149
|
+
if (data.burst.used >= data.burst.limit) {
|
|
150
|
+
return {
|
|
151
|
+
allowed: false,
|
|
152
|
+
message: `Burst limit reached (${data.burst.used}/${data.burst.limit}). Resets in ${data.burst.resetsIn}.\nUpgrade: ${data.upgradeUrl}`,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// Quick canFetch check from API
|
|
156
|
+
if (!data.canFetch) {
|
|
157
|
+
return {
|
|
158
|
+
allowed: false,
|
|
159
|
+
message: `Weekly limit reached (${data.weekly.used}/${data.weekly.limit}).\nResets: ${data.weekly.resetsAt}\nUpgrade: ${data.upgradeUrl}`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// Cache plan tier for offline feature gating
|
|
163
|
+
const planName = (data.plan?.tier || 'free').toLowerCase();
|
|
164
|
+
config.planTier = planName;
|
|
165
|
+
config.planCachedAt = new Date().toISOString();
|
|
166
|
+
saveConfig(config);
|
|
167
|
+
return {
|
|
168
|
+
allowed: true,
|
|
169
|
+
isAnonymous: false,
|
|
170
|
+
usageInfo: {
|
|
171
|
+
used: data.weekly.used,
|
|
172
|
+
limit: data.weekly.limit,
|
|
173
|
+
remaining: data.weekly.remaining,
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
// If API is unreachable, allow the request (graceful degradation)
|
|
179
|
+
return { allowed: true };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const FEATURE_LABELS = {
|
|
183
|
+
stealth: 'Stealth mode (anti-bot bypass)',
|
|
184
|
+
crawl: 'Crawl mode (multi-page)',
|
|
185
|
+
batch: 'Batch mode (bulk URLs)',
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* Check if user has access to a premium feature.
|
|
189
|
+
* Returns { allowed: true } for paid users, or a helpful upgrade message.
|
|
190
|
+
*
|
|
191
|
+
* Priority:
|
|
192
|
+
* 1. No API key → blocked (must sign up)
|
|
193
|
+
* 2. Has API key + cached plan → check plan tier
|
|
194
|
+
* 3. Has API key + no cache → check API, then cache
|
|
195
|
+
* 4. API unreachable + cached plan within 7 days → use cache
|
|
196
|
+
* 5. API unreachable + stale cache → allow gracefully (trust the user)
|
|
197
|
+
*/
|
|
198
|
+
export async function checkFeatureAccess(feature) {
|
|
199
|
+
const config = loadConfig();
|
|
200
|
+
// No API key → must sign up and subscribe
|
|
201
|
+
if (!config.apiKey) {
|
|
202
|
+
return {
|
|
203
|
+
allowed: false,
|
|
204
|
+
message: `⚡ ${FEATURE_LABELS[feature]} requires a Pro plan ($9/mo).\n\n` +
|
|
205
|
+
` Basic fetch is free — stealth, crawl, and batch are Pro features.\n\n` +
|
|
206
|
+
` Sign up: https://app.webpeel.dev/signup\n` +
|
|
207
|
+
` Pricing: https://webpeel.dev/#pricing\n` +
|
|
208
|
+
` Login: webpeel login\n`,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
// Try to get fresh plan info from API
|
|
212
|
+
try {
|
|
213
|
+
const response = await fetch(`${API_BASE_URL}/v1/cli/usage`, {
|
|
214
|
+
headers: { 'Authorization': `Bearer ${config.apiKey}` },
|
|
215
|
+
signal: AbortSignal.timeout(5000),
|
|
216
|
+
});
|
|
217
|
+
if (response.ok) {
|
|
218
|
+
const data = await response.json();
|
|
219
|
+
const planName = (data.plan?.tier || 'free').toLowerCase();
|
|
220
|
+
// Cache for offline use
|
|
221
|
+
config.planTier = planName;
|
|
222
|
+
config.planCachedAt = new Date().toISOString();
|
|
223
|
+
saveConfig(config);
|
|
224
|
+
if (planName === 'free') {
|
|
225
|
+
return {
|
|
226
|
+
allowed: false,
|
|
227
|
+
message: `⚡ ${FEATURE_LABELS[feature]} requires a Pro plan ($9/mo).\n\n` +
|
|
228
|
+
` You're on the Free plan. Upgrade to unlock stealth, crawl, and batch.\n\n` +
|
|
229
|
+
` Upgrade: https://app.webpeel.dev/billing\n` +
|
|
230
|
+
` Pricing: https://webpeel.dev/#pricing\n`,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
// Pro or Max — allowed
|
|
234
|
+
return { allowed: true };
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// API unreachable — fall through to cache check
|
|
239
|
+
}
|
|
240
|
+
// API unreachable — use cached plan if recent (within 7 days)
|
|
241
|
+
if (config.planTier && config.planCachedAt) {
|
|
242
|
+
const cacheAge = Date.now() - new Date(config.planCachedAt).getTime();
|
|
243
|
+
const SEVEN_DAYS = 7 * 24 * 60 * 60 * 1000;
|
|
244
|
+
if (cacheAge < SEVEN_DAYS) {
|
|
245
|
+
if (config.planTier === 'free') {
|
|
246
|
+
return {
|
|
247
|
+
allowed: false,
|
|
248
|
+
message: `⚡ ${FEATURE_LABELS[feature]} requires a Pro plan ($9/mo).\n\n` +
|
|
249
|
+
` Upgrade: https://app.webpeel.dev/billing\n`,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
return { allowed: true };
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// Stale cache or no cache, API unreachable — allow gracefully (trust paying users)
|
|
256
|
+
return { allowed: true };
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Show usage footer after successful fetch (for free/anonymous users only)
|
|
260
|
+
*/
|
|
261
|
+
export function showUsageFooter(usageInfo, isAnonymous, stealth = false) {
|
|
262
|
+
if (!usageInfo)
|
|
263
|
+
return;
|
|
264
|
+
// Only show footer for anonymous or free users
|
|
265
|
+
if (isAnonymous) {
|
|
266
|
+
const costText = stealth ? ' (costs 5 credits)' : '';
|
|
267
|
+
console.error(`⚡ ${usageInfo.remaining}/${usageInfo.limit} free fetches remaining${costText}. Run \`webpeel login\` to get 125/week free.`);
|
|
268
|
+
}
|
|
269
|
+
else if (usageInfo.limit <= 125) {
|
|
270
|
+
// Free tier authenticated users
|
|
271
|
+
const costText = stealth ? ' (costs 5 credits)' : '';
|
|
272
|
+
console.error(`⚡ ${usageInfo.remaining}/${usageInfo.limit} fetches remaining this week${costText}.`);
|
|
273
|
+
}
|
|
274
|
+
// Don't show footer for paid users
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Prompt user for API key via stdin
|
|
278
|
+
*/
|
|
279
|
+
export async function promptForApiKey() {
|
|
280
|
+
const rl = readline.createInterface({
|
|
281
|
+
input: process.stdin,
|
|
282
|
+
output: process.stdout,
|
|
283
|
+
});
|
|
284
|
+
return new Promise((resolve) => {
|
|
285
|
+
rl.question('Enter your API key (get one at https://app.webpeel.dev/keys): ', (answer) => {
|
|
286
|
+
rl.close();
|
|
287
|
+
resolve(answer.trim());
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Login command - save API key to config
|
|
293
|
+
*/
|
|
294
|
+
export async function handleLogin() {
|
|
295
|
+
const config = loadConfig();
|
|
296
|
+
if (config.apiKey) {
|
|
297
|
+
console.log('You are already logged in.');
|
|
298
|
+
console.log('Run `webpeel logout` first if you want to use a different API key.');
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
console.log('\n🔑 WebPeel CLI Authentication');
|
|
302
|
+
console.log('==============================\n');
|
|
303
|
+
console.log('Get your API key at: https://app.webpeel.dev/keys\n');
|
|
304
|
+
const apiKey = await promptForApiKey();
|
|
305
|
+
if (!apiKey) {
|
|
306
|
+
console.error('Error: API key cannot be empty');
|
|
307
|
+
process.exit(1);
|
|
308
|
+
}
|
|
309
|
+
// Validate API key format (should start with wp_)
|
|
310
|
+
if (!apiKey.startsWith('wp_')) {
|
|
311
|
+
console.error('Warning: API key should start with "wp_". Make sure you entered it correctly.');
|
|
312
|
+
}
|
|
313
|
+
// Validate API key against server before saving
|
|
314
|
+
console.log('\nVerifying API key...');
|
|
315
|
+
try {
|
|
316
|
+
const response = await fetch(`${API_BASE_URL}/v1/cli/usage`, {
|
|
317
|
+
headers: { 'Authorization': `Bearer ${apiKey}` },
|
|
318
|
+
signal: AbortSignal.timeout(5000),
|
|
319
|
+
});
|
|
320
|
+
if (response.ok) {
|
|
321
|
+
const data = await response.json();
|
|
322
|
+
const tierLabel = data.plan.tier.charAt(0).toUpperCase() + data.plan.tier.slice(1);
|
|
323
|
+
// Save to config with plan info
|
|
324
|
+
config.apiKey = apiKey;
|
|
325
|
+
config.planTier = data.plan.tier;
|
|
326
|
+
config.planCachedAt = new Date().toISOString();
|
|
327
|
+
saveConfig(config);
|
|
328
|
+
console.log(`\n✅ Successfully logged in!`);
|
|
329
|
+
console.log(`Plan: ${tierLabel} (${data.weekly.limit} fetches/week)`);
|
|
330
|
+
console.log(`Usage this week: ${data.weekly.used}/${data.weekly.limit}`);
|
|
331
|
+
}
|
|
332
|
+
else if (response.status === 401) {
|
|
333
|
+
console.error('\n❌ Invalid API key. Please check and try again.');
|
|
334
|
+
console.error('Get your API key at https://app.webpeel.dev/keys');
|
|
335
|
+
process.exit(1);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
// Server returned non-401 error — save key anyway (might be temporary)
|
|
339
|
+
config.apiKey = apiKey;
|
|
340
|
+
saveConfig(config);
|
|
341
|
+
console.log('\n✓ API key saved (could not verify — server may be temporarily unavailable).');
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
// Network error — save key anyway (graceful)
|
|
346
|
+
config.apiKey = apiKey;
|
|
347
|
+
saveConfig(config);
|
|
348
|
+
console.log('\n✓ API key saved (could not reach server to verify).');
|
|
349
|
+
}
|
|
350
|
+
console.log('Run `webpeel usage` to check your quota.');
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Logout command - remove API key from config
|
|
354
|
+
*/
|
|
355
|
+
export function handleLogout() {
|
|
356
|
+
const config = loadConfig();
|
|
357
|
+
if (!config.apiKey) {
|
|
358
|
+
console.log('You are not logged in.');
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
deleteConfig();
|
|
362
|
+
console.log('✓ Logged out successfully');
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Usage command - show current quota
|
|
366
|
+
*/
|
|
367
|
+
export async function handleUsage() {
|
|
368
|
+
const config = loadConfig();
|
|
369
|
+
// Check for weekly reset
|
|
370
|
+
if (shouldResetAnonymousUsage(config)) {
|
|
371
|
+
config.anonymousUsage = 0;
|
|
372
|
+
config.lastReset = getLastMonday().toISOString();
|
|
373
|
+
saveConfig(config);
|
|
374
|
+
}
|
|
375
|
+
// Anonymous user
|
|
376
|
+
if (!config.apiKey) {
|
|
377
|
+
const limit = 25;
|
|
378
|
+
const used = config.anonymousUsage;
|
|
379
|
+
const remaining = limit - used;
|
|
380
|
+
const nextMonday = new Date(getLastMonday());
|
|
381
|
+
nextMonday.setUTCDate(nextMonday.getUTCDate() + 7);
|
|
382
|
+
console.log('\nWebPeel Usage (Anonymous)');
|
|
383
|
+
console.log('=========================\n');
|
|
384
|
+
console.log(`Plan: Anonymous (25 free fetches/week)`);
|
|
385
|
+
console.log(`Used this week: ${used}/${limit}`);
|
|
386
|
+
console.log(`Remaining: ${remaining}`);
|
|
387
|
+
console.log(`Resets: ${nextMonday.toUTCString()}`);
|
|
388
|
+
console.log('\n💡 Run `webpeel login` to get 125 fetches/week for free!');
|
|
389
|
+
console.log(' Or sign up at https://app.webpeel.dev/signup\n');
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
// Authenticated user - fetch from API
|
|
393
|
+
try {
|
|
394
|
+
const response = await fetch(`${API_BASE_URL}/v1/cli/usage`, {
|
|
395
|
+
headers: {
|
|
396
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
397
|
+
},
|
|
398
|
+
signal: AbortSignal.timeout(5000),
|
|
399
|
+
});
|
|
400
|
+
if (!response.ok) {
|
|
401
|
+
if (response.status === 401) {
|
|
402
|
+
console.error('Error: Authentication failed. Your API key may be invalid.');
|
|
403
|
+
console.error('Run `webpeel logout` and `webpeel login` to re-authenticate.');
|
|
404
|
+
process.exit(1);
|
|
405
|
+
}
|
|
406
|
+
throw new Error(`API returned status ${response.status}`);
|
|
407
|
+
}
|
|
408
|
+
const data = await response.json();
|
|
409
|
+
const tierLabel = data.plan.tier.charAt(0).toUpperCase() + data.plan.tier.slice(1);
|
|
410
|
+
console.log('\nWebPeel Usage');
|
|
411
|
+
console.log('=============\n');
|
|
412
|
+
console.log(`Plan: ${tierLabel} (${data.weekly.limit}/week)`);
|
|
413
|
+
console.log(`Used this week: ${data.weekly.used}/${data.weekly.limit} (${data.weekly.percentUsed}%)`);
|
|
414
|
+
console.log(`Remaining: ${data.weekly.remaining}`);
|
|
415
|
+
console.log(`Burst: ${data.burst.used}/${data.burst.limit} this hour (resets in ${data.burst.resetsIn})`);
|
|
416
|
+
console.log(`Weekly reset: ${new Date(data.weekly.resetsAt).toUTCString()}`);
|
|
417
|
+
if (data.weekly.remaining <= 10) {
|
|
418
|
+
console.log(`\n⚠️ Running low on credits. Upgrade at ${data.upgradeUrl}`);
|
|
419
|
+
}
|
|
420
|
+
console.log();
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
console.error(`Error fetching usage data: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
424
|
+
console.error('The API may be temporarily unavailable. Try again later.');
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
//# sourceMappingURL=cli-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-auth.js","sourceRoot":"","sources":["../src/cli-auth.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -16,11 +16,12 @@ import { Command } from 'commander';
|
|
|
16
16
|
import ora from 'ora';
|
|
17
17
|
import { writeFileSync } from 'fs';
|
|
18
18
|
import { peel, peelBatch, cleanup } from './index.js';
|
|
19
|
+
import { checkUsage, checkFeatureAccess, showUsageFooter, handleLogin, handleLogout, handleUsage } from './cli-auth.js';
|
|
19
20
|
const program = new Command();
|
|
20
21
|
program
|
|
21
22
|
.name('webpeel')
|
|
22
23
|
.description('Fast web fetcher for AI agents')
|
|
23
|
-
.version('0.3.
|
|
24
|
+
.version('0.3.1')
|
|
24
25
|
.enablePositionalOptions();
|
|
25
26
|
program
|
|
26
27
|
.argument('[url]', 'URL to fetch')
|
|
@@ -67,6 +68,21 @@ program
|
|
|
67
68
|
console.error(`Error: Invalid URL format: ${url}`);
|
|
68
69
|
process.exit(1);
|
|
69
70
|
}
|
|
71
|
+
// Check premium feature access (stealth requires Pro plan)
|
|
72
|
+
const useStealth = options.stealth || false;
|
|
73
|
+
if (useStealth) {
|
|
74
|
+
const featureCheck = await checkFeatureAccess('stealth');
|
|
75
|
+
if (!featureCheck.allowed) {
|
|
76
|
+
console.error(featureCheck.message);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Check usage quota
|
|
81
|
+
const usageCheck = await checkUsage();
|
|
82
|
+
if (!usageCheck.allowed) {
|
|
83
|
+
console.error(usageCheck.message);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
70
86
|
const spinner = options.silent ? null : ora('Fetching...').start();
|
|
71
87
|
try {
|
|
72
88
|
// Validate options
|
|
@@ -91,8 +107,10 @@ program
|
|
|
91
107
|
}
|
|
92
108
|
}
|
|
93
109
|
// Build peel options
|
|
110
|
+
// --stealth auto-enables --render (stealth requires browser)
|
|
111
|
+
const useRender = options.render || options.stealth || false;
|
|
94
112
|
const peelOptions = {
|
|
95
|
-
render:
|
|
113
|
+
render: useRender,
|
|
96
114
|
stealth: options.stealth || false,
|
|
97
115
|
wait: options.wait || 0,
|
|
98
116
|
timeout: options.timeout,
|
|
@@ -119,6 +137,10 @@ program
|
|
|
119
137
|
if (spinner) {
|
|
120
138
|
spinner.succeed(`Fetched in ${result.elapsed}ms using ${result.method} method`);
|
|
121
139
|
}
|
|
140
|
+
// Show usage footer for free/anonymous users
|
|
141
|
+
if (usageCheck.usageInfo && !options.silent) {
|
|
142
|
+
showUsageFooter(usageCheck.usageInfo, usageCheck.isAnonymous || false, useStealth);
|
|
143
|
+
}
|
|
122
144
|
// Handle screenshot saving
|
|
123
145
|
if (options.screenshot && result.screenshot) {
|
|
124
146
|
const screenshotPath = typeof options.screenshot === 'string'
|
|
@@ -185,6 +207,12 @@ program
|
|
|
185
207
|
const isJson = options.json;
|
|
186
208
|
const isSilent = options.silent;
|
|
187
209
|
const count = parseInt(options.count) || 5;
|
|
210
|
+
// Check usage quota
|
|
211
|
+
const usageCheck = await checkUsage();
|
|
212
|
+
if (!usageCheck.allowed) {
|
|
213
|
+
console.error(usageCheck.message);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
188
216
|
const spinner = isSilent ? null : ora('Searching...').start();
|
|
189
217
|
try {
|
|
190
218
|
// Import the search function dynamically
|
|
@@ -243,6 +271,10 @@ program
|
|
|
243
271
|
if (spinner) {
|
|
244
272
|
spinner.succeed(`Found ${results.length} results`);
|
|
245
273
|
}
|
|
274
|
+
// Show usage footer for free/anonymous users
|
|
275
|
+
if (usageCheck.usageInfo && !isSilent) {
|
|
276
|
+
showUsageFooter(usageCheck.usageInfo, usageCheck.isAnonymous || false, false);
|
|
277
|
+
}
|
|
246
278
|
if (isJson) {
|
|
247
279
|
const jsonStr = JSON.stringify(results, null, 2);
|
|
248
280
|
await new Promise((resolve, reject) => {
|
|
@@ -279,7 +311,7 @@ program
|
|
|
279
311
|
// Batch command
|
|
280
312
|
program
|
|
281
313
|
.command('batch <file>')
|
|
282
|
-
.description('Fetch multiple URLs')
|
|
314
|
+
.description('Fetch multiple URLs (Pro feature)')
|
|
283
315
|
.option('-c, --concurrency <n>', 'Max concurrent fetches (default: 3)', '3')
|
|
284
316
|
.option('-o, --output <dir>', 'Output directory (one file per URL)')
|
|
285
317
|
.option('--json', 'Output as JSON array')
|
|
@@ -291,6 +323,18 @@ program
|
|
|
291
323
|
const isSilent = options.silent;
|
|
292
324
|
const shouldRender = options.render;
|
|
293
325
|
const selector = options.selector;
|
|
326
|
+
// Check premium feature access (batch requires Pro plan)
|
|
327
|
+
const featureCheck = await checkFeatureAccess('batch');
|
|
328
|
+
if (!featureCheck.allowed) {
|
|
329
|
+
console.error(featureCheck.message);
|
|
330
|
+
process.exit(1);
|
|
331
|
+
}
|
|
332
|
+
// Check usage quota
|
|
333
|
+
const usageCheck = await checkUsage();
|
|
334
|
+
if (!usageCheck.allowed) {
|
|
335
|
+
console.error(usageCheck.message);
|
|
336
|
+
process.exit(1);
|
|
337
|
+
}
|
|
294
338
|
const spinner = isSilent ? null : ora('Loading URLs...').start();
|
|
295
339
|
try {
|
|
296
340
|
const { readFileSync } = await import('fs');
|
|
@@ -321,6 +365,10 @@ program
|
|
|
321
365
|
const successCount = results.filter(r => 'content' in r).length;
|
|
322
366
|
spinner.succeed(`Completed: ${successCount}/${urls.length} successful`);
|
|
323
367
|
}
|
|
368
|
+
// Show usage footer for free/anonymous users
|
|
369
|
+
if (usageCheck.usageInfo && !isSilent) {
|
|
370
|
+
showUsageFooter(usageCheck.usageInfo, usageCheck.isAnonymous || false, false);
|
|
371
|
+
}
|
|
324
372
|
// Output results
|
|
325
373
|
if (isJson) {
|
|
326
374
|
const jsonStr = JSON.stringify(results, null, 2);
|
|
@@ -384,7 +432,7 @@ program
|
|
|
384
432
|
});
|
|
385
433
|
program
|
|
386
434
|
.command('crawl <url>')
|
|
387
|
-
.description('Crawl a website starting from a URL')
|
|
435
|
+
.description('Crawl a website starting from a URL (Pro feature)')
|
|
388
436
|
.option('--max-pages <number>', 'Maximum number of pages to crawl (default: 10, max: 100)', parseInt, 10)
|
|
389
437
|
.option('--max-depth <number>', 'Maximum depth to crawl (default: 2, max: 5)', parseInt, 2)
|
|
390
438
|
.option('--allowed-domains <domains...>', 'Only crawl these domains (default: same as starting URL)')
|
|
@@ -396,6 +444,18 @@ program
|
|
|
396
444
|
.option('-s, --silent', 'Silent mode (no spinner)')
|
|
397
445
|
.option('--json', 'Output as JSON')
|
|
398
446
|
.action(async (url, options) => {
|
|
447
|
+
// Check premium feature access (crawl requires Pro plan)
|
|
448
|
+
const featureCheck = await checkFeatureAccess('crawl');
|
|
449
|
+
if (!featureCheck.allowed) {
|
|
450
|
+
console.error(featureCheck.message);
|
|
451
|
+
process.exit(1);
|
|
452
|
+
}
|
|
453
|
+
// Check usage quota
|
|
454
|
+
const usageCheck = await checkUsage();
|
|
455
|
+
if (!usageCheck.allowed) {
|
|
456
|
+
console.error(usageCheck.message);
|
|
457
|
+
process.exit(1);
|
|
458
|
+
}
|
|
399
459
|
const { crawl } = await import('./core/crawler.js');
|
|
400
460
|
const spinner = options.silent ? null : ora('Crawling...').start();
|
|
401
461
|
try {
|
|
@@ -412,6 +472,10 @@ program
|
|
|
412
472
|
if (spinner) {
|
|
413
473
|
spinner.succeed(`Crawled ${results.length} pages`);
|
|
414
474
|
}
|
|
475
|
+
// Show usage footer for free/anonymous users
|
|
476
|
+
if (usageCheck.usageInfo && !options.silent) {
|
|
477
|
+
showUsageFooter(usageCheck.usageInfo, usageCheck.isAnonymous || false, options.stealth || false);
|
|
478
|
+
}
|
|
415
479
|
if (options.json) {
|
|
416
480
|
console.log(JSON.stringify(results, null, 2));
|
|
417
481
|
}
|
|
@@ -448,6 +512,71 @@ program
|
|
|
448
512
|
process.exit(1);
|
|
449
513
|
}
|
|
450
514
|
});
|
|
515
|
+
program
|
|
516
|
+
.command('login')
|
|
517
|
+
.description('Authenticate the CLI with your API key')
|
|
518
|
+
.action(async () => {
|
|
519
|
+
try {
|
|
520
|
+
await handleLogin();
|
|
521
|
+
process.exit(0);
|
|
522
|
+
}
|
|
523
|
+
catch (error) {
|
|
524
|
+
console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
525
|
+
process.exit(1);
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
program
|
|
529
|
+
.command('whoami')
|
|
530
|
+
.description('Show your current authentication status')
|
|
531
|
+
.action(async () => {
|
|
532
|
+
try {
|
|
533
|
+
const { loadConfig } = await import('./cli-auth.js');
|
|
534
|
+
const config = loadConfig();
|
|
535
|
+
if (!config.apiKey) {
|
|
536
|
+
console.log('Not logged in. Run `webpeel login` to authenticate.');
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
const masked = config.apiKey.slice(0, 7) + '...' + config.apiKey.slice(-4);
|
|
540
|
+
console.log(`Logged in with API key: ${masked}`);
|
|
541
|
+
if (config.planTier) {
|
|
542
|
+
const tierLabel = config.planTier.charAt(0).toUpperCase() + config.planTier.slice(1);
|
|
543
|
+
console.log(`Plan: ${tierLabel}`);
|
|
544
|
+
}
|
|
545
|
+
console.log(`Config: ~/.webpeel/config.json`);
|
|
546
|
+
}
|
|
547
|
+
process.exit(0);
|
|
548
|
+
}
|
|
549
|
+
catch (error) {
|
|
550
|
+
console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
551
|
+
process.exit(1);
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
program
|
|
555
|
+
.command('logout')
|
|
556
|
+
.description('Clear your saved credentials')
|
|
557
|
+
.action(() => {
|
|
558
|
+
try {
|
|
559
|
+
handleLogout();
|
|
560
|
+
process.exit(0);
|
|
561
|
+
}
|
|
562
|
+
catch (error) {
|
|
563
|
+
console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
564
|
+
process.exit(1);
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
program
|
|
568
|
+
.command('usage')
|
|
569
|
+
.description('Show your current usage and quota')
|
|
570
|
+
.action(async () => {
|
|
571
|
+
try {
|
|
572
|
+
await handleUsage();
|
|
573
|
+
process.exit(0);
|
|
574
|
+
}
|
|
575
|
+
catch (error) {
|
|
576
|
+
console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
577
|
+
process.exit(1);
|
|
578
|
+
}
|
|
579
|
+
});
|
|
451
580
|
program
|
|
452
581
|
.command('serve')
|
|
453
582
|
.description('Start API server')
|