@stati/core 1.0.0 → 1.2.0
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 +217 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +24 -2
- package/dist/core/build.d.ts +9 -2
- package/dist/core/build.d.ts.map +1 -1
- package/dist/core/build.js +200 -46
- package/dist/core/dev.d.ts +21 -0
- package/dist/core/dev.d.ts.map +1 -0
- package/dist/core/dev.js +371 -0
- package/dist/core/invalidate.d.ts +67 -1
- package/dist/core/invalidate.d.ts.map +1 -1
- package/dist/core/invalidate.js +321 -4
- package/dist/core/isg/build-lock.d.ts +116 -0
- package/dist/core/isg/build-lock.d.ts.map +1 -0
- package/dist/core/isg/build-lock.js +243 -0
- package/dist/core/isg/builder.d.ts +51 -0
- package/dist/core/isg/builder.d.ts.map +1 -0
- package/dist/core/isg/builder.js +321 -0
- package/dist/core/isg/deps.d.ts +63 -0
- package/dist/core/isg/deps.d.ts.map +1 -0
- package/dist/core/isg/deps.js +332 -0
- package/dist/core/isg/hash.d.ts +48 -0
- package/dist/core/isg/hash.d.ts.map +1 -0
- package/dist/core/isg/hash.js +82 -0
- package/dist/core/isg/manifest.d.ts +47 -0
- package/dist/core/isg/manifest.d.ts.map +1 -0
- package/dist/core/isg/manifest.js +233 -0
- package/dist/core/isg/ttl.d.ts +101 -0
- package/dist/core/isg/ttl.d.ts.map +1 -0
- package/dist/core/isg/ttl.js +222 -0
- package/dist/core/isg/validation.d.ts +71 -0
- package/dist/core/isg/validation.d.ts.map +1 -0
- package/dist/core/isg/validation.js +226 -0
- package/dist/core/templates.d.ts.map +1 -1
- package/dist/core/templates.js +23 -5
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/types.d.ts +172 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/core/dev.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,MAAM,EAAE,MAAM,aAAa,CAAC;AAMvD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,CA0ZxF"}
|
package/dist/core/dev.js
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { createServer } from 'http';
|
|
2
|
+
import { join, extname } from 'path';
|
|
3
|
+
import { posix } from 'path';
|
|
4
|
+
import { readFile, stat } from 'fs/promises';
|
|
5
|
+
import { WebSocketServer } from 'ws';
|
|
6
|
+
import chokidar from 'chokidar';
|
|
7
|
+
import { build } from './build.js';
|
|
8
|
+
import { loadConfig } from '../config/loader.js';
|
|
9
|
+
import { loadCacheManifest, saveCacheManifest } from './isg/manifest.js';
|
|
10
|
+
/**
|
|
11
|
+
* Creates and configures a development server with live reload functionality.
|
|
12
|
+
*
|
|
13
|
+
* @param options - Development server configuration options
|
|
14
|
+
* @returns Promise resolving to a DevServer instance
|
|
15
|
+
*/
|
|
16
|
+
export async function createDevServer(options = {}) {
|
|
17
|
+
const { port = 3000, host = 'localhost', open = false, configPath, logger = {
|
|
18
|
+
info: (msg) => console.log(msg),
|
|
19
|
+
success: (msg) => console.log(msg),
|
|
20
|
+
error: (msg) => console.error(msg),
|
|
21
|
+
warning: (msg) => console.warn(msg),
|
|
22
|
+
building: (msg) => console.log(msg),
|
|
23
|
+
processing: (msg) => console.log(msg),
|
|
24
|
+
stats: (msg) => console.log(msg),
|
|
25
|
+
}, } = options;
|
|
26
|
+
const url = `http://${host}:${port}`;
|
|
27
|
+
let httpServer = null;
|
|
28
|
+
let wsServer = null;
|
|
29
|
+
let watcher = null;
|
|
30
|
+
let config;
|
|
31
|
+
let isBuilding = false;
|
|
32
|
+
// Load configuration
|
|
33
|
+
try {
|
|
34
|
+
if (configPath) {
|
|
35
|
+
// For custom config path, we need to change to that directory temporarily
|
|
36
|
+
// This is a limitation of the current loadConfig implementation
|
|
37
|
+
logger.info?.(`Loading config from: ${configPath}`);
|
|
38
|
+
}
|
|
39
|
+
config = await loadConfig(process.cwd());
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
logger.error?.(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`);
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
const outDir = join(process.cwd(), config.outDir || 'dist');
|
|
46
|
+
const srcDir = join(process.cwd(), config.srcDir || 'site');
|
|
47
|
+
const staticDir = join(process.cwd(), config.staticDir || 'public');
|
|
48
|
+
/**
|
|
49
|
+
* Performs an initial build to ensure dist/ exists
|
|
50
|
+
*/
|
|
51
|
+
async function initialBuild() {
|
|
52
|
+
try {
|
|
53
|
+
await build({
|
|
54
|
+
logger,
|
|
55
|
+
force: false,
|
|
56
|
+
clean: false,
|
|
57
|
+
...(configPath && { configPath }),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
logger.error?.(`Initial build failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Performs incremental rebuild when files change, using ISG logic for smart rebuilds
|
|
67
|
+
*/
|
|
68
|
+
async function incrementalRebuild(changedPath) {
|
|
69
|
+
if (isBuilding) {
|
|
70
|
+
logger.info?.('⏳ Build in progress, skipping...');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
isBuilding = true;
|
|
74
|
+
try {
|
|
75
|
+
// Check if the changed file is a template/partial
|
|
76
|
+
if (changedPath.endsWith('.eta') || changedPath.includes('_partials')) {
|
|
77
|
+
logger.info?.(`🎨 Template changed: ${changedPath}`);
|
|
78
|
+
await handleTemplateChange(changedPath);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Content or static file changed - use normal rebuild
|
|
82
|
+
logger.info?.(`📄 Content changed: ${changedPath}`);
|
|
83
|
+
await build({
|
|
84
|
+
logger,
|
|
85
|
+
force: false,
|
|
86
|
+
clean: false,
|
|
87
|
+
...(configPath && { configPath }),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
// Notify all connected clients to reload
|
|
91
|
+
if (wsServer) {
|
|
92
|
+
wsServer.clients.forEach((client) => {
|
|
93
|
+
const ws = client;
|
|
94
|
+
if (ws.readyState === 1) {
|
|
95
|
+
// WebSocket.OPEN
|
|
96
|
+
ws.send(JSON.stringify({ type: 'reload' }));
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
logger.success?.('Rebuild complete');
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
logger.error?.(`Rebuild failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
isBuilding = false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Handles template/partial file changes by invalidating affected pages
|
|
111
|
+
*/
|
|
112
|
+
async function handleTemplateChange(templatePath) {
|
|
113
|
+
const cacheDir = join(process.cwd(), '.stati');
|
|
114
|
+
try {
|
|
115
|
+
// Load existing cache manifest
|
|
116
|
+
let cacheManifest = await loadCacheManifest(cacheDir);
|
|
117
|
+
if (!cacheManifest) {
|
|
118
|
+
// No cache exists, perform full rebuild
|
|
119
|
+
logger.info?.('No cache found, performing full rebuild...');
|
|
120
|
+
await build({
|
|
121
|
+
logger,
|
|
122
|
+
force: false,
|
|
123
|
+
clean: false,
|
|
124
|
+
...(configPath && { configPath }),
|
|
125
|
+
});
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
// Find pages that depend on this template
|
|
129
|
+
const affectedPages = [];
|
|
130
|
+
for (const [pagePath, entry] of Object.entries(cacheManifest.entries)) {
|
|
131
|
+
if (entry.deps.some((dep) => dep.includes(posix.normalize(templatePath.replace(/\\/g, '/'))))) {
|
|
132
|
+
affectedPages.push(pagePath);
|
|
133
|
+
// Remove from cache to force rebuild
|
|
134
|
+
delete cacheManifest.entries[pagePath];
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (affectedPages.length > 0) {
|
|
138
|
+
logger.info?.(`🎯 Invalidating ${affectedPages.length} affected pages:`);
|
|
139
|
+
affectedPages.forEach((page) => logger.info?.(` 📄 ${page}`));
|
|
140
|
+
// Save updated cache manifest
|
|
141
|
+
await saveCacheManifest(cacheDir, cacheManifest);
|
|
142
|
+
// Perform incremental rebuild (only affected pages will be rebuilt)
|
|
143
|
+
await build({
|
|
144
|
+
logger,
|
|
145
|
+
force: false,
|
|
146
|
+
clean: false,
|
|
147
|
+
...(configPath && { configPath }),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
logger.info?.('ℹ️ No pages affected by template change');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
logger.warning?.(`Template dependency analysis failed, performing full rebuild: ${error instanceof Error ? error.message : String(error)}`);
|
|
156
|
+
// Fallback to full rebuild
|
|
157
|
+
await build({
|
|
158
|
+
logger,
|
|
159
|
+
force: false,
|
|
160
|
+
clean: false,
|
|
161
|
+
...(configPath && { configPath }),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Gets MIME type for a file based on its extension
|
|
167
|
+
*/
|
|
168
|
+
function getMimeType(filePath) {
|
|
169
|
+
const ext = extname(filePath).toLowerCase();
|
|
170
|
+
const mimeTypes = {
|
|
171
|
+
'.html': 'text/html',
|
|
172
|
+
'.js': 'application/javascript',
|
|
173
|
+
'.css': 'text/css',
|
|
174
|
+
'.json': 'application/json',
|
|
175
|
+
'.png': 'image/png',
|
|
176
|
+
'.jpg': 'image/jpeg',
|
|
177
|
+
'.jpeg': 'image/jpeg',
|
|
178
|
+
'.gif': 'image/gif',
|
|
179
|
+
'.svg': 'image/svg+xml',
|
|
180
|
+
'.ico': 'image/x-icon',
|
|
181
|
+
'.webp': 'image/webp',
|
|
182
|
+
'.woff': 'font/woff',
|
|
183
|
+
'.woff2': 'font/woff2',
|
|
184
|
+
'.ttf': 'font/ttf',
|
|
185
|
+
'.eot': 'application/vnd.ms-fontobject',
|
|
186
|
+
};
|
|
187
|
+
return mimeTypes[ext] || 'application/octet-stream';
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Injects live reload script into HTML responses
|
|
191
|
+
*/
|
|
192
|
+
function injectLiveReloadScript(html) {
|
|
193
|
+
const script = `
|
|
194
|
+
<script>
|
|
195
|
+
(function() {
|
|
196
|
+
const ws = new WebSocket('ws://${host}:${port}/__ws');
|
|
197
|
+
ws.onmessage = function(event) {
|
|
198
|
+
const data = JSON.parse(event.data);
|
|
199
|
+
if (data.type === 'reload') {
|
|
200
|
+
console.log('Reloading page due to file changes...');
|
|
201
|
+
window.location.reload();
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
ws.onopen = function() {
|
|
205
|
+
console.log('Connected to Stati dev server');
|
|
206
|
+
};
|
|
207
|
+
ws.onclose = function() {
|
|
208
|
+
console.log('Lost connection to Stati dev server');
|
|
209
|
+
// Try to reconnect after a delay
|
|
210
|
+
setTimeout(() => window.location.reload(), 1000);
|
|
211
|
+
};
|
|
212
|
+
})();
|
|
213
|
+
</script>`;
|
|
214
|
+
// Insert before closing </body> tag, or at the end if no </body>
|
|
215
|
+
if (html.includes('</body>')) {
|
|
216
|
+
return html.replace('</body>', `${script}\n</body>`);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
return html + script;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Serves files from the dist directory
|
|
224
|
+
*/
|
|
225
|
+
async function serveFile(requestPath) {
|
|
226
|
+
let filePath = join(outDir, requestPath === '/' ? 'index.html' : requestPath);
|
|
227
|
+
try {
|
|
228
|
+
const stats = await stat(filePath);
|
|
229
|
+
if (stats.isDirectory()) {
|
|
230
|
+
// Try to serve index.html from directory
|
|
231
|
+
const indexPath = join(filePath, 'index.html');
|
|
232
|
+
try {
|
|
233
|
+
await stat(indexPath);
|
|
234
|
+
filePath = indexPath;
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
return {
|
|
238
|
+
content: '404 - Directory listing not available',
|
|
239
|
+
mimeType: 'text/plain',
|
|
240
|
+
statusCode: 404,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const mimeType = getMimeType(filePath);
|
|
245
|
+
const content = await readFile(filePath);
|
|
246
|
+
// Inject live reload script into HTML files
|
|
247
|
+
if (mimeType === 'text/html') {
|
|
248
|
+
const html = content.toString('utf-8');
|
|
249
|
+
const injectedHtml = injectLiveReloadScript(html);
|
|
250
|
+
return {
|
|
251
|
+
content: injectedHtml,
|
|
252
|
+
mimeType,
|
|
253
|
+
statusCode: 200,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
content,
|
|
258
|
+
mimeType,
|
|
259
|
+
statusCode: 200,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// File not found
|
|
264
|
+
return {
|
|
265
|
+
content: '404 - File not found',
|
|
266
|
+
mimeType: 'text/plain',
|
|
267
|
+
statusCode: 404,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const devServer = {
|
|
272
|
+
url,
|
|
273
|
+
async start() {
|
|
274
|
+
// Perform initial build
|
|
275
|
+
await initialBuild();
|
|
276
|
+
// Create HTTP server
|
|
277
|
+
httpServer = createServer(async (req, res) => {
|
|
278
|
+
const requestPath = req.url || '/';
|
|
279
|
+
// Handle WebSocket upgrade path
|
|
280
|
+
if (requestPath === '/__ws') {
|
|
281
|
+
return; // Let WebSocket server handle this
|
|
282
|
+
}
|
|
283
|
+
logger.processing?.(`${req.method} ${requestPath}`);
|
|
284
|
+
try {
|
|
285
|
+
const { content, mimeType, statusCode } = await serveFile(requestPath);
|
|
286
|
+
res.writeHead(statusCode, {
|
|
287
|
+
'Content-Type': mimeType,
|
|
288
|
+
'Access-Control-Allow-Origin': '*',
|
|
289
|
+
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
|
290
|
+
});
|
|
291
|
+
res.end(content);
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
logger.error?.(`Server error: ${error instanceof Error ? error.message : String(error)}`);
|
|
295
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
296
|
+
res.end('500 - Internal Server Error');
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
// Create WebSocket server for live reload
|
|
300
|
+
wsServer = new WebSocketServer({
|
|
301
|
+
server: httpServer,
|
|
302
|
+
path: '/__ws',
|
|
303
|
+
});
|
|
304
|
+
wsServer.on('connection', (ws) => {
|
|
305
|
+
logger.info?.('🔗 Browser connected for live reload');
|
|
306
|
+
const websocket = ws;
|
|
307
|
+
websocket.on('close', () => {
|
|
308
|
+
logger.info?.('Browser disconnected from live reload');
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
// Start HTTP server
|
|
312
|
+
await new Promise((resolve, reject) => {
|
|
313
|
+
httpServer.listen(port, host, () => {
|
|
314
|
+
resolve();
|
|
315
|
+
});
|
|
316
|
+
httpServer.on('error', (error) => {
|
|
317
|
+
reject(error);
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
// Set up file watching
|
|
321
|
+
const watchPaths = [srcDir, staticDir].filter(Boolean);
|
|
322
|
+
watcher = chokidar.watch(watchPaths, {
|
|
323
|
+
ignored: /(^|[/\\])\../, // ignore dotfiles
|
|
324
|
+
persistent: true,
|
|
325
|
+
ignoreInitial: true,
|
|
326
|
+
});
|
|
327
|
+
watcher.on('change', (path) => {
|
|
328
|
+
void incrementalRebuild(path);
|
|
329
|
+
});
|
|
330
|
+
watcher.on('add', (path) => {
|
|
331
|
+
void incrementalRebuild(path);
|
|
332
|
+
});
|
|
333
|
+
watcher.on('unlink', (path) => {
|
|
334
|
+
void incrementalRebuild(path);
|
|
335
|
+
});
|
|
336
|
+
logger.success?.(`Dev server running at ${url}`);
|
|
337
|
+
logger.info?.(`\nServing from:`);
|
|
338
|
+
logger.info?.(` 📁 ${outDir}`);
|
|
339
|
+
logger.info?.('Watching:');
|
|
340
|
+
watchPaths.forEach((path) => logger.info?.(` 📁 ${path}`));
|
|
341
|
+
// Open browser if requested
|
|
342
|
+
if (open) {
|
|
343
|
+
try {
|
|
344
|
+
const { default: openBrowser } = await import('open');
|
|
345
|
+
await openBrowser(url);
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
logger.info?.('Could not open browser automatically');
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
async stop() {
|
|
353
|
+
if (watcher) {
|
|
354
|
+
await watcher.close();
|
|
355
|
+
watcher = null;
|
|
356
|
+
}
|
|
357
|
+
if (wsServer) {
|
|
358
|
+
wsServer.close();
|
|
359
|
+
wsServer = null;
|
|
360
|
+
}
|
|
361
|
+
if (httpServer) {
|
|
362
|
+
await new Promise((resolve) => {
|
|
363
|
+
httpServer.close(() => resolve());
|
|
364
|
+
});
|
|
365
|
+
httpServer = null;
|
|
366
|
+
}
|
|
367
|
+
logger.info?.('🛑 Dev server stopped');
|
|
368
|
+
},
|
|
369
|
+
};
|
|
370
|
+
return devServer;
|
|
371
|
+
}
|
|
@@ -1,2 +1,68 @@
|
|
|
1
|
-
|
|
1
|
+
import type { CacheEntry } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Invalidation result containing affected cache entries.
|
|
4
|
+
*/
|
|
5
|
+
export interface InvalidationResult {
|
|
6
|
+
/** Number of cache entries invalidated */
|
|
7
|
+
invalidatedCount: number;
|
|
8
|
+
/** Paths of invalidated pages */
|
|
9
|
+
invalidatedPaths: string[];
|
|
10
|
+
/** Whether the entire cache was cleared */
|
|
11
|
+
clearedAll: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parses an invalidation query string into individual query terms.
|
|
15
|
+
* Supports space-separated values and quoted strings.
|
|
16
|
+
*
|
|
17
|
+
* @param query - The query string to parse
|
|
18
|
+
* @returns Array of parsed query terms
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* parseInvalidationQuery('tag:blog path:/posts') // ['tag:blog', 'path:/posts']
|
|
23
|
+
* parseInvalidationQuery('"tag:my tag" path:"/my path"') // ['tag:my tag', 'path:/my path']
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseInvalidationQuery(query: string): string[];
|
|
27
|
+
/**
|
|
28
|
+
* Checks if a cache entry matches a specific invalidation term.
|
|
29
|
+
*
|
|
30
|
+
* @param entry - Cache entry to check
|
|
31
|
+
* @param path - The page path for this entry
|
|
32
|
+
* @param term - Invalidation term to match against
|
|
33
|
+
* @returns True if the entry matches the term
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* matchesInvalidationTerm(entry, '/blog/post-1', 'tag:blog') // true if entry has 'blog' tag
|
|
38
|
+
* matchesInvalidationTerm(entry, '/blog/post-1', 'path:/blog') // true (path prefix match)
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function matchesInvalidationTerm(entry: CacheEntry, path: string, term: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Invalidates cache entries based on a query string.
|
|
44
|
+
* Supports tag-based, path-based, pattern-based, and time-based invalidation.
|
|
45
|
+
*
|
|
46
|
+
* @param query - Invalidation query string, or undefined to clear all cache
|
|
47
|
+
* @returns Promise resolving to invalidation result
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* // Invalidate all pages with 'blog' tag
|
|
52
|
+
* await invalidate('tag:blog');
|
|
53
|
+
*
|
|
54
|
+
* // Invalidate specific path
|
|
55
|
+
* await invalidate('path:/about');
|
|
56
|
+
*
|
|
57
|
+
* // Invalidate content younger than 3 months
|
|
58
|
+
* await invalidate('age:3months');
|
|
59
|
+
*
|
|
60
|
+
* // Invalidate multiple criteria
|
|
61
|
+
* await invalidate('tag:blog age:1week');
|
|
62
|
+
*
|
|
63
|
+
* // Clear entire cache
|
|
64
|
+
* await invalidate();
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare function invalidate(query?: string): Promise<InvalidationResult>;
|
|
2
68
|
//# sourceMappingURL=invalidate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invalidate.d.ts","sourceRoot":"","sources":["../../src/core/invalidate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"invalidate.d.ts","sourceRoot":"","sources":["../../src/core/invalidate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,0CAA0C;IAC1C,gBAAgB,EAAE,MAAM,CAAC;IACzB,iCAAiC;IACjC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,2CAA2C;IAC3C,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAkC9D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAkC9F;AAiLD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAoD5E"}
|