webspresso 0.0.96 → 0.0.98
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/.agents/ADMIN.md +153 -5
- package/.agents/ARCHITECTURE.md +10 -0
- package/.agents/CLI.md +195 -1
- package/.agents/PLUGINS.md +153 -9
- package/.agents/QUEUE.md +43 -0
- package/.agents/skills/webspresso-admin-and-plugins/SKILL.md +122 -0
- package/.agents/skills/webspresso-framework/SKILL.md +56 -0
- package/.agents/skills/webspresso-orm-and-database/SKILL.md +119 -0
- package/.agents/skills/webspresso-routing-and-api/SKILL.md +114 -0
- package/.agents/skills/webspresso-services/SKILL.md +101 -0
- package/bin/commands/add-esbuild.js +80 -0
- package/bin/commands/add-tailwind.js +76 -31
- package/bin/commands/admin-password.js +2 -1
- package/bin/commands/admin-setup.js +1 -1
- package/bin/commands/agents-init.js +51 -11
- package/bin/commands/analytics-prune.js +57 -0
- package/bin/commands/api.js +207 -15
- package/bin/commands/audit-prune.js +1 -1
- package/bin/commands/build.js +99 -0
- package/bin/commands/dev.js +64 -35
- package/bin/commands/doctor.js +26 -0
- package/bin/commands/email-prune.js +47 -0
- package/bin/commands/favicon-generate.js +1 -1
- package/bin/commands/make-job.js +86 -0
- package/bin/commands/make-model.js +250 -0
- package/bin/commands/new.js +45 -28
- package/bin/commands/openapi.js +102 -0
- package/bin/commands/orm-map.js +5 -4
- package/bin/commands/page.js +6 -3
- package/bin/commands/polar-migrate.js +1 -1
- package/bin/commands/queue-prune.js +59 -0
- package/bin/commands/routes.js +52 -0
- package/bin/commands/seed.js +1 -1
- package/bin/commands/service.js +6 -3
- package/bin/commands/typegen.js +106 -0
- package/bin/commands/upload-prune.js +79 -0
- package/bin/webspresso.js +22 -0
- package/core/applySchema.js +13 -6
- package/core/auth/hash.js +31 -17
- package/core/compression/middleware.js +23 -17
- package/core/openapi/build-from-api-routes.js +160 -29
- package/core/orm/cache/fingerprint.js +15 -1
- package/core/orm/cache/memory-provider.js +27 -2
- package/core/orm/index.js +12 -7
- package/core/orm/model.js +49 -7
- package/core/queue/adapters/database.js +94 -0
- package/core/queue/adapters/memory.js +62 -0
- package/core/queue/adapters/redis.js +80 -0
- package/core/queue/manager.js +123 -0
- package/core/ssr/stream.js +11 -0
- package/index.d.ts +660 -10
- package/index.js +44 -96
- package/package.json +32 -12
- package/plugins/admin-panel/api.js +279 -17
- package/plugins/admin-panel/app.js +124 -31
- package/plugins/admin-panel/client/parts/01-state-api-breadcrumb.js +314 -9
- package/plugins/admin-panel/client/parts/04-field-renderers.js +264 -67
- package/plugins/admin-panel/client/parts/05-rich-text-file-helpers.js +10 -5
- package/plugins/admin-panel/client/parts/06-login-setup-forms.js +119 -28
- package/plugins/admin-panel/client/parts/07-model-list.js +49 -8
- package/plugins/admin-panel/client/parts/08-record-list.js +243 -23
- package/plugins/admin-panel/client/parts/09-record-form.js +59 -12
- package/plugins/admin-panel/client/parts/10-export-registry.js +23 -0
- package/plugins/admin-panel/core/admin-module.js +13 -7
- package/plugins/admin-panel/core/api-extensions.js +34 -2
- package/plugins/admin-panel/core/registry.js +96 -16
- package/plugins/admin-panel/index.js +96 -0
- package/plugins/admin-panel/lib/login-rate-limiter.js +119 -0
- package/plugins/admin-panel/modules/admin-users.js +16 -1
- package/plugins/admin-panel/modules/bulk-actions.js +13 -5
- package/plugins/admin-panel/modules/custom-pages.js +492 -3
- package/plugins/admin-panel/modules/dashboard.js +283 -0
- package/plugins/admin-panel/modules/menu.js +56 -18
- package/plugins/admin-panel/modules/user-management.js +24 -6
- package/plugins/audit-log/admin-component.js +11 -0
- package/plugins/audit-log/api-handlers.js +34 -0
- package/plugins/audit-log/index.js +129 -3
- package/plugins/audit-log/purge.js +60 -10
- package/plugins/basic-auth/index.js +3 -1
- package/plugins/content/client/inline-edit.js +12 -12
- package/plugins/cors.js +6 -7
- package/plugins/dashboard/app.js +152 -27
- package/plugins/dashboard/index.js +143 -39
- package/plugins/dashboard/styles.js +78 -0
- package/plugins/data-exchange/export-xlsx.js +9 -2
- package/plugins/data-exchange/import.js +9 -2
- package/plugins/data-exchange/index.js +6 -3
- package/plugins/email/index.js +132 -2
- package/plugins/email/purge.js +60 -10
- package/plugins/file-manager/core.js +1 -1
- package/plugins/file-manager/security.js +33 -23
- package/plugins/index.js +49 -87
- package/plugins/mcp/transports/sse.js +4 -2
- package/plugins/orm-cache-admin/index.js +4 -2
- package/plugins/queue/index.js +11 -0
- package/plugins/schema-explorer/admin-component.js +714 -0
- package/plugins/schema-explorer/relations-graph.js +205 -0
- package/plugins/schema-explorer.js +248 -69
- package/plugins/site-analytics/admin-component.js +30 -8
- package/plugins/site-analytics/api-handlers.js +42 -0
- package/plugins/site-analytics/index.js +147 -2
- package/plugins/site-analytics/purge.js +168 -0
- package/plugins/swagger.js +261 -13
- package/plugins/upload/index.js +26 -0
- package/plugins/upload/orphan-pruner.js +292 -0
- package/src/api/api-loader.js +3 -1
- package/src/bundle/index.js +517 -0
- package/src/bundle/manifest.js +165 -0
- package/src/dev/banner.js +296 -0
- package/src/dev/colors.js +70 -0
- package/src/dev/index.js +62 -0
- package/src/dev/profiler.js +354 -0
- package/src/dev/typegen.js +497 -0
- package/src/dev-reload/index.js +611 -0
- package/src/file-router.js +213 -63
- package/src/helpers.js +958 -98
- package/src/njk-frontmatter.js +12 -0
- package/src/pages/page-loader.js +61 -11
- package/src/server.js +629 -63
- package/src/services/discovery.js +6 -1
- package/src/services/index.js +6 -13
package/.agents/ADMIN.md
CHANGED
|
@@ -133,7 +133,59 @@ registry.registerPageDir(path.join(__dirname, 'admin-pages'));
|
|
|
133
133
|
|
|
134
134
|
---
|
|
135
135
|
|
|
136
|
-
## 5.
|
|
136
|
+
## 5. Page & Plugin Title Management
|
|
137
|
+
|
|
138
|
+
Admin Panel supports configurable base titles, title templates, and dynamic SPA page titles:
|
|
139
|
+
|
|
140
|
+
### Plugin Configuration
|
|
141
|
+
```js
|
|
142
|
+
adminPanelPlugin({
|
|
143
|
+
db,
|
|
144
|
+
title: 'Acme Admin', // Base title in <title> and header (default: 'Admin Panel')
|
|
145
|
+
titleTemplate: '%s | %b', // Format template: %s = page title, %b = base title (default: '%s | %b')
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Module & Page Title Configuration
|
|
150
|
+
When registering modules and custom pages, titles are automatically propagated to navigation and browser document title:
|
|
151
|
+
```js
|
|
152
|
+
adminApi.registerModule({
|
|
153
|
+
id: 'reports',
|
|
154
|
+
title: 'Reports & Analytics', // Module fallback title
|
|
155
|
+
pages: [
|
|
156
|
+
{
|
|
157
|
+
id: 'monthly-report',
|
|
158
|
+
title: 'Monthly Report', // Document title -> "Monthly Report | Acme Admin"
|
|
159
|
+
path: '/reports/monthly',
|
|
160
|
+
component: ...,
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
id: 'live-dashboard',
|
|
164
|
+
documentTitle: 'Live Monitor (Fullscreen)', // Raw document.title override
|
|
165
|
+
path: '/reports/live',
|
|
166
|
+
layout: false,
|
|
167
|
+
component: ...,
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Dynamic Client-Side Title Helper (`setAdminPageTitle`)
|
|
174
|
+
From any Mithril component or client script:
|
|
175
|
+
```js
|
|
176
|
+
// Dynamic title formatted with template (e.g. "Sales Overview | Acme Admin")
|
|
177
|
+
window.setAdminPageTitle('Sales Overview');
|
|
178
|
+
|
|
179
|
+
// Custom template override
|
|
180
|
+
window.setAdminPageTitle('Sales Overview', { template: '%s — %b' });
|
|
181
|
+
|
|
182
|
+
// Raw document title without template
|
|
183
|
+
window.setAdminPageTitle('Sales Overview', { raw: true });
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## 6. Custom Field Renderers (`registerFieldRenderer`)
|
|
137
189
|
|
|
138
190
|
Register custom display and edit renderers for specific column types:
|
|
139
191
|
|
|
@@ -152,7 +204,7 @@ registry.registerFieldRenderer('color-picker', {
|
|
|
152
204
|
|
|
153
205
|
---
|
|
154
206
|
|
|
155
|
-
##
|
|
207
|
+
## 7. Dashboard Widgets (`registerWidget`)
|
|
156
208
|
|
|
157
209
|
Register dashboard widgets for the Admin overview screen:
|
|
158
210
|
|
|
@@ -164,9 +216,20 @@ registry.registerWidget('recent-orders', {
|
|
|
164
216
|
});
|
|
165
217
|
```
|
|
166
218
|
|
|
219
|
+
### Built-in Dashboard Widgets
|
|
220
|
+
- **`model-stats`**: Model overview cards displaying record counts, column counts, and last update timestamps.
|
|
221
|
+
- **`database-storage`**: Database Storage & Health monitor showing:
|
|
222
|
+
- Database engine (SQLite, PostgreSQL, MySQL) & active file sizes
|
|
223
|
+
- Total tables and total record counts across the schema
|
|
224
|
+
- Storage health status badge with high-volume alerts for unpruned logs
|
|
225
|
+
- Top tables by row count with visual progress percentage bars
|
|
226
|
+
- Direct navigation links to model CRUD screens
|
|
227
|
+
- **`quick-actions`**: Fast shortcuts to create new records across enabled models.
|
|
228
|
+
- **`recent-activity`**: Timeline of recent administrative mutations (creates, updates, deletes).
|
|
229
|
+
|
|
167
230
|
---
|
|
168
231
|
|
|
169
|
-
##
|
|
232
|
+
## 8. Single Record & Bulk Table Actions
|
|
170
233
|
|
|
171
234
|
Add custom action buttons to model table views:
|
|
172
235
|
|
|
@@ -196,7 +259,7 @@ registry.registerBulkAction('Product', {
|
|
|
196
259
|
|
|
197
260
|
---
|
|
198
261
|
|
|
199
|
-
##
|
|
262
|
+
## 9. Client Components & Custom Client Script Injections
|
|
200
263
|
|
|
201
264
|
Inject custom client-side JavaScript / Mithril components into the Admin SPA runtime:
|
|
202
265
|
|
|
@@ -213,7 +276,7 @@ registry.registerClientComponent('custom-banner', `
|
|
|
213
276
|
|
|
214
277
|
---
|
|
215
278
|
|
|
216
|
-
##
|
|
279
|
+
## 10. Offline & Zero-CDN Architecture
|
|
217
280
|
|
|
218
281
|
The Admin Panel is 100% self-contained and operates completely offline without external CDN dependencies (`unpkg.com`, `cdn.jsdelivr.net`, or `cdn.tailwindcss.com`):
|
|
219
282
|
- **Vendored Static Assets (`plugins/admin-panel/vendor/`)**:
|
|
@@ -223,3 +286,88 @@ The Admin Panel is 100% self-contained and operates completely offline without e
|
|
|
223
286
|
- **Local Asset Serving**: Served locally at `GET /_admin/vendor/:file` with proper MIME types, path traversal protections, and `Cache-Control: public, max-age=86400` caching.
|
|
224
287
|
- **Hardened CSP**: Works in air-gapped / intranet environments with strict `'self'` Content Security Policy without leaking third-party network requests.
|
|
225
288
|
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 11. Toast Notifications, Modal Confirmations & Session Expiry UX
|
|
292
|
+
|
|
293
|
+
The Admin SPA includes a built-in reactive notification and modal system that replaces intrusive browser `alert()` and `confirm()` dialogs.
|
|
294
|
+
|
|
295
|
+
### Toast Notifications (`window.notify`)
|
|
296
|
+
Display auto-dismissing, animated toasts in the top-right corner with pause-on-hover:
|
|
297
|
+
|
|
298
|
+
```js
|
|
299
|
+
// Available on window.notify or as global helpers: notifySuccess, notifyError, notifyWarning, notifyInfo
|
|
300
|
+
notify.success('Record created successfully');
|
|
301
|
+
notify.error('Failed to save record: Validation error');
|
|
302
|
+
notify.warning('Please review unsaved changes');
|
|
303
|
+
notify.info('Export started in the background');
|
|
304
|
+
|
|
305
|
+
// Custom duration (TTL in milliseconds, default 4000ms):
|
|
306
|
+
notify.success('Saved!', 2000);
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Confirmation Modal (`window.confirmModal` / `confirmAction`)
|
|
310
|
+
Display an accessible, styled modal dialog returning a Promise resolving to `true` or `false`:
|
|
311
|
+
|
|
312
|
+
```js
|
|
313
|
+
// Destructive confirmation (danger: true highlights the confirm button in red)
|
|
314
|
+
const confirmed = await confirmAction({
|
|
315
|
+
title: 'Delete User',
|
|
316
|
+
message: 'Are you sure you want to permanently delete this user?',
|
|
317
|
+
confirmText: 'Delete',
|
|
318
|
+
cancelText: 'Cancel',
|
|
319
|
+
danger: true,
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
if (confirmed) {
|
|
323
|
+
await api.delete(`/users/${id}`);
|
|
324
|
+
notify.success('User deleted');
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Session Expiration & Intended Return-To Redirection
|
|
329
|
+
When an authenticated staff user's session expires or an API call returns `401 Unauthorized`:
|
|
330
|
+
1. `redirectToLogin('expired')` captures the active route and redirects to `/_admin/#!/login?returnTo=<route>&reason=expired`.
|
|
331
|
+
2. The login screen displays an informational notice banner: *"Your session has expired. Please sign in again."*
|
|
332
|
+
3. After authenticating successfully, the user is automatically redirected to their intended route.
|
|
333
|
+
4. **Open-Redirect Hardening**: All return destinations are strictly validated by `isSafeIntendedRoute(path)` to disallow protocol-relative URLs (`//evil.com`), foreign protocols (`http:`, `javascript:`), or backslashes.
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## 12. Admin Login Brute-Force Protection & Rate Limiting
|
|
338
|
+
|
|
339
|
+
The Admin Panel includes built-in in-memory rate limiting to defend staff login endpoints against credential stuffing and brute-force password guessing.
|
|
340
|
+
|
|
341
|
+
### Configuration (`adminPanelPlugin`)
|
|
342
|
+
|
|
343
|
+
```js
|
|
344
|
+
import { createApp, adminPanelPlugin } from 'webspresso';
|
|
345
|
+
|
|
346
|
+
const app = createApp({
|
|
347
|
+
plugins: [
|
|
348
|
+
adminPanelPlugin({
|
|
349
|
+
db,
|
|
350
|
+
// Configure or disable login rate limiting:
|
|
351
|
+
loginRateLimit: {
|
|
352
|
+
enabled: true, // Default: true
|
|
353
|
+
maxAttempts: 5, // Max failed attempts before blocking (default: 5)
|
|
354
|
+
windowMs: 15 * 60 * 1000, // Tracking window (default: 15 minutes)
|
|
355
|
+
blockDurationMs: 15 * 60 * 1000 // Temporary block duration (default: 15 minutes)
|
|
356
|
+
},
|
|
357
|
+
}),
|
|
358
|
+
],
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
To disable rate limiting (e.g. in test or internal automated environments):
|
|
363
|
+
```js
|
|
364
|
+
adminPanelPlugin({ db, loginRateLimit: false });
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Protection Mechanics
|
|
368
|
+
- **IP Tracking**: Tracks failed attempts keyed by client IP (`req.ip` or upstream trusted proxy headers).
|
|
369
|
+
- **Automatic Block**: After `maxAttempts` failed logins within `windowMs`, returns HTTP 429 Too Many Requests with a `Retry-After: <seconds>` response header and JSON error payload.
|
|
370
|
+
- **Success Reset**: A single successful login clears the failed attempt counter for that IP.
|
|
371
|
+
- **Programmatic Reset**: Cleared automatically upon server restart or via `plugin.api.resetLoginAttempts(ip)`.
|
|
372
|
+
|
|
373
|
+
|
package/.agents/ARCHITECTURE.md
CHANGED
|
@@ -116,4 +116,14 @@ Plugins expose `name`, `version`, `dependencies`, and lifecycle hooks (`register
|
|
|
116
116
|
| `xlsxPlugin` | Excel / Export | Excel spreadsheet generation, parsing, ORM streaming export (`res.xlsx`), and services |
|
|
117
117
|
| `csvPlugin` | CSV / Export | RFC 4180 CSV generator, parser, Excel UTF-8 BOM, streaming writer (`res.csv`), and services |
|
|
118
118
|
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## 5. Developer Experience & Live/Hot Reload (`src/dev-reload/`)
|
|
122
|
+
|
|
123
|
+
- **Zero-Dependency SSE Reload Hub**: Enabled via `createApp({ devReload: true })` (or `devReload: { watchTemplates: true, watchCss: true, debounce: 50 }`).
|
|
124
|
+
- **Instant CSS Hot Swap**: Modifying `.css` files dynamically refreshes all `<link rel="stylesheet">` elements without page refresh or DOM state loss.
|
|
125
|
+
- **Template & Layout Live Reload**: Modifying Nunjucks templates (`.njk`, `.html`) in `views/` or pages in `pages/` automatically invalidates frontmatter/loader caches and broadcasts a debounced `'full'` reload event to active browser tabs.
|
|
126
|
+
- **Error Overlay Frame**: Client runtime script automatically renders terminal-free in-browser error frames for compile/build errors with line numbers and dismiss keyboard shortcuts (`Esc`).
|
|
127
|
+
- **DevTools Toolbar & Dashboard**: Embedded via `fsy.devToolbar()` and available at `/_webspresso` for interactive inspection of routes, models, services, cache, and profiler metrics.
|
|
128
|
+
|
|
119
129
|
|
package/.agents/CLI.md
CHANGED
|
@@ -13,8 +13,12 @@ npx webspresso dev
|
|
|
13
13
|
# --port, -p <number> (default: 3001)
|
|
14
14
|
# --host <string> (default: localhost)
|
|
15
15
|
|
|
16
|
-
# Build production bundle /
|
|
16
|
+
# Build production bundle / compile assets (Tailwind + esbuild with manifest.json)
|
|
17
17
|
npx webspresso build
|
|
18
|
+
# Flags:
|
|
19
|
+
# --no-css (skip CSS build)
|
|
20
|
+
# --no-js (skip JS bundle build)
|
|
21
|
+
# --no-hash (disable content hashing in filenames)
|
|
18
22
|
```
|
|
19
23
|
|
|
20
24
|
---
|
|
@@ -113,3 +117,193 @@ npx webspresso agents:init
|
|
|
113
117
|
npx webspresso agents:init --force
|
|
114
118
|
```
|
|
115
119
|
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 8. Tailwind CSS Setup & Migration (`add:tailwind`)
|
|
123
|
+
|
|
124
|
+
Add or upgrade Tailwind CSS in a project:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Add Tailwind CSS v4 (Oxide engine, LightningCSS, zero-config)
|
|
128
|
+
npx webspresso add tailwind --v4
|
|
129
|
+
|
|
130
|
+
# Add Tailwind CSS v3 (legacy PostCSS engine)
|
|
131
|
+
npx webspresso add tailwind --v3
|
|
132
|
+
|
|
133
|
+
# Upgrade existing Tailwind v3 project to v4
|
|
134
|
+
npx webspresso add tailwind --upgrade
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 9. Client Bundler Setup (`add:esbuild`)
|
|
140
|
+
|
|
141
|
+
Add client-side JS/TS bundling with esbuild incremental watching:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Scaffold esbuild client bundler setup
|
|
145
|
+
npx webspresso add esbuild
|
|
146
|
+
# or
|
|
147
|
+
npx webspresso add:esbuild
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 10. Data Retention & Storage Cleanup Commands
|
|
153
|
+
|
|
154
|
+
Keep databases and storage clean by pruning historical records and unreferenced files:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Delete audit log entries older than N days (default: 90)
|
|
158
|
+
npx webspresso audit:prune --days 90
|
|
159
|
+
|
|
160
|
+
# Delete email delivery logs older than N days (default: 90)
|
|
161
|
+
npx webspresso email:prune --days 90
|
|
162
|
+
|
|
163
|
+
# Delete completed/failed background jobs older than N days (default: 30)
|
|
164
|
+
npx webspresso queue:prune --days 30
|
|
165
|
+
|
|
166
|
+
# Delete expired site analytics visits & JS errors older than N days
|
|
167
|
+
npx webspresso analytics:prune --days 90
|
|
168
|
+
|
|
169
|
+
# Scan and delete orphaned uploads not referenced by any database model
|
|
170
|
+
npx webspresso upload:prune
|
|
171
|
+
|
|
172
|
+
# Dry run mode (inspect orphaned files without deleting)
|
|
173
|
+
npx webspresso upload:prune --dry-run
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 11. Routes Introspection (`routes`)
|
|
179
|
+
|
|
180
|
+
List and inspect all compiled file-based and API routes in terminal:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# List all application routes in a colorized table
|
|
184
|
+
npx webspresso routes
|
|
185
|
+
|
|
186
|
+
# Filter to only API endpoints
|
|
187
|
+
npx webspresso routes --api
|
|
188
|
+
|
|
189
|
+
# Filter to only SSR page routes
|
|
190
|
+
npx webspresso routes --pages
|
|
191
|
+
|
|
192
|
+
# Output routes as machine-readable JSON
|
|
193
|
+
npx webspresso routes --json
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## 12. Dev Server DX & Query Profiler
|
|
199
|
+
|
|
200
|
+
When starting in development mode (`isDev: true` / `process.env.NODE_ENV !== 'production'`), Webspresso automatically:
|
|
201
|
+
|
|
202
|
+
- **Displays Startup Banner**: ASCII box with Node/Framework version, Local & Admin URLs, Database dialect, and counts of routes, models, services, and plugins.
|
|
203
|
+
- **Request Profiler & Logger**: Color-coded HTTP requests with status, response duration, and database metrics:
|
|
204
|
+
```text
|
|
205
|
+
[GET 200] /api/notes — 14.2ms | 2 DB queries (2.8ms)
|
|
206
|
+
```
|
|
207
|
+
- **N+1 Query Detection**: Flags queries executing repeatedly against the same table within a single request:
|
|
208
|
+
```text
|
|
209
|
+
⚠️ [webspresso:n+1] Potential N+1 query pattern detected on table 'users' (5 queries, 6.4ms). Consider eager loading with repo.query().include('users') or batching.
|
|
210
|
+
```
|
|
211
|
+
- **Configuration (`dev` options in `createApp`)**:
|
|
212
|
+
```javascript
|
|
213
|
+
createApp({
|
|
214
|
+
dev: {
|
|
215
|
+
banner: true, // show startup banner (default: true in dev)
|
|
216
|
+
routeTable: true, // show route table in banner (default: true)
|
|
217
|
+
profiler: true, // enable request & DB profiler (default: true)
|
|
218
|
+
nPlusOne: true, // detect N+1 queries (default: true)
|
|
219
|
+
nPlusOneThreshold: 4,// query count threshold for warning (default: 4)
|
|
220
|
+
slowQueryMs: 50, // flag queries slower than N ms (default: 50)
|
|
221
|
+
verbose: false, // log individual SQL statements
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## 13. Scaffolding & Code Generation (`make:*` Commands)
|
|
229
|
+
|
|
230
|
+
Quickly generate boilerplate adhering strictly to Webspresso contracts:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
# 1. Scaffold an ORM Model in models/<Name>.js with parsed zdb fields and Knex migration
|
|
234
|
+
npx webspresso make:model Post --fields title:string,content:text,published:boolean,views:integer --migration
|
|
235
|
+
# Flags:
|
|
236
|
+
# --fields <list> (title:string,content:text,views:integer,price:number,published:boolean,authorId:id)
|
|
237
|
+
# --table <name> (custom table name; defaults to pluralized lowercase)
|
|
238
|
+
# --migration, -m (auto-generate timestamped Knex migration in migrations/)
|
|
239
|
+
# --soft-deletes (include deletedAt column and default scope)
|
|
240
|
+
|
|
241
|
+
# 2. Scaffold API Endpoints in pages/api/
|
|
242
|
+
# Single endpoint with Zod validation and handler:
|
|
243
|
+
npx webspresso make:api notes/export --method POST --auth
|
|
244
|
+
|
|
245
|
+
# Full REST CRUD Suite (list, create, detail, update, delete) in pages/api/posts:
|
|
246
|
+
npx webspresso make:api posts --crud --model Post
|
|
247
|
+
|
|
248
|
+
# 3. Scaffold an SSR Page in pages/
|
|
249
|
+
npx webspresso make:page blog/[slug]
|
|
250
|
+
# Generates pages/blog/[slug].njk template + companion loader pages/blog/[slug].js
|
|
251
|
+
|
|
252
|
+
# 4. Scaffold a Service in services/<domain>/<action>.js
|
|
253
|
+
npx webspresso make:service order.process --transaction --auth admin
|
|
254
|
+
|
|
255
|
+
# 5. Scaffold a Background Queue Worker in jobs/<name>.js
|
|
256
|
+
npx webspresso make:job send-welcome-email --queue default --retries 3
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## 14. OpenAPI & API Documentation Export (`openapi` / `api:docs`)
|
|
262
|
+
|
|
263
|
+
Generate and export standard OpenAPI 3.0 JSON specification from file-based API routes and Zod schemas:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# Print OpenAPI 3.0 specification to stdout
|
|
267
|
+
npx webspresso openapi
|
|
268
|
+
|
|
269
|
+
# Export directly to a JSON file
|
|
270
|
+
npx webspresso openapi --out openapi.json
|
|
271
|
+
|
|
272
|
+
# Export with custom title, version, and server URL
|
|
273
|
+
npx webspresso api:docs --out public/openapi.json --title "My API" --api-version "2.0.0" --server "https://api.myapp.com"
|
|
274
|
+
|
|
275
|
+
# Include ORM model schemas in components.schemas
|
|
276
|
+
npx webspresso openapi --out openapi.json --include-orm
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## 15. TypeScript Definitions & IDE Auto-Complete Generator (`typegen` / `types`)
|
|
282
|
+
|
|
283
|
+
Scan ORM models, business services, and routes to automatically generate typed TypeScript declaration files (`.webspresso/types.d.ts` and `webspresso-env.d.ts`) with module augmentation:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
# Generate TypeScript definitions
|
|
287
|
+
npx webspresso typegen
|
|
288
|
+
|
|
289
|
+
# Aliases
|
|
290
|
+
npx webspresso types
|
|
291
|
+
npx webspresso generate:types
|
|
292
|
+
|
|
293
|
+
# Watch mode (automatically regenerates on model/service/page edits)
|
|
294
|
+
npx webspresso typegen --watch
|
|
295
|
+
|
|
296
|
+
# Custom output destination
|
|
297
|
+
npx webspresso typegen --out types/webspresso.d.ts --no-env-file
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Generated Capabilities & IDE DX:
|
|
301
|
+
- **Typed Models (`db.getRepository('Model')`)**: Auto-completes model names and infers entity column types from Zod schemas.
|
|
302
|
+
- **Typed Services (`req.service('name', input)`)**: Auto-completes registered service names and enforces validated input payloads.
|
|
303
|
+
- **Typed Route Table (`AppRoute`, `AppRoutePath`)**: Union types for all discovered SSR and API routes.
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
|
package/.agents/PLUGINS.md
CHANGED
|
@@ -91,6 +91,8 @@ Schema-driven headless CMS & inline content editing.
|
|
|
91
91
|
Multipart file upload manager with local / cloud storage providers.
|
|
92
92
|
- **Options**: `{ path: '/api/upload', local: { destDir, publicBasePath }, maxBytes: 10000000, mimeAllowlist: ['image/png', 'image/jpeg'] }`
|
|
93
93
|
- **Features**: Single & multi-file uploads, file size & extension validation, storage drivers.
|
|
94
|
+
- **Orphan Pruning**: `scanOrphanedUploads({ db, destDir })` and `pruneOrphanedUploads({ db, destDir, dryRun })` to detect and remove disk files no longer referenced by any database model, accompanied by CLI command `webspresso upload:prune [--dry-run]`.
|
|
95
|
+
|
|
94
96
|
|
|
95
97
|
### 2.5 `fileManagerPlugin` (`plugins/file-manager`)
|
|
96
98
|
Filesystem-first media library, directory explorer, and modal asset picker for Admin Panel.
|
|
@@ -122,12 +124,49 @@ Request rate limiting using express-rate-limit logic.
|
|
|
122
124
|
- **Options**: `{ windowMs: 15 * 60 * 1000, max: 100 }`
|
|
123
125
|
|
|
124
126
|
### 2.9 `siteAnalyticsPlugin` (`plugins/site-analytics`)
|
|
125
|
-
Self-hosted privacy-focused page view analytics
|
|
126
|
-
- **Options**:
|
|
127
|
+
Self-hosted privacy-focused page view analytics, client error tracking, and automated retention cleanup.
|
|
128
|
+
- **Options**:
|
|
129
|
+
- `db`: Knex database instance.
|
|
130
|
+
- `tableName`: Table name for page views (default: `'analytics_page_views'`).
|
|
131
|
+
- `errorsTableName`: Table name for client errors (default: `'analytics_client_errors'`).
|
|
132
|
+
- `retentionDays`: Page views retention window in days (default: `90`).
|
|
133
|
+
- `errorRetentionDays`: Client error logs retention window in days (default: `30`).
|
|
134
|
+
- `cleanupIntervalMs`: Background scheduled cleanup interval in milliseconds (default: `86400000` / 24 hours).
|
|
135
|
+
- `autoCleanup`: Enable automated periodic background cleanup (default: `true`).
|
|
136
|
+
- `cleanupOnStart`: Run an initial non-blocking cleanup shortly after startup (default: `true`).
|
|
137
|
+
- `retention`: Shorthand object `{ enabled, days, errorDays, intervalMs, runOnStart }` or `false` to disable retention cleanup.
|
|
138
|
+
- `excludePaths`, `excludeBots`, `customBots`, `anonymizeIp`, `trustProxy`, `collectErrors`, `dashboard`.
|
|
139
|
+
- **Programmatic API (`plugin.api`)**:
|
|
140
|
+
- `purge({ days, errorDays, olderThan, errorsOlderThan })`: Manual purge of page views and error logs.
|
|
141
|
+
- `purgeAnalyticsData(knex, options)`: Standalone query purge helper.
|
|
142
|
+
- `startCleanup(intervalMs)` / `stopCleanup()`: Control background cleanup lifecycle.
|
|
143
|
+
- `getRetentionConfig()`: Inspect active retention configuration.
|
|
144
|
+
- **Admin REST Endpoint**: `POST /_admin/api/analytics/purge` (accepts `{ days, errorDays }`).
|
|
145
|
+
- **Admin UI**: "Purge Old Data" button with confirmation prompt in the Analytics admin dashboard header.
|
|
146
|
+
- **CLI Command**:
|
|
147
|
+
```bash
|
|
148
|
+
webspresso analytics:prune --days 90 --error-days 30
|
|
149
|
+
```
|
|
150
|
+
- **Lifecycle Integration**: Background timer uses `.unref()` to avoid keeping Node event loop open, and registers a framework disposer to clear timers on shutdown.
|
|
127
151
|
|
|
128
152
|
### 2.10 `emailPlugin` (`plugins/email`)
|
|
129
|
-
Transactional email compiler (MJML) & Nodemailer transport integration.
|
|
130
|
-
- **Options**:
|
|
153
|
+
Transactional email compiler (MJML) & Nodemailer transport integration with database delivery logging and auto-retention cleanup.
|
|
154
|
+
- **Options**:
|
|
155
|
+
- `transport` / `smtp`: Nodemailer transport or SMTP settings.
|
|
156
|
+
- `defaults`: Default sender/reply-to address.
|
|
157
|
+
- `templatesDir`: Directory containing `.mjml` templates.
|
|
158
|
+
- `logToDb`: Store delivery history in database (default `true` when `db` is supplied).
|
|
159
|
+
- `tableName`: Database table name (default `'email_logs'`).
|
|
160
|
+
- `retentionDays`: Days to retain email logs (default `90`).
|
|
161
|
+
- `cleanupIntervalMs`: Background cleanup timer frequency (default 24h).
|
|
162
|
+
- `autoCleanup`: Enable scheduled background purge (default `true`).
|
|
163
|
+
- `cleanupOnStart`: Run initial purge shortly after boot (default `true`).
|
|
164
|
+
- `retention`: `{ enabled, days: 90, intervalMs: 86400000, runOnStart: true }` (or `false` to disable).
|
|
165
|
+
- **Pruning CLI**:
|
|
166
|
+
```bash
|
|
167
|
+
webspresso email:prune --days 90
|
|
168
|
+
```
|
|
169
|
+
- **Admin Panel UI**: Includes log listing, test email dispatch, template preview, connection verification, and "Purge 90d" action.
|
|
131
170
|
|
|
132
171
|
### 2.11 `polarPlugin` (`plugins/polar`)
|
|
133
172
|
Polar.sh subscription billing — checkout, customer portal, webhooks, Customer State sync, tier columns. Zero extra deps (`crypto` + `fetch`).
|
|
@@ -178,17 +217,86 @@ Polar.sh subscription billing — checkout, customer portal, webhooks, Customer
|
|
|
178
217
|
- [docs/guides/polar-production-checklist.md](../docs/guides/polar-production-checklist.md)
|
|
179
218
|
|
|
180
219
|
### 2.12 `auditLogPlugin` (`plugins/audit-log`)
|
|
181
|
-
Admin mutation tracking and audit
|
|
182
|
-
- **Options**:
|
|
220
|
+
Admin mutation tracking and audit history with scheduled retention and manual purge API.
|
|
221
|
+
- **Options**:
|
|
222
|
+
- `db`: Database instance (must expose `.knex`).
|
|
223
|
+
- `tableName`: Database table name (default `'audit_logs'`).
|
|
224
|
+
- `retentionDays`: Days to retain audit trail entries (default `90`).
|
|
225
|
+
- `cleanupIntervalMs`: Background cleanup timer frequency (default 24h).
|
|
226
|
+
- `autoCleanup`: Enable scheduled background purge (default `true`).
|
|
227
|
+
- `cleanupOnStart`: Run initial purge shortly after boot (default `true`).
|
|
228
|
+
- `retention`: `{ enabled, days: 90, intervalMs: 86400000, runOnStart: true }` (or `false` to disable).
|
|
229
|
+
- **Pruning CLI**:
|
|
230
|
+
```bash
|
|
231
|
+
webspresso audit:prune --days 90
|
|
232
|
+
```
|
|
233
|
+
- **API & Admin Panel**:
|
|
234
|
+
- `POST /_admin/api/audit-logs/purge`: `{ days: 90 }` or `{ olderThan: '2026-01-01' }`
|
|
235
|
+
- "Purge 90d" button directly in the Admin Panel audit log viewer.
|
|
236
|
+
- Lifecycle integration: background timers use `.unref()` and clean up on server shutdown.
|
|
183
237
|
|
|
184
238
|
### 2.13 `ormCacheAdminPlugin` (`plugins/orm-cache-admin`)
|
|
185
239
|
ORM Cache inspection and invalidation dashboard.
|
|
186
240
|
|
|
187
241
|
### 2.14 `schemaExplorerPlugin` (`plugins/schema-explorer`)
|
|
188
|
-
Interactive
|
|
242
|
+
Interactive Database Schema & ER Diagram Explorer for both raw JSON/OpenAPI endpoints and Admin Panel SPA.
|
|
243
|
+
- **Admin Panel Page (`/_admin/schema`)**:
|
|
244
|
+
- Interactive Table & Column details (Primary Keys, Foreign Keys, Nullability, Types, Constraints, Scopes).
|
|
245
|
+
- Visual Relationship Map (ER Diagram) with bidirectional incoming & outgoing relation links.
|
|
246
|
+
- Interactive table cards highlighting connected models and key mappings (`posts.author_id ➔ authors.id`).
|
|
247
|
+
- One-click Mermaid.js ER diagram code generation and copy.
|
|
248
|
+
- JSON schema export.
|
|
249
|
+
- **Options**:
|
|
250
|
+
- `admin: true` — Automatically registers into `adminPanelPlugin` when present.
|
|
251
|
+
- `adminPath: '/schema'` — Custom path inside Admin Panel.
|
|
252
|
+
- `menuLabel: 'Schema Explorer'` — Sidebar menu label.
|
|
253
|
+
- `menuIcon: 'database'` — Sidebar icon.
|
|
254
|
+
- `path: '/_schema'` — Raw JSON endpoint path.
|
|
255
|
+
- `exclude: ['SecretModel']` — Models to exclude.
|
|
256
|
+
- **Usage**:
|
|
257
|
+
```js
|
|
258
|
+
const { createApp } = require('webspresso');
|
|
259
|
+
const { adminPanelPlugin, schemaExplorerPlugin } = require('webspresso/plugins');
|
|
260
|
+
|
|
261
|
+
const { app } = createApp({
|
|
262
|
+
plugins: [
|
|
263
|
+
adminPanelPlugin({ db }),
|
|
264
|
+
schemaExplorerPlugin({ admin: true }),
|
|
265
|
+
],
|
|
266
|
+
});
|
|
267
|
+
```
|
|
189
268
|
|
|
190
|
-
### 2.15 `swaggerPlugin` (`plugins/swagger`)
|
|
191
|
-
Interactive OpenAPI 3.0 Swagger UI
|
|
269
|
+
### 2.15 `swaggerPlugin` / `openapiPlugin` (`plugins/swagger`)
|
|
270
|
+
Interactive OpenAPI 3.0 API documentation supporting both modern **Scalar API Reference** and classic **Swagger UI**, automated parameter/tag/summary inference, auth detection, Admin Panel embedding, and CLI export.
|
|
271
|
+
|
|
272
|
+
- **Options**:
|
|
273
|
+
- `path`: Base path for documentation (default: `/_swagger`). Spec served at `{path}/openapi.json`.
|
|
274
|
+
- `ui`: Default playground engine: `'swagger'` or `'scalar'` (default: `'swagger'`).
|
|
275
|
+
- `theme`: Theme for Scalar UI (`'default'`, `'purple'`, `'moon'`, `'solarized'`, etc.).
|
|
276
|
+
- `darkMode`: Scalar dark mode toggle (default: `true`).
|
|
277
|
+
- `admin`: Auto-register inside Admin Panel (`/_admin/#!/api-docs`) when `admin-panel` plugin is loaded (default: `true`).
|
|
278
|
+
- `adminTitle`: Admin navigation label (default: `'API Docs'`).
|
|
279
|
+
- `includeOrmSchemas`: Merge ORM models into `components.schemas` (default: `false`).
|
|
280
|
+
- `authorize`: Custom `(req) => boolean` guard function.
|
|
281
|
+
- **Endpoints**:
|
|
282
|
+
- `GET /_swagger`: Primary UI (Scalar or Swagger based on `ui` option).
|
|
283
|
+
- `GET /_swagger/scalar`: Always serves modern Scalar UI.
|
|
284
|
+
- `GET /_swagger/swagger`: Always serves Swagger UI.
|
|
285
|
+
- `GET /_swagger/openapi.json`: OpenAPI 3.0 specification document.
|
|
286
|
+
- **Example**:
|
|
287
|
+
```javascript
|
|
288
|
+
const { createApp, openapiPlugin } = require('webspresso');
|
|
289
|
+
|
|
290
|
+
const { app } = createApp({
|
|
291
|
+
plugins: [
|
|
292
|
+
openapiPlugin({
|
|
293
|
+
ui: 'scalar',
|
|
294
|
+
theme: 'purple',
|
|
295
|
+
includeOrmSchemas: true,
|
|
296
|
+
}),
|
|
297
|
+
],
|
|
298
|
+
});
|
|
299
|
+
```
|
|
192
300
|
|
|
193
301
|
### 2.16 `realtimePlugin` (`plugins/realtime`, `core/realtime`)
|
|
194
302
|
Framework-agnostic, plugin-based, and adapter-driven Realtime layer supporting WebSocket, SSE, Socket.IO, and distributed Redis Pub/Sub transports with zero SSR execution hazards.
|
|
@@ -415,5 +523,41 @@ RFC 4180 compliant CSV generator, parser, ORM model export, streaming chunk writ
|
|
|
415
523
|
- `csv.createStreamWriter(stream, options)` → `{ writeHeader, writeRow, writeRows, end }`
|
|
416
524
|
- **Built-in Services**: `csv.generate`, `csv.parse`, `csv.exportModel` accessible via `ctx.service()` or `req.service()`.
|
|
417
525
|
|
|
526
|
+
### 2.19 `dashboardPlugin` / `devToolbarPlugin` (`plugins/dashboard`)
|
|
527
|
+
Interactive Webspresso Developer Dashboard SPA mounted at `/_webspresso` and Floating In-Page DevTools bar (`fsy.devToolbar()`) inspired by Django Debug Toolbar and Nuxt DevTools.
|
|
528
|
+
|
|
529
|
+
- **Aliases**: `dashboardPlugin`, `devToolbarPlugin`, `devtoolsPlugin`.
|
|
530
|
+
- **Options**:
|
|
531
|
+
- `path`: Base URL path for dashboard (default `/_webspresso`).
|
|
532
|
+
- `title`: Dashboard browser title (default `'Webspresso Developer Dashboard'`).
|
|
533
|
+
- `enabled`: Boolean to force enable in production (default `process.env.NODE_ENV !== 'production'`).
|
|
534
|
+
- **Dashboard Features (`/_webspresso`)**:
|
|
535
|
+
- **Routes Tab**: Full table of file-based SSR and API routes with live search, method badges, dynamic parameters (`[id]`), and target files.
|
|
536
|
+
- **Models Tab**: All registered ORM models with database tables, columns list, cache strategy (`smart` / `auto`), and soft-delete status.
|
|
537
|
+
- **Services Tab**: All business services with transaction safety status, authentication guards (`admin`, roles), schemas, and cache TTL.
|
|
538
|
+
- **Plugins & Config Tabs**: Active plugin manifests, dependencies, and sanitized framework configuration.
|
|
539
|
+
- **JSON API Endpoints**:
|
|
540
|
+
- `GET /_webspresso/api/routes`
|
|
541
|
+
- `GET /_webspresso/api/plugins`
|
|
542
|
+
- `GET /_webspresso/api/config`
|
|
543
|
+
- `GET /_webspresso/api/models`
|
|
544
|
+
- `GET /_webspresso/api/services`
|
|
545
|
+
- `GET /_webspresso/api/overview` (aggregate system metrics, memory, uptime, node version)
|
|
546
|
+
- **Floating In-Page Dev Toolbar (`fsy.devToolbar()`)**:
|
|
547
|
+
- Automatically embedded in `views/layout.njk` during development (`NODE_ENV !== 'production'`).
|
|
548
|
+
- **Collapsed Bottom Pill**:
|
|
549
|
+
- `⚡ DEV` toggle button with `Alt+D` hotkey shortcut.
|
|
550
|
+
- Current route method, HTTP status code (`[GET 200] /path`).
|
|
551
|
+
- Ambient database queries pill (`🗄️ N queries (Xms)`) from `AsyncLocalStorage` request profiler.
|
|
552
|
+
- Prominent N+1 warning alert badge (`⚠️ N+1 (M)`).
|
|
553
|
+
- Quick access buttons to `Dashboard (/_webspresso)`, `Admin (/_admin)`, `API Docs (/_swagger)`, and `Schema (/_schema)`.
|
|
554
|
+
- **Expandable DevTools Drawer (toggled via click or `Alt+D`)**:
|
|
555
|
+
- **🗄️ SQL Queries Tab**: Execution duration (<40ms green, >40ms red), table pills, formatted SQL statement, and N+1 warning box with actionable suggestions (`repo.query().include(...)`).
|
|
556
|
+
- **📄 Route & Page Tab**: Route path, matched file, template name, params, and parsed query string.
|
|
557
|
+
- **🚀 Quick Links Tab**: Configurable tool cards for fast navigation between admin, swagger, and custom tooling.
|
|
558
|
+
- **💻 System Tab**: Process uptime, memory usage, environment, and Node platform metrics.
|
|
559
|
+
- **Zero Production Overhead**: When `process.env.NODE_ENV === 'production'`, `devToolbar()` immediately returns `""` with zero overhead.
|
|
560
|
+
|
|
561
|
+
|
|
418
562
|
|
|
419
563
|
|
package/.agents/QUEUE.md
CHANGED
|
@@ -111,3 +111,46 @@ module.exports.options = {
|
|
|
111
111
|
backoff: { type: 'exponential', delay: 2000 },
|
|
112
112
|
};
|
|
113
113
|
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 5. Job Retention & Pruning
|
|
118
|
+
|
|
119
|
+
To prevent the queue database table or memory cache from accumulating indefinitely:
|
|
120
|
+
|
|
121
|
+
### 1. Auto-Retention in `createQueueManager` / `queuePlugin`
|
|
122
|
+
```js
|
|
123
|
+
queuePlugin({
|
|
124
|
+
adapter: 'database',
|
|
125
|
+
db: appDb,
|
|
126
|
+
retentionDays: 7, // Keep completed jobs for 7 days
|
|
127
|
+
cleanupIntervalMs: 24 * 60 * 60 * 1000, // Run every 24h
|
|
128
|
+
autoCleanup: true,
|
|
129
|
+
retentionStatuses: ['completed'], // or ['completed', 'failed']
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 2. Programmatic `clean()`
|
|
134
|
+
```js
|
|
135
|
+
// Delete completed jobs older than 7 days
|
|
136
|
+
const deletedCount = await queue.clean({
|
|
137
|
+
days: 7,
|
|
138
|
+
status: ['completed'], // or 'failed', or ['completed', 'failed']
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Or with an explicit cutoff date:
|
|
142
|
+
await queue.clean({
|
|
143
|
+
olderThan: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
|
|
144
|
+
status: 'failed',
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 3. CLI Command: `queue:prune`
|
|
149
|
+
```bash
|
|
150
|
+
# Delete completed jobs older than 7 days
|
|
151
|
+
webspresso queue:prune --days 7
|
|
152
|
+
|
|
153
|
+
# Delete both completed and failed jobs older than 14 days
|
|
154
|
+
webspresso queue:prune --days 14 --status completed,failed
|
|
155
|
+
```
|
|
156
|
+
|