webpeel 0.3.5 → 0.3.6
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/dist/cache.d.ts +31 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +132 -0
- package/dist/cache.js.map +1 -0
- package/package.json +6 -2
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local response cache for WebPeel CLI
|
|
3
|
+
*
|
|
4
|
+
* Caches fetch results in ~/.webpeel/cache/ with TTL support.
|
|
5
|
+
* Cache key is a hash of URL + relevant options.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parse a TTL string like "5m", "1h", "30s", "1d" into milliseconds
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseTTL(ttl: string): number;
|
|
11
|
+
/**
|
|
12
|
+
* Get a cached result if it exists and hasn't expired
|
|
13
|
+
*/
|
|
14
|
+
export declare function getCache(url: string, options?: Record<string, any>): any | null;
|
|
15
|
+
/**
|
|
16
|
+
* Store a result in the cache
|
|
17
|
+
*/
|
|
18
|
+
export declare function setCache(url: string, result: any, ttlMs: number, options?: Record<string, any>): void;
|
|
19
|
+
/**
|
|
20
|
+
* Clear expired cache entries (or all entries)
|
|
21
|
+
*/
|
|
22
|
+
export declare function clearCache(all?: boolean): number;
|
|
23
|
+
/**
|
|
24
|
+
* Get cache stats
|
|
25
|
+
*/
|
|
26
|
+
export declare function cacheStats(): {
|
|
27
|
+
entries: number;
|
|
28
|
+
sizeBytes: number;
|
|
29
|
+
dir: string;
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiBH;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAc5C;AAiBD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,IAAI,CAoB/E;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAerG;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,UAAQ,GAAG,MAAM,CAyB9C;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAchF"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local response cache for WebPeel CLI
|
|
3
|
+
*
|
|
4
|
+
* Caches fetch results in ~/.webpeel/cache/ with TTL support.
|
|
5
|
+
* Cache key is a hash of URL + relevant options.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, unlinkSync, statSync } from 'fs';
|
|
8
|
+
import { homedir } from 'os';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
import { createHash } from 'crypto';
|
|
11
|
+
const CACHE_DIR = join(homedir(), '.webpeel', 'cache');
|
|
12
|
+
/**
|
|
13
|
+
* Parse a TTL string like "5m", "1h", "30s", "1d" into milliseconds
|
|
14
|
+
*/
|
|
15
|
+
export function parseTTL(ttl) {
|
|
16
|
+
const match = ttl.match(/^(\d+)(s|m|h|d)$/);
|
|
17
|
+
if (!match) {
|
|
18
|
+
throw new Error(`Invalid TTL format: "${ttl}". Use: 30s, 5m, 1h, 1d`);
|
|
19
|
+
}
|
|
20
|
+
const value = parseInt(match[1]);
|
|
21
|
+
const unit = match[2];
|
|
22
|
+
switch (unit) {
|
|
23
|
+
case 's': return value * 1000;
|
|
24
|
+
case 'm': return value * 60 * 1000;
|
|
25
|
+
case 'h': return value * 60 * 60 * 1000;
|
|
26
|
+
case 'd': return value * 24 * 60 * 60 * 1000;
|
|
27
|
+
default: throw new Error(`Unknown TTL unit: ${unit}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generate a cache key from URL + options
|
|
32
|
+
*/
|
|
33
|
+
function cacheKey(url, options) {
|
|
34
|
+
const relevant = {
|
|
35
|
+
url,
|
|
36
|
+
render: options?.render || false,
|
|
37
|
+
stealth: options?.stealth || false,
|
|
38
|
+
selector: options?.selector || null,
|
|
39
|
+
format: options?.format || 'markdown',
|
|
40
|
+
};
|
|
41
|
+
const hash = createHash('sha256').update(JSON.stringify(relevant)).digest('hex').slice(0, 16);
|
|
42
|
+
return hash;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get a cached result if it exists and hasn't expired
|
|
46
|
+
*/
|
|
47
|
+
export function getCache(url, options) {
|
|
48
|
+
const key = cacheKey(url, options);
|
|
49
|
+
const filePath = join(CACHE_DIR, `${key}.json`);
|
|
50
|
+
if (!existsSync(filePath))
|
|
51
|
+
return null;
|
|
52
|
+
try {
|
|
53
|
+
const entry = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
54
|
+
const age = Date.now() - entry.cachedAt;
|
|
55
|
+
if (age > entry.ttlMs) {
|
|
56
|
+
// Expired — delete and return null
|
|
57
|
+
try {
|
|
58
|
+
unlinkSync(filePath);
|
|
59
|
+
}
|
|
60
|
+
catch { }
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
return entry.result;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Store a result in the cache
|
|
71
|
+
*/
|
|
72
|
+
export function setCache(url, result, ttlMs, options) {
|
|
73
|
+
if (!existsSync(CACHE_DIR)) {
|
|
74
|
+
mkdirSync(CACHE_DIR, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
const key = cacheKey(url, options);
|
|
77
|
+
const entry = {
|
|
78
|
+
url,
|
|
79
|
+
result,
|
|
80
|
+
cachedAt: Date.now(),
|
|
81
|
+
ttlMs,
|
|
82
|
+
options: options ? JSON.stringify(options) : undefined,
|
|
83
|
+
};
|
|
84
|
+
writeFileSync(join(CACHE_DIR, `${key}.json`), JSON.stringify(entry));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Clear expired cache entries (or all entries)
|
|
88
|
+
*/
|
|
89
|
+
export function clearCache(all = false) {
|
|
90
|
+
if (!existsSync(CACHE_DIR))
|
|
91
|
+
return 0;
|
|
92
|
+
const files = readdirSync(CACHE_DIR).filter(f => f.endsWith('.json'));
|
|
93
|
+
let cleared = 0;
|
|
94
|
+
for (const file of files) {
|
|
95
|
+
const filePath = join(CACHE_DIR, file);
|
|
96
|
+
try {
|
|
97
|
+
if (all) {
|
|
98
|
+
unlinkSync(filePath);
|
|
99
|
+
cleared++;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const entry = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
103
|
+
if (Date.now() - entry.cachedAt > entry.ttlMs) {
|
|
104
|
+
unlinkSync(filePath);
|
|
105
|
+
cleared++;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Skip corrupt files
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return cleared;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get cache stats
|
|
117
|
+
*/
|
|
118
|
+
export function cacheStats() {
|
|
119
|
+
if (!existsSync(CACHE_DIR))
|
|
120
|
+
return { entries: 0, sizeBytes: 0, dir: CACHE_DIR };
|
|
121
|
+
const files = readdirSync(CACHE_DIR).filter(f => f.endsWith('.json'));
|
|
122
|
+
let sizeBytes = 0;
|
|
123
|
+
for (const file of files) {
|
|
124
|
+
try {
|
|
125
|
+
const stat = statSync(join(CACHE_DIR, file));
|
|
126
|
+
sizeBytes += stat.size;
|
|
127
|
+
}
|
|
128
|
+
catch { }
|
|
129
|
+
}
|
|
130
|
+
return { entries: files.length, sizeBytes, dir: CACHE_DIR };
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webpeel",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "Fast web fetcher for AI agents - stealth mode, crawl mode, smart escalation from simple HTTP to headless browser",
|
|
5
5
|
"author": "Jake Liu",
|
|
6
6
|
"license": "MIT",
|
|
@@ -37,7 +37,11 @@
|
|
|
37
37
|
"dist/cli-auth.js",
|
|
38
38
|
"dist/cli-auth.js.map",
|
|
39
39
|
"dist/cli-auth.d.ts",
|
|
40
|
-
"dist/cli-auth.d.ts.map"
|
|
40
|
+
"dist/cli-auth.d.ts.map",
|
|
41
|
+
"dist/cache.js",
|
|
42
|
+
"dist/cache.js.map",
|
|
43
|
+
"dist/cache.d.ts",
|
|
44
|
+
"dist/cache.d.ts.map"
|
|
41
45
|
],
|
|
42
46
|
"scripts": {
|
|
43
47
|
"build": "tsc",
|